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", g_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 gst_ssm_parse_confirm_audiotag(gchar ** fourcc, gint audio_tag)
242 *fourcc = (gchar *)strdup("AACL");
245 *fourcc = (gchar *)strdup("WMAP");
254 ssm_parse_quality_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr quality_node)
256 GstSSMQualityNode *quality_level = NULL;
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);
262 quality_level = g_slice_new0 (GstSSMQualityNode);
263 if (quality_level == NULL) {
264 GST_ERROR ("Allocation of quality_level node failed!");
268 quality_level->codec_data = NULL;
269 quality_level->fourcc = NULL;
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...");
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...");
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...");
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...");
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...");
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...");
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...");
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...");
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...");
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);
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");
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);
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");
372 GST_DEBUG("FourCC = %s", quality_level->fourcc);
374 // TODO: need to check whether it is required for all video & audio
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");
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);
387 stream->quality_lists = g_list_append (stream->quality_lists, quality_level);
389 GST_LOG ("Appened quality level to stream...");
396 ssm_parse_fragment_node (GstSSMParse *parser, GstSSMStreamNode *stream, xmlNodePtr fragment_node)
398 GstSSMFragmentNode *fragment = NULL;
399 gboolean found_time = FALSE;
400 gboolean found_duration = FALSE;
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);
406 fragment = g_slice_new0 (GstSSMFragmentNode);
407 if (fragment == NULL) {
408 GST_ERROR ("Allocation of fragment failed!");
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);
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");
421 } else if (fragment->dur != -1) {
422 GST_DEBUG ("Fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (fragment->dur));
423 found_duration = TRUE;
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));
433 if (!found_time && !found_duration) {
434 GST_ERROR ("Both time & duration attributes are NOT present.. ERROR");
436 } else if (!found_time && found_duration) {
437 GList *prev_fragment_list = NULL;
438 GstSSMFragmentNode *prev_fragment = NULL;
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");
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);
451 GST_INFO ("Frament list is empty, assuming it as first fragment...");
454 } else if (found_time && !found_duration) {
455 xmlNodePtr next_fragment_node = NULL;
458 GST_DEBUG ("Only time attribute is present...");
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);
464 GST_ERROR ("Next fragment time not present to calculate duration of present fragment...");
467 fragment->dur = next_ts - fragment->time;
468 GST_DEBUG ("Current fragment duration = %"GST_TIME_FORMAT, GST_TIME_ARGS(fragment->dur));
471 GST_ERROR ("Next fragment not present to calculate duration of present fragment...");
477 /*error check for timestamps as specified in spec */
479 xmlNodePtr next_fragment_node = NULL;
480 unsigned long long next_ts = 0;
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);
486 GST_DEBUG ("Next Fragment time = %llu and Current fragment time = %llu\n", next_ts, fragment->time);
488 if ( next_ts < fragment->time) {
489 GST_ERROR ("Error in timestamp sequence...");
497 stream->stream_duration += fragment->dur;
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
507 ssm_parse_stream_index_node (GstSSMParse *parser, xmlNodePtr stream_node)
509 GstSSMStreamNode *stream = NULL;
510 xmlNodePtr stream_children = NULL;
512 g_return_val_if_fail (parser != NULL, FALSE);
513 g_return_val_if_fail (stream_node != NULL, FALSE);
515 stream = g_slice_new0 (GstSSMStreamNode);
516 if (stream == NULL) {
517 GST_WARNING ("Allocation of stream node failed!");
521 stream->frag_lock = g_mutex_new ();
522 stream->frag_cond = g_cond_new ();
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");
530 GST_DEBUG ("Type = %s", stream->StreamType);
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;
539 GST_ERROR ("UnKnown Stream type...");
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);
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);
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);
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");
562 GST_DEBUG("nChunks = %d", stream->nChunks);
564 stream->nQualityLevels = ssm_parse_get_xml_prop_uint (parser, stream_node, "QualityLevels", 0);
565 GST_DEBUG("nQualityLevels = %d", stream->nQualityLevels);
567 stream->StreamUrl = (gchar *)xmlGetProp(stream_node, (const xmlChar *) "Url");
568 if (NULL == stream->StreamUrl) {
569 GST_ERROR ("Url Pattern attribute is not present");
572 GST_DEBUG ("Url = %s", stream->StreamUrl);
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);
579 stream->MaxHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "MaxHeight", 0);
580 GST_DEBUG("MaxHeight = %d", stream->MaxHeight);
582 stream->DisplayWidth = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayWidth", 0);
583 GST_DEBUG("DisplayWidth = %d", stream->DisplayWidth);
585 stream->DisplayHeight = ssm_parse_get_xml_prop_uint (parser, stream_node, "DisplayHeight", 0);
586 GST_DEBUG("DisplayHeight = %d", stream->DisplayHeight);
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");
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;
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");
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");
613 GST_WARNING (" ==== >>>>>> Unknow ChildrenNode in StreamNode : %s", stream_children->name);
615 stream_children = stream_children->next;
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);
623 parser->RootNode->streams[stream->type] = g_list_append (parser->RootNode->streams[stream->type], stream);
631 ssm_parse_protection_node (GstSSMParse *parser, xmlNodePtr protection_node)
633 xmlChar *xml_string = NULL;
635 g_return_val_if_fail (parser != NULL, FALSE);
636 g_return_val_if_fail (protection_node != NULL, FALSE);
638 parser->RootNode->ProtectNode = g_slice_new0 (GstSSMFragmentNode);
639 if (NULL == parser->RootNode->ProtectNode) {
640 GST_ERROR ("Failed to allocate memory...\n");
644 parser->RootNode->ProtectNode->SystemID = NULL;
645 parser->RootNode->ProtectNode->Content = NULL;
646 parser->RootNode->ProtectNode->ContentSize = 0;
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");
655 GST_DEBUG ("system ID = %s\n", parser->RootNode->ProtectNode->SystemID);
657 if (!strncasecmp ((char *)parser->RootNode->ProtectNode->SystemID,
658 "9A04F079-9840-4286-AB92-E65BE0885F95",
660 g_print ("======== >>>>>>>. Content is encrypted using PLAYREADY\n");
662 GST_ERROR ("\n\n ******** UN-supported encrypted content... *********\n\n");
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");
671 gsize content_size = 0;
673 g_print ("Content = %s\n", xml_string);
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");
683 parser->RootNode->ProtectNode->ContentSize = content_size;
687 GST_DEBUG ("ProtectionNode content = %s and size = %d\n", parser->RootNode->ProtectNode->Content, content_size);
690 GST_ERROR ("ProtectionHeader is NOT PRESENT in Protection node...ERROR\n");
694 GST_LOG ("successfully parsed protectionheader node...");
699 ssm_parse_root_node (GstSSMParse *parser, xmlNodePtr root_node)
703 g_return_val_if_fail (parser != NULL, FALSE);
704 g_return_val_if_fail (root_node != NULL, FALSE);
706 parser->RootNode = g_slice_new0 (GstSSMRootNode);
707 if (parser->RootNode == NULL) {
708 GST_WARNING ("Allocation of root node failed!");
712 for (i = 0; i < SS_STREAM_NUM; i++) {
713 parser->RootNode->streams[i] = NULL;
716 parser->RootNode->ProtectNode = NULL;
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");
724 GST_LOG("SmoothStreamingMedia :: Majorversion = %d", parser->RootNode->MajorVersion);
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);
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);
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);
736 parser->RootNode->PresentationIsLive = ssm_parse_get_xml_prop_boolean (parser, root_node, "IsLive");
737 GST_LOG("SmoothStreamingMedia :: IsLive = %d", parser->RootNode->PresentationIsLive);
739 /* valid for live presentation only*/
740 if (parser->RootNode->PresentationIsLive) {
742 parser->RootNode->LookAheadCount = ssm_parse_get_xml_prop_uint (parser, root_node, "LookaheadCount", -1);
743 GST_LOG("SmoothStreamingMedia :: LookaheadCount = %d", parser->RootNode->LookAheadCount);
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);
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");
762 gst_ssm_parse_manifest (GstSSMParse *parser, char *data, unsigned int size)
764 xmlNodePtr root = NULL;
765 xmlNodePtr curnode = NULL;
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);
773 /* parse manifest xml file */
774 doc = xmlReadMemory ((gchar *) data, size, NULL, NULL, 0);
776 GST_ERROR("failed to parse manifest file...");
780 /* Get the root element */
781 root = xmlDocGetRootElement(doc);
783 GST_ERROR("no ROOT node in manifest file...");
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...");
793 GST_DEBUG ("Parsing ROOT element is successful");
795 GST_ERROR ("SmoothStreamingMedia ROOT element is not present...");
799 /* moving to children nodes */
800 curnode = root->xmlChildrenNode;
803 if (xmlIsBlankNode (curnode)) {/* skip blank node */
804 curnode = curnode->next;
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...");
814 } else if (!xmlStrcmp(curnode->name, (const xmlChar *) "Protection")) {
815 xmlNodePtr protect_node;
817 /* get the children */
818 protect_node = curnode->xmlChildrenNode;
819 if (NULL == protect_node) {
820 GST_ERROR ("No Children for Protection Node...\n");
823 if (!ssm_parse_protection_node (parser, protect_node)) {
824 GST_ERROR ("failed to parse protectionheader node");
829 curnode = curnode->next;
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);
843 parser->ns_start = 0;
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;
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);
859 stream = (parser->RootNode->streams[i])->data;
860 frag_list = stream->fragment_lists;
861 start_ts = ((GstSSMFragmentNode *)frag_list->data)->time;
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);
866 /* take MAX of stream's start as new_segment start */
867 parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
871 GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
878 GST_DEBUG ("successfully parsed manifest");
891 /* Only supporting url in 'QualityLevels({bitrate})/Fragments(xxxxxx={start time})'
892 * FIXME : Add support for any */
894 gst_ssm_parse_get_next_fragment_url (GstSSMParse *parser, SS_STREAM_TYPE stream_type, gchar **uri, guint64 *start_ts)
896 GstSSMStreamNode *stream = NULL;
897 GList *frag_list = NULL;
900 gchar **splitter1 = NULL;
901 gchar **splitter2 = NULL;
902 gchar **splitter3 = NULL;
904 MANIFEST_LOCK(parser);
905 stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
906 g_mutex_lock (stream->frag_lock);
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);
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);
925 stream = (parser->RootNode->streams[stream_type])->data; //get current video stream
927 frag_list = stream->fragment_lists;
929 strs = g_ptr_array_new ();
931 /* adding presentation uri */
932 g_ptr_array_add (strs, g_strdup(parser->presentation_uri));
934 splitter1 = g_strsplit (stream->StreamUrl, "{", 3);
936 /* add stream url till first '{' */
937 g_ptr_array_add (strs, g_strdup(splitter1[0]));
939 /* adding bitrate param */
940 g_ptr_array_add (strs, g_strdup_printf ("%d", ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate));
942 /* tokenize based on '}' */
943 splitter2 = g_strsplit (splitter1[1], "}", 2);
945 g_ptr_array_add (strs, g_strdup(splitter2[1]));
947 time = ((GstSSMFragmentNode *)frag_list->data)->time;
949 /* adding fragment time */
950 g_ptr_array_add (strs, g_strdup_printf ("%llu", time));
952 *start_ts = gst_util_uint64_scale (time, GST_SECOND, parser->RootNode->TimeScale);
954 /* tokenize based on '}' */
955 splitter3 = g_strsplit (splitter1[2], "}", 2);
957 g_ptr_array_add (strs, g_strdup(splitter3[1]));
959 /* add a terminating NULL */
960 g_ptr_array_add (strs, NULL);
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;
965 GST_INFO ("Reached end of fragment list...\n");
966 ((GstSSMStreamNode *)(parser->RootNode->streams[stream_type]->data))->fraglist_eos = TRUE;
969 *uri = g_strjoinv (NULL, (gchar **) strs->pdata);
970 g_strfreev ((gchar **) g_ptr_array_free (strs, FALSE));
972 g_mutex_unlock (stream->frag_lock);
974 MANIFEST_UNLOCK(parser);
980 ssm_parse_get_stream_caps (GstSSMParse *parser, SS_STREAM_TYPE stream_type)
982 GstSSMStreamNode *stream = NULL;
983 MANIFEST_LOCK(parser);
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);
994 MANIFEST_UNLOCK(parser);
999 ssm_prepare_video_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1001 GstSSMQualityNode *cur_quality_node = (GstSSMQualityNode *)(stream->quality_lists->data);
1002 GstBuffer *codec_data = NULL;
1003 GstCaps *caps = NULL;
1005 codec_data = gst_buffer_new ();
1007 GST_ERROR ("failed to allocate buffer");
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");
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, };
1023 gint codec_data_len = 0;
1026 codec_data_len = (DCI_len >>1);
1028 codec_data = gst_buffer_new_and_alloc (codec_data_len);
1030 GST_ERROR ("Failed to allocate memory..\n");
1034 /* copy codec data */
1036 memset (tmp, 0x00, 3);
1037 strncpy ((char*)tmp, (char*)codec_data, 2);
1039 if (!int_from_string ((char*)tmp, NULL, &val, 16)) {
1040 GST_ERROR ("Failed to int from string...");
1043 (GST_BUFFER_DATA(codec_data))[idx] = val;
1045 DCI_len = DCI_len - 2;
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,
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,
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,
1083 gchar *caps_name = gst_caps_to_string(caps);
1084 GST_INFO ( "prepared video caps : %s\n", caps_name);
1091 ssm_prepare_audio_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1093 GstSSMQualityNode *cur_quality_node = (GstSSMQualityNode *)(stream->quality_lists->data);
1094 GstBuffer *codec_data = NULL;
1095 GstCaps *caps = NULL;
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, };
1103 gint codec_data_len = (DCI_len >>1);
1106 codec_data = gst_buffer_new_and_alloc (codec_data_len);
1107 if (NULL == codec_data) {
1108 GST_ERROR ("Failed to allocate memory..\n");
1112 /* copy codec data */
1114 memset (tmp, 0x00, 3);
1115 strncpy ((char*)tmp, (char*)dci, 2);
1117 if (!int_from_string ((char*)tmp, NULL, &val , 16)) {
1118 GST_ERROR ("Failed to int from string...");
1121 (GST_BUFFER_DATA(codec_data))[idx] = val;
1123 DCI_len = DCI_len - 2;
1124 //g_print ("val = 0x%02x, codec_data_length = %d, idx = %d\n", val, DCI_len, idx);
1128 GST_ERROR ("\n\n\nUnsupported Audio Codec Fourcc...\n\n\n");
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,
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,
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,
1156 gchar *caps_name = gst_caps_to_string(caps);
1157 GST_INFO ( "prepared video caps : %s\n", caps_name);
1164 ssm_prepare_text_caps (GstSSMParse *parser, GstSSMStreamNode *stream)
1166 // TODO: Yet to add support for text caps
1171 gst_ssm_parse_switch_qualitylevel (GstSSMParse *parser, guint drate)
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;
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);
1183 bitrate = ((GstSSMQualityNode *)stream->quality_lists->data)->bitrate;
1185 g_print ("Already at MAX Bitrate possible...\n");
1186 ret = SS_MODE_NO_SWITCH;
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;
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;
1213 gst_ssm_parse_append_next_fragment (GstSSMParse *parser, SS_STREAM_TYPE stream_type, guint64 timestamp, guint64 duration)
1215 GstSSMStreamNode *stream = NULL;
1216 GstSSMFragmentNode *new_fragment = NULL;
1217 GstSSMFragmentNode *last_fragment = NULL;
1218 GList *last_node = NULL;
1220 g_return_val_if_fail (parser != NULL, FALSE);
1222 /*get current stream based on stream_type */
1223 stream = (parser->RootNode->streams[stream_type])->data;
1225 g_return_val_if_fail (stream->fragment_lists, FALSE);
1227 g_mutex_lock (stream->frag_lock);
1229 last_node = g_list_last(stream->fragment_lists);
1231 last_fragment = (GstSSMFragmentNode *)(last_node->data);
1233 if (last_fragment->time < timestamp) {
1235 GST_LOG ("+++++ last_fragment time = %llu and current recd = %llu +++++\n", last_fragment->time, timestamp);
1237 /* allocate new fragment node */
1238 new_fragment = g_slice_new0 (GstSSMFragmentNode);
1239 if (new_fragment == NULL) {
1240 GST_ERROR ("Allocation of fragment failed!");
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;
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;
1255 /* add the new fragment duration to total stream duration */
1256 stream->stream_duration += duration;
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);
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);
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;
1271 /* signal fragment wait */
1272 g_cond_signal (stream->frag_cond);
1275 g_print ("--------- Received '%s' fragment is less than Last fragment in the list -----------\n", ssm_parse_get_stream_name(stream_type));
1278 g_mutex_unlock (stream->frag_lock);
1284 gst_ssm_parse_seek_manifest (GstSSMParse *parser, guint64 seek_time)
1287 GstSSMStreamNode *stream = NULL;
1288 guint64 stream_time = -1;
1289 guint64 start_ts = -1;
1291 parser->ns_start = 0;
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));
1300 if (seek_time > stream_time) {
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));
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) {
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;
1330 start_ts = ((GstSSMFragmentNode *)stream->fragment_lists->data)->time;
1333 if (stream->type == SS_STREAM_VIDEO) {
1334 /* move to least possible bitrate variant*/
1335 stream->quality_lists = g_list_first (stream->quality_lists);
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);
1341 /* take max of stream's start as new_segment start */
1342 parser->ns_start = START_TS_MAX (parser->ns_start, start_ts);
1346 GST_INFO ("ns_start = %"G_GUINT64_FORMAT, parser->ns_start);
1352 gst_ssm_parse_get_protection_header (GstSSMParse *parser, unsigned char **protection_header, unsigned int *protection_header_len)
1354 if (!parser->RootNode->ProtectNode) {
1355 *protection_header = NULL;
1356 *protection_header_len = 0;
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...");
1367 memcpy (*protection_header, parser->RootNode->ProtectNode->Content, parser->RootNode->ProtectNode->ContentSize);
1368 *protection_header_len = parser->RootNode->ProtectNode->ContentSize;
1375 convert_NALUnitDCI_to_PacktizedDCI (unsigned char *nalu_dci, unsigned char **packetized_dci, unsigned int *packetized_dci_len)
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, };
1389 unsigned int idx = 0;
1391 // TODO: need to generalize this logic for finding multiple SPS and PPS sets and finding SPS/PPS by ANDing 0x1F
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));
1397 sps_len = pps_start - nalu_dci;
1399 GST_DEBUG ("sps length = %d\n", sps_len);
1401 sps_data = (unsigned char*) malloc (sps_len + 1);
1402 if (NULL == sps_data)
1404 GST_ERROR ("Failed to allocate memory..\n");
1410 strncpy ((char*)sps_data, (char *)nalu_dci, sps_len);
1411 sps_data[sps_len] = '\0';
1413 tmp_sps_ptr = sps_data;
1415 GST_DEBUG ("SPS data = %s\n", sps_data);
1417 pps_len = pps_end - pps_start;
1418 GST_DEBUG ("pps length = %d\n", pps_len);
1420 pps_data = (unsigned char*)malloc (pps_len + 1);
1421 if (NULL == pps_data)
1423 GST_ERROR ("Failed to allocate memory..\n");
1429 strncpy ((char*)pps_data, (char*)pps_start, pps_len);
1430 pps_data[pps_len] = '\0';
1431 tmp_pps_ptr = pps_data;
1433 GST_DEBUG ("PPS data = %s\n", pps_data);
1435 /* 6 bytes of metadata */
1436 *packetized_dci_len = 8;
1438 *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
1439 if (NULL == *packetized_dci)
1441 GST_ERROR ("Failed to allocate memory..\n");
1446 /* configurationVersion */
1447 (*packetized_dci)[0] = 0x01;
1449 /* AVCProfileIndication */
1450 memset (tmp, 0x00, 3);
1452 strncpy ((char*)tmp, (char*)sps_data+10, 2);
1455 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1458 GST_ERROR ("Failed to int from string...");
1462 (*packetized_dci)[1] = val;
1464 /* profile_compatibility*/
1465 memset (tmp, 0x00, 3);
1466 strncpy ((char*)tmp, (char*)sps_data+12, 2);
1468 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1471 GST_ERROR ("Failed to int from string...");
1474 (*packetized_dci)[2] = val;
1476 /* AVCLevelIndication */
1477 memset (tmp, 0x00, 3);
1478 strncpy ((char*)tmp, (char*)sps_data+14, 2);
1480 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1483 GST_ERROR ("Failed to int from string...");
1487 (*packetized_dci)[3] = val;
1489 /* Reserver (6) + LengthSizeMinusOne (2) */
1490 (*packetized_dci)[4] = 0xff; // hardcoding lengthoflength = 4 for present
1492 /* Reserver (3) + numOfSequenceParameterSets (5) */
1493 (*packetized_dci)[5] = 0xe1; // hardcoding numOfSequenceParameterSets = 1 for present
1495 /* avoiding NALU start code 0x00 00 00 01 */
1496 sps_len = sps_len -8;
1497 sps_data = sps_data + 8;
1499 (*packetized_dci)[6] = (sps_len >>1) >> 16;
1500 (*packetized_dci)[7] = (sps_len >>1);
1502 *packetized_dci_len += (sps_len/2);
1504 *packetized_dci = (unsigned char*) realloc (*packetized_dci, *packetized_dci_len);
1505 if (NULL == *packetized_dci)
1507 GST_ERROR ("Failed to allocate memory..\n");
1514 /* convert SPS data and store*/
1517 memset (tmp, 0x00, 3);
1518 strncpy ((char*)tmp, (char*)sps_data, 2);
1520 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1523 GST_ERROR ("Failed to int from string...");
1526 (*packetized_dci)[idx] = val;
1528 sps_len = sps_len - 2;
1529 //g_print ("val = 0x%02x, sps_len = %d, idx = %d\n", val, sps_len, idx);
1533 /* avoiding NALU start code 0x00 00 00 01 */
1534 pps_len = pps_len -8;
1535 pps_data = pps_data + 8;
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)
1542 GST_ERROR ("Failed to allocate memory..\n");
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);
1551 /* convert PPS data and store */
1554 memset (tmp, 0x00, 3);
1555 strncpy ((char*)tmp, (char*)pps_data, 2);
1557 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1560 GST_ERROR ("Failed to int from string...");
1564 (*packetized_dci)[idx] = val;
1566 pps_len = pps_len - 2;
1567 //g_print ("val = 0x%02x, pps_len = %d, idx = %d\n", val, pps_len, idx);
1575 g_print ("Complete VIDEO packetized_dci: 0x");
1576 while (idx < *packetized_dci_len)
1578 g_print ("%02x", (*packetized_dci)[idx]);
1596 if ((FALSE == bret) && *packetized_dci)
1598 free (*packetized_dci);
1599 *packetized_dci = NULL;
1605 /* code for sending NALU DCI as it is */
1606 guint nalu_dci_len = strlen ((char *)nalu_dci);
1607 unsigned char *nalu = nalu_dci;
1609 unsigned char tmp[3] = {0, };
1610 gboolean bret = TRUE;
1613 *packetized_dci_len = (nalu_dci_len/2);
1615 *packetized_dci = (unsigned char*) malloc (*packetized_dci_len);
1616 if (NULL == *packetized_dci)
1618 GST_ERROR ("Failed to allocate memory..\n");
1623 /* copy entire DCI*/
1624 while (nalu_dci_len)
1626 memset (tmp, 0x00, 3);
1627 strncpy ((char*)tmp, (char*)nalu, 2);
1629 bret = int_from_string ((char*)tmp, NULL, &val , 16);
1632 GST_ERROR ("Failed to int from string...");
1635 (*packetized_dci)[idx] = val;
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);
1644 g_print ("\n\n NEW DCI : 0x ");
1646 while (idx < *packetized_dci_len)
1648 g_print ("%02x", (*packetized_dci)[idx] );
1656 if ((FALSE == bret) && *packetized_dci)
1658 free (*packetized_dci);
1659 *packetized_dci = NULL;