tsdemux: Parse Audio Preselection Descriptor
authoryychao <yychao@realtek.com>
Fri, 4 Sep 2020 15:34:16 +0000 (23:34 +0800)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 14 Sep 2020 06:27:07 +0000 (06:27 +0000)
For Dolby AC4 audio experience, parsing PMTs/APD from transport stream layer for all available presentations.
Refer to ETSI EN 300 468 V1.16.1 (2019-05)

1. 6.4.1 Audio preselection descriptor
2. Table M.1: Mapping of codec specific values to the audio preselection descriptor

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1555>

gst-libs/gst/mpegts/gst-dvb-descriptor.c
gst-libs/gst/mpegts/gst-dvb-descriptor.h
gst/mpegtsdemux/tsdemux.c

index 09a42da6d765422406ec6f019cba7d2b37d20419..2fd46133f0ff879213311c5fcd3420c7c16f362b 100644 (file)
@@ -2460,3 +2460,116 @@ gst_mpegts_descriptor_parse_dvb_t2_delivery_system (const GstMpegtsDescriptor
   *desc = res;
   return TRUE;
 }
+
+/**
+ * gst_mpegts_descriptor_parse_audio_selection_list:
+ * @descriptor: a %GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION #GstMpegtsDescriptor
+ * @list: (out) (transfer full) (element-type GstMpegtsAudioPreselectionDescriptor):
+ * the list of audio preselection
+ *
+ *
+ * Parses out a list of audio preselection from the @descriptor.
+ *
+ * Returns: %TRUE if the parsing happened correctly, else %FALSE.
+ */
+gboolean
+gst_mpegts_descriptor_parse_audio_preselection_list (const GstMpegtsDescriptor
+    * descriptor, GPtrArray ** list)
+{
+  guint8 *data;
+  guint8 i, num_preselections, num_aux_components, future_extension_length;
+  GstMpegtsAudioPreselectionDescriptor *item;
+
+  g_return_val_if_fail (descriptor != NULL && list != NULL, FALSE);
+  __common_desc_ext_check_base (descriptor,
+      GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION, FALSE);
+
+  *list = g_ptr_array_new_with_free_func ((GDestroyNotify)
+      gst_mpegts_descriptor_parse_audio_preselection_free);
+
+  data = (guint8 *) descriptor->data + 3;
+  num_preselections = (guint8) ((*data & 0xF8) >> 3);
+  data += 1;
+
+  for (i = 0; i < num_preselections; i++) {
+    item = g_slice_new0 (GstMpegtsAudioPreselectionDescriptor);
+    g_ptr_array_add (*list, item);
+
+    item->preselection_id = (*data & 0xF8) >> 3;
+    item->audio_rendering_indication = *data & 0x7;
+    data += 1;
+
+    item->audio_description = (*data & 0x80) >> 7;
+    item->spoken_subtitles = (*data & 0x40) >> 6;
+    item->dialogue_enhancement = (*data & 0x20) >> 5;
+    item->interactivity_enabled = (*data & 0x10) >> 4;
+    item->language_code_present = (*data & 0x08) >> 3;
+    item->text_label_present = (*data & 0x04) >> 2;
+    item->multi_stream_info_present = (*data & 0x02) >> 1;
+    item->future_extension = (*data) & 0x01;
+    data += 1;
+
+    if (item->language_code_present == 1) {
+      item->language_code = convert_lang_code (data);
+      data += 3;
+    }
+
+    if (item->text_label_present == 1) {
+      item->message_id = *data;
+      data += 1;
+    }
+
+    if (item->multi_stream_info_present == 1) {
+      num_aux_components = (*data & 0xE0) >> 5;
+      data += 1;
+      for (i = 0; i < num_aux_components; i++) {
+        data += 1;
+      }
+    }
+
+    if (item->future_extension == 1) {
+      future_extension_length = *data & 0x1F;
+      data += 1;
+      for (i = 0; i < future_extension_length; i++) {
+        data += 1;
+      }
+    }
+  }
+
+  return TRUE;
+}
+
+void gst_mpegts_descriptor_parse_audio_preselection_free
+    (GstMpegtsAudioPreselectionDescriptor * source)
+{
+  if (source->language_code_present == 1) {
+    g_free (source->language_code);
+  }
+  g_slice_free (GstMpegtsAudioPreselectionDescriptor, source);
+}
+
+void gst_mpegts_descriptor_parse_audio_preselection_dump
+    (GstMpegtsAudioPreselectionDescriptor * source)
+{
+  GST_DEBUG ("[Audio Preselection Descriptor]");
+  GST_DEBUG ("           preselection_id: 0x%02x", source->preselection_id);
+  GST_DEBUG ("audio_rendering_indication: 0x%02x",
+      source->audio_rendering_indication);
+  GST_DEBUG ("         audio_description: %d", source->audio_description);
+  GST_DEBUG ("          spoken_subtitles: %d", source->spoken_subtitles);
+  GST_DEBUG ("      dialogue_enhancement: %d", source->dialogue_enhancement);
+  GST_DEBUG ("     interactivity_enabled: %d", source->interactivity_enabled);
+  GST_DEBUG ("     language_code_present: %d", source->language_code_present);
+  GST_DEBUG ("        text_label_present: %d", source->text_label_present);
+  GST_DEBUG (" multi_stream_info_present: %d",
+      source->multi_stream_info_present);
+  GST_DEBUG ("          future_extension: %d", source->future_extension);
+
+  if (source->language_code_present == 1) {
+    GST_DEBUG ("             language_code: %s", source->language_code);
+  }
+  if (source->text_label_present == 1) {
+    GST_DEBUG ("                message_id: 0x%02x", source->message_id);
+  }
+  GST_DEBUG ("-------------------------------");
+}
index c68046b330a40c50f1ab6bb86ba98b71b8d624bb..f6b34c2e840fd0af784c35d1e51550a9fb99dc50 100644 (file)
@@ -152,6 +152,14 @@ typedef enum {
   GST_MTS_DESC_EXT_DVB_T2MI                     = 0x11,
   GST_MTS_DESC_EXT_DVB_URI_LINKAGE              = 0x13,
   GST_MTS_DESC_EXT_DVB_AC4                      = 0x15,
+  /**
+   * GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION:
+   *
+   * Provide all avaliable audio programme for user selection
+   *
+   * Since: 1.20
+   */
+  GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION       = 0x19
 } GstMpegtsDVBExtendedDescriptorType;
 
 /* GST_MTS_DESC_DVB_CAROUSEL_IDENTIFIER (0x13) */
@@ -1055,6 +1063,75 @@ GST_MPEGTS_API
 gboolean gst_mpegts_descriptor_parse_dvb_t2_delivery_system (const GstMpegtsDescriptor
               *descriptor, GstMpegtsT2DeliverySystemDescriptor ** res);
 
+/**
+ * GstMpegtsAudioPreselectionDescriptor:
+ * @preselection_id: 5-bit
+ * @audio_rendering_indication: 3-bit field
+ * @audio_description: visually impaired
+ * @spoken_subtitles:
+ * @dialogue_enhancement:
+ * @interactivity_enabled:
+ * @language_code_present:
+ * @text_label_present:
+ * @multi_stream_info_present: indicates if this PID conveys a complete audio programme
+ * @future_extension:
+ * @language_code: NULL terminated ISO 639 language code.
+ * @message_id:
+ * @items: (element-type GstMpegtsExtendedEventItem): the #GstMpegtsExtendedEventItem
+ * @text:
+ *
+ * Table 110: Audio Preselection Descriptor (ETSI EN 300 468 v1.16.1)
+ *
+ * Since: 1.20
+ */
+typedef struct _GstMpegtsAudioPreselectionDescriptor GstMpegtsAudioPreselectionDescriptor;
+struct _GstMpegtsAudioPreselectionDescriptor
+{
+  guint8                                preselection_id;
+  guint8                                audio_rendering_indication;
+  gboolean                              audio_description;
+  gboolean                              spoken_subtitles;
+  gboolean                              dialogue_enhancement;
+  gboolean                              interactivity_enabled;
+  gboolean                              language_code_present;
+  gboolean                              text_label_present;
+  gboolean                              multi_stream_info_present;
+  gboolean                              future_extension;
+  gchar                                 *language_code;
+  guint8                                message_id;
+};
+
+/**
+ * gst_mpegts_descriptor_parse_audio_preselection_list:
+ *
+ * Since: 1.20
+ */
+GST_MPEGTS_API
+gboolean
+gst_mpegts_descriptor_parse_audio_preselection_list (const GstMpegtsDescriptor
+    * descriptor, GPtrArray ** list);
+
+/**
+ * gst_mpegts_descriptor_parse_audio_preselection_free:
+ *
+ * Since: 1.20
+ */
+GST_MPEGTS_API
+void
+gst_mpegts_descriptor_parse_audio_preselection_free (GstMpegtsAudioPreselectionDescriptor
+    * source);
+
+/**
+ * gst_mpegts_descriptor_parse_audio_preselection_dump:
+ *
+ * Since: 1.20
+ */
+GST_MPEGTS_API
+void
+gst_mpegts_descriptor_parse_audio_preselection_dump (GstMpegtsAudioPreselectionDescriptor
+    * source);
+
+
 G_END_DECLS
 
 #endif                         /* GST_MPEGTS_DESCRIPTOR_H */
index 44f964a168a5912ba3eb6f46d8d35a6f1713cbc6..52665762f7ddb4d48bd08c6a274cf047310190e8 100644 (file)
@@ -1147,6 +1147,32 @@ gst_ts_demux_create_tags (TSDemuxStream * stream)
         g_free (lang_code);
       }
   }
+
+  if (bstream->stream_type == GST_MPEGTS_STREAM_TYPE_PRIVATE_PES_PACKETS) {
+    desc = mpegts_get_descriptor_from_stream_with_extension (bstream,
+        GST_MTS_DESC_DVB_EXTENSION, GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION);
+
+    if (desc) {
+      GPtrArray *list;
+      GstMpegtsAudioPreselectionDescriptor *item;
+
+      if (gst_mpegts_descriptor_parse_audio_preselection_list (desc, &list)) {
+        GST_DEBUG ("Found AUDIO PRESELECTION descriptor (%d entries)",
+            list->len);
+
+        for (i = 0; i < list->len; i++) {
+          item = g_ptr_array_index (list, i);
+          gst_mpegts_descriptor_parse_audio_preselection_dump (item);
+
+          if (item->language_code_present) {
+            add_iso639_language_to_tags (stream, item->language_code);
+            break;
+          }
+        }
+        g_ptr_array_unref (list);
+      }
+    }
+  }
 }
 
 static GstPad *