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