From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 2DA8F49E07 for ; Tue, 12 Mar 2024 06:00:21 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8261268C4C4; Tue, 12 Mar 2024 08:00:18 +0200 (EET) Received: from mail-yb1-f226.google.com (mail-yb1-f226.google.com [209.85.219.226]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4A28168C1D5 for ; Tue, 12 Mar 2024 08:00:12 +0200 (EET) Received: by mail-yb1-f226.google.com with SMTP id 3f1490d57ef6-db4364ecd6aso3720320276.2 for ; Mon, 11 Mar 2024 23:00:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proxyid.net; s=google; t=1710223210; x=1710828010; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CCopq5K7S7TwEPcAnaExZE6aKMKrKNm8QpSlXL5waSk=; b=N1Hma7qKwpxdx2rPPZ0qNAmJx3Hp0Q63CJtHGTM/DzWk7uctGs2SqTq2oTt6Mm6O9F ePxx/73Uk5Z8GgCFldcLsXmKxOV7/jIYrWevuv/LiIbVCTfEcWFU/PjWLQIR5/u2v+fF +Vmp+9p5GV2EF3N1MF4BzGLUoy/ZEagXthYjCfBI9eLZn7QMbJ348BSCi/nOeBwYShqF nIdiemDCV0P6P3gfu7zQrpjEJU96GyCUxEU7FEcFz/0/95m0+9S2I8yZ/X6l2zW0jYee +5A/R5enQImXT8+CRTpJF2HJseRc9vIo2uWOjaaUMbzvWlnEyAKweIIbq6aEvf/vbQKX KSRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710223210; x=1710828010; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CCopq5K7S7TwEPcAnaExZE6aKMKrKNm8QpSlXL5waSk=; b=PSDbnpH4pgbIJQAk5l9JcB8uq8+hwZddIRYErzjTXRkvVW32RDptMHV5ADyphrptC5 f0N86os50imSE+BRCajjLv0KRo7Msrj7QBFmgXlNqntWQv0heySMdWEv8BGXppNZ2IgC MDss5zHC26EnjwzzCG2ubyOZuOhtFVFApwfTTwoJMpG2/8t5V4LDbgTdR9XJfKEb0rwM aO4zCdRK5esSV7Vt13jHnSaqkCpNoQkgUScaskuzToHwTR7lsWzy6ARpFByf0uvraM7h Hf92HY6FQylX1fTtKWWDv07HaJTERT+RQaNetTY0/FkndfF7HXoIGb9nlGUkP5sJQZji SRqA== X-Gm-Message-State: AOJu0Yw+goI5LXgf909tFtFapdEK8auqIIV3WBFVdTpk9r9GqW/SNCAC iol26Ngelfc7DBldZIvxNxjUV267LhQplM4vMkrCrUfd3sxZOvrkz0twJUqama2IIJlC0UJGnAC IyHOoKmC1lY/c+6UEh/zkL73xYFivnpcDB2sSH4SW X-Google-Smtp-Source: AGHT+IHukKSBM+d/ajrDV3lrb5Rv/B5EpNsLSVZiOCId0+X4MJIMDN6dkxUTD2e3rKa14VudgZhoTq1Ug2mC X-Received: by 2002:a5b:c8a:0:b0:dc7:43fe:e124 with SMTP id i10-20020a5b0c8a000000b00dc743fee124mr5586256ybq.11.1710223210385; Mon, 11 Mar 2024 23:00:10 -0700 (PDT) Received: from wsx-cc1-001.. (c-76-141-249-38.hsd1.il.comcast.net. [76.141.249.38]) by smtp-relay.gmail.com with ESMTPS id ds4-20020a056902248400b00dc6185d4494sm322329ybb.6.2024.03.11.23.00.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Mar 2024 23:00:10 -0700 (PDT) X-Relaying-Domain: proxyid.net From: Marth64 To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Mar 2024 01:00:00 -0500 Message-Id: <20240312060005.2111135-2-marth64@proxyid.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240312060005.2111135-1-marth64@proxyid.net> References: <20240312060005.2111135-1-marth64@proxyid.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Marth64 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: In MPEG-2 user data, there can be different types of Closed Captions formats embedded (A53, SCTE-20, or DVD). The current behavior of the CC extraction code in the MPEG-2 decoder is to not be aware of multiple formats if multiple exist, therefore allowing one format to overwrite the other during the extraction process since the CC extraction shares one output buffer for the normalized bytes. This causes sources that have two CC formats to produce flawed output. There exist real-world samples which contain both A53 and SCTE-20 captions in the same MPEG-2 stream, and that manifest this problem. Example of symptom: THANK YOU (expected) --> THTHANANK K YOYOUU (actual) The solution is to pick only the first CC substream observed with valid bytes, and ignore the other types. Additionally, provide an option for users to manually "force" a type in the event that this matters for a particular source. Signed-off-by: Marth64 --- libavcodec/mpeg12dec.c | 67 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 3a2f17e508..8961a290a3 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -62,6 +62,16 @@ #define A53_MAX_CC_COUNT 2000 +enum Mpeg2ClosedCaptionsFormat { + CC_FORMAT_AUTO, + CC_FORMAT_A53_PART4, + CC_FORMAT_SCTE20, + CC_FORMAT_DVD +}; +static const char mpeg2_cc_format_labels[4][12] = { + "Unknown", "A/53 Part 4", "SCTE-20", "DVD" +}; + typedef struct Mpeg1Context { MpegEncContext mpeg_enc_ctx; int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ @@ -70,6 +80,7 @@ typedef struct Mpeg1Context { AVStereo3D stereo3d; int has_stereo3d; AVBufferRef *a53_buf_ref; + enum Mpeg2ClosedCaptionsFormat cc_format; uint8_t afd; int has_afd; int slice_count; @@ -1903,12 +1914,27 @@ static int vcr2_init_sequence(AVCodecContext *avctx) return 0; } +static void mpeg_set_cc_format(AVCodecContext *avctx, enum Mpeg2ClosedCaptionsFormat format) +{ + Mpeg1Context *s1 = avctx->priv_data; + + av_assert2(format != CC_FORMAT_AUTO); + + if (!s1->cc_format) { + s1->cc_format = format; + + av_log(avctx, AV_LOG_DEBUG, "CC: first seen substream is %s format\n", + mpeg2_cc_format_labels[format]); + } +} + static int mpeg_decode_a53_cc(AVCodecContext *avctx, const uint8_t *p, int buf_size) { Mpeg1Context *s1 = avctx->priv_data; - if (buf_size >= 6 && + if ((!s1->cc_format || s1->cc_format == CC_FORMAT_A53_PART4) && + buf_size >= 6 && p[0] == 'G' && p[1] == 'A' && p[2] == '9' && p[3] == '4' && p[4] == 3 && (p[5] & 0x40)) { /* extract A53 Part 4 CC data */ @@ -1927,9 +1953,11 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, memcpy(s1->a53_buf_ref->data + old_size, p + 7, cc_count * UINT64_C(3)); avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + mpeg_set_cc_format(avctx, CC_FORMAT_A53_PART4); } return 1; - } else if (buf_size >= 2 && + } else if ((!s1->cc_format || s1->cc_format == CC_FORMAT_SCTE20) && + buf_size >= 2 && p[0] == 0x03 && (p[1]&0x7f) == 0x01) { /* extract SCTE-20 CC data */ GetBitContext gb; @@ -1973,10 +2001,13 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, cap += 3; } } + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + mpeg_set_cc_format(avctx, CC_FORMAT_SCTE20); } return 1; - } else if (buf_size >= 11 && + } else if ((!s1->cc_format || s1->cc_format == CC_FORMAT_DVD) && + buf_size >= 11 && p[0] == 'C' && p[1] == 'C' && p[2] == 0x01 && p[3] == 0xf8) { /* extract DVD CC data * @@ -2033,7 +2064,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, p += 6; } } + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + mpeg_set_cc_format(avctx, CC_FORMAT_DVD); } return 1; } @@ -2598,11 +2631,39 @@ const FFCodec ff_mpeg1video_decoder = { }, }; +#define M2V_OFFSET(x) offsetof(Mpeg1Context, x) +#define M2V_PARAM AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +static const AVOption mpeg2video_options[] = { + { "cc_format", "extract a specific Closed Captions format", + M2V_OFFSET(cc_format), AV_OPT_TYPE_INT, { .i64 = CC_FORMAT_AUTO }, + CC_FORMAT_AUTO, CC_FORMAT_DVD, M2V_PARAM, .unit = "cc_format" }, + + { "auto", "pick first seen CC substream", 0, AV_OPT_TYPE_CONST, + { .i64 = CC_FORMAT_AUTO }, .flags = M2V_PARAM, .unit = "cc_format" }, + { "a53", "pick A/53 Part 4 CC substream", 0, AV_OPT_TYPE_CONST, + { .i64 = CC_FORMAT_A53_PART4 }, .flags = M2V_PARAM, .unit = "cc_format" }, + { "scte20", "pick SCTE-20 CC substream", 0, AV_OPT_TYPE_CONST, + { .i64 = CC_FORMAT_SCTE20 }, .flags = M2V_PARAM, .unit = "cc_format" }, + { "dvd", "pick DVD CC substream", 0, AV_OPT_TYPE_CONST, + { .i64 = CC_FORMAT_DVD }, .flags = M2V_PARAM, .unit = "cc_format" }, + { NULL } +}; + +static const AVClass mpeg2video_class = { + .class_name = "MPEG-2 video", + .item_name = av_default_item_name, + .option = mpeg2video_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DECODER, +}; + const FFCodec ff_mpeg2video_decoder = { .p.name = "mpeg2video", CODEC_LONG_NAME("MPEG-2 video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_MPEG2VIDEO, + .p.priv_class = &mpeg2video_class, .priv_data_size = sizeof(Mpeg1Context), .init = mpeg_decode_init, .close = mpeg_decode_end, -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".