hldemux: parse cue tag to post ad info 84/319884/2 accepted/tizen/unified/20250220.093348 accepted/tizen/unified/x/20250221.101001
authorEunhye Choi <eunhae1.choi@samsung.com>
Wed, 19 Feb 2025 07:03:48 +0000 (16:03 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Wed, 19 Feb 2025 07:34:29 +0000 (16:34 +0900)
[Version] 1.24.11-5

parse EXT-T-CUE-OUT, EXT-T-CUE-IN, EXT-T-CUE-OUT-CONT tags
to post msg about ad info

Change-Id: I79c0c5d164040dfa1d7d619fe66af9b22304ac85

packaging/gstreamer.spec
subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c
subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.c
subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.h
subprojects/gst-plugins-good/meson.build

index 615f6bbb61c7ded96f7d7cb4c059cf80d8413e57..cd7c2750cbc0dbc070aedac8771037f91957e821 100644 (file)
@@ -60,7 +60,7 @@
 
 Name:           %{_name}
 Version:        1.24.11
-Release:        4
+Release:        5
 Summary:        Streaming-Media Framework Runtime
 License:        LGPL-2.0+
 Group:          Multimedia/Framework
index 113ea625d7bc111678574e1b0761b453fc684997..f4d5dea0d3ea08182eda755e02aa89fe91d6f61b 100644 (file)
@@ -781,6 +781,23 @@ gst_hls_demux_process_initial_manifest (GstAdaptiveDemux * demux,
    * is available to the baseclass at the start */
   gst_hls_demux_update_manifest (demux);
 
+#ifdef TIZEN_FEATURE_AD
+  if (variant) {
+    GST_DEBUG_OBJECT (hlsdemux, "post AD info");
+    gst_element_post_message (GST_ELEMENT_CAST (hlsdemux),
+        gst_message_new_element (GST_OBJECT_CAST (hlsdemux),
+          gst_structure_new ("adaptive-ad-info",
+            "ad-info", G_TYPE_POINTER, hlsdemux->main_playlist->ad_info, NULL)));
+
+    GST_DEBUG_OBJECT (hlsdemux, "post current bandwidth info : %d",
+                      variant->bandwidth);
+    gst_element_post_message (GST_ELEMENT_CAST (hlsdemux),
+        gst_message_new_element (GST_OBJECT_CAST (hlsdemux),
+          gst_structure_new (GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME,
+            "bitrate", G_TYPE_INT, variant->bandwidth, NULL)));
+  }
+#endif
+
   return TRUE;
 }
 
@@ -1074,12 +1091,12 @@ gst_hls_demux_update_manifest (GstAdaptiveDemux * demux)
         gst_hls_media_playlist_ref (hlsdemux->main_stream->playlist);
 
 #ifdef TIZEN_FEATURE_POST_VARIANT_INFO
-  GST_DEBUG_OBJECT (hlsdemux, "post variant info message");
-  gst_element_post_message (GST_ELEMENT_CAST (hlsdemux),
-      gst_message_new_element (GST_OBJECT_CAST (hlsdemux),
-          gst_structure_new (GST_ADAPTIVE_DEMUX_VARIANT_MESSAGE_NAME,
-              "video-variant-info", G_TYPE_POINTER,
-              hlsdemux->master->variant_info, NULL)));
+    GST_DEBUG_OBJECT (hlsdemux, "post variant info message");
+    gst_element_post_message (GST_ELEMENT_CAST (hlsdemux),
+        gst_message_new_element (GST_OBJECT_CAST (hlsdemux),
+            gst_structure_new (GST_ADAPTIVE_DEMUX_VARIANT_MESSAGE_NAME,
+                "video-variant-info", G_TYPE_POINTER,
+                hlsdemux->master->variant_info, NULL)));
 #endif
 
     return GST_FLOW_OK;
index 8a69f46baaed8b8ce64ad8781e76dae220f333d1..fe9118f6c224ad00cdc43cf872ca0af1cb9f6582 100644 (file)
@@ -47,6 +47,28 @@ static void
 gst_m3u8_media_segment_fill_partial_stream_times (GstM3U8MediaSegment *
     segment);
 
+#ifdef TIZEN_FEATURE_AD
+static GstM3U8Cue *
+gst_m3u8_cue_info_new (GstClockTime start_time, GstClockTime duration)
+{
+  GstM3U8Cue *ad;
+
+  ad = g_new0 (GstM3U8Cue, 1);
+  ad->start_time = start_time;
+  ad->end_time = 0;
+  ad->duration = duration;
+
+  return ad;
+}
+
+void
+gst_m3u8_cue_cont_free (GstM3U8CueOutCont * self)
+{
+  g_return_if_fail (self != NULL);
+  g_free (self->cont_data);
+}
+#endif
+
 GstHLSMediaPlaylist *
 gst_hls_media_playlist_ref (GstHLSMediaPlaylist * m3u8)
 {
@@ -73,6 +95,14 @@ gst_hls_media_playlist_unref (GstHLSMediaPlaylist * self)
     if (self->removed_date_ranges != NULL)
       g_strfreev (self->removed_date_ranges);
 
+#ifdef TIZEN_FEATURE_AD
+    if (self->ad_info) {
+      g_list_free (self->ad_info->cue);
+      g_list_free_full(self->ad_info->cue_cont, (GDestroyNotify) gst_m3u8_cue_cont_free);
+      g_free (self->ad_info);
+    }
+#endif
+
     g_free (self->last_data);
     g_mutex_clear (&self->lock);
     g_free (self);
@@ -438,6 +468,10 @@ gst_hls_media_playlist_new (const gchar * uri, const gchar * base_uri)
   m3u8->hold_back = GST_CLOCK_TIME_NONE;
   m3u8->part_hold_back = GST_CLOCK_TIME_NONE;
 
+#ifdef TIZEN_FEATURE_AD
+  m3u8->ad_info = g_new0 (GstM3U8AdInfo, 1);
+#endif
+
   g_mutex_init (&m3u8->lock);
   m3u8->ref_count = 1;
 
@@ -834,6 +868,9 @@ gst_hls_media_playlist_parse (gchar * data,
   GstM3U8MediaSegment *previous = NULL;
   GPtrArray *partial_segments = NULL;
   gboolean is_gap = FALSE;
+#ifdef TIZEN_FEATURE_AD
+  GstClockTime timestamp = 0;
+#endif
 
   GST_LOG ("playlist ts: %" GST_TIMEP_FORMAT, &playlist_ts);
   GST_LOG ("uri: %s", uri);
@@ -935,6 +972,10 @@ gst_hls_media_playlist_parse (gchar * data,
         if (last_init_file)
           file->init_file = gst_m3u8_init_file_ref (last_init_file);
 
+#ifdef TIZEN_FEATURE_AD
+        timestamp += duration;
+#endif
+
         file->partial_segments = partial_segments;
         partial_segments = NULL;
 
@@ -1162,6 +1203,65 @@ gst_hls_media_playlist_parse (gchar * data,
         /* Increment the current MSN by the number
          * of segments that were removed */
         mediasequence += self->skipped_segments;
+#ifdef TIZEN_FEATURE_AD
+      } else if (g_str_has_prefix (data_ext_x, "CUE-OUT:")) {
+        GstM3U8Cue *cue;
+        gdouble fval;
+
+        GST_LOG ("cue out: %" GST_TIME_FORMAT ", %s", GST_TIME_ARGS (timestamp), data);
+
+        data = data + strlen ("#EXT-X-CUE-OUT:");
+        if (g_str_has_prefix (data, "DURATION="))
+          data = data + strlen ("DURATION=");
+
+        if (!double_from_string (data, &data, &fval)) {
+          GST_WARNING ("Can't read CUE-OUT duration");
+          goto next_line;
+        }
+
+        duration = fval * (gdouble) GST_SECOND;
+
+        cue = gst_m3u8_cue_info_new (timestamp, duration);
+        GST_LOG ("cue out start %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT
+                      , GST_TIME_ARGS (cue->start_time), GST_TIME_ARGS (cue->duration));
+        self->ad_info->cue = g_list_append (self->ad_info->cue, cue);
+        duration = 0;
+      } else if (g_str_has_prefix (data_ext_x, "CUE-IN")) {
+        GList *cue;
+        GstM3U8Cue *cue_data;
+
+        GST_LOG ("cue in: %" GST_TIME_FORMAT ", %s", GST_TIME_ARGS (timestamp), data);
+
+        cue = g_list_last (self->ad_info->cue);
+        if (!cue || !(cue->data)) {
+          GST_WARNING ("there is no valid data");
+          goto next_line;
+        }
+
+        cue_data = cue->data;
+        GST_LOG ("start %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
+                GST_TIME_ARGS (cue_data->start_time), GST_TIME_ARGS (cue_data->duration));
+
+        if (cue_data->end_time != 0) {
+          GST_WARNING ("cue syntax error, skip this tag.");
+          goto next_line;
+        }
+
+        cue_data->end_time = timestamp;
+
+        GST_LOG ("cue start %" GST_TIME_FORMAT ", end %" GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
+                 GST_TIME_ARGS (cue_data->start_time), GST_TIME_ARGS (cue_data->end_time),
+                 GST_TIME_ARGS (cue_data->duration));
+      } else if (g_str_has_prefix (data_ext_x, "CUE-OUT-CONT:")) {
+        GstM3U8CueOutCont *cont = g_new0 (GstM3U8CueOutCont, 1);
+
+        GST_LOG ("cue cont: %" GST_TIME_FORMAT ", %s", GST_TIME_ARGS (timestamp), data);
+
+        data = data + strlen ("#EXT-X-CUE-OUT-CONT:");
+        cont->timestamp = timestamp;
+        cont->cont_data = g_strdup (data);
+        self->ad_info->cue_cont = g_list_append (self->ad_info->cue_cont, cont);
+#endif
       } else {
         GST_LOG ("Ignored line: %s", data);
       }
index 9216fc04b250ab05e796e24d4ce7311f8a5692d7..662271378e65f02bde88593dfc70252abc697b36 100644 (file)
@@ -48,6 +48,11 @@ typedef struct _GstHLSRenditionStream GstHLSRenditionStream;
 typedef struct _GstM3U8Client GstM3U8Client;
 typedef struct _GstHLSVariantStream GstHLSVariantStream;
 typedef struct _GstHLSMasterPlaylist GstHLSMasterPlaylist;
+#ifdef TIZEN_FEATURE_AD
+typedef struct _GstM3U8AdInfo GstM3U8AdInfo;
+typedef struct _GstM3U8Cue GstM3U8Cue;
+typedef struct _GstM3U8CueOutCont GstM3U8CueOutCont;
+#endif
 
 #define GST_HLS_MEDIA_PLAYLIST(m) ((GstHLSMediaPlaylist*)m)
 #define GST_M3U8_MEDIA_SEGMENT(f) ((GstM3U8MediaSegment*)f)
@@ -152,6 +157,10 @@ struct _GstHLSMediaPlaylist
   gint num_removed_date_ranges;
   gchar **removed_date_ranges;
 
+#ifdef TIZEN_FEATURE_AD
+  GstM3U8AdInfo *ad_info;
+#endif
+
   /*< private > */
   GMutex lock;
 
@@ -268,6 +277,27 @@ struct _GstM3U8InitFile
   guint ref_count;      /* ATOMIC */
 };
 
+#ifdef TIZEN_FEATURE_AD
+struct _GstM3U8Cue
+{
+  GstClockTime start_time;      /* EXT-X-CUE-OUT */
+  GstClockTime end_time;        /* EXT-X-CUE-IN */
+  GstClockTime duration;        /* from EXT-X-CUE-OUT */
+};
+
+struct _GstM3U8CueOutCont
+{
+  GstClockTime timestamp;
+  gchar *cont_data;             /* EXT-X-CUE-OUT-CONT */
+};
+
+struct _GstM3U8AdInfo
+{
+  GList *cue;                   /* GstM3U8Cue */
+  GList *cue_cont;              /* GstM3U8CueOutCont */
+};
+#endif
+
 GstM3U8InitFile *gst_m3u8_init_file_ref (GstM3U8InitFile * ifile);
 void gst_m3u8_init_file_unref (GstM3U8InitFile * ifile);
 gboolean gst_m3u8_init_file_equal (const GstM3U8InitFile * ifile1, const GstM3U8InitFile *ifile2);
index db7e1d849c757ba4cf1d886eb898276a9816059e..1a6b6c3a46923cea2ed57714b76bbb2d374079b7 100644 (file)
@@ -477,6 +477,7 @@ cdata.set('TIZEN_FEATURE_GST_MUX_ENHANCEMENT', true)
 cdata.set('TIZEN_FEATURE_V4L2_DISABLE_COLORIMETRY', true)
 cdata.set('TIZEN_FEATURE_POST_VARIANT_INFO', true)
 cdata.set('TIZEN_FEATURE_ADAPTIVE_VARIANT_LIMIT', true)
+cdata.set('TIZEN_FEATURE_AD', true)
 cdata.set('TIZEN_FEATURE_BUG_FIX', true)
 cdata.set('TIZEN_FEATURE_V4L2_ENCODER_SET_MAX_LEVEL', true)
 cdata.set('TIZEN_FEATURE_RTPH264PAY_MODIFICATION', true)