使用FFmpeg在Android上将MPEG4转换为MPEGTS

时间:2013-05-21 21:29:36

标签: android ffmpeg mpeg-4 mpeg2-ts

好吧,很明显,当我发布原始帖子时,我对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)

in.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

out.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]

out.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个视频)。

显然,我还在学习并且还不太了解...有什么事情对任何人来说都是明显的问题吗?我将非常感谢任何信息/建议,但将继续研究它!

1 个答案:

答案 0 :(得分: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)。但是,我控制输入文件,所以这对我来说就足够了。

相关问题