[vlc-devel] [PATCH 1/8] decoder: let the decoder tell how many pictures it needs in the pool

Steve Lhomme robux4 at ycbcr.xyz
Tue Jul 28 11:08:34 CEST 2020


This is necessary for pools that attach buffers/surfaces to the pictures from
the decoder so that the picture wait is done at the decoder_t level and not
inside each decoder module (which can't be easily canceled otherwise).

For now no module provides the proper size so the behavior is unchanged.
---
 include/vlc_codec.h                  |  7 +++++--
 modules/codec/avcodec/video.c        |  6 +++---
 modules/codec/hxxx_helper_testdec.c  |  2 +-
 modules/codec/omxil/mediacodec.c     |  2 +-
 modules/codec/videotoolbox.c         |  2 +-
 modules/hw/mmal/codec.c              |  4 ++--
 modules/hw/nvdec/nvdec.c             |  4 ++--
 modules/stream_out/mosaic_bridge.c   |  5 +++--
 modules/stream_out/sdi/SDIStream.cpp |  3 ++-
 modules/stream_out/sdi/SDIStream.hpp |  2 +-
 modules/stream_out/transcode/video.c |  3 ++-
 src/input/decoder.c                  | 23 ++++++++++++++++++-----
 src/input/decoder_helpers.c          |  6 +++---
 13 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index 81c2cb5d142..edebfa94e55 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -50,7 +50,7 @@ struct decoder_owner_callbacks
         struct
         {
             vlc_decoder_device * (*get_device)( decoder_t * );
-            int         (*format_update)( decoder_t *, vlc_video_context * );
+            int         (*format_update)( decoder_t *, vlc_video_context *, size_t );
 
             /* cf. decoder_NewPicture, can be called from any decoder thread */
             picture_t*  (*buffer_new)( decoder_t * );
@@ -314,12 +314,15 @@ static inline vlc_decoder_device * decoder_GetDecoderDevice( decoder_t *dec )
  *
  * If the format is unchanged, this function has no effects and returns zero.
  *
+ * @param pool_size the required pool size to hold the decoder buffers or 0
+ *
  * \note
  * This function is not reentrant.
  *
  * @return 0 if the video output was set up successfully, -1 otherwise.
  */
-VLC_API int decoder_UpdateVideoOutput( decoder_t *dec, vlc_video_context *vctx_out );
+VLC_API int decoder_UpdateVideoOutput( decoder_t *dec, vlc_video_context *vctx_out,
+                                       size_t pool_size );
 
 /**
  * Updates the video output format.
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 4c5943d22ea..688b7587777 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -1249,7 +1249,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
             if (p_sys->p_va == NULL
              && lavc_UpdateVideoFormat(p_dec, p_context, p_context->pix_fmt,
                                        p_context->pix_fmt, NULL) == 0
-             && decoder_UpdateVideoOutput(p_dec, NULL) == 0)
+             && decoder_UpdateVideoOutput(p_dec, NULL, 0) == 0)
                 p_pic = decoder_NewPicture(p_dec);
 
             if( !p_pic )
@@ -1597,7 +1597,7 @@ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags)
          * update the output video format here. The MT semaphore must be held
          * to protect p_dec->fmt_out. */
         if (lavc_UpdateVideoFormat(dec, ctx, ctx->pix_fmt, ctx->pix_fmt, NULL) ||
-            decoder_UpdateVideoOutput(dec, NULL))
+            decoder_UpdateVideoOutput(dec, NULL, 0))
         {
             vlc_mutex_unlock(&sys->lock);
             return -1;
@@ -1756,7 +1756,7 @@ no_reuse:
         assert(vctx_out != NULL);
         p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
 
-        if (decoder_UpdateVideoOutput(p_dec, vctx_out))
+        if (decoder_UpdateVideoOutput(p_dec, vctx_out, 0))
         {
             vlc_va_Delete(va);
             p_context->hwaccel_context = NULL;
diff --git a/modules/codec/hxxx_helper_testdec.c b/modules/codec/hxxx_helper_testdec.c
index c0dd3119e97..81638c22984 100644
--- a/modules/codec/hxxx_helper_testdec.c
+++ b/modules/codec/hxxx_helper_testdec.c
@@ -89,7 +89,7 @@ DecodeBlock(decoder_t *dec, block_t *block)
             dec->fmt_out.video.i_sar_den = sar_den;
         }
 
-        ret = decoder_UpdateVideoOutput(dec, NULL);
+        ret = decoder_UpdateVideoOutput(dec, NULL, 0);
         if (ret != 0)
             return VLCDEC_ECRITICAL;
     }
diff --git a/modules/codec/omxil/mediacodec.c b/modules/codec/omxil/mediacodec.c
index 041faa9a46e..05582c9fccc 100644
--- a/modules/codec/omxil/mediacodec.c
+++ b/modules/codec/omxil/mediacodec.c
@@ -1207,7 +1207,7 @@ static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
             video_format_TransformTo(&p_dec->fmt_out.video, ORIENT_NORMAL);
         }
 
-        if (decoder_UpdateVideoOutput(p_dec, p_sys->video.ctx) != 0)
+        if (decoder_UpdateVideoOutput(p_dec, p_sys->video.ctx, 0) != 0)
         {
             msg_Err(p_dec, "UpdateVout failed");
             return -1;
diff --git a/modules/codec/videotoolbox.c b/modules/codec/videotoolbox.c
index 5e5b30f0a27..6176a195deb 100644
--- a/modules/codec/videotoolbox.c
+++ b/modules/codec/videotoolbox.c
@@ -2047,7 +2047,7 @@ static int UpdateVideoFormat(decoder_t *p_dec, CVPixelBufferRef imageBuffer)
             return -1;
     }
 
-    if (decoder_UpdateVideoOutput(p_dec, p_sys->vctx) != 0)
+    if (decoder_UpdateVideoOutput(p_dec, p_sys->vctx, 0) != 0)
     {
         p_sys->vtsession_status = VTSESSION_STATUS_ABORT;
         return -1;
diff --git a/modules/hw/mmal/codec.c b/modules/hw/mmal/codec.c
index a10ac5637ae..d6cf0a6f8d1 100644
--- a/modules/hw/mmal/codec.c
+++ b/modules/hw/mmal/codec.c
@@ -283,7 +283,7 @@ static void fill_output_port(decoder_t *dec)
 {
     decoder_sys_t *sys = dec->p_sys;
 
-    if (decoder_UpdateVideoOutput(dec, sys->vctx) != 0)
+    if (decoder_UpdateVideoOutput(dec, sys->vctx, 0) != 0)
     {
         // If we have a new format don't bother stuffing the buffer
         // We should get a reset RSN
@@ -371,7 +371,7 @@ apply_fmt:
 
     // Tell the rest of the world we have changed format
     vlc_mutex_lock(&sys->pic_lock);
-    ret = decoder_UpdateVideoOutput(dec, sys->vctx);
+    ret = decoder_UpdateVideoOutput(dec, sys->vctx, 0);
     vlc_mutex_unlock(&sys->pic_lock);
 
     return ret;
diff --git a/modules/hw/nvdec/nvdec.c b/modules/hw/nvdec/nvdec.c
index acf8e06a15d..7fb0e8b4025 100644
--- a/modules/hw/nvdec/nvdec.c
+++ b/modules/hw/nvdec/nvdec.c
@@ -440,7 +440,7 @@ static int CUDAAPI HandleVideoSequence(void *p_opaque, CUVIDEOFORMAT *p_format)
 
     CALL_CUDA_DEC(cuCtxPopCurrent, NULL);
 
-    ret = decoder_UpdateVideoOutput(p_dec, p_sys->vctx_out);
+    ret = decoder_UpdateVideoOutput(p_dec, p_sys->vctx_out, 0);
     return (ret == VLC_SUCCESS);
 
 cuda_error:
@@ -1047,7 +1047,7 @@ static int OpenDecoder(vlc_object_t *p_this)
     for (chroma_idx = 0; output_chromas[chroma_idx] != 0; chroma_idx++)
     {
         p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma = output_chromas[chroma_idx];
-        result = decoder_UpdateVideoOutput(p_dec, p_sys->vctx_out);
+        result = decoder_UpdateVideoOutput(p_dec, p_sys->vctx_out, 0);
         if (result == VLC_SUCCESS)
         {
             msg_Dbg(p_dec, "using chroma %4.4s", (char*)&p_dec->fmt_out.video.i_chroma);
diff --git a/modules/stream_out/mosaic_bridge.c b/modules/stream_out/mosaic_bridge.c
index 518ea73b304..67b1f599a37 100644
--- a/modules/stream_out/mosaic_bridge.c
+++ b/modules/stream_out/mosaic_bridge.c
@@ -83,7 +83,7 @@ static void  Del( sout_stream_t *, void * );
 static int   Send( sout_stream_t *, void *, block_t * );
 
 static void decoder_queue_video( decoder_t *p_dec, picture_t *p_pic );
-static int video_update_format_decoder( decoder_t *p_dec, vlc_video_context * );
+static int video_update_format_decoder( decoder_t *p_dec, vlc_video_context *, size_t );
 static picture_t *video_new_buffer_filter( filter_t * );
 
 static int HeightCallback( vlc_object_t *, char const *,
@@ -591,8 +591,9 @@ static int Send( sout_stream_t *p_stream, void *id, block_t *p_buffer )
     return ret == VLCDEC_SUCCESS ? VLC_SUCCESS : VLC_EGENERIC;
 }
 
-static int video_update_format_decoder( decoder_t *p_dec, vlc_video_context *vctx )
+static int video_update_format_decoder( decoder_t *p_dec, vlc_video_context *vctx, size_t poolsize )
 {
+    VLC_UNUSED(poolsize); // we don't use a picture pool nor wait for pictures to be available
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
     sout_stream_sys_t *p_sys = p_owner->p_stream->p_sys;
     if ( p_sys->p_vf2 )
diff --git a/modules/stream_out/sdi/SDIStream.cpp b/modules/stream_out/sdi/SDIStream.cpp
index ce4588d28ce..1cadb1d164f 100644
--- a/modules/stream_out/sdi/SDIStream.cpp
+++ b/modules/stream_out/sdi/SDIStream.cpp
@@ -506,7 +506,8 @@ void VideoDecodedStream::ReleaseDecoder()
 }
 
 int VideoDecodedStream::VideoDecCallback_update_format(decoder_t *p_dec,
-                                                       vlc_video_context *)
+                                                       vlc_video_context *,
+                                                       size_t)
 {
     struct decoder_owner *p_owner;
     p_owner = container_of(p_dec, struct decoder_owner, dec);
diff --git a/modules/stream_out/sdi/SDIStream.hpp b/modules/stream_out/sdi/SDIStream.hpp
index 1eb624e12ae..d37d5dcbcc2 100644
--- a/modules/stream_out/sdi/SDIStream.hpp
+++ b/modules/stream_out/sdi/SDIStream.hpp
@@ -169,7 +169,7 @@ namespace sdi_sout
             static void VideoDecCallback_queue_cc( decoder_t *, block_t *,
                                                    const decoder_cc_desc_t * );
             static vlc_decoder_device * VideoDecCallback_get_device(decoder_t *);
-            static int VideoDecCallback_update_format(decoder_t *, vlc_video_context *);
+            static int VideoDecCallback_update_format(decoder_t *, vlc_video_context *, size_t);
             filter_chain_t * VideoFilterCreate(const es_format_t *, vlc_video_context *);
             virtual void ReleaseDecoder();
             void Output(picture_t *);
diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c
index 094c1a357fc..ebf05f7b266 100644
--- a/modules/stream_out/transcode/video.c
+++ b/modules/stream_out/transcode/video.c
@@ -93,8 +93,9 @@ static vlc_decoder_device * transcode_video_filter_hold_device(vlc_object_t *o,
     return TranscodeHoldDecoderDevice(o, id);
 }
 
-static int video_update_format_decoder( decoder_t *p_dec, vlc_video_context *vctx )
+static int video_update_format_decoder( decoder_t *p_dec, vlc_video_context *vctx, size_t poolsize )
 {
+    VLC_UNUSED(poolsize); // we don't use a picture pool nor wait for pictures to be available
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
     sout_stream_id_sys_t *id = p_owner->id;
     vlc_object_t        *p_obj = p_owner->p_obj;
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 99c5f12e12f..ec30337cf8c 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -407,7 +407,8 @@ static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec )
 static int CreateVoutIfNeeded(vlc_input_decoder_t *);
 
 
-static int ModuleThread_UpdateVideoFormat( decoder_t *p_dec, vlc_video_context *vctx )
+static int ModuleThread_UpdateVideoFormat( decoder_t *p_dec, vlc_video_context *vctx,
+                                           size_t pool_size )
 {
     vlc_input_decoder_t *p_owner = dec_get_owner( p_dec );
 
@@ -428,7 +429,7 @@ static int ModuleThread_UpdateVideoFormat( decoder_t *p_dec, vlc_video_context *
 
     // configure the new vout
 
-    if ( p_owner->out_pool == NULL )
+    if (pool_size == 0)
     {
         unsigned dpb_size;
         switch( p_dec->fmt_in.i_codec )
@@ -452,13 +453,25 @@ static int ModuleThread_UpdateVideoFormat( decoder_t *p_dec, vlc_video_context *
             dpb_size = 2;
             break;
         }
+        pool_size = dpb_size + p_dec->i_extra_picture_buffers + 1;
+    }
 
+    if (p_owner->out_pool && picture_pool_GetSize(p_owner->out_pool) < pool_size)
+    {
+        msg_Dbg( p_dec, "using a new bigger pool was %u needs %zu",
+                 picture_pool_GetSize(p_owner->out_pool), pool_size );
+        picture_pool_Release( p_owner->out_pool );
+        p_owner->out_pool = NULL;
+    }
+
+    if ( p_owner->out_pool == NULL )
+    {
         p_owner->out_pool = picture_pool_NewFromFormat( &p_dec->fmt_out.video,
-                            dpb_size + p_dec->i_extra_picture_buffers + 1 );
+                            pool_size );
         if (p_owner->out_pool == NULL)
         {
-            msg_Err(p_dec, "Failed to create a pool of %d %4.4s pictures",
-                           dpb_size + p_dec->i_extra_picture_buffers + 1,
+            msg_Err(p_dec, "Failed to create a pool of %zu %4.4s pictures",
+                           pool_size,
                            (char*)&p_dec->fmt_out.video.i_chroma);
             return -1;
         }
diff --git a/src/input/decoder_helpers.c b/src/input/decoder_helpers.c
index c98e62bf214..b54ec667828 100644
--- a/src/input/decoder_helpers.c
+++ b/src/input/decoder_helpers.c
@@ -78,10 +78,10 @@ void decoder_Destroy( decoder_t *p_dec )
 
 int decoder_UpdateVideoFormat( decoder_t *dec )
 {
-    return decoder_UpdateVideoOutput( dec, NULL );
+    return decoder_UpdateVideoOutput( dec, NULL, 0 );
 }
 
-int decoder_UpdateVideoOutput( decoder_t *dec, vlc_video_context *vctx_out )
+int decoder_UpdateVideoOutput( decoder_t *dec, vlc_video_context *vctx_out, size_t pool_size )
 {
     vlc_assert( dec->fmt_in.i_cat == VIDEO_ES && dec->cbs != NULL );
     if ( unlikely(dec->fmt_in.i_cat != VIDEO_ES || dec->cbs == NULL) )
@@ -148,7 +148,7 @@ int decoder_UpdateVideoOutput( decoder_t *dec, vlc_video_context *vctx_out )
     if (dec->cbs->video.format_update == NULL)
         return 0;
 
-    return dec->cbs->video.format_update( dec, vctx_out );
+    return dec->cbs->video.format_update( dec, vctx_out, pool_size );
 }
 
 picture_t *decoder_NewPicture( decoder_t *dec )
-- 
2.26.2



More information about the vlc-devel mailing list