tizen2.0 init
[framework/multimedia/gst-plugins-ext0.10.git] / ssdemux / src / ssmanifestparse.c
1 #include "ssmanifestparse.h"
2
3 static gboolean ssm_parse_root_node (GstSSMParse *parser, xmlNodePtr root_node);
4 GstCaps * ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream);
5 GstCaps * ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream);
6 GstCaps *ssm_prepare_text_caps (GstSSMParse *parser, GstSSMStreamNode *stream);
7 static gboolean convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len);
8
9 #define MANIFEST_LOCK(parser) g_mutex_lock(parser->lock)
10 #define MANIFEST_UNLOCK(parser) g_mutex_unlock(parser->lock)
11 #define START_TS_MAX(a,b) ((a)>(b) ? (a) : (b))
12
13 const gchar *
14 ssm_parse_get_stream_name(SS_STREAM_TYPE type)
15 {
16   if (type == SS_STREAM_VIDEO) return "video"; \
17   else if (type == SS_STREAM_AUDIO) return "audio"; \
18   else if (type == SS_STREAM_TEXT) return "text"; \
19   else return "unknown";
20 }
21
22
23 static gboolean
24 int_from_string (gchar * ptr, gchar ** endptr, gint * val, gint base)
25 {
26   gchar *end;
27   g_return_val_if_fail (ptr != NULL, FALSE);
28   g_return_val_if_fail (val != NULL, FALSE);
29
30   errno = 0;
31   *val = strtol (ptr, &end, base);
32   if ((errno == ERANGE && (*val == LONG_MAX || *val == LONG_MIN)) || (errno != 0 && *val == 0)) {
33     g_print ("Error in strtol : %s\n", strerror(errno));
34     return FALSE;
35   }
36
37   if (endptr)
38     *endptr = end;
39
40   return end != ptr;
41 }
42
43 static gboolean
44 ssm_parse_get_xml_prop_boolean (GstSSMParse *parser, xmlNode * node,
45     const gchar * property)
46 {
47   xmlChar *prop_string;
48   gboolean prop_bool = FALSE;
49
50   prop_string = xmlGetProp (node, (const xmlChar *) property);
51   if (prop_string) {
52     if ((xmlStrcmp (prop_string, (xmlChar *) "false") == 0) ||
53         (xmlStrcmp (prop_string, (xmlChar *) "FALSE") == 0)) {
54       GST_LOG (" - %s: false", property);
55     } else if ((xmlStrcmp (prop_string, (xmlChar *) "true") == 0) ||
56        (xmlStrcmp (prop_string, (xmlChar *) "TRUE") == 0)) {
57       GST_LOG(" - %s: true", property);
58       prop_bool = TRUE;
59     } else {
60       GST_WARNING("failed to parse boolean property %s from xml string %s", property, prop_string);
61     }
62     xmlFree (prop_string);
63   }
64
65   return prop_bool;
66 }
67
68 static guint
69 ssm_parse_get_xml_prop_uint (GstSSMParse *parser,
70     xmlNode * node, const gchar * property, guint default_val)
71 {
72   xmlChar *prop_string;
73   guint prop_uint = default_val;
74
75   prop_string = xmlGetProp (node, (const xmlChar *) property);
76   if (prop_string) {
77     if (sscanf ((gchar *) prop_string, "%u", &prop_uint)) {
78       GST_LOG (" - %s: %u", property, prop_uint);
79     } else {
80       GST_WARNING("failed to parse unsigned integer property %s from xml string %s",
81           property, prop_string);
82     }
83     xmlFree (prop_string);
84   }
85
86   return prop_uint;
87 }
88
89 static guint64
90 ssm_parse_get_xml_prop_uint64 (GstSSMParse *parser,
91     xmlNode * node, const gchar * property, guint64 default_val)
92 {
93   xmlChar *prop_string;
94   guint64 prop_uint64 = default_val;
95
96   prop_string = xmlGetProp (node, (const xmlChar *) property);
97   if (prop_string) {
98     if (sscanf ((gchar *) prop_string, "%llu", &prop_uint64)) {
99       GST_LOG (" - %s: %s[%"G_GUINT64_FORMAT"]", property, prop_string, prop_uint64);
100     } else {
101       GST_WARNING("failed to parse unsigned integer property %s from xml string %s",
102           property, prop_string);
103     }
104     xmlFree (prop_string);
105   }
106
107   return prop_uint64;
108
109
110 static gint
111 ssm_parser_sort_qualitylevels_by_bitrate (gconstpointer a, gconstpointer b)
112 {
113         return ((GstSSMQualityNode *) (a))->bitrate - ((GstSSMQualityNode *) (b))->bitrate; //sorting in ascending order
114         //return ((GstSSMQualityNode *) (b))->bitrate - ((GstSSMQualityNode *) (a))->bitrate; // sorting in descending order
115 }
116
117
118 static void
119 gst_ssm_parse_free_quality_node (GstSSMQualityNode *qualitynode)
120 {
121   if (qualitynode) {
122     g_free (qualitynode->codec_data);
123     g_free (qualitynode->fourcc);
124     g_slice_free (GstSSMQualityNode, qualitynode);
125   }
126 }
127
128 static void
129 gst_ssm_parse_free_fragment_node (GstSSMFragmentNode*fragnode)
130 {
131   if (fragnode) {
132     g_slice_free (GstSSMFragmentNode, fragnode);
133   }
134 }
135
136
137 static void
138 gst_ssm_parse_free_stream_node (GstSSMStreamNode *streamnode)
139 {
140   if (streamnode) {
141     if (streamnode->quality_lists) {
142       streamnode->quality_lists = g_list_first (streamnode->quality_lists);
143       g_list_foreach (streamnode->quality_lists, (GFunc) gst_ssm_parse_free_quality_node, NULL);
144       g_list_free (streamnode->quality_lists);
145       streamnode->quality_lists = NULL;
146     }
147     if (streamnode->fragment_lists) {
148       streamnode->fragment_lists = g_list_first (streamnode->fragment_lists);
149       g_list_foreach (streamnode->fragment_lists, (GFunc) gst_ssm_parse_free_fragment_node, NULL);
150       g_list_free (streamnode->fragment_lists);
151       streamnode->fragment_lists = NULL;
152     }
153     if (streamnode->StreamType) {
154       g_free(streamnode->StreamType);
155       streamnode->StreamType = NULL;
156     }
157     if (streamnode->StreamUrl) {
158       g_free(streamnode->StreamUrl);
159       streamnode->StreamUrl = NULL;
160     }
161     if (streamnode->StreamSubType) {
162       g_free(streamnode->StreamSubType);
163       streamnode->StreamSubType = NULL;
164     }
165     if (streamnode->StreamName) {
166       g_free(streamnode->StreamName);
167       streamnode->StreamName = NULL;
168     }
169     if (streamnode->frag_cond) {
170       g_cond_free (streamnode->frag_cond);
171       streamnode->frag_cond = NULL;
172     }
173     if (streamnode->frag_lock) {
174       g_mutex_free (streamnode->frag_lock);
175       streamnode->frag_lock = NULL;
176     }
177     g_slice_free (GstSSMStreamNode, streamnode);
178   }
179 }
180
181 GstSSMParse *
182 gst_ssm_parse_new (const gchar * uri)
183 {
184   GstSSMParse *parser;
185   gchar *tmp = NULL;
186
187   g_return_val_if_fail (uri != NULL, NULL);
188
189   parser = g_new0 (GstSSMParse, 1);
190
191   parser->uri = g_strdup (uri);
192   parser->lock = g_mutex_new();
193   tmp = strrchr(uri, '/');
194   tmp = tmp+1;
195   parser->presentation_uri = (gchar *) malloc (tmp - uri + 1);
196   if (NULL == parser->presentation_uri) {
197     GST_ERROR ("Failed to allocate memory..\n");
198     return NULL;
199   }
200
201   strncpy (parser->presentation_uri, uri, tmp - uri);
202   parser->presentation_uri[tmp-uri] = '\0';
203   parser->ns_start = GST_CLOCK_TIME_NONE;
204   GST_INFO ("Presentation URI : %s", parser->presentation_uri);
205   return parser;
206 }
207
208 void
209 gst_ssm_parse_free (GstSSMParse *parser)
210 {
211   int i =0;
212
213   g_return_if_fail (parser != NULL);
214
215   g_mutex_free(parser->lock);
216
217   // TODO: cleanup memory allocated.....
218   if (parser->RootNode) {
219     for (i = 0; i < SS_STREAM_NUM; i++) {
220       if (parser->RootNode->streams[i]) {
221         g_list_foreach (parser->RootNode->streams[i], (GFunc) gst_ssm_parse_free_stream_node, NULL);
222         parser->RootNode->streams[i] = NULL;
223       }
224     }
225     if (parser->RootNode->ProtectNode) {
226       g_slice_free (GstSSMProtectionNode, parser->RootNode->ProtectNode);
227       parser->RootNode->ProtectNode = NULL;
228     }
229     g_slice_free (GstSSMRootNode, parser->RootNode);
230     parser->RootNode = NULL;
231   }
232
233   g_free (parser);
234 }
235
236
237 static gboolean
238 ssm_parse_quality_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr quality_node)
239 {
240   GstSSMQualityNode *quality_level = NULL;
241
242   g_return_val_if_fail (parser != NULL, FALSE);
243   g_return_val_if_fail (quality_node != NULL, FALSE);
244   g_return_val_if_fail (stream != NULL, FALSE);
245
246   quality_level = g_slice_new0 (GstSSMQualityNode);
247   if (quality_level == NULL) {
248     GST_ERROR ("Allocation of quality_level node failed!");
249     return FALSE;
250   }
251
252   quality_level->codec_data = NULL;
253   quality_level->fourcc = NULL;
254
255   quality_level->index = ssm_parse_get_xml_prop_uint (parser, quality_node, "Index", -1);
256   GST_DEBUG("Quality Index = %d", quality_level->index);
257   if (SS_STREAM_VIDEO == stream->type && (quality_level->index == -1)) {
258     GST_ERROR ("Index attribute is not present for VIDEO stream...");
259     return FALSE;
260   }
261
262   /* MANDATORY : parsing Bitrate attribute */
263   quality_level->bitrate = ssm_parse_get_xml_prop_uint (parser, quality_node, "Bitrate", -1);
264   GST_DEBUG("Bitrate = %d", quality_level->bitrate);
265   if (quality_level->bitrate == -1) {
266     GST_ERROR ("bitrate attribute is not present...");
267     return FALSE;
268   }
269
270   /* MANDATORY for video: parsing MaxWidth attribute */
271   quality_level->max_width = ssm_parse_get_xml_prop_uint (parser, quality_node, "MaxWidth", -1);
272   GST_DEBUG("MaxWidth = %d", quality_level->max_width);
273   if (SS_STREAM_VIDEO == stream->type && (quality_level->max_width == -1)) {
274     GST_ERROR ("max_width attribute is not present in VIDEO...");
275     return FALSE;
276   }
277
278   /* MANDATORY for video: parsing MaxHeight attribute */
279   quality_level->max_height = ssm_parse_get_xml_prop_uint (parser, quality_node, "MaxHeight", -1);
280   GST_DEBUG("MaxWidth = %d", quality_level->max_height);
281   if (SS_STREAM_VIDEO == stream->type && (quality_level->max_height == -1)) {
282     GST_ERROR ("max_height attribute is not present in VIDEO...");
283     return FALSE;
284   }
285
286   /* MANDATORY for audio: parsing SamplingRate attribute */
287   quality_level->samplingrate = ssm_parse_get_xml_prop_uint (parser, quality_node, "SamplingRate", -1);
288   GST_DEBUG("SamplingRate = %d", quality_level->samplingrate);
289   if (SS_STREAM_AUDIO == stream->type && (quality_level->samplingrate == -1)) {
290     GST_ERROR ("SamplingRate attribute is not present for AUDIO...");
291     return FALSE;
292   }
293
294   /* MANDATORY for audio: parsing Channels attribute */
295   quality_level->channels = ssm_parse_get_xml_prop_uint (parser, quality_node, "Channels", -1);
296   GST_DEBUG("SamplingRate = %d", quality_level->channels);
297   if (SS_STREAM_AUDIO == stream->type && (quality_level->channels == -1)) {
298     GST_ERROR ("Channels attribute is not present for AUDIO...");
299     return FALSE;
300   }
301
302   /* MANDATORY for audio: parsing BitsPerSample attribute */
303   quality_level->bps = ssm_parse_get_xml_prop_uint (parser, quality_node, "BitsPerSample", -1);
304   GST_DEBUG("BitsPerSample = %d", quality_level->bps);
305   if (SS_STREAM_AUDIO == stream->type && (quality_level->bps == -1)) {
306     GST_ERROR ("BitsPerSample attribute is not present for AUDIO...");
307     return FALSE;
308   }
309
310   /* MANDATORY for audio: parsing PacketSize attribute */
311   quality_level->packet_size = ssm_parse_get_xml_prop_uint (parser, quality_node, "PacketSize", -1);
312   GST_DEBUG("PacketSize = %d", quality_level->packet_size);
313   if (SS_STREAM_AUDIO == stream->type && (quality_level->packet_size == -1)) {
314     GST_ERROR ("PacketSize attribute is not present for AUDIO...");
315     return FALSE;
316   }
317
318
319   /* MANDATORY for audio: parsing AudioTag attribute */
320   quality_level->audio_tag = ssm_parse_get_xml_prop_uint (parser, quality_node, "AudioTag", -1);
321   GST_DEBUG("AudioTag = %d", quality_level->audio_tag);
322   if (SS_STREAM_AUDIO == stream->type && (quality_level->audio_tag == -1)) {
323     GST_ERROR ("AudioTag attribute is not present for AUDIO...");
324     return FALSE;
325   }
326
327   /* MANDATORY for audio & video: parsing FourCC attribute */
328   quality_level->fourcc = (gchar *)xmlGetProp(quality_node, (const xmlChar *) "FourCC");
329   if (!quality_level->fourcc && ((SS_STREAM_AUDIO == stream->type) || (SS_STREAM_VIDEO == stream->type))) {
330     GST_ERROR ("failed to parse fourcc from quality node");
331     return FALSE;
332   }
333
334   if (!((!strncmp ((char *)quality_level->fourcc, "AACL", 4)) || !strncmp ((char *)quality_level->fourcc, "WMAP", 4) ||
335   (!strncmp ((char *)quality_level->fourcc, "H264", 4)) || !strncmp ((char *)quality_level->fourcc, "WVC1", 4) ||
336   (!strncmp ((char *)quality_level->fourcc, "TTML", 4)))) {
337     GST_INFO ("Not a proper Fourcc Code...If possible take from SubType\n\n\n");
338     if (quality_level->fourcc) {
339       free (quality_level->fourcc);
340       quality_level->fourcc = NULL;
341     }
342     GST_DEBUG ("Subtype = %s\n\n",stream->StreamSubType);
343     quality_level->fourcc = g_strdup (stream->StreamSubType);
344     if (!((!strncmp ((char *)quality_level->fourcc, "AACL", 4)) || !strncmp ((char *)quality_level->fourcc, "WMAP", 4) ||
345     (!strncmp ((char *)quality_level->fourcc, "H264", 4)) || !strncmp ((char *)quality_level->fourcc, "WVC1", 4))) {
346       GST_ERROR ("Subtype also does not contain valid fourcc code...ERROR\n");
347       return FALSE;
348     }
349   }
350
351   GST_DEBUG("FourCC = %s", quality_level->fourcc);
352
353   // TODO: need to check whether it is required for all video & audio
354
355   /* MANDATORY for audio & video: parsing CodecPrivateData attribute */
356   quality_level->codec_data = (gchar *)xmlGetProp(quality_node, (const xmlChar *) "CodecPrivateData");
357   if (!quality_level->codec_data && ((SS_STREAM_AUDIO == stream->type) || (SS_STREAM_VIDEO == stream->type))) {
358     GST_ERROR ("failed to get codec data from quality node");
359     return FALSE;
360   }
361
362   /* Optional for VIDEO H264: parsing NALUnitLengthField attribute */
363   quality_level->NALULengthofLength = ssm_parse_get_xml_prop_uint (parser, quality_node, "NALUnitLengthField", 4);
364   GST_DEBUG("NALUnitLengthField = %d", quality_level->NALULengthofLength);
365
366   stream->quality_lists = g_list_append (stream->quality_lists, quality_level);
367
368   GST_LOG ("Appened quality level to stream...");
369
370   return TRUE;
371
372 }
373
374 static gboolean
375 ssm_parse_fragment_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr fragment_node)
376 {
377   GstSSMFragmentNode *fragment = NULL;
378   gboolean found_time = FALSE;
379   gboolean found_duration = FALSE;
380
381   g_return_val_if_fail (parser != NULL, FALSE);
382   g_return_val_if_fail (fragment_node != NULL, FALSE);
383   g_return_val_if_fail (stream != NULL, FALSE);
384
385   fragment = g_slice_new0 (GstSSMFragmentNode);
386   if (fragment == NULL) {
387     GST_ERROR ("Allocation of fragment failed!");
388     return FALSE;
389   }
390
391   /*parsing fragmentnumber attribute */
392   fragment->num = ssm_parse_get_xml_prop_uint (parser, fragment_node, "n", -1);
393   GST_DEBUG ("fragment number = %d", fragment->num);
394
395   /*parsing duration attribute */
396   fragment->dur = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "d", -1);
397   if (fragment->dur == -1 && !fragment_node->next) {
398     GST_ERROR ("Fragment Duration for last fragment is mandatory");
399     return FALSE;
400   } else if (fragment->dur != -1) {
401     GST_DEBUG ("Fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (fragment->dur));
402     found_duration = TRUE;
403   }
404
405   /*parsing time attribute */
406   fragment->time = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "t", -1);
407   if (fragment->time != -1) {
408     GST_DEBUG ("Fragment time = %"GST_TIME_FORMAT, GST_TIME_ARGS(fragment->time));
409     found_time = TRUE;
410   }
411
412   if (!found_time && !found_duration) {
413     GST_ERROR ("Both time & duration attributes are NOT present.. ERROR");
414     return FALSE;
415   } else if (!found_time && found_duration) {
416     GList *prev_fragment_list = NULL;
417     GstSSMFragmentNode *prev_fragment = NULL;
418
419     GST_DEBUG ("Only Duration attribute is present...");
420     if (stream->fragment_lists) {
421     prev_fragment_list = g_list_last(stream->fragment_lists);
422     if (NULL == prev_fragment_list) {
423       GST_ERROR ("Error last fragment lists are not present..\n");
424       return FALSE;
425     }
426     prev_fragment = (GstSSMFragmentNode *)prev_fragment_list->data;
427     fragment->time = prev_fragment->time +  prev_fragment->dur;
428     GST_DEBUG ("Fragment time = %llu", fragment->time);
429     } else {
430       GST_INFO ("Frament list is empty, assuming it as first fragment...");
431       fragment->time = 0;
432     }
433   } else if (found_time && !found_duration) {
434     xmlNodePtr next_fragment_node = NULL;
435     guint64 next_ts = 0;
436
437     GST_DEBUG ("Only time attribute is present...");
438
439     next_fragment_node = fragment_node->next;
440     if (next_fragment_node) {
441       next_ts = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "t", -1);
442       if (next_ts == -1) {
443         GST_ERROR ("Next fragment time not present to calculate duration of present fragment...");
444         return FALSE;
445       } else {
446         fragment->dur = next_ts - fragment->time;
447         GST_DEBUG ("Current fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(fragment->dur));
448       }
449     } else {
450       GST_ERROR ("Next fragment not present to calculate duration of present fragment...");
451       return FALSE;
452     }
453   }
454
455 #if 1
456   /*error check for timestamps as specified in spec */
457   {
458     xmlNodePtr next_fragment_node = NULL;
459     unsigned long long next_ts = 0;
460
461     next_fragment_node = fragment_node->next;
462     if (next_fragment_node) {
463       next_ts = ssm_parse_get_xml_prop_uint64 (parser, fragment_node, "t", -1);
464       if (next_ts != -1) {
465         GST_DEBUG ("Next Fragment time = %llu and Current fragment time = %llu\n", next_ts,  fragment->time);
466
467         if ( next_ts < fragment->time) {
468           GST_ERROR ("Error in timestamp sequence...");
469           return FALSE;
470         }
471       }
472     }
473   }
474 #endif
475
476   stream->stream_duration += fragment->dur;
477
478   stream->fragment_lists = g_list_append (stream->fragment_lists, fragment);
479   GST_DEBUG ("Added fragment node to list...");
480   // TODO: Need to invetigate on TrackFragmentIndex Attribute
481
482   return TRUE;
483 }
484
485 static gboolean
486 ssm_parse_stream_index_node (GstSSMParse *parser, xmlNodePtr stream_node)
487 {
488   GstSSMStreamNode *stream = NULL;
489   xmlNodePtr stream_children = NULL;
490
491   g_return_val_if_fail (parser != NULL, FALSE);
492   g_return_val_if_fail (stream_node != NULL, FALSE);
493
494   stream = g_slice_new0 (GstSSMStreamNode);
495   if (stream == NULL) {
496     GST_WARNING ("Allocation of stream node failed!");
497     return FALSE;
498   }
499
500   stream->frag_lock = g_mutex_new ();
501   stream->frag_cond = g_cond_new ();
502
503   /* Type, Chunks, QualityLevels are MUST attributes */
504   stream->StreamType = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Type");
505   if (NULL == stream->StreamType) {
506     GST_ERROR ("Type attribute is not present");
507     return FALSE;
508   }
509   GST_DEBUG ("Type = %s", stream->StreamType);
510
511   if (!strncmp ((char *)stream->StreamType, "video", 5))
512     stream->type = SS_STREAM_VIDEO;
513   else if (!strncmp ((char *)stream->StreamType, "audio", 5))
514     stream->type = SS_STREAM_AUDIO;
515   else if (!strncmp ((char *)stream->StreamType, "text", 4))
516     stream->type = SS_STREAM_TEXT;
517   else {
518     GST_ERROR ("UnKnown Stream type...");
519     return FALSE;
520   }
521
522   /* Optional SubType Attribute */
523   stream->StreamSubType = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Subtype");
524   if (stream->StreamSubType)
525     GST_DEBUG ("StreamSubType = %s", stream->StreamSubType);
526
527   stream->StreamTimeScale = ssm_parse_get_xml_prop_uint64 (parser, stream_node, "TimeScale", parser->RootNode->TimeScale);
528   GST_LOG("StreamTimeScale = %"G_GUINT64_FORMAT, stream->StreamTimeScale);
529
530   /* Optional StreamName Attribute */
531   stream->StreamName = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Name");
532   if (stream->StreamName)
533     GST_DEBUG ("StreamName = %s", stream->StreamName);
534
535   // TODO: need to understand more on this chunks whether mandatory or not in LIVE case
536   stream->nChunks = ssm_parse_get_xml_prop_uint (parser, stream_node, "Chunks", 0);
537   if (!stream->nChunks && !parser->RootNode->PresentationIsLive) {
538     GST_ERROR ("nChunks is zero in VOD case...ERROR");
539     return FALSE;
540   }
541   GST_DEBUG("nChunks = %d", stream->nChunks);
542
543   stream->nQualityLevels = ssm_parse_get_xml_prop_uint (parser, stream_node, "QualityLevels", 0);
544   GST_DEBUG("nQualityLevels = %d", stream->nQualityLevels);
545
546   stream->StreamUrl = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Url");
547   if (NULL == stream->StreamUrl) {
548     GST_ERROR ("Url Pattern attribute is not present");
549     return FALSE;
550   }
551   GST_DEBUG ("Url = %s", stream->StreamUrl);
552
553   if (stream->type == SS_STREAM_VIDEO) {
554     /* Video stream specific attributes */
555     stream->MaxWidth = ssm_parse_get_xml_prop_uint (parser, stream_node, "MaxWidth", 0);
556     GST_DEBUG("MaxWidth = %d", stream->MaxWidth);
557
558     stream->MaxHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "MaxHeight", 0);
559     GST_DEBUG("MaxHeight = %d", stream->MaxHeight);
560
561     stream->DisplayWidth = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayWidth", 0);
562     GST_DEBUG("DisplayWidth = %d", stream->DisplayWidth);
563
564     stream->DisplayHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayHeight", 0);
565     GST_DEBUG("DisplayHeight = %d", stream->DisplayHeight);
566   }
567
568   /* get the children nodes */
569   stream_children = stream_node->xmlChildrenNode;
570   if (NULL == stream_children) {
571     GST_ERROR ("No Children for StreamIndex Node...\n");
572     return FALSE;
573   }
574
575   /* Parse StreamIndex Children Nodes i.e. QualityLevel */
576   while (stream_children) {
577     if ( xmlIsBlankNode (stream_children)) {/* skip blank nodes */
578       stream_children = stream_children->next;
579       continue;
580     }
581     if (!xmlStrcmp(stream_children->name, (const xmlChar *) "QualityLevel")) {
582       if (!ssm_parse_quality_node (parser, stream, stream_children)) {
583         GST_ERROR ("failed to parse quality node");
584         return FALSE;
585       }
586     } else if (!xmlStrcmp(stream_children->name, (const xmlChar *) "c")) {
587       if (!ssm_parse_fragment_node (parser, stream, stream_children)) {
588         GST_ERROR ("failed to parse fragment node");
589         return FALSE;
590       }
591     } else {
592       GST_WARNING (" ==== >>>>>> Unknow ChildrenNode in StreamNode : %s", stream_children->name);
593     }
594     stream_children = stream_children->next;
595   }
596
597   /* sort the quality lists */
598   if (stream->quality_lists && (g_list_length(stream->quality_lists) > 1)) {
599     stream->quality_lists =  g_list_sort (stream->quality_lists,  (GCompareFunc) ssm_parser_sort_qualitylevels_by_bitrate);
600   }
601
602   parser->RootNode->streams[stream->type] = g_list_append (parser->RootNode->streams[stream->type], stream);
603
604   return TRUE;
605
606 }
607
608
609 static gboolean
610 ssm_parse_protection_node (GstSSMParse *parser, xmlNodePtr protection_node)
611 {
612   xmlChar *xml_string = NULL;
613
614   g_return_val_if_fail (parser != NULL, FALSE);
615   g_return_val_if_fail (protection_node != NULL, FALSE);
616
617   parser->RootNode->ProtectNode = g_slice_new0 (GstSSMFragmentNode);
618   if (NULL == parser->RootNode->ProtectNode) {
619     GST_ERROR ("Failed to allocate memory...\n");
620     return FALSE;
621   }
622
623   parser->RootNode->ProtectNode->SystemID = NULL;
624   parser->RootNode->ProtectNode->Content = NULL;
625   parser->RootNode->ProtectNode->ContentSize = 0;
626
627   if (!xmlStrcmp(protection_node->name, (const xmlChar *) "ProtectionHeader")) {
628     parser->RootNode->ProtectNode->SystemID = (unsigned char *) xmlGetProp(protection_node, (const xmlChar *) "SystemID");
629     if (NULL == parser->RootNode->ProtectNode->SystemID) {
630       GST_ERROR ("System ID is not present... need to decide ERROR or NOT... returning ERROR now\n");
631       return FALSE;
632     }
633
634     GST_DEBUG ("system ID = %s\n", parser->RootNode->ProtectNode->SystemID);
635
636     if (!strncasecmp ((char *)parser->RootNode->ProtectNode->SystemID,
637            "9A04F079-9840-4286-AB92-E65BE0885F95",
638            36)) {
639       g_print ("======== >>>>>>>. Content is encrypted using PLAYREADY\n");
640     } else {
641       GST_ERROR ("\n\n ******** UN-supported encrypted content... *********\n\n");
642       return FALSE;
643     }
644
645     xml_string = xmlNodeGetContent(protection_node);
646     if (NULL == xml_string) {
647       GST_ERROR ("Content is not present... need to decide ERROR or NOT\n");
648       return FALSE;
649     } else {
650       gsize content_size = 0;
651
652       g_print ("Content = %s\n", xml_string);
653
654       parser->RootNode->ProtectNode->Content = g_base64_decode ((gchar*)xml_string, &content_size);
655       if (NULL == parser->RootNode->ProtectNode->Content) {
656         GST_ERROR ("Failed to do base64 decoding...\n");
657         free (xml_string);
658         xml_string = NULL;
659         return FALSE;
660       }
661
662       parser->RootNode->ProtectNode->ContentSize = content_size;
663       free (xml_string);
664       xml_string = NULL;
665
666       GST_DEBUG ("ProtectionNode content = %s and size = %d\n", parser->RootNode->ProtectNode->Content, content_size);
667     }
668   } else {
669     GST_ERROR ("ProtectionHeader is NOT PRESENT in Protection node...ERROR\n");
670     return FALSE;
671   }
672
673   GST_LOG ("successfully parsed protectionheader node...");
674   return TRUE;
675 }
676
677 static gboolean
678 ssm_parse_root_node (GstSSMParse *parser, xmlNodePtr root_node)
679 {
680   int i = 0;
681
682   g_return_val_if_fail (parser != NULL, FALSE);
683   g_return_val_if_fail (root_node != NULL, FALSE);
684
685   parser->RootNode = g_slice_new0 (GstSSMRootNode);
686   if (parser->RootNode == NULL) {
687     GST_WARNING ("Allocation of root node failed!");
688     return FALSE;
689   }
690
691   for (i = 0; i < SS_STREAM_NUM; i++) {
692     parser->RootNode->streams[i] = NULL;
693   }
694
695   parser->RootNode->ProtectNode = NULL;
696
697   /* MANDATORY : parsing MajorVersion attribute */
698   parser->RootNode->MajorVersion = ssm_parse_get_xml_prop_uint (parser, root_node, "MajorVersion", -1);
699   if (parser->RootNode->MajorVersion != 2) {
700     GST_ERROR("Majorversion should be 2");
701     return FALSE;
702   }
703   GST_LOG("SmoothStreamingMedia :: Majorversion = %d", parser->RootNode->MajorVersion);
704
705   /* MANDATORY : parsing MinorVersion attribute */
706   parser->RootNode->MinorVersion = ssm_parse_get_xml_prop_uint (parser, root_node, "MinorVersion", 0);
707   GST_LOG("SmoothStreamingMedia :: MinorVersion = %d", parser->RootNode->MinorVersion);
708
709   parser->RootNode->TimeScale = ssm_parse_get_xml_prop_uint64 (parser, root_node, "TimeScale", 10000000);
710   GST_LOG("SmoothStreamingMedia :: TimeScale = %"G_GUINT64_FORMAT, parser->RootNode->TimeScale);
711
712   parser->RootNode->Duration = ssm_parse_get_xml_prop_uint64 (parser, root_node, "Duration", -1);
713   GST_LOG("SmoothStreamingMedia :: Duration = %"G_GUINT64_FORMAT, parser->RootNode->Duration);
714
715   parser->RootNode->PresentationIsLive = ssm_parse_get_xml_prop_boolean (parser, root_node, "IsLive");
716   GST_LOG("SmoothStreamingMedia :: IsLive = %d", parser->RootNode->PresentationIsLive);
717
718   /* valid for live presentation only*/
719   if (parser->RootNode->PresentationIsLive) {
720
721     parser->RootNode->LookAheadCount = ssm_parse_get_xml_prop_uint (parser, root_node, "LookaheadCount", -1);
722     GST_LOG("SmoothStreamingMedia :: LookaheadCount = %d", parser->RootNode->LookAheadCount);
723
724     if (parser->RootNode->LookAheadCount == -1) {
725      GST_INFO ("fallback case of lookaheadcount...");
726      parser->RootNode->LookAheadCount = ssm_parse_get_xml_prop_uint (parser, root_node, "LookAheadFragmentCount", -1);
727      GST_LOG("SmoothStreamingMedia :: LookAheadFragmentCount = %d", parser->RootNode->LookAheadCount);
728     }
729
730     parser->RootNode->DVRWindowLength = ssm_parse_get_xml_prop_uint64 (parser, root_node, "DVRWindowLength", 0);
731     GST_LOG("SmoothStreamingMedia :: DVRWindowLength = %"G_GUINT64_FORMAT, parser->RootNode->DVRWindowLength);
732     if (parser->RootNode->DVRWindowLength == 0)
733       GST_INFO ("DVR Window Length is zero...means INFINITE");
734   }
735
736   return TRUE;
737 }
738
739
740 gboolean
741 gst_ssm_parse_manifest (GstSSMParse *parser, char *data, unsigned int size)
742 {
743   xmlNodePtr root = NULL;
744   xmlNodePtr curnode = NULL;
745   xmlDocPtr doc;
746   int i;
747
748   g_return_val_if_fail (parser != NULL, FALSE);
749   g_return_val_if_fail (data != NULL, FALSE);
750   g_return_val_if_fail (size != 0, FALSE);
751
752   /* parse manifest xml file */
753   doc = xmlReadMemory ((gchar *) data, size, NULL, NULL, 0);
754   if (doc == NULL ) {
755     GST_ERROR("failed to parse manifest file...");
756     goto error;
757   }
758
759   /* Get the root element */
760   root = xmlDocGetRootElement(doc);
761   if (root == NULL) {
762     GST_ERROR("no ROOT node in manifest file...");
763     goto error;
764   }
765
766   if (!xmlStrcmp(root->name, (const xmlChar *) "SmoothStreamingMedia"))  {
767     /* parsing of ROOT Node SmoothStreamingMedia attributes */
768     if (!ssm_parse_root_node (parser, root)) {
769       GST_ERROR("failed to parse root node...");
770       goto error;
771     }
772     GST_DEBUG ("Parsing ROOT element is successful");
773   } else {
774     GST_ERROR ("SmoothStreamingMedia ROOT element is not present...");
775     goto error;
776   }
777
778   /* moving to children nodes */
779   curnode = root->xmlChildrenNode;
780
781   while (curnode) {
782     if (xmlIsBlankNode (curnode)) {/* skip blank node */
783       curnode = curnode->next;
784       continue;
785     }
786
787     if (!xmlStrcmp(curnode->name, (const xmlChar *)"StreamIndex")) {
788       /* Parsing Stream Node */
789       if (!ssm_parse_stream_index_node (parser, curnode)) {
790         GST_ERROR ("failed to parse stream index node...");
791         return FALSE;
792       }
793     } else if (!xmlStrcmp(curnode->name, (const xmlChar *) "Protection")) {
794       xmlNodePtr protect_node;
795
796       /* get the children */
797       protect_node = curnode->xmlChildrenNode;
798       if (NULL == protect_node) {
799         GST_ERROR ("No Children for Protection Node...\n");
800         return FALSE;
801       } else {
802         if (!ssm_parse_protection_node (parser, protect_node)) {
803           GST_ERROR ("failed to parse protectionheader node");
804           return FALSE;
805         }
806       }
807     }
808     curnode = curnode->next;
809   }
810
811   /* Move to last fragment when presentation is LIVE */
812   if (parser->RootNode->PresentationIsLive) {
813     for (i = 0; i < SS_STREAM_NUM; i++) {
814       if (parser->RootNode->streams[i]) {
815         GST_INFO ("Live presentation, so moved to last node...");
816         ((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists =
817                         g_list_last (((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists);
818       }
819     }
820   }
821
822   parser->ns_start = 0;
823
824   /* get new segment start */
825   for (i = 0; i < SS_STREAM_NUM; i++) {
826     GstSSMStreamNode *stream = NULL;
827     GList *frag_list = NULL;
828     guint64 start_ts = GST_CLOCK_TIME_NONE;
829
830     if (parser->RootNode->streams[i]) {
831       /* Move to last fragment when presentation is LIVE */
832       if (parser->RootNode->PresentationIsLive) {
833         GST_INFO ("Live presentation, so moved to last node...");
834         ((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists =
835             g_list_last (((GstSSMStreamNode *)(parser->RootNode->streams[i]->data))->fragment_lists);
836       }
837
838       stream = (parser->RootNode->streams[i])->data;
839       frag_list = stream->fragment_lists;
840       start_ts = ((GstSSMFragmentNode *)frag_list->data)->time;
841
842       GST_LOG ("ns_start = %"G_GUINT64_FORMAT" and start_ts[%s] = %"G_GUINT64_FORMAT,
843           parser->ns_start, ssm_parse_get_stream_name(i), start_ts);
844
845       /* take MAX of stream's start as new_segment start */
846       parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
847     }
848   }
849
850   GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
851
852   if (doc) {
853     xmlFreeDoc(doc);
854     doc = NULL;
855   }
856
857   GST_DEBUG ("successfully parsed manifest");
858
859   return TRUE;
860
861 error:
862   if (doc) {
863     xmlFreeDoc(doc);
864     doc = NULL;
865   }
866
867   return FALSE;
868 }
869
870 /* Only supporting url in 'QualityLevels({bitrate})/Fragments(xxxxxx={start time})'
871   * FIXME : Add support for any */
872 gboolean
873 gst_ssm_parse_get_next_fragment_url (GstSSMParse *parser, SS_STREAM_TYPE stream_type, gchar **uri, guint64 *start_ts)
874 {
875   GstSSMStreamNode *stream = NULL;
876   GList *frag_list = NULL;
877   GPtrArray *strs;
878   guint64 time = 0;
879   gchar **splitter1 = NULL;
880   gchar **splitter2 = NULL;
881   gchar **splitter3 = NULL;
882
883   MANIFEST_LOCK(parser);
884   stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
885   g_mutex_lock (stream->frag_lock);
886
887   if (stream->fraglist_eos) {
888     if (parser->RootNode->PresentationIsLive) {
889       /* Live Presentation need to wait for next uri */
890       g_print ("waiting for next URI in LIVE presentation...\n");
891       g_cond_wait (stream->frag_cond, stream->frag_lock);
892       g_print ("Received signal after appending new URI...move to next now\n");
893      ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists =
894          g_list_next (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists);
895     } else {
896       /* VOD presentation reached EOS */
897       GST_INFO("Fragment list is empty in VOD case...");
898       g_mutex_unlock (stream->frag_lock);
899       MANIFEST_UNLOCK(parser);
900       return FALSE;
901     }
902   }
903
904   stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
905
906   frag_list = stream->fragment_lists;
907
908   strs = g_ptr_array_new ();
909
910   /* adding presentation uri */
911   g_ptr_array_add (strs, g_strdup(parser->presentation_uri));
912
913   splitter1 = g_strsplit (stream->StreamUrl, "{", 3);
914
915   /* add stream url till first '{' */
916   g_ptr_array_add (strs, g_strdup(splitter1[0]));
917
918   /* adding bitrate param */
919   g_ptr_array_add (strs, g_strdup_printf ("%d", ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate));
920
921   /* tokenize based on '}' */
922   splitter2 = g_strsplit (splitter1[1], "}", 2);
923
924   g_ptr_array_add (strs, g_strdup(splitter2[1]));
925
926   time = ((GstSSMFragmentNode *)frag_list->data)->time;
927
928   /* adding fragment time */
929   g_ptr_array_add (strs, g_strdup_printf ("%llu", time));
930
931   *start_ts = gst_util_uint64_scale (time, GST_SECOND, parser->RootNode->TimeScale);
932
933   /* tokenize based on '}' */
934   splitter3 = g_strsplit (splitter1[2], "}", 2);
935
936   g_ptr_array_add (strs, g_strdup(splitter3[1]));
937
938   /* add a terminating NULL */
939   g_ptr_array_add (strs, NULL);
940
941   if (frag_list = g_list_next (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists)) {
942     ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists = frag_list;
943   } else {
944     GST_INFO ("Reached end of fragment list...\n");
945     ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fraglist_eos = TRUE;
946   }
947
948   *uri = g_strjoinv (NULL, (gchar **) strs->pdata);
949   g_strfreev ((gchar **) g_ptr_array_free (strs, FALSE));
950
951   g_mutex_unlock (stream->frag_lock);
952
953   MANIFEST_UNLOCK(parser);
954
955   return TRUE;
956 }
957
958 GstCaps *
959 ssm_parse_get_stream_caps (GstSSMParse *parser, SS_STREAM_TYPE stream_type)
960 {
961   GstSSMStreamNode *stream = NULL;
962   MANIFEST_LOCK(parser);
963
964   stream = parser->RootNode->streams[stream_type]->data;
965   GstCaps *caps = NULL;
966   if (stream_type == SS_STREAM_VIDEO) {
967     caps =  ssm_prepare_video_caps (parser, stream);
968   } else if (stream_type == SS_STREAM_AUDIO) {
969     caps =  ssm_prepare_audio_caps (parser, stream);
970   } else if (stream_type == SS_STREAM_TEXT) {
971     caps =  ssm_prepare_text_caps (parser, stream);
972   }
973   MANIFEST_UNLOCK(parser);
974   return caps;
975 }
976
977 GstCaps *
978 ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
979 {
980   GstSSMQualityNode *cur_quality_node =  (GstSSMQualityNode *)(stream->quality_lists->data);
981   GstBuffer *codec_data = NULL;
982   GstCaps *caps = NULL;
983
984   codec_data = gst_buffer_new ();
985   if (!codec_data) {
986     GST_ERROR ("failed to allocate buffer");
987     return NULL;
988   }
989
990   if (!strncmp ((char *)cur_quality_node->fourcc, "H264", 4)) {
991     /* converting NALU codec data to 3GPP codec data format */
992     if (!convert_NALUnitDCI_to_PacktizedDCI (cur_quality_node->codec_data, &(GST_BUFFER_DATA(codec_data)), &GST_BUFFER_SIZE(codec_data))) {
993       GST_ERROR ("Error in converting NALUDCI to Packetized DCI...\n");
994       return NULL;
995     }
996     GST_BUFFER_MALLOCDATA(codec_data) = GST_BUFFER_DATA(codec_data);
997   } else if (!strncmp ((char *)cur_quality_node->fourcc, "WVC1", 4)) {
998     unsigned char *codec_data = cur_quality_node->codec_data;
999     unsigned int DCI_len = strlen ((char *)cur_quality_node->codec_data);
1000     gchar tmp[3] = {0, };
1001     gint val = 0;
1002     gint codec_data_len = 0;
1003     gint idx = 0;
1004
1005     codec_data_len = (DCI_len >>1);
1006
1007     codec_data = gst_buffer_new_and_alloc (codec_data_len);
1008     if (!codec_data) {
1009       GST_ERROR ("Failed to allocate memory..\n");
1010       return FALSE;
1011     }
1012
1013     /* copy codec data */
1014     while (DCI_len) {
1015       memset (tmp, 0x00, 3);
1016       strncpy ((char*)tmp, (char*)codec_data, 2);
1017       tmp[2] = '\0';
1018       if (!int_from_string ((char*)tmp, NULL, &val, 16)) {
1019         GST_ERROR ("Failed to int from string...");
1020         return NULL;
1021       }
1022       (GST_BUFFER_DATA(codec_data))[idx] = val;
1023       codec_data += 2;
1024       DCI_len = DCI_len - 2;
1025       idx++;
1026     }
1027   }
1028
1029   if (!strncmp ((char *)cur_quality_node->fourcc, "H264", 4)) {
1030     /* prepare H264 caps */
1031     caps = gst_caps_new_simple ("video/x-h264",
1032                   "width", G_TYPE_INT, cur_quality_node->max_width,
1033                   "height", G_TYPE_INT, cur_quality_node->max_height,
1034                   "framerate", GST_TYPE_FRACTION, 30, 1,
1035                   "stream-format", G_TYPE_STRING, "avc",
1036                   "alignment", G_TYPE_STRING, "au",
1037                   "codec_data", GST_TYPE_BUFFER, codec_data,
1038                   NULL);
1039   } else if (!strncmp ((char *)cur_quality_node->fourcc, "WVC1", 4)) {
1040     /* prepare VC1 caps */
1041     caps = gst_caps_new_simple ("video/x-wmv",
1042                   "width", G_TYPE_INT, cur_quality_node->max_width,
1043                     "height", G_TYPE_INT, cur_quality_node->max_height,
1044                     "framerate", GST_TYPE_FRACTION, 30, 1,
1045                     "wmvversion", G_TYPE_INT, 3,
1046                     "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
1047                     "codec_data", GST_TYPE_BUFFER, codec_data,
1048                     NULL);
1049   } else {
1050     char *s;
1051     /* prepare gst generic caps caps */
1052     GST_ERROR ("Wrong VIDEO fourcc...");
1053     s = g_strdup_printf ("video/x-gst-fourcc-%s", "unknown");
1054     caps = gst_caps_new_simple (s,
1055                      "width", G_TYPE_INT, cur_quality_node->max_width,
1056                      "height", G_TYPE_INT, cur_quality_node->max_height,
1057                      "framerate", GST_TYPE_FRACTION, 30, 1,
1058                       "codec_data", GST_TYPE_BUFFER, codec_data,
1059                      NULL);
1060   }
1061
1062   GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
1063
1064    return caps;
1065 }
1066
1067 GstCaps *
1068 ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1069 {
1070   GstSSMQualityNode *cur_quality_node =  (GstSSMQualityNode *)(stream->quality_lists->data);
1071   GstBuffer *codec_data = NULL;
1072   GstCaps *caps = NULL;
1073
1074   if ((!strncmp ((char *)cur_quality_node->fourcc, "AACL", 4)) || !strncmp ((char *)cur_quality_node->fourcc, "WMAP", 4)) {
1075     guint DCI_len = strlen ((char *)cur_quality_node->codec_data);
1076     gchar tmp[3] = {0, };
1077     gint val = 0;
1078     gint codec_data_len = (DCI_len >>1);
1079     gint idx = 0;
1080
1081     codec_data = gst_buffer_new_and_alloc (codec_data_len);
1082     if (NULL == codec_data) {
1083       GST_ERROR ("Failed to allocate memory..\n");
1084       return NULL;
1085     }
1086
1087     /* copy codec data */
1088     while (DCI_len) {
1089       memset (tmp, 0x00, 3);
1090       strncpy ((char*)tmp, (char*)cur_quality_node->codec_data, 2);
1091       tmp[2] = '\0';
1092       if (!int_from_string ((char*)tmp, NULL, &val , 16)) {
1093         GST_ERROR ("Failed to int from string...");
1094         return NULL;
1095       }
1096       (GST_BUFFER_DATA(codec_data))[idx] = val;
1097       cur_quality_node->codec_data += 2;
1098       DCI_len = DCI_len - 2;
1099       //g_print ("val = 0x%02x, codec_data_length = %d, idx = %d\n", val, DCI_len, idx);
1100       idx++;
1101     }
1102   } else {
1103     GST_ERROR ("\n\n\nUnsupported Audio Codec Fourcc...\n\n\n");
1104     return NULL;
1105   }
1106
1107   if (!strncmp ((char *)cur_quality_node->fourcc, "AACL", 4)) {
1108     caps = gst_caps_new_simple ("audio/mpeg",
1109                           "mpegversion", G_TYPE_INT, 4,
1110                           "framed", G_TYPE_BOOLEAN, TRUE,
1111                           "stream-format", G_TYPE_STRING, "raw",
1112                           "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
1113                           "channels", G_TYPE_INT, cur_quality_node->channels,
1114                           NULL);
1115   } else if (!strncmp ((char *)cur_quality_node->fourcc, "WMAP", 4)) {
1116     caps = gst_caps_new_simple ("audio/x-wma",
1117                         "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
1118                          "channels", G_TYPE_INT, cur_quality_node->channels,
1119                         NULL);
1120   } else {
1121     char *s;
1122
1123     GST_ERROR ("Wrong Audio fourcc...");
1124     s = g_strdup_printf ("audio/x-gst-fourcc-%s", "unknown");
1125     caps = gst_caps_new_simple (s,
1126                             "rate", G_TYPE_INT, (int) cur_quality_node->samplingrate,
1127                              "channels", G_TYPE_INT, cur_quality_node->channels,
1128                              NULL);
1129   }
1130   GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
1131
1132   return caps;
1133 }
1134
1135 GstCaps *
1136 ssm_prepare_text_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1137 {
1138   // TODO: Yet to add support for text caps
1139   return NULL;
1140 }
1141
1142 SS_BW_MODE
1143 gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate)
1144 {
1145   GstSSMStreamNode *stream =  parser->RootNode->streams[SS_STREAM_VIDEO]->data;
1146   guint bitrate = ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate;
1147   SS_BW_MODE ret = SS_MODE_NO_SWITCH;
1148
1149   /* check for upward transition */
1150   while (drate > (bitrate + BITRATE_SWITCH_UPPER_THRESHOLD * bitrate)) {
1151     if (g_list_next (stream->quality_lists)) {
1152       stream->quality_lists = g_list_next (stream->quality_lists);
1153       g_print ("Move to next quality level : drate = %d and bitrate = %d\n", drate, ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate);
1154       ret = SS_MODE_AV;
1155     } else {
1156       g_print ("Already at MAX Bitrate possible...\n");
1157       ret = SS_MODE_NO_SWITCH;
1158       break;
1159     }
1160   }
1161
1162   /* check for downward transition */
1163   while (drate < (bitrate + BITRATE_SWITCH_LOWER_THRESHOLD * bitrate)) {
1164     if (g_list_previous (stream->quality_lists)) {
1165       stream->quality_lists = g_list_previous (stream->quality_lists);
1166       g_print ("Move to previous quality level : drate = %d and bitrate = %d\n", drate, ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate);
1167     } else {
1168       g_print ("Reached MIN video bitrate possible...\n");
1169       if (GST_SSM_PARSE_IS_LIVE_PRESENTATION(parser)) {
1170         g_print ("Going to audio-only because of LIVE...\n");
1171         ret = SS_MODE_AONLY;
1172       } else {
1173         ret = SS_MODE_AV;
1174       }
1175       break;
1176     }
1177   }
1178
1179   return ret;
1180 }
1181
1182 gboolean
1183 gst_ssm_parse_append_next_fragment (GstSSMParse *parser, SS_STREAM_TYPE stream_type, guint64 timestamp, guint64 duration)
1184 {
1185   GstSSMStreamNode *stream = NULL;
1186   GstSSMFragmentNode *new_fragment = NULL;
1187   GstSSMFragmentNode *last_fragment = NULL;
1188   GList *last_node = NULL;
1189
1190   g_return_val_if_fail (parser != NULL, FALSE);
1191
1192   /*get current stream based on stream_type */
1193   stream = (parser->RootNode->streams[stream_type])->data;
1194
1195   g_return_val_if_fail (stream->fragment_lists, FALSE);
1196
1197   g_mutex_lock (stream->frag_lock);
1198
1199   last_node = g_list_last(stream->fragment_lists);
1200
1201   last_fragment = (GstSSMFragmentNode *)(last_node->data);
1202
1203   if (last_fragment->time < timestamp) {
1204
1205     GST_LOG ("+++++ last_fragment time = %llu and current recd = %llu +++++\n", last_fragment->time, timestamp);
1206
1207     /* allocate new fragment node */
1208     new_fragment = g_slice_new0 (GstSSMFragmentNode);
1209     if (new_fragment == NULL) {
1210       GST_ERROR ("Allocation of fragment failed!");
1211       return FALSE;
1212     }
1213
1214     if (duration == GST_CLOCK_TIME_NONE) {
1215       /* useful when lookahead count is zero */
1216       // TODO: need to check how to handle, when there is discontinuity
1217       duration = timestamp - last_fragment->time;
1218     }
1219
1220     // TODO: need to handle when either time or duration present OR if both are non proper values
1221     new_fragment->dur = duration;
1222     new_fragment->time = timestamp;
1223     new_fragment->num = 0;
1224
1225     /* add the new fragment duration to total stream duration */
1226     stream->stream_duration += duration;
1227
1228     /* append new fragment list to stream fragment list */
1229    ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists =
1230          g_list_append (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists, new_fragment);
1231
1232     GST_DEBUG ("+++++ Appened new '%s' URL and signaling the condition and duration = %llu ++++++\n",
1233         ssm_parse_get_stream_name(stream_type), stream->stream_duration);
1234
1235     if (stream->fraglist_eos) {
1236       GST_INFO ("Need to move the list now to next.. as we received new one\n");
1237       ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists =
1238          g_list_next (((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fragment_lists);
1239       stream->fraglist_eos = FALSE;
1240     }
1241     /* signal fragment wait */
1242     g_cond_signal (stream->frag_cond);
1243
1244   } else {
1245     g_print ("--------- Received '%s' fragment is less than Last fragment in the list -----------\n", ssm_parse_get_stream_name(stream_type));
1246   }
1247
1248   g_mutex_unlock (stream->frag_lock);
1249
1250   return TRUE;
1251 }
1252
1253 gboolean
1254 gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time)
1255 {
1256   gint i = 0;
1257   GstSSMStreamNode *stream = NULL;
1258   guint64 stream_time = -1;
1259   guint64 start_ts = -1;
1260
1261   parser->ns_start = 0;
1262
1263   for (i = 0; i < SS_STREAM_NUM; i++) {
1264     if (parser->RootNode->streams[i]) {
1265       stream = parser->RootNode->streams[i]->data; // get current stream
1266       stream_time = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1267       stream_time = gst_util_uint64_scale (stream_time, GST_SECOND,
1268           GST_SSM_PARSE_GET_TIMESCALE(parser));
1269
1270       if (seek_time > stream_time) {
1271         /* forward seek */
1272         while (seek_time > stream_time) {
1273           stream->fragment_lists = g_list_next (stream->fragment_lists);
1274           stream_time = gst_util_uint64_scale (((GstSSMFragmentNode *)stream->fragment_lists->data)->time, GST_SECOND,
1275               GST_SSM_PARSE_GET_TIMESCALE(parser));
1276           GST_LOG ("seek time = %"GST_TIME_FORMAT", cur_time = %"GST_TIME_FORMAT,
1277               GST_TIME_ARGS(seek_time), GST_TIME_ARGS(stream_time));
1278         }
1279
1280         /* moving to fragment before our seeked time */
1281         stream->fragment_lists = g_list_previous (stream->fragment_lists);
1282         start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1283       } else if (seek_time < stream_time) {
1284         /* backward seek */
1285         while (seek_time < stream_time) {
1286           stream->fragment_lists = g_list_previous (stream->fragment_lists);
1287           stream_time = gst_util_uint64_scale (((GstSSMFragmentNode *)stream->fragment_lists->data)->time, GST_SECOND,
1288                                               GST_SSM_PARSE_GET_TIMESCALE(parser));
1289           GST_LOG ("seek time = %"GST_TIME_FORMAT", cur_time = %"GST_TIME_FORMAT,
1290           GST_TIME_ARGS(seek_time), GST_TIME_ARGS(stream_time));
1291         }
1292         start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1293       } else {
1294         /* rare case */
1295         start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1296       }
1297
1298       if (stream->type == SS_STREAM_VIDEO) {
1299         /* move to least possible bitrate variant*/
1300         stream->quality_lists = g_list_first (stream->quality_lists);
1301       }
1302
1303       GST_INFO ("SEEK : ns_start = %"G_GUINT64_FORMAT" and start_ts[%s] = %"G_GUINT64_FORMAT,
1304         parser->ns_start, ssm_parse_get_stream_name(i), start_ts);
1305
1306       /* take max of stream's start as new_segment start */
1307       parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
1308     }
1309   }
1310
1311   GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
1312
1313   return TRUE;
1314 }
1315
1316 static gboolean
1317 convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len)
1318 {
1319 #ifndef CHECK_NALU_OUT
1320         gboolean bret = TRUE;
1321         unsigned char *pps_start = NULL;
1322         unsigned char *pps_end = NULL;
1323         unsigned int sps_len = 0;
1324         unsigned int pps_len = 0;
1325         unsigned char *sps_data = NULL;
1326         unsigned char *pps_data = NULL;
1327         unsigned char *tmp_sps_ptr = NULL;
1328         unsigned char *tmp_pps_ptr = NULL;
1329         unsigned char tmp[3] = {0, };
1330         int val;
1331         unsigned int idx = 0;
1332
1333         // TODO: need to generalize this logic for finding multiple SPS and PPS sets and finding SPS/PPS by ANDing 0x1F
1334
1335         pps_start = strstr ((char*)nalu_dci, "0000000168");
1336         pps_end = nalu_dci + strlen ((char *)nalu_dci);
1337         GST_DEBUG ("nalu_dci length= %d\n", strlen ((char *)nalu_dci));
1338
1339         sps_len = pps_start - nalu_dci;
1340
1341        GST_DEBUG ("sps length = %d\n", sps_len);
1342
1343         sps_data = (unsigned char*) malloc (sps_len + 1);
1344         if (NULL == sps_data)
1345         {
1346                 GST_ERROR ("Failed to allocate memory..\n");
1347                 bret = FALSE;
1348                 goto exit;
1349         }
1350
1351         /* Copy SPS data */
1352         strncpy ((char*)sps_data, (char *)nalu_dci, sps_len);
1353         sps_data[sps_len] = '\0';
1354
1355         tmp_sps_ptr = sps_data;
1356
1357         GST_DEBUG ("SPS data = %s\n", sps_data);
1358
1359         pps_len = pps_end - pps_start;
1360         GST_DEBUG ("pps length = %d\n", pps_len);
1361
1362         pps_data = (unsigned char*)malloc (pps_len + 1);
1363         if (NULL == pps_data)
1364         {
1365                 GST_ERROR ("Failed to allocate memory..\n");
1366                 bret = FALSE;
1367                 goto exit;
1368         }
1369
1370         /* Copy PPS data */
1371         strncpy ((char*)pps_data, (char*)pps_start, pps_len);
1372         pps_data[pps_len] = '\0';
1373         tmp_pps_ptr = pps_data;
1374
1375         GST_DEBUG ("PPS data = %s\n", pps_data);
1376
1377         /* 6 bytes of metadata */
1378         *packetized_dci_len = 8;
1379
1380         *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
1381         if (NULL == *packetized_dci)
1382         {
1383                 GST_ERROR ("Failed to allocate memory..\n");
1384                 bret = FALSE;
1385                 goto exit;
1386         }
1387
1388         /* configurationVersion */
1389         (*packetized_dci)[0] = 0x01;
1390
1391         /* AVCProfileIndication */
1392         memset (tmp, 0x00, 3);
1393
1394         strncpy ((char*)tmp, (char*)sps_data+10, 2);
1395         tmp[2] = '\0';
1396
1397         bret = int_from_string ((char*)tmp, NULL, &val , 16);
1398         if (FALSE == bret)
1399         {
1400                 GST_ERROR ("Failed to int from string...");
1401                 goto exit;
1402         }
1403
1404         (*packetized_dci)[1] = val;
1405
1406         /* profile_compatibility*/
1407         memset (tmp, 0x00, 3);
1408         strncpy ((char*)tmp, (char*)sps_data+12, 2);
1409         tmp[2] = '\0';
1410         bret = int_from_string ((char*)tmp, NULL, &val , 16);
1411         if (FALSE == bret)
1412         {
1413                 GST_ERROR ("Failed to int from string...");
1414                 goto exit;
1415         }
1416         (*packetized_dci)[2] = val;
1417
1418         /* AVCLevelIndication */
1419         memset (tmp, 0x00, 3);
1420         strncpy ((char*)tmp, (char*)sps_data+14, 2);
1421         tmp[2] = '\0';
1422         bret = int_from_string ((char*)tmp, NULL, &val , 16);
1423         if (FALSE == bret)
1424         {
1425                 GST_ERROR ("Failed to int from string...");
1426                 goto exit;
1427         }
1428
1429         (*packetized_dci)[3] = val;
1430
1431         /* Reserver (6) + LengthSizeMinusOne (2) */
1432         (*packetized_dci)[4] = 0xff;     // hardcoding lengthoflength = 4 for present
1433
1434         /* Reserver (3) + numOfSequenceParameterSets (5) */
1435         (*packetized_dci)[5] = 0xe1;     // hardcoding numOfSequenceParameterSets = 1 for present
1436
1437         /* avoiding NALU start code 0x00 00 00 01 */
1438         sps_len = sps_len -8;
1439         sps_data = sps_data + 8;
1440
1441         (*packetized_dci)[6] = (sps_len >>1) >> 16;
1442         (*packetized_dci)[7] = (sps_len >>1);
1443
1444         *packetized_dci_len += (sps_len/2);
1445
1446         *packetized_dci = (unsigned char*) realloc (*packetized_dci, *packetized_dci_len);
1447         if (NULL == *packetized_dci)
1448         {
1449                 GST_ERROR ("Failed to allocate memory..\n");
1450                 bret = FALSE;
1451                 goto exit;
1452         }
1453
1454         idx = 8;
1455
1456         /* convert SPS data and store*/
1457         while (sps_len)
1458         {
1459                 memset (tmp, 0x00, 3);
1460                 strncpy ((char*)tmp, (char*)sps_data, 2);
1461                 tmp[2] = '\0';
1462                 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1463                 if (FALSE == bret)
1464                 {
1465                         GST_ERROR ("Failed to int from string...");
1466                         goto exit;
1467                 }
1468                 (*packetized_dci)[idx] = val;
1469                 sps_data += 2;
1470                 sps_len = sps_len - 2;
1471                 //g_print ("val = 0x%02x, sps_len = %d, idx = %d\n", val, sps_len, idx);
1472                 idx++;
1473         }
1474
1475         /* avoiding NALU start code 0x00 00 00 01 */
1476         pps_len = pps_len -8;
1477         pps_data = pps_data + 8;
1478
1479         /* no.of PPS sets (1 byte) + Lengthof PPS (2 bytes) + PPS length */
1480         *packetized_dci_len = *packetized_dci_len + 1 + 2 + (pps_len/2) ;
1481         *packetized_dci = (unsigned char*)realloc (*packetized_dci, *packetized_dci_len);
1482         if (NULL == *packetized_dci)
1483         {
1484                 GST_ERROR ("Failed to allocate memory..\n");
1485                 bret = FALSE;
1486                 goto exit;
1487         }
1488
1489         (*packetized_dci)[idx++] = 0x01; // Harding no.of PPS sets
1490         (*packetized_dci)[idx++] = (pps_len>>1) >> 16;
1491         (*packetized_dci)[idx++] = (pps_len >>1);
1492
1493         /* convert PPS data and store */
1494         while (pps_len)
1495         {
1496                 memset (tmp, 0x00, 3);
1497                 strncpy ((char*)tmp, (char*)pps_data, 2);
1498                 tmp[2] = '\0';
1499                 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1500                 if (FALSE == bret)
1501                 {
1502                         GST_ERROR ("Failed to int from string...");
1503                         goto exit;
1504                 }
1505
1506                 (*packetized_dci)[idx] = val;
1507                 pps_data += 2;
1508                 pps_len = pps_len - 2;
1509                 //g_print ("val = 0x%02x, pps_len = %d, idx = %d\n", val, pps_len, idx);
1510                 idx++;
1511         }
1512         idx = 0;
1513
1514 #if 0
1515         g_print ("\n\n");
1516
1517         g_print ("Complete VIDEO packetized_dci: 0x");
1518         while (idx < *packetized_dci_len)
1519         {
1520                 g_print ("%02x", (*packetized_dci)[idx]);
1521                 idx++;
1522         }
1523
1524         g_print ("\n\n");
1525 #endif
1526
1527 exit:
1528         if (tmp_sps_ptr)
1529         {
1530                 free (tmp_sps_ptr);
1531                 tmp_sps_ptr = NULL;
1532         }
1533         if (tmp_pps_ptr)
1534         {
1535                 free (tmp_pps_ptr);
1536                 tmp_pps_ptr = NULL;
1537         }
1538         if ((FALSE == bret) && *packetized_dci)
1539         {
1540                 free (*packetized_dci);
1541                 *packetized_dci = NULL;
1542         }
1543
1544         return bret;
1545
1546 #else
1547        /* code for sending NALU DCI as it is */
1548        guint nalu_dci_len = strlen ((char *)nalu_dci);
1549        unsigned char *nalu = nalu_dci;
1550        guint idx = 0;
1551         unsigned char tmp[3] = {0, };
1552         gboolean bret = TRUE;
1553         int val = 0;
1554
1555         *packetized_dci_len = (nalu_dci_len/2);
1556
1557         *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
1558         if (NULL == *packetized_dci)
1559         {
1560                 GST_ERROR ("Failed to allocate memory..\n");
1561                 bret = FALSE;
1562                 goto exit;
1563         }
1564
1565         /* copy entire DCI*/
1566         while (nalu_dci_len)
1567         {
1568                 memset (tmp, 0x00, 3);
1569                 strncpy ((char*)tmp, (char*)nalu, 2);
1570                 tmp[2] = '\0';
1571                 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1572                 if (FALSE == bret)
1573                 {
1574                         GST_ERROR ("Failed to int from string...");
1575                         goto exit;
1576                 }
1577                 (*packetized_dci)[idx] = val;
1578                 nalu += 2;
1579                 nalu_dci_len = nalu_dci_len - 2;
1580                 //g_print ("val = 0x%02x, dci_len = %d, idx = %d\n", val, nalu_dci_len, idx);
1581                 idx++;
1582         }
1583
1584       idx = 0;
1585
1586       g_print ("\n\n NEW DCI : 0x ");
1587
1588         while (idx < *packetized_dci_len)
1589         {
1590            g_print ("%02x", (*packetized_dci)[idx] );
1591            idx++;
1592         }
1593
1594        g_print ("\n\n\n");
1595
1596 exit:
1597
1598         if ((FALSE == bret) && *packetized_dci)
1599         {
1600                 free (*packetized_dci);
1601                 *packetized_dci = NULL;
1602         }
1603
1604         return bret;
1605 #endif
1606 }
1607