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.

314 lines
9.7KB

  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/avstring.h"
  19. #include "libavutil/common.h"
  20. #include "libavutil/opt.h"
  21. #include "bsf.h"
  22. #include "cbs.h"
  23. #include "cbs_mpeg2.h"
  24. #include "mpeg12.h"
  25. typedef struct MPEG2MetadataContext {
  26. const AVClass *class;
  27. CodedBitstreamContext *cbc;
  28. CodedBitstreamFragment fragment;
  29. MPEG2RawExtensionData sequence_display_extension;
  30. AVRational display_aspect_ratio;
  31. AVRational frame_rate;
  32. int video_format;
  33. int colour_primaries;
  34. int transfer_characteristics;
  35. int matrix_coefficients;
  36. int mpeg1_warned;
  37. } MPEG2MetadataContext;
  38. static int mpeg2_metadata_update_fragment(AVBSFContext *bsf,
  39. CodedBitstreamFragment *frag)
  40. {
  41. MPEG2MetadataContext *ctx = bsf->priv_data;
  42. MPEG2RawSequenceHeader *sh = NULL;
  43. MPEG2RawSequenceExtension *se = NULL;
  44. MPEG2RawSequenceDisplayExtension *sde = NULL;
  45. int i, se_pos, add_sde = 0;
  46. for (i = 0; i < frag->nb_units; i++) {
  47. if (frag->units[i].type == MPEG2_START_SEQUENCE_HEADER) {
  48. sh = frag->units[i].content;
  49. } else if (frag->units[i].type == MPEG2_START_EXTENSION) {
  50. MPEG2RawExtensionData *ext = frag->units[i].content;
  51. if (ext->extension_start_code_identifier ==
  52. MPEG2_EXTENSION_SEQUENCE) {
  53. se = &ext->data.sequence;
  54. se_pos = i;
  55. } else if (ext->extension_start_code_identifier ==
  56. MPEG2_EXTENSION_SEQUENCE_DISPLAY) {
  57. sde = &ext->data.sequence_display;
  58. }
  59. }
  60. }
  61. if (!sh || !se) {
  62. // No sequence header and sequence extension: not an MPEG-2 video
  63. // sequence.
  64. if (sh && !ctx->mpeg1_warned) {
  65. av_log(bsf, AV_LOG_WARNING, "Stream contains a sequence "
  66. "header but not a sequence extension: maybe it's "
  67. "actually MPEG-1?\n");
  68. ctx->mpeg1_warned = 1;
  69. }
  70. return 0;
  71. }
  72. if (ctx->display_aspect_ratio.num && ctx->display_aspect_ratio.den) {
  73. int num, den;
  74. av_reduce(&num, &den, ctx->display_aspect_ratio.num,
  75. ctx->display_aspect_ratio.den, 65535);
  76. if (num == 4 && den == 3)
  77. sh->aspect_ratio_information = 2;
  78. else if (num == 16 && den == 9)
  79. sh->aspect_ratio_information = 3;
  80. else if (num == 221 && den == 100)
  81. sh->aspect_ratio_information = 4;
  82. else
  83. sh->aspect_ratio_information = 1;
  84. }
  85. if (ctx->frame_rate.num && ctx->frame_rate.den) {
  86. int code, ext_n, ext_d;
  87. ff_mpeg12_find_best_frame_rate(ctx->frame_rate,
  88. &code, &ext_n, &ext_d, 0);
  89. sh->frame_rate_code = code;
  90. se->frame_rate_extension_n = ext_n;
  91. se->frame_rate_extension_d = ext_d;
  92. }
  93. if (ctx->video_format >= 0 ||
  94. ctx->colour_primaries >= 0 ||
  95. ctx->transfer_characteristics >= 0 ||
  96. ctx->matrix_coefficients >= 0) {
  97. if (!sde) {
  98. add_sde = 1;
  99. ctx->sequence_display_extension.extension_start_code =
  100. MPEG2_START_EXTENSION;
  101. ctx->sequence_display_extension.extension_start_code_identifier =
  102. MPEG2_EXTENSION_SEQUENCE_DISPLAY;
  103. sde = &ctx->sequence_display_extension.data.sequence_display;
  104. *sde = (MPEG2RawSequenceDisplayExtension) {
  105. .video_format = 5,
  106. .colour_description = 0,
  107. .colour_primaries = 2,
  108. .transfer_characteristics = 2,
  109. .matrix_coefficients = 2,
  110. .display_horizontal_size =
  111. se->horizontal_size_extension << 12 | sh->horizontal_size_value,
  112. .display_vertical_size =
  113. se->vertical_size_extension << 12 | sh->vertical_size_value,
  114. };
  115. }
  116. if (ctx->video_format >= 0)
  117. sde->video_format = ctx->video_format;
  118. if (ctx->colour_primaries >= 0 ||
  119. ctx->transfer_characteristics >= 0 ||
  120. ctx->matrix_coefficients >= 0) {
  121. sde->colour_description = 1;
  122. if (ctx->colour_primaries >= 0)
  123. sde->colour_primaries = ctx->colour_primaries;
  124. else if (add_sde)
  125. sde->colour_primaries = 2;
  126. if (ctx->transfer_characteristics >= 0)
  127. sde->transfer_characteristics = ctx->transfer_characteristics;
  128. else if (add_sde)
  129. sde->transfer_characteristics = 2;
  130. if (ctx->matrix_coefficients >= 0)
  131. sde->matrix_coefficients = ctx->matrix_coefficients;
  132. else if (add_sde)
  133. sde->matrix_coefficients = 2;
  134. }
  135. }
  136. if (add_sde) {
  137. int err;
  138. err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1,
  139. MPEG2_START_EXTENSION,
  140. &ctx->sequence_display_extension,
  141. NULL);
  142. if (err < 0) {
  143. av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence "
  144. "display extension.\n");
  145. return err;
  146. }
  147. }
  148. return 0;
  149. }
  150. static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out)
  151. {
  152. MPEG2MetadataContext *ctx = bsf->priv_data;
  153. AVPacket *in = NULL;
  154. CodedBitstreamFragment *frag = &ctx->fragment;
  155. int err;
  156. err = ff_bsf_get_packet(bsf, &in);
  157. if (err < 0)
  158. goto fail;
  159. err = ff_cbs_read_packet(ctx->cbc, frag, in);
  160. if (err < 0) {
  161. av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
  162. goto fail;
  163. }
  164. err = mpeg2_metadata_update_fragment(bsf, frag);
  165. if (err < 0) {
  166. av_log(bsf, AV_LOG_ERROR, "Failed to update frame fragment.\n");
  167. goto fail;
  168. }
  169. err = ff_cbs_write_packet(ctx->cbc, out, frag);
  170. if (err < 0) {
  171. av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
  172. goto fail;
  173. }
  174. err = av_packet_copy_props(out, in);
  175. if (err < 0) {
  176. av_packet_unref(out);
  177. goto fail;
  178. }
  179. err = 0;
  180. fail:
  181. ff_cbs_fragment_uninit(ctx->cbc, frag);
  182. av_packet_free(&in);
  183. return err;
  184. }
  185. static int mpeg2_metadata_init(AVBSFContext *bsf)
  186. {
  187. MPEG2MetadataContext *ctx = bsf->priv_data;
  188. CodedBitstreamFragment *frag = &ctx->fragment;
  189. int err;
  190. err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_MPEG2VIDEO, bsf);
  191. if (err < 0)
  192. return err;
  193. if (bsf->par_in->extradata) {
  194. err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in);
  195. if (err < 0) {
  196. av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
  197. goto fail;
  198. }
  199. err = mpeg2_metadata_update_fragment(bsf, frag);
  200. if (err < 0) {
  201. av_log(bsf, AV_LOG_ERROR, "Failed to update metadata fragment.\n");
  202. goto fail;
  203. }
  204. err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag);
  205. if (err < 0) {
  206. av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
  207. goto fail;
  208. }
  209. }
  210. err = 0;
  211. fail:
  212. ff_cbs_fragment_uninit(ctx->cbc, frag);
  213. return err;
  214. }
  215. static void mpeg2_metadata_close(AVBSFContext *bsf)
  216. {
  217. MPEG2MetadataContext *ctx = bsf->priv_data;
  218. ff_cbs_close(&ctx->cbc);
  219. }
  220. #define OFFSET(x) offsetof(MPEG2MetadataContext, x)
  221. static const AVOption mpeg2_metadata_options[] = {
  222. { "display_aspect_ratio", "Set display aspect ratio (table 6-3)",
  223. OFFSET(display_aspect_ratio), AV_OPT_TYPE_RATIONAL,
  224. { .i64 = 0 }, 0, 65535 },
  225. { "frame_rate", "Set frame rate",
  226. OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL,
  227. { .i64 = 0 }, 0, UINT_MAX },
  228. { "video_format", "Set video format (table 6-6)",
  229. OFFSET(video_format), AV_OPT_TYPE_INT,
  230. { .i64 = -1 }, -1, 7 },
  231. { "colour_primaries", "Set colour primaries (table 6-7)",
  232. OFFSET(colour_primaries), AV_OPT_TYPE_INT,
  233. { .i64 = -1 }, -1, 255 },
  234. { "transfer_characteristics", "Set transfer characteristics (table 6-8)",
  235. OFFSET(transfer_characteristics), AV_OPT_TYPE_INT,
  236. { .i64 = -1 }, -1, 255 },
  237. { "matrix_coefficients", "Set matrix coefficients (table 6-9)",
  238. OFFSET(matrix_coefficients), AV_OPT_TYPE_INT,
  239. { .i64 = -1 }, -1, 255 },
  240. { NULL }
  241. };
  242. static const AVClass mpeg2_metadata_class = {
  243. .class_name = "mpeg2_metadata_bsf",
  244. .item_name = av_default_item_name,
  245. .option = mpeg2_metadata_options,
  246. .version = LIBAVCODEC_VERSION_MAJOR,
  247. };
  248. static const enum AVCodecID mpeg2_metadata_codec_ids[] = {
  249. AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE,
  250. };
  251. const AVBitStreamFilter ff_mpeg2_metadata_bsf = {
  252. .name = "mpeg2_metadata",
  253. .priv_data_size = sizeof(MPEG2MetadataContext),
  254. .priv_class = &mpeg2_metadata_class,
  255. .init = &mpeg2_metadata_init,
  256. .close = &mpeg2_metadata_close,
  257. .filter = &mpeg2_metadata_filter,
  258. .codec_ids = mpeg2_metadata_codec_ids,
  259. };