Commit 6433fe8a authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

avcodec: vector get_buffer2() picture allocation

And fix locking around fmt_out in case of hwaccel.
parent 8c81c0f6
...@@ -954,21 +954,11 @@ static void lavc_ReleaseFrame(void *opaque, uint8_t *data) ...@@ -954,21 +954,11 @@ static void lavc_ReleaseFrame(void *opaque, uint8_t *data)
} }
static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
int flags) picture_t *pic)
{ {
decoder_t *dec = ctx->opaque; decoder_t *dec = ctx->opaque;
vlc_va_t *va = dec->p_sys->p_va; vlc_va_t *va = dec->p_sys->p_va;
if (vlc_va_Setup(va, ctx, &dec->fmt_out.video.i_chroma))
{
msg_Err(dec, "hardware acceleration setup failed");
return -1;
}
picture_t *pic = ffmpeg_NewPictBuf(dec, ctx);
if (pic == NULL)
return -1;
if (vlc_va_Get(va, pic, &frame->data[0])) if (vlc_va_Get(va, pic, &frame->data[0]))
{ {
msg_Err(dec, "hardware acceleration picture allocation failed"); msg_Err(dec, "hardware acceleration picture allocation failed");
...@@ -992,22 +982,17 @@ static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, ...@@ -992,22 +982,17 @@ static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
frame->opaque = pic; frame->opaque = pic;
assert(frame->data[0] != NULL); assert(frame->data[0] != NULL);
(void) flags;
return 0; return 0;
} }
static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx, static int lavc_dr_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
AVFrame *frame, int flags) picture_t *pic)
{ {
decoder_t *dec = (decoder_t *)ctx->opaque; decoder_t *dec = (decoder_t *)ctx->opaque;
decoder_sys_t *sys = dec->p_sys; decoder_sys_t *sys = dec->p_sys;
if (ctx->pix_fmt == PIX_FMT_PAL8) if (ctx->pix_fmt == PIX_FMT_PAL8)
return NULL; goto error;
picture_t *pic = ffmpeg_NewPictBuf(dec, ctx);
if (pic == NULL)
return NULL;
int width = frame->width; int width = frame->width;
int height = frame->height; int height = frame->height;
...@@ -1026,13 +1011,13 @@ static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx, ...@@ -1026,13 +1011,13 @@ static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx,
if (sys->i_direct_rendering_used != 0) if (sys->i_direct_rendering_used != 0)
msg_Dbg(dec, "plane %d: pitch not aligned (%d%%%d)", msg_Dbg(dec, "plane %d: pitch not aligned (%d%%%d)",
i, pic->p[i].i_pitch, aligns[i]); i, pic->p[i].i_pitch, aligns[i]);
goto no_dr; goto error;
} }
if (((uintptr_t)pic->p[i].p_pixels) % aligns[i]) if (((uintptr_t)pic->p[i].p_pixels) % aligns[i])
{ {
if (sys->i_direct_rendering_used != 0) if (sys->i_direct_rendering_used != 0)
msg_Warn(dec, "plane %d not aligned", i); msg_Warn(dec, "plane %d not aligned", i);
goto no_dr; goto error;
} }
} }
...@@ -1048,25 +1033,23 @@ static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx, ...@@ -1048,25 +1033,23 @@ static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx,
frame->data[i] = data; frame->data[i] = data;
frame->linesize[i] = pic->p[i].i_pitch; frame->linesize[i] = pic->p[i].i_pitch;
frame->buf[i] = av_buffer_create(data, size, lavc_ReleaseFrame, frame->buf[i] = av_buffer_create(data, size, lavc_ReleaseFrame,
picture_Hold(pic), 0); pic, 0);
if (unlikely(frame->buf[i] == NULL)) if (unlikely(frame->buf[i] == NULL))
{ {
lavc_ReleaseFrame(pic, data); while (i > 0)
av_buffer_unref(&frame->buf[--i]);
goto error; goto error;
} }
picture_Hold(pic);
} }
frame->opaque = pic; frame->opaque = pic;
/* The loop above held one reference to the picture for each plane. */ /* The loop above held one reference to the picture for each plane. */
picture_Release(pic); picture_Release(pic);
(void) flags; return 0;
return pic;
error: error:
for (unsigned i = 0; frame->buf[i] != NULL; i++)
av_buffer_unref(&frame->buf[i]);
no_dr:
picture_Release(pic); picture_Release(pic);
return NULL; return -1;
} }
/** /**
...@@ -1089,34 +1072,59 @@ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags) ...@@ -1089,34 +1072,59 @@ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags)
} }
frame->opaque = NULL; frame->opaque = NULL;
wait_mt(sys);
if (sys->p_va != NULL) if (sys->p_va != NULL)
return lavc_va_GetFrame(ctx, frame, flags); { /* TODO: Move this to get_format(). We are screwed if it fails here. */
if (vlc_va_Setup(sys->p_va, ctx, &dec->fmt_out.video.i_chroma))
if (!sys->b_direct_rendering) {
post_mt(sys);
msg_Err(dec, "hardware acceleration setup failed");
return -1;
}
}
else if (!sys->b_direct_rendering)
{
post_mt(sys);
return avcodec_default_get_buffer2(ctx, frame, flags); return avcodec_default_get_buffer2(ctx, frame, flags);
}
/* The semaphore protects updates to fmt_out */
pic = ffmpeg_NewPictBuf(dec, ctx);
if (pic == NULL)
{
post_mt(sys);
return -1;
}
if (sys->p_va != NULL)
{
post_mt(sys);
return lavc_va_GetFrame(ctx, frame, pic);
}
/* Some codecs set pix_fmt only after the 1st frame has been decoded, /* Some codecs set pix_fmt only after the 1st frame has been decoded,
* so we need to check for direct rendering again. */ * so we need to check for direct rendering again. */
wait_mt(sys); /* XXX: The semaphore is needed because of i_direct_rendering_used */
pic = lavc_dr_GetFrame(ctx, frame, flags); int ret = lavc_dr_GetFrame(ctx, frame, pic);
if (pic == NULL) if (ret)
{ {
if (sys->i_direct_rendering_used != 0) if (sys->i_direct_rendering_used != 0)
{ {
msg_Warn(dec, "disabling direct rendering"); msg_Warn(dec, "disabling direct rendering");
sys->i_direct_rendering_used = 0; sys->i_direct_rendering_used = 0;
} }
post_mt(sys); ret = avcodec_default_get_buffer2(ctx, frame, flags);
return avcodec_default_get_buffer2(ctx, frame, flags);
} }
else
{
if (sys->i_direct_rendering_used != 1) if (sys->i_direct_rendering_used != 1)
{ {
msg_Dbg(dec, "enabling direct rendering"); msg_Dbg(dec, "enabling direct rendering");
sys->i_direct_rendering_used = 1; sys->i_direct_rendering_used = 1;
} }
}
post_mt(sys); post_mt(sys);
return 0; return ret;
} }
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context, static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment