libx264编码器视频播放速度太快

时间:2014-04-23 16:17:34

标签: video encoding x264

我正在尝试编写一个使用libx264编码视频帧的程序。我把这段代码包装成一个小类(见下文)。我有YUV420格式的帧。 libx264对帧进行编码,然后将它们保存到文件中。我可以在VLC中播放该文件,所有帧都在那里,但它以实际帧速率的几百倍播放。目前我正以2.5 FPS的速度捕捉帧数,但它们的回放效果好像是以250 FPS的速度录制的。我试图改变帧速率,没有运气。

我也试过设置

_param.b_vfr_input = 1

然后适当地设置时基,但这会导致我的程序崩溃。有任何想法吗?我的编码代码如下所示。我还包括了ffprobe -show_frames

的输出

包装类:

x264wrapper::x264wrapper(int width, int height, int fps, int timeBaseNum, int timeBaseDen, int vfr)
{
    x264_param_default_preset(&_param, "veryfast", "zerolatency");
    _param.i_threads = 1;
    _param.i_width = width;
    _param.i_height = height;
    _param.i_fps_num = fps;
    _param.i_fps_den = 1;
    // Intra refres:
    _param.i_keyint_max = fps;
    _param.b_intra_refresh = 1;
    //Rate control:
    _param.rc.i_rc_method = X264_RC_CRF;
    //_param.rc.i_rc_method = X264_RC_CQP;
    _param.rc.f_rf_constant = 25;
    _param.rc.f_rf_constant_max = 35;
    //For streaming:
    _param.b_repeat_headers = 1;
    _param.b_annexb = 1;    
    // misc
    _param.b_vfr_input = vfr;
    _param.i_timebase_num = timeBaseNum; 
    _param.i_timebase_den = timeBaseDen;

    _param.i_log_level = X264_LOG_DEBUG;

    _encoder = x264_encoder_open(&_param);

    cout << "Timebase " << _param.i_timebase_num << "/" << _param.i_timebase_den << endl;
    cout << "fps " << _param.i_fps_num << "/" << _param.i_fps_den << endl;
    _ticks_per_frame = (int64_t)_param.i_timebase_den * _param.i_fps_den / _param.i_timebase_num / _param.i_fps_num;
    cout << "ticks_per_frame " << _ticks_per_frame << endl;
    int result = x264_picture_alloc(&_pic_in, X264_CSP_I420, width, height);
    if (result != 0)
    {
        cout << "Failed to allocate picture" << endl;
        throw(1);
    }

    _ofs = new ofstream("output.h264", ofstream::out | ofstream::binary);
    _pts = 0;
}


x264wrapper::~x264wrapper(void)
{
    _ofs->close();
}



void x264wrapper::encode(uint8_t * buf)
{
    x264_nal_t* nals;
    int i_nals;
    convertFromBalserToX264(buf);
    _pts += _ticks_per_frame;
    _pic_in.i_pts = _pts;
    x264_picture_t pic_out;
    int frame_size = x264_encoder_encode(_encoder, &nals, &i_nals, &_pic_in, &pic_out);
    if (frame_size >= 0)
    {
        _ofs->write((char*)nals[0].p_payload, frame_size);
    }
    else
    {
        cout << "error: x264_encoder_encode failed" << endl;
    }
}

输出ffprobe -show_frames:

[FRAME]
media_type=video
key_frame=1
pkt_pts=N/A
pkt_pts_time=N/A
pkt_dts=N/A
pkt_dts_time=N/A
pkt_duration=48000
pkt_duration_time=0.040000
pkt_pos=0
width=1920
height=1080
pix_fmt=yuv420p
sample_aspect_ratio=N/A
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
reference=0
[/FRAME]
[FRAME]
media_type=video
key_frame=0
pkt_pts=N/A
pkt_pts_time=N/A
pkt_dts=N/A
pkt_dts_time=N/A
pkt_duration=N/A
pkt_duration_time=N/A
pkt_pos=54947
width=1920
height=1080
pix_fmt=yuv420p
sample_aspect_ratio=N/A
pict_type=P
coded_picture_number=1
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
reference=0
[/FRAME]
[FRAME]
media_type=video
key_frame=0
pkt_pts=N/A
pkt_pts_time=N/A
pkt_dts=N/A
pkt_dts_time=N/A
pkt_duration=N/A
pkt_duration_time=N/A
pkt_pos=57899
width=1920
height=1080
pix_fmt=yuv420p
sample_aspect_ratio=N/A
pict_type=P
coded_picture_number=2
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
reference=0
[/FRAME]

1 个答案:

答案 0 :(得分:1)

据我了解,您输出原始附件B流,即您不在mkv / mp4等任何容器中复用它。正如我已经回答here原始附件B流在标头(VUI)中的其他几个值内没有任何定时信息,可用于找出恒定的帧速率但在可变帧速率的情况下不起作用(它可能导致以时基的速度播放而不是真正的fps)。如果你有恒定帧速率(param.b_vfr_input = 0)的问题,也要确保使用好的解码器/播放器,因为在过去的VLC中有播放原始附件B流的问题(它的帧速率加倍但不加速百倍)。您还可以尝试使用MKVToolnix对流进行多路复用,并查看它将检测到的fps。