[x264-devel] Re: [PATCH] set a valid value in direct_8x8_inference_flag

Loïc Le Loarer lll+vlc at m4x.org
Sat May 20 02:45:58 CEST 2006


Hi,

Here is patch which implement the following proposal.
I also contains the previous direct_8x8_inference_flag patch I sent.

Best regards.
-- 
Loïc

Le Saturday 20 May 2006 à 00:24:02 +0200, Loïc Le Loarer a écrit:
> Le Friday 19 May 2006 à 13:13:29 -0700, Loren Merritt a écrit:
> > On Fri, 19 May 2006, Loïc Le Loarer wrote:
> > >Le Thursday 11 May 2006 à 19:44:55 +0200, Loïc Le Loarer a écrit:
> > >>This patch avoids to produce invalid streams by enforcing the level
> > >>restrictions on direct_8x8_inference_flag value. It also allows the
> > >>application to ask for a given value of direct_8x8_inference_flag.
> 
> Thank you for taking time to take at look and answer. 
>  
> > The option is ok, but the default value needs quality testing. If 8x8 
> > inference measurably reduces quality, then I will leave it off by 
> > default, even if that violates levels.
> 
> Ok, I see your point of view, but the respect of the level contraints
> are essential in my point of view, because they are used by decoders to
> compute worst case senarii in term of memory, bandwidth, computing
> ressources... and so be sure that they can decode any stream respecting
> a given profile and level in real time. Producing invalid streams breaks
> interoperability and should be avoided. I propose that the default
> options always produce a valid stream and that some levels constraints
> can be ignored only with a special option and a big fat warning.
> 
> More precisely, I propose that only the constraints which cannot be
> removed by using a higher level _and_ can improve encoding quality, can
> be violated (if explicitly asked only, not by default). If I read the
> spec correctly, the candidates are: MaxMvsPer2Mb (not checked yet but
> not relevant), direct_8x8_inference_flag, frame_mbs_only_flag (not
> relevant yet), MinLumaBiPredSize (not relevant yet) and SliceRate (not
> checked yet but not really a problem given the usage of slices). So only
> direct_8x8_inference_flag needs to be evaluated for the moment and
> you are working on it.
> 
> All the other constraints (MB rate, MaxFS, DPB size, MaxBR, MaxCPB,
> MaxVmvR, MinCR (not yet checked, may be a problem for lossless mode))
> should be enforced and the CHECK macro in x264_validate_levels should
> return an error in such a condition, asking for a bigger level.
> 
> This way:
> - someone using the default values (level=5.1) will still be nearly
>   unconstrainted and produce a valid bitstream
> - someone who cares about interoperability and sets a level (and other
>   parameters like direct_8x8_inference_flag) will be confident that x264
>   will respect the level contraints and produce a valid bitstream or
>   refuse to encode at the given level
> - and someone who knows what he does, control the decoder which will be
>   used to decode his stream (and so can break interoperability) and
>   really want to break the limits to increase quality will be able to 
>   do it too.
> 
> I will try to give a patch which explain more clearly this.
> 
> > The mv range thing is probably ok, I'll review it sometime.
> Thank you.
> 
> Best regards.
> 
> -- 
> Loïc
> 
> "heaven is not a place, it's a feeling"
-------------- next part --------------
Index: encoder/set.h
===================================================================
--- encoder/set.h	(révision 525)
+++ encoder/set.h	(copie de travail)
@@ -29,6 +29,6 @@
 void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps );
 void x264_pps_write( bs_t *s, x264_pps_t *pps );
 void x264_sei_version_write( x264_t *h, bs_t *s );
-void x264_validate_levels( x264_t *h );
+int  x264_validate_levels( x264_t *h );
 
 #endif
Index: encoder/encoder.c
===================================================================
--- encoder/encoder.c	(révision 525)
+++ encoder/encoder.c	(copie de travail)
@@ -431,6 +431,26 @@
             h->param.analyse.i_mv_range = l->mv_range;
         else
             h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 2048);
+        /* Validate direct_8x8_inference_flag: */
+        if( h->param.i_direct_8x8_inference_flag < 0 )
+        {
+            /* The flag isn't forced, set it to 0 if the level doesn't
+             * limit it to 1 and it it possible to generate P macroblocks
+             * with partitions smaller than 8x8 */
+            h->param.i_direct_8x8_inference_flag = l->direct8x8 ? 1 : !(h->param.analyse.inter & X264_ANALYSE_PSUB8x8);
+        }
+        else
+        {
+            h->param.i_direct_8x8_inference_flag = x264_clip3( h->param.i_direct_8x8_inference_flag, 0, 1 );
+            /* if the level limits this flag to 1, check it isn't forced to 0 */
+            if (h->param.i_direct_8x8_inference_flag < l->direct8x8)
+            {
+                x264_log( h, X264_LOG_ERROR, "invalid direct_8x8_inference_flag %d for level %d\n", h->param.i_direct_8x8_inference_flag, h->param.i_level_idc );
+               if (!h->param.b_allow_invalid_bitstreams) {
+                   return -1;
+                }
+            }
+        }
     }
 
     if( h->param.rc.f_qblur < 0 )
@@ -536,7 +556,11 @@
     h->pps = &h->pps_array[0];
     x264_pps_init( h->pps, h->param.i_sps_id, &h->param, h->sps);
 
-    x264_validate_levels( h );
+    if (x264_validate_levels( h ) < 0)
+    {
+        x264_free( h );
+        return NULL;
+    }
 
     x264_cqm_init( h );
     
Index: encoder/set.c
===================================================================
--- encoder/set.c	(révision 525)
+++ encoder/set.c	(copie de travail)
@@ -130,13 +130,7 @@
     sps->i_mb_height= ( param->i_height + 15 )/ 16;
     sps->b_frame_mbs_only = 1;
     sps->b_mb_adaptive_frame_field = 0;
-    sps->b_direct8x8_inference = 0;
-    if( sps->b_frame_mbs_only == 0 ||
-        !(param->analyse.inter & X264_ANALYSE_PSUB8x8) )
-    {
-        sps->b_direct8x8_inference = 1;
-    }
-
+    sps->b_direct8x8_inference = param->i_direct_8x8_inference_flag;
     sps->crop.i_left   = 0;
     sps->crop.i_top    = 0;
     sps->crop.i_right  = (- param->i_width)  & 15;
@@ -518,7 +512,7 @@
     { 0 }
 };
 
-void x264_validate_levels( x264_t *h )
+int x264_validate_levels( x264_t *h )
 {
     int mbs;
 
@@ -530,12 +524,20 @@
     if( l->frame_size < mbs
         || l->frame_size*8 < h->sps->i_mb_width * h->sps->i_mb_width
         || l->frame_size*8 < h->sps->i_mb_height * h->sps->i_mb_height )
-        x264_log( h, X264_LOG_WARNING, "frame MB size (%dx%d) > level limit (%d)\n",
+    {
+        x264_log( h, X264_LOG_ERROR, "frame MB size (%dx%d) > level limit (%d)\n",
                   h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size );
+        if (!h->param.b_allow_invalid_bitstreams)
+            return -1;
+    }
 
 #define CHECK( name, limit, val ) \
     if( (val) > (limit) ) \
-        x264_log( h, X264_LOG_WARNING, name " (%d) > level limit (%d)\n", (int)(val), (limit) );
+    { \
+        x264_log( h, X264_LOG_ERROR, name " (%d) > level limit (%d), try increase level\n", (int)(val), (limit) ); \
+        if (!h->param.b_allow_invalid_bitstreams) \
+            return -1; \
+    }
 
     CHECK( "DPB size", l->dpb, mbs * 384 * h->sps->i_num_ref_frames );
     CHECK( "VBV bitrate", l->bitrate, h->param.rc.i_vbv_max_bitrate );
Index: x264.c
===================================================================
--- x264.c	(révision 525)
+++ x264.c	(copie de travail)
@@ -202,6 +202,10 @@
              "                                  (p4x4 requires p8x8. i8x8 requires --8x8dct.)\n"
              "      --direct <string>       Direct MV prediction mode [\"%s\"]\n"
              "                                  - none, spatial, temporal, auto\n"
+             "      --direct_8x8 <-1|0|1>   Direct prediction size [%d]\n"
+             "                                  -  0: 4x4\n"
+             "                                  -  1: 8x8\n"
+             "                                  - -1: smallest possible according to level\n"
              "  -w, --weightb               Weighted prediction for B-frames\n"
              "      --me <string>           Integer pixel motion estimation method [\"%s\"]\n"
              "                                  - dia: diamond search, radius 1 (fast)\n"
@@ -314,6 +318,7 @@
             defaults->rc.f_complexity_blur,
             defaults->rc.f_qblur,
             strtable_lookup( x264_direct_pred_names, defaults->analyse.i_direct_mv_pred ),
+            defaults->i_direct_8x8_inference_flag,
             strtable_lookup( x264_motion_est_names, defaults->analyse.i_me_method ),
             defaults->analyse.i_me_range,
             defaults->analyse.i_subpel_refine,
@@ -452,6 +457,7 @@
 #define OPT_THREAD_INPUT 320
 #define OPT_NO_DCT_DECIMATE 321
 #define OPT_SPS_ID 322
+#define OPT_DIRECT_8X8 323
 
         static struct option long_options[] =
         {
@@ -481,6 +487,7 @@
             { "output",  required_argument, NULL, 'o' },
             { "analyse", required_argument, NULL, 'A' },
             { "direct",  required_argument, NULL, OPT_DIRECT },
+            { "direct_8x8",  required_argument, NULL, OPT_DIRECT_8X8 },
             { "weightb", no_argument,       NULL, 'w' },
             { "me",      required_argument, NULL, OPT_ME },
             { "merange", required_argument, NULL, OPT_MERANGE },
@@ -703,6 +710,9 @@
             case OPT_DIRECT:
                 b_error |= parse_enum( optarg, x264_direct_pred_names, &param->analyse.i_direct_mv_pred );
                 break;
+            case OPT_DIRECT_8X8:
+                param->i_direct_8x8_inference_flag = atoi(optarg);
+                break;
             case 'w':
                 param->analyse.b_weighted_bipred = 1;
                 break;
Index: common/common.c
===================================================================
--- common/common.c	(révision 525)
+++ common/common.c	(copie de travail)
@@ -72,6 +72,7 @@
     param->b_bframe_adaptive = 1;
     param->i_bframe_bias = 0;
     param->b_bframe_pyramid = 0;
+    param->i_direct_8x8_inference_flag = -1;
 
     param->b_deblocking_filter = 1;
     param->i_deblocking_filter_alphac0 = 0;
@@ -132,6 +133,7 @@
     memset( param->cqm_8iy, 16, 64 );
     memset( param->cqm_8py, 16, 64 );
 
+    param->b_allow_invalid_bitstreams = 0;
     param->b_repeat_headers = 1;
     param->b_aud = 0;
 }
@@ -485,10 +487,10 @@
     s += sprintf( s, " bframes=%d", p->i_bframe );
     if( p->i_bframe )
     {
-        s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d bime=%d",
+        s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d d8x8=%d wpredb=%d bime=%d",
                       p->b_bframe_pyramid, p->b_bframe_adaptive, p->i_bframe_bias,
-                      p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred,
-                      p->analyse.b_bidir_me );
+                      p->analyse.i_direct_mv_pred, p->i_direct_8x8_inference_flag,
+                      p->analyse.b_weighted_bipred, p->analyse.b_bidir_me );
     }
 
     s += sprintf( s, " keyint=%d keyint_min=%d scenecut=%d",
Index: x264.h
===================================================================
--- x264.h	(révision 525)
+++ x264.h	(copie de travail)
@@ -159,6 +159,7 @@
     int         b_bframe_adaptive;
     int         i_bframe_bias;
     int         b_bframe_pyramid;   /* Keep some B-frames as references */
+    int         i_direct_8x8_inference_flag; /* Use direct_8x8_inference_flag in SPS: (-1: 0 if possible according to level and partition mode) */
 
     int         b_deblocking_filter;
     int         i_deblocking_filter_alphac0;    /* [-6, 6] -6 light filter, 6 strong */
@@ -243,6 +244,15 @@
         char        *psz_zones;     /* alternate method of specifying zones */
     } rc;
 
+    /* b_allow_invalid_bitstreams allow produce invalid bitstream by violating
+     * certains level contraints.
+     *
+     * this breaks interoperability so it should never be set except if you
+     * know in advance which decoder will decode the produced streams and you
+     * know that this decoder support the constraints which are not respected.
+     * */
+    int b_allow_invalid_bitstreams;
+
     /* Muxing parameters */
     int b_aud;                  /* generate access unit delimiters */
     int b_repeat_headers;       /* put SPS/PPS before each keyframe */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mailman.videolan.org/pipermail/x264-devel/attachments/20060520/36b7181b/attachment.pgp 


More information about the x264-devel mailing list