2

好的,很明显,当我发表原始帖子时,我对 ffmpeg API 知之甚少……当一个人开始学习数字媒体和转换细节时,我感到非常不知所措。在阅读了更多内容并通过 ffmpeg 源代码之后,我能够获得从 mp4 到 mpegts 的工作输出。该概念类似于执行:

ffmpeg -i in.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb out.ts

但正如我之前提到的,我需要用 C 中的 ffmpeg API 来实现它。

因此,虽然我能够生成一个可播放的 .ts 文件,但它的视频和音频流并未同步。也就是说,在 Android 平板电脑上播放它们会非常缓慢地播放视频,而音频以正常速度播放,然后(一旦音频流结束)视频以正常速度播放到最后。在 VLC 中播放相同的生成 .ts 文件会产生非常压缩的音频(就像快进一样)并且可以很好地播放视频。

媒体转换还有很多我不熟悉的方面。我确信其中一些会阻止我成功转换。

以下是有关文件的一些信息(通过 ffprobe): - in.mp4 - 通过 Android 录制生成的文件 - MPEG4 (H.264 + AAC) - ffmpeg.ts - 通过 ffmpeg 转换生成的文件 - MPEG2TS (H.264 + AAC) - out.ts - 通过我的代码生成的文件 - MPEGTS (H.264 + AAC)

在.mp4

filename=in.mp4
nb_streams=2
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime/MPEG-4/Motion JPEG 2000 format
start_time=0:00:00.000000
duration=0:00:09.961383
size=4.730 Mibyte
bit_rate=3.983 Mbit/s
TAG:major_brand=isom
TAG:minor_version=0
TAG:compatible_brands=isom3gp4
TAG:creation_time=2013-05-28 17:06:57

ffmpeg.ts

filename=ffmpeg.ts
nb_streams=2
format_name=mpegts
format_long_name=MPEG-2 transport stream format
start_time=0:00:01.400000
duration=0:00:09.741267
size=5.132 Mibyte
bit_rate=4.419 Mbit/s

输出.ts

filename=out.ts
nb_streams=2
format_name=mpegts
format_long_name=MPEG-2 transport stream format
start_time=0:00:00.000000
duration=0:00:09.741267
size=5.166 Mibyte
bit_rate=4.449 Mbit/s

首先,我无法影响输出文件的 start_time。接下来,在检查 probe 的 -show_packets 输出后,我看到了以下内容:

ffmpeg.ts

[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=0
duration_time=0:00:00.000000
size=20.506 Kibyte
pos=564
flags=K
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=0
duration_time=0:00:00.000000
size=11.727 Kibyte
pos=22936
flags=_
[/PACKET]
...
[PACKET]
codec_type=audio
stream_index=1
pts=126000
pts_time=0:00:01.400000
dts=126000
dts_time=0:00:01.400000
duration=2089
duration_time=0:00:00.023211
size=285.000 byte
pos=109416
flags=K
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=128089
pts_time=0:00:01.423211
dts=128089
dts_time=0:00:01.423211
duration=2089
duration_time=0:00:00.023211
size=374.000 byte
pos=-1
flags=K
[/PACKET]
...
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=0
duration_time=0:00:00.000000
size=20.000 Kibyte
pos=87232
flags=_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=0
duration_time=0:00:00.000000
size=16.852 Kibyte
pos=112800
flags=_
[/PACKET]

输出.ts

[PACKET]
codec_type=audio
stream_index=1
pts=0
pts_time=0:00:00.000000
dts=0
dts_time=0:00:00.000000
duration=2089
duration_time=0:00:00.023211
size=285.000 byte
pos=22936
flags=K
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=1024
pts_time=0:00:00.011378
dts=1024
dts_time=0:00:00.011378
duration=2089
duration_time=0:00:00.023211
size=374.000 byte
pos=23312
flags=K
[/PACKET]
...

[PACKET]
codec_type=video
stream_index=0
pts=N/A
pts_time=N/A
dts=N/A
dts_time=N/A
duration=0
duration_time=0:00:00.000000
size=11.727 Kibyte
pos=25004
flags=_
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=7168
pts_time=0:00:00.079644
dts=7168
dts_time=0:00:00.079644
duration=2089
duration_time=0:00:00.023211
size=299.000 byte
pos=55460
flags=K
[/PACKET]

如您所见,ffmpeg.ts 以没有 pts/dts 的视频数据包开始。随后的音频数据包包含 pts/dts。如此重复直到结束。根据 ffprobe 输出,所有视频数据包都没有 pts/dts。

但是,out.ts 以音频数据包开头并与视频数据包交替。在这里,视频数据包也没有 pts/dts。不同之处在于,这里在一系列音频包之间有一个视频包。其余的视频数据包发生了什么(ffmpeg.ts 有 ~5 个音频,然后是 ~5 个视频)。

显然,我还在学习,还不太了解……有什么东西对任何人来说都是显而易见的问题吗?我将非常感谢任何信息/建议,但会继续努力!

4

1 回答 1

2

好的,正如我所怀疑的那样,这很明显,但对新手来说却不是。基本上,即使您不必重新编码数据包,原始容器中的流也会为每个流提供自己的时基。这需要转换或“重新调整”到新输出流的时基。

packet.pts = av_rescale_q(packet->pts, inStream->time_base, outStream->time_base);
packet.dts = av_rescale_q(packet->dts, inStream->time_base, outStream->time_base);

这将为每个流正确重新缩放数据包。当然,这可能是可以采取的最基本的操作,并且可能需要执行额外的交替/重新缩放(数据包没有 dts / pts)。但是,我控制着输入文件,所以这对我来说应该足够了。

于 2013-06-03T19:04:27.267 回答