Gives the needed DPB size when requesting a vout.
authorLaurent Aimar <fenrir@videolan.org>
Sun, 23 May 2010 20:37:29 +0000 (22:37 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Sun, 23 May 2010 20:37:29 +0000 (22:37 +0200)
It properly fixes #3526.

include/vlc_config.h
include/vlc_vout.h
src/audio_output/input.c
src/input/decoder.c
src/input/resource.c
src/input/resource.h
src/video_output/video_output.c
src/video_output/vout_internal.h
src/video_output/vout_wrapper.c

index 2dfc502..5727629 100644 (file)
 /* Number of planes in a picture */
 #define VOUT_MAX_PLANES                 5
 
-/* Video heap size - remember that a decompressed picture is big
- * (~1 Mbyte) before using huge values */
-#define VOUT_MAX_PICTURES              20
-
 /*
  * Time settings
  */
index f42d319..51c2190 100644 (file)
@@ -54,6 +54,7 @@ typedef struct {
     vout_thread_t        *vout;
     vlc_object_t         *input;
     const video_format_t *fmt;
+    unsigned             dpb_size;
 } vout_configuration_t;
 
 /**
index 85d439b..3894e52 100644 (file)
@@ -816,9 +816,10 @@ static vout_thread_t *RequestVout( void *p_private,
     aout_instance_t *p_aout = p_private;
     VLC_UNUSED(b_recycle);
     vout_configuration_t cfg = {
-        .vout  = p_vout,
-        .input = NULL,
-        .fmt   = p_fmt,
+        .vout     = p_vout,
+        .input    = NULL,
+        .fmt      = p_fmt,
+        .dpb_size = 1,
     };
     return vout_Request( p_aout, &cfg );
 }
index e5f84dd..a68fe96 100644 (file)
@@ -2077,7 +2077,7 @@ static void DeleteDecoder( decoder_t * p_dec )
         vout_Reset( p_owner->p_vout );
 
         /* */
-        input_resource_RequestVout( p_owner->p_input->p->p_resource, p_owner->p_vout, NULL, true );
+        input_resource_RequestVout( p_owner->p_input->p->p_resource, p_owner->p_vout, NULL, 0, true );
         input_SendEventVout( p_owner->p_input );
     }
 
@@ -2157,7 +2157,7 @@ static vout_thread_t *aout_request_vout( void *p_private,
     decoder_t *p_dec = p_private;
     input_thread_t *p_input = p_dec->p_owner->p_input;
 
-    p_vout = input_resource_RequestVout( p_input->p->p_resource, p_vout, p_fmt, b_recyle );
+    p_vout = input_resource_RequestVout( p_input->p->p_resource, p_vout, p_fmt, 1, b_recyle );
     input_SendEventVout( p_input );
 
     return p_vout;
@@ -2333,9 +2333,27 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
         p_owner->p_vout = NULL;
         vlc_mutex_unlock( &p_owner->lock );
 
+        unsigned dpb_size;
+        switch( p_dec->fmt_in.i_codec )
+        {
+        case VLC_CODEC_H264:
+        case VLC_CODEC_DIRAC: /* FIXME valid ? */
+            dpb_size = 18;
+            break;
+        case VLC_CODEC_VP5:
+        case VLC_CODEC_VP6:
+        case VLC_CODEC_VP6F:
+        case VLC_CODEC_VP8:
+            dpb_size = 3;
+            break;
+        default:
+            dpb_size = 2;
+            break;
+        }
         p_vout = input_resource_RequestVout( p_owner->p_input->p->p_resource,
-                                              p_vout, &p_dec->fmt_out.video, true );
-
+                                             p_vout, &p_dec->fmt_out.video,
+                                             dpb_size + 1 + DECODER_MAX_BUFFERING_COUNT,
+                                             true );
         vlc_mutex_lock( &p_owner->lock );
         p_owner->p_vout = p_vout;
 
index b015be8..a97ff7f 100644 (file)
@@ -205,7 +205,8 @@ static void DisplayVoutTitle( input_resource_t *p_resource,
     free( psz_nowplaying );
 }
 static vout_thread_t *RequestVout( input_resource_t *p_resource,
-                                   vout_thread_t *p_vout, video_format_t *p_fmt,
+                                   vout_thread_t *p_vout,
+                                   video_format_t *p_fmt, unsigned dpb_size,
                                    bool b_recycle )
 {
     vlc_assert_locked( &p_resource->lock );
@@ -243,9 +244,10 @@ static vout_thread_t *RequestVout( input_resource_t *p_resource,
 
         /* */
         vout_configuration_t cfg = {
-            .vout  = p_vout,
-            .input = VLC_OBJECT(p_resource->p_input),
-            .fmt   = p_fmt,
+            .vout     = p_vout,
+            .input    = VLC_OBJECT(p_resource->p_input),
+            .fmt      = p_fmt,
+            .dpb_size = dpb_size,
         };
         p_vout = vout_Request( p_resource->p_input, &cfg );
         if( !p_vout )
@@ -281,9 +283,10 @@ static vout_thread_t *RequestVout( input_resource_t *p_resource,
             vout_FlushSubpictureChannel( p_vout, -1 );
 
             vout_configuration_t cfg = {
-                .vout  = p_vout,
-                .input = NULL,
-                .fmt   = p_fmt,
+                .vout     = p_vout,
+                .input    = NULL,
+                .fmt      = p_fmt,
+                .dpb_size = 0,
             };
             p_resource->p_vout_free = vout_Request( p_resource->p_input, &cfg );
         }
@@ -467,10 +470,12 @@ input_resource_t *input_resource_Detach( input_resource_t *p_resource )
 }
 
 vout_thread_t *input_resource_RequestVout( input_resource_t *p_resource,
-                                            vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recycle )
+                                            vout_thread_t *p_vout,
+                                            video_format_t *p_fmt, unsigned dpb_size,
+                                            bool b_recycle )
 {
     vlc_mutex_lock( &p_resource->lock );
-    vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, b_recycle );
+    vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, dpb_size, b_recycle );
     vlc_mutex_unlock( &p_resource->lock );
 
     return p_ret;
@@ -488,7 +493,7 @@ void input_resource_HoldVouts( input_resource_t *p_resource, vout_thread_t ***pp
 
 void input_resource_TerminateVout( input_resource_t *p_resource )
 {
-    input_resource_RequestVout( p_resource, NULL, NULL, false );
+    input_resource_RequestVout( p_resource, NULL, NULL, 0, false );
 }
 bool input_resource_HasVout( input_resource_t *p_resource )
 {
index fa20611..431c237 100644 (file)
@@ -67,7 +67,7 @@ aout_instance_t *input_resource_HoldAout( input_resource_t *p_resource );
 /**
  * This function handles vout request.
  */
-vout_thread_t *input_resource_RequestVout( input_resource_t *, vout_thread_t *, video_format_t *, bool b_recycle );
+vout_thread_t *input_resource_RequestVout( input_resource_t *, vout_thread_t *, video_format_t *, unsigned dpb_size, bool b_recycle );
 
 /**
  * This function return one of the current vout if any.
index d827b41..c096d8e 100644 (file)
@@ -112,6 +112,7 @@ static vout_thread_t *VoutCreate(vlc_object_t *object,
     vout->p = (vout_thread_sys_t*)&vout[1];
 
     vout->p->original = original;
+    vout->p->dpb_size = cfg->dpb_size;
 
     vout_control_Init(&vout->p->control);
     vout_control_PushVoid(&vout->p->control, VOUT_CONTROL_INIT);
@@ -1027,8 +1028,11 @@ static int ThreadReinit(vout_thread_t *vout,
         ThreadClean(vout);
         return VLC_EGENERIC;
     }
-    if (video_format_IsSimilar(&original, &vout->p->original))
-        return VLC_SUCCESS;
+    if (video_format_IsSimilar(&original, &vout->p->original)) {
+        if (cfg->dpb_size <= vout->p->dpb_size)
+            return VLC_SUCCESS;
+        msg_Warn(vout, "DPB need to be increased");
+    }
 
     vout_display_state_t state;
     memset(&state, 0, sizeof(state));
@@ -1045,6 +1049,7 @@ static int ThreadReinit(vout_thread_t *vout,
      * and I am not sure what to do */
 
     vout->p->original = original;
+    vout->p->dpb_size = cfg->dpb_size;
     if (ThreadStart(vout, &state)) {
         ThreadClean(vout);
         return VLC_EGENERIC;
index 0caa915..8602997 100644 (file)
 #include "statistic.h"
 #include "chrono.h"
 
+/* It should be high enough to absorbe jitter due to difficult picture(s)
+ * to decode but not too high as memory is not that cheap.
+ *
+ * It can be made lower at compilation time if needed, but performance
+ * may be degraded.
+ */
+#define VOUT_MAX_PICTURES (20)
+
 /* */
 struct vout_thread_sys_t
 {
@@ -51,6 +59,7 @@ struct vout_thread_sys_t
 
     /* */
     video_format_t  original;   /* Original format ie coming from the decoder */
+    unsigned        dpb_size;
 
     /* Snapshot interface */
     vout_snapshot_t snapshot;
index 6d6be09..0022eeb 100644 (file)
 #include "vout_internal.h"
 #include "display.h"
 
-/* Minimum number of direct pictures the video output will accept without
- * creating additional pictures in system memory */
-#ifdef OPTIMIZE_MEMORY
-#   define VOUT_MIN_DIRECT_PICTURES        (VOUT_MAX_PICTURES/2)
-#else
-#   define VOUT_MIN_DIRECT_PICTURES        (3*VOUT_MAX_PICTURES/4)
-#endif
-
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -126,27 +118,42 @@ int vout_InitWrapper(vout_thread_t *vout)
     vout_display_t *vd = sys->display.vd;
     video_format_t source = vd->source;
 
-    /* XXX For non dr case, the current vout implementation force us to
-     * create at most 1 direct picture (otherwise the buffers will be kept
-     * referenced even through the Init/End.
-     */
     sys->display.use_dr = !vout_IsDisplayFiltered(vd);
     const bool allow_dr = !vd->info.has_pictures_invalid && sys->display.use_dr;
-
-    picture_pool_t *display_pool = vout_display_Pool(vd, allow_dr ? VOUT_MAX_PICTURES : 3);
-    if (allow_dr && picture_pool_GetSize(display_pool) >= VOUT_MIN_DIRECT_PICTURES) {
+    const unsigned private_picture  = 3; /* XXX 2 for filter, 1 for SPU */
+    const unsigned display_picture  = 1; /* Minimum number of display picture */
+    const unsigned decoder_picture  = 1 + sys->dpb_size;
+    const unsigned kept_picture     = 1; /* last displayed picture */
+    const unsigned reserved_picture = display_picture +
+                                      private_picture +
+                                      kept_picture;
+    picture_pool_t *display_pool =
+        vout_display_Pool(vd, allow_dr ? __MAX(VOUT_MAX_PICTURES,
+                                               reserved_picture + decoder_picture) : 3);
+    if (allow_dr &&
+        picture_pool_GetSize(display_pool) >= reserved_picture + decoder_picture) {
+        sys->dpb_size     = picture_pool_GetSize(display_pool) - reserved_picture - kept_picture;
         sys->decoder_pool = display_pool;
         sys->display_pool = display_pool;
         sys->is_decoder_pool_slow = vd->info.is_slow;
     } else if (!sys->decoder_pool) {
-        sys->decoder_pool = picture_pool_NewFromFormat(&source, VOUT_MAX_PICTURES);
+        sys->decoder_pool =
+            picture_pool_NewFromFormat(&source,
+                                       __MAX(VOUT_MAX_PICTURES,
+                                             private_picture + kept_picture + decoder_picture));
+        if (allow_dr) {
+            msg_Warn(vout, "Not enough direct buffers, using system memory");
+            sys->dpb_size = 0;
+        } else {
+            sys->dpb_size = picture_pool_GetSize(display_pool) - private_picture - kept_picture;
+        }
         if (sys->display.use_dr)
             sys->display_pool = display_pool;
         else
-            sys->display_pool = picture_pool_Reserve(sys->decoder_pool, 1);;
+            sys->display_pool = picture_pool_Reserve(sys->decoder_pool, display_picture);
         sys->is_decoder_pool_slow = false;
     }
-    sys->private_pool = picture_pool_Reserve(sys->decoder_pool, 3); /* XXX 2 for filter, 1 for SPU */
+    sys->private_pool = picture_pool_Reserve(sys->decoder_pool, private_picture);
     sys->display.filtered = NULL;
     return VLC_SUCCESS;
 }