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.

313 lines
9.9KB

  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg 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. * FFmpeg 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 FFmpeg; 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;
  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. int err;
  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. err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1,
  116. MPEG2_START_EXTENSION,
  117. &ctx->sequence_display_extension,
  118. NULL);
  119. if (err < 0) {
  120. av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence "
  121. "display extension.\n");
  122. return err;
  123. }
  124. }
  125. if (ctx->video_format >= 0)
  126. sde->video_format = ctx->video_format;
  127. if (ctx->colour_primaries >= 0 ||
  128. ctx->transfer_characteristics >= 0 ||
  129. ctx->matrix_coefficients >= 0) {
  130. sde->colour_description = 1;
  131. if (ctx->colour_primaries >= 0)
  132. sde->colour_primaries = ctx->colour_primaries;
  133. if (ctx->transfer_characteristics >= 0)
  134. sde->transfer_characteristics = ctx->transfer_characteristics;
  135. if (ctx->matrix_coefficients >= 0)
  136. sde->matrix_coefficients = ctx->matrix_coefficients;
  137. }
  138. }
  139. return 0;
  140. }
  141. static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
  142. {
  143. MPEG2MetadataContext *ctx = bsf->priv_data;
  144. CodedBitstreamFragment *frag = &ctx->fragment;
  145. int err;
  146. err = ff_bsf_get_packet_ref(bsf, pkt);
  147. if (err < 0)
  148. return err;
  149. err = ff_cbs_read_packet(ctx->cbc, frag, pkt);
  150. if (err < 0) {
  151. av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
  152. goto fail;
  153. }
  154. err = mpeg2_metadata_update_fragment(bsf, frag);
  155. if (err < 0) {
  156. av_log(bsf, AV_LOG_ERROR, "Failed to update frame fragment.\n");
  157. goto fail;
  158. }
  159. err = ff_cbs_write_packet(ctx->cbc, pkt, frag);
  160. if (err < 0) {
  161. av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
  162. goto fail;
  163. }
  164. err = 0;
  165. fail:
  166. ff_cbs_fragment_reset(ctx->cbc, frag);
  167. if (err < 0)
  168. av_packet_unref(pkt);
  169. return err;
  170. }
  171. static int mpeg2_metadata_init(AVBSFContext *bsf)
  172. {
  173. MPEG2MetadataContext *ctx = bsf->priv_data;
  174. CodedBitstreamFragment *frag = &ctx->fragment;
  175. int err;
  176. #define VALIDITY_CHECK(name) do { \
  177. if (!ctx->name) { \
  178. av_log(bsf, AV_LOG_ERROR, "The value 0 for %s is " \
  179. "forbidden.\n", #name); \
  180. return AVERROR(EINVAL); \
  181. } \
  182. } while (0)
  183. VALIDITY_CHECK(colour_primaries);
  184. VALIDITY_CHECK(transfer_characteristics);
  185. VALIDITY_CHECK(matrix_coefficients);
  186. #undef VALIDITY_CHECK
  187. err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_MPEG2VIDEO, bsf);
  188. if (err < 0)
  189. return err;
  190. if (bsf->par_in->extradata) {
  191. err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in);
  192. if (err < 0) {
  193. av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
  194. goto fail;
  195. }
  196. err = mpeg2_metadata_update_fragment(bsf, frag);
  197. if (err < 0) {
  198. av_log(bsf, AV_LOG_ERROR, "Failed to update metadata fragment.\n");
  199. goto fail;
  200. }
  201. err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag);
  202. if (err < 0) {
  203. av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
  204. goto fail;
  205. }
  206. }
  207. err = 0;
  208. fail:
  209. ff_cbs_fragment_reset(ctx->cbc, frag);
  210. return err;
  211. }
  212. static void mpeg2_metadata_close(AVBSFContext *bsf)
  213. {
  214. MPEG2MetadataContext *ctx = bsf->priv_data;
  215. ff_cbs_fragment_free(ctx->cbc, &ctx->fragment);
  216. ff_cbs_close(&ctx->cbc);
  217. }
  218. #define OFFSET(x) offsetof(MPEG2MetadataContext, x)
  219. #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
  220. static const AVOption mpeg2_metadata_options[] = {
  221. { "display_aspect_ratio", "Set display aspect ratio (table 6-3)",
  222. OFFSET(display_aspect_ratio), AV_OPT_TYPE_RATIONAL,
  223. { .dbl = 0.0 }, 0, 65535, FLAGS },
  224. { "frame_rate", "Set frame rate",
  225. OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL,
  226. { .dbl = 0.0 }, 0, UINT_MAX, FLAGS },
  227. { "video_format", "Set video format (table 6-6)",
  228. OFFSET(video_format), AV_OPT_TYPE_INT,
  229. { .i64 = -1 }, -1, 7, FLAGS },
  230. { "colour_primaries", "Set colour primaries (table 6-7)",
  231. OFFSET(colour_primaries), AV_OPT_TYPE_INT,
  232. { .i64 = -1 }, -1, 255, FLAGS },
  233. { "transfer_characteristics", "Set transfer characteristics (table 6-8)",
  234. OFFSET(transfer_characteristics), AV_OPT_TYPE_INT,
  235. { .i64 = -1 }, -1, 255, FLAGS },
  236. { "matrix_coefficients", "Set matrix coefficients (table 6-9)",
  237. OFFSET(matrix_coefficients), AV_OPT_TYPE_INT,
  238. { .i64 = -1 }, -1, 255, FLAGS },
  239. { NULL }
  240. };
  241. static const AVClass mpeg2_metadata_class = {
  242. .class_name = "mpeg2_metadata_bsf",
  243. .item_name = av_default_item_name,
  244. .option = mpeg2_metadata_options,
  245. .version = LIBAVUTIL_VERSION_INT,
  246. };
  247. static const enum AVCodecID mpeg2_metadata_codec_ids[] = {
  248. AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE,
  249. };
  250. const AVBitStreamFilter ff_mpeg2_metadata_bsf = {
  251. .name = "mpeg2_metadata",
  252. .priv_data_size = sizeof(MPEG2MetadataContext),
  253. .priv_class = &mpeg2_metadata_class,
  254. .init = &mpeg2_metadata_init,
  255. .close = &mpeg2_metadata_close,
  256. .filter = &mpeg2_metadata_filter,
  257. .codec_ids = mpeg2_metadata_codec_ids,
  258. };