tizen 2.3 release
[framework/multimedia/gst-plugins-ext0.10.git] / hlsdemux2 / src / gsthlsdemux2.c
1 /*
2  * hlsdemux2
3  *
4  * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, Naveen Cherukuri <naveen.ch@samsung.com>
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  * Alternatively, the contents of this file may be used under the
27  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
28  * which case the following provisions apply instead of the ones
29  * mentioned above:
30  *
31  * This library is free software; you can redistribute it and/or
32  * modify it under the terms of the GNU Library General Public
33  * License as published by the Free Software Foundation; either
34  * version 2 of the License, or (at your option) any later version.
35  *
36  * This library is distributed in the hope that it will be useful,
37  * but WITHOUT ANY WARRANTY; without even the implied warranty of
38  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39  * Library General Public License for more details.
40  *
41  * You should have received a copy of the GNU Library General Public
42  * License along with this library; if not, write to the
43  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
44  * Boston, MA 02111-1307, USA.
45  */
46
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50
51 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
52  * with newer GLib versions (>= 2.31.0) */
53 #define GLIB_DISABLE_DEPRECATION_WARNINGS
54
55 #include <string.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <gst/tag/tag.h>
59 #include <fcntl.h>
60 #include <unistd.h>
61 #include <gst/gst.h>
62
63 #include "gsthlsdemux2.h"
64
65 enum
66 {
67   PROP_0,
68   PROP_BITRATE_SWITCH_TOLERANCE,
69   PROP_FORCE_LOWER_BITRATE,
70   PROP_BLOCKSIZE,
71   PROP_LAST
72 };
73
74 #define HLS_VIDEO_CAPS \
75   GST_STATIC_CAPS (\
76     "video/mpeg, " \
77       "mpegversion = (int) { 1, 2, 4 }, " \
78       "systemstream = (boolean) FALSE; " \
79     "video/x-h264,stream-format=(string)byte-stream," \
80       "alignment=(string)nal;" \
81     "video/x-dirac;" \
82     "video/x-wmv," \
83       "wmvversion = (int) 3, " \
84       "format = (fourcc) WVC1" \
85   )
86
87 #define HLS_AUDIO_CAPS \
88   GST_STATIC_CAPS ( \
89     "audio/mpeg, " \
90       "mpegversion = (int) { 1, 4 };" \
91     "audio/x-lpcm, " \
92       "width = (int) { 16, 20, 24 }, " \
93       "rate = (int) { 48000, 96000 }, " \
94       "channels = (int) [ 1, 8 ], " \
95       "dynamic_range = (int) [ 0, 255 ], " \
96       "emphasis = (boolean) { FALSE, TRUE }, " \
97       "mute = (boolean) { FALSE, TRUE }; " \
98     "audio/x-ac3; audio/x-eac3;" \
99     "audio/x-dts;" \
100     "audio/x-private-ts-lpcm;" \
101     "application/x-id3" \
102   )
103
104 /* Can also use the subpicture pads for text subtitles? */
105 #define HLS_SUBPICTURE_CAPS \
106     GST_STATIC_CAPS ("subpicture/x-pgs; video/x-dvd-subpicture")
107
108 static GstStaticPadTemplate hlsdemux2_sink_template =
109 GST_STATIC_PAD_TEMPLATE ("sink",
110     GST_PAD_SINK,
111     GST_PAD_ALWAYS,
112     GST_STATIC_CAPS ("application/x-hls"));
113
114 static GstStaticPadTemplate hlsdemux2_videosrc_template =
115 GST_STATIC_PAD_TEMPLATE ("video",
116     GST_PAD_SRC,
117     GST_PAD_SOMETIMES,
118     HLS_VIDEO_CAPS);
119
120 static GstStaticPadTemplate hlsdemux2_audiosrc_template =
121 GST_STATIC_PAD_TEMPLATE ("audio",
122     GST_PAD_SRC,
123     GST_PAD_SOMETIMES,
124     HLS_AUDIO_CAPS);
125
126 static GstStaticPadTemplate hlsdemux2_subpicture_template =
127 GST_STATIC_PAD_TEMPLATE ("subpicture",
128     GST_PAD_SRC,
129     GST_PAD_SOMETIMES,
130     HLS_SUBPICTURE_CAPS);
131
132 static GstStaticPadTemplate hlsdemux2_private_template =
133 GST_STATIC_PAD_TEMPLATE ("private",
134     GST_PAD_SRC,
135     GST_PAD_SOMETIMES,
136     GST_STATIC_CAPS_ANY);
137
138 GST_DEBUG_CATEGORY_STATIC (gst_hlsdemux2_debug);
139 #define GST_CAT_DEFAULT gst_hlsdemux2_debug
140
141 GST_DEBUG_CATEGORY (hlsdemux2_m3u8_debug);
142
143 static const float update_interval_factor[] = { 1, 0.5, 1.5, 3 };
144
145 #define HLS_DEFAULT_FRAME_DURATION (0.04 * GST_SECOND) // 40ms
146 #define DEFAULT_BLOCKSIZE (8 * 1024) // 8 kbytes
147 #define DEFAULT_FAST_SWITCH_BUFFER_SIZE 0.7 // factor
148 static void _do_init (GType type)
149 {
150   GST_DEBUG_CATEGORY_INIT (gst_hlsdemux2_debug, "hlsdemux2", 0, "hlsdemux2 element");
151   GST_DEBUG_CATEGORY_INIT (hlsdemux2_m3u8_debug, "hlsdemux2m3u8", 0, "m3u8 parser");
152 }
153
154 GST_BOILERPLATE_FULL (GstHLSDemux2, gst_hlsdemux2, GstElement, GST_TYPE_ELEMENT, _do_init);
155
156 #define DEFAULT_BITRATE_SWITCH_TOLERANCE 0.4
157 #define DEFAULT_FAILED_COUNT 3
158 #define DEFAULT_TARGET_DURATION 10
159 #define DEFAULT_NUM_FRAGMENTS_CACHE 3
160 #define DEFAULT_TOTAL_CACHE_DURATION (DEFAULT_NUM_FRAGMENTS_CACHE * DEFAULT_TARGET_DURATION * GST_SECOND)
161
162 #define PREDEFINED_VIDEO_FRAME_LOCATION "/usr/etc/sec_audio_fixed_qvga.264"
163 //#define PREDEFINED_VIDEO_FRAME_LOCATION "/usr/etc/blackframe_QVGA.264"
164 #define PREDEFINED_IMAGE_FRAME_LOCATION "/usr/etc/sec_audio_fixed_qvga.jpg"
165
166 #define HLSDEMUX2_SOUP_FAILED_CNT 10
167 #define DEFAULT_FORCE_LOWER_BITRATE FALSE
168 #define FORCE_LOW_BITRATE_AFTER_CNT 4
169 #define HLSDEMUX2_HTTP_TIMEOUT 30 //30sec
170
171 enum {
172   HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE = 0,
173   HLSDEMUX2_HTTP_ERROR_RECOVERABLE = 1,
174 };
175
176 typedef struct _HLSDemux2_HTTP_error HLSDemux2_HTTP_error;
177
178 typedef gboolean (*HLS_HTTP_error_handle_function) (GstHLSDemux2 *demux, gchar *element_name);
179
180 struct _HLSDemux2_HTTP_error {
181   guint HTTP_error_code;
182   const gchar *error_phrase;
183   guint error_type;
184   HLS_HTTP_error_handle_function handle_error;
185 };
186
187 struct _GstHLSDemux2PvtStream
188 {
189   void *parent;
190   GstPad *sinkpad;
191   GstElement *sink;
192   gulong sink_eprobe;
193   gulong sink_bprobe;
194   HLSDEMUX2_STREAM_TYPE type;
195   GValue      codec_type;
196   GstBuffer  *id3_buffer;
197   GstBuffer  *image_buffer;
198   GstBuffer  *video_buffer;
199   gboolean    got_img_buffer;
200   GstElement *convert_pipe;
201   GCond      *img_load_cond;
202   GMutex     *img_load_lock;
203   GCond      *convert_cond;
204   GMutex     *convert_lock;
205 };
206
207 struct _GstHLSDemux2Stream
208 {
209   void *parent;
210   GstPad *pad;
211   GQueue *queue;
212   GMutex *queue_lock;
213   GCond *queue_full;
214   GCond *queue_empty;
215   gint64 percent;
216   HLSDEMUX2_STREAM_TYPE type;
217   gboolean is_linked;
218   gboolean eos;
219   gboolean apply_disc;
220   gint64 cached_duration;
221   GThread *dummy_data_thread; /* for pushing dummy video data */
222   GstClockTime base_ts; /* base ts start */
223   GstClockTime fts; /* first valid timestamp in a fragment */
224   GstClockTime lts; /* last valid timestamp in a fragment */
225   /* expected first timestamp in next fragment : usefule for handling fragments discontinuities*/
226   GstClockTime nts;
227   GstClockTime prev_nts; /* stores last nts for handling .aac files */
228   gboolean valid_fts_rcvd;
229   GstClockTime cdisc; /* current disc time */
230   GstClockTime frame_duration;
231   guint64 total_stream_time;
232   GstClockTime total_disc;
233   GQueue *downloader_queue;
234   gboolean need_newsegment;
235   GstEvent *newsegment;
236 };
237
238 /* GStreamer virtual functions */
239 static void gst_hlsdemux2_set_property (GObject * object, guint prop_id,
240     const GValue * value, GParamSpec * pspec);
241 static void gst_hlsdemux2_get_property (GObject * object, guint prop_id,
242     GValue * value, GParamSpec * pspec);
243 static gboolean gst_hlsdemux2_sink_event (GstPad * pad, GstEvent * event);
244 static GstStateChangeReturn gst_hlsdemux2_change_state (GstElement * element, GstStateChange transition);
245 static void gst_hlsdemux2_dispose (GObject * obj);
246 static GstFlowReturn gst_hlsdemux2_chain (GstPad * pad, GstBuffer * buf);
247 static gboolean gst_hlsdemux2_handle_src_event (GstPad * pad, GstEvent * event);
248
249 /* init & de-init functions */
250 static void gst_hlsdemux2_private_init (GstHLSDemux2 *demux);
251 static void gst_hlsdemux2_private_deinit (GstHLSDemux2 *demux);
252 static void gst_hlsdemux2_playlist_downloader_init (GstHLSDemux2 *demux);
253 static void gst_hlsdemux2_playlist_downloader_deinit (GstHLSDemux2 *demux);
254 static void gst_hlsdemux2_key_downloader_init (GstHLSDemux2 *demux);
255 static void gst_hlsdemux2_key_downloader_deinit (GstHLSDemux2 *demux);
256 static void gst_hlsdemux2_fragment_downloader_init (GstHLSDemux2 *demux);
257 static void gst_hlsdemux2_fragment_downloader_deinit (GstHLSDemux2 *demux);
258
259 /* helper functions */
260 static void gst_hlsdemux2_stop (GstHLSDemux2 * demux);
261 static gboolean gst_hlsdemux2_set_location (GstHLSDemux2 * demux, const gchar * uri);
262 static gchar *gst_hlsdemux2_src_buf_to_utf8_playlist (GstBuffer * buf);
263 static void gst_hlsdemux2_new_pad_added (GstElement *element, GstPad *pad, gpointer data);
264 static void gst_hlsdemux2_get_cookies(GstHLSDemux2 *demux);
265 static void gst_hlsdemux2_get_user_agent(GstHLSDemux2 *demux);
266 static gboolean gst_hlsdemux2_update_playlist (GstHLSDemux2 * demux, gboolean update, gboolean *is_error);
267 static gboolean gst_hlsdemux2_schedule (GstHLSDemux2 * demux);
268 static void gst_hlsdemux2_calculate_pushed_duration (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
269     GstBuffer *inbuf);
270
271 /* stream specific functions */
272 static void gst_hlsdemux2_stream_init (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
273     HLSDEMUX2_STREAM_TYPE stream_type, gchar *name, GstCaps *src_caps);
274 static void gst_hlsdemux2_stream_deinit (GstHLSDemux2Stream *stream, gpointer data);
275 static void gst_hlsdemux2_stop_stream (GstHLSDemux2 *demux);
276 static HLSDemux2SinkBin *gst_hlsdemux2_create_stream (GstHLSDemux2 *demux, gchar *name, GstCaps *caps);
277
278 /* task functions */
279 static void gst_hlsdemux2_push_loop (GstHLSDemux2Stream *stream);
280 static void gst_hlsdemux2_fragment_download_loop (GstHLSDemux2 * demux);
281
282 /* playlist download related functions */
283 static void gst_hlsdemux2_on_playlist_buffer (GstElement * appsink, void* data);
284 static GstBusSyncReply gst_hlsdemux2_playlist_download_bus_sync_cb (GstBus * bus, GstMessage *msg, gpointer data);
285
286 /* key file download related functions */
287 static gboolean gst_hlsdemux2_key_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data);
288 static void gst_hlsdemux2_on_key_buffer (GstElement *appsink, void *data);
289
290 /* fragment download related functions */
291 static gboolean gst_hlsdemux2_fragment_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data);
292 static void gst_hlsdemux2_downloader_new_buffer (GstElement *appsink, void *user_data);
293 static void gst_hlsdemux2_downloader_eos (GstElement * appsink, void* user_data);
294
295 /* probe functions */
296 static gboolean gst_hlsdemux2_sink_event_handler (GstPad * pad, GstEvent * event, gpointer data);
297 static gboolean gst_hlsdemux2_change_playlist (GstHLSDemux2 * demux, guint max_bitrate, gboolean *is_switched);
298 static gboolean gst_hlsdemux2_download_monitor_thread (GstHLSDemux2 *demux);
299 static void gst_hlsdemux2_push_eos (GstHLSDemux2 *demux);
300 static void gst_hlsdemux2_apply_disc (GstHLSDemux2 * demux);
301 static gboolean gst_hlsdemux2_queue_buffer_handler (GstPad * pad, GstBuffer *buffer, gpointer data);
302 static gboolean hlsdemux2_HTTP_not_found(GstHLSDemux2 *demux, gchar *element_name);
303 static gboolean hlsdemux2_HTTP_time_out (GstHLSDemux2 *demux, gchar *element_name);
304 static gboolean hlsdemux2_HTTP_repeat_request (GstHLSDemux2 *demux, gchar *element_name);
305 static void gst_hlsdemux2_handle_private_pad (GstHLSDemux2 *demux, GstPad *srcpad);
306 static void gst_hlsdemux2_private_sink_on_new_buffer (GstElement *appsink, void *user_data);
307 static void gst_hlsdemux2_private_sink_on_eos (GstElement * appsink, void* user_data);
308 static gboolean gst_hlsdemux2_imagebuf_pipe_bus_cb (GstBus *bus, GstMessage *msg, gpointer data);
309 static gboolean gst_hlsdemux2_set_video_buffer (GstPad * srcpad, GstBuffer * buffer, gpointer user_data);
310 static gboolean gst_hlsdemux2_done_video_buffer (GstPad * srcpad, GstEvent * event, gpointer user_data);
311 static gboolean gst_hlsdemux2_check_fast_switch (GstHLSDemux2 *demux);
312
313 static const HLSDemux2_HTTP_error http_errors[] = {
314
315   /* transport errors by libsoup */
316   { 1, "Cancelled", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
317   { 2, "Cannot resolve hostname", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
318   { 3, "Cannot resolve proxy hostname", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
319   { 4, "Cannot connect to destination", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_repeat_request },
320   { 5, "Cannot connect to proxy", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_repeat_request },
321   { 6, "SSL handshake failed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
322   { 7, "Connection terminated unexpectedly", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
323   { 8, "Message Corrupt", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
324   { 9, "Too many redirects", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
325
326   /* Client error */
327   { 400, "Bad Request", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
328   { 401, "Unauthorized", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
329   { 402, "Payment Required", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
330   { 403, "Forbidden", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_repeat_request }, // TODO: Currently taking it as recoverable for testing
331   { 404, "Not Found", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_not_found },
332   { 405, "Method Not Allowed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
333   { 406, "Not Acceptable", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
334   { 407, "Proxy Authentication Required", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
335   { 408, "Request Timeout", HLSDEMUX2_HTTP_ERROR_RECOVERABLE, hlsdemux2_HTTP_time_out },
336   { 409, "Conflict", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
337   { 410, "Gone", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
338   { 411, "Length Required", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
339   { 412, "Precondition Failed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
340   { 413, "Request Entity Too Large", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
341   { 414, "Request-URI Too Long", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
342   { 415, "Unsupported Media Type", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
343   { 416, "Requested Range Not Satisfiable", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
344   { 417, "Expectation Failed", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
345   { 418, "Unprocessable Entity", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
346   { 419, "Locked", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
347   { 420, "Failed Dependency", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
348
349   /* Server error */
350   { 500, "Internal Server Error", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
351   { 501, "Not Implemented", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
352   { 502, "Bad Gateway", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
353   { 503, "Service Unavailable", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL }, // TODO: need to make as recoverable with timout value
354   { 504, "Gateway Timeout", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
355   { 505, "HTTP Version Not Supported", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
356   { 506, "Insufficient Storage", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
357   { 507, "Not Extended", HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE, NULL },
358 };
359
360
361 static void
362 gst_hlsdemux2_base_init (gpointer g_class)
363 {
364   GstElementClass *element_class= GST_ELEMENT_CLASS (g_class);
365
366   gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_videosrc_template));
367   gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_audiosrc_template));
368   gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_subpicture_template));
369   gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&hlsdemux2_sink_template));
370
371   gst_element_class_set_details_simple (element_class,
372       "HLS Demuxer2",
373       "Demuxer/URIList",
374       "HTTP Live Streaming (HLS) demuxer",
375       "Naveen Cherukuri<naveen.ch@samsung.com>");
376 }
377
378 static void
379 gst_hlsdemux2_class_init (GstHLSDemux2Class * klass)
380 {
381   GObjectClass *gobject_class;
382   GstElementClass *gstelement_class;
383
384   gobject_class = (GObjectClass *) klass;
385   gstelement_class = (GstElementClass *) klass;
386
387   gobject_class->set_property = gst_hlsdemux2_set_property;
388   gobject_class->get_property = gst_hlsdemux2_get_property;
389   gobject_class->dispose = gst_hlsdemux2_dispose;
390
391   g_object_class_install_property (gobject_class, PROP_BITRATE_SWITCH_TOLERANCE,
392       g_param_spec_float ("bitrate-switch-tolerance",
393           "Bitrate switch tolerance",
394           "Tolerance with respect of the fragment duration to switch to "
395           "a different bitrate if the client is too slow/fast.",
396           0, 1, DEFAULT_BITRATE_SWITCH_TOLERANCE,
397           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
398
399   g_object_class_install_property (gobject_class, PROP_FORCE_LOWER_BITRATE,
400       g_param_spec_boolean ("force-low-bitrate",
401           "forcing lower variant", "forcing lower variant after every few fragments [for debugging purpose only]",
402           DEFAULT_FORCE_LOWER_BITRATE,
403           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
404
405   g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
406       g_param_spec_ulong ("blocksize", "Block size",
407           "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG,
408           DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
409
410   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_hlsdemux2_change_state);
411 }
412
413 static void
414 gst_hlsdemux2_init (GstHLSDemux2 * demux, GstHLSDemux2Class * klass)
415 {
416   /* sink pad */
417   demux->sinkpad = gst_pad_new_from_static_template (&hlsdemux2_sink_template, "sink");
418   gst_pad_set_chain_function (demux->sinkpad, GST_DEBUG_FUNCPTR (gst_hlsdemux2_chain));
419   gst_pad_set_event_function (demux->sinkpad, GST_DEBUG_FUNCPTR (gst_hlsdemux2_sink_event));
420   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
421
422   gst_hlsdemux2_private_init (demux);
423
424   /* fragment downloader init */
425   gst_hlsdemux2_fragment_downloader_init (demux);
426
427   /* playlist downloader init */
428   gst_hlsdemux2_playlist_downloader_init (demux);
429
430   /* key downloader init */
431   gst_hlsdemux2_key_downloader_init (demux);
432
433 }
434
435 static void
436 gst_hlsdemux2_dispose (GObject * obj)
437 {
438   GstHLSDemux2 *demux = GST_HLSDEMUX2 (obj);
439
440   GST_INFO_OBJECT (demux,"entering");
441
442   gst_hlsdemux2_stop (demux);
443
444   gst_hlsdemux2_private_deinit (demux);
445
446   gst_hlsdemux2_fragment_downloader_deinit (demux);
447
448   gst_hlsdemux2_playlist_downloader_deinit (demux);
449
450   gst_hlsdemux2_key_downloader_deinit (demux);
451
452   GST_INFO_OBJECT (demux,"leaving");
453
454   G_OBJECT_CLASS (parent_class)->dispose (obj);
455 }
456
457 static void
458 gst_hlsdemux2_private_init (GstHLSDemux2 *demux)
459 {
460   demux->is_live = TRUE;
461   demux->bitrate_switch_tol = DEFAULT_BITRATE_SWITCH_TOLERANCE;
462   demux->percent = 100;
463   demux->active_stream_cnt = 0;
464   demux->download_task = NULL;
465   demux->pl_update_lock = g_mutex_new ();
466   demux->pl_update_cond = g_cond_new ();
467   demux->cancelled = FALSE;
468   demux->total_cache_duration = DEFAULT_TOTAL_CACHE_DURATION;
469   demux->target_duration = DEFAULT_TARGET_DURATION;
470   demux->keyCookie = NULL;
471   demux->playlistCookie = NULL;
472   demux->fragCookie = NULL;
473   demux->lastCookie = NULL;
474   demux->keyDomain = NULL;
475   demux->playlistDomain = NULL;
476   demux->fragDomain = NULL;
477   demux->lastDomain = NULL;
478   demux->user_agent = NULL;
479   demux->buffering_lock = g_mutex_new ();
480   demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
481   demux->force_lower_bitrate = DEFAULT_FORCE_LOWER_BITRATE;
482   demux->cfrag_dur = 0;
483   demux->error_posted = FALSE;
484   demux->playlist_uri = NULL;
485   demux->frag_uri = NULL;
486   demux->key_uri = NULL;
487   demux->blocksize = DEFAULT_BLOCKSIZE;
488   demux->flushing = FALSE;
489   demux->ns_start = 0;
490   demux->cur_audio_fts = GST_CLOCK_TIME_NONE;
491   demux->is_buffering = TRUE;
492   demux->buffering_posting_thread = NULL;
493   demux->post_msg_lock = g_mutex_new ();
494   demux->post_msg_start = g_cond_new ();
495   demux->post_msg_exit = g_cond_new ();
496   demux->stream_config = HLSDEMUX2_SINGLE_VARIANT;
497   demux->has_image_buffer = FALSE;
498   demux->prev_image_buffer = NULL;
499   demux->prev_video_buffer = NULL;
500   demux->private_stream = NULL;
501 }
502
503 static void
504 gst_hlsdemux2_private_deinit (GstHLSDemux2 *demux)
505 {
506   demux->end_of_playlist = FALSE;
507
508   if (demux->pl_update_lock) {
509     g_mutex_free (demux->pl_update_lock);
510     demux->pl_update_lock = NULL;
511   }
512
513   if (demux->pl_update_cond) {
514     g_cond_free (demux->pl_update_cond);
515     demux->pl_update_cond = NULL;
516   }
517
518   if (demux->buffering_lock) {
519     g_mutex_free (demux->buffering_lock);
520     demux->buffering_lock = NULL;
521   }
522
523   if (demux->user_agent) {
524     g_free (demux->user_agent);
525     demux->user_agent = NULL;
526   }
527
528   if (demux->playlist) {
529     gst_buffer_unref (demux->playlist);
530     demux->playlist = NULL;
531   }
532
533   if (demux->fragCookie) {
534     g_strfreev (demux->fragCookie);
535     demux->fragCookie = NULL;
536   }
537
538   if (demux->keyCookie) {
539     g_strfreev (demux->keyCookie);
540     demux->keyCookie = NULL;
541   }
542
543   if (demux->lastCookie) {
544     g_strfreev (demux->lastCookie);
545     demux->lastCookie = NULL;
546   }
547
548   if (demux->playlistCookie) {
549     g_strfreev (demux->playlistCookie);
550     demux->playlistCookie = NULL;
551   }
552
553   if (demux->fragDomain) {
554     g_free (demux->fragDomain);
555     demux->fragDomain = NULL;
556   }
557
558   if (demux->keyDomain) {
559     g_free (demux->keyDomain);
560     demux->keyDomain = NULL;
561   }
562
563   if (demux->lastDomain) {
564     g_free (demux->lastDomain);
565     demux->lastDomain = NULL;
566   }
567
568   if (demux->playlistDomain) {
569     g_free (demux->playlistDomain);
570     demux->playlistDomain = NULL;
571   }
572
573   if (demux->playlist_uri) {
574     g_free (demux->playlist_uri);
575     demux->playlist_uri = NULL;
576   }
577
578   if (demux->key_uri) {
579     g_free (demux->key_uri);
580     demux->key_uri = NULL;
581   }
582
583   if (demux->frag_uri) {
584     g_free (demux->frag_uri);
585     demux->frag_uri = NULL;
586   }
587
588   if (demux->prev_image_buffer) {
589     gst_buffer_unref (demux->prev_image_buffer);
590     demux->prev_image_buffer = NULL;
591   }
592
593   if (demux->prev_video_buffer) {
594     gst_buffer_unref (demux->prev_video_buffer);
595     demux->prev_video_buffer = NULL;
596   }
597
598   if (demux->private_stream) {
599     g_free (demux->private_stream);
600     demux->private_stream = NULL;
601   }
602
603   if (demux->client) {
604     gst_m3u8_client_free (demux->client);
605     demux->client = NULL;
606   }
607 }
608
609 static void
610 gst_hlsdemux2_fragment_downloader_init (GstHLSDemux2 *demux)
611 {
612   demux->fdownloader = g_new0 (HLSDemux2FragDownloader, 1);
613   demux->fdownloader->pipe = NULL;
614   demux->fdownloader->urisrc = NULL;
615   demux->fdownloader->queue = NULL;
616   demux->fdownloader->typefind = NULL;
617   demux->fdownloader->demuxer = NULL;
618   demux->fdownloader->sinkbins = NULL;
619   demux->fdownloader->lock = g_mutex_new ();
620   demux->fdownloader->cond = g_cond_new ();
621   demux->fdownloader->is_encrypted = FALSE;
622   demux->fdownloader->content_size = 0;
623   demux->fdownloader->get_next_frag = FALSE;
624   demux->fdownloader->applied_fast_switch = FALSE;
625   demux->fdownloader->remaining_data = NULL;
626   demux->fdownloader->remaining_size = 0;
627   demux->fdownloader->first_buffer = TRUE;
628   demux->fdownloader->cur_stream_cnt = 0;
629   demux->fdownloader->force_timestamps = FALSE;
630   demux->fdownloader->error_rcvd = FALSE;
631   demux->fdownloader->find_mediaseq = FALSE;
632   demux->fdownloader->seeked_pos = 0;
633   demux->fdownloader->cur_running_dur = 0;
634   demux->fdownloader->download_rate = -1;
635   demux->fdownloader->download_start_ts = 0;
636   demux->fdownloader->download_stop_ts = 0;
637   demux->fdownloader->src_downloaded_size = 0;
638   demux->fdownloader->queue_downloaded_size = 0;
639   demux->fdownloader->ndownloaded = 0;
640   demux->fdownloader->chunk_downloaded_size = 0;
641   demux->fdownloader->chunk_start_ts = 0;
642   demux->fdownloader->avg_chunk_drates = g_array_new(FALSE, TRUE, sizeof(guint64));
643   demux->fdownloader->avg_frag_drates = g_array_new(FALSE, TRUE, sizeof(guint64));
644 }
645
646 static void
647 gst_hlsdemux2_fragment_downloader_deinit (GstHLSDemux2 *demux)
648 {
649   if (!demux->fdownloader)
650     return;
651
652   /* free fragment downloader structure */
653   if (demux->fdownloader->lock) {
654     g_mutex_free (demux->fdownloader->lock);
655     demux->fdownloader->lock = NULL;
656   }
657
658   if (demux->fdownloader->cond) {
659     g_cond_free (demux->fdownloader->cond);
660     demux->fdownloader->cond = NULL;
661   }
662
663   if (demux->fdownloader->remaining_data) {
664     g_free (demux->fdownloader->remaining_data);
665     demux->fdownloader->remaining_data = NULL;
666   }
667
668   if (demux->fdownloader->avg_chunk_drates) {
669     g_array_free(demux->fdownloader->avg_chunk_drates, TRUE);
670     demux->fdownloader->avg_chunk_drates = NULL;
671   }
672
673   if (demux->fdownloader->avg_frag_drates) {
674     g_array_free(demux->fdownloader->avg_frag_drates, TRUE);
675     demux->fdownloader->avg_frag_drates = NULL;
676   }
677
678   g_free (demux->fdownloader);
679   demux->fdownloader = NULL;
680 }
681
682 static void
683 gst_hlsdemux2_playlist_downloader_init (GstHLSDemux2 *demux)
684 {
685   demux->pldownloader = g_new0 (HLSDemux2PLDownloader, 1);
686   demux->pldownloader->pipe = NULL;
687   demux->pldownloader->bus = NULL;
688   demux->pldownloader->urisrc = NULL;
689   demux->pldownloader->sink = NULL;
690   demux->pldownloader->lock = g_mutex_new ();
691   demux->pldownloader->cond = g_cond_new ();
692   demux->pldownloader->playlist = NULL;
693   demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
694 }
695
696 static void
697 gst_hlsdemux2_playlist_downloader_deinit (GstHLSDemux2 *demux)
698 {
699   if (!demux->pldownloader)
700     return;
701
702   /* free playlist downloader structure */
703   if (demux->pldownloader->lock) {
704     g_mutex_free (demux->pldownloader->lock);
705     demux->pldownloader->lock = NULL;
706   }
707
708   if (demux->pldownloader->cond) {
709     g_cond_free (demux->pldownloader->cond);
710     demux->pldownloader->cond = NULL;
711   }
712
713   if (demux->pldownloader->playlist){
714     gst_buffer_unref (demux->pldownloader->playlist);
715     demux->pldownloader->playlist = NULL;
716   }
717
718   g_free (demux->pldownloader);
719   demux->pldownloader = NULL;
720 }
721
722 static void
723 gst_hlsdemux2_key_downloader_init (GstHLSDemux2 *demux)
724 {
725   demux->kdownloader = g_new0 (HLSDemux2KeyDownloader, 1);
726   demux->kdownloader->pipe = NULL;
727   demux->kdownloader->bus = NULL;
728   demux->kdownloader->urisrc = NULL;
729   demux->kdownloader->sink = NULL;
730   demux->kdownloader->lock = g_mutex_new ();
731   demux->kdownloader->cond = g_cond_new ();
732   demux->kdownloader->key = NULL;
733   demux->kdownloader->prev_key_uri = NULL;
734 }
735
736 static void
737 gst_hlsdemux2_key_downloader_deinit (GstHLSDemux2 *demux)
738 {
739   /* free key file downloader structure */
740   if (!demux->kdownloader)
741     return;
742
743   if (demux->kdownloader->lock) {
744     g_mutex_free (demux->kdownloader->lock);
745     demux->kdownloader->lock = NULL;
746   }
747
748   if (demux->kdownloader->cond) {
749     g_cond_free (demux->kdownloader->cond);
750     demux->kdownloader->cond = NULL;
751   }
752
753   if (demux->kdownloader->key){
754     gst_buffer_unref (demux->kdownloader->key);
755     demux->kdownloader->key = NULL;
756   }
757
758   if (demux->kdownloader->prev_key_uri) {
759     g_free (demux->kdownloader->prev_key_uri);
760     demux->kdownloader->prev_key_uri = NULL;
761   }
762
763   g_free (demux->kdownloader);
764   demux->kdownloader = NULL;
765 }
766
767 static void
768 gst_hlsdemux2_set_property (GObject * object, guint prop_id,
769     const GValue * value, GParamSpec * pspec)
770 {
771   GstHLSDemux2 *demux = GST_HLSDEMUX2 (object);
772
773   switch (prop_id) {
774     case PROP_BITRATE_SWITCH_TOLERANCE:
775       demux->bitrate_switch_tol = g_value_get_float (value);
776       break;
777     case PROP_FORCE_LOWER_BITRATE:
778       demux->force_lower_bitrate = g_value_get_boolean (value);
779       break;
780     case PROP_BLOCKSIZE:
781       demux->blocksize = g_value_get_ulong (value);
782       break;
783     default:
784       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
785       break;
786   }
787 }
788
789 static void
790 gst_hlsdemux2_get_property (GObject * object, guint prop_id,
791    GValue * value, GParamSpec * pspec)
792 {
793   GstHLSDemux2 *demux = GST_HLSDEMUX2 (object);
794
795   switch (prop_id) {
796     case PROP_BITRATE_SWITCH_TOLERANCE:
797       g_value_set_float (value, demux->bitrate_switch_tol);
798       break;
799     case PROP_FORCE_LOWER_BITRATE:
800       g_value_set_boolean (value, demux->force_lower_bitrate);
801       break;
802     case PROP_BLOCKSIZE:
803       g_value_set_ulong (value, demux->blocksize);
804       break;
805     default:
806       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
807       break;
808   }
809 }
810
811 static gboolean
812 gst_hlsdemux2_sink_event (GstPad * pad, GstEvent * event)
813 {
814   GstHLSDemux2 *demux = GST_HLSDEMUX2 (gst_pad_get_parent (pad));
815   GstQuery *query = NULL;
816   gboolean ret = FALSE;
817   gchar *uri = NULL;
818
819   GST_LOG_OBJECT (demux, "Received event '%s' on sink pad...", GST_EVENT_TYPE_NAME (event));
820
821   switch (event->type) {
822     case GST_EVENT_EOS: {
823       gchar *playlist = NULL;
824       GError *err = NULL;
825
826       if (demux->playlist == NULL) {
827         GST_ERROR_OBJECT (demux, "Received EOS without a playlist.");
828         goto error;
829       }
830
831       GST_INFO_OBJECT (demux, "Got EOS on the sink pad: playlist file fetched");
832
833       query = gst_query_new_uri ();
834
835       /* query the location from upstream element for absolute path */
836       ret = gst_pad_peer_query (demux->sinkpad, query);
837       if (ret) {
838         gst_query_parse_uri (query, &uri);
839         gst_hlsdemux2_set_location (demux, uri);
840         g_free (uri);
841       } else {
842         GST_ERROR_OBJECT (demux, "failed to query URI from upstream");
843         goto error;
844       }
845       gst_query_unref (query);
846       query = NULL;
847
848       /* get cookies from upstream httpsrc */
849       gst_hlsdemux2_get_cookies (demux);
850
851       /* get user-agent from upstream httpsrc */
852       gst_hlsdemux2_get_user_agent (demux);
853
854       playlist = gst_hlsdemux2_src_buf_to_utf8_playlist (demux->playlist);
855       demux->playlist = NULL;
856
857       if (playlist == NULL) {
858         GST_ERROR_OBJECT (demux, "Error validating first playlist.");
859         GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."), (NULL));
860         goto error;
861       }
862
863       if (!gst_m3u8_client_update (demux->client, playlist)) {
864         /* In most cases, this will happen if we set a wrong url in the
865          * source element and we have received the 404 HTML response instead of
866          * the playlist */
867         GST_ERROR_OBJECT (demux, "failed to parse playlist...");
868         GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Invalid playlist."), (NULL));
869         goto error;
870       }
871
872       /* Loop to download the fragments & updates playlist */
873       g_static_rec_mutex_init (&demux->download_lock);
874       demux->download_task = gst_task_create ((GstTaskFunction) gst_hlsdemux2_fragment_download_loop, demux);
875       if (NULL == demux->download_task) {
876         GST_ERROR_OBJECT (demux, "failed to create download task...");
877         GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to fragment download task"), (NULL));
878         goto error;
879       }
880       gst_task_set_lock (demux->download_task, &demux->download_lock);
881       gst_task_start (demux->download_task);
882
883       /* create thread to send dummy data */
884       demux->buffering_posting_thread = g_thread_create (
885         (GThreadFunc) gst_hlsdemux2_download_monitor_thread, demux, TRUE, &err);
886
887       /* Swallow EOS, we'll push our own */
888       gst_event_unref (event);
889       gst_object_unref (demux);
890       return TRUE;
891     }
892     case GST_EVENT_NEWSEGMENT:
893       /* Swallow newsegments, we'll push our own */
894       gst_event_unref (event);
895       gst_object_unref (demux);
896       return TRUE;
897     default:
898       gst_object_unref (demux);
899       break;
900   }
901
902   return gst_pad_event_default (pad, event);
903
904 error:
905   gst_hlsdemux2_stop (demux);
906   gst_event_unref (event);
907   gst_object_unref (demux);
908
909   if (query)
910     gst_query_unref (query);
911
912   GST_LOG_OBJECT (demux,"Returning from sink event...");
913   return FALSE;
914 }
915
916 static GstStateChangeReturn
917   gst_hlsdemux2_change_state (GstElement * element, GstStateChange transition)
918   {
919     GstStateChangeReturn ret;
920     GstHLSDemux2 *demux = GST_HLSDEMUX2 (element);
921     gboolean bret = FALSE;
922
923     switch (transition) {
924       case GST_STATE_CHANGE_READY_TO_PAUSED:
925         break;
926       case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
927         GST_INFO_OBJECT (demux,"PAUSED->PLAYING");
928         break;
929       case GST_STATE_CHANGE_PAUSED_TO_READY:
930         GST_INFO_OBJECT (demux,"PAUSED->READY before parent");
931         gst_hlsdemux2_stop (demux);
932         break;
933       default:
934         break;
935     }
936
937     ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
938
939     switch (transition) {
940       case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
941         GST_INFO_OBJECT (demux,"PLAYING->PAUSED");
942         break;
943       case GST_STATE_CHANGE_PAUSED_TO_READY:
944         GST_INFO_OBJECT (demux,"PAUSED->READY after parent");
945         if (demux->download_task) {
946           bret = gst_task_join (demux->download_task);
947           GST_DEBUG_OBJECT (demux,"Joining download task : %d", bret);
948         }
949         break;
950       case GST_STATE_CHANGE_READY_TO_NULL:
951         GST_INFO_OBJECT (demux,"READY->NULL");
952         break;
953       default:
954         break;
955     }
956     return ret;
957   }
958
959
960
961 static GstFlowReturn
962 gst_hlsdemux2_chain (GstPad * pad, GstBuffer * buf)
963 {
964   GstHLSDemux2 *demux = GST_HLSDEMUX2 (gst_pad_get_parent (pad));
965
966   if (demux->playlist == NULL)
967     demux->playlist = buf;
968   else
969     demux->playlist = gst_buffer_join (demux->playlist, buf);
970   gst_object_unref (demux);
971
972   return GST_FLOW_OK;
973 }
974
975 static gboolean
976 gst_hlsdemux2_handle_src_event (GstPad * pad, GstEvent * event)
977 {
978   GstHLSDemux2 *hlsdemux2 = NULL;
979   GstHLSDemux2Stream *stream = NULL;
980
981   stream = (GstHLSDemux2Stream *) (gst_pad_get_element_private (pad));
982   hlsdemux2 = stream->parent;
983
984   switch (event->type) {
985     case GST_EVENT_SEEK: {
986       gdouble rate;
987       GstFormat format;
988       GstSeekFlags flags;
989       GstSeekType start_type, stop_type;
990       gint64 start, stop;
991       gint idx = 0;
992
993       if (gst_m3u8_client_is_live (hlsdemux2->client)) {
994         GST_WARNING_OBJECT (stream->pad, "SEEK is NOT Supported in LIVE");
995         return FALSE;
996       }
997
998       GST_INFO_OBJECT (stream->pad, "received SEEK event..");
999
1000       gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
1001                 &stop_type, &stop);
1002
1003       if (format != GST_FORMAT_TIME) {
1004         GST_WARNING_OBJECT (stream->pad, "received seek with unsupported format");
1005         return FALSE;
1006       }
1007
1008       // TODO: Validate requested SEEK time is within the duration or not
1009
1010       hlsdemux2->end_of_playlist = FALSE; // resent end of playlist
1011
1012       GST_DEBUG_OBJECT (stream->pad, "SEEK event with rate: %f start: %" GST_TIME_FORMAT
1013           " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
1014           GST_TIME_ARGS (stop));
1015
1016       if (!(flags & GST_SEEK_FLAG_FLUSH)) {
1017         GST_WARNING_OBJECT (stream->pad, "non-flush seek is not supported yet");
1018         return FALSE;
1019       }
1020
1021       hlsdemux2->flushing = TRUE;
1022
1023       /* signal queue full condition to come out */
1024       for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1025         GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
1026
1027         if (cur_stream) {
1028           cur_stream->eos = FALSE; // resent stream EOS
1029           if (cur_stream->queue) {
1030             GST_INFO_OBJECT (cur_stream->pad, "signalling stream queue");
1031             g_cond_signal (cur_stream->queue_full); /* to signal downloader eos blocking */
1032             g_cond_signal (cur_stream->queue_empty); /* incase push_loop blocked on condition */
1033           }
1034         }
1035       }
1036
1037       /* send FLUSH_START event to all source pads */
1038       if (flags & GST_SEEK_FLAG_FLUSH) {
1039
1040         GST_INFO_OBJECT (hlsdemux2, "sending flush start on all the stream pads");
1041
1042         for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1043           GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
1044
1045           if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
1046             gboolean bret = FALSE;
1047             bret = gst_pad_push_event (cur_stream->pad, gst_event_new_flush_start ());
1048             GST_DEBUG_OBJECT (cur_stream->pad, "flush_start returned = %d", bret);
1049           }
1050         }
1051       }
1052
1053       /* wait till all stream pad's task paused */
1054       for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1055         GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
1056
1057         if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
1058           GST_INFO_OBJECT (cur_stream->pad, "trying acquire stream lock");
1059           GST_PAD_STREAM_LOCK (cur_stream->pad);
1060           GST_INFO_OBJECT (cur_stream->pad, "acquired stream lock");
1061           GST_PAD_STREAM_UNLOCK (cur_stream->pad);
1062         }
1063       }
1064
1065       /* pause fragment download loop */
1066       g_mutex_lock (hlsdemux2->kdownloader->lock);
1067       GST_INFO_OBJECT (stream->pad, "Signalling key downloader condition");
1068       g_cond_signal (hlsdemux2->kdownloader->cond);
1069       g_mutex_unlock (hlsdemux2->kdownloader->lock);
1070
1071       g_mutex_lock (hlsdemux2->fdownloader->lock);
1072       GST_INFO_OBJECT (stream->pad, "Signalling fragment downloader condition");
1073       g_cond_signal (hlsdemux2->fdownloader->cond);
1074       g_mutex_unlock (hlsdemux2->fdownloader->lock);
1075
1076       g_mutex_lock (hlsdemux2->pldownloader->lock);
1077       GST_INFO_OBJECT (stream->pad, "Signalling playlist downloader condition");
1078       g_cond_signal (hlsdemux2->pldownloader->cond);
1079       g_mutex_unlock (hlsdemux2->pldownloader->lock);
1080
1081       GST_INFO_OBJECT (stream->pad, "waiting for download task to pause...");
1082       g_static_rec_mutex_lock (&hlsdemux2->download_lock);
1083       g_static_rec_mutex_unlock (&hlsdemux2->download_lock);
1084
1085       GST_INFO_OBJECT (hlsdemux2, "Download task paused");
1086
1087       /* clear internal stream queues */
1088       for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1089         GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
1090
1091         if (cur_stream && cur_stream->queue) {
1092           while (!g_queue_is_empty (cur_stream->queue)) {
1093             gpointer data = NULL;
1094             data = g_queue_pop_head (cur_stream->queue);
1095             gst_object_unref (data);
1096           }
1097           g_queue_clear (cur_stream->queue);
1098           cur_stream->cached_duration = 0;
1099           stream->percent = 0;
1100
1101           while (!g_queue_is_empty (cur_stream->downloader_queue)) {
1102             gpointer data = NULL;
1103             data = g_queue_pop_head (cur_stream->downloader_queue);
1104             gst_object_unref (data);
1105           }
1106           g_queue_clear (cur_stream->downloader_queue);
1107         }
1108       }
1109
1110 #if 0 /* useful when we want to switch to lowest variant on seek for faster buffering */
1111       if (gst_m3u8_client_has_variant_playlist (hlsdemux2->client)) {
1112         /* intentionally sending zero download rate, to move to least possible variant */
1113         gst_hlsdemux2_change_playlist (hlsdemux2, 0, NULL);
1114       }
1115 #endif
1116
1117       /* send FLUSH_STOP event to all source pads */
1118       if (flags & GST_SEEK_FLAG_FLUSH) {
1119
1120         GST_INFO_OBJECT (hlsdemux2, "sending flush stop");
1121
1122         for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1123           GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
1124
1125           if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
1126             gboolean bret = FALSE;
1127             bret = gst_pad_push_event (cur_stream->pad, gst_event_new_flush_stop ());
1128             GST_DEBUG_OBJECT (cur_stream->pad, "flush_stop returned = %d", bret);
1129           }
1130         }
1131       }
1132
1133       hlsdemux2->flushing = FALSE;
1134       hlsdemux2->fdownloader->find_mediaseq = TRUE;
1135       hlsdemux2->fdownloader->seeked_pos = start;
1136
1137       /* start all streams loop tasks & fragment download task */
1138       for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1139         GstHLSDemux2Stream *cur_stream = hlsdemux2->streams[idx];
1140
1141         if (cur_stream && GST_PAD_TASK(cur_stream->pad)) {
1142           GST_INFO_OBJECT (cur_stream->pad, "Starting push task");
1143           cur_stream->need_newsegment = TRUE;
1144           cur_stream->nts = GST_CLOCK_TIME_NONE; /*useful for audio-only seeking */
1145           cur_stream->cdisc = 0;
1146           cur_stream->fts = GST_CLOCK_TIME_NONE;
1147           cur_stream->valid_fts_rcvd = FALSE;
1148           cur_stream->total_stream_time = 0;
1149
1150           if (!gst_pad_start_task (cur_stream->pad, (GstTaskFunction) gst_hlsdemux2_push_loop, cur_stream)) {
1151             GST_ERROR_OBJECT (hlsdemux2, "failed to start stream task...");
1152             GST_ELEMENT_ERROR (hlsdemux2, RESOURCE, FAILED, ("failed to create stream push loop"), (NULL));
1153             goto error;
1154           }
1155         }
1156       }
1157
1158       gst_hlsdemux2_apply_disc (hlsdemux2);
1159
1160       GST_INFO_OBJECT (hlsdemux2, "Starting Download task..");
1161
1162       gst_task_start (hlsdemux2->download_task);
1163
1164       GST_INFO_OBJECT (hlsdemux2, "Successfully configured SEEK...");
1165       gst_event_unref (event);
1166       return TRUE;
1167     }
1168     default:
1169       break;
1170   }
1171
1172   return gst_pad_event_default (pad, event);
1173
1174 error:
1175   GST_ERROR_OBJECT (hlsdemux2, "seeking failed...");
1176   gst_event_unref (event);
1177   return FALSE;
1178 }
1179
1180 static gboolean
1181 gst_hlsdemux2_src_query (GstPad *pad, GstQuery * query)
1182 {
1183   GstHLSDemux2 *hlsdemux2 = NULL;
1184   gboolean ret = FALSE;
1185   GstHLSDemux2Stream *stream = NULL;
1186
1187   if (query == NULL)
1188     return FALSE;
1189
1190   stream = (GstHLSDemux2Stream *) (gst_pad_get_element_private (pad));
1191   hlsdemux2 = stream->parent;
1192
1193   switch (query->type) {
1194     case GST_QUERY_DURATION:{
1195       GstClockTime duration = -1;
1196       GstFormat fmt;
1197
1198       gst_query_parse_duration (query, &fmt, NULL);
1199       if (fmt == GST_FORMAT_TIME) {
1200         duration = gst_m3u8_client_get_duration (hlsdemux2->client);
1201         if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
1202           gst_query_set_duration (query, GST_FORMAT_TIME, duration);
1203           ret = TRUE;
1204         }
1205       }
1206       GST_LOG_OBJECT (hlsdemux2, "GST_QUERY_DURATION returns %s with duration %"
1207           GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
1208       break;
1209     }
1210     case GST_QUERY_URI:
1211       if (hlsdemux2->client) {
1212         /* FIXME: Do we answer with the variant playlist, with the current
1213          * playlist or the the uri of the least downlowaded fragment? */
1214         gst_query_set_uri (query, gst_m3u8_client_get_uri (hlsdemux2->client));
1215         ret = TRUE;
1216       }
1217       break;
1218     case GST_QUERY_SEEKING:{
1219       GstFormat fmt;
1220       gint64 stop = -1;
1221
1222       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1223       GST_INFO_OBJECT (hlsdemux2, "Received GST_QUERY_SEEKING with format %d",
1224           fmt);
1225       if (fmt == GST_FORMAT_TIME) {
1226         GstClockTime duration;
1227
1228         duration = gst_m3u8_client_get_duration (hlsdemux2->client);
1229         if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0)
1230           stop = duration;
1231
1232         gst_query_set_seeking (query, fmt,
1233             !gst_m3u8_client_is_live (hlsdemux2->client), 0, stop);
1234         ret = TRUE;
1235         GST_INFO_OBJECT (hlsdemux2, "GST_QUERY_SEEKING returning with stop : %"
1236             GST_TIME_FORMAT, GST_TIME_ARGS (stop));
1237       }
1238       break;
1239     }
1240     default:
1241       /* Don't fordward queries upstream because of the special nature of this
1242        * "demuxer", which relies on the upstream element only to be fed with the
1243        * first playlist */
1244       break;
1245   }
1246
1247   return ret;
1248 }
1249
1250 static gchar *
1251 gst_hlsdemux2_uri_get_domain ( GstHLSDemux2 *demux, gchar * uri)
1252 {
1253   gchar *pointer = uri;
1254   gchar *domain = NULL;
1255   guint flag = 0;
1256   guint counter=0;
1257
1258   domain = g_malloc0(strlen (uri));
1259   if (!domain) {
1260     GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
1261     GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
1262     return NULL;
1263   }
1264
1265   while(*pointer != '\0') {
1266     switch(*pointer) {
1267       case '.':
1268         flag = 1;
1269         break;
1270       case '/':
1271         if(flag==1)
1272           flag = 2;
1273         break;
1274     }
1275     if(flag==1) {
1276       domain[counter]=*pointer;
1277       counter++;
1278     } else if(flag == 2) {
1279       domain[counter]='\0';
1280       break;
1281     }
1282     pointer++;
1283   }
1284
1285   GST_DEBUG_OBJECT (demux, "uri = %s and domain = %s", uri, domain);
1286   return domain;
1287 }
1288
1289 static void
1290 gst_hlsdemux2_get_cookies(GstHLSDemux2 *demux)
1291 {
1292   GstQuery *cquery;
1293   GstStructure *structure;
1294   gboolean bret = FALSE;
1295
1296   structure = gst_structure_new ("HTTPCookies",
1297                                  "cookies", G_TYPE_STRING, NULL, NULL);
1298
1299   cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
1300
1301   bret = gst_pad_peer_query (demux->sinkpad, cquery);
1302   if (bret) {
1303     const GstStructure *s;
1304     const GValue *value;
1305
1306     s = gst_query_get_structure (cquery);
1307     value = gst_structure_get_value (s, "cookies");
1308     demux->playlistCookie = g_strdupv (g_value_get_boxed (value));
1309
1310     GST_INFO_OBJECT (demux, "Received playlist cookies from upstream element : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
1311     if(demux->playlistCookie){
1312         demux->lastCookie = g_strdupv(demux->playlistCookie);
1313     }
1314   } else {
1315     GST_WARNING_OBJECT (demux, "Failed to get cookies");
1316   }
1317
1318   gst_query_unref (cquery);
1319 }
1320
1321 static void
1322 gst_hlsdemux2_get_user_agent(GstHLSDemux2 *demux)
1323 {
1324   GstQuery *cquery;
1325   GstStructure *structure;
1326   gboolean bret = FALSE;
1327
1328   structure = gst_structure_new ("HTTPUserAgent",
1329                                  "user-agent", G_TYPE_STRING, NULL, NULL);
1330
1331   cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
1332
1333   bret = gst_pad_peer_query (demux->sinkpad, cquery);
1334   if (bret) {
1335     const GstStructure *s;
1336     const GValue *value;
1337
1338     GST_INFO_OBJECT (demux, "Received user-agent from upstream element...");
1339
1340     s = gst_query_get_structure (cquery);
1341     value = gst_structure_get_value (s, "user-agent");
1342     demux->user_agent = g_strdup (g_value_get_string (value));
1343
1344     GST_INFO_OBJECT (demux,"User agent received from query : %s", demux->user_agent);
1345   } else {
1346     GST_WARNING_OBJECT (demux, "Failed to get user-agent");
1347   }
1348
1349   gst_query_unref (cquery);
1350 }
1351
1352 static gboolean
1353 gst_hlsdemux2_create_playlist_download (GstHLSDemux2 *demux, const gchar *playlist_uri)
1354 {
1355   if (!gst_uri_is_valid (playlist_uri)) {
1356     GST_ERROR_OBJECT (demux, "invalid uri : %s...", playlist_uri == NULL ? "NULL" : playlist_uri);
1357     return FALSE;
1358   }
1359
1360   if (demux->cancelled || demux->flushing) {
1361     GST_WARNING_OBJECT (demux,"returning from download playlist due to cancel or flushing..");
1362     return FALSE;
1363   }
1364
1365   /* create playlist downloader pipeline */
1366   demux->pldownloader->pipe = gst_pipeline_new ("playlist-downloader");
1367   if (!demux->pldownloader->pipe) {
1368     GST_ERROR_OBJECT (demux, "failed to create pipeline");
1369     return FALSE;
1370   }
1371
1372   demux->pldownloader->bus = gst_pipeline_get_bus (GST_PIPELINE (demux->pldownloader->pipe));
1373   gst_bus_set_sync_handler(demux->pldownloader->bus, gst_hlsdemux2_playlist_download_bus_sync_cb, demux);
1374
1375   gst_object_unref (demux->pldownloader->bus);
1376
1377   GST_INFO_OBJECT (demux, "Creating source element for the URI : %s", playlist_uri);
1378
1379   /* creating source element */
1380   demux->pldownloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, playlist_uri, "playlisturisrc");
1381   if (!demux->pldownloader->urisrc) {
1382     GST_ERROR_OBJECT (demux, "failed to create urisrc");
1383     return FALSE;
1384   }
1385   g_object_set (G_OBJECT (demux->pldownloader->urisrc), "timeout", HLSDEMUX2_HTTP_TIMEOUT, NULL);
1386   g_object_set (G_OBJECT (demux->pldownloader->urisrc), "user-agent", demux->user_agent, NULL);
1387   g_object_set (G_OBJECT (demux->pldownloader->urisrc), "ahs-streaming", TRUE, NULL);
1388
1389   demux->playlistDomain = gst_hlsdemux2_uri_get_domain(demux, playlist_uri);
1390   if(!g_strcmp0(demux->playlistDomain, demux->lastDomain) && demux->lastCookie) {
1391     g_strfreev (demux->playlistCookie);
1392     demux->playlistCookie = g_strdupv (demux->lastCookie);
1393   }
1394
1395   if (demux->playlistCookie) {
1396     GST_DEBUG_OBJECT (demux, "Setting cookies before PLAYLIST download, before PLAYING: %s", *(demux->playlistCookie));
1397     /* setting cookies */
1398     g_object_set (demux->pldownloader->urisrc, "cookies", demux->playlistCookie, NULL);
1399   }
1400
1401   /* create sink element */
1402   demux->pldownloader->sink =  gst_element_factory_make ("appsink", "playlistsink");
1403   if (!demux->pldownloader->sink) {
1404     GST_ERROR_OBJECT (demux, "failed to create playlist sink element");
1405     return FALSE;
1406   }
1407   g_object_set (G_OBJECT (demux->pldownloader->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
1408   g_signal_connect (demux->pldownloader->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_on_playlist_buffer), demux);
1409
1410   gst_bin_add_many (GST_BIN (demux->pldownloader->pipe), demux->pldownloader->urisrc, demux->pldownloader->sink, NULL);
1411
1412   if (!gst_element_link_many (demux->pldownloader->urisrc, demux->pldownloader->sink, NULL)) {
1413     GST_ERROR_OBJECT (demux, "failed to link src & demux elements...");
1414     return FALSE;
1415   }
1416
1417   return TRUE;
1418 }
1419
1420 static void
1421 gst_hlsdemux2_destroy_playlist_download (GstHLSDemux2 * demux)
1422 {
1423   if (demux->pldownloader->pipe) {
1424     GST_DEBUG_OBJECT (demux, "Shutting down playlist download pipeline");
1425     gst_element_set_state (demux->pldownloader->pipe, GST_STATE_NULL);
1426     gst_element_get_state (demux->pldownloader->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
1427     gst_object_unref (demux->pldownloader->pipe);
1428     demux->pldownloader->pipe = NULL;
1429   }
1430 }
1431
1432 static gboolean
1433 gst_hlsdemux2_download_playlist (GstHLSDemux2 *demux, const gchar * uri)
1434 {
1435   GstStateChangeReturn ret;
1436
1437   if (demux->playlist_uri) {
1438     g_free (demux->playlist_uri);
1439   }
1440   demux->playlist_uri = g_strdup (uri);
1441
1442   demux->pldownloader->download_start_ts = gst_util_get_timestamp();
1443
1444   if (!gst_hlsdemux2_create_playlist_download (demux, uri)) {
1445     GST_ERROR_OBJECT (demux, "failed to create playlist download pipeline");
1446     return FALSE;
1447   }
1448
1449   ret = gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
1450   if (ret == GST_STATE_CHANGE_FAILURE) {
1451     GST_ERROR_OBJECT (demux, "set_state failed...");
1452     return FALSE;
1453   }
1454
1455   /* schedule the next update of playlist */
1456   if (demux->is_live)
1457     gst_hlsdemux2_schedule (demux);
1458
1459   /* wait until:
1460    *   - the download succeed (EOS)
1461    *   - the download failed (Error message on the fetcher bus)
1462    *   - the download was canceled
1463    */
1464   GST_LOG_OBJECT (demux, "Waiting to fetch the URI");
1465   g_cond_wait (demux->pldownloader->cond, demux->pldownloader->lock);
1466   GST_LOG_OBJECT (demux, "Recived signal to shutdown...");
1467
1468   if (demux->playlistCookie)
1469     g_strfreev (demux->playlistCookie);
1470
1471   g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
1472
1473   GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
1474
1475   if(demux->playlistCookie){
1476     g_strfreev(demux->lastCookie);
1477     g_free(demux->lastDomain);
1478     demux->lastCookie = g_strdupv(demux->playlistCookie);
1479     demux->lastDomain = g_strdup(demux->playlistDomain);
1480   }
1481
1482   gst_hlsdemux2_destroy_playlist_download (demux);
1483
1484   if (demux->cancelled || demux->flushing)
1485     return FALSE;
1486
1487   return TRUE;
1488 }
1489
1490
1491 static gboolean
1492 gst_hlsdemux2_update_playlist (GstHLSDemux2 * demux, gboolean update, gboolean *is_error)
1493 {
1494   gchar *playlist = NULL;
1495   gboolean updated = FALSE;
1496   const gchar *playlist_uri = gst_m3u8_client_get_current_uri (demux->client);
1497
1498   *is_error = FALSE;
1499
1500   if (!gst_m3u8_client_is_playlist_download_needed (demux->client)) {
1501     GST_INFO_OBJECT (demux, "Playlist download is not needed...");
1502     return TRUE;
1503   }
1504
1505   g_mutex_lock (demux->pldownloader->lock);
1506
1507 try_again:
1508
1509   if (!gst_hlsdemux2_download_playlist (demux, playlist_uri)) {
1510     GST_ERROR_OBJECT (demux, "failed to create playlist download");
1511     goto error;
1512   }
1513
1514   if ((demux->pldownloader->playlist == NULL) || (GST_BUFFER_DATA(demux->pldownloader->playlist) == NULL)) {
1515     // TODO: don't exact reason, why eos is coming from soup without data...
1516     GST_ERROR_OBJECT (demux, "Received playlist eos, without playlist data -> TRY AGAIN");
1517     goto try_again;
1518   }
1519
1520   /* reset the count */
1521   demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
1522
1523   playlist = gst_hlsdemux2_src_buf_to_utf8_playlist (demux->pldownloader->playlist);
1524   if (!playlist) {
1525     GST_ERROR_OBJECT(demux, "failed to create playlist");
1526     goto error;
1527   }
1528   demux->pldownloader->playlist = NULL;
1529
1530   updated = gst_m3u8_client_update (demux->client, playlist);
1531   g_mutex_unlock (demux->pldownloader->lock);
1532
1533   return updated;
1534
1535 error:
1536   if (demux->flushing)
1537     *is_error = TRUE;
1538   g_mutex_unlock (demux->pldownloader->lock);
1539   return FALSE;
1540 }
1541
1542 static gboolean
1543 gst_hlsdemux2_create_key_download (GstHLSDemux2 *demux, const gchar *key_uri)
1544 {
1545   if (!gst_uri_is_valid (key_uri)) {
1546     GST_ERROR_OBJECT (demux, "invalid uri : %s...", key_uri == NULL ? "NULL" : key_uri);
1547     return FALSE;
1548   }
1549
1550   if (demux->cancelled || demux->flushing) {
1551     GST_WARNING_OBJECT (demux,"returning from download key due to cancel or flushing..");
1552     return FALSE;
1553   }
1554
1555   demux->kdownloader->pipe = gst_pipeline_new ("keydownloader");
1556   if (!demux->kdownloader->pipe) {
1557     GST_ERROR_OBJECT (demux, "failed to create pipeline");
1558     return FALSE;
1559   }
1560
1561   demux->kdownloader->bus = gst_pipeline_get_bus (GST_PIPELINE (demux->kdownloader->pipe));
1562   gst_bus_add_watch (demux->kdownloader->bus, (GstBusFunc)gst_hlsdemux2_key_download_bus_cb, demux);
1563   gst_object_unref (demux->kdownloader->bus);
1564
1565   GST_INFO_OBJECT (demux, "Creating source element for the URI : %s", key_uri);
1566
1567   demux->kdownloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, key_uri, "keyurisrc");
1568   if (!demux->kdownloader->urisrc) {
1569     GST_ERROR_OBJECT (demux, "failed to create urisrc");
1570     return FALSE;
1571   }
1572
1573   g_object_set (G_OBJECT (demux->kdownloader->urisrc), "timeout", HLSDEMUX2_HTTP_TIMEOUT, NULL);
1574   g_object_set (G_OBJECT (demux->kdownloader->urisrc), "user-agent", demux->user_agent, NULL);
1575   g_object_set (G_OBJECT (demux->kdownloader->urisrc), "ahs-streaming", TRUE, NULL);
1576
1577   demux->keyDomain = gst_hlsdemux2_uri_get_domain(demux, key_uri);
1578   if(!g_strcmp0(demux->keyDomain, demux->lastDomain) && demux->lastCookie) {
1579     g_strfreev(demux->keyCookie);
1580     demux->keyCookie = g_strdupv(demux->lastCookie);
1581   }
1582
1583   if (demux->keyCookie) {
1584     GST_DEBUG_OBJECT (demux, "Setting cookies before KEY download goto PLAYING : %s", *(demux->keyCookie));
1585     g_object_set (demux->kdownloader->urisrc, "cookies", demux->keyCookie, NULL);
1586   }
1587
1588   demux->kdownloader->sink =  gst_element_factory_make ("appsink", "keyfilesink");
1589   if (!demux->kdownloader->sink) {
1590     GST_ERROR_OBJECT (demux, "failed to create playlist sink element");
1591     return FALSE;
1592   }
1593   g_object_set (G_OBJECT (demux->kdownloader->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
1594   g_signal_connect (demux->kdownloader->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_on_key_buffer), demux);
1595
1596   gst_bin_add_many (GST_BIN (demux->kdownloader->pipe), demux->kdownloader->urisrc, demux->kdownloader->sink, NULL);
1597
1598   if (!gst_element_link_many (demux->kdownloader->urisrc, demux->kdownloader->sink, NULL)) {
1599     GST_ERROR_OBJECT (demux, "failed to link src & demux elements...");
1600     return FALSE;
1601   }
1602
1603   return TRUE;
1604 }
1605
1606 static void
1607 gst_hlsdemux2_destroy_key_download (GstHLSDemux2 * demux)
1608 {
1609   if (demux->kdownloader->pipe) {
1610     GST_DEBUG_OBJECT (demux, "Shutting down key download pipeline");
1611     gst_element_set_state (demux->kdownloader->pipe, GST_STATE_NULL);
1612     gst_element_get_state (demux->kdownloader->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
1613     gst_object_unref (demux->kdownloader->pipe);
1614     demux->kdownloader->pipe = NULL;
1615   }
1616 }
1617
1618 static gboolean
1619 gst_hlsdemux2_download_key (GstHLSDemux2 *demux, const gchar * uri)
1620 {
1621   GstStateChangeReturn ret;
1622
1623   if (demux->key_uri) {
1624     g_free (demux->key_uri);
1625   }
1626   demux->key_uri = g_strdup (uri);
1627
1628   g_mutex_lock (demux->kdownloader->lock);
1629
1630   if (!gst_hlsdemux2_create_key_download (demux, uri)) {
1631     GST_ERROR_OBJECT (demux, "failed to create key download pipeline");
1632     return FALSE;
1633   }
1634
1635   ret = gst_element_set_state (demux->kdownloader->pipe, GST_STATE_PLAYING);
1636   if (ret == GST_STATE_CHANGE_FAILURE) {
1637     GST_ERROR_OBJECT (demux, "set_state failed...");
1638     return FALSE;
1639   }
1640
1641   /* wait until:
1642    *   - the download succeed (EOS)
1643    *   - the download failed (Error message on the fetcher bus)
1644    *   - the download was canceled
1645    */
1646   GST_DEBUG_OBJECT (demux, "Waiting to fetch the key URI");
1647   g_cond_wait (demux->kdownloader->cond, demux->kdownloader->lock);
1648   GST_DEBUG_OBJECT (demux, "Recived signal to shutdown key downloader...");
1649   g_mutex_unlock (demux->kdownloader->lock);
1650
1651   if (demux->keyCookie) {
1652     g_object_get (demux->kdownloader->urisrc, "cookies", &demux->keyCookie, NULL);
1653   }
1654
1655   GST_DEBUG_OBJECT (demux, "Got cookies after KEY download : %s", demux->keyCookie ? *(demux->keyCookie) : NULL);
1656
1657   if(demux->keyCookie){
1658       g_strfreev(demux->lastCookie);
1659       g_free(demux->lastDomain);
1660       demux->lastCookie = g_strdupv(demux->keyCookie);
1661       demux->lastDomain = g_strdup(demux->keyDomain);
1662   }
1663
1664   gst_hlsdemux2_destroy_key_download (demux);
1665
1666   if (demux->cancelled || demux->flushing)
1667     return FALSE;
1668
1669   return TRUE;
1670 }
1671
1672 static void
1673 gst_hlsdemux2_have_type_cb (GstElement * typefind, guint probability,
1674     GstCaps * caps, GstHLSDemux2 * demux)
1675 {
1676   GstStructure *structure = NULL;
1677
1678   structure = gst_caps_get_structure (caps, 0);
1679
1680   GST_DEBUG_OBJECT (demux, "typefind found caps %" GST_PTR_FORMAT, caps);
1681
1682   if (gst_structure_has_name (structure, "video/mpegts")) {
1683     /* found ts fragment */
1684     demux->fdownloader->demuxer = gst_element_factory_make ("mpegtsdemux", "tsdemux");
1685     if (!demux->fdownloader->demuxer) {
1686       GST_ERROR_OBJECT (demux, "failed to create mpegtsdemux element");
1687       GST_ELEMENT_ERROR (demux, CORE, MISSING_PLUGIN, ("failed to create mpegtsdemuxer element"), (NULL));
1688       return;
1689     }
1690     g_signal_connect (demux->fdownloader->demuxer, "pad-added", G_CALLBACK (gst_hlsdemux2_new_pad_added), demux);
1691
1692     gst_bin_add (GST_BIN (demux->fdownloader->pipe), demux->fdownloader->demuxer);
1693
1694     /* set queue element to PLAYING state */
1695     gst_element_set_state (demux->fdownloader->demuxer, GST_STATE_PLAYING);
1696
1697     if (!gst_element_link (demux->fdownloader->typefind, demux->fdownloader->demuxer)) {
1698       GST_ERROR_OBJECT (demux, "failed to link src and demux elements...");
1699       GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("failed to link typefind & demuxer"), (NULL));
1700       return;
1701     }
1702   } else if (gst_structure_has_name (structure, "application/x-id3")) {
1703     /* found ts fragment */
1704     demux->fdownloader->demuxer = gst_element_factory_make ("id3demux", "id3demuxer");
1705     if (!demux->fdownloader->demuxer) {
1706       GST_ERROR_OBJECT (demux, "failed to create mpegtsdemux element");
1707       GST_ELEMENT_ERROR (demux, CORE, MISSING_PLUGIN, ("failed to create id3demuxer element"), (NULL));
1708       return;
1709     }
1710     g_signal_connect (demux->fdownloader->demuxer, "pad-added", G_CALLBACK (gst_hlsdemux2_new_pad_added), demux);
1711
1712     gst_bin_add (GST_BIN (demux->fdownloader->pipe), demux->fdownloader->demuxer);
1713
1714     /* set queue element to PLAYING state */
1715     gst_element_set_state (demux->fdownloader->demuxer, GST_STATE_PLAYING);
1716
1717     if (!gst_element_link_many (demux->fdownloader->typefind, demux->fdownloader->demuxer, NULL)) {
1718       GST_ERROR_OBJECT (demux, "failed to link src and demux elements...");
1719       GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("failed to link typefind & demuxer"), (NULL));
1720       return;
1721     }
1722
1723     /* as the fragment does not contain in container format, force the timestamps based on fragment duration */
1724     demux->fdownloader->force_timestamps = TRUE;
1725   }
1726 }
1727
1728 static gboolean
1729 gst_hlsdemux2_download_monitor_thread (GstHLSDemux2 *demux)
1730 {
1731   GTimeVal post_msg_update = {0, };
1732
1733   g_mutex_lock (demux->post_msg_lock);
1734   GST_INFO_OBJECT (demux, "waiting for streaming to start to post message...");
1735   g_cond_wait (demux->post_msg_start, demux->post_msg_lock);
1736   GST_INFO_OBJECT (demux, "Start posting messages...");
1737   g_mutex_unlock (demux->post_msg_lock);
1738
1739   while (TRUE) {
1740     gboolean do_post = FALSE;
1741     guint64 percent = 0;
1742     guint idx = 0;
1743     guint64 total_percent = 0;
1744     gboolean bret = FALSE;
1745
1746     if (demux->cancelled) {
1747       GST_WARNING_OBJECT (demux, "returning msg posting thread...");
1748       return TRUE;
1749     }
1750
1751     /* schedule the next update using the target duration field of the
1752      * playlist */
1753     post_msg_update.tv_sec = 0;
1754     post_msg_update.tv_usec = 0;
1755
1756     g_get_current_time (&post_msg_update);
1757     g_time_val_add (&post_msg_update, 200000); // posts buffering msg after every 0.5 sec
1758
1759     /* verify fast switch from here */
1760     g_mutex_lock (demux->fdownloader->lock);
1761     if (demux->fdownloader->ndownloaded
1762       && !demux->fdownloader->applied_fast_switch && demux->fdownloader->download_start_ts) {
1763       gst_hlsdemux2_check_fast_switch (demux);
1764     }
1765     g_mutex_unlock (demux->fdownloader->lock);
1766
1767     /* calculate avg percent of streams' percentages */
1768     for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
1769       GstHLSDemux2Stream *stream = demux->streams[idx];
1770       if (stream ) {
1771         guint64 stream_percent = 0;
1772
1773         stream_percent = ((stream->cached_duration * 100) / (demux->total_cache_duration / DEFAULT_NUM_FRAGMENTS_CACHE));
1774         GST_DEBUG_OBJECT (stream->pad, "stream percent = %"G_GUINT64_FORMAT, stream_percent);
1775         total_percent += stream_percent;
1776       }
1777     }
1778     percent = total_percent / demux->active_stream_cnt;
1779
1780     if (demux->is_buffering) {
1781       do_post = TRUE;
1782       if (percent >= 100)
1783         demux->is_buffering = FALSE;
1784     } else {
1785       if (percent < 10) {
1786         /* if buffering drops below 10% lets start posting msgs */
1787         demux->is_buffering = TRUE;
1788         do_post = TRUE;
1789       }
1790     }
1791
1792     if (do_post) {
1793       GstMessage *message;
1794
1795       if (percent > 100) {
1796         //GST_LOG_OBJECT (demux, " exceeded percent = %d", (gint) percent);
1797         percent = 100;
1798       }
1799
1800       if (demux->end_of_playlist) {
1801         GST_INFO_OBJECT (demux, "end of the playlist reached... always post 100%");
1802         percent = 100;
1803       }
1804
1805       if (percent != demux->percent) {
1806         g_mutex_lock (demux->buffering_lock);
1807         demux->percent = percent;
1808         g_mutex_unlock (demux->buffering_lock);
1809
1810         GST_LOG_OBJECT (demux, "buffering %d percent", (gint) percent);
1811
1812         /* posting buffering to internal bus, which will take average & post to main bus */
1813         message = gst_message_new_buffering (GST_OBJECT_CAST (demux), (gint) demux->percent);
1814         if (!gst_element_post_message (GST_ELEMENT_CAST (demux), message)) {
1815           GST_WARNING_OBJECT (demux, "failed to post buffering msg...");
1816         }
1817       }
1818     }
1819
1820     g_mutex_lock (demux->post_msg_lock);
1821     /*  block until the next scheduled update or the exit signal */
1822     bret = g_cond_timed_wait (demux->post_msg_exit, demux->post_msg_lock, &post_msg_update);
1823     g_mutex_unlock (demux->post_msg_lock);
1824
1825     if (bret) {
1826       GST_WARNING_OBJECT (demux, "signalled to exit posting msgs...");
1827       break;
1828     }
1829   }
1830
1831   return TRUE;
1832 }
1833
1834 static gboolean
1835 gst_hlsdemux2_fragurisrc_event_handler (GstPad * pad, GstEvent *event, gpointer data)
1836 {
1837   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
1838
1839   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
1840     GTimeVal time = {0, };
1841
1842     GST_INFO_OBJECT (demux, "received EOS from fragment downloader's httpsrc");
1843
1844     if (demux->fdownloader->error_rcvd) {
1845       GST_WARNING_OBJECT (demux, "received EOS event after ERROR.. discard this");
1846       demux->fdownloader->src_downloaded_size = 0;
1847       demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
1848       return FALSE;
1849     }
1850
1851     /* download rate calculation : note down stop time*/
1852     g_get_current_time (&time);
1853     demux->fdownloader->download_stop_ts = gst_util_get_timestamp();
1854
1855     GST_INFO_OBJECT (demux, "download stop_ts = %"G_GUINT64_FORMAT, demux->fdownloader->download_stop_ts);
1856     GST_INFO_OBJECT (demux, "time taken to download current fragment = %"G_GUINT64_FORMAT, demux->fdownloader->download_stop_ts - demux->fdownloader->download_start_ts);
1857     GST_INFO_OBJECT (demux, "fragment downloaded size = %"G_GUINT64_FORMAT" and content_size = %"G_GUINT64_FORMAT,
1858       demux->fdownloader->src_downloaded_size, demux->fdownloader->content_size);
1859
1860     if (demux->fdownloader->src_downloaded_size && (demux->fdownloader->src_downloaded_size == demux->fdownloader->content_size)) {
1861       guint64 download_rate = 0;
1862       guint i = 0;
1863       guint64 dsum = 0;
1864
1865       /* calculate current fragment download rate */
1866       download_rate = (demux->fdownloader->src_downloaded_size * 8 * GST_SECOND) /
1867         (demux->fdownloader->download_stop_ts - demux->fdownloader->download_start_ts);
1868
1869       if (demux->fdownloader->avg_frag_drates->len == HLSDEMUX2_MAX_N_PAST_FRAG_DOWNLOADRATES) {
1870         /* removing starting element */
1871         g_array_remove_index (demux->fdownloader->avg_frag_drates, 0);
1872         GST_DEBUG_OBJECT (demux, "removing index from download rates");
1873       }
1874       g_array_append_val (demux->fdownloader->avg_frag_drates, download_rate);
1875
1876       for (i = 0 ; i < demux->fdownloader->avg_frag_drates->len; i++) {
1877         dsum += g_array_index (demux->fdownloader->avg_frag_drates, guint64, i);
1878       }
1879
1880       demux->fdownloader->download_rate = dsum / demux->fdownloader->avg_frag_drates->len;
1881
1882       GST_INFO_OBJECT (demux, " >>>> DOWNLOAD RATE = %"G_GUINT64_FORMAT, demux->fdownloader->download_rate);
1883     } else {
1884       GST_WARNING_OBJECT (demux, "something wrong better not to calculate download rate with this and discard EOS...");
1885       demux->fdownloader->src_downloaded_size = 0;
1886       demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
1887       return FALSE;
1888     }
1889
1890     demux->fdownloader->src_downloaded_size = 0;
1891     demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
1892   }
1893
1894   return TRUE;
1895 }
1896
1897 static gboolean
1898 gst_hlsdemux2_check_fast_switch (GstHLSDemux2 *demux)
1899 {
1900   GstClockTime elapsed_time = 0;
1901   guint i = 0;
1902   guint64 download_rate = 0;
1903
1904   elapsed_time = gst_util_get_timestamp();
1905
1906   if (gst_m3u8_client_has_variant_playlist (demux->client) &&
1907     ((elapsed_time - demux->fdownloader->download_start_ts) >
1908       (HLSDEMUX2_FAST_CHECK_WARNING_TIME_FACTOR * demux->target_duration))) {
1909     guint64 drate_sum = 0;
1910     GList *previous_variant, *current_variant;
1911     gint old_bandwidth, new_bandwidth;
1912
1913     GST_INFO_OBJECT (demux, "Doing fast switch using array len %d...", demux->fdownloader->avg_chunk_drates->len);
1914
1915     for (i = 0 ; i < demux->fdownloader->avg_chunk_drates->len; i++) {
1916       drate_sum += g_array_index (demux->fdownloader->avg_chunk_drates, guint64, i);
1917     }
1918
1919     /* 0.9 factor is for compensating for connection time*/
1920     download_rate = (drate_sum * 0.9) / demux->fdownloader->avg_chunk_drates->len;
1921
1922     GST_INFO_OBJECT (demux, "average chunk download rate = %"G_GUINT64_FORMAT, download_rate);
1923
1924     if ((elapsed_time - demux->fdownloader->download_start_ts) >
1925       (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration)) {
1926       GST_WARNING_OBJECT (demux, "Reached FAST_SWITCH critical point...do fast_switch");
1927       goto fast_switch;
1928     }
1929
1930     previous_variant = demux->client->main->current_variant;
1931     current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client, download_rate);
1932
1933     old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
1934     new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
1935
1936     GST_INFO_OBJECT (demux, "variant's bandwidth got using average chunk download rate is %d", new_bandwidth);
1937
1938     /* Don't do anything else if the playlist is the same */
1939     if (new_bandwidth == old_bandwidth) {
1940       GST_WARNING_OBJECT (demux, "Either BW is recovering or NO LOWER variant available than current, DON'T DO FAST_SWITCH...");
1941       return TRUE;
1942     }
1943
1944     GST_WARNING_OBJECT (demux, "Going to do fast_switch due to BW problem...");
1945     goto fast_switch;
1946   }
1947
1948   return TRUE;
1949
1950 fast_switch:
1951
1952   demux->fdownloader->download_rate = download_rate;
1953
1954   /* flush previous fragment downloads history */
1955   for (i = 3; i ; --i) {
1956     g_array_remove_index (demux->fdownloader->avg_frag_drates, i - 1);
1957   }
1958
1959   GST_INFO_OBJECT (demux, "in fast download rate : len %d...", demux->fdownloader->avg_frag_drates->len);
1960   g_array_append_val (demux->fdownloader->avg_frag_drates, demux->fdownloader->download_rate);
1961
1962   GST_INFO_OBJECT (demux, " >>>> DOWNLOAD RATE in fast switch = %"G_GUINT64_FORMAT, demux->fdownloader->download_rate);
1963
1964   demux->fdownloader->applied_fast_switch = TRUE;
1965
1966   /* close current fragment */
1967   g_cond_signal (demux->fdownloader->cond);
1968
1969   return FALSE;
1970
1971 }
1972
1973 static gboolean
1974 gst_hlsdemux2_fragurisrc_buffer_handler (GstPad * pad, GstBuffer *buffer, gpointer data)
1975 {
1976   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
1977   GstClockTime elapsed_ts = 0;
1978   guint64 chunk_drate = 0;
1979
1980   /* if block_switch already enabled no need to cross check. IMP check*/
1981   if (demux->fdownloader->applied_fast_switch) {
1982     GST_WARNING_OBJECT (demux, "already applied fast_switch.. drop current buffer");
1983     return FALSE;
1984   }
1985
1986   demux->fdownloader->src_downloaded_size += GST_BUFFER_SIZE(buffer);
1987
1988   if (demux->fdownloader->first_buffer) {
1989     /* get the content size for doing last buffer decryption & for vaidating complete download happend or not */
1990     GST_INFO_OBJECT (demux, "just received first buffer...");
1991     g_object_get (demux->fdownloader->urisrc, "content-size", &demux->fdownloader->content_size, NULL);
1992     GST_INFO_OBJECT (demux, "content size = %"G_GUINT64_FORMAT, demux->fdownloader->content_size);
1993     demux->fdownloader->first_buffer = FALSE;
1994     demux->fdownloader->chunk_start_ts = gst_util_get_timestamp();
1995     demux->fdownloader->chunk_downloaded_size = 0;
1996   }
1997
1998
1999   demux->fdownloader->chunk_downloaded_size += GST_BUFFER_SIZE(buffer);
2000   elapsed_ts = gst_util_get_timestamp();
2001
2002   if ((elapsed_ts - demux->fdownloader->chunk_start_ts) > HLSDEMUX2_CHUNK_TIME_DURATION) {
2003     GST_DEBUG_OBJECT (demux, "chunk downloaded time = %"GST_TIME_FORMAT,
2004       GST_TIME_ARGS(elapsed_ts - demux->fdownloader->chunk_start_ts));
2005
2006     chunk_drate = (demux->fdownloader->chunk_downloaded_size * 8 * GST_SECOND) / (elapsed_ts - demux->fdownloader->chunk_start_ts);
2007     demux->fdownloader->chunk_start_ts = elapsed_ts;
2008     demux->fdownloader->chunk_downloaded_size = 0;
2009
2010     GST_DEBUG_OBJECT(demux, "CHUNK DOWNLOAD RATE = %"G_GUINT64_FORMAT, chunk_drate);
2011
2012     if (demux->fdownloader->avg_chunk_drates->len == HLSDEMUX2_NUM_CHUNK_DOWNLOADS_FAST_SWITCH) {
2013       /* removing starting element */
2014       g_array_remove_index (demux->fdownloader->avg_chunk_drates, 0);
2015     }
2016     g_array_append_val (demux->fdownloader->avg_chunk_drates, chunk_drate);
2017   }
2018
2019   GST_LOG_OBJECT (demux, "fragment downloaded size at urisrc = %"G_GUINT64_FORMAT, demux->fdownloader->src_downloaded_size);
2020
2021   return TRUE;
2022 }
2023
2024 static gboolean
2025 gst_hlsdemux2_queue_buffer_handler (GstPad *pad, GstBuffer *buffer, gpointer data)
2026 {
2027   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
2028   unsigned char *encry_data = NULL;
2029   unsigned char *outdata = NULL;
2030   unsigned char *remained_data = NULL;
2031   unsigned char* total_data = NULL;
2032
2033   demux->fdownloader->queue_downloaded_size += GST_BUFFER_SIZE(buffer);
2034
2035   GST_DEBUG_OBJECT (demux, "total downloaded size = %"G_GUINT64_FORMAT, demux->fdownloader->queue_downloaded_size);
2036
2037   if (demux->fdownloader->is_encrypted) {
2038     guint encry_data_size = 0;
2039     unsigned char *indata = GST_BUFFER_DATA (buffer);
2040     guint insize = GST_BUFFER_SIZE (buffer);
2041     gint out_len = 0;
2042
2043     if (demux->fdownloader->remaining_data && demux->fdownloader->remaining_size) {
2044       GST_LOG_OBJECT (demux, "remain size = %d..", demux->fdownloader->remaining_size);
2045
2046       encry_data = (unsigned char *) malloc (insize + demux->fdownloader->remaining_size);
2047       if (!encry_data) {
2048         GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
2049         GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
2050         goto error;
2051       }
2052
2053       /* copy remaining data in previous iteration */
2054       memcpy (encry_data, demux->fdownloader->remaining_data, demux->fdownloader->remaining_size);
2055       /* copy input encrypted data of current iteration */
2056       memcpy (encry_data + demux->fdownloader->remaining_size, indata, insize);
2057
2058       encry_data_size = insize + demux->fdownloader->remaining_size;
2059
2060       free (demux->fdownloader->remaining_data);
2061       demux->fdownloader->remaining_data = NULL;
2062       demux->fdownloader->remaining_size = 0;
2063     } else {
2064       encry_data_size = insize;
2065       encry_data = indata;
2066     }
2067
2068     demux->fdownloader->remaining_size = encry_data_size % GST_HLS_DEMUX_AES_BLOCK_SIZE;
2069
2070     if (demux->fdownloader->remaining_size) {
2071       GST_LOG_OBJECT (demux, "Remining in current iteration = %d\n", demux->fdownloader->remaining_size);
2072       demux->fdownloader->remaining_data = (gchar *) malloc (demux->fdownloader->remaining_size);
2073       if ( demux->fdownloader->remaining_data == NULL) {
2074         GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
2075         GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
2076         goto error;
2077       }
2078
2079       /* copy remained portion to buffer */
2080       memcpy (demux->fdownloader->remaining_data,
2081               encry_data + encry_data_size - demux->fdownloader->remaining_size,
2082               demux->fdownloader->remaining_size);
2083     }
2084
2085     out_len = encry_data_size - demux->fdownloader->remaining_size + GST_HLS_DEMUX_AES_BLOCK_SIZE;
2086     outdata = (unsigned char *) malloc (out_len);
2087     if (!outdata) {
2088       GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
2089       GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
2090       goto error;
2091     }
2092
2093     if (!gst_m3u8_client_decrypt_update (demux->client, outdata, &out_len,
2094         encry_data, encry_data_size - demux->fdownloader->remaining_size)) {
2095       GST_ERROR_OBJECT (demux, "failed to decrypt...\n");
2096       GST_ELEMENT_ERROR (demux, STREAM, FAILED, ("failed to decrypt"), (NULL));
2097       goto error;
2098     }
2099
2100     if (encry_data != indata) {
2101       g_free (encry_data);
2102       encry_data = NULL;
2103     }
2104
2105     g_free (GST_BUFFER_MALLOCDATA(buffer));
2106
2107     /* decrypt the final buffer */
2108     if (demux->fdownloader->queue_downloaded_size == demux->fdownloader->content_size) {
2109       gint remained_size = 0;
2110       gint total_len = 0;
2111
2112       GST_LOG_OBJECT (demux, "remained data = %p & remained size = %d", demux->fdownloader->remaining_data, demux->fdownloader->remaining_size);
2113
2114       remained_data =  (unsigned char *) malloc (GST_HLS_DEMUX_AES_BLOCK_SIZE);
2115       if (!remained_data) {
2116         GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
2117         GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
2118         goto error;
2119       }
2120       gst_m3u8_client_decrypt_final (demux->client, remained_data, &remained_size);
2121       GST_LOG_OBJECT (demux,"remained size = %d\n", remained_size);
2122
2123       if (remained_size) {
2124         total_len = out_len + remained_size;
2125
2126         total_data = (unsigned char *) malloc (total_len);
2127         if (!total_data) {
2128           GST_ERROR_OBJECT (demux, "failed to allocate memory...\n");
2129           GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
2130           goto error;
2131         }
2132
2133         memcpy (total_data, outdata, out_len);
2134         memcpy (total_data+out_len, remained_data, remained_size);
2135
2136         GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = total_data;
2137         GST_BUFFER_SIZE(buffer) = total_len;
2138         g_free (remained_data);
2139         g_free (outdata);
2140       } else {
2141         GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = outdata;
2142         GST_BUFFER_SIZE(buffer) = out_len;
2143         g_free (remained_data);
2144       }
2145
2146       if (!gst_m3u8_client_decrypt_deinit (demux->client)) {
2147         GST_WARNING_OBJECT (demux, "decryption cleanup failed...");
2148       }
2149     } else {
2150       GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = outdata;
2151       GST_BUFFER_SIZE(buffer) = out_len;
2152     }
2153   }
2154
2155   return TRUE;
2156
2157 error:
2158   if (encry_data)
2159     free (encry_data);
2160
2161   if (outdata)
2162     free (outdata);
2163
2164   if (remained_data)
2165     free (remained_data);
2166
2167  return FALSE;
2168 }
2169
2170 static gboolean
2171 gst_hlsdemux2_create_fragment_download (GstHLSDemux2 * demux, const gchar * uri)
2172 {
2173   GstBus *bus = NULL;
2174   GstPad *srcpad = NULL;
2175
2176   if (!gst_uri_is_valid (uri)) {
2177     GST_ERROR_OBJECT (demux, "invalid uri : %s...", uri == NULL ? "NULL" : uri);
2178     return FALSE;
2179   }
2180
2181   /* re-initialize fragment variables */
2182   demux->fdownloader->first_buffer = TRUE;
2183   demux->fdownloader->cur_stream_cnt = 0;
2184   demux->fdownloader->error_rcvd = FALSE;
2185
2186   demux->fdownloader->pipe = gst_pipeline_new ("frag-fdownloader");
2187   if (!demux->fdownloader->pipe) {
2188     GST_ERROR_OBJECT (demux, "failed to create pipeline");
2189     return FALSE;
2190   }
2191
2192   bus = gst_pipeline_get_bus (GST_PIPELINE (demux->fdownloader->pipe));
2193   gst_bus_add_watch (bus, (GstBusFunc)gst_hlsdemux2_fragment_download_bus_cb, demux);
2194   gst_object_unref (bus);
2195
2196   GST_INFO_OBJECT (demux, "Creating source element for the URI : %s", uri);
2197
2198   demux->fdownloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, "fragurisrc");
2199   if (!demux->fdownloader->urisrc) {
2200     GST_ERROR_OBJECT (demux, "failed to create urisrc");
2201     return FALSE;
2202   }
2203
2204   g_object_set (G_OBJECT (demux->fdownloader->urisrc), "timeout", HLSDEMUX2_HTTP_TIMEOUT, NULL);
2205   g_object_set (G_OBJECT (demux->fdownloader->urisrc), "user-agent", demux->user_agent, NULL);
2206   g_object_set (G_OBJECT (demux->fdownloader->urisrc), "ahs-streaming", TRUE, NULL);
2207   g_object_set (G_OBJECT (demux->fdownloader->urisrc), "blocksize", DEFAULT_BLOCKSIZE, NULL);
2208
2209   demux->fragDomain = gst_hlsdemux2_uri_get_domain(demux, uri);
2210   if(!g_strcmp0 (demux->fragDomain, demux->lastDomain) && demux->lastCookie) {
2211     g_strfreev(demux->fragCookie);
2212     demux->fragCookie = g_strdupv (demux->lastCookie);
2213   }
2214
2215   if (demux->fragCookie) {
2216     GST_DEBUG_OBJECT (demux, "Setting cookies before FRAG download goto PLAYING: %s", *(demux->fragCookie));
2217     g_object_set (demux->fdownloader->urisrc, "cookies", demux->fragCookie, NULL);
2218   }
2219
2220   srcpad = gst_element_get_static_pad (demux->fdownloader->urisrc, "src");
2221   if (!srcpad) {
2222     GST_ERROR_OBJECT (demux, "failed to get source pad from urisrc...");
2223     return FALSE;
2224   }
2225
2226   gst_pad_add_event_probe (srcpad, G_CALLBACK (gst_hlsdemux2_fragurisrc_event_handler), demux);
2227   gst_pad_add_buffer_probe (srcpad, G_CALLBACK (gst_hlsdemux2_fragurisrc_buffer_handler), demux);
2228
2229   gst_object_unref (srcpad);
2230
2231   demux->fdownloader->queue = gst_element_factory_make ("queue2", "frag_queue");
2232   if (!demux->fdownloader->queue) {
2233     GST_ERROR_OBJECT (demux, "failed to create queue2");
2234     return FALSE;
2235   }
2236
2237   g_object_set (G_OBJECT (demux->fdownloader->queue),
2238     "max-size-buffers", 0,
2239     "max-size-bytes", 0,
2240     "max-size-time", 0 * GST_SECOND, NULL);
2241
2242   srcpad = gst_element_get_static_pad (demux->fdownloader->queue, "src");
2243   if (!srcpad) {
2244     GST_ERROR_OBJECT (demux, "failed to get source pad from fragment queue...");
2245     return FALSE;
2246   }
2247
2248   gst_pad_add_buffer_probe (srcpad, G_CALLBACK (gst_hlsdemux2_queue_buffer_handler), demux);
2249
2250   demux->fdownloader->typefind = gst_element_factory_make ("typefind", "typefinder");
2251   if (!demux->fdownloader->typefind) {
2252     GST_ERROR_OBJECT (demux, "failed to create typefind element");
2253     gst_object_unref (srcpad);
2254     return FALSE;
2255   }
2256
2257   gst_bin_add_many (GST_BIN (demux->fdownloader->pipe),
2258     demux->fdownloader->urisrc, demux->fdownloader->queue, demux->fdownloader->typefind, NULL);
2259
2260   if (!gst_element_link_many (demux->fdownloader->urisrc,
2261     demux->fdownloader->queue, demux->fdownloader->typefind, NULL)) {
2262     GST_ERROR_OBJECT (demux, "failed to link src, queue & typefind elements...");
2263     gst_object_unref (srcpad);
2264     return FALSE;
2265   }
2266
2267   /* typefind callback to determine file type */
2268   g_signal_connect (demux->fdownloader->typefind, "have-type", G_CALLBACK (gst_hlsdemux2_have_type_cb), demux);
2269
2270   gst_object_unref (srcpad);
2271
2272   return TRUE;
2273 }
2274
2275 static void
2276 gst_hlsdemux2_destroy_fragment_download (GstHLSDemux2 * demux)
2277 {
2278   if (demux->fdownloader->pipe) {
2279     GST_DEBUG_OBJECT (demux, "completely closing fragment downloader pipeline");
2280     gst_element_set_state (demux->fdownloader->pipe, GST_STATE_NULL);
2281     gst_element_get_state (demux->fdownloader->pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
2282     GST_DEBUG_OBJECT (demux, "completely closed fragment downloader pipeline");
2283     gst_object_unref (demux->fdownloader->pipe);
2284     demux->has_image_buffer = FALSE;
2285     demux->fdownloader->pipe = NULL;
2286     demux->fdownloader->cur_stream_cnt = 0;
2287     g_list_free (demux->fdownloader->sinkbins); // all sink elements will be unreffed when pipeline is unreffed
2288     demux->fdownloader->sinkbins = 0;
2289   }
2290 }
2291
2292 static gboolean
2293 gst_hlsdemux2_download_fragment (GstHLSDemux2 *demux, const gchar * uri)
2294 {
2295   GstStateChangeReturn ret;
2296
2297   g_mutex_lock (demux->fdownloader->lock);
2298
2299   if (demux->cancelled || demux->flushing) {
2300     GST_WARNING_OBJECT (demux,"returning from download fragment due to cancel or flushing..");
2301     g_mutex_unlock (demux->fdownloader->lock);
2302     return FALSE;
2303   }
2304
2305   if (demux->frag_uri) {
2306     g_free (demux->frag_uri);
2307   }
2308   demux->frag_uri = g_strdup (uri);
2309
2310   demux->fdownloader->get_next_frag = FALSE;
2311
2312   if (!gst_hlsdemux2_create_fragment_download (demux, uri)) {
2313     GST_ERROR_OBJECT (demux, "failed to create download pipeline");
2314     g_mutex_unlock (demux->fdownloader->lock);
2315     return FALSE;
2316   }
2317
2318   /* download rate calculation : note down start time*/
2319   demux->fdownloader->download_start_ts = gst_util_get_timestamp();
2320   GST_INFO_OBJECT (demux, "download start_ts = %"G_GUINT64_FORMAT, demux->fdownloader->download_start_ts);
2321
2322   ret = gst_element_set_state (demux->fdownloader->pipe, GST_STATE_PLAYING);
2323   if (ret == GST_STATE_CHANGE_FAILURE) {
2324     GST_ERROR_OBJECT (demux, "set_state failed...");
2325     g_mutex_unlock (demux->fdownloader->lock);
2326     return FALSE;
2327   }
2328   gst_element_get_state (demux->fdownloader->pipe, NULL, NULL, -1);
2329
2330   /* wait until:
2331    *   - the download succeed (EOS)
2332    *   - the download failed (Error message on the fetcher bus)
2333    *   - the download was canceled
2334    */
2335   GST_DEBUG_OBJECT (demux, "Waiting to fetch the URI");
2336   g_cond_wait (demux->fdownloader->cond, demux->fdownloader->lock);
2337   GST_INFO_OBJECT (demux, "Recived signal to shutdown...");
2338
2339   if (demux->fragCookie)
2340     g_strfreev (demux->fragCookie);
2341
2342   g_object_get (demux->fdownloader->urisrc, "cookies", &demux->fragCookie, NULL);
2343
2344   GST_DEBUG_OBJECT (demux, "Got cookies after FRAG download : %s", demux->fragCookie ? *(demux->fragCookie) : NULL);
2345
2346   if (demux->fdownloader->applied_fast_switch) {
2347     if (demux->fdownloader->src_downloaded_size == demux->fdownloader->content_size) {
2348       /* to handle case, when both fast_switch & bus_callback signalled at same moment */
2349       GST_WARNING_OBJECT (demux, "ignoring fast_switch as fragment download is completed...");
2350       demux->fdownloader->applied_fast_switch = FALSE;
2351     } else {
2352       GST_WARNING_OBJECT (demux, "decrement the media sequence by one, due to fast_switch");
2353       gst_m3u8_client_decrement_sequence (demux->client);
2354     }
2355   }
2356
2357   if (demux->cancelled || demux->flushing ||
2358       demux->fdownloader->get_next_frag || demux->fdownloader->applied_fast_switch) {
2359     GstBuffer *buf = NULL;
2360     guint idx = 0;
2361
2362     /* clear stream queues if we already downloaded some data */
2363     for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
2364       GstHLSDemux2Stream *stream = demux->streams[idx];
2365       if (stream ) {
2366         while (!g_queue_is_empty (stream->downloader_queue)) {
2367           buf = g_queue_pop_head (stream->downloader_queue);
2368           gst_buffer_unref (buf);
2369         }
2370         GST_LOG_OBJECT (stream->pad, "cleared stream download queue...");
2371         g_queue_clear (stream->downloader_queue);
2372       }
2373     }
2374   }
2375
2376   if(demux->fragCookie){
2377     g_strfreev(demux->lastCookie);
2378     g_free(demux->lastDomain);
2379     demux->lastCookie = g_strdupv(demux->fragCookie);
2380     demux->lastDomain = g_strdup(demux->fragDomain);
2381   }
2382
2383   if(demux->active_stream_cnt == 1 && !demux->private_stream) {
2384     gchar *image_header = NULL;
2385     GValue codec_type = G_VALUE_INIT;
2386     GValue image_data = G_VALUE_INIT;
2387     GstMessage * tag_message = NULL;
2388     struct stat stat_results;
2389     gint iread = 0;
2390     GstBuffer *image_buffer = NULL;
2391     GstTagList * tag_list = gst_tag_list_new();
2392     int dummy_fp = -1;
2393
2394     GST_INFO_OBJECT (demux, "Going to show fixed image");
2395     dummy_fp = open (PREDEFINED_IMAGE_FRAME_LOCATION, O_RDONLY);
2396     if (dummy_fp < 0) {
2397       GST_WARNING_OBJECT (demux, "failed to open fixed image file : %s...", PREDEFINED_IMAGE_FRAME_LOCATION);
2398       goto skip_posting_image;
2399     }
2400
2401     GST_LOG_OBJECT (demux, "opened fixed image file %s successfully...", PREDEFINED_IMAGE_FRAME_LOCATION);
2402
2403     if (fstat (dummy_fp, &stat_results) < 0) {
2404       GST_WARNING_OBJECT (demux, "failed to get stats of a file...");
2405       close (dummy_fp);
2406       goto skip_posting_image;
2407     }
2408
2409     GST_LOG_OBJECT (demux, "size of the dummy file = %d", stat_results.st_size);
2410
2411     image_buffer = gst_buffer_new_and_alloc (stat_results.st_size);
2412     if (!image_buffer) {
2413       GST_ERROR_OBJECT (demux, "failed to allocate memory...");
2414       GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
2415       close (dummy_fp);
2416       goto error;
2417     }
2418
2419     iread = read (dummy_fp, GST_BUFFER_DATA (image_buffer), stat_results.st_size);
2420
2421     GST_LOG_OBJECT (demux, "read size = %d successfully", iread);
2422
2423     close (dummy_fp);
2424
2425     /* check whether it is same as previous image */
2426     if (demux->prev_image_buffer &&
2427       (GST_BUFFER_SIZE(demux->prev_image_buffer) == GST_BUFFER_SIZE(image_buffer))) {
2428       if (!memcmp (GST_BUFFER_DATA(demux->prev_image_buffer), GST_BUFFER_DATA(image_buffer), GST_BUFFER_SIZE(image_buffer))) {
2429         GST_INFO_OBJECT (demux, "current & previous embedded images are same..no need to post image again");
2430         gst_buffer_unref (image_buffer);
2431         goto skip_posting_image;
2432       }
2433     }
2434
2435     if (demux->prev_image_buffer) {
2436       gst_buffer_unref (demux->prev_image_buffer);
2437     }
2438     demux->prev_image_buffer = gst_buffer_copy(image_buffer);
2439
2440     g_value_init (&codec_type, G_TYPE_STRING);
2441     g_value_init (&image_data, GST_TYPE_BUFFER);
2442     gst_value_set_buffer(&image_data, image_buffer);
2443
2444     image_header = g_strndup((gchar *) image_buffer->data, 8);
2445
2446     if((image_header[0] == 0xFF) && (image_header[1] == 0xD8)) {
2447       GST_INFO_OBJECT(demux, "Found JPEG image header");
2448       g_value_set_static_string (&codec_type, "image/jpeg");
2449       gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
2450     } else if (!g_strcmp0(image_header, "\211PNG\015\012\032\012")) {
2451       GST_INFO_OBJECT(demux, "Found PNG image header");
2452       g_value_set_static_string (&codec_type, "image/png");
2453       gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
2454     } else {
2455       g_value_set_static_string (&codec_type, "image/unknown");
2456       GST_INFO_OBJECT(demux, "Unknown image header");
2457       gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
2458     }
2459
2460     gst_tag_list_add_value (tag_list, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, &image_data);
2461
2462     GST_INFO_OBJECT(demux, "Set value : %s", g_value_get_string (&codec_type));
2463     g_value_unset(&codec_type);
2464
2465     tag_message = gst_message_new_tag (GST_OBJECT_CAST (demux), tag_list);
2466     if(!gst_element_post_message (GST_ELEMENT_CAST (demux), tag_message)) {
2467       GST_ERROR_OBJECT (demux, "failed to post fixed image tag");
2468     }
2469
2470     GST_INFO_OBJECT (demux, "successfully posted image tag...");
2471     gst_buffer_unref (image_buffer);
2472     g_free (image_header);
2473   }
2474
2475 skip_posting_image:
2476
2477   gst_hlsdemux2_destroy_fragment_download (demux);
2478
2479   if (demux->fdownloader->remaining_data) {
2480     free (demux->fdownloader->remaining_data);
2481     demux->fdownloader->remaining_data = NULL;
2482   }
2483
2484   demux->fdownloader->remaining_size = 0;
2485   demux->fdownloader->src_downloaded_size = 0;
2486   demux->fdownloader->queue_downloaded_size = 0;
2487   demux->fdownloader->download_stop_ts = demux->fdownloader->download_start_ts = 0;
2488   demux->fdownloader->applied_fast_switch = FALSE;
2489   demux->fdownloader->content_size = 0;
2490
2491   if (demux->cancelled || demux->flushing) {
2492     GST_WARNING_OBJECT (demux, "returning false due to flushing/cancelled");
2493     goto error;
2494   } else if (demux->fdownloader->get_next_frag || demux->fdownloader->applied_fast_switch) {
2495     GST_INFO_OBJECT (demux, "Requesting next fragment due to error or same sequence number from different variant");
2496     goto exit;
2497   }
2498
2499   demux->fdownloader->ndownloaded++;
2500
2501   GST_INFO_OBJECT (demux, "number of fragments downloaded = %d", demux->fdownloader->ndownloaded);
2502
2503   /* reset the count */
2504   demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
2505
2506 exit:
2507   if (demux->private_stream) {
2508     g_free (demux->private_stream);
2509     demux->private_stream = NULL;
2510   }
2511   g_mutex_unlock (demux->fdownloader->lock);
2512
2513   return TRUE;
2514
2515 error:
2516   if (demux->private_stream) {
2517     g_free (demux->private_stream);
2518     demux->private_stream = NULL;
2519   }
2520   g_mutex_unlock (demux->fdownloader->lock);
2521
2522   return FALSE;
2523 }
2524
2525 static gboolean
2526 gst_hlsdemux2_change_playlist (GstHLSDemux2 * demux, guint max_bitrate, gboolean *is_switched)
2527 {
2528   GList *previous_variant, *current_variant;
2529   gint old_bandwidth, new_bandwidth;
2530
2531   previous_variant = demux->client->main->current_variant;
2532   current_variant = gst_m3u8_client_get_playlist_for_bitrate (demux->client, max_bitrate);
2533
2534   old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
2535   new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
2536
2537   /* Don't do anything else if the playlist is the same */
2538   if (new_bandwidth == old_bandwidth) {
2539     if (is_switched)
2540       *is_switched = FALSE;
2541     return TRUE;
2542   }
2543
2544   GST_M3U8_CLIENT_LOCK (demux->client);
2545   demux->client->main->current_variant = current_variant;
2546   GST_M3U8_CLIENT_UNLOCK (demux->client);
2547
2548   gst_m3u8_client_set_current (demux->client, current_variant->data);
2549
2550   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
2551       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
2552
2553   gst_hlsdemux2_apply_disc(demux);
2554
2555   if (is_switched)
2556     *is_switched = TRUE;
2557
2558   return TRUE;
2559 }
2560
2561 static gboolean
2562 gst_hlsdemux2_get_next_fragment (GstHLSDemux2 * demux, gboolean *is_error)
2563 {
2564   const gchar *next_fragment_uri = NULL;;
2565   gchar *next_fragment_key_uri = NULL;
2566   gchar *iv = NULL;
2567   GstClockTime duration;
2568   GstClockTime timestamp;
2569   gboolean discont = FALSE;
2570   gboolean bret = TRUE;
2571   GstClockTime lookup_time = 0;
2572   guint i = 0;
2573   GstHLSDemux2Stream *stream = NULL;
2574
2575   if (!demux->is_live) {
2576     for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
2577       stream = demux->streams[i];
2578       if (stream) {
2579         lookup_time = stream->lts + stream->frame_duration + (0.5 * GST_SECOND);
2580         GST_INFO_OBJECT (stream->pad, "Lookup time = %"GST_TIME_FORMAT, GST_TIME_ARGS(lookup_time));
2581         stream->frame_duration = 0;
2582         if (stream->type == HLSDEMUX2_STREAM_AUDIO)
2583           break;
2584       }
2585     }
2586   }
2587
2588   if (!gst_m3u8_client_get_next_fragment (demux->client, lookup_time,
2589     &discont, &next_fragment_uri, &duration, &timestamp, &next_fragment_key_uri, &iv)) {
2590
2591     GST_INFO_OBJECT (demux, "This playlist doesn't contain more fragments");
2592
2593     if (demux->is_live && (demux->client->update_failed_count < DEFAULT_FAILED_COUNT)) {
2594       GST_WARNING_OBJECT (demux, "Could not get next fragment, try again after updating playlist...");
2595       *is_error = FALSE;
2596       return FALSE;
2597     } else {
2598       goto end_of_list;
2599     }
2600   }
2601
2602   demux->cfrag_dur = duration;
2603   demux->fdownloader->cur_running_dur += duration;
2604
2605   GST_LOG_OBJECT (demux, "current running duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->fdownloader->cur_running_dur));
2606
2607   GST_DEBUG_OBJECT (demux, "Fetching next fragment = %s & key uri = %s", next_fragment_uri, next_fragment_key_uri);
2608
2609   /* when hls requests next fragment due to some error like NOT_FOUND, then also we need to set apply disc */
2610   if (discont || demux->fdownloader->get_next_frag)
2611     gst_hlsdemux2_apply_disc (demux);
2612
2613   if (next_fragment_key_uri) {
2614     /* download key data & initialize decryption with key data & IV */
2615     GST_INFO_OBJECT (demux, "Fetching next fragment key %s", next_fragment_key_uri);
2616
2617     if (demux->kdownloader->prev_key_uri) {
2618       if (strcmp (demux->kdownloader->prev_key_uri, next_fragment_key_uri)) {
2619         /* if previous & current key uris are different, download new one */
2620         if (demux->kdownloader->key) {
2621           gst_buffer_unref (demux->kdownloader->key);
2622           demux->kdownloader->key = NULL;
2623         }
2624
2625         if (demux->kdownloader->prev_key_uri)
2626           g_free (demux->kdownloader->prev_key_uri);
2627
2628         demux->kdownloader->prev_key_uri = g_strdup(next_fragment_key_uri);
2629
2630         /* download the key data as there is a change */
2631         if (!gst_hlsdemux2_download_key (demux, next_fragment_key_uri)) {
2632           GST_ERROR_OBJECT (demux, "failed to download key...");
2633           goto error;
2634         }
2635       } else {
2636         GST_INFO_OBJECT (demux, "already having the key...no need to download again");
2637       }
2638     } else {
2639       if (demux->kdownloader->key) {
2640         gst_buffer_unref (demux->kdownloader->key);
2641         demux->kdownloader->key = NULL;
2642       }
2643
2644       demux->kdownloader->prev_key_uri = g_strdup(next_fragment_key_uri);
2645
2646       if (!gst_hlsdemux2_download_key (demux, next_fragment_key_uri)) {
2647         GST_ERROR_OBJECT (demux, "failed to download key...");
2648         goto error;
2649       }
2650       /* reset the count */
2651       demux->soup_request_fail_cnt = HLSDEMUX2_SOUP_FAILED_CNT;
2652     }
2653
2654     if (!demux->kdownloader->key || !GST_BUFFER_DATA (demux->kdownloader->key)) {
2655       GST_ERROR_OBJECT (demux, "eos received without key content...");
2656       goto error;
2657     }
2658
2659     if (!gst_m3u8_client_decrypt_init (demux->client, GST_BUFFER_DATA (demux->kdownloader->key), iv)) {
2660       GST_ERROR_OBJECT (demux, "failed to initialize AES decryption...");
2661       goto error;
2662     }
2663
2664     demux->fdownloader->is_encrypted = TRUE;
2665   }
2666
2667   if (!gst_hlsdemux2_download_fragment (demux, next_fragment_uri)) {
2668     GST_ERROR_OBJECT (demux, "failed to download fragment...");
2669     goto error;
2670   }
2671
2672 exit:
2673   if (next_fragment_uri)
2674     g_free ((gpointer)next_fragment_uri);
2675   if (next_fragment_key_uri)
2676     g_free ((gpointer)next_fragment_key_uri);
2677   if (iv)
2678     g_free ((gpointer)iv);
2679
2680   return bret;
2681
2682 error:
2683   if (!demux->flushing)
2684     *is_error = TRUE;
2685   bret = FALSE;
2686   goto exit;
2687
2688  end_of_list:
2689   GST_INFO_OBJECT (demux, "Reached end of playlist, sending EOS");
2690
2691   gst_hlsdemux2_push_eos (demux);
2692
2693   demux->end_of_playlist = TRUE;
2694   bret = FALSE;
2695   goto exit;
2696 }
2697
2698
2699 static gboolean
2700 gst_hlsdemux2_switch_playlist (GstHLSDemux2 * demux, gboolean *is_switched)
2701 {
2702   GST_M3U8_CLIENT_LOCK (demux->client);
2703   if (!demux->client->main->lists) {
2704     /* not a variant to switch */
2705     GST_M3U8_CLIENT_UNLOCK (demux->client);
2706     GST_INFO_OBJECT (demux, "not a variant to switch...");
2707     return TRUE;
2708   }
2709   GST_M3U8_CLIENT_UNLOCK (demux->client);
2710
2711   if (demux->force_lower_bitrate && (demux->fdownloader->ndownloaded % FORCE_LOW_BITRATE_AFTER_CNT == 0)) {
2712     demux->fdownloader->download_rate = 0; // Using some temp lowest value
2713     GST_WARNING_OBJECT (demux, "resetting to lowest one bitrate = %"G_GUINT64_FORMAT, demux->fdownloader->download_rate);
2714   }
2715
2716   return gst_hlsdemux2_change_playlist (demux, demux->fdownloader->download_rate, is_switched);
2717 }
2718
2719 static void
2720 gst_hlsdemux2_apply_disc (GstHLSDemux2 * demux)
2721 {
2722   int i = 0;
2723   GstHLSDemux2Stream *stream = NULL;
2724
2725   for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
2726     stream = demux->streams[i];
2727
2728     if (stream) {
2729       stream->apply_disc = TRUE;
2730       GST_INFO_OBJECT (stream->pad, "apply discontinuity...");
2731     }
2732   }
2733 }
2734
2735 static void
2736 gst_hlsdemux2_fragment_download_loop (GstHLSDemux2 * demux)
2737 {
2738   gboolean is_error = FALSE;
2739   gboolean bret = FALSE;
2740   GTimeVal tmp_update = {0, };
2741   GTimeVal current;
2742   guint64 current_time = 0;
2743   guint64 nextupdate_time = 0;
2744
2745   /* if variant playlist, get current subplaylist first */
2746   if (gst_m3u8_client_has_variant_playlist(demux->client)) {
2747     gboolean is_error = FALSE;
2748
2749     if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
2750       GST_ERROR_OBJECT (demux, "failed to update playlist. uri : %s", gst_m3u8_client_get_current_uri(demux->client));
2751       GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update the playlist"), (NULL));
2752       goto exit;
2753     }
2754   } else if (demux->is_live) {
2755     /* single variant live.. so schedule for starting */
2756     if (demux->is_live)
2757       gst_hlsdemux2_schedule (demux);
2758   }
2759
2760   if (demux->fdownloader->find_mediaseq) {
2761     GList *walk;
2762     GstClockTime current_pos, target_pos;
2763     gint current_sequence;
2764     GstM3U8MediaFile *file;
2765     guint i = 0;
2766     GstHLSDemux2Stream *stream = NULL;
2767
2768     GST_M3U8_CLIENT_LOCK (demux->client);
2769     file = GST_M3U8_MEDIA_FILE (demux->client->current->files->data);
2770     current_sequence = file->sequence;
2771     current_pos = 0 ;
2772     target_pos = demux->fdownloader->seeked_pos;
2773     for (walk = demux->client->current->files; walk; walk = walk->next) {
2774       file = walk->data;
2775
2776       current_sequence = file->sequence;
2777       if (current_pos <= target_pos &&
2778         target_pos < current_pos + file->duration) {
2779         break;
2780       }
2781       current_pos += file->duration;
2782     }
2783     GST_M3U8_CLIENT_UNLOCK (demux->client);
2784
2785     if (walk == NULL) {
2786       GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
2787     }
2788     GST_M3U8_CLIENT_LOCK (demux->client);
2789     GST_INFO_OBJECT (demux, "seeking to sequence %d", current_sequence);
2790     demux->client->sequence = current_sequence;
2791     GST_M3U8_CLIENT_UNLOCK (demux->client);
2792     demux->ns_start = demux->fdownloader->cur_running_dur = current_pos;  // NON-accurate seek
2793
2794     for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
2795       stream = demux->streams[i];
2796 #ifdef LATEST_AV_SYNC
2797       if (stream) {
2798         stream->lts = stream->total_stream_time = current_pos;
2799         GST_INFO_OBJECT (stream->pad, "Changed stream->lts to %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts));
2800       }
2801 #else
2802       if (stream && stream->type == HLSDEMUX2_STREAM_AUDIO) {
2803         stream->lts  = current_pos;
2804       }
2805 #endif
2806     }
2807
2808     demux->fdownloader->find_mediaseq = FALSE;
2809   }
2810
2811   demux->target_duration = gst_m3u8_client_get_target_duration(demux->client);
2812   demux->total_cache_duration = DEFAULT_NUM_FRAGMENTS_CACHE * demux->target_duration;
2813   demux->is_live = gst_m3u8_client_is_live(demux->client);
2814
2815   GST_INFO_OBJECT (demux, "Total cache duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->total_cache_duration));
2816
2817   while (TRUE) {
2818
2819     if (demux->cancelled)
2820       goto exit;
2821
2822     /* get the next fragement */
2823     bret = gst_hlsdemux2_get_next_fragment (demux, &is_error);
2824
2825     if (!bret) {
2826       if (is_error) {
2827         GST_ERROR_OBJECT (demux, "error in getting next fragment");
2828         GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("could not download fragment"), (NULL));
2829         goto exit;
2830       } else {
2831         if (!demux->end_of_playlist) {
2832           if (demux->flushing) {
2833             GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
2834             goto exit;
2835           } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
2836             GST_WARNING_OBJECT (demux, "Could not update fragment & playlist update failed count = %d",
2837               demux->client->update_failed_count);
2838           } else {
2839             GST_ERROR_OBJECT (demux, "Could not get next fragment..");
2840             GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not get next fragment..."), (NULL));
2841             goto exit;
2842           }
2843         } else {
2844           GST_INFO_OBJECT (demux, "end of fragment download, doing pause");
2845           goto exit;
2846         }
2847       }
2848     } else {
2849       /* reset the update failed count */
2850       demux->client->update_failed_count = 0;
2851     }
2852
2853     if (demux->cancelled)
2854       goto exit;
2855
2856     if (demux->is_live) {
2857       /* get the current time */
2858       current.tv_sec = current.tv_usec = 0;
2859       g_get_current_time (&current);
2860
2861       current_time = (current.tv_sec * 1000000)+ current.tv_usec;
2862       nextupdate_time = (demux->next_update.tv_sec * 1000000)+ demux->next_update.tv_usec;
2863     }
2864
2865     if (demux->is_live && ((current_time > nextupdate_time) || !bret)) {
2866       gboolean is_switched = FALSE;
2867
2868       /* try to switch to another bitrate if needed */
2869       // TODO: take care of return value
2870       gst_hlsdemux2_switch_playlist (demux, &is_switched);
2871
2872       g_mutex_lock (demux->pl_update_lock);
2873
2874       /*  block until the next scheduled update or the exit signal */
2875       bret = g_cond_timed_wait (demux->pl_update_cond, demux->pl_update_lock, &demux->next_update);
2876
2877       g_mutex_unlock (demux->pl_update_lock);
2878
2879       GST_DEBUG_OBJECT (demux, "playlist update wait is completed. reason : %s",  bret ? "Received signal" : "time-out");
2880
2881       tmp_update.tv_sec = 0;
2882       tmp_update.tv_usec = 0;
2883
2884       g_get_current_time (&tmp_update);
2885
2886       if (bret) {
2887         GST_DEBUG_OBJECT (demux, "Sombody signalled manifest waiting... going to exit and diff = %ld",
2888             ((demux->next_update.tv_sec * 1000000)+ demux->next_update.tv_usec) - ((tmp_update.tv_sec * 1000000)+ tmp_update.tv_usec));
2889         goto exit;
2890       } else if (demux->cancelled) {
2891         GST_WARNING_OBJECT (demux, "closing is in progress..exit now");
2892         goto exit;
2893       }
2894
2895       if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
2896         if (is_error) {
2897           GST_ERROR_OBJECT (demux, "failed to update playlist...");
2898           GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to update playlist"), (NULL));
2899           goto exit;
2900         } else {
2901           if (demux->flushing) {
2902             GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
2903             goto exit;
2904           } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
2905             GST_WARNING_OBJECT (demux, "Could not update playlist & playlist update failed count = %d",
2906               demux->client->update_failed_count);
2907             continue;
2908           } else {
2909             GST_ERROR_OBJECT (demux, "Could not update playlist..");
2910             GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update playlist..."), (NULL));
2911             goto exit;
2912           }
2913         }
2914       }
2915
2916     } else {
2917       gboolean is_switched = FALSE;
2918
2919       /* try to switch to another bitrate if needed */
2920       // TODO: take care of return value
2921
2922       /* when in recovery mode, do not obey download rates */
2923       if (demux->pldownloader->recovery_mode == HLSDEMUX2_NO_RECOVERY)
2924         gst_hlsdemux2_switch_playlist (demux, &is_switched);
2925
2926       if (is_switched) {
2927         if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
2928           if (is_error) {
2929             GST_ERROR_OBJECT (demux, "failed to update playlist...");
2930             GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to update playlist"), (NULL));
2931             goto exit;
2932           } else {
2933             if (demux->flushing) {
2934               GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
2935               goto exit;
2936             } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
2937               GST_WARNING_OBJECT (demux, "Could not update playlist & playlist update failed count = %d",
2938                 demux->client->update_failed_count);
2939               continue;
2940             } else {
2941               GST_ERROR_OBJECT (demux, "Could not update playlist..");
2942               GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update playlist..."), (NULL));
2943               goto exit;
2944             }
2945           }
2946         }
2947       } else if (demux->is_live) {
2948         GstClockTime current_time = gst_util_get_timestamp();
2949
2950         if ((current_time - demux->pldownloader->download_start_ts) <
2951           (PLAYLIST_REFRESH_TIMEOUT - (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration) - HLSDEMUX2_OVERHEAD)) {
2952           GST_INFO_OBJECT (demux, "Eligible to download next fragment w/o playlist update : "
2953             "elapsed time since last playlist request = %"GST_TIME_FORMAT" and max_time_limit = %"GST_TIME_FORMAT,
2954             GST_TIME_ARGS(current_time - demux->pldownloader->download_start_ts),
2955             GST_TIME_ARGS(PLAYLIST_REFRESH_TIMEOUT - (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration) - HLSDEMUX2_OVERHEAD));
2956         } else {
2957
2958           GST_INFO_OBJECT (demux, "NOT Eligible to download next fragment w/o playlist update : "
2959             "elapsed time since previous request = %"GST_TIME_FORMAT" and max_time_limit = %"GST_TIME_FORMAT,
2960             GST_TIME_ARGS(current_time - demux->pldownloader->download_start_ts),
2961             GST_TIME_ARGS(PLAYLIST_REFRESH_TIMEOUT - (HLSDEMUX2_FAST_CHECK_CRITICAL_TIME_FACTOR * demux->target_duration) - HLSDEMUX2_OVERHEAD));
2962
2963           /* we are not eligible to download, next fragment.. So wait till next playlist update */
2964           g_mutex_lock (demux->pl_update_lock);
2965           /*  block until the next scheduled update or the exit signal */
2966           bret = g_cond_timed_wait (demux->pl_update_cond, demux->pl_update_lock, &demux->next_update);
2967           g_mutex_unlock (demux->pl_update_lock);
2968
2969           GST_DEBUG_OBJECT (demux, "playlist update wait is completed. reason : %s",  bret ? "Received signal" : "time-out");
2970
2971           tmp_update.tv_sec = 0;
2972           tmp_update.tv_usec = 0;
2973
2974           g_get_current_time (&tmp_update);
2975
2976           if (bret) {
2977             GST_DEBUG_OBJECT (demux, "Sombody signalled manifest waiting... going to exit and diff = %ld",
2978                 ((demux->next_update.tv_sec * 1000000)+ demux->next_update.tv_usec) - ((tmp_update.tv_sec * 1000000)+ tmp_update.tv_usec));
2979             goto exit;
2980           } else if (demux->cancelled) {
2981             GST_WARNING_OBJECT (demux, "closing is in progress..exit now");
2982             goto exit;
2983           }
2984
2985           if (!gst_hlsdemux2_update_playlist (demux, FALSE, &is_error)) {
2986             if (is_error) {
2987               GST_ERROR_OBJECT (demux, "failed to update playlist...");
2988               GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to update playlist"), (NULL));
2989               goto exit;
2990             } else {
2991               if (demux->flushing) {
2992                 GST_WARNING_OBJECT (demux, "SEEK is in progress.. pause the task");
2993                 goto exit;
2994               } else if (demux->client->update_failed_count < DEFAULT_FAILED_COUNT) {
2995                 GST_WARNING_OBJECT (demux, "Could not update playlist & playlist update failed count = %d",
2996                   demux->client->update_failed_count);
2997                 continue;
2998               } else {
2999                 GST_ERROR_OBJECT (demux, "Could not update playlist..");
3000                 GST_ELEMENT_ERROR (demux, RESOURCE, NOT_FOUND, ("Could not update playlist..."), (NULL));
3001                 goto exit;
3002               }
3003             }
3004           }
3005         }
3006       }
3007     }
3008   }
3009
3010 exit:
3011   GST_WARNING_OBJECT (demux, "Going to PAUSE download task from self");
3012   gst_task_pause (demux->download_task);
3013   return;
3014 }
3015
3016 static void
3017 gst_hlsdemux2_calculate_popped_duration (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
3018     GstBuffer *outbuf)
3019 {
3020   gpointer data = NULL;
3021   gint i = g_queue_get_length (stream->queue);
3022
3023   /* get the buffer with valid timestamp from tail of the queue */
3024   while (i > 1) {
3025     data = g_queue_peek_nth (stream->queue, (i - 1));
3026     if (data == NULL) {
3027       return;
3028     }
3029
3030     if (GST_IS_BUFFER ((GstBuffer *)data)) {
3031       if (GST_BUFFER_TIMESTAMP_IS_VALID(data)) {
3032         /* found valid timestamp & stop searching */
3033         GST_LOG_OBJECT (stream->pad, "data found buffer with valid ts = %"GST_TIME_FORMAT " len = %d & i = %d",
3034           GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(data)), g_queue_get_length (stream->queue), i);
3035         break;
3036       }
3037     }
3038     i--;
3039   }
3040
3041   if (data == NULL) {
3042     return;
3043   }
3044
3045   if (GST_BUFFER_TIMESTAMP (outbuf) <= GST_BUFFER_TIMESTAMP ((GstBuffer *)data)) {
3046     stream->cached_duration = GST_BUFFER_TIMESTAMP ((GstBuffer *)data) - GST_BUFFER_TIMESTAMP (outbuf);
3047     GST_DEBUG_OBJECT (stream->pad, "cache duration in popping : %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->cached_duration));
3048   } else {
3049     GST_ERROR_OBJECT (stream->pad, "Wrong order.. not calculating");
3050   }
3051
3052   return;
3053 }
3054
3055 static void
3056 gst_hlsdemux2_push_loop (GstHLSDemux2Stream *stream)
3057 {
3058   GstHLSDemux2 *demux = stream->parent;
3059   GstFlowReturn fret = GST_FLOW_OK;
3060   gpointer data = NULL;
3061
3062   // TODO: need to take care of EOS handling....
3063
3064   if (demux->cancelled || demux->flushing)
3065     goto error;
3066
3067   g_mutex_lock (stream->queue_lock);
3068
3069   if (g_queue_is_empty (stream->queue)) {
3070     GST_LOG_OBJECT (stream->pad,"queue is empty wait till, some buffers are available...");
3071     g_cond_wait (stream->queue_empty, stream->queue_lock);
3072     GST_LOG_OBJECT (stream->pad,"Received queue empty signal...");
3073   }
3074
3075   if (demux->cancelled || demux->flushing) {
3076     GST_ERROR_OBJECT (stream->pad, "Shutting down push loop");
3077     g_mutex_unlock (stream->queue_lock);
3078     goto error;
3079   }
3080
3081   if (g_queue_is_empty (stream->queue)) {
3082     GST_ERROR_OBJECT (stream->pad, "Queue empty undesired....");
3083     g_mutex_unlock (stream->queue_lock);
3084     goto error;
3085   }
3086
3087   data = g_queue_pop_head (stream->queue);
3088   if (!data) {
3089     GST_ERROR_OBJECT (stream->pad, "Received null data...");
3090     GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Unhandled GstObjectType"), (NULL));
3091     g_mutex_unlock (stream->queue_lock);
3092     goto error;
3093   }
3094
3095   /*  Calculate duration only when
3096     *  1. popped obj is a buffer and
3097     *  2. buffer has valid ts and
3098     *  3. queue length > 1
3099    */
3100
3101   if (GST_IS_BUFFER(data) &&
3102      GST_BUFFER_TIMESTAMP_IS_VALID(data) ) {
3103
3104     /* calculate buffering duration */
3105     gst_hlsdemux2_calculate_popped_duration (demux, stream, data);
3106
3107     if (stream->cached_duration < 0) {
3108       GST_WARNING_OBJECT (stream->pad, "Wrong cached duration in push_loop...\n");
3109       stream->cached_duration = 0;
3110     }
3111   }
3112
3113   g_mutex_unlock (stream->queue_lock);
3114
3115   if (GST_IS_EVENT(data)) {
3116     GstEvent *event = (GstEvent *)data;
3117
3118     switch (GST_EVENT_TYPE (event)) {
3119       case GST_EVENT_NEWSEGMENT: {
3120         GstFormat format;
3121         gboolean update;
3122         gdouble rate, arate;
3123         gint64 start, stop, pos;
3124         gst_event_parse_new_segment_full(event, &update, &rate, &arate, &format, &start, &stop, &pos);
3125         GST_INFO_OBJECT (stream->pad, "Pushing newsegment to downstream : rate = %0.3f, start = %"GST_TIME_FORMAT
3126           ", stop = %"GST_TIME_FORMAT, rate, GST_TIME_ARGS(start), GST_TIME_ARGS(stop));
3127       }
3128       break;
3129       case GST_EVENT_EOS:
3130       GST_INFO_OBJECT (stream->pad, "going to push eos event to downstream");
3131       stream->eos = TRUE;
3132       break;
3133       default:
3134       GST_ERROR_OBJECT (stream->pad, "not handled event...still pushing event");
3135       break;
3136     }
3137     if (!gst_pad_push_event (stream->pad, event)) {
3138       GST_ERROR_OBJECT (demux, "failed to push newsegment event");
3139       GST_ELEMENT_ERROR (demux, CORE, PAD, ("failed to push '%s' event", GST_EVENT_TYPE_NAME(event)), (NULL));
3140       goto error;
3141     }
3142
3143     GST_INFO_OBJECT (stream->pad, "Pushed '%s' event...", GST_EVENT_TYPE_NAME(event));
3144
3145     if (stream->eos) {
3146       //gst_element_post_message (GST_ELEMENT_CAST (stream->sink), gst_message_new_eos (GST_OBJECT_CAST(stream->sink)));
3147       GST_INFO_OBJECT (stream->pad, "Pausing the task");
3148       goto error;
3149     }
3150   } else if (GST_IS_BUFFER(data)) {
3151     GstCaps *temp_caps = NULL;
3152     g_cond_signal (stream->queue_full);
3153
3154     GST_DEBUG_OBJECT (stream->pad, "Pushing buffer : size = %d, ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
3155       GST_BUFFER_SIZE(data), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(data)), GST_TIME_ARGS(GST_BUFFER_DURATION(data)));
3156
3157     temp_caps = gst_buffer_get_caps((GstBuffer *)data);
3158     temp_caps = gst_caps_make_writable (temp_caps);
3159     gst_caps_set_simple (temp_caps,"hls_streaming", G_TYPE_BOOLEAN, TRUE, NULL);
3160     gst_buffer_set_caps((GstBuffer *)data, temp_caps);
3161     gst_caps_unref(temp_caps);
3162
3163     /* push data to downstream*/
3164     fret = gst_pad_push (stream->pad, data);
3165     if (fret != GST_FLOW_OK) {
3166       GST_ERROR_OBJECT (stream->pad, "failed to push data, reason : %s", gst_flow_get_name (fret));
3167       goto error;
3168     }
3169   } else {
3170     GST_ERROR_OBJECT (stream->pad, "unhandled object type..still pushing");
3171     //GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Unhandled GstObjectType"), (NULL));
3172     //return;
3173     gst_object_unref (data);
3174   }
3175
3176   if (demux->cancelled || demux->flushing) {
3177     goto error;
3178   }
3179
3180   return;
3181
3182 error:
3183   {
3184     GST_WARNING_OBJECT (stream->pad, "Pausing the push task...");
3185
3186     if (fret < GST_FLOW_UNEXPECTED) {
3187       GST_ERROR_OBJECT (stream->pad, "Crtical error in push loop....");
3188       GST_ELEMENT_ERROR (demux, CORE, PAD, ("failed to push. reason - %s", gst_flow_get_name (fret)), (NULL));
3189     }
3190
3191     gst_pad_pause_task (stream->pad);
3192     return;
3193   }
3194 }
3195
3196 // TODO: need to review change_playlist API
3197
3198 static gboolean
3199 gst_hlsdemux2_schedule (GstHLSDemux2 * demux)
3200 {
3201   gfloat update_factor;
3202   gint count;
3203   GstClockTime last_frag_duration;
3204
3205   /* As defined in Â§6.3.4. Reloading the Playlist file:
3206    * "If the client reloads a Playlist file and finds that it has not
3207    * changed then it MUST wait for a period of time before retrying.  The
3208    * minimum delay is a multiple of the target duration.  This multiple is
3209    * 0.5 for the first attempt, 1.5 for the second, and 3.0 thereafter."
3210    */
3211   count = demux->client->update_failed_count;
3212   if (count < 3)
3213     update_factor = update_interval_factor[count];
3214   else
3215     update_factor = update_interval_factor[3];
3216
3217   /* schedule the next update using the target duration field of the
3218    * playlist */
3219   demux->next_update.tv_sec = 0;
3220   demux->next_update.tv_usec = 0;
3221
3222   last_frag_duration = gst_m3u8_client_get_last_fragment_duration (demux->client);
3223
3224   GST_DEBUG_OBJECT (demux, "last fragment duration = %"GST_TIME_FORMAT" and next update = %"GST_TIME_FORMAT,
3225     GST_TIME_ARGS(last_frag_duration), GST_TIME_ARGS(GST_TIME_AS_USECONDS(last_frag_duration) * 1000));
3226
3227   g_get_current_time (&demux->next_update);
3228
3229   //g_time_val_add (&demux->next_update, last_frag_duration / GST_SECOND * G_USEC_PER_SEC * update_factor);
3230   g_time_val_add (&demux->next_update, GST_TIME_AS_USECONDS(last_frag_duration)* update_factor);
3231
3232   return TRUE;
3233 }
3234
3235 static void
3236 gst_hlsdemux2_new_pad_added (GstElement *element, GstPad *srcpad, gpointer data)
3237 {
3238   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
3239   GstPad *sinkpad = NULL;
3240   GstCaps *caps = NULL;
3241   HLSDemux2SinkBin *sinkbin = NULL;
3242   gchar *demuxer_name = NULL;
3243   gchar *src_pad_name = NULL;
3244
3245   GST_INFO_OBJECT (demux, "received the src_pad '%s' from mpeg2ts demuxer...", GST_PAD_NAME(srcpad));
3246
3247   if (strstr (GST_PAD_NAME(srcpad), "private")) {
3248     /* handle private image TAG */
3249     gst_hlsdemux2_handle_private_pad (demux, srcpad);
3250     return;
3251   }
3252
3253   caps = GST_PAD_CAPS (srcpad);
3254   demuxer_name = GST_ELEMENT_NAME (element);
3255
3256   sinkbin = gst_hlsdemux2_create_stream (demux, demuxer_name, caps);
3257   if (!sinkbin) {
3258     return;
3259   }
3260
3261   sinkpad = gst_element_get_pad(GST_ELEMENT(sinkbin->sinkbin), "sink");
3262   if (!sinkpad) {
3263     GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", GST_PAD_NAME(sinkbin->sinkbin));
3264     GST_ELEMENT_ERROR (demux, CORE, PAD, ("could not get sink pad"), (NULL));
3265     return;
3266   }
3267
3268   /* link demuxer srcpad & sink element's sink pad */
3269   if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
3270     GST_ERROR_OBJECT (demux, "failed to link pad '%s' &  sink's sink pad", GST_PAD_NAME(srcpad));
3271     GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
3272     gst_object_unref(sinkpad);
3273     return;
3274   }
3275
3276   if (sinkbin->parser) {
3277     GST_INFO_OBJECT (demux, "linking parser");
3278     if (!gst_element_link_many (sinkbin->queue, sinkbin->parser, sinkbin->sink, NULL)) {
3279       GST_ERROR_OBJECT (demux, "failed to link sink bin elements");
3280     GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
3281       gst_object_unref(sinkpad);
3282       return;
3283     }
3284   } else {
3285     if (!gst_element_link_many (sinkbin->queue, sinkbin->sink, NULL)) {
3286       GST_ERROR_OBJECT (demux, "failed to link sink bin elements");
3287       GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
3288       gst_object_unref(sinkpad);
3289       return;
3290     }
3291   }
3292   demux->fdownloader->cur_stream_cnt++;
3293
3294   src_pad_name = gst_pad_get_name(srcpad);
3295   GST_INFO_OBJECT (demux, "succesfully linked pad (%s) with stream pad and current stream cnt = %d",
3296     src_pad_name, demux->fdownloader->cur_stream_cnt);
3297   g_free(src_pad_name);
3298   src_pad_name = NULL;
3299
3300   gst_element_set_state (GST_ELEMENT(sinkbin->sinkbin), GST_STATE_PLAYING);
3301
3302   gst_object_unref (sinkpad);
3303 }
3304
3305 static gboolean
3306 gst_hlsdemux2_check_stream_type_exist (GstHLSDemux2 *demux, HLSDEMUX2_STREAM_TYPE stream_type)
3307 {
3308   int i = 0;
3309   GstHLSDemux2Stream *stream = NULL;
3310
3311   for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
3312     stream = demux->streams[i];
3313
3314     if (stream && (stream->type == stream_type)) {
3315       GST_INFO_OBJECT (demux, "stream type '%d' is already present", stream_type);
3316       return TRUE;
3317     }
3318   }
3319
3320   GST_INFO_OBJECT (demux, "received new stream type [%d]", stream_type);
3321
3322   return FALSE;
3323 }
3324
3325 static HLSDemux2SinkBin *
3326 gst_hlsdemux2_create_stream (GstHLSDemux2 *demux, gchar *demuxer_name, GstCaps *caps)
3327 {
3328   GstHLSDemux2Stream *stream = NULL;
3329   GstPad *sinkpad = NULL;
3330   GstPad *linkpad = NULL;
3331   HLSDEMUX2_STREAM_TYPE stream_type;
3332   gchar *element_name = NULL;
3333   gboolean stream_exist = FALSE;
3334   gulong sink_probe;
3335   HLSDemux2SinkBin *bin = NULL;
3336   GstStructure *structure = NULL;
3337   gchar *mime = NULL;
3338   gchar *stream_name = NULL;
3339
3340   stream = g_new0 (GstHLSDemux2Stream, 1);
3341
3342   structure = gst_caps_get_structure (caps, 0);
3343
3344   mime = gst_structure_get_name (structure);
3345
3346   if (strstr (mime, "video")) {
3347     stream_type = HLSDEMUX2_STREAM_VIDEO;
3348     GST_DEBUG_OBJECT (demux, "Its a Multi-variant, Audio only stream..");
3349     demux->stream_config = HLSDEMUX2_MULTI_VARIANT;
3350     stream_name = g_strdup ("video");
3351   } else if (strstr (mime, "audio")) {
3352     stream_type = HLSDEMUX2_STREAM_AUDIO;
3353     stream_name = g_strdup ("audio");
3354   } else if (strstr (mime, "subpicture")) {
3355     stream_type = HLSDEMUX2_STREAM_TEXT;
3356     stream_name = g_strdup ("subpicture");
3357   } else if (strstr (mime, "private")) {
3358     stream_type = HLSDEMUX2_STREAM_PRIVATE;
3359     stream_name = g_strdup ("private");
3360   } else {
3361     GST_ELEMENT_ERROR (demux, CORE, PAD, ("Received unknown named pad"), (NULL));
3362     goto error;
3363   }
3364
3365   stream_exist = gst_hlsdemux2_check_stream_type_exist (demux, stream_type);
3366
3367   if (!stream_exist) {
3368     stream = g_new0 (GstHLSDemux2Stream, 1);
3369     gst_hlsdemux2_stream_init (demux, stream, stream_type, stream_name, caps);
3370
3371     if (!stream->is_linked) {
3372       goto error;
3373     }
3374   } else {
3375     int i = 0;
3376
3377     for (i = 0; i< HLSDEMUX2_STREAM_NUM; i++) {
3378       stream = demux->streams[i];
3379       if (stream && (stream->type == stream_type)) {
3380         GST_INFO_OBJECT (demux, "found the stream - '%d'", stream->type);
3381         break;
3382       }
3383     }
3384   }
3385
3386   if (!stream)
3387     goto error;
3388
3389   bin = g_new0 (HLSDemux2SinkBin, 1);
3390
3391   element_name = g_strdup_printf("%s-%s", stream_name, "bin");
3392   bin->sinkbin = GST_BIN(gst_bin_new (element_name));
3393   if (!bin->sinkbin) {
3394     GST_ERROR_OBJECT (demux, "failed to create sink bin - %s", element_name);
3395     GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create bin - %s", element_name), (NULL));
3396     goto error;
3397   }
3398   g_free (element_name);
3399   element_name = NULL;
3400
3401   /* create queue element */
3402   element_name = g_strdup_printf("%s-%s", stream_name, "queue");
3403   bin->queue =  gst_element_factory_make ("queue", element_name);
3404   if (!bin->queue) {
3405     GST_ERROR_OBJECT (demux, "failed to create queue element - %s", element_name);
3406     GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", element_name), (NULL));
3407     goto error;
3408   }
3409   g_free (element_name);
3410   element_name = NULL;
3411
3412   if ((stream->type == HLSDEMUX2_STREAM_AUDIO) &&
3413     g_strstr_len(demuxer_name, strlen(demuxer_name), "id3")) {
3414     /* create parser element */
3415
3416     GST_INFO_OBJECT (stream->pad, "demuxer is id3demuxer, so create audio parser...");
3417
3418     element_name = g_strdup_printf("%s-%s", stream_name, "parse");
3419     bin->parser =  gst_element_factory_make ("aacparse", element_name);
3420     if (!bin->parser) {
3421       GST_ERROR_OBJECT (demux, "failed to create parser element - %s", element_name);
3422       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", element_name), (NULL));
3423       goto error;
3424     }
3425     g_free (element_name);
3426     element_name = NULL;
3427     gst_bin_add (GST_BIN (bin->sinkbin), bin->parser);
3428   }
3429
3430   /* create sink element */
3431   element_name = g_strdup_printf("%s-%s", stream_name, "sink");
3432   bin->sink =  gst_element_factory_make ("appsink", element_name);
3433   if (!bin->sink) {
3434     GST_ERROR_OBJECT (demux, "failed to create sink element - %s", element_name);
3435     GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", element_name), (NULL));
3436     goto error;
3437   }
3438
3439   g_object_set (G_OBJECT (bin->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
3440   g_signal_connect (bin->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_downloader_new_buffer), stream);
3441   g_signal_connect (bin->sink, "eos",  G_CALLBACK (gst_hlsdemux2_downloader_eos), stream);
3442
3443   gst_bin_add_many (GST_BIN (bin->sinkbin), bin->queue, bin->sink, NULL);
3444
3445   gst_bin_add (GST_BIN (demux->fdownloader->pipe), GST_ELEMENT(bin->sinkbin));
3446
3447   /* set queue element to PLAYING state */
3448   gst_element_set_state (GST_ELEMENT(bin->sinkbin), GST_STATE_READY);
3449
3450   sinkpad = gst_element_get_pad(bin->sink, "sink");
3451   if (!sinkpad) {
3452     GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", element_name);
3453     GST_ELEMENT_ERROR (demux, CORE, PAD, ("Count not get sink pad"), (NULL));
3454     goto error;
3455   }
3456   g_free (element_name);
3457   element_name = NULL;
3458
3459   /* adding probe to get new segment events */
3460   sink_probe = gst_pad_add_event_probe (sinkpad,
3461       G_CALLBACK (gst_hlsdemux2_sink_event_handler), stream);
3462
3463   if (!stream_exist) {
3464     /* add stream to stream_type list */
3465     demux->streams[stream_type] = stream;
3466     demux->active_stream_cnt++;
3467     GST_INFO_OBJECT (demux, "number of active streams = %d", demux->active_stream_cnt);
3468   }
3469
3470   linkpad = gst_element_get_pad(bin->queue, "sink");
3471   if (!linkpad) {
3472     element_name = gst_element_get_name (bin->queue);
3473     GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", element_name);
3474     GST_ELEMENT_ERROR (demux, CORE, PAD, ("could not get sink pad"), (NULL));
3475     goto error;
3476   }
3477
3478   gst_pad_set_active(linkpad,TRUE);
3479
3480   gst_element_add_pad (GST_ELEMENT(bin->sinkbin), gst_ghost_pad_new ("sink", linkpad));
3481
3482   GST_INFO_OBJECT (stream->pad, "successfully created stream...");
3483
3484   demux->fdownloader->sinkbins = g_list_append (demux->fdownloader->sinkbins, bin);
3485
3486   g_cond_signal (demux->post_msg_start);
3487
3488   g_free (stream_name);
3489
3490   return bin;
3491
3492 error:
3493   g_free (stream);
3494   if (element_name)
3495     g_free (element_name);
3496
3497   if (stream_name)
3498     g_free (stream_name);
3499
3500   return NULL;
3501 }
3502
3503 static gboolean
3504 gst_hlsdemux2_private_image_to_vid(gpointer user_data,GstBuffer *image_buffer)
3505 {
3506   GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *) user_data;
3507   GstHLSDemux2 *demux = (GstHLSDemux2 *) pvt_stream->parent;
3508   GstPad *pad, *srcpad;
3509   GstElement *appsrc, *appsink, *dec, *videorate, *capsfilter, *enc;
3510   GstCaps *scale_caps, *image_caps;
3511   GstBus * bus;
3512   GstFlowReturn fret = GST_FLOW_OK;
3513
3514   gchar *image_header = g_strndup((gchar *) image_buffer->data, 8);
3515   if(!((image_header[0] == 0xFF) && (image_header[1] == 0xD8))) {
3516     GST_WARNING_OBJECT(demux, "Not a valid JPEG image header : %d %d",image_header[0],image_header[1]);
3517     goto error;
3518   }
3519
3520   GST_DEBUG_OBJECT(demux, "IMAGE DATA [%d,%d]",pvt_stream->image_buffer->data[0],pvt_stream->image_buffer->data[1]);
3521
3522   GST_INFO_OBJECT (demux, "Creating jpeg->h264 conversion pipeline");
3523
3524   pvt_stream->convert_pipe = gst_pipeline_new ("jpegdec-pipe");
3525   if (!pvt_stream->convert_pipe) {
3526     GST_ERROR_OBJECT (demux, "failed to create pipeline");
3527     goto error;
3528   }
3529
3530   bus = gst_pipeline_get_bus (GST_PIPELINE (pvt_stream->convert_pipe));
3531   gst_bus_add_watch (bus, (GstBusFunc)gst_hlsdemux2_imagebuf_pipe_bus_cb, user_data);
3532   gst_object_unref (bus);
3533
3534   appsrc = gst_element_factory_make ("appsrc", "imgbuf-src");
3535   if (!appsrc) {
3536     GST_ERROR_OBJECT (demux, "failed to create appSrc element");
3537     goto error;
3538   }
3539
3540   appsink = gst_element_factory_make ("appsink", "imgbuf-sink");
3541   if (!appsink) {
3542     GST_ERROR_OBJECT (demux, "failed to create appSink element");
3543     goto error;
3544   }
3545
3546   dec = gst_element_factory_make ("jpegdec", "jpeg-decoder");
3547   if (!dec) {
3548     GST_ERROR_OBJECT (demux, "failed to create jpeg-decoder element");
3549     goto error;
3550   }
3551
3552   videorate = gst_element_factory_make ("videorate", "video-rate");
3553   if (!videorate) {
3554     GST_ERROR_OBJECT (demux, "failed to create ffmpeg-converter element");
3555     goto error;
3556   }
3557
3558   capsfilter = gst_element_factory_make ("capsfilter", "caps-filter");
3559   if (!capsfilter) {
3560     GST_ERROR_OBJECT (demux, "failed to create caps-filter element");
3561     goto error;
3562   }
3563
3564   scale_caps = gst_caps_new_simple ("video/x-raw-yuv",
3565       "width" , G_TYPE_INT, 480,
3566       "height", G_TYPE_INT, 270,
3567       "framerate",GST_TYPE_FRACTION,30,1,
3568       "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('I','4','2','0'),
3569       NULL);
3570   g_object_set (capsfilter, "caps", scale_caps, NULL);
3571
3572   enc = gst_element_factory_make ("savsenc_h264", "h264-encoder");
3573   if (!enc) {
3574     GST_ERROR_OBJECT (demux, "failed to create h264-encoder element");
3575     goto error;
3576   }
3577
3578   image_caps = gst_caps_new_simple ("image/jpeg",
3579       "framerate", GST_TYPE_FRACTION, 30, 1,
3580       "width", G_TYPE_INT, 480,
3581       "height", G_TYPE_INT, 270,
3582       NULL);
3583   gst_buffer_set_caps (image_buffer, image_caps);
3584
3585   gst_bin_add_many (GST_BIN (pvt_stream->convert_pipe), appsrc, dec, videorate, capsfilter, enc, appsink, NULL);
3586   if (!gst_element_link_many ( appsrc, dec, videorate, capsfilter, enc, appsink, NULL)) {
3587     GST_ERROR_OBJECT (demux, "failed to link elements...");
3588     goto error;
3589   }
3590
3591   pad = gst_element_get_static_pad(appsink,"sink");
3592   gst_pad_add_buffer_probe (pad,G_CALLBACK (gst_hlsdemux2_set_video_buffer), user_data);
3593   gst_pad_add_event_probe  (pad,G_CALLBACK (gst_hlsdemux2_done_video_buffer), user_data);
3594   gst_element_set_state (pvt_stream->convert_pipe, GST_STATE_PLAYING);
3595
3596   fret = gst_app_src_push_buffer ((GstAppSrc *)appsrc, pvt_stream->image_buffer);
3597   if(fret != GST_FLOW_OK){
3598     GST_ERROR_OBJECT (demux, "Push Failed; Error: %s[%d]", gst_flow_get_name(fret),fret);
3599     goto error;
3600   }
3601
3602   fret = gst_app_src_end_of_stream ((GstAppSrc *)appsrc);
3603   if(fret != GST_FLOW_OK){
3604     GST_ERROR_OBJECT (demux, "Push EOS Failed; Error: %s[%d]", gst_flow_get_name(fret),fret);
3605     goto error;
3606   }
3607   g_free(image_header);
3608   image_header = NULL;
3609   return TRUE;
3610
3611   error:
3612     GST_ERROR_OBJECT (demux, "ERROR ERROR ERROR: tut tut tut ");
3613     g_free(image_header);
3614     image_header = NULL;
3615     return FALSE;
3616 }
3617
3618 static gboolean
3619 gst_hlsdemux2_push_dummy_data (GstHLSDemux2Stream *stream)
3620 {
3621   GstHLSDemux2 *demux = stream->parent;
3622   struct stat stat_results;
3623   GstBuffer *buf = NULL;
3624   gint iread = 0;
3625   gint64 percent = 0;
3626   GstCaps *caps = NULL;
3627   GstBuffer *pushbuf = NULL;
3628   GstClockTime stop = GST_CLOCK_TIME_NONE;
3629   GstClockTime next_ts = GST_CLOCK_TIME_NONE;
3630   gboolean first_frame = TRUE;
3631   gint n = 0;
3632   gboolean convert_success = TRUE;
3633   GstHLSDemux2Stream *cur_stream = NULL;
3634   int dummy_fp = -1;
3635   GstClockTime cdisc = 0;
3636
3637   GST_INFO_OBJECT (demux, "START dummy video data thread");
3638
3639   /* Read dummy frame */
3640   if(demux->has_image_buffer) {
3641     GstHLSDemux2PvtStream *pvt_stream = demux->private_stream;
3642
3643     g_mutex_lock (pvt_stream->img_load_lock);
3644     if(pvt_stream->got_img_buffer == FALSE)
3645       g_cond_wait(pvt_stream->img_load_cond, pvt_stream->img_load_lock);
3646     g_mutex_unlock (pvt_stream->img_load_lock);
3647
3648     GST_LOG_OBJECT (demux, "prev_image_buffer = %p and image_buffer = %p",
3649       demux->prev_image_buffer, pvt_stream->image_buffer);
3650
3651     /* check whether it is same as previous image */
3652     if (demux->prev_video_buffer && demux->prev_image_buffer &&
3653       (GST_BUFFER_SIZE(demux->prev_image_buffer) == GST_BUFFER_SIZE(pvt_stream->image_buffer))) {
3654       if (!memcmp (GST_BUFFER_DATA(demux->prev_image_buffer), GST_BUFFER_DATA(pvt_stream->image_buffer),
3655           GST_BUFFER_SIZE(pvt_stream->image_buffer))) {
3656         GST_INFO_OBJECT (demux, "current & previous embedded images are same..no need to prepare video buffer");
3657         gst_buffer_unref(pvt_stream->image_buffer);
3658         pvt_stream->image_buffer = NULL;
3659         buf = gst_buffer_copy(demux->prev_video_buffer);
3660         goto start_push;
3661       }
3662     }
3663
3664     if (demux->prev_image_buffer) {
3665       gst_buffer_unref (demux->prev_image_buffer);
3666     }
3667     demux->prev_image_buffer = gst_buffer_copy(pvt_stream->image_buffer);
3668
3669     g_mutex_lock (pvt_stream->convert_lock);
3670     convert_success = gst_hlsdemux2_private_image_to_vid(pvt_stream, pvt_stream->image_buffer);
3671     if(convert_success)
3672       g_cond_wait(pvt_stream->convert_cond, pvt_stream->convert_lock);
3673     g_mutex_unlock (pvt_stream->convert_lock);
3674
3675     if(pvt_stream->convert_pipe){
3676       pvt_stream->convert_pipe = NULL;
3677       gst_object_unref(pvt_stream->convert_pipe);
3678     }
3679
3680     if (demux->prev_video_buffer) {
3681       gst_buffer_unref (demux->prev_video_buffer);
3682       demux->prev_video_buffer = NULL;
3683     }
3684
3685     if(convert_success){
3686       buf = pvt_stream->video_buffer;
3687       pvt_stream->video_buffer = NULL;
3688       demux->prev_video_buffer = gst_buffer_copy(buf);
3689       GST_DEBUG_OBJECT (demux, "Set Image from buffer - success  [%d,%d]", buf->data[0], buf->data[1]);
3690       GST_INFO_OBJECT (demux, "Going to show embedded image");
3691     }
3692   }
3693
3694   //load black frame if error occured while creating video buffer.
3695   if(demux->has_image_buffer == FALSE || convert_success == FALSE)
3696   {
3697     GST_INFO_OBJECT (demux, "Going to show fixed image");
3698     dummy_fp = open (PREDEFINED_VIDEO_FRAME_LOCATION, O_RDONLY);
3699     if (dummy_fp < 0) {
3700       GST_ERROR_OBJECT (stream->pad, "failed to open dummy data file : %s...", PREDEFINED_VIDEO_FRAME_LOCATION);
3701       GST_ELEMENT_ERROR (demux, RESOURCE, OPEN_READ, ("Failed open file '%s' for reading. reason : %s",PREDEFINED_VIDEO_FRAME_LOCATION ,g_strerror(errno)), (NULL));
3702       goto quit;
3703     }
3704
3705     GST_LOG_OBJECT (stream->pad, "opened dummy video file %s succefully...", PREDEFINED_VIDEO_FRAME_LOCATION);
3706
3707     if (fstat (dummy_fp, &stat_results) < 0) {
3708       GST_ERROR_OBJECT (stream->pad, "failed to get stats of a file...");
3709       GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("Failed get stats. reason : %s", g_strerror(errno)), (NULL));
3710       close (dummy_fp);
3711       goto quit;
3712     }
3713
3714     GST_LOG_OBJECT (stream->pad, "size of the dummy file = %d\n", stat_results.st_size);
3715
3716     buf = gst_buffer_new_and_alloc (stat_results.st_size);
3717     if (!buf) {
3718       GST_ERROR_OBJECT (stream->pad, "failed to allocate memory...");
3719       GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
3720       close (dummy_fp);
3721       goto quit;
3722     }
3723
3724     iread = read (dummy_fp, GST_BUFFER_DATA (buf), stat_results.st_size);
3725
3726     close (dummy_fp);
3727   }
3728
3729 start_push:
3730
3731   for (n = 0; n < HLSDEMUX2_STREAM_NUM; n++) {
3732     cur_stream = demux->streams[n];
3733
3734     if (cur_stream && (stream != cur_stream)) {
3735       cdisc = cur_stream->cdisc;
3736     }
3737   }
3738
3739   stream->nts = stop = stream->fts + demux->cfrag_dur;
3740   stream->total_disc += cdisc;
3741   stream->cdisc = cdisc;
3742   next_ts = stream->fts;
3743
3744   GST_INFO_OBJECT (stream->pad, "Dummy video start_ts = %"GST_TIME_FORMAT" and stop_ts = %"GST_TIME_FORMAT,
3745     GST_TIME_ARGS(stream->fts), GST_TIME_ARGS(stop));
3746
3747   /* set caps on buffer */
3748   caps = gst_caps_new_simple ("video/x-h264",
3749                   "stream-format", G_TYPE_STRING, "byte-stream",
3750                   "alignment", G_TYPE_STRING, "nal",
3751                   NULL);
3752
3753   gst_buffer_set_caps (buf, caps);
3754
3755   if (stream->need_newsegment) {
3756     GST_INFO_OBJECT (stream->pad, "need to send new segment event based on audio");
3757     g_queue_push_tail (stream->queue, (demux->streams[HLSDEMUX2_STREAM_AUDIO])->newsegment);
3758     stream->need_newsegment = FALSE;
3759   }
3760
3761   while (TRUE) {
3762
3763     if (demux->cancelled || demux->flushing) {
3764       GST_WARNING_OBJECT (stream->pad, "Stopping dummy push task...");
3765       goto quit;
3766     }
3767
3768     g_mutex_lock (stream->queue_lock);
3769
3770     pushbuf = gst_buffer_copy (buf);
3771     gst_buffer_set_caps (pushbuf, caps);
3772     GST_BUFFER_TIMESTAMP (pushbuf) = stream->lts = next_ts;
3773     GST_BUFFER_DURATION (pushbuf) = GST_CLOCK_TIME_NONE;
3774
3775     if (first_frame) {
3776       GST_BUFFER_FLAG_SET (pushbuf, GST_BUFFER_FLAG_DISCONT);
3777       first_frame = FALSE;
3778     }
3779
3780     GST_LOG_OBJECT (stream->pad, "Pushing dummy buffer : ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (pushbuf)));
3781
3782     /* calculate cached duration */
3783     gst_hlsdemux2_calculate_pushed_duration (demux, stream, pushbuf);
3784
3785     if (stream->cached_duration >= 0) {
3786
3787       percent = (stream->cached_duration * 100) / demux->total_cache_duration;
3788       GST_LOG_OBJECT (stream->pad, "percent done = %"G_GINT64_FORMAT, percent);
3789
3790       if (percent > 100) {
3791         guint64 overall_percent = 0;
3792
3793         g_mutex_lock (demux->buffering_lock);
3794         overall_percent = demux->percent;
3795         g_mutex_unlock (demux->buffering_lock);
3796
3797         if (overall_percent < 100) { /* otherwise, may cause blocking while buffering*/
3798           GST_DEBUG_OBJECT (stream->pad, "@@@@@@@@@@@ queue should not go to wait now @@@@@@@@");
3799         } else {
3800           /* update buffering & wait if space is not available */
3801           GST_DEBUG_OBJECT (stream->pad, "Reached more than 100 percent, queue full & wait till free");
3802           g_cond_wait(stream->queue_full, stream->queue_lock);
3803           GST_DEBUG_OBJECT (stream->pad,"Received signal to add more data...");
3804         }
3805       }
3806     }
3807
3808     g_cond_signal (stream->queue_empty);
3809
3810     g_mutex_unlock (stream->queue_lock);
3811
3812     /* calculate next timestamp */
3813     next_ts += HLS_DEFAULT_FRAME_DURATION;
3814
3815     if (next_ts > stop) {
3816       GST_DEBUG_OBJECT (stream->pad, "Reached Endof the fragment ....\n\n");
3817       break;
3818     }
3819   }
3820
3821   if (demux->end_of_playlist) {
3822     /* end of playlist, push EOS to queue */
3823     GST_INFO_OBJECT (stream->pad, "pushing EOS event to stream's queue");
3824     g_queue_push_tail (stream->queue, gst_event_new_eos ());
3825   }
3826
3827 #ifdef LATEST_AV_SYNC
3828   if (demux->is_live) {
3829     stream->total_stream_time += (stream->lts - stream->fts);
3830   } else {
3831     stream->total_stream_time += (stream->lts - stream->fts + HLS_DEFAULT_FRAME_DURATION);
3832     stream->total_stream_time = stream->nts;
3833   }
3834 #else
3835   stream->total_stream_time += (stream->lts - stream->fts);
3836 #endif
3837
3838   GST_DEBUG_OBJECT (stream->pad, "---------------- TS VALUES ----------------");
3839   GST_DEBUG_OBJECT (stream->pad, "valid start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
3840   GST_DEBUG_OBJECT (stream->pad, "valid end ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts));
3841   GST_DEBUG_OBJECT (stream->pad, "fragment duration received = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts - stream->fts));
3842   GST_DEBUG_OBJECT (stream->pad, "total stream time = %"GST_TIME_FORMAT,GST_TIME_ARGS(stream->total_stream_time));
3843   GST_DEBUG_OBJECT (stream->pad, "total disc time = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->total_disc));
3844   GST_DEBUG_OBJECT (stream->pad, "next expected start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->nts));
3845   GST_DEBUG_OBJECT (stream->pad, "---------------- DUMP VALUES END----------------");
3846
3847   stream->apply_disc = FALSE;
3848   stream->fts = GST_CLOCK_TIME_NONE;
3849   stream->valid_fts_rcvd = FALSE;
3850   stream->prev_nts = stream->nts;
3851
3852 quit:
3853   {
3854     GST_INFO_OBJECT (stream->pad, "Stopping dummy data thread...");
3855     gst_buffer_unref (buf);
3856     stream->dummy_data_thread = NULL;
3857     return TRUE;
3858   }
3859
3860 }
3861
3862 static gboolean
3863 gst_hlsdemux2_sink_event_handler (GstPad * pad, GstEvent * event, gpointer data)
3864 {
3865   GstHLSDemux2Stream *stream = (GstHLSDemux2Stream *)data;
3866   GstHLSDemux2 *demux = stream->parent;
3867
3868   if ((GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) && stream->need_newsegment) {
3869     GstEvent *newsegment = NULL;
3870     GstFormat format;
3871     gboolean update;
3872     gdouble rate, arate;
3873     gint64 start, stop, pos;
3874
3875     newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, demux->ns_start, -1, demux->ns_start);
3876
3877     GST_INFO_OBJECT (stream->pad, "Received NEWSEGMENT event...");
3878
3879     g_mutex_lock (stream->queue_lock);
3880
3881     gst_event_parse_new_segment_full(event, &update, &rate, &arate, &format, &start, &stop, &pos);
3882
3883     if (!GST_CLOCK_TIME_IS_VALID(stream->base_ts)) {
3884       GST_INFO_OBJECT (stream->pad, "storing stream's base timestamp = %"GST_TIME_FORMAT, GST_TIME_ARGS(start));
3885       stream->base_ts = start;
3886     }
3887
3888     g_queue_push_tail (stream->queue, newsegment);
3889
3890     GST_INFO_OBJECT (stream->pad, "Pushed new segment event with start = %"GST_TIME_FORMAT" to queue..",
3891       GST_TIME_ARGS(demux->ns_start));
3892
3893     g_mutex_unlock (stream->queue_lock);
3894
3895     stream->need_newsegment = FALSE;
3896     stream->prev_nts = demux->ns_start;
3897
3898     if (stream->newsegment)
3899       gst_event_unref (stream->newsegment);
3900
3901     stream->newsegment = gst_event_copy (newsegment);
3902   }
3903   return TRUE;
3904 }
3905
3906 static gboolean
3907 hlsdemux2_HTTP_repeat_request (GstHLSDemux2 *demux, gchar *element_name)
3908 {
3909   if (g_strrstr(element_name, "fragurisrc")) {
3910     guint idx = 0;
3911     GstBuffer *buf = NULL;
3912
3913     /* clear stream queues if we already downloaded some data */
3914     for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
3915       GstHLSDemux2Stream *stream = demux->streams[idx];
3916       if (stream ) {
3917         while (!g_queue_is_empty (stream->downloader_queue)) {
3918           buf = g_queue_pop_head (stream->downloader_queue);
3919           gst_buffer_unref (buf);
3920         }
3921         GST_LOG_OBJECT (stream->pad, "cleared stream download queue...");
3922         g_queue_clear (stream->downloader_queue);
3923       }
3924     }
3925
3926     /* request the same fragment again */
3927     if (demux->fragCookie)
3928       g_strfreev (demux->fragCookie);
3929
3930     g_object_get (demux->fdownloader->urisrc, "cookies", &demux->fragCookie, NULL);
3931     GST_DEBUG_OBJECT (demux, "Got cookies after FRAGMENT download : %s", demux->fragCookie ? *(demux->fragCookie) : NULL);
3932
3933     GST_INFO_OBJECT (demux, "========>>>>>Going to download fragment AGAIN: %s", demux->frag_uri);
3934
3935     gst_hlsdemux2_destroy_fragment_download (demux);
3936
3937     if (!gst_hlsdemux2_create_fragment_download (demux, demux->frag_uri)) {
3938       GST_ERROR_OBJECT (demux, "failed to create download pipeline");
3939       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
3940       return FALSE;
3941     }
3942
3943     /* download rate calculation : note down start time*/
3944     demux->fdownloader->download_start_ts = gst_util_get_timestamp();
3945
3946     gst_element_set_state (demux->fdownloader->pipe, GST_STATE_PLAYING);
3947
3948     return TRUE;
3949   } else if (g_strrstr(element_name, "playlisturisrc")) {
3950
3951     if (demux->playlistCookie)
3952       g_strfreev (demux->playlistCookie);
3953
3954     g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
3955
3956     GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
3957
3958     gst_hlsdemux2_destroy_playlist_download (demux);
3959
3960     GST_INFO_OBJECT (demux, "========>>>>>Going to download playlist AGAIN: %s", demux->playlist_uri);
3961     if (!gst_hlsdemux2_create_playlist_download (demux, demux->playlist_uri)) {
3962       GST_ERROR_OBJECT (demux, "failed to create download pipeline");
3963       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
3964       return FALSE;
3965     }
3966
3967     gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
3968     return TRUE;
3969   } else if (g_strrstr(element_name, "keyurisrc")) {
3970
3971     if (demux->keyCookie)
3972       g_strfreev (demux->keyCookie);
3973
3974     g_object_get (demux->kdownloader->urisrc, "cookies", &demux->keyCookie, NULL);
3975
3976     GST_DEBUG_OBJECT (demux, "Got cookies after KEY download : %s", demux->keyCookie ? *(demux->keyCookie) : NULL);
3977
3978     GST_INFO_OBJECT (demux, "========>>>>>Going to download key AGAIN: %s", demux->key_uri);
3979
3980     gst_hlsdemux2_destroy_key_download (demux);
3981
3982     if (!gst_hlsdemux2_create_key_download (demux, demux->key_uri)) {
3983       GST_ERROR_OBJECT (demux, "failed to create download pipeline");
3984       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
3985       return FALSE;
3986     }
3987
3988     gst_element_set_state (demux->kdownloader->pipe, GST_STATE_PLAYING);
3989     return TRUE;
3990   }
3991
3992   return FALSE;
3993 }
3994
3995
3996 static gboolean
3997 hlsdemux2_HTTP_time_out (GstHLSDemux2 *demux, gchar *element_name)
3998 {
3999   if (g_strrstr(element_name, "fragurisrc")) {
4000     /* as it is because of timeout, there is no point in requesting the same fragment again, so request next one */
4001     GST_INFO_OBJECT (demux, "signalling fragment downloader to get next fragment...");
4002     demux->fdownloader->get_next_frag = TRUE;
4003     g_cond_signal (demux->fdownloader->cond);
4004     return TRUE;
4005   } else if (g_strrstr(element_name, "playlisturisrc")) {
4006
4007     if (demux->playlistCookie)
4008       g_strfreev (demux->playlistCookie);
4009
4010     g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
4011
4012     GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
4013
4014     gst_hlsdemux2_destroy_playlist_download (demux);
4015
4016     GST_INFO_OBJECT (demux, "========>>>>>Going to download playlist AGAIN: %s", demux->playlist_uri);
4017     if (!gst_hlsdemux2_create_playlist_download (demux, demux->playlist_uri)) {
4018       GST_ERROR_OBJECT (demux, "failed to create download pipeline");
4019       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
4020       return FALSE;
4021     }
4022
4023     gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
4024     return TRUE;
4025   } else if (g_strrstr(element_name, "keyurisrc")) {
4026
4027     if (demux->keyCookie)
4028       g_strfreev (demux->keyCookie);
4029
4030     g_object_get (demux->kdownloader->urisrc, "cookies", &demux->keyCookie, NULL);
4031
4032     GST_DEBUG_OBJECT (demux, "Got cookies after KEY download : %s", demux->keyCookie ? *(demux->keyCookie) : NULL);
4033
4034     GST_INFO_OBJECT (demux, "========>>>>>Going to download key AGAIN: %s", demux->key_uri);
4035
4036     gst_hlsdemux2_destroy_key_download (demux);
4037
4038     if (!gst_hlsdemux2_create_key_download (demux, demux->key_uri)) {
4039       GST_ERROR_OBJECT (demux, "failed to create download pipeline");
4040       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
4041       return FALSE;
4042     }
4043
4044     gst_element_set_state (demux->kdownloader->pipe, GST_STATE_PLAYING);
4045     return TRUE;
4046   }
4047
4048   return FALSE;
4049 }
4050
4051 static gboolean
4052 hlsdemux2_HTTP_not_found(GstHLSDemux2 *demux, gchar *element_name)
4053 {
4054   if (g_strrstr(element_name, "fragurisrc")) {
4055     if (demux->is_live) {
4056       /* request next fragment url */
4057       GST_INFO_OBJECT (demux, "signalling fragment downloader to get next fragment...");
4058       demux->fdownloader->get_next_frag = TRUE;
4059       g_cond_signal (demux->fdownloader->cond);
4060       return TRUE;
4061     } else {
4062
4063 #if 0 // In future enable
4064       GList *next_variant = NULL;
4065
4066       if (demux->pldownloader->recovery_mode == HLSDEMUX2_NO_RECOVERY)
4067         demux->pldownloader->recovery_mode = HLSDEMUX2_DOWNWARD_RECOVERY;
4068
4069       if (demux->pldownloader->recovery_mode == HLSDEMUX2_DOWNWARD_RECOVERY) {
4070         /* get next available lower variant */
4071         next_variant = gst_m3u8_client_get_next_lower_bw_playlist (demux->client);
4072         if (!next_variant) {
4073           GST_WARNING_OBJECT (demux, "no next lower variants.. Go Upward");
4074           demux->pldownloader->recovery_mode = HLSDEMUX2_UPWARD_RECOVERY;
4075         }
4076       }
4077
4078       if (demux->pldownloader->recovery_mode == HLSDEMUX2_UPWARD_RECOVERY) {
4079         /* get next available lower variant */
4080         next_variant = gst_m3u8_client_get_next_higher_bw_playlist (demux->client);
4081         if (!next_variant) {
4082           GST_ERROR_OBJECT (demux, "no next higher variants.. need to exit");
4083           demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
4084           return FALSE;
4085         }
4086       }
4087
4088       /* change variant */
4089       GST_M3U8_CLIENT_LOCK (demux->client);
4090       demux->client->main->current_variant = next_variant;
4091       GST_M3U8_CLIENT_UNLOCK (demux->client);
4092
4093       gst_m3u8_client_set_current (demux->client, next_variant->data);
4094
4095       demux->fdownloader->get_next_frag = TRUE;
4096       g_cond_signal (demux->fdownloader->cond);
4097
4098       return TRUE;
4099 #else
4100       return FALSE;
4101 #endif
4102     }
4103   } else if (g_strrstr(element_name, "playlisturisrc")) {
4104     GList *next_variant = NULL;
4105
4106     if (demux->pldownloader->recovery_mode == HLSDEMUX2_NO_RECOVERY)
4107       demux->pldownloader->recovery_mode = HLSDEMUX2_DOWNWARD_RECOVERY;
4108
4109     if (demux->pldownloader->recovery_mode == HLSDEMUX2_DOWNWARD_RECOVERY) {
4110       /* get next available lower variant */
4111       next_variant = gst_m3u8_client_get_next_lower_bw_playlist (demux->client);
4112       if (!next_variant) {
4113         GST_WARNING_OBJECT (demux, "no next lower variants.. Go Upward");
4114         demux->pldownloader->recovery_mode = HLSDEMUX2_UPWARD_RECOVERY;
4115       }
4116     }
4117
4118     if (demux->pldownloader->recovery_mode == HLSDEMUX2_UPWARD_RECOVERY) {
4119       /* get next available lower variant */
4120       next_variant = gst_m3u8_client_get_next_higher_bw_playlist (demux->client);
4121       if (!next_variant) {
4122         GST_ERROR_OBJECT (demux, "no next higher variants.. need to exit");
4123         demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
4124         return FALSE;
4125       }
4126     }
4127
4128     /* change variant */
4129     GST_M3U8_CLIENT_LOCK (demux->client);
4130     demux->client->main->current_variant = next_variant;
4131     GST_M3U8_CLIENT_UNLOCK (demux->client);
4132
4133     gst_m3u8_client_set_current (demux->client, next_variant->data);
4134
4135     /* get new playlist uri */
4136     demux->playlist_uri = g_strdup (gst_m3u8_client_get_current_uri (demux->client));
4137
4138     if (demux->playlistCookie)
4139       g_strfreev (demux->playlistCookie);
4140
4141     g_object_get (demux->pldownloader->urisrc, "cookies", &demux->playlistCookie, NULL);
4142
4143     GST_DEBUG_OBJECT (demux, "Got cookies after PLAYLIST download : %s", demux->playlistCookie ? *(demux->playlistCookie) : NULL);
4144
4145     gst_hlsdemux2_destroy_playlist_download (demux);
4146
4147     GST_INFO_OBJECT (demux, "========>>>>>Going to download recovery playlist : %s", demux->playlist_uri);
4148     if (!gst_hlsdemux2_create_playlist_download (demux, demux->playlist_uri)) {
4149       GST_ERROR_OBJECT (demux, "failed to create download pipeline");
4150       GST_ELEMENT_ERROR (demux, CORE, FAILED, ("Failed to create pipeline"), (NULL));
4151       return FALSE;
4152     }
4153
4154     gst_element_set_state (demux->pldownloader->pipe, GST_STATE_PLAYING);
4155
4156     return TRUE;
4157
4158   } else if (g_strrstr(element_name, "keyurisrc")) {
4159     /* treating it as non-recoverable error */
4160     return FALSE;
4161   }
4162
4163   return FALSE;
4164 }
4165
4166 static gboolean
4167 gst_hlsdemux2_handle_HTTP_error (GstHLSDemux2 *demux, GError *error, gchar *element_name) {
4168   guint i = 0;
4169   guint n_http_errors = sizeof (http_errors) / sizeof (http_errors[0]);
4170
4171   if(!error)
4172     return HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE;
4173   for (i = 0; i < n_http_errors; i++) {
4174     if (G_LIKELY (!strncmp(error->message, http_errors[i].error_phrase, strlen(error->message)))) {
4175       if (http_errors[i].handle_error) {
4176         return http_errors[i].handle_error (demux, element_name);
4177       }
4178       return http_errors[i].error_type;
4179     }
4180   }
4181   return HLSDEMUX2_HTTP_ERROR_NONRECOVERABLE;
4182 }
4183
4184 static gboolean
4185 gst_hlsdemux2_fragment_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
4186 {
4187   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
4188   GError *error = NULL;
4189   gchar* debug = NULL;
4190   gboolean bret = TRUE;
4191   GstMessage *err_msg = NULL;
4192   gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
4193
4194   switch (GST_MESSAGE_TYPE(msg)) {
4195     case GST_MESSAGE_EOS: {
4196       GST_INFO_OBJECT (demux, "received EOS on download pipe from '%s'..", ele_name);
4197       demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
4198       g_cond_signal(demux->fdownloader->cond);
4199       break;
4200     }
4201     case GST_MESSAGE_ERROR: {
4202       GST_ERROR_OBJECT (demux, "Error from %s\n", ele_name);
4203
4204       gst_message_parse_error( msg, &error, &debug );
4205
4206       demux->fdownloader->error_rcvd = TRUE;
4207
4208       if (error)
4209         GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error->message = %s and error->code = %d", error->message);
4210
4211       GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s", debug);
4212
4213       if (g_strrstr(ele_name, "fragurisrc") && !demux->cancelled && demux->soup_request_fail_cnt) {
4214
4215         /* flush the error msgs pending.. as we are going to create new pipeline */
4216         gst_bus_set_flushing (bus, TRUE);
4217
4218         bret = gst_hlsdemux2_handle_HTTP_error (demux, error, ele_name);
4219         if (!bret)
4220           goto post_error;
4221         else {
4222           demux->soup_request_fail_cnt--;
4223           GST_WARNING_OBJECT (demux, "HTTP error count remaining = %d", demux->soup_request_fail_cnt);
4224           goto exit;
4225         }
4226       }
4227
4228 post_error:
4229
4230       GST_ERROR_OBJECT (demux, "posting error from fragment download callback");
4231
4232       err_msg = gst_message_new_error (GST_OBJECT(demux), error, debug);
4233       if (!gst_element_post_message (GST_ELEMENT(demux), err_msg)) {
4234         GST_ERROR_OBJECT (demux, "failed to post error");
4235         bret = FALSE;
4236         goto exit;
4237       }
4238       gst_hlsdemux2_stop (demux);
4239       break;
4240     }
4241     case GST_MESSAGE_WARNING: {
4242       gst_message_parse_warning(msg, &error, &debug);
4243       GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
4244       GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
4245       break;
4246     }
4247     case GST_MESSAGE_ELEMENT: {
4248       const GstStructure *s = gst_message_get_structure (msg);
4249
4250       if (gst_structure_has_name (s, "cookies")) {
4251         const GValue *value;
4252         gchar **cookies = NULL;
4253         gchar *cookie = NULL;
4254         value = gst_structure_get_value (s, "cookies");
4255         cookie = g_strdup_value_contents(value);
4256
4257         cookies = &cookie;
4258         GST_ERROR_OBJECT (demux, "received cookies from soup : %s", *cookies);
4259       }
4260       break;
4261     }
4262     default : {
4263       break;
4264     }
4265   }
4266
4267 exit:
4268   if (debug)
4269     g_free( debug);
4270
4271   if (error)
4272     g_error_free( error);
4273
4274   if (!bret)
4275     gst_hlsdemux2_stop (demux);
4276
4277   g_free (ele_name);
4278
4279   return bret;
4280 }
4281
4282 static GstBusSyncReply
4283 gst_hlsdemux2_playlist_download_bus_sync_cb (GstBus * bus, GstMessage *msg, gpointer data)
4284 {
4285   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
4286   GstBusSyncReply reply = GST_BUS_DROP;
4287
4288   GError *error = NULL;
4289   gchar *debug = NULL;
4290   gboolean bret = TRUE;
4291   GstMessage *err_msg = NULL;
4292   gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
4293
4294   switch (GST_MESSAGE_TYPE(msg)) {
4295     case GST_MESSAGE_EOS: {
4296       GST_DEBUG_OBJECT (demux, "received EOS on playlist download pipe..");
4297       demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
4298       g_mutex_lock (demux->pldownloader->lock);
4299       g_cond_broadcast (demux->pldownloader->cond);
4300       g_mutex_unlock (demux->pldownloader->lock);
4301       break;
4302     }
4303     case GST_MESSAGE_ERROR: {
4304       GST_ERROR_OBJECT (demux, "Error from %s element", ele_name);
4305
4306       gst_message_parse_error( msg, &error, &debug );
4307       if (error)
4308         GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error= %s", error->message);
4309
4310       GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s", debug);
4311
4312       if (g_strrstr(ele_name, "playlisturisrc") && !demux->cancelled && demux->soup_request_fail_cnt) {
4313
4314         /* flush the error msgs pending.. as we are going to create new pipeline */
4315         gst_bus_set_flushing (bus, TRUE);
4316
4317         bret = gst_hlsdemux2_handle_HTTP_error (demux, error, ele_name);
4318         if (!bret)
4319           goto post_error;
4320         else {
4321           demux->soup_request_fail_cnt--;
4322           GST_WARNING_OBJECT (demux, "HTTP error count remaining = %d", demux->soup_request_fail_cnt);
4323           goto exit;
4324         }
4325       }
4326
4327 post_error:
4328
4329       GST_ERROR_OBJECT (demux, "posting error from playlist callback...");
4330
4331       err_msg = gst_message_new_error (GST_OBJECT(demux), error, debug);
4332       if (!gst_element_post_message (GST_ELEMENT(demux), err_msg)) {
4333         GST_ERROR_OBJECT (demux, "failed to post error");
4334         bret = FALSE;
4335         goto exit;
4336       }
4337       gst_hlsdemux2_stop (demux);
4338       break;
4339     }
4340     case GST_MESSAGE_WARNING: {
4341       gst_message_parse_warning(msg, &error, &debug);
4342       if (error)
4343         GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
4344       GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
4345       break;
4346     }
4347     case GST_MESSAGE_ELEMENT: {
4348       const GstStructure *s = gst_message_get_structure (msg);
4349
4350       if (gst_structure_has_name (s, "cookies")) {
4351         const GValue *value;
4352         gchar **cookies = NULL;
4353         gchar *cookie = NULL;
4354         value = gst_structure_get_value (s, "cookies");
4355         cookie = g_strdup_value_contents(value);
4356
4357         cookies = &cookie;
4358         GST_ERROR_OBJECT (demux, "received cookies from soup : %s", *cookies);
4359       }
4360       break;
4361     }
4362     default : {
4363       //GST_LOG_OBJECT(demux, "unhandled message : %s\n", gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
4364       break;
4365     }
4366   }
4367
4368 exit:
4369   if (debug)
4370     g_free( debug);
4371
4372   if (error)
4373     g_error_free( error);
4374
4375   if (!bret)
4376     gst_hlsdemux2_stop (demux);
4377
4378   g_free (ele_name);
4379
4380   return reply;
4381 }
4382
4383 static gboolean
4384 gst_hlsdemux2_key_download_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
4385 {
4386   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
4387   GError *error = NULL;
4388   gchar* debug = NULL;
4389   gboolean bret = TRUE;
4390   GstMessage *err_msg = NULL;
4391   gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
4392
4393   switch (GST_MESSAGE_TYPE(msg)) {
4394     case GST_MESSAGE_EOS: {
4395       GST_DEBUG_OBJECT (demux, "received EOS on key download pipe..");
4396       demux->pldownloader->recovery_mode = HLSDEMUX2_NO_RECOVERY;
4397       g_mutex_lock (demux->kdownloader->lock);
4398       g_cond_signal (demux->kdownloader->cond);
4399       g_mutex_unlock (demux->kdownloader->lock);
4400       break;
4401     }
4402     case GST_MESSAGE_ERROR: {
4403       GST_INFO_OBJECT (demux, "Error from %s element...", ele_name);
4404
4405       gst_message_parse_error(msg, &error, &debug);
4406
4407       if (error)
4408         GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: error= %s", error->message);
4409
4410       GST_ERROR_OBJECT (demux, "GST_MESSAGE_ERROR: debug = %s", debug);
4411
4412       if (g_strrstr(ele_name, "keyurisrc") && !demux->cancelled && demux->soup_request_fail_cnt) {
4413
4414         /* flush the error msgs pending.. as we are going to create new pipeline */
4415         gst_bus_set_flushing (bus, TRUE);
4416
4417         bret = gst_hlsdemux2_handle_HTTP_error (demux, error, ele_name);
4418         if (!bret)
4419           goto post_error;
4420         else {
4421           demux->soup_request_fail_cnt--;
4422           GST_WARNING_OBJECT (demux, "HTTP error count remaining = %d", demux->soup_request_fail_cnt);
4423           goto exit;
4424         }
4425       }
4426
4427 post_error:
4428       GST_ERROR_OBJECT (demux, "Error posting from key downloader...");
4429       err_msg = gst_message_new_error (GST_OBJECT(demux), error, debug);
4430
4431       if (!gst_element_post_message (GST_ELEMENT(demux), err_msg)) {
4432         GST_ERROR_OBJECT (demux, "failed to post error");
4433         gst_hlsdemux2_stop (demux);
4434         bret = FALSE;
4435         goto exit;
4436       }
4437       gst_hlsdemux2_stop (demux);
4438       break;
4439     }
4440     case GST_MESSAGE_WARNING: {
4441       gst_message_parse_warning(msg, &error, &debug);
4442       if (error)
4443         GST_WARNING_OBJECT(demux, "warning : %s\n", error->message);
4444       GST_WARNING_OBJECT(demux, "debug : %s\n", debug);
4445       break;
4446     }
4447     case GST_MESSAGE_ELEMENT: {
4448       const GstStructure *s = gst_message_get_structure (msg);
4449
4450       if (gst_structure_has_name (s, "cookies")) {
4451         const GValue *value;
4452         gchar **cookies = NULL;
4453         gchar *cookie = NULL;
4454         value = gst_structure_get_value (s, "cookies");
4455         cookie = g_strdup_value_contents(value);
4456
4457         cookies = &cookie;
4458         GST_ERROR_OBJECT (demux, "received cookies from soup : %s", *cookies);
4459       }
4460      break;
4461     }
4462     default : {
4463       break;
4464     }
4465   }
4466
4467 exit:
4468
4469   if (debug)
4470     g_free( debug);
4471
4472   if (error)
4473     g_error_free( error);
4474
4475   if (!bret)
4476     gst_hlsdemux2_stop (demux);
4477
4478   g_free (ele_name);
4479
4480   return bret;
4481 }
4482
4483 static void
4484 gst_hlsdemux2_calculate_pushed_duration (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream,
4485     GstBuffer *inbuf)
4486 {
4487   gint len = 0;
4488   int qidx = 0;
4489   gpointer data = NULL;
4490
4491   // TODO: for all timestamps -1 case, we need to add max-bytes also
4492
4493   g_queue_push_tail (stream->queue, inbuf);
4494
4495   len = g_queue_get_length (stream->queue);
4496
4497   /* peek the head buffer having valid timestamp to calculate cached duration */
4498   while (qidx < len) {
4499     data = g_queue_peek_nth (stream->queue, qidx);
4500
4501     if (GST_IS_BUFFER (data)) {
4502       if (GST_BUFFER_TIMESTAMP_IS_VALID(data)) {
4503         GST_LOG_OBJECT (stream->pad, "data found buffer with valid ts = %"GST_TIME_FORMAT " len = %d & qidx = %d",
4504           GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(data)), len, qidx);
4505         break;
4506       }
4507     }
4508     qidx++;
4509   }
4510   if(GST_IS_BUFFER (data)) {
4511     if (GST_BUFFER_TIMESTAMP (inbuf) >= GST_BUFFER_TIMESTAMP ((GstBuffer *)data)) {
4512       stream->cached_duration = GST_BUFFER_TIMESTAMP (inbuf) - GST_BUFFER_TIMESTAMP ((GstBuffer *)data);
4513       GST_LOG_OBJECT (stream->pad, "len = %d, cached duration = %"GST_TIME_FORMAT,
4514           g_queue_get_length (stream->queue), GST_TIME_ARGS(stream->cached_duration));
4515     } else {
4516       GST_WARNING_OBJECT (stream->pad, "Wrong order.. not calculating");
4517     }
4518   }
4519   return;
4520 }
4521
4522 static gboolean
4523 gst_hlsdemux2_alter_timestamps (GstHLSDemux2Stream *stream, GstBuffer *inbuf)
4524 {
4525   GstHLSDemux2 *demux = stream->parent;
4526   GstClockTime cts = 0;
4527
4528   /* set discontinuity only when there is real fragment discontinuity */
4529   if (GST_BUFFER_IS_DISCONT(inbuf)) {
4530     if (!stream->apply_disc) {
4531       GST_BUFFER_FLAG_UNSET (inbuf, GST_BUFFER_FLAG_DISCONT);
4532       GST_INFO_OBJECT (stream->pad, "unsetting discontinuity flag...");
4533     }
4534   }
4535
4536   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (inbuf))) {
4537     if (GST_BUFFER_TIMESTAMP (inbuf) >= stream->base_ts) {
4538       cts = GST_BUFFER_TIMESTAMP (inbuf) - stream->base_ts;
4539     } else {
4540       /* this buffer should be dropped at sink */
4541       GST_WARNING_OBJECT (stream->pad, "input timestamp [%"GST_TIME_FORMAT"] is less than base_ts [%"GST_TIME_FORMAT"]",
4542         GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_ARGS(stream->base_ts));
4543       if (stream->type == HLSDEMUX2_STREAM_AUDIO) {
4544         return FALSE;
4545       } else {
4546         GST_BUFFER_TIMESTAMP (inbuf) = GST_CLOCK_TIME_NONE;
4547         return TRUE;
4548       }
4549     }
4550   } else {
4551     /* this buffer should be dropped at sink */
4552     GST_LOG_OBJECT (stream->pad, "invalid input timestamp (i.e. GST_CLOCK_TIME_NONE)");
4553 #ifdef LATEST_AV_SYNC
4554     if (!demux->is_live && (stream->type == HLSDEMUX2_STREAM_AUDIO) && !stream->valid_fts_rcvd){
4555       GST_WARNING_OBJECT (stream->pad, "dropping invalid ts buffer, due to no valid first ts yet...");
4556       return FALSE;
4557     }
4558 #endif
4559     return TRUE;
4560   }
4561
4562   /* handle discontinuity in stream */
4563   if(GST_CLOCK_TIME_IS_VALID (stream->nts) && (GST_CLOCK_DIFF(stream->nts,cts) > (2 * GST_SECOND)) && stream->apply_disc) {
4564     GST_INFO_OBJECT (stream->pad, "cts = %"GST_TIME_FORMAT" and prev_next_ts = %"GST_TIME_FORMAT,
4565       GST_TIME_ARGS(cts), GST_TIME_ARGS(stream->nts));
4566     GST_INFO_OBJECT (stream->pad,"Received disc = %"GST_TIME_FORMAT, GST_TIME_ARGS(cts - stream->nts));
4567     stream->cdisc = cts - stream->nts;
4568     stream->total_disc += (cts - stream->nts);
4569     GST_INFO_OBJECT (stream->pad, "total disc = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->total_disc));
4570     stream->apply_disc = FALSE;
4571   }
4572
4573   cts -= stream->cdisc;
4574
4575   /* get the max last ts, required because of frame reordering */
4576   stream->lts = cts > stream->lts ? cts : stream->lts;
4577
4578   GST_DEBUG_OBJECT (stream->pad, "modifying buffer timestamp : %"GST_TIME_FORMAT" -> %"GST_TIME_FORMAT,
4579     GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_ARGS(cts));
4580
4581 #ifndef LATEST_AV_SYNC
4582   /* store first valid timestamp of a fragment */
4583   if (stream->fts == GST_CLOCK_TIME_NONE) {
4584     stream->fts = cts;
4585     stream->nts = stream->fts + demux->cfrag_dur;
4586     GST_INFO_OBJECT (stream->pad, "storing first ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
4587     if (demux->is_live && stream->type == HLSDEMUX2_STREAM_AUDIO)
4588       demux->cur_audio_fts = cts;
4589   }
4590 #endif
4591
4592 #ifdef LATEST_AV_SYNC
4593         /* 10/31/2013: dont want to disturb live case at this moment */
4594   if (!stream->valid_fts_rcvd) {
4595     if (stream->type == HLSDEMUX2_STREAM_AUDIO) {
4596       if (!demux->is_live && (GST_CLOCK_DIFF(cts, stream->prev_nts) > (10 * GST_MSECOND))) {
4597         GST_WARNING_OBJECT (stream->pad, "already seen audio timestamps[%"GST_TIME_FORMAT"]"
4598           " and previous_nts = %"GST_TIME_FORMAT"...drop this",
4599           GST_TIME_ARGS(cts), GST_TIME_ARGS(stream->prev_nts));
4600         return FALSE;
4601       } else {
4602         GST_INFO_OBJECT (stream->pad, "recevied valid audio first ts = %"GST_TIME_FORMAT,
4603           GST_TIME_ARGS (cts));
4604         demux->cur_audio_fts = cts;
4605       }
4606     }
4607
4608     stream->valid_fts_rcvd = TRUE;
4609     stream->fts = cts;
4610     stream->nts = stream->fts + demux->cfrag_dur; // Approximate nts
4611
4612     GST_INFO_OBJECT (stream->pad, "storing first ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
4613   } else if (!stream->frame_duration) {
4614     stream->frame_duration = cts - stream->fts;
4615     GST_DEBUG_OBJECT (stream->pad, "frame duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->frame_duration));
4616   }
4617
4618 #else
4619
4620   /* 10/31/2013: dont want to disturb live case at this moment */
4621   if (!demux->is_live && stream->type == HLSDEMUX2_STREAM_AUDIO) {
4622     if (!stream->valid_fts_rcvd) {
4623       if (GST_CLOCK_DIFF(cts, stream->prev_nts) > 0) {
4624         GST_WARNING_OBJECT (stream->pad, "already seen audio timestamps[%"GST_TIME_FORMAT"]"
4625           " and previous_nts = %"GST_TIME_FORMAT"...drop this",
4626           GST_TIME_ARGS(cts), GST_TIME_ARGS(stream->prev_nts));
4627         return FALSE;
4628       } else {
4629         GST_INFO_OBJECT (stream->pad, "recevied valid audio first ts = %"GST_TIME_FORMAT,
4630           GST_TIME_ARGS (cts));
4631         demux->cur_audio_fts = cts;
4632         stream->valid_fts_rcvd = TRUE;
4633       }
4634     } else if (!stream->frame_duration) {
4635       stream->frame_duration = cts - demux->cur_audio_fts;
4636       GST_DEBUG_OBJECT (demux, "audio frame duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->frame_duration));
4637     }
4638   }
4639 #endif
4640
4641   GST_BUFFER_TIMESTAMP (inbuf) = cts;
4642
4643   return TRUE;
4644 }
4645
4646 static void
4647 gst_hlsdemux2_downloader_new_buffer (GstElement *appsink, void *user_data)
4648 {
4649   GstHLSDemux2Stream *stream = (GstHLSDemux2Stream *)user_data;
4650   GstHLSDemux2 *demux = stream->parent;
4651   GstBuffer *inbuf = NULL;
4652   gboolean bret = FALSE;
4653
4654   if (demux->cancelled ) {
4655     return;
4656   }
4657
4658   inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
4659   if (!inbuf) {
4660     GST_WARNING_OBJECT (demux, "Input buffer not available...");
4661     return;
4662   }
4663
4664   GST_LOG_OBJECT (stream->pad, "Received buffer with size = %d and ts = %"GST_TIME_FORMAT,
4665     GST_BUFFER_SIZE(inbuf), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)));
4666
4667   if (demux->fdownloader->force_timestamps) {
4668     GST_BUFFER_TIMESTAMP(inbuf) += (stream->prev_nts + stream->base_ts);
4669     GST_DEBUG_OBJECT (stream->pad, "forced timestamp = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(inbuf)));
4670   }
4671
4672   /* alter the timestamps */
4673   bret = gst_hlsdemux2_alter_timestamps (stream, inbuf);
4674   if (!bret) {
4675     gst_buffer_unref (inbuf);
4676     return;
4677   }
4678
4679   /* store buffer in queue */
4680   g_queue_push_tail (stream->downloader_queue, inbuf);
4681
4682   return;
4683 }
4684
4685 static gboolean
4686 gst_hlsdemux2_imagebuf_pipe_bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
4687 {
4688   GstHLSDemux2PvtStream *stream = (GstHLSDemux2PvtStream *)data;
4689   GstHLSDemux2 *demux = (GstHLSDemux2 *)stream->parent;
4690   gboolean bret = TRUE;
4691   gchar *ele_name = gst_element_get_name (GST_MESSAGE_SRC (msg));
4692
4693   GST_INFO_OBJECT(demux, "Message on BUS : %s", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
4694   switch (GST_MESSAGE_TYPE(msg)) {
4695     case GST_MESSAGE_EOS: {
4696       GST_INFO_OBJECT (demux, "received EOS on IMAGE pipe from '%s'.. Closing pipeline", ele_name);
4697       g_cond_signal (stream->convert_cond);
4698       gst_object_unref (stream->convert_pipe);
4699       break;
4700     }
4701     case GST_MESSAGE_ERROR: {
4702       GST_ERROR_OBJECT (demux, "Error Image Pipe from %s\n", ele_name);
4703       bret = FALSE;
4704       break;
4705     }
4706     default:{
4707       GST_DEBUG_OBJECT (demux, "Message on Image Pipe : %s from %s\n", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)), ele_name);
4708       bret = FALSE;
4709       break;
4710     }
4711   }
4712   g_free(ele_name);
4713   ele_name = NULL;
4714   return bret;
4715 }
4716
4717 static gboolean gst_hlsdemux2_done_video_buffer (GstPad * srcpad, GstEvent * event, gpointer user_data)
4718 {
4719   GstHLSDemux2PvtStream *stream = (GstHLSDemux2PvtStream *)user_data;
4720   GstHLSDemux2 *demux = (GstHLSDemux2 *)stream->parent;
4721   GST_LOG_OBJECT(demux,"EVENT %s on pad : %s having caps : %"GST_PTR_FORMAT,GST_EVENT_TYPE_NAME (event), GST_PAD_NAME(srcpad), srcpad->caps);
4722   if(event->type == GST_EVENT_EOS){
4723     GST_DEBUG_OBJECT(demux,"EVENT : %s Size : %d Pushing to demux video buffer [%d,%d]",
4724     GST_EVENT_TYPE_NAME (event),GST_BUFFER_SIZE(stream->video_buffer),
4725         stream->video_buffer->data[0],stream->video_buffer->data[1]);
4726     g_cond_signal (stream->convert_cond);
4727   }
4728   return TRUE;
4729 }
4730
4731 static gboolean gst_hlsdemux2_set_video_buffer (GstPad * srcpad, GstBuffer * buffer, gpointer user_data)
4732 {
4733   GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *)user_data;
4734   GstHLSDemux2 *demux = (GstHLSDemux2 *)pvt_stream->parent;
4735   GST_LOG_OBJECT(demux,"BUFFER size:%d on pad having caps : %"GST_PTR_FORMAT,GST_BUFFER_SIZE(buffer), srcpad->caps);
4736   GST_LOG_OBJECT(demux,"BUFFER DATA : %d %d",buffer->data[0],buffer->data[1]);
4737   pvt_stream->video_buffer = buffer;
4738   return TRUE;
4739 }
4740
4741 static void
4742 gst_hlsdemux2_downloader_eos (GstElement * appsink, void* user_data)
4743 {
4744   GstHLSDemux2Stream *stream = (GstHLSDemux2Stream *)user_data;
4745   GstHLSDemux2 *demux = stream->parent;
4746   GstBuffer *buf = NULL;
4747   gint64 percent = 0;
4748
4749   /* push all data to queue specific to this stream */
4750
4751   if (demux->cancelled || demux->flushing) {
4752     GST_WARNING_OBJECT (demux, "returning due to cancelled / flushing");
4753     return;
4754   }
4755
4756   if (g_queue_is_empty (stream->downloader_queue)) {
4757     GST_WARNING_OBJECT (demux, "EOS received without any buffer in downloader queue");
4758     return;
4759   }
4760
4761   if (demux->fdownloader->force_timestamps) {
4762     demux->cur_audio_fts = stream->prev_nts;
4763   }
4764
4765   if (demux->fdownloader->cur_stream_cnt < demux->active_stream_cnt) {
4766     gint idx = 0;
4767
4768     GST_INFO_OBJECT (demux, "need to send dummy data.. check for the stream");
4769
4770     /* signal queue full condition to come out */
4771     for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
4772       GstHLSDemux2Stream *cur_stream = demux->streams[idx];
4773       GError *error = NULL;
4774
4775       if (cur_stream) {
4776         if (g_queue_is_empty (cur_stream->downloader_queue)) {
4777           GST_INFO_OBJECT (cur_stream->pad, "enable sending dummy data");
4778
4779           /* take first ts of audio as cur_stream fts */
4780           cur_stream->fts = demux->cur_audio_fts;
4781
4782           /* create thread to send dummy data */
4783           cur_stream->dummy_data_thread = g_thread_create ((GThreadFunc) gst_hlsdemux2_push_dummy_data,
4784             cur_stream, TRUE, &error);
4785         }
4786       }
4787     }
4788   }
4789
4790   while (!g_queue_is_empty (stream->downloader_queue)) {
4791
4792     if (demux->cancelled || demux->flushing) {
4793       GST_WARNING_OBJECT (stream->pad, "on cancel/flushing stopping pushing");
4794       break;
4795     }
4796
4797     buf = (GstBuffer *) g_queue_pop_head (stream->downloader_queue);
4798
4799     GST_DEBUG_OBJECT (stream->pad, "input buffer timestamp : %"GST_TIME_FORMAT,
4800       GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
4801
4802     g_mutex_lock (stream->queue_lock);
4803
4804     if (!GST_BUFFER_TIMESTAMP_IS_VALID(buf)){
4805       g_queue_push_tail (stream->queue, buf);
4806       g_cond_signal (stream->queue_empty);
4807       g_mutex_unlock (stream->queue_lock);
4808       continue;
4809     }
4810
4811     GST_LOG_OBJECT (stream->pad, "buffer size = %d, ts = %"GST_TIME_FORMAT", dur = %"GST_TIME_FORMAT,
4812       GST_BUFFER_SIZE(buf), GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)), GST_TIME_ARGS(GST_BUFFER_DURATION(buf)));
4813
4814     /* calculate cached duration */
4815     gst_hlsdemux2_calculate_pushed_duration (demux, stream, buf);
4816
4817     if (stream->cached_duration < 0)
4818       stream->cached_duration = 0;
4819
4820     percent = (stream->cached_duration * 100) / demux->total_cache_duration;
4821     GST_LOG_OBJECT (stream->pad, "percent done = %"G_GINT64_FORMAT, (gint)percent, percent);
4822
4823     if (percent > 100) {
4824       guint64 overall_percent = 0;
4825
4826       g_mutex_lock (demux->buffering_lock);
4827       overall_percent = demux->percent;
4828       g_mutex_unlock (demux->buffering_lock);
4829
4830       if (overall_percent < 100) { /* otherwise, may cause blocking while buffering*/
4831         if (percent > 400) {
4832           GST_ERROR_OBJECT (stream->pad,"having worrest buffering.. exiting");
4833           GST_ELEMENT_ERROR (demux, STREAM, FAILED, ("wrong buffering.. check implementation"), (NULL));
4834         }
4835         GST_INFO_OBJECT (stream->pad, "@@@@@@ queue should not go to wait now @@@@@@@@");
4836       } else {
4837         /* update buffering & wait if space is not available */
4838         GST_LOG_OBJECT (stream->pad, "Reached more than 100 percent, queue full & wait till free");
4839         g_cond_wait(stream->queue_full, stream->queue_lock);
4840         GST_LOG_OBJECT (stream->pad,"Received signal to add more data...");
4841       }
4842     }
4843
4844     g_cond_signal (stream->queue_empty);
4845
4846     g_mutex_unlock (stream->queue_lock);
4847   }
4848
4849   /* wait for dummy threads finish their processing */
4850   if (demux->fdownloader->cur_stream_cnt < demux->active_stream_cnt) {
4851     gint idx = 0;
4852
4853     GST_INFO_OBJECT (demux, "need to close dummy threads");
4854
4855     /* signal queue full condition to come out */
4856     for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
4857       GstHLSDemux2Stream *cur_stream = demux->streams[idx];
4858
4859       if (cur_stream && cur_stream->dummy_data_thread) {
4860         GST_INFO_OBJECT (stream->pad, "waiting for dummy push thread to finish...");
4861         g_thread_join(cur_stream->dummy_data_thread);
4862         cur_stream->dummy_data_thread = NULL;
4863         GST_INFO_OBJECT (stream->pad, "COMPLETED DUMMY PUSH...");
4864       }
4865     }
4866   }
4867
4868 #ifdef LATEST_AV_SYNC
4869   if (demux->is_live) {
4870     stream->total_stream_time += (stream->lts - stream->fts);
4871   } else {
4872     stream->total_stream_time += (stream->lts - stream->fts + stream->frame_duration);
4873     stream->nts = stream->total_stream_time;
4874   }
4875 #else
4876   stream->total_stream_time += (stream->lts - stream->fts);
4877 #endif
4878
4879   GST_DEBUG_OBJECT (stream->pad, "---------------- TS VALUES ----------------");
4880   GST_DEBUG_OBJECT (stream->pad, "valid start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->fts));
4881   GST_DEBUG_OBJECT (stream->pad, "valid end ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts));
4882   GST_DEBUG_OBJECT (stream->pad, "fragment duration received = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->lts - stream->fts));
4883   GST_DEBUG_OBJECT (stream->pad, "total stream time = %"GST_TIME_FORMAT,GST_TIME_ARGS(stream->total_stream_time));
4884   GST_DEBUG_OBJECT (stream->pad, "total disc time = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->total_disc));
4885   GST_DEBUG_OBJECT (stream->pad, "next expected start ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(stream->nts));
4886   GST_DEBUG_OBJECT (stream->pad, "---------------- DUMP VALUES END----------------");
4887
4888   stream->apply_disc = FALSE;
4889   stream->fts = GST_CLOCK_TIME_NONE;
4890   stream->valid_fts_rcvd = FALSE;
4891   stream->prev_nts = stream->nts;
4892   demux->fdownloader->force_timestamps = FALSE;
4893   return;
4894 }
4895
4896 static void
4897 gst_hlsdemux2_push_eos (GstHLSDemux2 *demux)
4898 {
4899   guint idx = 0;
4900
4901   /* signal queue full condition to come out */
4902   for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
4903     GstHLSDemux2Stream *stream = demux->streams[idx];
4904
4905     if (stream) {
4906       g_mutex_lock (stream->queue_lock);
4907       /* end of playlist, push EOS to queue */
4908       GST_INFO_OBJECT (stream->pad, "pushing EOS event to stream's queue");
4909       g_queue_push_tail (stream->queue, gst_event_new_eos ());
4910       g_cond_signal (stream->queue_empty);
4911       g_mutex_unlock (stream->queue_lock);
4912     }
4913   }
4914 }
4915
4916 static void
4917 gst_hlsdemux2_on_playlist_buffer (GstElement *appsink, void *data)
4918 {
4919   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
4920   GstBuffer *inbuf = NULL;
4921
4922   inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
4923   if (!inbuf) {
4924     GST_WARNING_OBJECT (demux, "Input buffer not available...");
4925     return;
4926   }
4927
4928   if (demux->pldownloader->playlist == NULL) {
4929     demux->pldownloader->playlist = gst_buffer_copy (inbuf);
4930     gst_buffer_unref (inbuf);
4931   } else {
4932     GstBuffer *buffer = NULL;
4933     guint size = GST_BUFFER_SIZE(demux->pldownloader->playlist) + GST_BUFFER_SIZE(inbuf);
4934
4935     buffer = gst_buffer_new_and_alloc (size);
4936     if (!buffer) {
4937       GST_ERROR_OBJECT (demux, "failed allocate memory...");
4938       GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
4939       gst_buffer_unref (inbuf);
4940       gst_buffer_unref (demux->pldownloader->playlist);
4941       return;
4942     }
4943
4944     /*copy existing playlist buffer */
4945     memcpy (GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(demux->pldownloader->playlist), GST_BUFFER_SIZE(demux->pldownloader->playlist));
4946
4947     /*copy new playlist buffer */
4948     memcpy (GST_BUFFER_DATA(buffer) + GST_BUFFER_SIZE(demux->pldownloader->playlist),
4949         GST_BUFFER_DATA(inbuf), GST_BUFFER_SIZE(inbuf));
4950
4951     gst_buffer_unref (inbuf);
4952     gst_buffer_unref (demux->pldownloader->playlist);
4953     demux->pldownloader->playlist = buffer;
4954   }
4955
4956   return;
4957 }
4958
4959 static void
4960 gst_hlsdemux2_on_key_buffer (GstElement *appsink, void *data)
4961 {
4962   GstHLSDemux2 *demux = (GstHLSDemux2 *)data;
4963   GstBuffer *inbuf = NULL;
4964
4965   inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
4966   if (!inbuf) {
4967     GST_WARNING_OBJECT (demux, "Input buffer not available...");
4968     return;
4969   }
4970
4971   if (demux->kdownloader->key == NULL) {
4972     demux->kdownloader->key = gst_buffer_copy (inbuf);
4973     gst_buffer_unref (inbuf);
4974   } else {
4975     GstBuffer *buffer = NULL;
4976     guint size = GST_BUFFER_SIZE(demux->kdownloader->key) + GST_BUFFER_SIZE(inbuf);
4977
4978     buffer = gst_buffer_new_and_alloc (size);
4979     if (!buffer) {
4980       GST_ERROR_OBJECT (demux, "failed allocate memory...");
4981       GST_ELEMENT_ERROR (demux, RESOURCE, NO_SPACE_LEFT, ("can't allocate memory"), (NULL));
4982       gst_buffer_unref (inbuf);
4983       gst_buffer_unref (demux->kdownloader->key);
4984       return;
4985     }
4986
4987     /*copy existing playlist buffer */
4988     memcpy (GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(demux->kdownloader->key), GST_BUFFER_SIZE(demux->kdownloader->key));
4989
4990     /*copy new playlist buffer */
4991     memcpy (GST_BUFFER_DATA(buffer) + GST_BUFFER_SIZE(demux->kdownloader->key),
4992         GST_BUFFER_DATA(inbuf), GST_BUFFER_SIZE(inbuf));
4993
4994     gst_buffer_unref (inbuf);
4995     gst_buffer_unref (demux->kdownloader->key);
4996     demux->kdownloader->key = buffer;
4997   }
4998
4999   return;
5000 }
5001
5002 static void
5003 gst_hlsdemux2_stop (GstHLSDemux2 *demux)
5004 {
5005   GST_INFO_OBJECT (demux, "entering...");
5006
5007   demux->cancelled = TRUE;
5008
5009   g_cond_signal (demux->post_msg_start);
5010   g_cond_signal (demux->post_msg_exit);
5011
5012   /* special case: for exiting playlist downloader created from sink event */
5013   if (demux->pldownloader && demux->pldownloader->cond)
5014     g_cond_broadcast (demux->pldownloader->cond);
5015
5016   while (demux->download_task && (GST_TASK_STATE (demux->download_task) != GST_TASK_STOPPED)) {
5017     int idx = 0;
5018     GstHLSDemux2Stream *stream = NULL;
5019
5020     GST_INFO_OBJECT (demux, "Closing Download task...");
5021
5022     /* signal queue full conditions */
5023     for (idx = 0; idx < HLSDEMUX2_STREAM_NUM; idx++) {
5024       stream = demux->streams[idx];
5025
5026       if (stream && GST_PAD_TASK(stream->pad)) {
5027         gst_pad_push_event (stream->pad, gst_event_new_flush_start ());
5028         g_cond_broadcast(stream->queue_full);
5029         g_cond_broadcast(stream->queue_empty);
5030       }
5031     }
5032
5033     if (demux->pl_update_cond)
5034       g_cond_broadcast (demux->pl_update_cond);
5035
5036     if (demux->fdownloader && demux->fdownloader->cond)
5037       g_cond_broadcast (demux->fdownloader->cond);
5038     if (demux->kdownloader && demux->kdownloader->cond)
5039       g_cond_broadcast (demux->kdownloader->cond);
5040     if (demux->pldownloader && demux->pldownloader->cond)
5041       g_cond_broadcast (demux->pldownloader->cond);
5042
5043     GST_INFO_OBJECT (demux, "Waiting to acquire download lock");
5044     g_static_rec_mutex_lock (&demux->download_lock);
5045     g_static_rec_mutex_unlock (&demux->download_lock);
5046
5047     GST_INFO_OBJECT (demux, "Waiting download task JOIN");
5048     gst_task_join (demux->download_task);
5049     gst_object_unref (demux->download_task);
5050     demux->download_task = NULL;
5051
5052     GST_INFO_OBJECT (demux, "Completed closing of download task...");
5053
5054     g_thread_join(demux->buffering_posting_thread);
5055     GST_INFO_OBJECT (demux, "Completed closing of download monitor thread...");
5056
5057     if (demux->fdownloader && demux->fdownloader->pipe) {
5058       GST_WARNING_OBJECT (demux, "Still fragment download exist");
5059       gst_hlsdemux2_destroy_fragment_download (demux);
5060     }
5061     if (demux->pldownloader && demux->pldownloader->pipe) {
5062       GST_WARNING_OBJECT (demux, "Still playlist download exist");
5063       gst_hlsdemux2_destroy_playlist_download (demux);
5064     }
5065     if (demux->kdownloader && demux->kdownloader->pipe) {
5066       GST_WARNING_OBJECT (demux, "Still key download exist");
5067       gst_hlsdemux2_destroy_key_download (demux);
5068     }
5069   }
5070
5071   gst_hlsdemux2_stop_stream (demux);
5072
5073   GST_INFO_OBJECT (demux, "leaving...");
5074 }
5075
5076 static void
5077 gst_hlsdemux2_stop_stream (GstHLSDemux2 *demux)
5078 {
5079   int n = 0;
5080   GstHLSDemux2Stream *stream = NULL;
5081   gchar *pad_name = NULL;
5082
5083   GST_INFO_OBJECT (demux, "entering");
5084
5085   for (n = 0; n < HLSDEMUX2_STREAM_NUM; n++) {
5086     stream = demux->streams[n];
5087
5088     if (stream && GST_PAD_TASK(stream->pad)) {
5089       pad_name = gst_pad_get_name (stream->pad);
5090       GST_INFO_OBJECT (stream->pad, "stopping pad task : %s", pad_name);
5091       gst_pad_stop_task (stream->pad);
5092       GST_INFO_OBJECT (stream->pad, "stopped pad task : %s", pad_name);
5093       g_free(pad_name);
5094       pad_name = NULL;
5095     }
5096   }
5097
5098   for (n = 0; n < HLSDEMUX2_STREAM_NUM; n++) {
5099     if (demux->streams[n]) {
5100       gst_hlsdemux2_stream_deinit(demux->streams[n], demux);
5101       demux->streams[n] = NULL;
5102     }
5103   }
5104   demux->active_stream_cnt = 0;
5105   GST_INFO_OBJECT (demux, "leaving");
5106 }
5107
5108 static void
5109 gst_hlsdemux2_stream_init (GstHLSDemux2 *demux, GstHLSDemux2Stream *stream, HLSDEMUX2_STREAM_TYPE stream_type, gchar *name, GstCaps *src_caps)
5110 {
5111   stream->queue = g_queue_new ();
5112   stream->queue_full = g_cond_new ();
5113   stream->queue_empty = g_cond_new ();
5114   stream->queue_lock = g_mutex_new ();
5115   stream->parent = demux;
5116   stream->type = stream_type;
5117   stream->percent = 100;
5118   stream->eos = FALSE;
5119   stream->cached_duration = 0;
5120   stream->lts = 0;
5121   stream->dummy_data_thread = NULL;
5122   stream->base_ts = GST_CLOCK_TIME_NONE;
5123   stream->fts = GST_CLOCK_TIME_NONE;
5124   stream->valid_fts_rcvd = FALSE;
5125   stream->total_stream_time = 0;
5126   stream->total_disc = 0;
5127   stream->cdisc = 0;
5128   stream->nts = GST_CLOCK_TIME_NONE;
5129   stream->prev_nts = 0;
5130   stream->downloader_queue = g_queue_new();
5131   stream->need_newsegment = TRUE;
5132   stream->newsegment = NULL;
5133   stream->frame_duration = 0;
5134
5135   if (stream_type == HLSDEMUX2_STREAM_VIDEO) {
5136     stream->pad = gst_pad_new_from_static_template (&hlsdemux2_videosrc_template, name);
5137     GST_INFO_OBJECT (demux, "Its a Multi-variant stream..");
5138     demux->stream_config = HLSDEMUX2_MULTI_VARIANT;
5139   } else if (stream_type == HLSDEMUX2_STREAM_AUDIO) {
5140     stream->pad = gst_pad_new_from_static_template (&hlsdemux2_audiosrc_template, name);
5141   } else if (stream_type == HLSDEMUX2_STREAM_TEXT) {
5142     stream->pad = gst_pad_new_from_static_template (&hlsdemux2_subpicture_template, name);
5143   } else if (stream_type == HLSDEMUX2_STREAM_PRIVATE) {
5144     stream->pad = gst_pad_new_from_static_template (&hlsdemux2_private_template, name);
5145   }
5146
5147   GST_INFO_OBJECT (demux, "======>>>> created hlsdemux2 source pad : %s", name);
5148
5149   GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
5150
5151   gst_pad_use_fixed_caps (stream->pad);
5152   gst_pad_set_event_function (stream->pad, gst_hlsdemux2_handle_src_event);
5153   gst_pad_set_query_function (stream->pad, gst_hlsdemux2_src_query);
5154   gst_pad_set_caps (stream->pad, src_caps);
5155
5156   GST_DEBUG_OBJECT (demux, "adding pad %s %p to demux %p", GST_OBJECT_NAME (stream->pad), stream->pad, demux);
5157   gst_pad_set_active (stream->pad, TRUE);
5158   gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
5159
5160   if (!gst_pad_is_linked (stream->pad)) {
5161     GST_WARNING_OBJECT (stream->pad, "'%s' pad is not linked...", GST_OBJECT_NAME (stream->pad));
5162     stream->is_linked = FALSE;
5163     return;
5164   }
5165   stream->is_linked = TRUE;
5166
5167   if (!gst_pad_start_task (stream->pad, (GstTaskFunction) gst_hlsdemux2_push_loop, stream)) {
5168     GST_ERROR_OBJECT (demux, "failed to create stream task...");
5169     GST_ELEMENT_ERROR (demux, RESOURCE, FAILED, ("failed to create stream push loop"), (NULL));
5170     return;
5171   }
5172
5173 }
5174
5175 static void
5176 gst_hlsdemux2_stream_deinit (GstHLSDemux2Stream *stream, gpointer data)
5177 {
5178   GstHLSDemux2 * demux = (GstHLSDemux2 *)data;
5179   if (stream) {
5180
5181     if (stream->queue) {
5182       while (!g_queue_is_empty(stream->queue)) {
5183         gst_buffer_unref (g_queue_pop_head (stream->queue));
5184       }
5185       g_queue_free (stream->queue);
5186       stream->queue = NULL;
5187     }
5188
5189     if (stream->pad) {
5190       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
5191       stream->pad = NULL;
5192     }
5193
5194     if (stream->queue_lock) {
5195       g_mutex_free (stream->queue_lock);
5196       stream->queue_lock = NULL;
5197     }
5198     if (stream->queue_full) {
5199       g_cond_free (stream->queue_full);
5200       stream->queue_full = NULL;
5201     }
5202     if (stream->queue_empty) {
5203       g_cond_free (stream->queue_empty);
5204       stream->queue_empty= NULL;
5205     }
5206     g_free (stream);
5207   }
5208
5209 }
5210
5211 static gboolean
5212 gst_hlsdemux2_set_location (GstHLSDemux2 * demux, const gchar * uri)
5213 {
5214   if (demux->client)
5215     gst_m3u8_client_free (demux->client);
5216   demux->client = gst_m3u8_client_new (uri);
5217   GST_INFO_OBJECT (demux, "Changed location: %s", uri);
5218   return TRUE;
5219 }
5220
5221 static gchar *
5222 gst_hlsdemux2_src_buf_to_utf8_playlist (GstBuffer * buf)
5223 {
5224   gint size;
5225   gchar *data;
5226   gchar *playlist;
5227
5228   data = (gchar *) GST_BUFFER_DATA (buf);
5229   size = GST_BUFFER_SIZE (buf);
5230
5231 #if 0 /* giving error some times, so removing*/
5232   if (!g_utf8_validate (data, size, NULL))
5233     goto validate_error;
5234 #endif
5235
5236   /* alloc size + 1 to end with a null character */
5237   playlist = g_malloc0 (size + 1);
5238   if (!playlist) {
5239     GST_ERROR ("failed to create memory...");
5240     gst_buffer_unref (buf);
5241     return NULL;
5242   }
5243
5244   memcpy (playlist, data, size);
5245   playlist[size] = '\0';
5246
5247   gst_buffer_unref (buf);
5248   return playlist;
5249 #if 0
5250 validate_error:
5251   gst_buffer_unref (buf);
5252   GST_ERROR ("failed to validate playlist");
5253   return NULL;
5254 #endif
5255 }
5256
5257 static void
5258 gst_hlsdemux2_handle_private_pad (GstHLSDemux2 *demux, GstPad *srcpad)
5259 {
5260   GstHLSDemux2PvtStream *pvt_stream = NULL;
5261   gchar *sinkname = NULL;
5262   GstPad *sinkpad = NULL;
5263
5264   pvt_stream = g_new0 (GstHLSDemux2PvtStream, 1);
5265
5266   demux->private_stream = pvt_stream;
5267   pvt_stream->parent = demux;
5268   pvt_stream->type = HLSDEMUX2_STREAM_PRIVATE;
5269   pvt_stream->image_buffer = NULL;
5270   pvt_stream->got_img_buffer = FALSE;
5271   pvt_stream->video_buffer = NULL;
5272   pvt_stream->id3_buffer   = NULL;
5273   pvt_stream->convert_lock = g_mutex_new ();
5274   pvt_stream->convert_cond = g_cond_new ();
5275   pvt_stream->sink = NULL;
5276   pvt_stream->img_load_lock = g_mutex_new ();
5277   pvt_stream->img_load_cond = g_cond_new ();
5278
5279   /* create sink element */
5280   sinkname = g_strdup_printf("%s-%s", GST_PAD_NAME(srcpad) , "sink");
5281   pvt_stream->sink =  gst_element_factory_make ("appsink", NULL);
5282   if (!pvt_stream->sink) {
5283     GST_ERROR_OBJECT (demux, "failed to create sink element - %s", sinkname);
5284     GST_ELEMENT_ERROR (demux, CORE, FAILED, ("failed to create element - %s", sinkname), (NULL));
5285     g_free(sinkname);
5286     sinkname = NULL;
5287     return;
5288   }
5289
5290   /* set sink element to PLAYING state */
5291   gst_bin_add (GST_BIN (demux->fdownloader->pipe), pvt_stream->sink);
5292   gst_element_set_state (pvt_stream->sink, GST_STATE_READY);
5293   g_object_set (G_OBJECT (pvt_stream->sink), "sync", FALSE, "emit-signals", TRUE, NULL);
5294
5295   sinkpad = gst_element_get_pad(pvt_stream->sink, "sink");
5296   if (!sinkpad) {
5297     GST_ERROR_OBJECT (demux, "failed to get sinkpad from element  - %s", sinkname);
5298     GST_ELEMENT_ERROR (demux, CORE, PAD, ("Count not get sink pad"), (NULL));
5299     g_free(sinkname);
5300     sinkname = NULL;
5301     return;
5302   }
5303
5304   if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
5305     GST_ERROR_OBJECT (demux, "failed to link sink bin elements");
5306     GST_ELEMENT_ERROR (demux, CORE, NEGOTIATION, ("Could not link pads.."), (NULL));
5307     gst_object_unref(sinkpad);
5308   }
5309
5310   gst_element_set_state (pvt_stream->sink, GST_STATE_PLAYING);
5311
5312   g_signal_connect (pvt_stream->sink, "new-buffer",  G_CALLBACK (gst_hlsdemux2_private_sink_on_new_buffer), pvt_stream);
5313   g_signal_connect (pvt_stream->sink, "eos",  G_CALLBACK (gst_hlsdemux2_private_sink_on_eos), pvt_stream);
5314
5315   gst_object_unref(sinkpad);
5316
5317   GST_INFO_OBJECT (demux, "successfully created private pad bin...");
5318
5319   g_free(sinkname);
5320   sinkname = NULL;
5321   return;
5322 }
5323
5324 static void
5325 gst_hlsdemux2_private_sink_on_new_buffer (GstElement *appsink, void *user_data)
5326 {
5327   GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *)user_data;
5328   GstHLSDemux2 *demux = pvt_stream->parent;
5329   GstBuffer *inbuf = NULL;
5330
5331   inbuf = gst_app_sink_pull_buffer ((GstAppSink *)appsink);
5332   if (!inbuf) {
5333     GST_ERROR_OBJECT (demux, "Input buffer not available....");
5334     return;
5335   }
5336
5337   GST_LOG_OBJECT (demux, "Image buffer received of size = %d", GST_BUFFER_SIZE (inbuf));
5338   if(pvt_stream->id3_buffer==NULL)
5339     pvt_stream->id3_buffer = gst_buffer_copy(inbuf);
5340   else
5341     pvt_stream->id3_buffer = gst_buffer_join (pvt_stream->id3_buffer, inbuf);
5342   return;
5343 }
5344
5345 static void
5346 gst_hlsdemux2_private_sink_on_eos (GstElement * appsink, void* user_data)
5347 {
5348   GstHLSDemux2PvtStream *pvt_stream = (GstHLSDemux2PvtStream *)user_data;
5349   GstHLSDemux2 *demux = pvt_stream->parent;
5350   GstBuffer *image_buffer = NULL;
5351   GstTagList *tag_list = gst_tag_list_from_id3v2_tag(pvt_stream->id3_buffer);
5352
5353   GST_INFO_OBJECT (demux, "Processing image buffer");
5354
5355   if(!gst_tag_list_get_buffer (tag_list, GST_TAG_IMAGE, &image_buffer)) {
5356     GST_ERROR_OBJECT(demux, "Failed to obtain image data.");
5357     return;
5358   }
5359
5360   if(demux->stream_config == HLSDEMUX2_SINGLE_VARIANT) {
5361     gchar *image_header = NULL;
5362     GValue codec_type = G_VALUE_INIT;
5363     GstMessage * tag_message = NULL;
5364
5365     /* check whether it is same as previous image */
5366     if (demux->prev_image_buffer &&
5367       (GST_BUFFER_SIZE(demux->prev_image_buffer) == GST_BUFFER_SIZE(image_buffer))) {
5368       if (!memcmp (GST_BUFFER_DATA(demux->prev_image_buffer), GST_BUFFER_DATA(image_buffer), GST_BUFFER_SIZE(image_buffer))) {
5369         GST_INFO_OBJECT (demux, "current & previous embedded images are same..no need to post image again");
5370         gst_buffer_unref (image_buffer);
5371         return;
5372       }
5373     }
5374
5375     if (demux->prev_image_buffer) {
5376       gst_buffer_unref (demux->prev_image_buffer);
5377     }
5378     demux->prev_image_buffer = gst_buffer_copy(image_buffer);
5379
5380     image_header = g_strndup((gchar *) image_buffer->data, 8);
5381
5382     g_value_init (&codec_type, G_TYPE_STRING);
5383
5384     if((image_header[0] == 0xFF) && (image_header[1] == 0xD8)) {
5385       GST_INFO_OBJECT(demux, "Found JPEG image header");
5386       g_value_set_static_string (&codec_type, "image/jpeg");
5387       gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
5388     } else if (!g_strcmp0(image_header, "\211PNG\015\012\032\012")) {
5389       GST_INFO_OBJECT(demux, "Found PNG image header");
5390       g_value_set_static_string (&codec_type, "image/png");
5391       gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
5392     } else {
5393       g_value_set_static_string (&codec_type, "image/unknown");
5394       GST_INFO_OBJECT(demux, "Unknown image header");
5395       gst_tag_list_add_value(tag_list, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, &codec_type);
5396     }
5397
5398     GST_INFO_OBJECT(demux, "Set value : %s", g_value_get_string (&codec_type));
5399     g_value_unset(&codec_type);
5400
5401     tag_message = gst_message_new_tag (GST_OBJECT_CAST (demux), tag_list);
5402     if(!gst_element_post_message (GST_ELEMENT_CAST (demux), tag_message)) {
5403       GST_ERROR_OBJECT (demux, "failed to post image tag");
5404       gst_buffer_unref (image_buffer);
5405       g_free (image_header);
5406       return;
5407     }
5408
5409     GST_INFO_OBJECT (demux, "successfully posted image tag...");
5410     gst_buffer_unref (image_buffer);
5411     g_free (image_header);
5412     return;
5413   }
5414
5415   GST_INFO_OBJECT(demux, "image header : %d,%d", image_buffer->data[0],image_buffer->data[1]);
5416
5417   pvt_stream->image_buffer = gst_buffer_copy(image_buffer);
5418   gst_buffer_unref (image_buffer);
5419   pvt_stream->got_img_buffer = TRUE;
5420
5421   g_cond_signal (pvt_stream->img_load_cond);
5422   demux->has_image_buffer = TRUE;
5423
5424 }
5425
5426 static gboolean
5427 hlsdemux2_init (GstPlugin * plugin)
5428 {
5429   if (!gst_element_register (plugin, "hlsdemux2", GST_RANK_PRIMARY + 1, GST_TYPE_HLSDEMUX2) || FALSE)
5430     return FALSE;
5431   return TRUE;
5432 }
5433
5434 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
5435   GST_VERSION_MINOR,
5436   "hlsdemux2",
5437   "HLS demux - 2 plugin",
5438   hlsdemux2_init,
5439   VERSION,
5440   "LGPL",
5441   PACKAGE_NAME,
5442   "http://www.samsung.com/")
5443