Hello, all!
I was trying to see if x264's cli option "piulldown" can be ported to
libx264/ffmpeg.
Not as simple as copy/pasta, it seems :O
in x264.c (from x264 source tree) I see this:
/* set up pulldown */
if( opt->i_pulldown && !param->b_vfr_input )
{
param->b_pulldown = 1;
param->b_pic_struct = 1;
pulldown = &pulldown_values[opt->i_pulldown];
param->i_timebase_num = param->i_fps_den;
FAIL_IF_ERROR2( fmod( param->i_fps_num * pulldown->fps_factor, 1 ),
"unsupported framerate for chosen pulldown\n" );
param->i_timebase_den = param->i_fps_num * pulldown->fps_factor;
}
and then:
/* Encode frames */
for( ; !b_ctrl_c && (i_frame < param->i_frame_total ||
!param->i_frame_total); i_frame++ )
{
if( filter.get_frame( opt->hin, &cli_pic, i_frame + opt->i_seek ) )
break;
x264_picture_init( &pic );
convert_cli_to_lib_pic( &pic, &cli_pic );
if( !param->b_vfr_input )
pic.i_pts = i_frame;
if( opt->i_pulldown && !param->b_vfr_input )
{
pic.i_pic_struct = pulldown->pattern[ i_frame % pulldown->mod ];
pic.i_pts = (int64_t)( pulldown_pts + 0.5 );
pulldown_pts += pulldown_frame_duration[pic.i_pic_struct];
I tried to insert similar logic into libx264, but failed %)
in x264.h i see
typedef struct x264_picture_t
{
/* In: force picture type (if not auto)
* If x264 encoding parameters are violated in the forcing of picture
types,
* x264 will correct the input picture type and log a warning.
* Out: type of the picture encoded */
int i_type;
/* In: force quantizer for != X264_QP_AUTO */
int i_qpplus1;
/* In: pic_struct, for pulldown/doubling/etc...used only if b_pic_struct=1.
* use pic_struct_e for pic_struct inputs
* Out: pic_struct element associated with frame */
int i_pic_struct;
and enum declared just above this as
enum pic_struct_e
{
PIC_STRUCT_AUTO = 0, // automatically decide (default)
PIC_STRUCT_PROGRESSIVE = 1, // progressive frame
// "TOP" and "BOTTOM" are not supported in x264 (PAFF only)
PIC_STRUCT_TOP_BOTTOM = 4, // top field followed by bottom
PIC_STRUCT_BOTTOM_TOP = 5, // bottom field followed by top
PIC_STRUCT_TOP_BOTTOM_TOP = 6, // top field, bottom field, top field
repeated
PIC_STRUCT_BOTTOM_TOP_BOTTOM = 7, // bottom field, top field, bottom field
repeated
PIC_STRUCT_DOUBLE = 8, // double frame
PIC_STRUCT_TRIPLE = 9, // triple frame
};
so, it basically number ? Just this number should be put in encoded frames,
so they can be repeated at decoding according to pattern?
Now, does libx264 allow such manipulation, I mean it eats frames, and feed them
to x264 library fuctions, so
just re-doing this dance with pts and timebase and pic_struct should be enough
for making pulldown-converted video?
It seems blu-ray at specific resolutions/framerates demand this type of
encoding, see for example
http://www.x264bluray.com/home/720p-encoding
"NB: the next two streams use frame doubling to comply with the Blu-Ray
specification:
720p25
x264 --bitrate XXXXX --preset veryslow --tune film --bluray-compat
--vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 25 --open-gop
--slices 4
--pulldown double
--colorprim "bt709" --transfer "bt709" --colormatrix "bt709" --sar 1:1 --pass 1
-o out.264 input.file"
But because pulldown option only supported via x264 cli, it makes creating such
streams harder, at least for CinelerraGG
Also, what kind of program can check if this pulldown process actually was
applied to encoded stream? medianfo?
Copy/pasta 'patch' attached ... (it isn't working, not even compiling, just for
showing areas I hack on..
I hope at least i bark at correct tree?)
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index bfd91bb900..8dc4e4dd79 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -842,6 +842,66 @@ FF_ENABLE_DEPRECATION_WARNINGS
av_reduce(&sw, &sh, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 4096);
x4->params.vui.i_sar_width = sw;
x4->params.vui.i_sar_height = sh;
+ if (x4->params.b_pulldown) {
+
+ static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };
+
+typedef struct
+{
+ int mod;
+ uint8_t pattern[24];
+ float fps_factor;
+} cli_pulldown_t;
+
+enum pulldown_type_e
+{
+ X264_PULLDOWN_22 = 1,
+ X264_PULLDOWN_32,
+ X264_PULLDOWN_64,
+ X264_PULLDOWN_DOUBLE,
+ X264_PULLDOWN_TRIPLE,
+ X264_PULLDOWN_EURO
+};
+
+#define TB PIC_STRUCT_TOP_BOTTOM
+#define BT PIC_STRUCT_BOTTOM_TOP
+#define TBT PIC_STRUCT_TOP_BOTTOM_TOP
+#define BTB PIC_STRUCT_BOTTOM_TOP_BOTTOM
+
+static const cli_pulldown_t pulldown_values[] =
+{
+ [X264_PULLDOWN_22] = {1, {TB}, 1.0},
+ [X264_PULLDOWN_32] = {4, {TBT, BT, BTB, TB}, 1.25},
+ [X264_PULLDOWN_64] = {2, {PIC_STRUCT_DOUBLE, PIC_STRUCT_TRIPLE}, 1.0},
+ [X264_PULLDOWN_DOUBLE] = {1, {PIC_STRUCT_DOUBLE}, 2.0},
+ [X264_PULLDOWN_TRIPLE] = {1, {PIC_STRUCT_TRIPLE}, 3.0},
+ [X264_PULLDOWN_EURO] = {24, {TBT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT,
+ BTB, TB, TB, TB, TB, TB, TB, TB, TB, TB, TB, TB}, 25.0/24.0}
+};
+
+#undef TB
+#undef BT
+#undef TBT
+#undef BTB
+double pulldown_pts = 0;
+int i_frame = 0;
+
+// indexed by pic_struct enum
+static const float pulldown_frame_duration[10] = { 0.0, 1, 0.5, 0.5, 1, 1, 1.5, 1.5, 2, 3 };
+
+ x4->params.b_pulldown = 1;
+ x4->params.b_pic_struct = 1;
+ pulldown = &pulldown_values[opt->i_pulldown];
+ x4->params.i_timebase_num = x4->params.i_fps_den;
+ //FAIL_IF_ERROR2( fmod( param->i_fps_num * pulldown->fps_factor, 1 ),
+ // "unsupported framerate for chosen pulldown\n" );
+ x4->params.i_timebase_den = x4->params.i_fps_num * pulldown->fps_factor;
+
+ x4->pic.i_pic_struct = pulldown->pattern[ i_frame % pulldown->mod ];
+ x4->pic.i_pts = (int64_t)( pulldown_pts + 0.5 );
+ pulldown_pts += pulldown_frame_duration[x4->pic.i_pic_struct];
+}
+
x4->params.i_timebase_den = avctx->time_base.den;
x4->params.i_timebase_num = avctx->time_base.num;
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
_______________________________________________
Libav-user mailing list
[email protected]
https://ffmpeg.org/mailman/listinfo/libav-user
To unsubscribe, visit link above, or email
[email protected] with subject "unsubscribe".