[vlc-commits] videotoolbox: use the new push model

Thomas Guillem git at videolan.org
Fri Jan 10 13:02:03 CET 2020


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Jan  8 16:43:09 2020 +0100| [41d5af70c6dbc653fe9f430241a68671db772672] | committer: Thomas Guillem

videotoolbox: use the new push model

Deprecate the "videotoolbox" bool variable. This module should be
enabled/disabled by the "dec-dev" variable like any other hw modules.

The vt decoder device is just used to enable/disable hw decoding on Apple and
act like other hw module. Indeed, VideoToolBox doesn't need any context from
the window to initialize.

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

 modules/codec/videotoolbox.m | 133 ++++++++++++++++++++++++++++---------------
 modules/codec/vt_utils.c     |  25 ++++----
 modules/codec/vt_utils.h     |   5 +-
 3 files changed, 100 insertions(+), 63 deletions(-)

diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index a34a82af10..4c95b5d96e 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -71,6 +71,7 @@ const CFStringRef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDe
 
 static int OpenDecoder(vlc_object_t *);
 static void CloseDecoder(vlc_object_t *);
+static int OpenDecDevice(vlc_decoder_device *device, vout_window_t *window);
 
 #define VT_ENABLE_TEXT N_("Enable hardware acceleration")
 #define VT_REQUIRE_HW_DEC N_("Use Hardware decoders only")
@@ -86,9 +87,11 @@ set_capability("video decoder",800)
 set_callbacks(OpenDecoder, CloseDecoder)
 
 add_obsolete_bool("videotoolbox-temporal-deinterlacing")
-add_bool("videotoolbox", true, VT_ENABLE_TEXT, NULL, false)
+add_obsolete_bool("videotoolbox")
 add_bool("videotoolbox-hw-decoder-only", true, VT_REQUIRE_HW_DEC, VT_REQUIRE_HW_DEC, false)
 add_string("videotoolbox-cvpx-chroma", "", VT_FORCE_CVPX_CHROMA, VT_FORCE_CVPX_CHROMA_LONG, true);
+add_submodule ()
+    set_callback_dec_device(OpenDecDevice, 1)
 vlc_module_end()
 
 #pragma mark - local prototypes
@@ -184,6 +187,7 @@ typedef struct decoder_sys_t
     bool                        b_drop_blocks;
     date_t                      pts;
 
+    vlc_video_context          *vctx;
     struct pic_pacer           *pic_pacer;
 } decoder_sys_t;
 
@@ -191,7 +195,6 @@ typedef struct decoder_sys_t
  * that can lead to a OOM. cf. pic_pacer_Wait usage in DecoderCallback() */
 struct pic_pacer
 {
-    bool        closed;
     vlc_mutex_t lock;
     vlc_cond_t  wait;
     uint8_t     nb_field_out;
@@ -1317,11 +1320,12 @@ static void StopVideoToolbox(decoder_t *p_dec, bool closing)
 
 #pragma mark - module open and close
 
-static void pic_pacer_Clean(struct pic_pacer *pic_pacer)
+static void pic_pacer_Destroy(void *priv)
 {
+    struct pic_pacer *pic_pacer = priv;
+
     vlc_mutex_destroy(&pic_pacer->lock);
     vlc_cond_destroy(&pic_pacer->wait);
-    free(pic_pacer);
 }
 
 static void pic_pacer_Init(struct pic_pacer *pic_pacer, uint8_t pic_reorder_max)
@@ -1329,16 +1333,63 @@ static void pic_pacer_Init(struct pic_pacer *pic_pacer, uint8_t pic_reorder_max)
     vlc_mutex_init(&pic_pacer->lock);
     vlc_cond_init(&pic_pacer->wait);
     pic_pacer->nb_field_out = 0;
-    pic_pacer->closed = false;
     pic_pacer->field_reorder_max = pic_reorder_max * 2;
 }
 
-static int OpenDecoder(vlc_object_t *p_this)
+static int
+CreateVideoContext(decoder_t *p_dec)
 {
-    decoder_t *p_dec = (decoder_t *)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    p_dec->fmt_out.video = p_dec->fmt_in.video;
+    p_dec->fmt_out.video.p_palette = NULL;
+
+    /* Most likely used chroma but can be reconfigured in the future */
+    p_dec->fmt_out.i_codec = VLC_CODEC_CVPX_NV12;
+    p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
+
+    if (!p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den)
+    {
+        p_dec->fmt_out.video.i_sar_num = 1;
+        p_dec->fmt_out.video.i_sar_den = 1;
+    }
 
-    if (!var_InheritBool(p_dec, "videotoolbox"))
+    vlc_decoder_device *dec_dev = decoder_GetDecoderDevice(p_dec);
+    if (!dec_dev || dec_dev->type != VLC_DECODER_DEVICE_VIDEOTOOLBOX)
+    {
+        msg_Warn(p_dec, "Could not find an VIDEOTOOLBOX decoder device");
         return VLC_EGENERIC;
+    }
+
+    static const struct vlc_video_context_operations ops =
+    {
+        pic_pacer_Destroy,
+    };
+    p_sys->vctx =
+        vlc_video_context_Create(dec_dev, VLC_VIDEO_CONTEXT_CVPX,
+                                 sizeof(struct pic_pacer), &ops);
+    vlc_decoder_device_Release(dec_dev);
+
+    if (!p_sys->vctx)
+        return VLC_ENOMEM;
+
+    /* Since pictures can outlive the decoder, the private video context is a
+     * good place to place the pic_pacer that need to be valid during the
+     * lifetime of all pictures */
+    p_sys->pic_pacer =
+        vlc_video_context_GetPrivate(p_sys->vctx,
+                                     VLC_VIDEO_CONTEXT_CVPX);
+    assert(p_sys->pic_pacer);
+
+    pic_pacer_Init(p_sys->pic_pacer, p_sys->i_pic_reorder_max);
+
+    return VLC_SUCCESS;
+}
+
+static int OpenDecoder(vlc_object_t *p_this)
+{
+    int i_ret;
+    decoder_t *p_dec = (decoder_t *)p_this;
 
     /* Fail if this module already failed to decode this ES */
     if (var_Type(p_dec, "videotoolbox-failed") != 0)
@@ -1381,14 +1432,13 @@ static int OpenDecoder(vlc_object_t *p_this)
         free(cvpx_chroma);
     }
 
-    p_sys->pic_pacer = malloc(sizeof(struct pic_pacer));
-    if (!p_sys->pic_pacer)
+    i_ret = CreateVideoContext(p_dec);
+    if (i_ret != VLC_SUCCESS)
     {
         free(p_sys);
-        return VLC_ENOMEM;
+        return i_ret;
     }
 
-    pic_pacer_Init(&p_sys->pic_pacer, p_sys->i_pic_reorder_max);
     p_sys->b_vt_need_keyframe = false;
 
     vlc_mutex_init(&p_sys->lock);
@@ -1446,7 +1496,7 @@ static int OpenDecoder(vlc_object_t *p_this)
         return VLC_EGENERIC;
     }
 
-    int i_ret = StartVideoToolbox(p_dec);
+    i_ret = StartVideoToolbox(p_dec);
     if (i_ret == VLC_SUCCESS) {
         PtsInit(p_dec);
         msg_Info(p_dec, "Using Video Toolbox to decode '%4.4s'",
@@ -1470,17 +1520,8 @@ static void CloseDecoder(vlc_object_t *p_this)
 
     vlc_mutex_destroy(&p_sys->lock);
 
-    vlc_mutex_lock(&p_sys->pic_pacer->lock);
-    if (p_sys->pic_pacer->nb_field_out == 0)
-    {
-        vlc_mutex_unlock(&p_sys->pic_pacer->lock);
-        pic_pacer_Clean(p_sys->pic_pacer);
-    }
-    else
-    {
-        p_sys->pic_pacer->closed = true;
-        vlc_mutex_unlock(&p_sys->pic_pacer->lock);
-    }
+    vlc_video_context_Release(p_sys->vctx);
+
     free(p_sys);
 }
 
@@ -1595,20 +1636,12 @@ static int ConfigureVout(decoder_t *p_dec)
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     /* return our proper VLC internal state */
-    p_dec->fmt_out.video = p_dec->fmt_in.video;
-    p_dec->fmt_out.video.p_palette = NULL;
     p_dec->fmt_out.i_codec = 0;
 
     if(p_sys->pf_configure_vout &&
        !p_sys->pf_configure_vout(p_dec))
         return VLC_EGENERIC;
 
-    if (!p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den)
-    {
-        p_dec->fmt_out.video.i_sar_num = 1;
-        p_dec->fmt_out.video.i_sar_den = 1;
-    }
-
     if (!p_dec->fmt_out.video.i_visible_width || !p_dec->fmt_out.video.i_visible_height)
     {
         p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width;
@@ -2068,7 +2101,7 @@ static int UpdateVideoFormat(decoder_t *p_dec, CVPixelBufferRef imageBuffer)
             return -1;
     }
     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
-    if (decoder_UpdateVideoFormat(p_dec) != 0)
+    if (decoder_UpdateVideoOutput(p_dec, p_sys->vctx) != 0)
     {
         p_sys->vtsession_status = VTSESSION_STATUS_ABORT;
         return -1;
@@ -2077,23 +2110,16 @@ static int UpdateVideoFormat(decoder_t *p_dec, CVPixelBufferRef imageBuffer)
 }
 
 static void
-pic_pacer_OnCvpxReleased(CVPixelBufferRef cvpx, void *data, unsigned nb_fields)
+video_context_OnPicReleased(vlc_video_context *vctx, unsigned nb_fields)
 {
-    struct pic_pacer *pic_pacer = data;
+    struct pic_pacer *pic_pacer =
+        vlc_video_context_GetPrivate(vctx, VLC_VIDEO_CONTEXT_CVPX);
 
     vlc_mutex_lock(&pic_pacer->lock);
     assert((int) pic_pacer->nb_field_out - nb_fields >= 0);
     pic_pacer->nb_field_out -= nb_fields;
-    if (pic_pacer->nb_field_out == 0 && pic_pacer->closed)
-    {
-        vlc_mutex_unlock(&pic_pacer->lock);
-        pic_pacer_Clean(pic_pacer);
-    }
-    else
-    {
-        vlc_cond_broadcast(&pic_pacer->wait);
-        vlc_mutex_unlock(&pic_pacer->lock);
-    }
+    vlc_cond_signal(&pic_pacer->wait);
+    vlc_mutex_unlock(&pic_pacer->lock);
 }
 
 static void
@@ -2215,8 +2241,8 @@ static void DecoderCallback(void *decompressionOutputRefCon,
             p_pic->b_top_field_first = p_info->b_top_field_first;
         }
 
-        if (cvpxpic_attach(p_pic, imageBuffer, pic_pacer_OnCvpxReleased,
-                           p_sys->pic_pacer) != VLC_SUCCESS)
+        if (cvpxpic_attach(p_pic, imageBuffer, p_sys->vctx,
+                           video_context_OnPicReleased) != VLC_SUCCESS)
         {
             vlc_mutex_lock(&p_sys->lock);
             goto end;
@@ -2249,3 +2275,16 @@ end:
     vlc_mutex_unlock(&p_sys->lock);
     return;
 }
+
+static int
+OpenDecDevice(vlc_decoder_device *device, vout_window_t *window)
+{
+    static const struct vlc_decoder_device_operations ops =
+    {
+        NULL,
+    };
+    device->ops = &ops;
+    device->type = VLC_DECODER_DEVICE_VIDEOTOOLBOX;
+
+    return VLC_SUCCESS;
+}
diff --git a/modules/codec/vt_utils.c b/modules/codec/vt_utils.c
index ca61779118..c23ff75b08 100644
--- a/modules/codec/vt_utils.c
+++ b/modules/codec/vt_utils.c
@@ -49,8 +49,7 @@ struct cvpxpic_ctx
     unsigned nb_fields;
 
     vlc_atomic_rc_t rc;
-    void (*on_released_cb)(CVPixelBufferRef, void *, unsigned);
-    void *on_released_data;
+    void (*on_released_cb)(vlc_video_context *vctx, unsigned);
 };
 
 static void
@@ -62,7 +61,7 @@ cvpxpic_destroy_cb(picture_context_t *opaque)
     {
         CFRelease(ctx->cvpx);
         if (ctx->on_released_cb)
-            ctx->on_released_cb(ctx->cvpx, ctx->on_released_data, ctx->nb_fields);
+            ctx->on_released_cb(opaque->vctx, ctx->nb_fields);
         free(opaque);
     }
 }
@@ -72,14 +71,16 @@ cvpxpic_copy_cb(struct picture_context_t *opaque)
 {
     struct cvpxpic_ctx *ctx = (struct cvpxpic_ctx *)opaque;
     vlc_atomic_rc_inc(&ctx->rc);
+    if (opaque->vctx)
+        vlc_video_context_Hold(opaque->vctx);
     return opaque;
 }
 
 static int
 cvpxpic_attach_common(picture_t *p_pic, CVPixelBufferRef cvpx,
                       void (*pf_destroy)(picture_context_t *),
-                      void (*on_released_cb)(CVPixelBufferRef, void *, unsigned),
-                      void *on_released_data)
+                      vlc_video_context *vctx,
+                      void (*on_released_cb)(vlc_video_context *vctx, unsigned))
 {
     struct cvpxpic_ctx *ctx = malloc(sizeof(struct cvpxpic_ctx));
     if (ctx == NULL)
@@ -88,15 +89,15 @@ cvpxpic_attach_common(picture_t *p_pic, CVPixelBufferRef cvpx,
         return VLC_ENOMEM;
     }
     ctx->s = (picture_context_t) {
-        pf_destroy, cvpxpic_copy_cb,
-        NULL // no video context for now
+        pf_destroy, cvpxpic_copy_cb, vctx,
     };
     ctx->cvpx = CVPixelBufferRetain(cvpx);
     ctx->nb_fields = p_pic->i_nb_fields;
     vlc_atomic_rc_init(&ctx->rc);
 
+    if (vctx)
+        vlc_video_context_Hold(vctx);
     ctx->on_released_cb = on_released_cb;
-    ctx->on_released_data = on_released_data;
 
     p_pic->context = &ctx->s;
 
@@ -104,12 +105,10 @@ cvpxpic_attach_common(picture_t *p_pic, CVPixelBufferRef cvpx,
 }
 
 int
-cvpxpic_attach(picture_t *p_pic, CVPixelBufferRef cvpx,
-               void (*on_released_cb)(CVPixelBufferRef, void *, unsigned),
-               void *on_released_data)
+cvpxpic_attach(picture_t *p_pic, CVPixelBufferRef cvpx, vlc_video_context *vctx,
+               void (*on_released_cb)(vlc_video_context *vctx, unsigned))
 {
-    return cvpxpic_attach_common(p_pic, cvpx, cvpxpic_destroy_cb, on_released_cb,
-                                 on_released_data);
+    return cvpxpic_attach_common(p_pic, cvpx, cvpxpic_destroy_cb, vctx, on_released_cb);
 }
 
 CVPixelBufferRef
diff --git a/modules/codec/vt_utils.h b/modules/codec/vt_utils.h
index 1033450667..e981237ed6 100644
--- a/modules/codec/vt_utils.h
+++ b/modules/codec/vt_utils.h
@@ -34,9 +34,8 @@ void cfdict_set_int32(CFMutableDictionaryRef dict, CFStringRef key, int value);
  * The cvpx ref will be released when the picture is released
  * @return VLC_SUCCESS or VLC_ENOMEM
  */
-int cvpxpic_attach(picture_t *p_pic, CVPixelBufferRef cvpx,
-                   void (*on_released_cb)(CVPixelBufferRef, void *, unsigned nb_fields),
-                   void *on_released_data);
+int cvpxpic_attach(picture_t *p_pic, CVPixelBufferRef cvpx, vlc_video_context *vctx,
+                   void (*on_released_cb)(vlc_video_context *vctx, unsigned));
 
 /*
  * Get the cvpx buffer attached to a picture



More information about the vlc-commits mailing list