dovi_rpuenc.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. /*
  2. * Dolby Vision RPU encoder
  3. *
  4. * Copyright (C) 2024 Niklas Haas
  5. *
  6. * This file is part of FFmpeg.
  7. *
  8. * FFmpeg is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * FFmpeg is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with FFmpeg; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include "libavutil/attributes.h"
  23. #include "libavutil/avassert.h"
  24. #include "libavutil/crc.h"
  25. #include "libavutil/mem.h"
  26. #include "libavutil/refstruct.h"
  27. #include "avcodec.h"
  28. #include "dovi_rpu.h"
  29. #include "itut35.h"
  30. #include "put_bits.h"
  31. #include "put_golomb.h"
  32. static const struct {
  33. uint64_t pps; // maximum pixels per second
  34. int width; // maximum width
  35. int main; // maximum bitrate in main tier
  36. int high; // maximum bitrate in high tier
  37. } dv_levels[] = {
  38. [1] = {1280*720*24, 1280, 20, 50},
  39. [2] = {1280*720*30, 1280, 20, 50},
  40. [3] = {1920*1080*24, 1920, 20, 70},
  41. [4] = {1920*1080*30, 2560, 20, 70},
  42. [5] = {1920*1080*60, 3840, 20, 70},
  43. [6] = {3840*2160*24, 3840, 25, 130},
  44. [7] = {3840*2160*30, 3840, 25, 130},
  45. [8] = {3840*2160*48, 3840, 40, 130},
  46. [9] = {3840*2160*60, 3840, 40, 130},
  47. [10] = {3840*2160*120, 3840, 60, 240},
  48. [11] = {3840*2160*120, 7680, 60, 240},
  49. [12] = {7680*4320*60, 7680, 120, 450},
  50. [13] = {7680*4320*120u, 7680, 240, 800},
  51. };
  52. static av_cold int dovi_configure_ext(DOVIContext *s, enum AVCodecID codec_id,
  53. const AVDOVIMetadata *metadata,
  54. enum AVDOVICompression compression,
  55. int strict_std_compliance,
  56. int width, int height,
  57. AVRational framerate,
  58. enum AVPixelFormat pix_format,
  59. enum AVColorSpace color_space,
  60. enum AVColorPrimaries color_primaries,
  61. enum AVColorTransferCharacteristic color_trc,
  62. AVPacketSideData **coded_side_data,
  63. int *nb_coded_side_data)
  64. {
  65. AVDOVIDecoderConfigurationRecord *cfg;
  66. const AVDOVIRpuDataHeader *hdr = NULL;
  67. int dv_profile, dv_level, bl_compat_id = -1;
  68. size_t cfg_size;
  69. uint64_t pps;
  70. if (!s->enable)
  71. goto skip;
  72. if (metadata)
  73. hdr = av_dovi_get_header(metadata);
  74. if (s->enable == FF_DOVI_AUTOMATIC && !hdr)
  75. goto skip;
  76. if (compression == AV_DOVI_COMPRESSION_RESERVED ||
  77. compression > AV_DOVI_COMPRESSION_EXTENDED)
  78. return AVERROR(EINVAL);
  79. switch (codec_id) {
  80. case AV_CODEC_ID_AV1: dv_profile = 10; break;
  81. case AV_CODEC_ID_H264: dv_profile = 9; break;
  82. case AV_CODEC_ID_HEVC:
  83. if (hdr) {
  84. dv_profile = ff_dovi_guess_profile_hevc(hdr);
  85. break;
  86. }
  87. /* This is likely to be proprietary IPTPQc2 */
  88. if (color_space == AVCOL_SPC_IPT_C2 ||
  89. (color_space == AVCOL_SPC_UNSPECIFIED &&
  90. color_trc == AVCOL_TRC_UNSPECIFIED))
  91. dv_profile = 5;
  92. else
  93. dv_profile = 8;
  94. break;
  95. default:
  96. av_unreachable("ff_dovi_configure only used with AV1, H.264 and HEVC");
  97. }
  98. if (strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
  99. if (dv_profile == 9) {
  100. if (pix_format != AV_PIX_FMT_YUV420P)
  101. dv_profile = 0;
  102. } else {
  103. if (pix_format != AV_PIX_FMT_YUV420P10)
  104. dv_profile = 0;
  105. }
  106. }
  107. switch (dv_profile) {
  108. case 4: /* HEVC with enhancement layer */
  109. case 7:
  110. if (s->enable > 0) {
  111. av_log(s->logctx, AV_LOG_ERROR, "Coding of Dolby Vision enhancement "
  112. "layers is currently unsupported.");
  113. return AVERROR_PATCHWELCOME;
  114. } else {
  115. goto skip;
  116. }
  117. case 5: /* HEVC with proprietary IPTPQc2 */
  118. bl_compat_id = 0;
  119. break;
  120. case 10:
  121. /* FIXME: check for proper H.273 tags once those are added */
  122. if (hdr && hdr->bl_video_full_range_flag) {
  123. /* AV1 with proprietary IPTPQc2 */
  124. bl_compat_id = 0;
  125. break;
  126. }
  127. /* fall through */
  128. case 8: /* HEVC (or AV1) with BL compatibility */
  129. if (color_space == AVCOL_SPC_BT2020_NCL &&
  130. color_primaries == AVCOL_PRI_BT2020 &&
  131. color_trc == AVCOL_TRC_SMPTE2084) {
  132. bl_compat_id = 1;
  133. } else if (color_space == AVCOL_SPC_BT2020_NCL &&
  134. color_primaries == AVCOL_PRI_BT2020 &&
  135. color_trc == AVCOL_TRC_ARIB_STD_B67) {
  136. bl_compat_id = 4;
  137. } else if (color_space == AVCOL_SPC_BT709 &&
  138. color_primaries == AVCOL_PRI_BT709 &&
  139. color_trc == AVCOL_TRC_BT709) {
  140. bl_compat_id = 2;
  141. }
  142. }
  143. if (!dv_profile || bl_compat_id < 0) {
  144. if (s->enable > 0) {
  145. av_log(s->logctx, AV_LOG_ERROR, "Dolby Vision enabled, but could "
  146. "not determine profile and compatibility mode. Double-check "
  147. "colorspace and format settings for compatibility?\n");
  148. return AVERROR(EINVAL);
  149. }
  150. goto skip;
  151. }
  152. if (compression != AV_DOVI_COMPRESSION_NONE) {
  153. if (dv_profile < 8 && strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
  154. av_log(s->logctx, AV_LOG_ERROR, "Dolby Vision metadata compression "
  155. "is not permitted for profiles 7 and earlier. (dv_profile: %d, "
  156. "compression: %d)\n", dv_profile, compression);
  157. return AVERROR(EINVAL);
  158. } else if (compression == AV_DOVI_COMPRESSION_EXTENDED &&
  159. strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
  160. av_log(s->logctx, AV_LOG_ERROR, "Dolby Vision extended metadata "
  161. "compression is experimental and not supported by "
  162. "devices.");
  163. return AVERROR(EINVAL);
  164. } else if (dv_profile == 8) {
  165. av_log(s->logctx, AV_LOG_WARNING, "Dolby Vision metadata compression "
  166. "for profile 8 is known to be unsupported by many devices, "
  167. "use with caution.\n");
  168. }
  169. }
  170. pps = width * height;
  171. if (framerate.num) {
  172. pps = pps * framerate.num / framerate.den;
  173. } else {
  174. pps *= 25; /* sanity fallback */
  175. }
  176. dv_level = 0;
  177. for (int i = 1; i < FF_ARRAY_ELEMS(dv_levels); i++) {
  178. if (pps > dv_levels[i].pps)
  179. continue;
  180. if (width > dv_levels[i].width)
  181. continue;
  182. /* In theory, we should also test the bitrate when known, and
  183. * distinguish between main and high tier. In practice, just ignore
  184. * the bitrate constraints and hope they work out. This would ideally
  185. * be handled by either the encoder or muxer directly. */
  186. dv_level = i;
  187. break;
  188. }
  189. if (!dv_level) {
  190. if (strict_std_compliance >= FF_COMPLIANCE_STRICT) {
  191. av_log(s->logctx, AV_LOG_ERROR, "Coded PPS (%"PRIu64") and width (%d) "
  192. "exceed Dolby Vision limitations\n", pps, width);
  193. return AVERROR(EINVAL);
  194. } else {
  195. av_log(s->logctx, AV_LOG_WARNING, "Coded PPS (%"PRIu64") and width (%d) "
  196. "exceed Dolby Vision limitations. Ignoring, resulting file "
  197. "may be non-conforming.\n", pps, width);
  198. dv_level = FF_ARRAY_ELEMS(dv_levels) - 1;
  199. }
  200. }
  201. cfg = av_dovi_alloc(&cfg_size);
  202. if (!cfg)
  203. return AVERROR(ENOMEM);
  204. if (!av_packet_side_data_add(coded_side_data,
  205. nb_coded_side_data,
  206. AV_PKT_DATA_DOVI_CONF, cfg, cfg_size, 0)) {
  207. av_free(cfg);
  208. return AVERROR(ENOMEM);
  209. }
  210. cfg->dv_version_major = 1;
  211. cfg->dv_version_minor = 0;
  212. cfg->dv_profile = dv_profile;
  213. cfg->dv_level = dv_level;
  214. cfg->rpu_present_flag = 1;
  215. cfg->el_present_flag = 0;
  216. cfg->bl_present_flag = 1;
  217. cfg->dv_bl_signal_compatibility_id = bl_compat_id;
  218. cfg->dv_md_compression = compression;
  219. s->cfg = *cfg;
  220. return 0;
  221. skip:
  222. s->cfg = (AVDOVIDecoderConfigurationRecord) {0};
  223. return 0;
  224. }
  225. av_cold int ff_dovi_configure_from_codedpar(DOVIContext *s, AVCodecParameters *par,
  226. const AVDOVIMetadata *metadata,
  227. enum AVDOVICompression compression,
  228. int strict_std_compliance)
  229. {
  230. return dovi_configure_ext(s, par->codec_id, metadata, compression,
  231. strict_std_compliance, par->width, par->height,
  232. par->framerate, par->format, par->color_space,
  233. par->color_primaries, par->color_trc,
  234. &par->coded_side_data, &par->nb_coded_side_data);
  235. }
  236. av_cold int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
  237. {
  238. const AVDOVIMetadata *metadata = NULL;
  239. const AVFrameSideData *sd;
  240. sd = av_frame_side_data_get(avctx->decoded_side_data,
  241. avctx->nb_decoded_side_data,
  242. AV_FRAME_DATA_DOVI_METADATA);
  243. if (sd)
  244. metadata = (const AVDOVIMetadata *) sd->data;
  245. /* Current encoders cannot handle metadata compression during encoding */
  246. return dovi_configure_ext(s, avctx->codec_id, metadata, AV_DOVI_COMPRESSION_NONE,
  247. avctx->strict_std_compliance, avctx->width,
  248. avctx->height, avctx->framerate, avctx->pix_fmt,
  249. avctx->colorspace, avctx->color_primaries, avctx->color_trc,
  250. &avctx->coded_side_data, &avctx->nb_coded_side_data);
  251. }
  252. /* Compares only the static DM metadata parts of AVDOVIColorMetadata (excluding
  253. * dm_metadata_id and scene_refresh_flag) */
  254. static int cmp_dm_level0(const AVDOVIColorMetadata *dm1,
  255. const AVDOVIColorMetadata *dm2)
  256. {
  257. int ret;
  258. for (int i = 0; i < FF_ARRAY_ELEMS(dm1->ycc_to_rgb_matrix); i++) {
  259. if ((ret = av_cmp_q(dm1->ycc_to_rgb_matrix[i], dm2->ycc_to_rgb_matrix[i])))
  260. return ret;
  261. }
  262. for (int i = 0; i < FF_ARRAY_ELEMS(dm1->ycc_to_rgb_offset); i++) {
  263. if ((ret = av_cmp_q(dm1->ycc_to_rgb_offset[i], dm2->ycc_to_rgb_offset[i])))
  264. return ret;
  265. }
  266. for (int i = 0; i < FF_ARRAY_ELEMS(dm1->rgb_to_lms_matrix); i++) {
  267. if ((ret = av_cmp_q(dm1->rgb_to_lms_matrix[i], dm2->rgb_to_lms_matrix[i])))
  268. return ret;
  269. }
  270. return memcmp(&dm1->signal_eotf, &dm2->signal_eotf,
  271. sizeof(AVDOVIColorMetadata) -offsetof(AVDOVIColorMetadata, signal_eotf));
  272. }
  273. /* Tries to reuse the static ext blocks. May reorder `ext->dm_static` */
  274. static int try_reuse_ext(DOVIExt *ext, const AVDOVIMetadata *metadata)
  275. {
  276. int i, j, idx = 0;
  277. for (i = 0; i < metadata->num_ext_blocks; i++) {
  278. const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
  279. if (!ff_dovi_rpu_extension_is_static(dm->level))
  280. continue;
  281. /* Find the first matching ext block and move it to [idx] */
  282. for (j = idx; j < ext->num_static; j++) {
  283. if (!memcmp(&ext->dm_static[j], dm, sizeof(*dm))) {
  284. if (j != idx)
  285. FFSWAP(AVDOVIDmData, ext->dm_static[j], ext->dm_static[idx]);
  286. idx++;
  287. break;
  288. }
  289. }
  290. if (j == ext->num_static) {
  291. /* Found no matching ext block */
  292. return 0;
  293. }
  294. }
  295. /* If idx is less than ext->num_static, then there are extra unmatched
  296. * ext blocks inside ext->dm_static */
  297. return idx == ext->num_static;
  298. }
  299. static inline void put_ue_coef(PutBitContext *pb, const AVDOVIRpuDataHeader *hdr,
  300. uint64_t coef)
  301. {
  302. union { uint32_t u32; float f32; } fpart;
  303. switch (hdr->coef_data_type) {
  304. case RPU_COEFF_FIXED:
  305. set_ue_golomb(pb, coef >> hdr->coef_log2_denom);
  306. put_bits63(pb, hdr->coef_log2_denom,
  307. coef & ((1LL << hdr->coef_log2_denom) - 1));
  308. break;
  309. case RPU_COEFF_FLOAT:
  310. fpart.f32 = coef / (float) (1LL << hdr->coef_log2_denom);
  311. put_bits63(pb, hdr->coef_log2_denom, fpart.u32);
  312. break;
  313. }
  314. }
  315. static inline void put_se_coef(PutBitContext *pb, const AVDOVIRpuDataHeader *hdr,
  316. uint64_t coef)
  317. {
  318. union { uint32_t u32; float f32; } fpart;
  319. switch (hdr->coef_data_type) {
  320. case RPU_COEFF_FIXED:
  321. set_se_golomb(pb, coef >> hdr->coef_log2_denom);
  322. put_bits63(pb, hdr->coef_log2_denom,
  323. coef & ((1LL << hdr->coef_log2_denom) - 1));
  324. break;
  325. case RPU_COEFF_FLOAT:
  326. fpart.f32 = coef / (float) (1LL << hdr->coef_log2_denom);
  327. put_bits63(pb, hdr->coef_log2_denom, fpart.u32);
  328. break;
  329. }
  330. }
  331. static int av_q2den(AVRational q, int den)
  332. {
  333. if (!q.den || q.den == den)
  334. return q.num;
  335. q = av_mul_q(q, av_make_q(den, 1));
  336. return (q.num + (q.den >> 1)) / q.den;
  337. }
  338. static void generate_ext_v1(PutBitContext *pb, const AVDOVIDmData *dm)
  339. {
  340. int ext_block_length, start_pos, pad_bits;
  341. switch (dm->level) {
  342. case 1: ext_block_length = 5; break;
  343. case 2: ext_block_length = 11; break;
  344. case 4: ext_block_length = 3; break;
  345. case 5: ext_block_length = 7; break;
  346. case 6: ext_block_length = 8; break;
  347. case 255: ext_block_length = 6; break;
  348. default: return;
  349. }
  350. set_ue_golomb(pb, ext_block_length);
  351. put_bits(pb, 8, dm->level);
  352. start_pos = put_bits_count(pb);
  353. switch (dm->level) {
  354. case 1:
  355. put_bits(pb, 12, dm->l1.min_pq);
  356. put_bits(pb, 12, dm->l1.max_pq);
  357. put_bits(pb, 12, dm->l1.avg_pq);
  358. break;
  359. case 2:
  360. put_bits(pb, 12, dm->l2.target_max_pq);
  361. put_bits(pb, 12, dm->l2.trim_slope);
  362. put_bits(pb, 12, dm->l2.trim_offset);
  363. put_bits(pb, 12, dm->l2.trim_power);
  364. put_bits(pb, 12, dm->l2.trim_chroma_weight);
  365. put_bits(pb, 12, dm->l2.trim_saturation_gain);
  366. put_sbits(pb, 13, dm->l2.ms_weight);
  367. break;
  368. case 4:
  369. put_bits(pb, 12, dm->l4.anchor_pq);
  370. put_bits(pb, 12, dm->l4.anchor_power);
  371. break;
  372. case 5:
  373. put_bits(pb, 13, dm->l5.left_offset);
  374. put_bits(pb, 13, dm->l5.right_offset);
  375. put_bits(pb, 13, dm->l5.top_offset);
  376. put_bits(pb, 13, dm->l5.bottom_offset);
  377. break;
  378. case 6:
  379. put_bits(pb, 16, dm->l6.max_luminance);
  380. put_bits(pb, 16, dm->l6.min_luminance);
  381. put_bits(pb, 16, dm->l6.max_cll);
  382. put_bits(pb, 16, dm->l6.max_fall);
  383. break;
  384. case 255:
  385. put_bits(pb, 8, dm->l255.dm_run_mode);
  386. put_bits(pb, 8, dm->l255.dm_run_version);
  387. for (int i = 0; i < 4; i++)
  388. put_bits(pb, 8, dm->l255.dm_debug[i]);
  389. break;
  390. }
  391. pad_bits = ext_block_length * 8 - (put_bits_count(pb) - start_pos);
  392. av_assert1(pad_bits >= 0);
  393. put_bits(pb, pad_bits, 0);
  394. }
  395. static void put_cie_xy(PutBitContext *pb, AVCIExy xy)
  396. {
  397. const int denom = 32767;
  398. put_sbits(pb, 16, av_q2den(xy.x, denom));
  399. put_sbits(pb, 16, av_q2den(xy.y, denom));
  400. }
  401. #define ANY6(arr) (arr[0] || arr[1] || arr[2] || arr[3] || arr[4] || arr[5])
  402. #define ANY_XY(xy) (xy.x.num || xy.y.num)
  403. #define ANY_CSP(csp) (ANY_XY(csp.prim.r) || ANY_XY(csp.prim.g) || \
  404. ANY_XY(csp.prim.b) || ANY_XY(csp.wp))
  405. static void generate_ext_v2(PutBitContext *pb, const AVDOVIDmData *dm)
  406. {
  407. int ext_block_length, start_pos, pad_bits;
  408. switch (dm->level) {
  409. case 3: ext_block_length = 5; break;
  410. case 8:
  411. if (ANY6(dm->l8.hue_vector_field)) {
  412. ext_block_length = 25;
  413. } else if (ANY6(dm->l8.saturation_vector_field)) {
  414. ext_block_length = 19;
  415. } else if (dm->l8.clip_trim) {
  416. ext_block_length = 13;
  417. } else if (dm->l8.target_mid_contrast) {
  418. ext_block_length = 12;
  419. } else {
  420. ext_block_length = 10;
  421. }
  422. break;
  423. case 9:
  424. if (ANY_CSP(dm->l9.source_display_primaries)) {
  425. ext_block_length = 17;
  426. } else {
  427. ext_block_length = 1;
  428. }
  429. break;
  430. case 10:
  431. if (ANY_CSP(dm->l10.target_display_primaries)) {
  432. ext_block_length = 21;
  433. } else {
  434. ext_block_length = 5;
  435. }
  436. break;
  437. case 11: ext_block_length = 4; break;
  438. case 254: ext_block_length = 2; break;
  439. default: return;
  440. }
  441. set_ue_golomb(pb, ext_block_length);
  442. put_bits(pb, 8, dm->level);
  443. start_pos = put_bits_count(pb);
  444. switch (dm->level) {
  445. case 3:
  446. put_bits(pb, 12, dm->l3.min_pq_offset);
  447. put_bits(pb, 12, dm->l3.max_pq_offset);
  448. put_bits(pb, 12, dm->l3.avg_pq_offset);
  449. break;
  450. case 8:
  451. put_bits(pb, 8, dm->l8.target_display_index);
  452. put_bits(pb, 12, dm->l8.trim_slope);
  453. put_bits(pb, 12, dm->l8.trim_offset);
  454. put_bits(pb, 12, dm->l8.trim_power);
  455. put_bits(pb, 12, dm->l8.trim_chroma_weight);
  456. put_bits(pb, 12, dm->l8.trim_saturation_gain);
  457. put_bits(pb, 12, dm->l8.ms_weight);
  458. if (ext_block_length < 12)
  459. break;
  460. put_bits(pb, 12, dm->l8.target_mid_contrast);
  461. if (ext_block_length < 13)
  462. break;
  463. put_bits(pb, 12, dm->l8.clip_trim);
  464. if (ext_block_length < 19)
  465. break;
  466. for (int i = 0; i < 6; i++)
  467. put_bits(pb, 8, dm->l8.saturation_vector_field[i]);
  468. if (ext_block_length < 25)
  469. break;
  470. for (int i = 0; i < 6; i++)
  471. put_bits(pb, 8, dm->l8.hue_vector_field[i]);
  472. break;
  473. case 9:
  474. put_bits(pb, 8, dm->l9.source_primary_index);
  475. if (ext_block_length < 17)
  476. break;
  477. put_cie_xy(pb, dm->l9.source_display_primaries.prim.r);
  478. put_cie_xy(pb, dm->l9.source_display_primaries.prim.g);
  479. put_cie_xy(pb, dm->l9.source_display_primaries.prim.b);
  480. put_cie_xy(pb, dm->l9.source_display_primaries.wp);
  481. break;
  482. case 10:
  483. put_bits(pb, 8, dm->l10.target_display_index);
  484. put_bits(pb, 12, dm->l10.target_max_pq);
  485. put_bits(pb, 12, dm->l10.target_min_pq);
  486. put_bits(pb, 8, dm->l10.target_primary_index);
  487. if (ext_block_length < 21)
  488. break;
  489. put_cie_xy(pb, dm->l10.target_display_primaries.prim.r);
  490. put_cie_xy(pb, dm->l10.target_display_primaries.prim.g);
  491. put_cie_xy(pb, dm->l10.target_display_primaries.prim.b);
  492. put_cie_xy(pb, dm->l10.target_display_primaries.wp);
  493. break;
  494. case 11:
  495. put_bits(pb, 8, dm->l11.content_type);
  496. put_bits(pb, 4, dm->l11.whitepoint);
  497. put_bits(pb, 1, dm->l11.reference_mode_flag);
  498. put_bits(pb, 3, 0); /* reserved */
  499. put_bits(pb, 2, dm->l11.sharpness);
  500. put_bits(pb, 2, dm->l11.noise_reduction);
  501. put_bits(pb, 2, dm->l11.mpeg_noise_reduction);
  502. put_bits(pb, 2, dm->l11.frame_rate_conversion);
  503. put_bits(pb, 2, dm->l11.brightness);
  504. put_bits(pb, 2, dm->l11.color);
  505. break;
  506. case 254:
  507. put_bits(pb, 8, dm->l254.dm_mode);
  508. put_bits(pb, 8, dm->l254.dm_version_index);
  509. break;
  510. }
  511. pad_bits = ext_block_length * 8 - (put_bits_count(pb) - start_pos);
  512. av_assert1(pad_bits >= 0);
  513. put_bits(pb, pad_bits, 0);
  514. }
  515. int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
  516. int flags, uint8_t **out_rpu, int *out_size)
  517. {
  518. PutBitContext *pb = &(PutBitContext){0};
  519. const AVDOVIRpuDataHeader *hdr;
  520. const AVDOVIDataMapping *mapping;
  521. const AVDOVIColorMetadata *color;
  522. int vdr_dm_metadata_present, vdr_rpu_id, use_prev_vdr_rpu, profile,
  523. buffer_size, rpu_size, pad, zero_run, dm_compression;
  524. int num_ext_blocks_v1, num_ext_blocks_v2;
  525. int dv_md_compression = s->cfg.dv_md_compression;
  526. uint32_t crc;
  527. uint8_t *dst;
  528. if (!metadata) {
  529. *out_rpu = NULL;
  530. *out_size = 0;
  531. return 0;
  532. }
  533. hdr = av_dovi_get_header(metadata);
  534. mapping = av_dovi_get_mapping(metadata);
  535. color = av_dovi_get_color(metadata);
  536. av_assert0(s->cfg.dv_profile);
  537. if (!(flags & FF_DOVI_COMPRESS_RPU))
  538. dv_md_compression = AV_DOVI_COMPRESSION_NONE;
  539. else if (dv_md_compression == AV_DOVI_COMPRESSION_RESERVED)
  540. return AVERROR(EINVAL);
  541. if (hdr->rpu_type != 2) {
  542. av_log(s->logctx, AV_LOG_ERROR, "Unhandled RPU type %"PRIu8"\n",
  543. hdr->rpu_type);
  544. return AVERROR_INVALIDDATA;
  545. }
  546. if (!(flags & FF_DOVI_COMPRESS_RPU))
  547. dv_md_compression = AV_DOVI_COMPRESSION_NONE;
  548. vdr_rpu_id = mapping->vdr_rpu_id;
  549. use_prev_vdr_rpu = 0;
  550. if (!s->vdr[vdr_rpu_id]) {
  551. s->vdr[vdr_rpu_id] = av_refstruct_allocz(sizeof(AVDOVIDataMapping));
  552. if (!s->vdr[vdr_rpu_id])
  553. return AVERROR(ENOMEM);
  554. }
  555. switch (dv_md_compression) {
  556. case AV_DOVI_COMPRESSION_LIMITED:
  557. /* Limited metadata compression requires vdr_rpi_id == 0 */
  558. if (vdr_rpu_id != 0)
  559. break;
  560. /* fall through */
  561. case AV_DOVI_COMPRESSION_EXTENDED:
  562. if (s->vdr[vdr_rpu_id])
  563. use_prev_vdr_rpu = !memcmp(s->vdr[vdr_rpu_id], mapping, sizeof(*mapping));
  564. break;
  565. case AV_DOVI_COMPRESSION_RESERVED:
  566. return AVERROR(EINVAL);
  567. }
  568. if (s->cfg.dv_md_compression != AV_DOVI_COMPRESSION_EXTENDED) {
  569. /* Flush VDRs to avoid leaking old state; maintaining multiple VDR
  570. * references requires extended compression */
  571. for (int i = 0; i <= DOVI_MAX_DM_ID; i++) {
  572. if (i != vdr_rpu_id)
  573. av_refstruct_unref(&s->vdr[i]);
  574. }
  575. }
  576. if (metadata->num_ext_blocks && !s->ext_blocks) {
  577. s->ext_blocks = av_refstruct_allocz(sizeof(*s->ext_blocks));
  578. if (!s->ext_blocks)
  579. return AVERROR(ENOMEM);
  580. }
  581. vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
  582. if (metadata->num_ext_blocks)
  583. vdr_dm_metadata_present = 1;
  584. if (vdr_dm_metadata_present && !s->dm) {
  585. s->dm = av_refstruct_allocz(sizeof(AVDOVIColorMetadata));
  586. if (!s->dm)
  587. return AVERROR(ENOMEM);
  588. }
  589. dm_compression = 0;
  590. if (dv_md_compression != AV_DOVI_COMPRESSION_NONE) {
  591. if (!cmp_dm_level0(s->dm, color) && try_reuse_ext(s->ext_blocks, metadata))
  592. dm_compression = 1;
  593. }
  594. num_ext_blocks_v1 = num_ext_blocks_v2 = 0;
  595. for (int i = 0; i < metadata->num_ext_blocks; i++) {
  596. const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
  597. if (dm_compression && ff_dovi_rpu_extension_is_static(dm->level))
  598. continue;
  599. switch (dm->level) {
  600. case 1:
  601. case 2:
  602. case 4:
  603. case 5:
  604. case 6:
  605. case 255:
  606. num_ext_blocks_v1++;
  607. break;
  608. case 3:
  609. case 8:
  610. case 9:
  611. case 10:
  612. case 11:
  613. case 254:
  614. num_ext_blocks_v2++;
  615. break;
  616. default:
  617. av_log(s->logctx, AV_LOG_ERROR, "Invalid ext block level %d\n",
  618. dm->level);
  619. return AVERROR_INVALIDDATA;
  620. }
  621. }
  622. buffer_size = 12 /* vdr seq info */ + 5 /* CRC32 + terminator */;
  623. buffer_size += num_ext_blocks_v1 * 13;
  624. buffer_size += num_ext_blocks_v2 * 28;
  625. if (!use_prev_vdr_rpu) {
  626. buffer_size += 160;
  627. for (int c = 0; c < 3; c++) {
  628. for (int i = 0; i < mapping->curves[c].num_pivots - 1; i++) {
  629. switch (mapping->curves[c].mapping_idc[i]) {
  630. case AV_DOVI_MAPPING_POLYNOMIAL: buffer_size += 26; break;
  631. case AV_DOVI_MAPPING_MMR: buffer_size += 177; break;
  632. }
  633. }
  634. }
  635. }
  636. if (vdr_dm_metadata_present)
  637. buffer_size += 67;
  638. av_fast_padded_malloc(&s->rpu_buf, &s->rpu_buf_sz, buffer_size);
  639. if (!s->rpu_buf)
  640. return AVERROR(ENOMEM);
  641. init_put_bits(pb, s->rpu_buf, s->rpu_buf_sz);
  642. /* RPU header */
  643. put_bits(pb, 6, hdr->rpu_type);
  644. put_bits(pb, 11, hdr->rpu_format);
  645. put_bits(pb, 4, hdr->vdr_rpu_profile);
  646. put_bits(pb, 4, hdr->vdr_rpu_level);
  647. put_bits(pb, 1, 1); /* vdr_seq_info_present */
  648. put_bits(pb, 1, hdr->chroma_resampling_explicit_filter_flag);
  649. put_bits(pb, 2, hdr->coef_data_type);
  650. if (hdr->coef_data_type == RPU_COEFF_FIXED)
  651. set_ue_golomb(pb, hdr->coef_log2_denom);
  652. put_bits(pb, 2, hdr->vdr_rpu_normalized_idc);
  653. put_bits(pb, 1, hdr->bl_video_full_range_flag);
  654. if ((hdr->rpu_format & 0x700) == 0) {
  655. int ext_mapping_idc = (hdr->ext_mapping_idc_5_7 << 5) | hdr->ext_mapping_idc_0_4;
  656. set_ue_golomb(pb, hdr->bl_bit_depth - 8);
  657. set_ue_golomb(pb, (ext_mapping_idc << 8) | (hdr->el_bit_depth - 8));
  658. set_ue_golomb(pb, hdr->vdr_bit_depth - 8);
  659. put_bits(pb, 1, hdr->spatial_resampling_filter_flag);
  660. put_bits(pb, 3, dm_compression);
  661. put_bits(pb, 1, hdr->el_spatial_resampling_filter_flag);
  662. put_bits(pb, 1, hdr->disable_residual_flag);
  663. }
  664. s->header = *hdr;
  665. put_bits(pb, 1, vdr_dm_metadata_present);
  666. put_bits(pb, 1, use_prev_vdr_rpu);
  667. set_ue_golomb(pb, vdr_rpu_id);
  668. s->mapping = s->vdr[vdr_rpu_id];
  669. profile = s->cfg.dv_profile ? s->cfg.dv_profile : ff_dovi_guess_profile_hevc(hdr);
  670. if (!use_prev_vdr_rpu) {
  671. set_ue_golomb(pb, mapping->mapping_color_space);
  672. set_ue_golomb(pb, mapping->mapping_chroma_format_idc);
  673. for (int c = 0; c < 3; c++) {
  674. const AVDOVIReshapingCurve *curve = &mapping->curves[c];
  675. int prev = 0;
  676. set_ue_golomb(pb, curve->num_pivots - 2);
  677. for (int i = 0; i < curve->num_pivots; i++) {
  678. put_bits(pb, hdr->bl_bit_depth, curve->pivots[i] - prev);
  679. prev = curve->pivots[i];
  680. }
  681. }
  682. if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
  683. put_bits(pb, 3, mapping->nlq_method_idc);
  684. put_bits(pb, hdr->bl_bit_depth, mapping->nlq_pivots[0]);
  685. put_bits(pb, hdr->bl_bit_depth, mapping->nlq_pivots[1] - mapping->nlq_pivots[0]);
  686. }
  687. set_ue_golomb(pb, mapping->num_x_partitions - 1);
  688. set_ue_golomb(pb, mapping->num_y_partitions - 1);
  689. for (int c = 0; c < 3; c++) {
  690. const AVDOVIReshapingCurve *curve = &mapping->curves[c];
  691. for (int i = 0; i < curve->num_pivots - 1; i++) {
  692. set_ue_golomb(pb, curve->mapping_idc[i]);
  693. switch (curve->mapping_idc[i]) {
  694. case AV_DOVI_MAPPING_POLYNOMIAL: {
  695. set_ue_golomb(pb, curve->poly_order[i] - 1);
  696. if (curve->poly_order[i] == 1)
  697. put_bits(pb, 1, 0); /* linear_interp_flag */
  698. for (int k = 0; k <= curve->poly_order[i]; k++)
  699. put_se_coef(pb, hdr, curve->poly_coef[i][k]);
  700. break;
  701. }
  702. case AV_DOVI_MAPPING_MMR: {
  703. put_bits(pb, 2, curve->mmr_order[i] - 1);
  704. put_se_coef(pb, hdr, curve->mmr_constant[i]);
  705. for (int j = 0; j < curve->mmr_order[i]; j++) {
  706. for (int k = 0; k < 7; k++)
  707. put_se_coef(pb, hdr, curve->mmr_coef[i][j][k]);
  708. }
  709. break;
  710. }
  711. }
  712. }
  713. }
  714. if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
  715. for (int c = 0; c < 3; c++) {
  716. const AVDOVINLQParams *nlq = &mapping->nlq[c];
  717. put_bits(pb, hdr->el_bit_depth, nlq->nlq_offset);
  718. put_ue_coef(pb, hdr, nlq->vdr_in_max);
  719. switch (mapping->nlq_method_idc) {
  720. case AV_DOVI_NLQ_LINEAR_DZ:
  721. put_ue_coef(pb, hdr, nlq->linear_deadzone_slope);
  722. put_ue_coef(pb, hdr, nlq->linear_deadzone_threshold);
  723. break;
  724. }
  725. }
  726. }
  727. memcpy(s->vdr[vdr_rpu_id], mapping, sizeof(*mapping));
  728. }
  729. if (vdr_dm_metadata_present) {
  730. DOVIExt *ext = s->ext_blocks;
  731. const int denom = profile == 4 ? (1 << 30) : (1 << 28);
  732. set_ue_golomb(pb, color->dm_metadata_id); /* affected_dm_id */
  733. set_ue_golomb(pb, color->dm_metadata_id); /* current_dm_id */
  734. set_ue_golomb(pb, color->scene_refresh_flag);
  735. if (!dm_compression) {
  736. for (int i = 0; i < 9; i++)
  737. put_sbits(pb, 16, av_q2den(color->ycc_to_rgb_matrix[i], 1 << 13));
  738. for (int i = 0; i < 3; i++)
  739. put_bits32(pb, av_q2den(color->ycc_to_rgb_offset[i], denom));
  740. for (int i = 0; i < 9; i++)
  741. put_sbits(pb, 16, av_q2den(color->rgb_to_lms_matrix[i], 1 << 14));
  742. put_bits(pb, 16, color->signal_eotf);
  743. put_bits(pb, 16, color->signal_eotf_param0);
  744. put_bits(pb, 16, color->signal_eotf_param1);
  745. put_bits32(pb, color->signal_eotf_param2);
  746. put_bits(pb, 5, color->signal_bit_depth);
  747. put_bits(pb, 2, color->signal_color_space);
  748. put_bits(pb, 2, color->signal_chroma_format);
  749. put_bits(pb, 2, color->signal_full_range_flag);
  750. put_bits(pb, 12, color->source_min_pq);
  751. put_bits(pb, 12, color->source_max_pq);
  752. put_bits(pb, 10, color->source_diagonal);
  753. }
  754. memcpy(s->dm, color, sizeof(*color));
  755. s->color = s->dm;
  756. /* Extension blocks */
  757. set_ue_golomb(pb, num_ext_blocks_v1);
  758. align_put_bits(pb);
  759. for (int i = 0; i < metadata->num_ext_blocks; i++) {
  760. const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
  761. if (dm_compression && ff_dovi_rpu_extension_is_static(dm->level))
  762. continue;
  763. generate_ext_v1(pb, dm);
  764. }
  765. if (num_ext_blocks_v2) {
  766. set_ue_golomb(pb, num_ext_blocks_v2);
  767. align_put_bits(pb);
  768. for (int i = 0; i < metadata->num_ext_blocks; i++) {
  769. const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
  770. if (dm_compression && ff_dovi_rpu_extension_is_static(dm->level))
  771. continue;
  772. generate_ext_v2(pb, av_dovi_get_ext(metadata, i));
  773. }
  774. }
  775. if (ext) {
  776. size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
  777. ext->num_dynamic = 0;
  778. if (!dm_compression)
  779. ext->num_static = 0;
  780. for (int i = 0; i < metadata->num_ext_blocks; i++) {
  781. const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
  782. if (!ff_dovi_rpu_extension_is_static(dm->level))
  783. memcpy(&ext->dm_dynamic[ext->num_dynamic++], dm, ext_sz);
  784. else if (!dm_compression)
  785. memcpy(&ext->dm_static[ext->num_static++], dm, ext_sz);
  786. }
  787. }
  788. } else {
  789. s->color = &ff_dovi_color_default;
  790. av_refstruct_unref(&s->ext_blocks);
  791. }
  792. flush_put_bits(pb);
  793. crc = av_bswap32(av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1,
  794. s->rpu_buf, put_bytes_output(pb)));
  795. put_bits32(pb, crc);
  796. put_bits(pb, 8, 0x80); /* terminator */
  797. flush_put_bits(pb);
  798. rpu_size = put_bytes_output(pb);
  799. if (flags & FF_DOVI_WRAP_T35) {
  800. *out_rpu = av_malloc(rpu_size + 15);
  801. if (!*out_rpu)
  802. return AVERROR(ENOMEM);
  803. init_put_bits(pb, *out_rpu, rpu_size + 15);
  804. put_bits(pb, 8, ITU_T_T35_COUNTRY_CODE_US);
  805. put_bits(pb, 16, ITU_T_T35_PROVIDER_CODE_DOLBY);
  806. put_bits32(pb, 0x800); /* provider_oriented_code */
  807. put_bits(pb, 27, 0x01be6841u); /* fixed EMDF header, see above */
  808. if (rpu_size > 0xFF) {
  809. av_assert2(rpu_size <= 0x10000);
  810. put_bits(pb, 8, (rpu_size >> 8) - 1);
  811. put_bits(pb, 1, 1); /* read_more */
  812. put_bits(pb, 8, rpu_size & 0xFF);
  813. put_bits(pb, 1, 0);
  814. } else {
  815. put_bits(pb, 8, rpu_size);
  816. put_bits(pb, 1, 0);
  817. }
  818. ff_copy_bits(pb, s->rpu_buf, rpu_size * 8);
  819. put_bits(pb, 17, 0x400); /* emdf payload id + emdf_protection */
  820. pad = pb->bit_left & 7;
  821. put_bits(pb, pad, (1 << pad) - 1); /* pad to next byte with 1 bits */
  822. flush_put_bits(pb);
  823. *out_size = put_bytes_output(pb);
  824. return 0;
  825. } else if (flags & FF_DOVI_WRAP_NAL) {
  826. *out_rpu = dst = av_malloc(4 + rpu_size * 3 / 2); /* worst case */
  827. if (!*out_rpu)
  828. return AVERROR(ENOMEM);
  829. *dst++ = 25; /* NAL prefix */
  830. zero_run = 0;
  831. for (int i = 0; i < rpu_size; i++) {
  832. if (zero_run < 2) {
  833. if (s->rpu_buf[i] == 0) {
  834. zero_run++;
  835. } else {
  836. zero_run = 0;
  837. }
  838. } else {
  839. if ((s->rpu_buf[i] & ~3) == 0) {
  840. /* emulation prevention */
  841. *dst++ = 3;
  842. }
  843. zero_run = s->rpu_buf[i] == 0;
  844. }
  845. *dst++ = s->rpu_buf[i];
  846. }
  847. *out_size = dst - *out_rpu;
  848. return 0;
  849. } else {
  850. /* Return intermediate buffer directly */
  851. *out_rpu = s->rpu_buf;
  852. *out_size = rpu_size;
  853. s->rpu_buf = NULL;
  854. s->rpu_buf_sz = 0;
  855. return 0;
  856. }
  857. }