* 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;
}
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;
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)
{
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);
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;
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);
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;
/* 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);
}
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)
gint num_removed_date_ranges;
gchar **removed_date_ranges;
+#ifdef TIZEN_FEATURE_AD
+ GstM3U8AdInfo *ad_info;
+#endif
+
/*< private > */
GMutex lock;
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);