From d34a62b641bd455de3c90bd4c3c86add0ec0d677 Mon Sep 17 00:00:00 2001
From: erankor <eran.kornblau@kaltura.com>
Date: Sat, 21 Aug 2021 19:52:24 +0300
Subject: [PATCH] ccaption_dec: support multiple channels

added an optional "channel" param for selecting the channel to output
(similarly to the existing "data_field" param)
---
 libavcodec/ccaption_dec.c | 45 +++++++++++++++++++++++++++++++++++----
 1 file changed, 41 insertions(+), 4 deletions(-)

diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
index 27c61527f6..4dc3a99ea9 100644
--- a/libavcodec/ccaption_dec.c
+++ b/libavcodec/ccaption_dec.c
@@ -258,6 +258,8 @@ typedef struct CCaptionSubContext {
     int64_t last_real_time;
     uint8_t prev_cmd[2];
     int readorder;
+    int cur_channel;
+    int channel;
 } CCaptionSubContext;
 
 static av_cold int init_decoder(AVCodecContext *avctx)
@@ -756,15 +758,33 @@ static int process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
     ctx->prev_cmd[0] = hi;
     ctx->prev_cmd[1] = lo;
 
-    if ( (hi == 0x10 && (lo >= 0x40 && lo <= 0x5f)) ||
-       ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
+    if ( ((hi == 0x10 || hi == 0x18) && (lo >= 0x40 && lo <= 0x5f)) ||
+       ( ((hi >= 0x11 && hi <= 0x17) || (hi >= 0x19 && hi <= 0x1f)) && (lo >= 0x40 && lo <= 0x7f) ) ) {
+        ctx->cur_channel = hi <= 0x17 ? 1 : 2;
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         handle_pac(ctx, hi, lo);
     } else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) ||
                 ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) {
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         handle_textattr(ctx, hi, lo);
     } else if ((hi == 0x10 && lo >= 0x20 && lo <= 0x2f)) {
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         handle_bgattr(ctx, hi, lo);
-    } else if (hi == 0x14 || hi == 0x15 || hi == 0x1c) {
+    } else if (hi == 0x14 || hi == 0x15 || hi == 0x1c || hi == 0x1d) {
+        ctx->cur_channel = hi == 0x14 || hi == 0x15 ? 1 : 2;
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         switch (lo) {
         case 0x20:
             /* resume caption loading */
@@ -817,19 +837,35 @@ static int process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
             ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
             break;
         }
+
     } else if (hi >= 0x11 && hi <= 0x13) {
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         /* Special characters */
         handle_char(ctx, hi, lo);
     } else if (hi >= 0x20) {
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         /* Standard characters (always in pairs) */
         handle_char(ctx, hi, lo);
         ctx->prev_cmd[0] = ctx->prev_cmd[1] = 0;
-    } else if (hi == 0x17 && lo >= 0x21 && lo <= 0x23) {
+    } else if ((hi == 0x17 || hi == 0x1f) && lo >= 0x21 && lo <= 0x23) {
         int i;
+
+        ctx->cur_channel = hi == 0x17 ? 1 : 2;
+        if (ctx->cur_channel != ctx->channel) {
+            return 0;
+        }
+
         /* Tab offsets (spacing) */
         for (i = 0; i < lo - 0x20; i++) {
             handle_char(ctx, ' ', 0);
         }
+
     } else {
         /* Ignoring all other non data code */
         ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
@@ -933,6 +969,7 @@ static const AVOption options[] = {
     { "auto",   "pick first one that appears", 0, AV_OPT_TYPE_CONST, { .i64 =-1 }, 0, 0, SD, "data_field" },
     { "first",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, SD, "data_field" },
     { "second", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, SD, "data_field" },
+    { "channel", "select channel", OFFSET(channel), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 2, SD },
     {NULL}
 };
 
-- 
2.29.2.windows.4

