amlhwdmx: CB1 deal with private data [1/1]

PD#SWPL-180067

Problem:
e-ac3 codec, can't play, need to deal with
GST_MPEGTS_STREAM_TYPE_PRIVATE_PES_PACKETS

Solution:
add deal with GST_MPEGTS_STREAM_TYPE_PRIVATE_PES_PACKETS

Verify:
ap222

Change-Id: I542a7b0f25911a7e0f1df44968a998d2e430798c
Signed-off-by: hanghang.luo <hanghang.luo@amlogic.com>
diff --git a/src/aml_defs.h b/src/aml_defs.h
index 68b1ac0..b221c70 100644
--- a/src/aml_defs.h
+++ b/src/aml_defs.h
@@ -116,7 +116,6 @@
 #define GST_AML_TS_INFO_VIDEO_PID "video-pid"
 #define GST_AML_TS_INFO_AUDIO_PID "audio-pid"
 
-
 /** for debug **/
 // #define DBG_SECMEM
 
@@ -169,6 +168,93 @@
     /* 0x80 - 0xff : User Private (or defined in other specs) */
 } GstMpegtsStreamType;
 
+/**
+ * GstMpegtsDVBDescriptorType:
+ *
+ * The type of #GstMpegtsDescriptor
+ *
+ * These values correspond to the registered descriptor type from
+ * the various DVB specifications.
+ *
+ * Consult the relevant specifications for more details.
+ */
+typedef enum {
+  /* 64-127 DVB tags ETSI EN 300 468
+   * (Specification for Service Information (SI) in DVB systems)
+   */
+  GST_MTS_DESC_DVB_NETWORK_NAME                 = 0x40,
+  GST_MTS_DESC_DVB_SERVICE_LIST                 = 0x41,
+  GST_MTS_DESC_DVB_STUFFING                     = 0x42,
+  GST_MTS_DESC_DVB_SATELLITE_DELIVERY_SYSTEM    = 0x43,
+  GST_MTS_DESC_DVB_CABLE_DELIVERY_SYSTEM        = 0x44,
+  GST_MTS_DESC_DVB_VBI_DATA                     = 0x45,
+  GST_MTS_DESC_DVB_VBI_TELETEXT                 = 0x46,
+  GST_MTS_DESC_DVB_BOUQUET_NAME                 = 0x47,
+  GST_MTS_DESC_DVB_SERVICE                      = 0x48,
+  GST_MTS_DESC_DVB_COUNTRY_AVAILABILITY         = 0x49,
+  GST_MTS_DESC_DVB_LINKAGE                      = 0x4A,
+  GST_MTS_DESC_DVB_NVOD_REFERENCE               = 0x4B,
+  GST_MTS_DESC_DVB_TIME_SHIFTED_SERVICE         = 0x4C,
+  GST_MTS_DESC_DVB_SHORT_EVENT                  = 0x4D,
+  GST_MTS_DESC_DVB_EXTENDED_EVENT               = 0x4E,
+  GST_MTS_DESC_DVB_TIME_SHIFTED_EVENT           = 0x4F,
+  GST_MTS_DESC_DVB_COMPONENT                    = 0x50,
+  GST_MTS_DESC_DVB_MOSAIC                       = 0x51,
+  GST_MTS_DESC_DVB_STREAM_IDENTIFIER            = 0x52,
+  GST_MTS_DESC_DVB_CA_IDENTIFIER                = 0x53,
+  GST_MTS_DESC_DVB_CONTENT                      = 0x54,
+  GST_MTS_DESC_DVB_PARENTAL_RATING              = 0x55,
+  GST_MTS_DESC_DVB_TELETEXT                     = 0x56,
+  GST_MTS_DESC_DVB_TELEPHONE                    = 0x57,
+  GST_MTS_DESC_DVB_LOCAL_TIME_OFFSET            = 0x58,
+  GST_MTS_DESC_DVB_SUBTITLING                   = 0x59,
+  GST_MTS_DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM  = 0x5A,
+  GST_MTS_DESC_DVB_MULTILINGUAL_NETWORK_NAME    = 0x5B,
+  GST_MTS_DESC_DVB_MULTILINGUAL_BOUQUET_NAME    = 0x5C,
+  GST_MTS_DESC_DVB_MULTILINGUAL_SERVICE_NAME    = 0x5D,
+  GST_MTS_DESC_DVB_MULTILINGUAL_COMPONENT       = 0x5E,
+  GST_MTS_DESC_DVB_PRIVATE_DATA_SPECIFIER       = 0x5F,
+  GST_MTS_DESC_DVB_SERVICE_MOVE                 = 0x60,
+  GST_MTS_DESC_DVB_SHORT_SMOOTHING_BUFFER       = 0x61,
+  GST_MTS_DESC_DVB_FREQUENCY_LIST               = 0x62,
+  /**
+   * GST_MTS_DESC_DVB_PARTIAL_TRANSPORT_STREAM:
+   *
+   * Partial Transport Stream descriptor. Only present in SIT Sections.
+   *
+   * See also: %GST_MPEGTS_SECTION_SIT, %GstMpegtsSIT
+   */
+  GST_MTS_DESC_DVB_PARTIAL_TRANSPORT_STREAM     = 0x63,
+  GST_MTS_DESC_DVB_DATA_BROADCAST               = 0x64,
+  GST_MTS_DESC_DVB_SCRAMBLING                   = 0x65,
+  GST_MTS_DESC_DVB_DATA_BROADCAST_ID            = 0x66,
+  GST_MTS_DESC_DVB_TRANSPORT_STREAM             = 0x67,
+  GST_MTS_DESC_DVB_DSNG                         = 0x68,
+  GST_MTS_DESC_DVB_PDC                          = 0x69,
+  GST_MTS_DESC_DVB_AC3                          = 0x6A,
+  GST_MTS_DESC_DVB_ANCILLARY_DATA               = 0x6B,
+  GST_MTS_DESC_DVB_CELL_LIST                    = 0x6C,
+  GST_MTS_DESC_DVB_CELL_FREQUENCY_LINK          = 0x6D,
+  GST_MTS_DESC_DVB_ANNOUNCEMENT_SUPPORT         = 0x6E,
+  GST_MTS_DESC_DVB_APPLICATION_SIGNALLING       = 0x6F,
+  GST_MTS_DESC_DVB_ADAPTATION_FIELD_DATA        = 0x70,
+  GST_MTS_DESC_DVB_SERVICE_IDENTIFIER           = 0x71,
+  GST_MTS_DESC_DVB_SERVICE_AVAILABILITY         = 0x72,
+  GST_MTS_DESC_DVB_DEFAULT_AUTHORITY            = 0x73,
+  GST_MTS_DESC_DVB_RELATED_CONTENT              = 0x74,
+  GST_MTS_DESC_DVB_TVA_ID                       = 0x75,
+  GST_MTS_DESC_DVB_CONTENT_IDENTIFIER           = 0x76,
+  GST_MTS_DESC_DVB_TIMESLICE_FEC_IDENTIFIER     = 0x77,
+  GST_MTS_DESC_DVB_ECM_REPETITION_RATE          = 0x78,
+  GST_MTS_DESC_DVB_S2_SATELLITE_DELIVERY_SYSTEM = 0x79,
+  GST_MTS_DESC_DVB_ENHANCED_AC3                 = 0x7A,
+  GST_MTS_DESC_DVB_DTS                          = 0x7B,
+  GST_MTS_DESC_DVB_AAC                          = 0x7C,
+  GST_MTS_DESC_DVB_XAIT_LOCATION                = 0x7D,
+  GST_MTS_DESC_DVB_FTA_CONTENT_MANAGEMENT       = 0x7E,
+  GST_MTS_DESC_DVB_EXTENSION                    = 0x7F,
+} GstMpegtsDVBDescriptorType;
+
 /* audio codec types(using in seure case. copy from aml_aucpu.h) */
 typedef enum
 {
diff --git a/src/gstamldmx.c b/src/gstamldmx.c
index b6b7c73..04c00f6 100644
--- a/src/gstamldmx.c
+++ b/src/gstamldmx.c
@@ -1313,8 +1313,21 @@
     }
     case GST_MPEGTS_STREAM_TYPE_PRIVATE_PES_PACKETS:
     {
+        GPtrArray * array = NULL;
+
         GST_LOG("private data");
-        // TODO: handle codec info saves in descriptor
+        array = gst_parse_descriptors (pmt_stream->descriptor, pmt_stream->ES_info_length);
+        if (gst_find_descriptor(array, GST_MTS_DESC_DVB_ENHANCED_AC3))
+        {
+            GST_LOG("ac3 audio");
+            is_audio = TRUE;
+            caps = gst_caps_new_empty_simple("audio/x-eac3");
+        }
+        else
+        {
+            GST_WARNING("can't parse des");
+        }
+        g_ptr_array_free(array, TRUE);
         break;
     }
     case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_ADTS:
diff --git a/src/gstamldmxfilter.c b/src/gstamldmxfilter.c
index 4d6eec8..5810c0a 100644
--- a/src/gstamldmxfilter.c
+++ b/src/gstamldmxfilter.c
@@ -23,12 +23,26 @@
 #include <gst/allocators/gstdmabuf.h>
 #include <stdio.h>
 
+typedef struct
+{
+  guint8 tag;
+  guint8 tag_extension;
+  guint8 length;
+  guint8 *data;
+  guint32 codec_tag;
+
+  /*< private >*/
+  /* Padding for future extension */
+  gpointer _gst_reserved[GST_PADDING];
+} GstMpegtsDescriptor ;
+
 static gint get_prog_id(GstAmlhwdmx *amlhwdmx, int fid);
 static GstBuffer *gst_es_filter_construct_buf(GstDmxSrcStreamPad *spad, int dev_no, int fid, const guint *data, int len);
 static GstBuffer *gst_es_filter_construct_non_sec_buf(GstAmlhwdmx *amlhwdmx, int dev_no, int fid, const guint *data, int len);
 static GstBuffer *gst_es_filter_construct_sec_buf(GstAmlhwdmx *amlhwdmx, int dev_no, int fid, const guint *data, int len);
 static void gst_es_filter_dbg_non_sec_header(GstAmlhwdmx *amlhwdmx, const guint *data, int len);
-static GstAucpuStreamType gst_amlhwdmx_convert_acodectype_gst2dmx(GstMpegtsStreamType type);
+static GstAucpuStreamType gst_amlhwdmx_convert_acodectype_gst2dmx(TS_PMT_Stream stream);
+static void gst_descriptor_free(GstMpegtsDescriptor * desc);
 
 void gst_parse_pat_cb(int dev_no, int fid, const guint *data, int len, void *user_data)
 {
@@ -161,10 +175,10 @@
         }
         case GST_STREAM_TYPE_AUDIO:
         {
-            GstAucpuStreamType acodec_type;
+            GstAucpuStreamType acodec_type = MEDIA_UNKNOWN;
 
             es_fpara->pes_type = DMX_PES_AUDIO0;
-            acodec_type = gst_amlhwdmx_convert_acodectype_gst2dmx(amlhwdmx->sinkpad.pmt_para[progid].pmt.PMT_Stream[i].stream_type);
+            acodec_type = gst_amlhwdmx_convert_acodectype_gst2dmx(amlhwdmx->sinkpad.pmt_para[progid].pmt.PMT_Stream[i]);
             if (acodec_type == MEDIA_UNKNOWN)
             {
                 GST_ERROR_OBJECT(amlhwdmx, "parse acodec type error");
@@ -255,6 +269,133 @@
     gst_amladapterpipe_push(adapter_pipe, buf);
 }
 
+/**
+ * gst_descriptor_free:
+ * @desc: The descriptor to free
+ *
+ * Frees @desc
+ */
+static void gst_descriptor_free(GstMpegtsDescriptor * desc)
+{
+    g_return_val_if_fail(desc != NULL, NULL);
+    g_return_val_if_fail(desc->data != NULL, NULL);
+
+    g_free ((gpointer) desc->data);
+    g_slice_free (GstMpegtsDescriptor, desc);
+}
+
+/**
+ * gst_parse_descriptors:
+ * @buffer: (transfer none): descriptors to parse
+ * @buf_len: Size of @buffer
+ *
+ * Parses the descriptors present in @buffer and returns them as an
+ * array.
+ *
+ * Note: The data provided in @buffer will not be copied.
+ *
+ * Returns: (transfer full) (element-type GstMpegtsDescriptor): an
+ * array of the parsed descriptors or %NULL if there was an error.
+ * Release with #g_array_unref when done with it.
+ */
+GPtrArray* gst_parse_descriptors(guint8 * buffer, gsize buf_len)
+{
+  GPtrArray *res;
+  guint8 length;
+  guint8 *data;
+  guint i, nb_desc = 0;
+
+  /* fast-path */
+  if (buf_len == 0)
+    return g_ptr_array_new ();
+
+  data = buffer;
+
+  GST_MEMDUMP ("Full descriptor array", buffer, buf_len);
+
+  while (data - buffer < buf_len) {
+    data++;                     /* skip tag */
+    length = *data++;
+
+    if (data - buffer > buf_len) {
+      GST_WARNING ("invalid descriptor length %d now at %d max %"
+          G_GSIZE_FORMAT, length, (gint) (data - buffer), buf_len);
+      return NULL;
+    }
+
+    data += length;
+    nb_desc++;
+  }
+
+  GST_DEBUG ("Saw %d descriptors, read %" G_GSIZE_FORMAT " bytes",
+      nb_desc, (gsize) (data - buffer));
+
+  if (data - buffer != buf_len) {
+    GST_WARNING ("descriptors size %d expected %" G_GSIZE_FORMAT,
+        (gint) (data - buffer), buf_len);
+    return NULL;
+  }
+
+  res =
+      g_ptr_array_new_full (nb_desc + 1,
+      (GDestroyNotify) gst_descriptor_free);
+
+  data = buffer;
+
+  for (i = 0; i < nb_desc; i++) {
+    GstMpegtsDescriptor *desc = g_slice_new0 (GstMpegtsDescriptor);
+
+    desc->data = data;
+    desc->tag = *data++;
+    desc->length = *data++;
+    desc->codec_tag = *(guint32 *)data;
+    /* Copy the data now that we known the size */
+    desc->data = g_memdup2 (desc->data, desc->length + 2);
+    GST_LOG ("descriptor 0x%02x length:%d codec_tag %x ", desc->tag, desc->length, desc->codec_tag);
+    GST_MEMDUMP ("descriptor", desc->data + 2, desc->length);
+    /* extended descriptors */
+    if (G_UNLIKELY (desc->tag == 0x7f))
+      desc->tag_extension = *data;
+
+    data += desc->length;
+
+    /* Set the descriptor in the array */
+    g_ptr_array_index (res, i) = desc;
+  }
+
+  res->len = nb_desc;
+
+  return res;
+}
+
+/**
+ * gst_find_descriptor:
+ * @descriptors: (element-type GstMpegtsDescriptor) (transfer none): an array
+ * of #GstMpegtsDescriptor
+ * @tag: the tag to look for
+ *
+ * Finds the first descriptor of type @tag in the array.
+ *
+ * Note: To look for descriptors that can be present more than once in an
+ * array of descriptors, iterate the #GArray manually.
+ *
+ * Returns: (transfer none): the first descriptor matching @tag, else %NULL.
+ */
+const void* gst_find_descriptor(GPtrArray * descriptors, guint8 tag)
+{
+  guint i, nb_desc;
+
+  g_return_val_if_fail (descriptors != NULL, NULL);
+
+  nb_desc = descriptors->len;
+  for (i = 0; i < nb_desc; i++) {
+    GstMpegtsDescriptor *desc = g_ptr_array_index (descriptors, i);
+    if (desc->tag == tag)
+      return (const GstMpegtsDescriptor *) desc;
+  }
+  return NULL;
+}
+
 void gst_es_filter_reset(GstAmlhwdmx *amlhwdmx)
 {
     gint dmxret;
@@ -520,25 +661,42 @@
     }
 }
 
-static GstAucpuStreamType gst_amlhwdmx_convert_acodectype_gst2dmx(GstMpegtsStreamType type)
+static GstAucpuStreamType gst_amlhwdmx_convert_acodectype_gst2dmx(TS_PMT_Stream stream)
 {
-
-    GST_DEBUG("input type:0x%x", type);
-
+    GstMpegtsStreamType type = stream.stream_type;
+    GST_DEBUG("stream type:0x%x ", type);
     switch (type)
     {
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_MPEG1:
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_MPEG2:
-        return MEDIA_MPX;
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_ADTS:
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_CLEAN:
-        return MEDIA_AAC_ADTS;
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_LATM:
-        return MEDIA_AAC_LOAS;
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_EAC3:
-    case GST_MPEGTS_STREAM_TYPE_AUDIO_AC3_PLUS:
-        return MEDIA_AC3;
-    default:
-        return MEDIA_UNKNOWN;
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_MPEG1:
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_MPEG2:
+            return MEDIA_MPX;
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_ADTS:
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_CLEAN:
+            return MEDIA_AAC_ADTS;
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_AAC_LATM:
+            return MEDIA_AAC_LOAS;
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_EAC3:
+        case GST_MPEGTS_STREAM_TYPE_AUDIO_AC3_PLUS:
+            return MEDIA_AC3;
+        case GST_MPEGTS_STREAM_TYPE_PRIVATE_PES_PACKETS:
+        {
+            GPtrArray *array = NULL;
+            GstMpegtsDVBDescriptorType des_type;
+
+            array = gst_parse_descriptors(stream.descriptor, stream.ES_info_length);
+            if (gst_find_descriptor(array, GST_MTS_DESC_DVB_ENHANCED_AC3))
+                des_type = GST_MTS_DESC_DVB_ENHANCED_AC3;
+            g_ptr_array_free(array, TRUE);
+            GST_DEBUG("des type:0x%x ", des_type);
+            switch (des_type)
+            {
+                case GST_MTS_DESC_DVB_ENHANCED_AC3:
+                    return MEDIA_AC3;
+                default:
+                    return MEDIA_UNKNOWN;
+            }
+        }
+        default:
+            return MEDIA_UNKNOWN;
     }
 }
\ No newline at end of file
diff --git a/src/gstamldmxfilter.h b/src/gstamldmxfilter.h
index cb57600..ab0133d 100644
--- a/src/gstamldmxfilter.h
+++ b/src/gstamldmxfilter.h
@@ -29,6 +29,8 @@
 void gst_parse_pat_cb(int dev_no, int fid, const guint *data, int len, void *user_data);
 void gst_parse_pmt_cb(int dev_no, int fid, const guint *data, int len, void *user_data);
 void gst_parse_es_cb(int dev_no, int fid, const guint *data, int len, void *user_data);
+const void * gst_find_descriptor (GPtrArray * descriptors, guint8 tag);
+GPtrArray *gst_parse_descriptors (guint8 * buffer, gsize buf_len);
 void gst_es_filter_reset(GstAmlhwdmx *amlhwdmx);
 void gst_pmt_filter_reset(GstAmlhwdmx *amlhwdmx);
 void gst_pat_filter_reset(GstAmlhwdmx *amlhwdmx);
diff --git a/src/ts_patpmt_parse.c b/src/ts_patpmt_parse.c
index d2e0ed0..ecf62eb 100644
--- a/src/ts_patpmt_parse.c
+++ b/src/ts_patpmt_parse.c
@@ -112,21 +112,25 @@
         packet->reserved_6 = buffer[pos + 3] >> 4;
         pmt_stream->ES_info_length = (buffer[pos + 3] & 0x0F) << 8 | buffer[pos + 4];
 
-        pmt_stream->descriptor = 0x00;
-        if (pmt_stream->ES_info_length != 0)
+        memset(pmt_stream->descriptor, 0, STREAM_DESCRIPTOR_SIZE);
+        if (pmt_stream->ES_info_length != 0 && pmt_stream->ES_info_length < STREAM_DESCRIPTOR_SIZE)
         {
-            pmt_stream->descriptor = buffer[pos + 5];
-
-            for (int len = 2; len <= pmt_stream->ES_info_length; len++)
-            {
-                pmt_stream->descriptor = pmt_stream->descriptor << 8 | buffer[pos + 4 + len];
-            }
+            memcpy(pmt_stream->descriptor,&buffer[pos + 5],pmt_stream->ES_info_length);
             pos += pmt_stream->ES_info_length;
         }
+        else
+        {
+            GST_ERROR("ES_info_length is %d",pmt_stream->ES_info_length);
+        }
         pos += 5;
         // packet->PMT_Stream.push_back(pmt_stream);
         // TS_Stream_type.push_back(pmt_stream);
         packet->PMT_Stream_num++;
+        if (packet->PMT_Stream_num >= MAX_STREAM_NUM)
+        {
+            GST_ERROR("PMT_Stream_num=%d, too many.", packet->PMT_Stream_num);
+            break;
+        }
     }
     return 0;
 }
diff --git a/src/ts_patpmt_parse.h b/src/ts_patpmt_parse.h
index 64b2cc0..47712ae 100644
--- a/src/ts_patpmt_parse.h
+++ b/src/ts_patpmt_parse.h
@@ -36,6 +36,8 @@
 #define STREAM_TYPE_AUDIO_AAC 0x0f
 #define STREAM_TYPE_AUDIO_AC3 0x81
 
+#define STREAM_DESCRIPTOR_SIZE 128
+
 GST_DEBUG_CATEGORY_EXTERN(gst_amlhwdmx_debug);
 #define GST_CAT_DEFAULT gst_amlhwdmx_debug
 
@@ -72,7 +74,7 @@
     unsigned stream_type : 8;
     unsigned elementary_PID : 13;
     unsigned ES_info_length : 12;
-    unsigned descriptor;
+    unsigned char descriptor[STREAM_DESCRIPTOR_SIZE];
 } TS_PMT_Stream;
 
 typedef struct TS_PMT