Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] libavcodec/mpeg12dec: extract embedded CC of particular type only
@ 2022-04-27  8:49 Ivan Baykalov
  2022-05-08  4:30 ` lance.lmwang
  0 siblings, 1 reply; 2+ messages in thread
From: Ivan Baykalov @ 2022-04-27  8:49 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Ivan Baykalov

Some streams contain closed caption data embedded using several wrapping
types. For example stream can contain CC wrapped as ATSC A53 packets +
the same data wrapped as SCTE-20 packets. Prior to the patch CC data was
extracted from both types of packets, so it gave duplicated character
pairs on the output.

Now we calculate some statistics which CC types appear more often in the
stream and extract the data from a single type only. If at some point
the other CC type becomes more active, we switch to this new type.

Fixes ticket #9724.
---
 libavcodec/mpeg12dec.c | 44 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index e9bde48f7a..f7e54ef0a9 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -58,6 +58,14 @@
 
 #define A53_MAX_CC_COUNT 2000
 
+typedef enum CcType {
+    CC_TYPE_UNKNOWN = -1,
+    CC_TYPE_A53 = 0,
+    CC_TYPE_SCTE20,
+    CC_TYPE_DVD,
+    CC_TYPE_COUNT
+} CcType;
+
 typedef struct Mpeg1Context {
     MpegEncContext mpeg_enc_ctx;
     int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
@@ -81,6 +89,7 @@ typedef struct Mpeg1Context {
     int first_slice;
     int extradata_decoded;
     int64_t timecode_frame_start;  /*< GOP timecode frame start number, in non drop frame format */
+    int cc_packet_count[CC_TYPE_COUNT];
 } Mpeg1Context;
 
 #define MB_TYPE_ZERO_MV   0x20000000
@@ -2198,6 +2207,32 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
     return 0;
 }
 
+static int cc_type_is_selected(Mpeg1Context *s1, CcType type)
+{
+    int max = 0;
+    int max_index = -1;
+    int sum = 0;
+    av_assert0(type >= 0 && type < CC_TYPE_COUNT);
+    s1->cc_packet_count[type]++;
+
+    for (int i = 0; i < CC_TYPE_COUNT; i++) {
+        if (s1->cc_packet_count[i] > max) {
+            max = s1->cc_packet_count[i];
+            max_index = i;
+        }
+        sum += s1->cc_packet_count[i];
+    }
+
+    if (sum < 2 || sum > 20) {
+        // reset statistics, but give some advantage to the current selection
+        // to avoid frequent switching between the types
+        memset(s1->cc_packet_count, 0, sizeof(s1->cc_packet_count));
+        s1->cc_packet_count[max_index] = 2;
+    }
+
+    return type == max_index;
+}
+
 static int mpeg_decode_a53_cc(AVCodecContext *avctx,
                               const uint8_t *p, int buf_size)
 {
@@ -2217,6 +2252,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
             if (new_size > 3*A53_MAX_CC_COUNT)
                 return AVERROR(EINVAL);
 
+            if (!cc_type_is_selected(s1, CC_TYPE_A53))
+                return 0;
+
             ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
             if (ret >= 0)
                 memcpy(s1->a53_buf_ref->data + old_size, p + 7, cc_count * UINT64_C(3));
@@ -2240,6 +2278,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
             if (new_size > 3*A53_MAX_CC_COUNT)
                 return AVERROR(EINVAL);
 
+            if (!cc_type_is_selected(s1, CC_TYPE_SCTE20))
+                return 0;
+
             ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
             if (ret >= 0) {
                 uint8_t field, cc1, cc2;
@@ -2310,6 +2351,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
             if (new_size > 3*A53_MAX_CC_COUNT)
                 return AVERROR(EINVAL);
 
+            if (!cc_type_is_selected(s1, CC_TYPE_DVD))
+                return 0;
+
             ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
             if (ret >= 0) {
                 uint8_t field1 = !!(p[4] & 0x80);
-- 
2.35.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".

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [FFmpeg-devel] [PATCH] libavcodec/mpeg12dec: extract embedded CC of particular type only
  2022-04-27  8:49 [FFmpeg-devel] [PATCH] libavcodec/mpeg12dec: extract embedded CC of particular type only Ivan Baykalov
@ 2022-05-08  4:30 ` lance.lmwang
  0 siblings, 0 replies; 2+ messages in thread
From: lance.lmwang @ 2022-05-08  4:30 UTC (permalink / raw)
  To: ffmpeg-devel

On Wed, Apr 27, 2022 at 03:49:49PM +0700, Ivan Baykalov wrote:
> Some streams contain closed caption data embedded using several wrapping
> types. For example stream can contain CC wrapped as ATSC A53 packets +
> the same data wrapped as SCTE-20 packets. Prior to the patch CC data was
> extracted from both types of packets, so it gave duplicated character
> pairs on the output.
> 
> Now we calculate some statistics which CC types appear more often in the
> stream and extract the data from a single type only. If at some point
> the other CC type becomes more active, we switch to this new type.

It's better to export them on demand instead of autodetect. I'll post the patchset
which fixed my local branch for review.

> 
> Fixes ticket #9724.
> ---
>  libavcodec/mpeg12dec.c | 44 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
> index e9bde48f7a..f7e54ef0a9 100644
> --- a/libavcodec/mpeg12dec.c
> +++ b/libavcodec/mpeg12dec.c
> @@ -58,6 +58,14 @@
>  
>  #define A53_MAX_CC_COUNT 2000
>  
> +typedef enum CcType {
> +    CC_TYPE_UNKNOWN = -1,
> +    CC_TYPE_A53 = 0,
> +    CC_TYPE_SCTE20,
> +    CC_TYPE_DVD,
> +    CC_TYPE_COUNT
> +} CcType;
> +
>  typedef struct Mpeg1Context {
>      MpegEncContext mpeg_enc_ctx;
>      int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
> @@ -81,6 +89,7 @@ typedef struct Mpeg1Context {
>      int first_slice;
>      int extradata_decoded;
>      int64_t timecode_frame_start;  /*< GOP timecode frame start number, in non drop frame format */
> +    int cc_packet_count[CC_TYPE_COUNT];
>  } Mpeg1Context;
>  
>  #define MB_TYPE_ZERO_MV   0x20000000
> @@ -2198,6 +2207,32 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
>      return 0;
>  }
>  
> +static int cc_type_is_selected(Mpeg1Context *s1, CcType type)
> +{
> +    int max = 0;
> +    int max_index = -1;
> +    int sum = 0;
> +    av_assert0(type >= 0 && type < CC_TYPE_COUNT);
> +    s1->cc_packet_count[type]++;
> +
> +    for (int i = 0; i < CC_TYPE_COUNT; i++) {
> +        if (s1->cc_packet_count[i] > max) {
> +            max = s1->cc_packet_count[i];
> +            max_index = i;
> +        }
> +        sum += s1->cc_packet_count[i];
> +    }
> +
> +    if (sum < 2 || sum > 20) {
> +        // reset statistics, but give some advantage to the current selection
> +        // to avoid frequent switching between the types
> +        memset(s1->cc_packet_count, 0, sizeof(s1->cc_packet_count));
> +        s1->cc_packet_count[max_index] = 2;
> +    }
> +
> +    return type == max_index;
> +}
> +
>  static int mpeg_decode_a53_cc(AVCodecContext *avctx,
>                                const uint8_t *p, int buf_size)
>  {
> @@ -2217,6 +2252,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
>              if (new_size > 3*A53_MAX_CC_COUNT)
>                  return AVERROR(EINVAL);
>  
> +            if (!cc_type_is_selected(s1, CC_TYPE_A53))
> +                return 0;
> +
>              ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
>              if (ret >= 0)
>                  memcpy(s1->a53_buf_ref->data + old_size, p + 7, cc_count * UINT64_C(3));
> @@ -2240,6 +2278,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
>              if (new_size > 3*A53_MAX_CC_COUNT)
>                  return AVERROR(EINVAL);
>  
> +            if (!cc_type_is_selected(s1, CC_TYPE_SCTE20))
> +                return 0;
> +
>              ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
>              if (ret >= 0) {
>                  uint8_t field, cc1, cc2;
> @@ -2310,6 +2351,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
>              if (new_size > 3*A53_MAX_CC_COUNT)
>                  return AVERROR(EINVAL);
>  
> +            if (!cc_type_is_selected(s1, CC_TYPE_DVD))
> +                return 0;
> +
>              ret = av_buffer_realloc(&s1->a53_buf_ref, new_size);
>              if (ret >= 0) {
>                  uint8_t field1 = !!(p[4] & 0x80);
> -- 
> 2.35.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".

-- 
Thanks,
Limin Wang
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-05-08  4:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27  8:49 [FFmpeg-devel] [PATCH] libavcodec/mpeg12dec: extract embedded CC of particular type only Ivan Baykalov
2022-05-08  4:30 ` lance.lmwang

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git