Video 修改MP4流中的H.264级别

Video 修改MP4流中的H.264级别,video,ffmpeg,h.264,mp4,Video,Ffmpeg,H.264,Mp4,我有1000多个视频包含错误的级别信息,因此无法在某些设备上播放。它们是mp4容器中带有aac音频的H.264基线。我想更正它们,但避免重新编码。我认为这是可能的,而且会更快,对吗?如何识别流中的idc位?所有流是否都在同一位置?我希望这只发生在流中的一个地方,这个假设正确吗? 更新:我遇到了一个windows可执行文件,它声称可以这样做。我希望能够在unix上执行此命令行,以便编写脚本 更多更新:根据下面罗曼的回答。我研究了MP4语法,发现概要文件和级别信息是stsd下avcCatom的一部分

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

更多更新:根据下面罗曼的回答。我研究了MP4语法,发现概要文件和级别信息是
stsd
avcC
atom的一部分。我可以看到该级别设置为
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模式参数,但可惜该流也没有在设备上播放。如何更正
格式配置文件中指示的级别
无需重新编码即可吗?

请注意,级别位于格式描述符上,也可能在负载本身上重复。如果您不关心描述符本身和有效负载/编码的实际完整性(我认为提高级别是好的,但降低级别可能不好),则可以在不重新编码视频的情况下更改级别

更重要的是,这两种方法都是可行的,通过定位包含视频轨迹描述符的框并在那里修补级别-您不需要FFmpeg,而是直接访问字节,MP4格式可能足够简单,可以从纯代码中执行


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

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

现在设置了什么级别,需要什么级别?你能发布一些文件的mediainfo吗?它设置为3.0,我希望它是3.1,它们都是720p视频。根据我对H.264的理解,它包含可以独立解码的数据包,因此每个数据包的头中都有一个级别的idc。如果我使用选项1,直接修改mp4中的位,我可能必须在流中的多个位置执行此操作?
level\u idc
可能会在每一帧中显示,但通常仅在关键帧中显示,并且也是可选的。当然,您可能也想修补帧,这取决于您的任务:如果某些软件或系统因为H.264级别而拒绝该文件,它可能只查看格式描述符来详细说明拒绝,修补描述符就足够了。我修补了描述符。我在STD下找到了avcC,并将级别从1E更改为1F。在此文件上运行的mediainfo为我提供了:
VideoID:1格式:AVC格式/Info:Advanced Video Codec格式配置文件:Baseline@L3.0格式设置,CABAC:无格式设置,重构:3帧Muxing模式:容器配置文件=Baseline@3.1
但它仍然不能在三星电视上播放。mediainfo从哪里获得其他配置文件?电视似乎很关心容器配置文件。是什么让你认为是级别首先导致文件无法播放?因为当我使用相同的参数重新编码,但确保级别设置正确时,它会播放。