From 4e797456664930fab817a373c20728e32239de55 Mon Sep 17 00:00:00 2001
From: Laurent Aimar <fenrir@videolan.org>
Date: Thu, 23 Oct 2008 22:00:54 +0200
Subject: [PATCH] Added decoder_New/Delete/Link/UnlinkPicture helpers.

---
 include/vlc_codec.h           | 51 +++++++++++++++++++++++++----------
 modules/codec/avcodec/video.c | 10 +++----
 modules/codec/cdg.c           |  2 +-
 modules/codec/dirac.c         |  2 +-
 modules/codec/dmo/dmo.c       |  2 +-
 modules/codec/fake.c          |  2 +-
 modules/codec/libmpeg2.c      | 10 +++----
 modules/codec/mash.cpp        |  2 +-
 modules/codec/png.c           |  2 +-
 modules/codec/quicktime.c     |  2 +-
 modules/codec/rawvideo.c      |  2 +-
 modules/codec/realvideo.c     |  2 +-
 modules/codec/schroedinger.c  |  4 +--
 modules/codec/sdl_image.c     |  2 +-
 modules/codec/tarkin.c        |  2 +-
 modules/codec/theora.c        |  2 +-
 modules/codec/xvmc/xxmc.c     |  8 +++---
 modules/misc/stats/decoder.c  |  2 +-
 src/input/decoder.c           | 22 +++++++++++++--
 src/libvlccore.sym            |  4 +++
 20 files changed, 90 insertions(+), 45 deletions(-)

diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index 80ca5995b7fc..5003e63f8a82 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -81,29 +81,28 @@ struct decoder_t
      * globaly, not necessary for the current packet */
     block_t *           ( * pf_get_cc )      ( decoder_t *, bool pb_present[4] );
 
-    /*
-     * Buffers allocation
-     */
-
-    /* Video output callbacks */
-    picture_t     * ( * pf_vout_buffer_new) ( decoder_t * );
-    void            ( * pf_vout_buffer_del) ( decoder_t *, picture_t * );
-    void            ( * pf_picture_link)    ( decoder_t *, picture_t * );
-    void            ( * pf_picture_unlink)  ( decoder_t *, picture_t * );
-
     /*
      * Owner fields
+     * XXX You MUST not use them directly.
      */
 
+    /* Video output callbacks
+     * XXX use decoder_NewPicture/decoder_DeletePicture
+     * and decoder_LinkPicture/decoder_UnlinkPicture */
+    picture_t      *(*pf_vout_buffer_new)( decoder_t * );
+    void            (*pf_vout_buffer_del)( decoder_t *, picture_t * );
+    void            (*pf_picture_link)   ( decoder_t *, picture_t * );
+    void            (*pf_picture_unlink) ( decoder_t *, picture_t * );
+
     /* Audio output callbacks
      * XXX use decoder_NewAudioBuffer/decoder_DeleteAudioBuffer */
-    aout_buffer_t * ( * pf_aout_buffer_new) ( decoder_t *, int );
-    void            ( * pf_aout_buffer_del) ( decoder_t *, aout_buffer_t * );
+    aout_buffer_t  *(*pf_aout_buffer_new)( decoder_t *, int );
+    void            (*pf_aout_buffer_del)( decoder_t *, aout_buffer_t * );
 
     /* SPU output callbacks
      * XXX use decoder_NewSubpicture and decoder_DeleteSubpicture */
-    subpicture_t   *(*pf_spu_buffer_new) ( decoder_t * );
-    void            (*pf_spu_buffer_del) ( decoder_t *, subpicture_t * );
+    subpicture_t   *(*pf_spu_buffer_new)( decoder_t * );
+    void            (*pf_spu_buffer_del)( decoder_t *, subpicture_t * );
 
     /* Input attachments
      * XXX use decoder_GetInputAttachments */
@@ -166,6 +165,30 @@ struct encoder_t
  */
 
 
+/**
+ * This function will return a new picture usable by a decoder as an output
+ * buffer. You have to release it using decoder_DeletePicture or by returning
+ * it to the caller as a pf_decode_video return value.
+ */
+VLC_EXPORT( picture_t *, decoder_NewPicture, ( decoder_t * ) );
+
+/**
+ * This function will release a picture create by decoder_NewPicture.
+ */
+VLC_EXPORT( void, decoder_DeletePicture, ( decoder_t *, picture_t *p_picture ) );
+
+/**
+ * This function will increase the picture reference count.
+ * (picture_Hold is not usable.)
+ */
+VLC_EXPORT( void, decoder_LinkPicture, ( decoder_t *, picture_t * ) );
+
+/**
+ * This function will decrease the picture reference count.
+ * (picture_Release is not usable.)
+ */
+VLC_EXPORT( void, decoder_UnlinkPicture, ( decoder_t *, picture_t * ) );
+
 /**
  * This function will return a new audio buffer usable by a decoder as an
  * output buffer. You have to release it using decoder_DeleteAudioBuffer
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index bd018e7043d8..5c63fa262fae 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -165,7 +165,7 @@ static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec,
         p_dec->fmt_out.video.i_frame_rate_base = p_context->time_base.num;
     }
 
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     return p_pic;
 }
@@ -609,7 +609,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             /* Do not display the picture */
             p_pic = (picture_t *)p_sys->p_ff_pic->opaque;
             if( !b_drawpicture && p_pic )
-                p_dec->pf_vout_buffer_del( p_dec, p_pic );
+                decoder_DeletePicture( p_dec, p_pic );
 
             ffmpeg_NextPts( p_dec );
             continue;
@@ -699,7 +699,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         }
         else
         {
-            p_dec->pf_vout_buffer_del( p_dec, p_pic );
+            decoder_DeletePicture( p_dec, p_pic );
         }
     }
 
@@ -914,7 +914,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
 
     if( p_ff_pic->reference != 0 )
     {
-        p_dec->pf_picture_link( p_dec, p_pic );
+        decoder_LinkPicture( p_dec, p_pic );
     }
 
     /* FIXME what is that, should give good value */
@@ -996,7 +996,7 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
 
     if( p_ff_pic->reference != 0 )
     {
-        p_dec->pf_picture_unlink( p_dec, p_pic );
+        decoder_UnlinkPicture( p_dec, p_pic );
     }
 }
 
diff --git a/modules/codec/cdg.c b/modules/codec/cdg.c
index af912284ef4b..ae0f5bacd822 100644
--- a/modules/codec/cdg.c
+++ b/modules/codec/cdg.c
@@ -153,7 +153,7 @@ static picture_t *Decode( decoder_t *p_dec, block_t **pp_block )
     }
 
     /* Get a new picture */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
     if( !p_pic )
         goto error;
 
diff --git a/modules/codec/dirac.c b/modules/codec/dirac.c
index f621090ec24d..87fb11bba1a6 100644
--- a/modules/codec/dirac.c
+++ b/modules/codec/dirac.c
@@ -168,7 +168,7 @@ static picture_t *GetNewPicture( decoder_t *p_dec )
         p_sys->p_dirac->src_params.frame_rate.denominator;
 
     /* Get a new picture */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     if( p_pic == NULL ) return NULL;
     p_pic->b_progressive = !p_sys->p_dirac->src_params.source_sampling;
diff --git a/modules/codec/dmo/dmo.c b/modules/codec/dmo/dmo.c
index f107f135438d..cb077976c58b 100644
--- a/modules/codec/dmo/dmo.c
+++ b/modules/codec/dmo/dmo.c
@@ -953,7 +953,7 @@ static void *DecBlock( decoder_t *p_dec, block_t **pp_block )
     if( p_dec->fmt_out.i_cat == VIDEO_ES )
     {
         /* Get a new picture */
-        picture_t *p_pic = p_dec->pf_vout_buffer_new( p_dec );
+        picture_t *p_pic = decoder_NewPicture( p_dec );
         if( !p_pic ) return NULL;
 
         CopyPicture( p_pic, block_out.p_buffer );
diff --git a/modules/codec/fake.c b/modules/codec/fake.c
index 0409b70699f8..5974564a90c4 100644
--- a/modules/codec/fake.c
+++ b/modules/codec/fake.c
@@ -345,7 +345,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
     picture_t *p_pic;
 
     if( pp_block == NULL || !*pp_block ) return NULL;
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
     if( p_pic == NULL )
     {
         msg_Err( p_dec, "cannot get picture" );
diff --git a/modules/codec/libmpeg2.c b/modules/codec/libmpeg2.c
index 429f10f27393..2c8ddecf0d48 100644
--- a/modules/codec/libmpeg2.c
+++ b/modules/codec/libmpeg2.c
@@ -341,7 +341,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 
             /* For some reason, libmpeg2 will put this pic twice in
              * discard_picture. This can be considered a bug in libmpeg2. */
-            p_dec->pf_picture_link( p_dec, p_pic );
+            decoder_LinkPicture( p_dec, p_pic );
 
             if( p_sys->p_synchro )
             {
@@ -509,8 +509,8 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
             if( p_sys->p_info->discard_fbuf &&
                 p_sys->p_info->discard_fbuf->id )
             {
-                p_dec->pf_picture_unlink( p_dec,
-                                          p_sys->p_info->discard_fbuf->id );
+                decoder_UnlinkPicture( p_dec,
+                                       p_sys->p_info->discard_fbuf->id );
             }
 
             /* For still frames */
@@ -639,7 +639,7 @@ static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
         VLC_FOURCC('I','4','2','0') : VLC_FOURCC('I','4','2','2');
 
     /* Get a new picture */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     if( p_pic == NULL ) return NULL;
 
@@ -650,7 +650,7 @@ static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
     p_pic->i_nb_fields = p_sys->p_info->current_picture != NULL ?
         p_sys->p_info->current_picture->nb_fields : 2;
 
-    p_dec->pf_picture_link( p_dec, p_pic );
+    decoder_LinkPicture( p_dec, p_pic );
 
     pp_buf[0] = p_pic->p[0].p_pixels;
     pp_buf[1] = p_pic->p[1].p_pixels;
diff --git a/modules/codec/mash.cpp b/modules/codec/mash.cpp
index 244ee101fd44..7895eb642796 100644
--- a/modules/codec/mash.cpp
+++ b/modules/codec/mash.cpp
@@ -202,7 +202,7 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 //    p_sys->p_decoder->sync();
     if( p_block->i_flags & BLOCK_FLAG_END_OF_FRAME )
     {
-        p_pic = p_dec->pf_vout_buffer_new( p_dec );
+        p_pic = decoder_NewPicture( p_dec );
         if( !p_pic )
         {
             block_Release( p_block );
diff --git a/modules/codec/png.c b/modules/codec/png.c
index 7ed1c03e6c9e..7fe5f0794d53 100644
--- a/modules/codec/png.c
+++ b/modules/codec/png.c
@@ -206,7 +206,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
     }
 
     /* Get a new picture */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
     if( !p_pic ) goto error;
 
     /* Decode picture */
diff --git a/modules/codec/quicktime.c b/modules/codec/quicktime.c
index 78531f4ec37f..e4e24cf359e4 100644
--- a/modules/codec/quicktime.c
+++ b/modules/codec/quicktime.c
@@ -924,7 +924,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
  
     vlc_mutex_lock( &qt_mutex );
 
-    if( ( p_pic = p_dec->pf_vout_buffer_new( p_dec ) ) )
+    if( ( p_pic = decoder_NewPicture( p_dec ) ) )
     {
         p_sys->decpar.data                  = (Ptr)p_block->p_buffer;
         p_sys->decpar.bufferSize            = p_block->i_buffer;
diff --git a/modules/codec/rawvideo.c b/modules/codec/rawvideo.c
index c1498644df26..a83a40f54e1e 100644
--- a/modules/codec/rawvideo.c
+++ b/modules/codec/rawvideo.c
@@ -289,7 +289,7 @@ static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block )
     picture_t *p_pic;
 
     /* Get a new picture */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
     if( !p_pic )
     {
         block_Release( p_block );
diff --git a/modules/codec/realvideo.c b/modules/codec/realvideo.c
index cc907e222916..04d7e8467632 100644
--- a/modules/codec/realvideo.c
+++ b/modules/codec/realvideo.c
@@ -463,7 +463,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
 
     vlc_mutex_lock( &rm_mutex );
 
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     if ( p_pic )
     {
diff --git a/modules/codec/schroedinger.c b/modules/codec/schroedinger.c
index b89e7dfa9847..1725e3602b17 100644
--- a/modules/codec/schroedinger.c
+++ b/modules/codec/schroedinger.c
@@ -256,7 +256,7 @@ static void SchroFrameFree( SchroFrame *frame, void *priv)
     if( !p_free )
         return;
 
-    p_free->p_dec->pf_vout_buffer_del( p_free->p_dec, p_free->p_pic );
+    decoder_DeletePicture( p_free->p_dec, p_free->p_pic );
     free(p_free);
     (void)frame;
 }
@@ -274,7 +274,7 @@ static SchroFrame *CreateSchroFrameFromPic( decoder_t *p_dec )
     if( !p_schroframe )
         return NULL;
 
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     if( !p_pic )
         return NULL;
diff --git a/modules/codec/sdl_image.c b/modules/codec/sdl_image.c
index 82022e8873eb..dcc558d25661 100644
--- a/modules/codec/sdl_image.c
+++ b/modules/codec/sdl_image.c
@@ -171,7 +171,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
                                      / p_surface->h;
 
     /* Get a new picture. */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
     if ( p_pic == NULL ) goto error;
 
     switch ( p_surface->format->BitsPerPixel )
diff --git a/modules/codec/tarkin.c b/modules/codec/tarkin.c
index a408ba9cc7e5..5b86788da131 100644
--- a/modules/codec/tarkin.c
+++ b/modules/codec/tarkin.c
@@ -266,7 +266,7 @@ static picture_t *DecodePacket( decoder_t *p_dec, block_t **pp_block,
         p_dec->fmt_out.i_codec = i_chroma;
 
         /* Get a new picture */
-        if( (p_pic = p_dec->pf_vout_buffer_new( p_dec )) )
+        if( (p_pic = decoder_NewPicture( p_dec )) )
         {
             tarkin_CopyPicture( p_dec, p_pic, rgb, i_stride );
 
diff --git a/modules/codec/theora.c b/modules/codec/theora.c
index b3d2e9e0ee1a..b6411c93a788 100644
--- a/modules/codec/theora.c
+++ b/modules/codec/theora.c
@@ -495,7 +495,7 @@ static picture_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
         return NULL;
 
     /* Get a new picture */
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
     if( !p_pic ) return NULL;
 
     theora_CopyPicture( p_dec, p_pic, &yuv );
diff --git a/modules/codec/xvmc/xxmc.c b/modules/codec/xvmc/xxmc.c
index 47adf0cd2be0..7941bc8e1d52 100644
--- a/modules/codec/xvmc/xxmc.c
+++ b/modules/codec/xvmc/xxmc.c
@@ -378,7 +378,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
                 mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
 
                 p_pic->date = 0;
-                p_dec->pf_picture_link( p_dec, p_pic );
+                decoder_LinkPicture( p_dec, p_pic );
 
                 if( p_sys->p_synchro )
                 {
@@ -531,7 +531,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
                 if( p_sys->p_info->discard_fbuf &&
                     p_sys->p_info->discard_fbuf->id )
                 {
-                    p_dec->pf_picture_unlink( p_dec, p_sys->p_info->discard_fbuf->id );
+                    decoder_UnlinkPicture( p_dec, p_sys->p_info->discard_fbuf->id );
                 }
                 /* For still frames */
                 //if( state == STATE_END && p_pic ) p_pic->b_force = true;
@@ -703,7 +703,7 @@ static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
         fflush(p_sys->f_wd_nb);
     }
 #endif
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     if( p_pic == NULL ) return NULL;
 
@@ -716,7 +716,7 @@ static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
     p_pic->format.i_frame_rate = p_dec->fmt_out.video.i_frame_rate;
     p_pic->format.i_frame_rate_base = p_dec->fmt_out.video.i_frame_rate_base;
 
-    p_dec->pf_picture_link( p_dec, p_pic );
+    decoder_LinkPicture( p_dec, p_pic );
 
     pp_buf[0] = p_pic->p[0].p_pixels;
     pp_buf[1] = p_pic->p[1].p_pixels;
diff --git a/modules/misc/stats/decoder.c b/modules/misc/stats/decoder.c
index 2f899ba42c1f..dbe13d8ea6ae 100644
--- a/modules/misc/stats/decoder.c
+++ b/modules/misc/stats/decoder.c
@@ -72,7 +72,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
     p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR;
     p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
 
-    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    p_pic = decoder_NewPicture( p_dec );
 
     if( p_block->i_buffer == kBufferSize )
     {
diff --git a/src/input/decoder.c b/src/input/decoder.c
index b6054cba1a67..ef10f4c772ec 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -161,6 +161,26 @@ struct decoder_owner_sys_t
 /*****************************************************************************
  * Public functions
  *****************************************************************************/
+picture_t *decoder_NewPicture( decoder_t *p_decoder )
+{
+    picture_t *p_picture = p_decoder->pf_vout_buffer_new( p_decoder );
+    if( !p_picture )
+        msg_Warn( p_decoder, "can't get output picture" );
+    return p_picture;
+}
+void decoder_DeletePicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+    p_decoder->pf_vout_buffer_del( p_decoder, p_picture );
+}
+void decoder_LinkPicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+    p_decoder->pf_picture_link( p_decoder, p_picture );
+}
+void decoder_UnlinkPicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+    p_decoder->pf_picture_unlink( p_decoder, p_picture );
+}
+
 aout_buffer_t *decoder_NewAudioBuffer( decoder_t *p_decoder, int i_size )
 {
     if( !p_decoder->pf_aout_buffer_new )
@@ -169,8 +189,6 @@ aout_buffer_t *decoder_NewAudioBuffer( decoder_t *p_decoder, int i_size )
 }
 void decoder_DeleteAudioBuffer( decoder_t *p_decoder, aout_buffer_t *p_buffer )
 {
-    if( !p_decoder->pf_aout_buffer_del )
-        return;
     p_decoder->pf_aout_buffer_del( p_decoder, p_buffer );
 }
 
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 8eac704cb17e..e88d1759a386 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -78,11 +78,14 @@ date_Init
 date_Move
 date_Set
 decoder_DeleteAudioBuffer
+decoder_DeletePicture
 decoder_DeleteSubpicture
 decoder_GetDisplayDate
 decoder_GetDisplayRate
 decoder_GetInputAttachments
+decoder_LinkPicture
 decoder_NewAudioBuffer
+decoder_NewPicture
 decoder_NewSubpicture
 decoder_SynchroChoose
 decoder_SynchroDate
@@ -93,6 +96,7 @@ decoder_SynchroNewPicture
 decoder_SynchroRelease
 decoder_SynchroReset
 decoder_SynchroTrash
+decoder_UnlinkPicture
 decode_URI
 decode_URI_duplicate
 demux_PacketizerDestroy
-- 
GitLab