1 #include "ssmanifestparse.h"
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);
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))
14 ssm_parse_get_stream_name(SS_STREAM_TYPE type)
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";
24 int_from_string (gchar * ptr, gchar ** endptr, gint * val, gint base)
27 g_return_val_if_fail (ptr != NULL, FALSE);
28 g_return_val_if_fail (val != NULL, FALSE);
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));
44 ssm_parse_get_xml_prop_boolean (GstSSMParse *parser, xmlNode * node,
45 const gchar * property)
48 gboolean prop_bool = FALSE;
50 prop_string = xmlGetProp (node, (const xmlChar *) property);
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);
60 GST_WARNING("failed to parse boolean property %s from xml string %s", property, prop_string);
62 xmlFree (prop_string);
69 ssm_parse_get_xml_prop_uint (GstSSMParse *parser,
70 xmlNode * node, const gchar * property, guint default_val)
73 guint prop_uint = default_val;
75 prop_string = xmlGetProp (node, (const xmlChar *) property);
77 if (sscanf ((gchar *) prop_string, "%u", &prop_uint)) {
78 GST_LOG (" - %s: %u", property, prop_uint);
80 GST_WARNING("failed to parse unsigned integer property %s from xml string %s",
81 property, prop_string);
83 xmlFree (prop_string);
90 ssm_parse_get_xml_prop_uint64 (GstSSMParse *parser,
91 xmlNode * node, const gchar * property, guint64 default_val)
94 guint64 prop_uint64 = default_val;
96 prop_string = xmlGetProp (node, (const xmlChar *) property);
98 if (sscanf ((gchar *) prop_string, "%llu", &prop_uint64)) {
99 GST_LOG (" - %s: %s[%"G_GUINT64_FORMAT"]", property, prop_string, prop_uint64);
101 GST_WARNING("failed to parse unsigned integer property %s from xml string %s",
102 property, prop_string);
104 xmlFree (prop_string);
111 ssm_parser_sort_qualitylevels_by_bitrate (gconstpointer a, gconstpointer b)
113 return ((GstSSMQualityNode *) (a))->bitrate - ((GstSSMQualityNode *) (b))->bitrate; //sorting in ascending order
114 //return ((GstSSMQualityNode *) (b))->bitrate - ((GstSSMQualityNode *) (a))->bitrate; // sorting in descending order
119 gst_ssm_parse_free_quality_node (GstSSMQualityNode *qualitynode)
122 g_free (qualitynode->codec_data);
123 g_free (qualitynode->fourcc);
124 g_slice_free (GstSSMQualityNode, qualitynode);
129 gst_ssm_parse_free_fragment_node (GstSSMFragmentNode*fragnode)
132 g_slice_free (GstSSMFragmentNode, fragnode);
138 gst_ssm_parse_free_stream_node (GstSSMStreamNode *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;
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;
153 if (streamnode->StreamType) {
154 g_free(streamnode->StreamType);
155 streamnode->StreamType = NULL;
157 if (streamnode->StreamUrl) {
158 g_free(streamnode->StreamUrl);
159 streamnode->StreamUrl = NULL;
161 if (streamnode->StreamSubType) {
162 g_free(streamnode->StreamSubType);
163 streamnode->StreamSubType = NULL;
165 if (streamnode->StreamName) {
166 g_free(streamnode->StreamName);
167 streamnode->StreamName = NULL;
169 if (streamnode->frag_cond) {
170 g_cond_free (streamnode->frag_cond);
171 streamnode->frag_cond = NULL;
173 if (streamnode->frag_lock) {
174 g_mutex_free (streamnode->frag_lock);
175 streamnode->frag_lock = NULL;
177 g_slice_free (GstSSMStreamNode, streamnode);
182 gst_ssm_parse_new (const gchar * uri)
187 g_return_val_if_fail (uri != NULL, NULL);
189 parser = g_new0 (GstSSMParse, 1);
191 parser->uri = g_strdup (uri);
192 parser->lock = g_mutex_new();
193 tmp = strrchr(uri, '/');
195 parser->presentation_uri = (gchar *) malloc (tmp - uri + 1);
196 if (NULL == parser->presentation_uri) {
197 GST_ERROR ("Failed to allocate memory..\n");
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);
209 gst_ssm_parse_free (GstSSMParse *parser)
213 g_return_if_fail (parser != NULL);
215 g_mutex_free(parser->lock);
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;
225 if (parser->RootNode->ProtectNode) {
226 g_slice_free (GstSSMProtectionNode, parser->RootNode->ProtectNode);
227 parser->RootNode->ProtectNode = NULL;
229 g_slice_free (GstSSMRootNode, parser->RootNode);
230 parser->RootNode = NULL;
238 ssm_parse_quality_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr quality_node)
240 GstSSMQualityNode *quality_level = NULL;
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);
246 quality_level = g_slice_new0 (GstSSMQualityNode);
247 if (quality_level == NULL) {
248 GST_ERROR ("Allocation of quality_level node failed!");
252 quality_level->codec_data = NULL;
253 quality_level->fourcc = NULL;
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...");
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...");
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...");
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...");
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...");
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...");
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...");
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...");
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...");
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");
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;
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");
351 GST_DEBUG("FourCC = %s", quality_level->fourcc);
353 // TODO: need to check whether it is required for all video & audio
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");
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);
366 stream->quality_lists = g_list_append (stream->quality_lists, quality_level);
368 GST_LOG ("Appened quality level to stream...");
375 ssm_parse_fragment_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr fragment_node)
377 GstSSMFragmentNode *fragment = NULL;
378 gboolean found_time = FALSE;
379 gboolean found_duration = FALSE;
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);
385 fragment = g_slice_new0 (GstSSMFragmentNode);
386 if (fragment == NULL) {
387 GST_ERROR ("Allocation of fragment failed!");
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);
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");
400 } else if (fragment->dur != -1) {
401 GST_DEBUG ("Fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (fragment->dur));
402 found_duration = TRUE;
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));
412 if (!found_time && !found_duration) {
413 GST_ERROR ("Both time & duration attributes are NOT present.. ERROR");
415 } else if (!found_time && found_duration) {
416 GList *prev_fragment_list = NULL;
417 GstSSMFragmentNode *prev_fragment = NULL;
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");
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);
430 GST_INFO ("Frament list is empty, assuming it as first fragment...");
433 } else if (found_time && !found_duration) {
434 xmlNodePtr next_fragment_node = NULL;
437 GST_DEBUG ("Only time attribute is present...");
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);
443 GST_ERROR ("Next fragment time not present to calculate duration of present fragment...");
446 fragment->dur = next_ts - fragment->time;
447 GST_DEBUG ("Current fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(fragment->dur));
450 GST_ERROR ("Next fragment not present to calculate duration of present fragment...");
456 /*error check for timestamps as specified in spec */
458 xmlNodePtr next_fragment_node = NULL;
459 unsigned long long next_ts = 0;
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);
465 GST_DEBUG ("Next Fragment time = %llu and Current fragment time = %llu\n", next_ts, fragment->time);
467 if ( next_ts < fragment->time) {
468 GST_ERROR ("Error in timestamp sequence...");
476 stream->stream_duration += fragment->dur;
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
486 ssm_parse_stream_index_node (GstSSMParse *parser, xmlNodePtr stream_node)
488 GstSSMStreamNode *stream = NULL;
489 xmlNodePtr stream_children = NULL;
491 g_return_val_if_fail (parser != NULL, FALSE);
492 g_return_val_if_fail (stream_node != NULL, FALSE);
494 stream = g_slice_new0 (GstSSMStreamNode);
495 if (stream == NULL) {
496 GST_WARNING ("Allocation of stream node failed!");
500 stream->frag_lock = g_mutex_new ();
501 stream->frag_cond = g_cond_new ();
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");
509 GST_DEBUG ("Type = %s", stream->StreamType);
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;
518 GST_ERROR ("UnKnown Stream type...");
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);
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);
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);
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");
541 GST_DEBUG("nChunks = %d", stream->nChunks);
543 stream->nQualityLevels = ssm_parse_get_xml_prop_uint (parser, stream_node, "QualityLevels", 0);
544 GST_DEBUG("nQualityLevels = %d", stream->nQualityLevels);
546 stream->StreamUrl = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Url");
547 if (NULL == stream->StreamUrl) {
548 GST_ERROR ("Url Pattern attribute is not present");
551 GST_DEBUG ("Url = %s", stream->StreamUrl);
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);
558 stream->MaxHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "MaxHeight", 0);
559 GST_DEBUG("MaxHeight = %d", stream->MaxHeight);
561 stream->DisplayWidth = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayWidth", 0);
562 GST_DEBUG("DisplayWidth = %d", stream->DisplayWidth);
564 stream->DisplayHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayHeight", 0);
565 GST_DEBUG("DisplayHeight = %d", stream->DisplayHeight);
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");
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;
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");
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");
592 GST_WARNING (" ==== >>>>>> Unknow ChildrenNode in StreamNode : %s", stream_children->name);
594 stream_children = stream_children->next;
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);
602 parser->RootNode->streams[stream->type] = g_list_append (parser->RootNode->streams[stream->type], stream);
610 ssm_parse_protection_node (GstSSMParse *parser, xmlNodePtr protection_node)
612 xmlChar *xml_string = NULL;
614 g_return_val_if_fail (parser != NULL, FALSE);
615 g_return_val_if_fail (protection_node != NULL, FALSE);
617 parser->RootNode->ProtectNode = g_slice_new0 (GstSSMFragmentNode);
618 if (NULL == parser->RootNode->ProtectNode) {
619 GST_ERROR ("Failed to allocate memory...\n");
623 parser->RootNode->ProtectNode->SystemID = NULL;
624 parser->RootNode->ProtectNode->Content = NULL;
625 parser->RootNode->ProtectNode->ContentSize = 0;
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");
634 GST_DEBUG ("system ID = %s\n", parser->RootNode->ProtectNode->SystemID);
636 if (!strncasecmp ((char *)parser->RootNode->ProtectNode->SystemID,
637 "9A04F079-9840-4286-AB92-E65BE0885F95",
639 g_print ("======== >>>>>>>. Content is encrypted using PLAYREADY\n");
641 GST_ERROR ("\n\n ******** UN-supported encrypted content... *********\n\n");
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");
650 gsize content_size = 0;
652 g_print ("Content = %s\n", xml_string);
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");
662 parser->RootNode->ProtectNode->ContentSize = content_size;
666 GST_DEBUG ("ProtectionNode content = %s and size = %d\n", parser->RootNode->ProtectNode->Content, content_size);
669 GST_ERROR ("ProtectionHeader is NOT PRESENT in Protection node...ERROR\n");
673 GST_LOG ("successfully parsed protectionheader node...");
678 ssm_parse_root_node (GstSSMParse *parser, xmlNodePtr root_node)
682 g_return_val_if_fail (parser != NULL, FALSE);
683 g_return_val_if_fail (root_node != NULL, FALSE);
685 parser->RootNode = g_slice_new0 (GstSSMRootNode);
686 if (parser->RootNode == NULL) {
687 GST_WARNING ("Allocation of root node failed!");
691 for (i = 0; i < SS_STREAM_NUM; i++) {
692 parser->RootNode->streams[i] = NULL;
695 parser->RootNode->ProtectNode = NULL;
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");
703 GST_LOG("SmoothStreamingMedia :: Majorversion = %d", parser->RootNode->MajorVersion);
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);
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);
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);
715 parser->RootNode->PresentationIsLive = ssm_parse_get_xml_prop_boolean (parser, root_node, "IsLive");
716 GST_LOG("SmoothStreamingMedia :: IsLive = %d", parser->RootNode->PresentationIsLive);
718 /* valid for live presentation only*/
719 if (parser->RootNode->PresentationIsLive) {
721 parser->RootNode->LookAheadCount = ssm_parse_get_xml_prop_uint (parser, root_node, "LookaheadCount", -1);
722 GST_LOG("SmoothStreamingMedia :: LookaheadCount = %d", parser->RootNode->LookAheadCount);
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);
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");
741 gst_ssm_parse_manifest (GstSSMParse *parser, char *data, unsigned int size)
743 xmlNodePtr root = NULL;
744 xmlNodePtr curnode = NULL;
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);
752 /* parse manifest xml file */
753 doc = xmlReadMemory ((gchar *) data, size, NULL, NULL, 0);
755 GST_ERROR("failed to parse manifest file...");
759 /* Get the root element */
760 root = xmlDocGetRootElement(doc);
762 GST_ERROR("no ROOT node in manifest file...");
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...");
772 GST_DEBUG ("Parsing ROOT element is successful");
774 GST_ERROR ("SmoothStreamingMedia ROOT element is not present...");
778 /* moving to children nodes */
779 curnode = root->xmlChildrenNode;
782 if (xmlIsBlankNode (curnode)) {/* skip blank node */
783 curnode = curnode->next;
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...");
793 } else if (!xmlStrcmp(curnode->name, (const xmlChar *) "Protection")) {
794 xmlNodePtr protect_node;
796 /* get the children */
797 protect_node = curnode->xmlChildrenNode;
798 if (NULL == protect_node) {
799 GST_ERROR ("No Children for Protection Node...\n");
802 if (!ssm_parse_protection_node (parser, protect_node)) {
803 GST_ERROR ("failed to parse protectionheader node");
808 curnode = curnode->next;
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);
822 parser->ns_start = 0;
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;
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);
838 stream = (parser->RootNode->streams[i])->data;
839 frag_list = stream->fragment_lists;
840 start_ts = ((GstSSMFragmentNode *)frag_list->data)->time;
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);
845 /* take MAX of stream's start as new_segment start */
846 parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
850 GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
857 GST_DEBUG ("successfully parsed manifest");
870 /* Only supporting url in 'QualityLevels({bitrate})/Fragments(xxxxxx={start time})'
871 * FIXME : Add support for any */
873 gst_ssm_parse_get_next_fragment_url (GstSSMParse *parser, SS_STREAM_TYPE stream_type, gchar **uri, guint64 *start_ts)
875 GstSSMStreamNode *stream = NULL;
876 GList *frag_list = NULL;
879 gchar **splitter1 = NULL;
880 gchar **splitter2 = NULL;
881 gchar **splitter3 = NULL;
883 MANIFEST_LOCK(parser);
884 stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
885 g_mutex_lock (stream->frag_lock);
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);
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);
904 stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
906 frag_list = stream->fragment_lists;
908 strs = g_ptr_array_new ();
910 /* adding presentation uri */
911 g_ptr_array_add (strs, g_strdup(parser->presentation_uri));
913 splitter1 = g_strsplit (stream->StreamUrl, "{", 3);
915 /* add stream url till first '{' */
916 g_ptr_array_add (strs, g_strdup(splitter1[0]));
918 /* adding bitrate param */
919 g_ptr_array_add (strs, g_strdup_printf ("%d", ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate));
921 /* tokenize based on '}' */
922 splitter2 = g_strsplit (splitter1[1], "}", 2);
924 g_ptr_array_add (strs, g_strdup(splitter2[1]));
926 time = ((GstSSMFragmentNode *)frag_list->data)->time;
928 /* adding fragment time */
929 g_ptr_array_add (strs, g_strdup_printf ("%llu", time));
931 *start_ts = gst_util_uint64_scale (time, GST_SECOND, parser->RootNode->TimeScale);
933 /* tokenize based on '}' */
934 splitter3 = g_strsplit (splitter1[2], "}", 2);
936 g_ptr_array_add (strs, g_strdup(splitter3[1]));
938 /* add a terminating NULL */
939 g_ptr_array_add (strs, NULL);
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;
944 GST_INFO ("Reached end of fragment list...\n");
945 ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fraglist_eos = TRUE;
948 *uri = g_strjoinv (NULL, (gchar **) strs->pdata);
949 g_strfreev ((gchar **) g_ptr_array_free (strs, FALSE));
951 g_mutex_unlock (stream->frag_lock);
953 MANIFEST_UNLOCK(parser);
959 ssm_parse_get_stream_caps (GstSSMParse *parser, SS_STREAM_TYPE stream_type)
961 GstSSMStreamNode *stream = NULL;
962 MANIFEST_LOCK(parser);
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);
973 MANIFEST_UNLOCK(parser);
978 ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
980 GstSSMQualityNode *cur_quality_node = (GstSSMQualityNode *)(stream->quality_lists->data);
981 GstBuffer *codec_data = NULL;
982 GstCaps *caps = NULL;
984 codec_data = gst_buffer_new ();
986 GST_ERROR ("failed to allocate buffer");
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");
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, };
1002 gint codec_data_len = 0;
1005 codec_data_len = (DCI_len >>1);
1007 codec_data = gst_buffer_new_and_alloc (codec_data_len);
1009 GST_ERROR ("Failed to allocate memory..\n");
1013 /* copy codec data */
1015 memset (tmp, 0x00, 3);
1016 strncpy ((char*)tmp, (char*)codec_data, 2);
1018 if (!int_from_string ((char*)tmp, NULL, &val, 16)) {
1019 GST_ERROR ("Failed to int from string...");
1022 (GST_BUFFER_DATA(codec_data))[idx] = val;
1024 DCI_len = DCI_len - 2;
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,
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,
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,
1062 GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
1068 ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1070 GstSSMQualityNode *cur_quality_node = (GstSSMQualityNode *)(stream->quality_lists->data);
1071 GstBuffer *codec_data = NULL;
1072 GstCaps *caps = NULL;
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, };
1078 gint codec_data_len = (DCI_len >>1);
1081 codec_data = gst_buffer_new_and_alloc (codec_data_len);
1082 if (NULL == codec_data) {
1083 GST_ERROR ("Failed to allocate memory..\n");
1087 /* copy codec data */
1089 memset (tmp, 0x00, 3);
1090 strncpy ((char*)tmp, (char*)cur_quality_node->codec_data, 2);
1092 if (!int_from_string ((char*)tmp, NULL, &val , 16)) {
1093 GST_ERROR ("Failed to int from string...");
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);
1103 GST_ERROR ("\n\n\nUnsupported Audio Codec Fourcc...\n\n\n");
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,
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,
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,
1130 GST_INFO ( "prepared video caps : %s\n", gst_caps_to_string(caps));
1136 ssm_prepare_text_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1138 // TODO: Yet to add support for text caps
1143 gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate)
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;
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);
1156 g_print ("Already at MAX Bitrate possible...\n");
1157 ret = SS_MODE_NO_SWITCH;
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);
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;
1183 gst_ssm_parse_append_next_fragment (GstSSMParse *parser, SS_STREAM_TYPE stream_type, guint64 timestamp, guint64 duration)
1185 GstSSMStreamNode *stream = NULL;
1186 GstSSMFragmentNode *new_fragment = NULL;
1187 GstSSMFragmentNode *last_fragment = NULL;
1188 GList *last_node = NULL;
1190 g_return_val_if_fail (parser != NULL, FALSE);
1192 /*get current stream based on stream_type */
1193 stream = (parser->RootNode->streams[stream_type])->data;
1195 g_return_val_if_fail (stream->fragment_lists, FALSE);
1197 g_mutex_lock (stream->frag_lock);
1199 last_node = g_list_last(stream->fragment_lists);
1201 last_fragment = (GstSSMFragmentNode *)(last_node->data);
1203 if (last_fragment->time < timestamp) {
1205 GST_LOG ("+++++ last_fragment time = %llu and current recd = %llu +++++\n", last_fragment->time, timestamp);
1207 /* allocate new fragment node */
1208 new_fragment = g_slice_new0 (GstSSMFragmentNode);
1209 if (new_fragment == NULL) {
1210 GST_ERROR ("Allocation of fragment failed!");
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;
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;
1225 /* add the new fragment duration to total stream duration */
1226 stream->stream_duration += duration;
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);
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);
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;
1241 /* signal fragment wait */
1242 g_cond_signal (stream->frag_cond);
1245 g_print ("--------- Received '%s' fragment is less than Last fragment in the list -----------\n", ssm_parse_get_stream_name(stream_type));
1248 g_mutex_unlock (stream->frag_lock);
1254 gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time)
1257 GstSSMStreamNode *stream = NULL;
1258 guint64 stream_time = -1;
1259 guint64 start_ts = -1;
1261 parser->ns_start = 0;
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));
1270 if (seek_time > stream_time) {
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));
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) {
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));
1292 start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1295 start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1298 if (stream->type == SS_STREAM_VIDEO) {
1299 /* move to least possible bitrate variant*/
1300 stream->quality_lists = g_list_first (stream->quality_lists);
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);
1306 /* take max of stream's start as new_segment start */
1307 parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
1311 GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
1317 convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len)
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, };
1331 unsigned int idx = 0;
1333 // TODO: need to generalize this logic for finding multiple SPS and PPS sets and finding SPS/PPS by ANDing 0x1F
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));
1339 sps_len = pps_start - nalu_dci;
1341 GST_DEBUG ("sps length = %d\n", sps_len);
1343 sps_data = (unsigned char*) malloc (sps_len + 1);
1344 if (NULL == sps_data)
1346 GST_ERROR ("Failed to allocate memory..\n");
1352 strncpy ((char*)sps_data, (char *)nalu_dci, sps_len);
1353 sps_data[sps_len] = '\0';
1355 tmp_sps_ptr = sps_data;
1357 GST_DEBUG ("SPS data = %s\n", sps_data);
1359 pps_len = pps_end - pps_start;
1360 GST_DEBUG ("pps length = %d\n", pps_len);
1362 pps_data = (unsigned char*)malloc (pps_len + 1);
1363 if (NULL == pps_data)
1365 GST_ERROR ("Failed to allocate memory..\n");
1371 strncpy ((char*)pps_data, (char*)pps_start, pps_len);
1372 pps_data[pps_len] = '\0';
1373 tmp_pps_ptr = pps_data;
1375 GST_DEBUG ("PPS data = %s\n", pps_data);
1377 /* 6 bytes of metadata */
1378 *packetized_dci_len = 8;
1380 *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
1381 if (NULL == *packetized_dci)
1383 GST_ERROR ("Failed to allocate memory..\n");
1388 /* configurationVersion */
1389 (*packetized_dci)[0] = 0x01;
1391 /* AVCProfileIndication */
1392 memset (tmp, 0x00, 3);
1394 strncpy ((char*)tmp, (char*)sps_data+10, 2);
1397 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1400 GST_ERROR ("Failed to int from string...");
1404 (*packetized_dci)[1] = val;
1406 /* profile_compatibility*/
1407 memset (tmp, 0x00, 3);
1408 strncpy ((char*)tmp, (char*)sps_data+12, 2);
1410 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1413 GST_ERROR ("Failed to int from string...");
1416 (*packetized_dci)[2] = val;
1418 /* AVCLevelIndication */
1419 memset (tmp, 0x00, 3);
1420 strncpy ((char*)tmp, (char*)sps_data+14, 2);
1422 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1425 GST_ERROR ("Failed to int from string...");
1429 (*packetized_dci)[3] = val;
1431 /* Reserver (6) + LengthSizeMinusOne (2) */
1432 (*packetized_dci)[4] = 0xff; // hardcoding lengthoflength = 4 for present
1434 /* Reserver (3) + numOfSequenceParameterSets (5) */
1435 (*packetized_dci)[5] = 0xe1; // hardcoding numOfSequenceParameterSets = 1 for present
1437 /* avoiding NALU start code 0x00 00 00 01 */
1438 sps_len = sps_len -8;
1439 sps_data = sps_data + 8;
1441 (*packetized_dci)[6] = (sps_len >>1) >> 16;
1442 (*packetized_dci)[7] = (sps_len >>1);
1444 *packetized_dci_len += (sps_len/2);
1446 *packetized_dci = (unsigned char*) realloc (*packetized_dci, *packetized_dci_len);
1447 if (NULL == *packetized_dci)
1449 GST_ERROR ("Failed to allocate memory..\n");
1456 /* convert SPS data and store*/
1459 memset (tmp, 0x00, 3);
1460 strncpy ((char*)tmp, (char*)sps_data, 2);
1462 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1465 GST_ERROR ("Failed to int from string...");
1468 (*packetized_dci)[idx] = val;
1470 sps_len = sps_len - 2;
1471 //g_print ("val = 0x%02x, sps_len = %d, idx = %d\n", val, sps_len, idx);
1475 /* avoiding NALU start code 0x00 00 00 01 */
1476 pps_len = pps_len -8;
1477 pps_data = pps_data + 8;
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)
1484 GST_ERROR ("Failed to allocate memory..\n");
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);
1493 /* convert PPS data and store */
1496 memset (tmp, 0x00, 3);
1497 strncpy ((char*)tmp, (char*)pps_data, 2);
1499 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1502 GST_ERROR ("Failed to int from string...");
1506 (*packetized_dci)[idx] = val;
1508 pps_len = pps_len - 2;
1509 //g_print ("val = 0x%02x, pps_len = %d, idx = %d\n", val, pps_len, idx);
1517 g_print ("Complete VIDEO packetized_dci: 0x");
1518 while (idx < *packetized_dci_len)
1520 g_print ("%02x", (*packetized_dci)[idx]);
1538 if ((FALSE == bret) && *packetized_dci)
1540 free (*packetized_dci);
1541 *packetized_dci = NULL;
1547 /* code for sending NALU DCI as it is */
1548 guint nalu_dci_len = strlen ((char *)nalu_dci);
1549 unsigned char *nalu = nalu_dci;
1551 unsigned char tmp[3] = {0, };
1552 gboolean bret = TRUE;
1555 *packetized_dci_len = (nalu_dci_len/2);
1557 *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
1558 if (NULL == *packetized_dci)
1560 GST_ERROR ("Failed to allocate memory..\n");
1565 /* copy entire DCI*/
1566 while (nalu_dci_len)
1568 memset (tmp, 0x00, 3);
1569 strncpy ((char*)tmp, (char*)nalu, 2);
1571 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1574 GST_ERROR ("Failed to int from string...");
1577 (*packetized_dci)[idx] = val;
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);
1586 g_print ("\n\n NEW DCI : 0x ");
1588 while (idx < *packetized_dci_len)
1590 g_print ("%02x", (*packetized_dci)[idx] );
1598 if ((FALSE == bret) && *packetized_dci)
1600 free (*packetized_dci);
1601 *packetized_dci = NULL;