将mp4转换为mpeg ts,视频和音频播放速度过快

时间:2013-06-13 09:17:40

标签: c mp4 libav mpeg2-ts

我正在将MP4文件转换为MPEG TS格式,虽然我的代码已经开始生成视频文件,但视频和音频的运行速度超高。在输出文件上运行avconv -i(与ffmpeg -i相同)我得到以下内容(180 fps!):

Input #0, mpegts, from 'mpegtest_result.ts':
  Duration: 00:01:56.05, start: 0.011111, bitrate: 6356 kb/s
  Program 1 
    Metadata:
      service_name    : Service01
      service_provider: Libav
    Stream #0.0[0x100]: Video: h264 (Main), yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 180 fps, 90k tbn, 47.95 tbc
    Stream #0.1[0x101]: Audio: aac, 48000 Hz, stereo, fltp, 126 kb/s

目前,在我的代码中,我没有改变数据包的PTS或DTS值,我很确定这是弄乱我的视频。我唯一要改变的是通过这段代码的time_base(变量应该说明一切):

if(av_q2d(input_codec_context->time_base) * input_codec_context->ticks_per_frame > av_q2d(input_stream->time_base) && av_q2d(input_stream->time_base) < 1.0/1000) {
    output_codec_context->time_base = input_codec_context->time_base;
    output_codec_context->time_base.num *= input_codec_context->ticks_per_frame;
}
else {
    output_codec_context->time_base = input_stream->time_base;
}

我知道我应该调用packet.pts = av_rescale_q(...),但我不确定哪些time_bases /值应该重新缩放。

可在此处查看完整代码http://pastebin.com/CHvrvc3G

对于我的输入/输出(代码行189 + 190),我得到以下输出:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testvideo.mp4':
  Metadata:
    major_brand     : M4V 
    minor_version   : 1
    compatible_brands: isomiso2avc1mp41M4A M4V mp42
    encoder         : Lavf54.63.100
  Duration: 00:07:15.41, start: 0.000000, bitrate: 1546 kb/s
    Stream #0.0(eng): Video: h264 (Main), yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 1416 kb/s, 23.98 fps, 11988 tbn, 47.95 tbc
    Stream #0.1(und): Audio: aac, 48000 Hz, stereo, fltp, 127 kb/s
    Metadata:
      creation_time   : 2013-05-09 14:37:22
Output #0, mpegts, to 'mpegtest':
    Stream #0.0: Video: libx264, yuv420p, 1280x720, q=2-31, 1416 kb/s, 90k tbn, 23.98 tbc
    Stream #0.1: Audio: libfaac, 48000 Hz, stereo, 127 kb/s

1 个答案:

答案 0 :(得分:3)

如果您没有进行任何重新缩放,那么毫无疑问时间戳会搞砸。

发送到多路复用器的数据包中的时间戳必须位于流时基(AVStream.time_base)中。现在的API语义是在写入标头之前设置编解码器时基(AVStream.codec.time_base),然后多路复用器选择流时基。它可能会也可能不会使用您设置的编解码器时基。

从解复用器获取的数据包中的时间戳也位于流时基中,因此您应该调用av_rescale_q(pts/dts/duration, input_stream->time_base, output_stream->time_base)