You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
15KB

  1. /*
  2. * This file is part of Libav.
  3. *
  4. * Libav is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * Libav is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with Libav; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "libavutil/common.h"
  19. #include "libavutil/opt.h"
  20. #include "bsf.h"
  21. #include "cbs.h"
  22. #include "cbs_h265.h"
  23. #include "hevc.h"
  24. enum {
  25. PASS,
  26. INSERT,
  27. REMOVE,
  28. };
  29. typedef struct H265MetadataContext {
  30. const AVClass *class;
  31. CodedBitstreamContext *cbc;
  32. CodedBitstreamFragment access_unit;
  33. H265RawAUD aud_nal;
  34. int aud;
  35. AVRational sample_aspect_ratio;
  36. int video_format;
  37. int video_full_range_flag;
  38. int colour_primaries;
  39. int transfer_characteristics;
  40. int matrix_coefficients;
  41. int chroma_sample_loc_type;
  42. AVRational tick_rate;
  43. int poc_proportional_to_timing_flag;
  44. int num_ticks_poc_diff_one;
  45. int crop_left;
  46. int crop_right;
  47. int crop_top;
  48. int crop_bottom;
  49. } H265MetadataContext;
  50. static int h265_metadata_update_vps(AVBSFContext *bsf,
  51. H265RawVPS *vps)
  52. {
  53. H265MetadataContext *ctx = bsf->priv_data;
  54. if (ctx->tick_rate.num && ctx->tick_rate.den) {
  55. int num, den;
  56. av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den,
  57. UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX);
  58. vps->vps_time_scale = num;
  59. vps->vps_num_units_in_tick = den;
  60. vps->vps_timing_info_present_flag = 1;
  61. if (ctx->num_ticks_poc_diff_one > 0) {
  62. vps->vps_num_ticks_poc_diff_one_minus1 =
  63. ctx->num_ticks_poc_diff_one - 1;
  64. vps->vps_poc_proportional_to_timing_flag = 1;
  65. } else if (ctx->num_ticks_poc_diff_one == 0) {
  66. vps->vps_poc_proportional_to_timing_flag = 0;
  67. }
  68. }
  69. return 0;
  70. }
  71. static int h265_metadata_update_sps(AVBSFContext *bsf,
  72. H265RawSPS *sps)
  73. {
  74. H265MetadataContext *ctx = bsf->priv_data;
  75. int need_vui = 0;
  76. int crop_unit_x, crop_unit_y;
  77. if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) {
  78. // Table E-1.
  79. static const AVRational sar_idc[] = {
  80. { 0, 0 }, // Unspecified (never written here).
  81. { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 },
  82. { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 },
  83. { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 },
  84. { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 },
  85. };
  86. int num, den, i;
  87. av_reduce(&num, &den, ctx->sample_aspect_ratio.num,
  88. ctx->sample_aspect_ratio.den, 65535);
  89. for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) {
  90. if (num == sar_idc[i].num &&
  91. den == sar_idc[i].den)
  92. break;
  93. }
  94. if (i == FF_ARRAY_ELEMS(sar_idc)) {
  95. sps->vui.aspect_ratio_idc = 255;
  96. sps->vui.sar_width = num;
  97. sps->vui.sar_height = den;
  98. } else {
  99. sps->vui.aspect_ratio_idc = i;
  100. }
  101. sps->vui.aspect_ratio_info_present_flag = 1;
  102. need_vui = 1;
  103. }
  104. #define SET_OR_INFER(field, value, present_flag, infer) do { \
  105. if (value >= 0) { \
  106. field = value; \
  107. need_vui = 1; \
  108. } else if (!present_flag) \
  109. field = infer; \
  110. } while (0)
  111. if (ctx->video_format >= 0 ||
  112. ctx->video_full_range_flag >= 0 ||
  113. ctx->colour_primaries >= 0 ||
  114. ctx->transfer_characteristics >= 0 ||
  115. ctx->matrix_coefficients >= 0) {
  116. SET_OR_INFER(sps->vui.video_format, ctx->video_format,
  117. sps->vui.video_signal_type_present_flag, 5);
  118. SET_OR_INFER(sps->vui.video_full_range_flag,
  119. ctx->video_full_range_flag,
  120. sps->vui.video_signal_type_present_flag, 0);
  121. if (ctx->colour_primaries >= 0 ||
  122. ctx->transfer_characteristics >= 0 ||
  123. ctx->matrix_coefficients >= 0) {
  124. SET_OR_INFER(sps->vui.colour_primaries,
  125. ctx->colour_primaries,
  126. sps->vui.colour_description_present_flag, 2);
  127. SET_OR_INFER(sps->vui.transfer_characteristics,
  128. ctx->transfer_characteristics,
  129. sps->vui.colour_description_present_flag, 2);
  130. SET_OR_INFER(sps->vui.matrix_coefficients,
  131. ctx->matrix_coefficients,
  132. sps->vui.colour_description_present_flag, 2);
  133. sps->vui.colour_description_present_flag = 1;
  134. }
  135. sps->vui.video_signal_type_present_flag = 1;
  136. need_vui = 1;
  137. }
  138. if (ctx->chroma_sample_loc_type >= 0) {
  139. sps->vui.chroma_sample_loc_type_top_field =
  140. ctx->chroma_sample_loc_type;
  141. sps->vui.chroma_sample_loc_type_bottom_field =
  142. ctx->chroma_sample_loc_type;
  143. sps->vui.chroma_loc_info_present_flag = 1;
  144. need_vui = 1;
  145. }
  146. if (ctx->tick_rate.num && ctx->tick_rate.den) {
  147. int num, den;
  148. av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den,
  149. UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX);
  150. sps->vui.vui_time_scale = num;
  151. sps->vui.vui_num_units_in_tick = den;
  152. sps->vui.vui_timing_info_present_flag = 1;
  153. need_vui = 1;
  154. if (ctx->num_ticks_poc_diff_one > 0) {
  155. sps->vui.vui_num_ticks_poc_diff_one_minus1 =
  156. ctx->num_ticks_poc_diff_one - 1;
  157. sps->vui.vui_poc_proportional_to_timing_flag = 1;
  158. } else if (ctx->num_ticks_poc_diff_one == 0) {
  159. sps->vui.vui_poc_proportional_to_timing_flag = 0;
  160. }
  161. }
  162. if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) {
  163. crop_unit_x = 1;
  164. crop_unit_y = 1;
  165. } else {
  166. crop_unit_x = 1 + (sps->chroma_format_idc < 3);
  167. crop_unit_y = 1 + (sps->chroma_format_idc < 2);
  168. }
  169. #define CROP(border, unit) do { \
  170. if (ctx->crop_ ## border >= 0) { \
  171. if (ctx->crop_ ## border % unit != 0) { \
  172. av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \
  173. "must be a multiple of %d.\n", #border, unit); \
  174. return AVERROR(EINVAL); \
  175. } \
  176. sps->conf_win_ ## border ## _offset = \
  177. ctx->crop_ ## border / unit; \
  178. sps->conformance_window_flag = 1; \
  179. } \
  180. } while (0)
  181. CROP(left, crop_unit_x);
  182. CROP(right, crop_unit_x);
  183. CROP(top, crop_unit_y);
  184. CROP(bottom, crop_unit_y);
  185. #undef CROP
  186. if (need_vui)
  187. sps->vui_parameters_present_flag = 1;
  188. return 0;
  189. }
  190. static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out)
  191. {
  192. H265MetadataContext *ctx = bsf->priv_data;
  193. AVPacket *in = NULL;
  194. CodedBitstreamFragment *au = &ctx->access_unit;
  195. int err, i;
  196. err = ff_bsf_get_packet(bsf, &in);
  197. if (err < 0)
  198. goto fail;
  199. err = ff_cbs_read_packet(ctx->cbc, au, in);
  200. if (err < 0) {
  201. av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
  202. goto fail;
  203. }
  204. if (au->nb_units == 0) {
  205. av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n");
  206. err = AVERROR_INVALIDDATA;
  207. goto fail;
  208. }
  209. // If an AUD is present, it must be the first NAL unit.
  210. if (au->units[0].type == HEVC_NAL_AUD) {
  211. if (ctx->aud == REMOVE)
  212. ff_cbs_delete_unit(ctx->cbc, au, 0);
  213. } else {
  214. if (ctx->aud == INSERT) {
  215. H265RawAUD *aud = &ctx->aud_nal;
  216. int pic_type = 0, temporal_id = 8, layer_id = 0;
  217. for (i = 0; i < au->nb_units; i++) {
  218. const H265RawNALUnitHeader *nal = au->units[i].content;
  219. if (!nal)
  220. continue;
  221. if (nal->nuh_temporal_id_plus1 < temporal_id + 1)
  222. temporal_id = nal->nuh_temporal_id_plus1 - 1;
  223. if (au->units[i].type <= HEVC_NAL_RSV_VCL31) {
  224. const H265RawSlice *slice = au->units[i].content;
  225. layer_id = nal->nuh_layer_id;
  226. if (slice->header.slice_type == HEVC_SLICE_B &&
  227. pic_type < 2)
  228. pic_type = 2;
  229. if (slice->header.slice_type == HEVC_SLICE_P &&
  230. pic_type < 1)
  231. pic_type = 1;
  232. }
  233. }
  234. aud->nal_unit_header = (H265RawNALUnitHeader) {
  235. .nal_unit_type = HEVC_NAL_AUD,
  236. .nuh_layer_id = layer_id,
  237. .nuh_temporal_id_plus1 = temporal_id + 1,
  238. };
  239. aud->pic_type = pic_type;
  240. err = ff_cbs_insert_unit_content(ctx->cbc, au,
  241. 0, HEVC_NAL_AUD, aud, NULL);
  242. if (err) {
  243. av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
  244. goto fail;
  245. }
  246. }
  247. }
  248. for (i = 0; i < au->nb_units; i++) {
  249. if (au->units[i].type == HEVC_NAL_VPS) {
  250. err = h265_metadata_update_vps(bsf, au->units[i].content);
  251. if (err < 0)
  252. goto fail;
  253. }
  254. if (au->units[i].type == HEVC_NAL_SPS) {
  255. err = h265_metadata_update_sps(bsf, au->units[i].content);
  256. if (err < 0)
  257. goto fail;
  258. }
  259. }
  260. err = ff_cbs_write_packet(ctx->cbc, out, au);
  261. if (err < 0) {
  262. av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
  263. goto fail;
  264. }
  265. err = av_packet_copy_props(out, in);
  266. if (err < 0)
  267. goto fail;
  268. err = 0;
  269. fail:
  270. ff_cbs_fragment_uninit(ctx->cbc, au);
  271. av_packet_free(&in);
  272. return err;
  273. }
  274. static int h265_metadata_init(AVBSFContext *bsf)
  275. {
  276. H265MetadataContext *ctx = bsf->priv_data;
  277. CodedBitstreamFragment *au = &ctx->access_unit;
  278. int err, i;
  279. err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_HEVC, bsf);
  280. if (err < 0)
  281. return err;
  282. if (bsf->par_in->extradata) {
  283. err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in);
  284. if (err < 0) {
  285. av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
  286. goto fail;
  287. }
  288. for (i = 0; i < au->nb_units; i++) {
  289. if (au->units[i].type == HEVC_NAL_VPS) {
  290. err = h265_metadata_update_vps(bsf, au->units[i].content);
  291. if (err < 0)
  292. goto fail;
  293. }
  294. if (au->units[i].type == HEVC_NAL_SPS) {
  295. err = h265_metadata_update_sps(bsf, au->units[i].content);
  296. if (err < 0)
  297. goto fail;
  298. }
  299. }
  300. err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au);
  301. if (err < 0) {
  302. av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
  303. goto fail;
  304. }
  305. }
  306. err = 0;
  307. fail:
  308. ff_cbs_fragment_uninit(ctx->cbc, au);
  309. return err;
  310. }
  311. static void h265_metadata_close(AVBSFContext *bsf)
  312. {
  313. H265MetadataContext *ctx = bsf->priv_data;
  314. ff_cbs_close(&ctx->cbc);
  315. }
  316. #define OFFSET(x) offsetof(H265MetadataContext, x)
  317. static const AVOption h265_metadata_options[] = {
  318. { "aud", "Access Unit Delimiter NAL units",
  319. OFFSET(aud), AV_OPT_TYPE_INT,
  320. { .i64 = PASS }, PASS, REMOVE, 0, "aud" },
  321. { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" },
  322. { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" },
  323. { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" },
  324. { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)",
  325. OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL,
  326. { .i64 = 0 }, 0, 65535 },
  327. { "video_format", "Set video format (table E-2)",
  328. OFFSET(video_format), AV_OPT_TYPE_INT,
  329. { .i64 = -1 }, -1, 7 },
  330. { "video_full_range_flag", "Set video full range flag",
  331. OFFSET(video_full_range_flag), AV_OPT_TYPE_INT,
  332. { .i64 = -1 }, -1, 1 },
  333. { "colour_primaries", "Set colour primaries (table E-3)",
  334. OFFSET(colour_primaries), AV_OPT_TYPE_INT,
  335. { .i64 = -1 }, -1, 255 },
  336. { "transfer_characteristics", "Set transfer characteristics (table E-4)",
  337. OFFSET(transfer_characteristics), AV_OPT_TYPE_INT,
  338. { .i64 = -1 }, -1, 255 },
  339. { "matrix_coefficients", "Set matrix coefficients (table E-5)",
  340. OFFSET(matrix_coefficients), AV_OPT_TYPE_INT,
  341. { .i64 = -1 }, -1, 255 },
  342. { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)",
  343. OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT,
  344. { .i64 = -1 }, -1, 6 },
  345. { "tick_rate",
  346. "Set VPS and VUI tick rate (num_units_in_tick / time_scale)",
  347. OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL,
  348. { .i64 = 0 }, 0, UINT_MAX },
  349. { "num_ticks_poc_diff_one",
  350. "Set VPS and VUI number of ticks per POC increment",
  351. OFFSET(num_ticks_poc_diff_one), AV_OPT_TYPE_INT,
  352. { .i64 = -1 }, -1, INT_MAX },
  353. { "crop_left", "Set left border crop offset",
  354. OFFSET(crop_left), AV_OPT_TYPE_INT,
  355. { .i64 = -1 }, -1, HEVC_MAX_WIDTH },
  356. { "crop_right", "Set right border crop offset",
  357. OFFSET(crop_right), AV_OPT_TYPE_INT,
  358. { .i64 = -1 }, -1, HEVC_MAX_WIDTH },
  359. { "crop_top", "Set top border crop offset",
  360. OFFSET(crop_top), AV_OPT_TYPE_INT,
  361. { .i64 = -1 }, -1, HEVC_MAX_HEIGHT },
  362. { "crop_bottom", "Set bottom border crop offset",
  363. OFFSET(crop_bottom), AV_OPT_TYPE_INT,
  364. { .i64 = -1 }, -1, HEVC_MAX_HEIGHT },
  365. { NULL }
  366. };
  367. static const AVClass h265_metadata_class = {
  368. .class_name = "h265_metadata_bsf",
  369. .item_name = av_default_item_name,
  370. .option = h265_metadata_options,
  371. .version = LIBAVCODEC_VERSION_MAJOR,
  372. };
  373. static const enum AVCodecID h265_metadata_codec_ids[] = {
  374. AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE,
  375. };
  376. const AVBitStreamFilter ff_hevc_metadata_bsf = {
  377. .name = "hevc_metadata",
  378. .priv_data_size = sizeof(H265MetadataContext),
  379. .priv_class = &h265_metadata_class,
  380. .init = &h265_metadata_init,
  381. .close = &h265_metadata_close,
  382. .filter = &h265_metadata_filter,
  383. .codec_ids = h265_metadata_codec_ids,
  384. };