Add frame-packing SEI support for signalling 3D video
authorVittorio Giovara <vitto.giova@yahoo.it>
Sat, 11 Dec 2010 04:43:00 +0000 (20:43 -0800)
committerJason Garrett-Glaser <darkshikari@gmail.com>
Tue, 14 Dec 2010 18:55:26 +0000 (10:55 -0800)
common/common.c
common/common.h
encoder/encoder.c
encoder/set.c
encoder/set.h
x264.c
x264.h

index 951e326..26b62a3 100644 (file)
@@ -165,6 +165,7 @@ void x264_param_default( x264_param_t *param )
     param->b_tff = 1;
     param->b_pic_struct = 0;
     param->b_fake_interlaced = 0;
+    param->i_frame_packing = -1;
 }
 
 static int x264_param_apply_preset( x264_param_t *param, const char *preset )
@@ -978,6 +979,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
         p->b_pic_struct = atobool(value);
     OPT("fake-interlaced")
         p->b_fake_interlaced = atobool(value);
+    OPT("frame-packing")
+        p->i_frame_packing = atoi(value);
     else
         return X264_PARAM_BAD_NAME;
 #undef OPT
index 3c80c0c..119508c 100644 (file)
@@ -309,6 +309,7 @@ enum sei_payload_type_e
     SEI_USER_DATA_REGISTERED   = 4,
     SEI_USER_DATA_UNREGISTERED = 5,
     SEI_RECOVERY_POINT         = 6,
+    SEI_FRAME_PACKING          = 45,
 };
 
 typedef struct
index ab66661..f5c481c 100644 (file)
@@ -469,6 +469,8 @@ static int x264_validate_parameters( x264_t *h )
         }
     }
 
+    h->param.i_frame_packing = x264_clip3( h->param.i_frame_packing, -1, 5 );
+
     /* Detect default ffmpeg settings and terminate with an error. */
     {
         int score = 0;
@@ -1199,6 +1201,7 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
     COPY( b_deblocking_filter );
     COPY( i_deblocking_filter_alphac0 );
     COPY( i_deblocking_filter_beta );
+    COPY( i_frame_packing );
     COPY( analyse.inter );
     COPY( analyse.intra );
     COPY( analyse.i_direct_mv_pred );
@@ -2674,7 +2677,17 @@ int     x264_encoder_encode( x264_t *h,
             int time_to_recovery = h->param.i_open_gop ? 0 : X264_MIN( h->mb.i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe - 1;
             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
             x264_sei_recovery_point_write( h, &h->out.bs, time_to_recovery );
-            x264_nal_end( h );
+            if( x264_nal_end( h ) )
+                return -1;
+            overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
+        }
+
+        if ( h->param.i_frame_packing >= 0 )
+        {
+            x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+            x264_sei_frame_packing_write( h, &h->out.bs );
+            if( x264_nal_end( h ) )
+                return -1;
             overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
         }
     }
index 6cf0c6a..622d16f 100644 (file)
@@ -638,6 +638,47 @@ void x264_sei_pic_timing_write( x264_t *h, bs_t *s )
     x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_PIC_TIMING );
 }
 
+void x264_sei_frame_packing_write( x264_t *h, bs_t *s )
+{
+    bs_t q;
+    uint8_t tmp_buf[100];
+    bs_init( &q, tmp_buf, 100 );
+
+    bs_realign( &q );
+
+    bs_write_ue( &q, 0 );                         // frame_packing_arrangement_id
+    bs_write1( &q, 0 );                           // frame_packing_arrangement_cancel_flag
+    bs_write ( &q, 7, h->param.i_frame_packing ); // frame_packing_arrangement_type
+    bs_write1( &q, 0 );                           // quincunx_sampling_flag
+
+    // 0: views are unrelated, 1: left view is on the left, 2: left view is on the right
+    bs_write ( &q, 6, 1 );                        // content_interpretation_type
+
+    /* The following flags shall be set to 0 and ignored by the decoder
+     * (Why, then, do they even exist?  Who knows.) */
+    bs_write1( &q, 0 );                           // spatial_flipping_flag
+    bs_write1( &q, 0 );                           // frame0_flipped_flag
+    bs_write1( &q, 0 );                           // field_views_flag
+    bs_write1( &q, 0 );                           // current_frame_is_frame0_flag
+    bs_write1( &q, 0 );                           // frame0_self_contained_flag
+    bs_write1( &q, 0 );                           // frame1_self_contained_flag
+    if ( /* quincunx_sampling_flag == 0 && */ h->param.i_frame_packing != 5 )
+    {
+        bs_write( &q, 4, 0 );                     // frame0_grid_position_x
+        bs_write( &q, 4, 0 );                     // frame0_grid_position_y
+        bs_write( &q, 4, 0 );                     // frame1_grid_position_x
+        bs_write( &q, 4, 0 );                     // frame1_grid_position_y
+    }
+    bs_write( &q, 8, 0 );                         // frame_packing_arrangement_reserved_byte
+    bs_write_ue( &q, 0 );                         // frame_packing_arrangement_repetition_period
+    bs_write1( &q, 0 );                           // frame_packing_arrangement_extension_flag
+
+    bs_align_10( &q );
+    bs_flush( &q );
+
+    x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_FRAME_PACKING );
+}
+
 void x264_filler_write( x264_t *h, bs_t *s, int filler )
 {
     bs_realign( s );
index 6d70e96..83c1bd9 100644 (file)
@@ -36,6 +36,7 @@ int  x264_sei_version_write( x264_t *h, bs_t *s );
 int  x264_validate_levels( x264_t *h, int verbose );
 void x264_sei_buffering_period_write( x264_t *h, bs_t *s );
 void x264_sei_pic_timing_write( x264_t *h, bs_t *s );
+void x264_sei_frame_packing_write( x264_t *h, bs_t *s );
 void x264_sei_write( bs_t *s, uint8_t *payload, int payload_size, int payload_type );
 void x264_filler_write( x264_t *h, bs_t *s, int filler );
 
diff --git a/x264.c b/x264.c
index 6fdd24a..1e465ad 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -551,6 +551,13 @@ static void help( x264_param_t *defaults, int longhelp )
     H2( "      --fake-interlaced       Flag stream as interlaced but encode progressive.\n"
         "                              Makes it possible to encode 25p and 30p Blu-Ray\n"
         "                              streams. Ignored in interlaced mode.\n" );
+    H2( "      --frame-packing <integer> For stereoscopic videos define frame arrangement\n"
+        "                                  - 0: checkerboard - pixels are alternatively from L and R\n"
+        "                                  - 1: column alternation - L and R are interlaced by column\n"
+        "                                  - 2: row alternation - L and R are interlaced by row\n"
+        "                                  - 3: side by side - L is on the left, R on the right\n"
+        "                                  - 4: top bottom - L is on top, R on bottom\n"
+        "                                  - 5: frame alternation - one view per frame\n" );
     H0( "\n" );
     H0( "Ratecontrol:\n" );
     H0( "\n" );
@@ -937,6 +944,7 @@ static struct option long_options[] =
     { "nal-hrd",     required_argument, NULL, 0 },
     { "pulldown",    required_argument, NULL, OPT_PULLDOWN },
     { "fake-interlaced",   no_argument, NULL, 0 },
+    { "frame-packing",     required_argument, NULL, 0 },
     { "vf",          required_argument, NULL, OPT_VIDEO_FILTER },
     { "video-filter", required_argument, NULL, OPT_VIDEO_FILTER },
     { "input-res",   required_argument, NULL, OPT_INPUT_RES },
diff --git a/x264.h b/x264.h
index d6c2120..c0fe84d 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -41,7 +41,7 @@
 
 #include "x264_config.h"
 
-#define X264_BUILD 110
+#define X264_BUILD 111
 
 /* x264_t:
  *      opaque handler for encoder */
@@ -390,6 +390,9 @@ typedef struct x264_param_t
         unsigned int i_bottom;
     } crop_rect;
 
+    /* frame packing arrangement flag */
+    int i_frame_packing;
+
     /* Muxing parameters */
     int b_aud;                  /* generate access unit delimiters */
     int b_repeat_headers;       /* put SPS/PPS before each keyframe */