修改MP4流中的H.264级别

时间:2013-03-20 09:33:39

标签: video ffmpeg h.264 mp4

我有超过1000个视频,其中包含错误的等级信息,因此无法在某些设备上播放。它们是H.264基线,在mp4容器中带有aac音频。我想纠正它们,但避免重新编码。我是否正确地认为这是可能的并且会更快?如何识别流中的level_idc位?所有流都会将它们放在同一个位置吗?我希望这只是在流中的一个地方,这个假设是否正确? 更新:我遇到了声称可以执行此操作的Windows可执行文件link。我希望能够在unix上执行此命令行,因此我可以编写脚本。

更多更新:根据罗马的答案如下。我挖出了MP4语法,发现Profile和Level信息是avcCstsd个原子的一部分。我可以看到该级别设置为1E,我将其更正为1F。之前:61 76 63 43 01 42 C0 1E FF E1 00 19 67 42 C0 1E D9 之后:61 76 63 43 01 42 C0 1F FF E1 00 19 67 42 C0 1E D9将MediaInfo更改为:

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : Baseline@L3.0
Format settings, CABAC                   : No
Format settings, ReFrames                : 3 frames
Muxing mode                              : Container profile=Baseline@3.1
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 1mn 4s
Bit rate                                 : 3 000 Kbps
Width                                    : 1 280 pixels
Height                                   : 720 pixels
Display aspect ratio                     : 16:9
Frame rate mode                          : Constant
Frame rate                               : 30.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.109
Stream size                              : 22.7 MiB (92%)
Writing library                          : x264 core 120 r2151 a3f4407
Encoding settings                        : cabac=0 / ref=3 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=0 / weightp=0 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=3000 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00 

它引入了一个具有级别3.1的Muxing模式参数,但是这个流也没有在设备上播放。如何更正Format Profile中指示的级别如果没有重新编码,这是否可行?

2 个答案:

答案 0 :(得分:1)

请注意,格式描述符上存在级别,并且还可能在有效负载本身上重复。如果你不关心描述符本身和有效载荷/编码的实际完整性(我认为提高级别很好,但降低它可能不合适),可以在不重新编码视频的情况下改变级别。

不仅如此,通过定位保存视频轨道描述符的框并在那里修改关卡,可以两种方式完成 - 你不需要FFmpeg,你宁可直接访问字节而MP4格式也许足够简单用普通代码来做。

或者,您需要在路上重新多路复用轨道更改格式。解复用器和多路复用器不进行检查以判断该电平值是否可接受,因此将其作为与FFmpeg重新多路复用的一部分进行修补是可行的。在没有重新编码的情况下写入MP4的任何示例FFmpeg代码都是一个好的开始(您的任务是在打开extradata之前更新AVFormatContext字段指向的字节数组。)

答案 1 :(得分:0)

我找到了一个解决方案,@ Roman帮助我解决了这个问题。 在mp4比特流中查找avcC原子之后的配置文件和级别,在我的例子中,这是42 C0 1E,Baseline @L3.0,我希望级别为3.1。为此,请在流中查找42 C0 1E的所有匹配项,并将1E替换为1F。我发现了大约8-10次这样的事件。现在你有了Baseline@L3.1。这可以使用mediainfo进行验证。我认为这是必要的,因为h.264被编码为一堆数据包,并且每个数据包都有带有配置文件和级别信息的SPS头。