[vlc-commits] avcodec: vector get_buffer2() picture allocation

Rémi Denis-Courmont git at videolan.org
Wed Apr 22 20:46:12 CEST 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Apr 22 21:18:17 2015 +0300| [6433fe8a1f2111b35094327af413f5a34c26c27e] | committer: Rémi Denis-Courmont

avcodec: vector get_buffer2() picture allocation

And fix locking around fmt_out in case of hwaccel.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6433fe8a1f2111b35094327af413f5a34c26c27e
---

 modules/codec/avcodec/video.c |   92 ++++++++++++++++++++++-------------------
 1 file changed, 50 insertions(+), 42 deletions(-)

diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 7aea1bb..7ee0eb8 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -954,21 +954,11 @@ static void lavc_ReleaseFrame(void *opaque, uint8_t *data)
 }
 
 static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
-                            int flags)
+                            picture_t *pic)
 {
     decoder_t *dec = ctx->opaque;
     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]))
     {
         msg_Err(dec, "hardware acceleration picture allocation failed");
@@ -992,22 +982,17 @@ static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
 
     frame->opaque = pic;
     assert(frame->data[0] != NULL);
-    (void) flags;
     return 0;
 }
 
-static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx,
-                                   AVFrame *frame, int flags)
+static int lavc_dr_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
+                            picture_t *pic)
 {
     decoder_t *dec = (decoder_t *)ctx->opaque;
     decoder_sys_t *sys = dec->p_sys;
 
     if (ctx->pix_fmt == PIX_FMT_PAL8)
-        return NULL;
-
-    picture_t *pic = ffmpeg_NewPictBuf(dec, ctx);
-    if (pic == NULL)
-        return NULL;
+        goto error;
 
     int width = frame->width;
     int height = frame->height;
@@ -1026,13 +1011,13 @@ static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx,
             if (sys->i_direct_rendering_used != 0)
                 msg_Dbg(dec, "plane %d: pitch not aligned (%d%%%d)",
                         i, pic->p[i].i_pitch, aligns[i]);
-            goto no_dr;
+            goto error;
         }
         if (((uintptr_t)pic->p[i].p_pixels) % aligns[i])
         {
             if (sys->i_direct_rendering_used != 0)
                 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,
         frame->data[i] = data;
         frame->linesize[i] = pic->p[i].i_pitch;
         frame->buf[i] = av_buffer_create(data, size, lavc_ReleaseFrame,
-                                         picture_Hold(pic), 0);
+                                         pic, 0);
         if (unlikely(frame->buf[i] == NULL))
         {
-            lavc_ReleaseFrame(pic, data);
+            while (i > 0)
+                av_buffer_unref(&frame->buf[--i]);
             goto error;
         }
+        picture_Hold(pic);
     }
 
     frame->opaque = pic;
     /* The loop above held one reference to the picture for each plane. */
     picture_Release(pic);
-    (void) flags;
-    return pic;
+    return 0;
 error:
-    for (unsigned i = 0; frame->buf[i] != NULL; i++)
-        av_buffer_unref(&frame->buf[i]);
-no_dr:
     picture_Release(pic);
-    return NULL;
+    return -1;
 }
 
 /**
@@ -1089,34 +1072,59 @@ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags)
     }
     frame->opaque = NULL;
 
+    wait_mt(sys);
     if (sys->p_va != NULL)
-        return lavc_va_GetFrame(ctx, frame, flags);
-
-    if (!sys->b_direct_rendering)
+    {   /* 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))
+        {
+            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);
+    }
+
+    /* 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,
      * so we need to check for direct rendering again. */
-    wait_mt(sys);
-    pic = lavc_dr_GetFrame(ctx, frame, flags);
-    if (pic == NULL)
+    /* XXX: The semaphore is needed because of i_direct_rendering_used */
+    int ret = lavc_dr_GetFrame(ctx, frame, pic);
+    if (ret)
     {
         if (sys->i_direct_rendering_used != 0)
         {
             msg_Warn(dec, "disabling direct rendering");
             sys->i_direct_rendering_used = 0;
         }
-        post_mt(sys);
-        return avcodec_default_get_buffer2(ctx, frame, flags);
+        ret = avcodec_default_get_buffer2(ctx, frame, flags);
     }
-
-    if (sys->i_direct_rendering_used != 1)
+    else
     {
-        msg_Dbg(dec, "enabling direct rendering");
-        sys->i_direct_rendering_used = 1;
+        if (sys->i_direct_rendering_used != 1)
+        {
+            msg_Dbg(dec, "enabling direct rendering");
+            sys->i_direct_rendering_used = 1;
+        }
     }
     post_mt(sys);
-    return 0;
+    return ret;
 }
 
 static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,



More information about the vlc-commits mailing list