1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "libavutil/common.h" 20cabdff1aSopenharmony_ci#include "libavutil/opt.h" 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "bsf.h" 23cabdff1aSopenharmony_ci#include "bsf_internal.h" 24cabdff1aSopenharmony_ci#include "cbs.h" 25cabdff1aSopenharmony_ci#include "cbs_bsf.h" 26cabdff1aSopenharmony_ci#include "cbs_mpeg2.h" 27cabdff1aSopenharmony_ci#include "mpeg12.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_citypedef struct MPEG2MetadataContext { 30cabdff1aSopenharmony_ci CBSBSFContext common; 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci MPEG2RawExtensionData sequence_display_extension; 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci AVRational display_aspect_ratio; 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci AVRational frame_rate; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci int video_format; 39cabdff1aSopenharmony_ci int colour_primaries; 40cabdff1aSopenharmony_ci int transfer_characteristics; 41cabdff1aSopenharmony_ci int matrix_coefficients; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci int mpeg1_warned; 44cabdff1aSopenharmony_ci} MPEG2MetadataContext; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_cistatic int mpeg2_metadata_update_fragment(AVBSFContext *bsf, 48cabdff1aSopenharmony_ci AVPacket *pkt, 49cabdff1aSopenharmony_ci CodedBitstreamFragment *frag) 50cabdff1aSopenharmony_ci{ 51cabdff1aSopenharmony_ci MPEG2MetadataContext *ctx = bsf->priv_data; 52cabdff1aSopenharmony_ci MPEG2RawSequenceHeader *sh = NULL; 53cabdff1aSopenharmony_ci MPEG2RawSequenceExtension *se = NULL; 54cabdff1aSopenharmony_ci MPEG2RawSequenceDisplayExtension *sde = NULL; 55cabdff1aSopenharmony_ci int i, se_pos; 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci for (i = 0; i < frag->nb_units; i++) { 58cabdff1aSopenharmony_ci if (frag->units[i].type == MPEG2_START_SEQUENCE_HEADER) { 59cabdff1aSopenharmony_ci sh = frag->units[i].content; 60cabdff1aSopenharmony_ci } else if (frag->units[i].type == MPEG2_START_EXTENSION) { 61cabdff1aSopenharmony_ci MPEG2RawExtensionData *ext = frag->units[i].content; 62cabdff1aSopenharmony_ci if (ext->extension_start_code_identifier == 63cabdff1aSopenharmony_ci MPEG2_EXTENSION_SEQUENCE) { 64cabdff1aSopenharmony_ci se = &ext->data.sequence; 65cabdff1aSopenharmony_ci se_pos = i; 66cabdff1aSopenharmony_ci } else if (ext->extension_start_code_identifier == 67cabdff1aSopenharmony_ci MPEG2_EXTENSION_SEQUENCE_DISPLAY) { 68cabdff1aSopenharmony_ci sde = &ext->data.sequence_display; 69cabdff1aSopenharmony_ci } 70cabdff1aSopenharmony_ci } 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci if (!sh || !se) { 74cabdff1aSopenharmony_ci // No sequence header and sequence extension: not an MPEG-2 video 75cabdff1aSopenharmony_ci // sequence. 76cabdff1aSopenharmony_ci if (sh && !ctx->mpeg1_warned) { 77cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_WARNING, "Stream contains a sequence " 78cabdff1aSopenharmony_ci "header but not a sequence extension: maybe it's " 79cabdff1aSopenharmony_ci "actually MPEG-1?\n"); 80cabdff1aSopenharmony_ci ctx->mpeg1_warned = 1; 81cabdff1aSopenharmony_ci } 82cabdff1aSopenharmony_ci return 0; 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci if (ctx->display_aspect_ratio.num && ctx->display_aspect_ratio.den) { 86cabdff1aSopenharmony_ci int num, den; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci av_reduce(&num, &den, ctx->display_aspect_ratio.num, 89cabdff1aSopenharmony_ci ctx->display_aspect_ratio.den, 65535); 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci if (num == 4 && den == 3) 92cabdff1aSopenharmony_ci sh->aspect_ratio_information = 2; 93cabdff1aSopenharmony_ci else if (num == 16 && den == 9) 94cabdff1aSopenharmony_ci sh->aspect_ratio_information = 3; 95cabdff1aSopenharmony_ci else if (num == 221 && den == 100) 96cabdff1aSopenharmony_ci sh->aspect_ratio_information = 4; 97cabdff1aSopenharmony_ci else 98cabdff1aSopenharmony_ci sh->aspect_ratio_information = 1; 99cabdff1aSopenharmony_ci } 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci if (ctx->frame_rate.num && ctx->frame_rate.den) { 102cabdff1aSopenharmony_ci int code, ext_n, ext_d; 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci ff_mpeg12_find_best_frame_rate(ctx->frame_rate, 105cabdff1aSopenharmony_ci &code, &ext_n, &ext_d, 0); 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci sh->frame_rate_code = code; 108cabdff1aSopenharmony_ci se->frame_rate_extension_n = ext_n; 109cabdff1aSopenharmony_ci se->frame_rate_extension_d = ext_d; 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci if (ctx->video_format >= 0 || 113cabdff1aSopenharmony_ci ctx->colour_primaries >= 0 || 114cabdff1aSopenharmony_ci ctx->transfer_characteristics >= 0 || 115cabdff1aSopenharmony_ci ctx->matrix_coefficients >= 0) { 116cabdff1aSopenharmony_ci if (!sde) { 117cabdff1aSopenharmony_ci int err; 118cabdff1aSopenharmony_ci ctx->sequence_display_extension.extension_start_code = 119cabdff1aSopenharmony_ci MPEG2_START_EXTENSION; 120cabdff1aSopenharmony_ci ctx->sequence_display_extension.extension_start_code_identifier = 121cabdff1aSopenharmony_ci MPEG2_EXTENSION_SEQUENCE_DISPLAY; 122cabdff1aSopenharmony_ci sde = &ctx->sequence_display_extension.data.sequence_display; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci *sde = (MPEG2RawSequenceDisplayExtension) { 125cabdff1aSopenharmony_ci .video_format = 5, 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci .colour_description = 0, 128cabdff1aSopenharmony_ci .colour_primaries = 2, 129cabdff1aSopenharmony_ci .transfer_characteristics = 2, 130cabdff1aSopenharmony_ci .matrix_coefficients = 2, 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci .display_horizontal_size = 133cabdff1aSopenharmony_ci se->horizontal_size_extension << 12 | sh->horizontal_size_value, 134cabdff1aSopenharmony_ci .display_vertical_size = 135cabdff1aSopenharmony_ci se->vertical_size_extension << 12 | sh->vertical_size_value, 136cabdff1aSopenharmony_ci }; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci err = ff_cbs_insert_unit_content(frag, se_pos + 1, 139cabdff1aSopenharmony_ci MPEG2_START_EXTENSION, 140cabdff1aSopenharmony_ci &ctx->sequence_display_extension, 141cabdff1aSopenharmony_ci NULL); 142cabdff1aSopenharmony_ci if (err < 0) { 143cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence " 144cabdff1aSopenharmony_ci "display extension.\n"); 145cabdff1aSopenharmony_ci return err; 146cabdff1aSopenharmony_ci } 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci if (ctx->video_format >= 0) 150cabdff1aSopenharmony_ci sde->video_format = ctx->video_format; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci if (ctx->colour_primaries >= 0 || 153cabdff1aSopenharmony_ci ctx->transfer_characteristics >= 0 || 154cabdff1aSopenharmony_ci ctx->matrix_coefficients >= 0) { 155cabdff1aSopenharmony_ci sde->colour_description = 1; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci if (ctx->colour_primaries >= 0) 158cabdff1aSopenharmony_ci sde->colour_primaries = ctx->colour_primaries; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci if (ctx->transfer_characteristics >= 0) 161cabdff1aSopenharmony_ci sde->transfer_characteristics = ctx->transfer_characteristics; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci if (ctx->matrix_coefficients >= 0) 164cabdff1aSopenharmony_ci sde->matrix_coefficients = ctx->matrix_coefficients; 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci return 0; 169cabdff1aSopenharmony_ci} 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_cistatic const CBSBSFType mpeg2_metadata_type = { 172cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_MPEG2VIDEO, 173cabdff1aSopenharmony_ci .fragment_name = "frame", 174cabdff1aSopenharmony_ci .unit_name = "start code", 175cabdff1aSopenharmony_ci .update_fragment = &mpeg2_metadata_update_fragment, 176cabdff1aSopenharmony_ci}; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_cistatic int mpeg2_metadata_init(AVBSFContext *bsf) 179cabdff1aSopenharmony_ci{ 180cabdff1aSopenharmony_ci MPEG2MetadataContext *ctx = bsf->priv_data; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci#define VALIDITY_CHECK(name) do { \ 183cabdff1aSopenharmony_ci if (!ctx->name) { \ 184cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_ERROR, "The value 0 for %s is " \ 185cabdff1aSopenharmony_ci "forbidden.\n", #name); \ 186cabdff1aSopenharmony_ci return AVERROR(EINVAL); \ 187cabdff1aSopenharmony_ci } \ 188cabdff1aSopenharmony_ci } while (0) 189cabdff1aSopenharmony_ci VALIDITY_CHECK(colour_primaries); 190cabdff1aSopenharmony_ci VALIDITY_CHECK(transfer_characteristics); 191cabdff1aSopenharmony_ci VALIDITY_CHECK(matrix_coefficients); 192cabdff1aSopenharmony_ci#undef VALIDITY_CHECK 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci return ff_cbs_bsf_generic_init(bsf, &mpeg2_metadata_type); 195cabdff1aSopenharmony_ci} 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(MPEG2MetadataContext, x) 198cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) 199cabdff1aSopenharmony_cistatic const AVOption mpeg2_metadata_options[] = { 200cabdff1aSopenharmony_ci { "display_aspect_ratio", "Set display aspect ratio (table 6-3)", 201cabdff1aSopenharmony_ci OFFSET(display_aspect_ratio), AV_OPT_TYPE_RATIONAL, 202cabdff1aSopenharmony_ci { .dbl = 0.0 }, 0, 65535, FLAGS }, 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci { "frame_rate", "Set frame rate", 205cabdff1aSopenharmony_ci OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, 206cabdff1aSopenharmony_ci { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci { "video_format", "Set video format (table 6-6)", 209cabdff1aSopenharmony_ci OFFSET(video_format), AV_OPT_TYPE_INT, 210cabdff1aSopenharmony_ci { .i64 = -1 }, -1, 7, FLAGS }, 211cabdff1aSopenharmony_ci { "colour_primaries", "Set colour primaries (table 6-7)", 212cabdff1aSopenharmony_ci OFFSET(colour_primaries), AV_OPT_TYPE_INT, 213cabdff1aSopenharmony_ci { .i64 = -1 }, -1, 255, FLAGS }, 214cabdff1aSopenharmony_ci { "transfer_characteristics", "Set transfer characteristics (table 6-8)", 215cabdff1aSopenharmony_ci OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, 216cabdff1aSopenharmony_ci { .i64 = -1 }, -1, 255, FLAGS }, 217cabdff1aSopenharmony_ci { "matrix_coefficients", "Set matrix coefficients (table 6-9)", 218cabdff1aSopenharmony_ci OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, 219cabdff1aSopenharmony_ci { .i64 = -1 }, -1, 255, FLAGS }, 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci { NULL } 222cabdff1aSopenharmony_ci}; 223cabdff1aSopenharmony_ci 224cabdff1aSopenharmony_cistatic const AVClass mpeg2_metadata_class = { 225cabdff1aSopenharmony_ci .class_name = "mpeg2_metadata_bsf", 226cabdff1aSopenharmony_ci .item_name = av_default_item_name, 227cabdff1aSopenharmony_ci .option = mpeg2_metadata_options, 228cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 229cabdff1aSopenharmony_ci}; 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_cistatic const enum AVCodecID mpeg2_metadata_codec_ids[] = { 232cabdff1aSopenharmony_ci AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, 233cabdff1aSopenharmony_ci}; 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_mpeg2_metadata_bsf = { 236cabdff1aSopenharmony_ci .p.name = "mpeg2_metadata", 237cabdff1aSopenharmony_ci .p.codec_ids = mpeg2_metadata_codec_ids, 238cabdff1aSopenharmony_ci .p.priv_class = &mpeg2_metadata_class, 239cabdff1aSopenharmony_ci .priv_data_size = sizeof(MPEG2MetadataContext), 240cabdff1aSopenharmony_ci .init = &mpeg2_metadata_init, 241cabdff1aSopenharmony_ci .close = &ff_cbs_bsf_generic_close, 242cabdff1aSopenharmony_ci .filter = &ff_cbs_bsf_generic_filter, 243cabdff1aSopenharmony_ci}; 244