最近做广电音视频项目,从CCTV发布的《中央广播电视总台4K超高清电视节目制播技术规范(暂行)》来看需要支持mxf封装XAVC编码的HLG视频。于是欣然完成了FFmpeg中XAVC Intra Class300/480的扩展工作,并且将HLG的信息封装进了H.264 sps vui中的color_trc、color_primaries。MediaInfo、FFprobe解析视频均解析到HLG/BT2020信息,完美。
今天拿到索贝提供的HLG样片,分析发现样片居然没有vui信息,然而MediaInfo明明解析出HLG/BT2020信息,但是奇怪的是FFProbe居然解析不出。直觉告诉样片的这部分信息一定是存在于mxf的容器封装里面,而不在h264的语法元素内。而且FFmpeg不支持这mxf部分信息的封装。
由于网上没有找到公开的mxf spec/uid定义资料,因此必须通过MediaInfo解码的逆向工程完成FFmpeg mxf的封装支持。
下载MediaInfo源码:
https://netix.dl.sourceforge.net/project/mediainfo/binary/mediainfogui/18.08.1/MediaInfo_GUI_18.08.1_GNU_FromSource.tar.xz
查看mxf解析源码:MediaInfoLib/Source/MediaInfo/Multiple/File_Mxf.cpp
1327 //---------------------------------------------------------------------------
1328 static const char* Mxf_TransferCharacteristic(const int128u TransferCharacteristic)
1329 {
1330 int32u Code_Compare4=(int32u)TransferCharacteristic.lo;
1331 int32u c1 = (int32u)(TransferCharacteristic.lo >> 32);
1332 int32u c2 = (int32u)(TransferCharacteristic.hi);
1333 int32u c3 = (int32u)(TransferCharacteristic.hi >> 32);
1334 printf("c0 %p\n", Code_Compare4);
1335 printf("c1 %p\n", c1);
1336 printf("c2 %p\n", c2);
1337 printf("c3 %p\n", c3);
1338 switch ((int8u)(Code_Compare4>>16))
1339 {
1340 case 0x01 : return "BT.601";
1341 case 0x02 : return "BT.709";
1342 case 0x03 : return "SMPTE 240M";
1343 case 0x04 : return "SMPTE 274M";
1344 case 0x05 : return "BT.1361";
1345 case 0x06 : return "Linear";
1346 case 0x07 : return "SMPTE 428M";
1347 case 0x08 : return "xvYCC";
1348 case 0x09 : return "BT.2020"; // ISO does a difference of value between 10 and 12 bit
1349 case 0x0A : return "PQ";
1350 case 0x0B : return "HLG";
1351 default : return "";
1352 }
1353 }
添加打印,打印出样片color_trc=HLG对应的完整uid值:
c0 0x10b0000
c1 0x4010101
c2 0x401010d
c3 0x60e2b34
1305 static const char* Mxf_ColorPrimaries(const int128u ColorPrimaries)
1306 {
1307 int32u Code_Compare4=(int32u)ColorPrimaries.lo;
1308 int32u c1 = (int32u)(ColorPrimaries.lo >> 32);
1309 int32u c2 = (int32u)(ColorPrimaries.hi);
1310 int32u c3 = (int32u)(ColorPrimaries.hi >> 32);
1311 printf("p0 %p\n", Code_Compare4);
1312 printf("p1 %p\n", c1);
1313 printf("p2 %p\n", c2);
1314 printf("p3 %p\n", c3);
1315 switch ((int8u)(Code_Compare4>>16))
1316 {
1317 case 0x01 : return "BT.601 NTSC";
1318 case 0x02 : return "BT.601 PAL";
1319 case 0x03 : return "BT.709";
1320 case 0x04 : return "BT.2020";
1321 case 0x05 : return "XYZ";
1322 case 0x06 : return "Display P3";
1323 default : return "";
1324 }
1325 }
同样对color_primaries添加打印,打印BT.2020的完整uid:
p0 0x3040000
p1 0x4010101
p2 0x4010101
p3 0x60e2b34
在获取常见关心的BT.709、BT.2020、HDR10(PQ)、HLG的uid后,在FFmpeg mxfenc.c 中添加:
From e3de4edf8ba509f2321223304ef54e6a95a4ba49 Mon Sep 17 00:00:00 2001
2 From: James
3 Date: Tue, 30 Oct 2018 16:48:06 +0800
4 Subject: [PATCH] extends mxf color_trc and color_primaries
5
6 Signed-off-by: James
7 ---
8 libavformat/mxfenc.c | 29 ++++++++++++++++++++++++++++-
9 1 file changed, 28 insertions(+), 1 deletion(-)
10
11 diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
12 index 46cf231a53..626245cfdb 100644
13 --- a/libavformat/mxfenc.c
14 +++ b/libavformat/mxfenc.c
15 @@ -1171,6 +1171,26 @@ static int get_trc(UID ul, enum AVColorTransferCharacteristic trc)
16 case AVCOL_TRC_SMPTE428 :
17 memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x08,0x04,0x01,0x01,0x01,0x01,0x07,0x00,0x00}), 16);
18 return 0;
19 + case AVCOL_TRC_SMPTE2084 :
20 + memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x0A,0x00,0x00}), 16);
21 + return 0;
22 + case AVCOL_TRC_ARIB_STD_B67 :
23 + memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x0B,0x00,0x00}), 16);
24 + return 0;
25 + default:
26 + return -1;
27 + }
28 +}
29 +
30 +static int get_color_primaries(UID ul, enum AVColorPrimaries p)
31 +{
32 + switch (p) {
33 + case AVCOL_PRI_BT709:
34 + memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00}), 16);
35 + return 0;
36 + case AVCOL_PRI_BT2020:
37 + memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x03,0x04,0x00,0x00}), 16);
38 + return 0;
39 default:
40 return -1;
41 }
42 @@ -1185,10 +1205,11 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID
43 int display_height;
44 int f1, f2;
45 UID transfer_ul = {0};
46 + UID color_primaries_ul = {0};
47 int64_t pos = mxf_write_generic_desc(s, st, key);
48
49 - av_log(s, AV_LOG_ERROR, "mxf color_trc %d\n", st->codecpar->color_trc);
50 get_trc(transfer_ul, st->codecpar->color_trc);
51 + get_color_primaries(color_primaries_ul, st->codecpar->color_primaries);
52
53 mxf_write_local_tag(pb, 4, 0x3203);
54 avio_wb32(pb, stored_width);
55 @@ -1342,6 +1363,12 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID
56 avio_w8(pb, sc->field_dominance);
57 }
58
59 + //Color Primaries
60 + if (color_primaries_ul[0]) {
61 + mxf_write_local_tag(pb, 16, 0x3219);
62 + avio_write(pb, color_primaries_ul, 16);
63 + }
64 +
65 return pos;
66 }
67
68 --
69 2.17.1
70
在libx264中去除对vui color_trc和color_primaries的信息添加,确保只有mxf携带,测试:
./ffmpeg -i '/home/lyh/4K/Customer/Sobey/2018080927test_video/10M_SR012CA3.mp4' -r 50 -pix_fmt yuv422p10le -c:v libx264 -avcintra-class 300 -x264opts avcintra-class=300 -x264opts avcintra-flavor=sony -color_primaries bt2020 -color_trc arib-std-b67 -colorspace bt2020nc 1.mxf
MediaInfo打印:
Video
ID : 2
Format : AVC
Format/Info : Advanced Video Codec
Format profile : High 4:2:2 [email protected]
Format settings, CABAC : No
Format settings, GOP : N=1
Format settings, wrapping mode : Frame
Codec ID : 0D01030102106001-0401020201323001
Duration : 1 s 600 ms
Bit rate : 501 Mb/s
Width : 3 840 pixels
Height : 2 160 pixels
Display aspect ratio : 16:9
Frame rate : 50.000 FPS
Color space : YUV
Chroma subsampling : 4:2:2
Bit depth : 10 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 1.207
Stream size : 95.5 MiB (100%)
Color primaries : BT.2020
Transfer characteristics : HLG
顺利识别。