用ffmpeg库向HEVC添加时间戳,与Gstreamer管道运行时时间戳不匹配

2 人关注

我们正在使用NvEncoder对HEVC的样本帧进行编码。由于HEVC帧没有任何时间戳,为了对视频进行寻址操作,我们用C++写了一个remuxer,为帧有序地创建时间戳,并将编码后的帧写入视频容器(mp4,mov)中。用ffplay播放mp4容器中的输出视频时看起来很好,用ffprobe检查时间戳时似乎也很正确。然而,当我们试图在Gstreamer管道中播放视频时,第二和第三帧的时间戳似乎完全相同。因此,当视频被播放时,第3帧被跳过,第2帧被显示两次。我们不能容忍任何帧的损失,所以我们需要解决这个问题,我们认为这是由于ffmpeg和gstreamer之间在帧的时间戳方面不兼容。如果有帮助的话,我还可以提供我们的reuxer的源代码和输出示例。

我使用下面的Gstreamer管道来播放mp4。

gst-launch-1.0 filesrc location=5_fps.mp4 ! qtdemux name=demux demux.video_0 ! queue! decodebin ! videoconvert ! videoscale ! autovideosink 

下面的命令也给出了同样不匹配的帧时间戳。

ffmpeg -i 5_fps.bin -vcodec copy -acodec copy 5_fps.mp4

非常感谢!

编辑:我正在添加remuxer的部分,其中输入流的每一帧都被读取并添加时间戳。

int frame_no=-1; //starting with -1 gives the same ffprobe results as command line ffmpeg container conversion, starting with 0 again causes the same timestamp problem    
while (1) {
AVStream *in_stream, *out_stream;
_status = av_read_frame(_ifmt_ctx, &_pkt);
if (_status < 0) break;
in_stream  = _ifmt_ctx->streams[_pkt.stream_index];
if (_pkt.stream_index >= _stream_mapping_size ||
    _stream_mapping[_pkt.stream_index] < 0) {
  av_packet_unref(&_pkt);
  continue;
double inputFPS=av_q2d(in_stream->r_frame_rate);
double outputFPS=av_q2d(in_stream->r_frame_rate);
_pkt.stream_index = _stream_mapping[_pkt.stream_index];
out_stream = _ofmt_ctx->streams[_pkt.stream_index];
_pkt.pts=frame_no*in_stream->time_base.den/inputFPS;
_pkt.dts=_pkt.pts;
_pkt.duration = in_stream->time_base.den/inputFPS; 
_pkt.pos = -1;
std::cout<<"rescaled pts: "<<_pkt.pts<<" dts: "<<_pkt.dts<<" frame no: "<< frame_no<<std::endl;
std::cout<<"input time_base den: "<<in_stream->time_base.den<<" output time_base den: "<<out_stream->time_base.den<<std::endl;
frame_no++;
_status = av_interleaved_write_frame(_ofmt_ctx, &_pkt);
if (_status < 0) {
  cout<<"Error muxing packet\n";
  break;
av_packet_unref(&_pkt);}