x264编码时基计算
x264 encoding timebase calculation
我有 yuv 帧,我正在使用 libx264 成功转换为 h264 帧。我知道每一帧之间的时间差。然后我使用以下 ffmpeg 命令将 h264 视频文件转换为 mp4:
ffmpeg.exe -i frames.h264 -c:v copy -f mp4 frames.mp4
这行得通。但是我不知道如何正确设置可变帧速率。电影放得太快了。我没有固定的帧速率,否则我会设置它并且生成的 mp4 是正确的持续时间。
我有每帧之间的时间差(以毫秒为单位)。如何设置时基和点,以便在将 h264 文件转换为 mp4 时,它是正确的持续时间。
bool X264Encoder::init(int width, int height,
AVRational &timebase, // what should timebase be?
int fps)
{
x264_param_t param;
if( x264_param_default_preset( ¶m, "medium", NULL ) < 0 )
{ return false; }
/* Configure non-default params */
param.i_bitdepth = 8;
param.i_csp = X264_CSP_I420;
param.i_width = width;
param.i_height = height;
param.b_vfr_input = 0;
param.b_repeat_headers = 1;
param.b_annexb = 1;
if(0) // don't have fixed frame rate, can't use it
{
param.b_vfr_input = 0;
param.i_fps_num = 4;
param.i_fps_den = 1;
}
else
{
param.b_vfr_input = 1;
param.i_timebase_num = timebase.den;
param.i_timebase_den = timebase.num;
}
if( x264_param_apply_profile(¶m, "high" ) < 0 )
{ return false; }
m_pic_in = new x264_picture_t;
x264_picture_init(m_pic_in);
m_pic_in->img.i_csp = X264_CSP_I420;
m_pic_in->img.i_plane = 3;
m_encoder = x264_encoder_open(¶m);
}
//This is called for each frame
void X264Encoder::encode(uint8_t *plane[4], int64_t pts) // what should pts be?
{
m_pic_in->img.plane[0] = plane[0]; // Y frame
m_pic_in->img.i_stride[0] = m_width;
m_pic_in->img.plane[1] = plane[1]; // U frame
m_pic_in->img.i_stride[1] = m_width;
m_pic_in->img.plane[2] = plane[2]; // V frame
m_pic_in->img.i_stride[2] = m_width;
x264_picture_t pic_out;
m_pic_in->i_pts = pts;
int frame_size = x264_encoder_encode(m_encoder, &m_nals, &m_i_nals, m_pic_in, &pic_out);
if(frame_size <= 0)
{
return;
}
writeH264Frame(m_nals->p_payload, frame_size); // basically same as fwrite
}
一般来说,时基是你的帧时间戳的单位,即如果你的第一帧有 40 毫秒和 33 毫秒的增量,而不是你设置的时基 1/1000 并提供 pts = 0、40、73。但是原始 H.264(附件 B)格式没有时间戳信息,因此不足以保存 VFR 视频。转换为 mp4 时需要提供时间戳文件,或者当您有编码帧的 pts/dts 信息时需要直接保存为 mp4。
我有 yuv 帧,我正在使用 libx264 成功转换为 h264 帧。我知道每一帧之间的时间差。然后我使用以下 ffmpeg 命令将 h264 视频文件转换为 mp4:
ffmpeg.exe -i frames.h264 -c:v copy -f mp4 frames.mp4
这行得通。但是我不知道如何正确设置可变帧速率。电影放得太快了。我没有固定的帧速率,否则我会设置它并且生成的 mp4 是正确的持续时间。
我有每帧之间的时间差(以毫秒为单位)。如何设置时基和点,以便在将 h264 文件转换为 mp4 时,它是正确的持续时间。
bool X264Encoder::init(int width, int height,
AVRational &timebase, // what should timebase be?
int fps)
{
x264_param_t param;
if( x264_param_default_preset( ¶m, "medium", NULL ) < 0 )
{ return false; }
/* Configure non-default params */
param.i_bitdepth = 8;
param.i_csp = X264_CSP_I420;
param.i_width = width;
param.i_height = height;
param.b_vfr_input = 0;
param.b_repeat_headers = 1;
param.b_annexb = 1;
if(0) // don't have fixed frame rate, can't use it
{
param.b_vfr_input = 0;
param.i_fps_num = 4;
param.i_fps_den = 1;
}
else
{
param.b_vfr_input = 1;
param.i_timebase_num = timebase.den;
param.i_timebase_den = timebase.num;
}
if( x264_param_apply_profile(¶m, "high" ) < 0 )
{ return false; }
m_pic_in = new x264_picture_t;
x264_picture_init(m_pic_in);
m_pic_in->img.i_csp = X264_CSP_I420;
m_pic_in->img.i_plane = 3;
m_encoder = x264_encoder_open(¶m);
}
//This is called for each frame
void X264Encoder::encode(uint8_t *plane[4], int64_t pts) // what should pts be?
{
m_pic_in->img.plane[0] = plane[0]; // Y frame
m_pic_in->img.i_stride[0] = m_width;
m_pic_in->img.plane[1] = plane[1]; // U frame
m_pic_in->img.i_stride[1] = m_width;
m_pic_in->img.plane[2] = plane[2]; // V frame
m_pic_in->img.i_stride[2] = m_width;
x264_picture_t pic_out;
m_pic_in->i_pts = pts;
int frame_size = x264_encoder_encode(m_encoder, &m_nals, &m_i_nals, m_pic_in, &pic_out);
if(frame_size <= 0)
{
return;
}
writeH264Frame(m_nals->p_payload, frame_size); // basically same as fwrite
}
一般来说,时基是你的帧时间戳的单位,即如果你的第一帧有 40 毫秒和 33 毫秒的增量,而不是你设置的时基 1/1000 并提供 pts = 0、40、73。但是原始 H.264(附件 B)格式没有时间戳信息,因此不足以保存 VFR 视频。转换为 mp4 时需要提供时间戳文件,或者当您有编码帧的 pts/dts 信息时需要直接保存为 mp4。