closedcaption: move cc_data->cdp to shared file
authorMatthew Waters <matthew@centricular.com>
Fri, 13 May 2022 05:19:43 +0000 (15:19 +1000)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 10 Nov 2022 00:52:14 +0000 (00:52 +0000)
Used by both ccconverter and cccombiner

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3211>

subprojects/gst-plugins-bad/ext/closedcaption/ccutils.c
subprojects/gst-plugins-bad/ext/closedcaption/ccutils.h
subprojects/gst-plugins-bad/ext/closedcaption/gstcccombiner.c
subprojects/gst-plugins-bad/ext/closedcaption/gstccconverter.c
subprojects/gst-plugins-bad/ext/closedcaption/gstclosedcaption.c

index 3c96754..fa2559d 100644 (file)
 #  include <config.h>
 #endif
 
+#include <gst/base/base.h>
+
 #include "ccutils.h"
 
+#define GST_CAT_DEFAULT ccutils_debug_cat
+GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
+
+typedef struct cdp_fps_entry cdp_fps_entry;
+
 static const struct cdp_fps_entry cdp_fps_table[] = {
   {0x1f, 24000, 1001, 25, 22, 3 /* FIXME: alternating max cea608 count! */ },
   {0x2f, 24, 1, 25, 22, 2},
@@ -57,3 +64,119 @@ cdp_fps_entry_from_id (guint8 id)
   }
   return &null_fps_entry;
 }
+
+/* Converts raw CEA708 cc_data and an optional timecode into CDP */
+guint
+convert_cea708_cc_data_to_cdp (GstObject * dbg_obj, GstCCCDPMode cdp_mode,
+    guint16 cdp_hdr_sequence_cntr, const guint8 * cc_data, guint cc_data_len,
+    guint8 * cdp, guint cdp_len, const GstVideoTimeCode * tc,
+    const cdp_fps_entry * fps_entry)
+{
+  GstByteWriter bw;
+  guint8 flags, checksum;
+  guint i, len;
+
+  GST_DEBUG_OBJECT (dbg_obj, "writing out cdp packet from cc_data with "
+      "length %u", cc_data_len);
+
+  gst_byte_writer_init_with_data (&bw, cdp, cdp_len, FALSE);
+  gst_byte_writer_put_uint16_be_unchecked (&bw, 0x9669);
+  /* Write a length of 0 for now */
+  gst_byte_writer_put_uint8_unchecked (&bw, 0);
+
+  gst_byte_writer_put_uint8_unchecked (&bw, fps_entry->fps_idx);
+
+  if (cc_data_len / 3 > fps_entry->max_cc_count) {
+    GST_WARNING_OBJECT (dbg_obj, "Too many cc_data triplets for framerate: %u. "
+        "Truncating to %u", cc_data_len / 3, fps_entry->max_cc_count);
+    cc_data_len = 3 * fps_entry->max_cc_count;
+  }
+
+  /* caption_service_active */
+  flags = 0x02;
+
+  /* ccdata_present */
+  if ((cdp_mode & GST_CC_CDP_MODE_CC_DATA))
+    flags |= 0x40;
+
+  /* time_code_present */
+  if ((cdp_mode & GST_CC_CDP_MODE_TIME_CODE) && tc && tc->config.fps_n > 0)
+    flags |= 0x80;
+
+  /* reserved */
+  flags |= 0x01;
+
+  gst_byte_writer_put_uint8_unchecked (&bw, flags);
+
+  gst_byte_writer_put_uint16_be_unchecked (&bw, cdp_hdr_sequence_cntr);
+
+  if ((cdp_mode & GST_CC_CDP_MODE_TIME_CODE) && tc && tc->config.fps_n > 0) {
+    guint8 u8;
+
+    gst_byte_writer_put_uint8_unchecked (&bw, 0x71);
+    /* reserved 11 - 2 bits */
+    u8 = 0xc0;
+    /* tens of hours - 2 bits */
+    u8 |= ((tc->hours / 10) & 0x3) << 4;
+    /* units of hours - 4 bits */
+    u8 |= (tc->hours % 10) & 0xf;
+    gst_byte_writer_put_uint8_unchecked (&bw, u8);
+
+    /* reserved 1 - 1 bit */
+    u8 = 0x80;
+    /* tens of minutes - 3 bits */
+    u8 |= ((tc->minutes / 10) & 0x7) << 4;
+    /* units of minutes - 4 bits */
+    u8 |= (tc->minutes % 10) & 0xf;
+    gst_byte_writer_put_uint8_unchecked (&bw, u8);
+
+    /* field flag - 1 bit */
+    u8 = tc->field_count < 2 ? 0x00 : 0x80;
+    /* tens of seconds - 3 bits */
+    u8 |= ((tc->seconds / 10) & 0x7) << 4;
+    /* units of seconds - 4 bits */
+    u8 |= (tc->seconds % 10) & 0xf;
+    gst_byte_writer_put_uint8_unchecked (&bw, u8);
+
+    /* drop frame flag - 1 bit */
+    u8 = (tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) ? 0x80 :
+        0x00;
+    /* reserved0 - 1 bit */
+    /* tens of frames - 2 bits */
+    u8 |= ((tc->frames / 10) & 0x3) << 4;
+    /* units of frames 4 bits */
+    u8 |= (tc->frames % 10) & 0xf;
+    gst_byte_writer_put_uint8_unchecked (&bw, u8);
+  }
+
+  if ((cdp_mode & GST_CC_CDP_MODE_CC_DATA)) {
+    gst_byte_writer_put_uint8_unchecked (&bw, 0x72);
+    gst_byte_writer_put_uint8_unchecked (&bw, 0xe0 | fps_entry->max_cc_count);
+    gst_byte_writer_put_data_unchecked (&bw, cc_data, cc_data_len);
+    while (fps_entry->max_cc_count > cc_data_len / 3) {
+      gst_byte_writer_put_uint8_unchecked (&bw, 0xfa);
+      gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
+      gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
+      cc_data_len += 3;
+    }
+  }
+
+  gst_byte_writer_put_uint8_unchecked (&bw, 0x74);
+  gst_byte_writer_put_uint16_be_unchecked (&bw, cdp_hdr_sequence_cntr);
+  /* We calculate the checksum afterwards */
+  gst_byte_writer_put_uint8_unchecked (&bw, 0);
+
+  len = gst_byte_writer_get_pos (&bw);
+  gst_byte_writer_set_pos (&bw, 2);
+  gst_byte_writer_put_uint8_unchecked (&bw, len);
+
+  checksum = 0;
+  for (i = 0; i < len; i++) {
+    checksum += cdp[i];
+  }
+  checksum &= 0xff;
+  checksum = 256 - checksum;
+  cdp[len - 1] = checksum;
+
+  return len;
+}
index d7586c8..1e3029e 100644 (file)
  */
 
 #include <gst/gst.h>
+#include <gst/video/video.h>
 
 #ifndef __CCUTILS_H__
 #define __CCUTILS_H__
 
 G_BEGIN_DECLS
 
+GST_DEBUG_CATEGORY_EXTERN(ccutils_debug_cat);
+
 struct cdp_fps_entry
 {
   guint8 fps_idx;               /* value stored in cdp */
@@ -41,6 +44,22 @@ const struct cdp_fps_entry * cdp_fps_entry_from_id  (guint8 id);
 
 extern const struct cdp_fps_entry null_fps_entry;
 
+typedef enum {
+  GST_CC_CDP_MODE_TIME_CODE   = (1<<0),
+  GST_CC_CDP_MODE_CC_DATA     = (1<<1),
+  GST_CC_CDP_MODE_CC_SVC_INFO = (1<<2)
+} GstCCCDPMode;
+
+guint           convert_cea708_cc_data_to_cdp  (GstObject * dbg_obj,
+                                                GstCCCDPMode cdp_mode,
+                                                guint16 cdp_hdr_sequence_cntr,
+                                                const guint8 * cc_data,
+                                                guint cc_data_len,
+                                                guint8 * cdp,
+                                                guint cdp_len,
+                                                const GstVideoTimeCode * tc,
+                                                const struct cdp_fps_entry *fps_entry);
+
 G_END_DECLS
 
 #endif
index 0f75170..b04b513 100644 (file)
@@ -192,108 +192,22 @@ done:
 
 #define MAX_CDP_PACKET_LEN 256
 #define MAX_CEA608_LEN 32
+#define CDP_MODE (GST_CC_CDP_MODE_CC_DATA | GST_CC_CDP_MODE_TIME_CODE)
 
 static GstBuffer *
 make_cdp (GstCCCombiner * self, const guint8 * cc_data, guint cc_data_len,
     const struct cdp_fps_entry *fps_entry, const GstVideoTimeCode * tc)
 {
-  GstByteWriter bw;
-  guint8 flags, checksum;
-  guint i, len;
+  guint len;
   GstBuffer *ret = gst_buffer_new_allocate (NULL, MAX_CDP_PACKET_LEN, NULL);
   GstMapInfo map;
 
   gst_buffer_map (ret, &map, GST_MAP_WRITE);
 
-  gst_byte_writer_init_with_data (&bw, map.data, MAX_CDP_PACKET_LEN, FALSE);
-  gst_byte_writer_put_uint16_be_unchecked (&bw, 0x9669);
-  /* Write a length of 0 for now */
-  gst_byte_writer_put_uint8_unchecked (&bw, 0);
-
-  gst_byte_writer_put_uint8_unchecked (&bw, fps_entry->fps_idx);
-
-  /* caption_service_active */
-  flags = 0x02;
-
-  /* ccdata_present */
-  flags |= 0x40;
-
-  if (tc && tc->config.fps_n > 0)
-    flags |= 0x80;
-
-  /* reserved */
-  flags |= 0x01;
-
-  gst_byte_writer_put_uint8_unchecked (&bw, flags);
-
-  gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr);
-
-  if (tc && tc->config.fps_n > 0) {
-    guint8 u8;
-
-    gst_byte_writer_put_uint8_unchecked (&bw, 0x71);
-    /* reserved 11 - 2 bits */
-    u8 = 0xc0;
-    /* tens of hours - 2 bits */
-    u8 |= ((tc->hours / 10) & 0x3) << 4;
-    /* units of hours - 4 bits */
-    u8 |= (tc->hours % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-
-    /* reserved 1 - 1 bit */
-    u8 = 0x80;
-    /* tens of minutes - 3 bits */
-    u8 |= ((tc->minutes / 10) & 0x7) << 4;
-    /* units of minutes - 4 bits */
-    u8 |= (tc->minutes % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-
-    /* field flag - 1 bit */
-    u8 = tc->field_count < 2 ? 0x00 : 0x80;
-    /* tens of seconds - 3 bits */
-    u8 |= ((tc->seconds / 10) & 0x7) << 4;
-    /* units of seconds - 4 bits */
-    u8 |= (tc->seconds % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-
-    /* drop frame flag - 1 bit */
-    u8 = (tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) ? 0x80 :
-        0x00;
-    /* reserved0 - 1 bit */
-    /* tens of frames - 2 bits */
-    u8 |= ((tc->frames / 10) & 0x3) << 4;
-    /* units of frames 4 bits */
-    u8 |= (tc->frames % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-  }
-
-  gst_byte_writer_put_uint8_unchecked (&bw, 0x72);
-  gst_byte_writer_put_uint8_unchecked (&bw, 0xe0 | fps_entry->max_cc_count);
-  gst_byte_writer_put_data_unchecked (&bw, cc_data, cc_data_len);
-  while (fps_entry->max_cc_count > cc_data_len / 3) {
-    gst_byte_writer_put_uint8_unchecked (&bw, 0xfa);
-    gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
-    gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
-    cc_data_len += 3;
-  }
-
-  gst_byte_writer_put_uint8_unchecked (&bw, 0x74);
-  gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr);
+  len = convert_cea708_cc_data_to_cdp (GST_OBJECT (self), CDP_MODE,
+      self->cdp_hdr_sequence_cntr, cc_data, cc_data_len, map.data, map.size,
+      tc, fps_entry);
   self->cdp_hdr_sequence_cntr++;
-  /* We calculate the checksum afterwards */
-  gst_byte_writer_put_uint8_unchecked (&bw, 0);
-
-  len = gst_byte_writer_get_pos (&bw);
-  gst_byte_writer_set_pos (&bw, 2);
-  gst_byte_writer_put_uint8_unchecked (&bw, len);
-
-  checksum = 0;
-  for (i = 0; i < len; i++) {
-    checksum += map.data[i];
-  }
-  checksum &= 0xff;
-  checksum = 256 - checksum;
-  map.data[len - 1] = checksum;
 
   gst_buffer_unmap (ret, &map);
 
index f2882d4..9fcbc89 100644 (file)
@@ -80,11 +80,11 @@ static GType
 gst_cc_converter_cdp_mode_get_type (void)
 {
   static const GFlagsValue values[] = {
-    {GST_CC_CONVERTER_CDP_MODE_TIME_CODE,
+    {GST_CC_CDP_MODE_TIME_CODE,
         "Store time code information in CDP packets", "time-code"},
-    {GST_CC_CONVERTER_CDP_MODE_CC_DATA, "Store CC data in CDP packets",
+    {GST_CC_CDP_MODE_CC_DATA, "Store CC data in CDP packets",
         "cc-data"},
-    {GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO,
+    {GST_CC_CDP_MODE_CC_SVC_INFO,
         "Store CC service information in CDP packets", "cc-svc-info"},
     {0, NULL, NULL}
   };
@@ -1104,122 +1104,19 @@ fit_and_scale_cc_data (GstCCConverter * self,
   return TRUE;
 }
 
-/* Converts raw CEA708 cc_data and an optional timecode into CDP */
 static guint
 convert_cea708_cc_data_cea708_cdp_internal (GstCCConverter * self,
     const guint8 * cc_data, guint cc_data_len, guint8 * cdp, guint cdp_len,
     const GstVideoTimeCode * tc, const struct cdp_fps_entry *fps_entry)
 {
-  GstByteWriter bw;
-  guint8 flags, checksum;
-  guint i, len;
+  guint ret;
 
-  GST_DEBUG_OBJECT (self, "writing out cdp packet from cc_data with length %u",
-      cc_data_len);
-
-  gst_byte_writer_init_with_data (&bw, cdp, cdp_len, FALSE);
-  gst_byte_writer_put_uint16_be_unchecked (&bw, 0x9669);
-  /* Write a length of 0 for now */
-  gst_byte_writer_put_uint8_unchecked (&bw, 0);
-
-  gst_byte_writer_put_uint8_unchecked (&bw, fps_entry->fps_idx);
-
-  if (cc_data_len / 3 > fps_entry->max_cc_count) {
-    GST_WARNING_OBJECT (self, "Too many cc_data triplets for framerate: %u. "
-        "Truncating to %u", cc_data_len / 3, fps_entry->max_cc_count);
-    cc_data_len = 3 * fps_entry->max_cc_count;
-  }
-
-  /* caption_service_active */
-  flags = 0x02;
-
-  /* ccdata_present */
-  if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_CC_DATA))
-    flags |= 0x40;
-
-  /* time_code_present */
-  if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_TIME_CODE) && tc
-      && tc->config.fps_n > 0)
-    flags |= 0x80;
-
-  /* reserved */
-  flags |= 0x01;
-
-  gst_byte_writer_put_uint8_unchecked (&bw, flags);
-
-  gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr);
-
-  if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_TIME_CODE) && tc
-      && tc->config.fps_n > 0) {
-    guint8 u8;
-
-    gst_byte_writer_put_uint8_unchecked (&bw, 0x71);
-    /* reserved 11 - 2 bits */
-    u8 = 0xc0;
-    /* tens of hours - 2 bits */
-    u8 |= ((tc->hours / 10) & 0x3) << 4;
-    /* units of hours - 4 bits */
-    u8 |= (tc->hours % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-
-    /* reserved 1 - 1 bit */
-    u8 = 0x80;
-    /* tens of minutes - 3 bits */
-    u8 |= ((tc->minutes / 10) & 0x7) << 4;
-    /* units of minutes - 4 bits */
-    u8 |= (tc->minutes % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-
-    /* field flag - 1 bit */
-    u8 = tc->field_count < 2 ? 0x00 : 0x80;
-    /* tens of seconds - 3 bits */
-    u8 |= ((tc->seconds / 10) & 0x7) << 4;
-    /* units of seconds - 4 bits */
-    u8 |= (tc->seconds % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-
-    /* drop frame flag - 1 bit */
-    u8 = (tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) ? 0x80 :
-        0x00;
-    /* reserved0 - 1 bit */
-    /* tens of frames - 2 bits */
-    u8 |= ((tc->frames / 10) & 0x3) << 4;
-    /* units of frames 4 bits */
-    u8 |= (tc->frames % 10) & 0xf;
-    gst_byte_writer_put_uint8_unchecked (&bw, u8);
-  }
-
-  if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_CC_DATA)) {
-    gst_byte_writer_put_uint8_unchecked (&bw, 0x72);
-    gst_byte_writer_put_uint8_unchecked (&bw, 0xe0 | fps_entry->max_cc_count);
-    gst_byte_writer_put_data_unchecked (&bw, cc_data, cc_data_len);
-    while (fps_entry->max_cc_count > cc_data_len / 3) {
-      gst_byte_writer_put_uint8_unchecked (&bw, 0xfa);
-      gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
-      gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
-      cc_data_len += 3;
-    }
-  }
-
-  gst_byte_writer_put_uint8_unchecked (&bw, 0x74);
-  gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr);
+  ret = convert_cea708_cc_data_to_cdp (GST_OBJECT (self),
+      (GstCCCDPMode) self->cdp_mode, self->cdp_hdr_sequence_cntr, cc_data,
+      cc_data_len, cdp, cdp_len, tc, fps_entry);
   self->cdp_hdr_sequence_cntr++;
-  /* We calculate the checksum afterwards */
-  gst_byte_writer_put_uint8_unchecked (&bw, 0);
-
-  len = gst_byte_writer_get_pos (&bw);
-  gst_byte_writer_set_pos (&bw, 2);
-  gst_byte_writer_put_uint8_unchecked (&bw, len);
 
-  checksum = 0;
-  for (i = 0; i < len; i++) {
-    checksum += cdp[i];
-  }
-  checksum &= 0xff;
-  checksum = 256 - checksum;
-  cdp[len - 1] = checksum;
-
-  return len;
+  return ret;
 }
 
 /* Converts CDP into raw CEA708 cc_data */
index 05910ac..8668a84 100644 (file)
 #include "gstline21dec.h"
 #include "gstceaccoverlay.h"
 #include "gstline21enc.h"
+#include "ccutils.h"
 
 static gboolean
 closedcaption_init (GstPlugin * plugin)
 {
   gboolean ret = FALSE;
 
+  GST_DEBUG_CATEGORY_INIT (ccutils_debug_cat, "ccutils", 0,
+      "Closed caption utilities");
+
   ret |= GST_ELEMENT_REGISTER (cccombiner, plugin);
   ret |= GST_ELEMENT_REGISTER (ccconverter, plugin);
   ret |= GST_ELEMENT_REGISTER (ccextractor, plugin);