]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/dashdec.c
avformat: Constify the API wrt AV(In|Out)putFormat
[ffmpeg] / libavformat / dashdec.c
index 693fc7372be5273af347585d2930e1e185591282..39e7810e42db98bd206918157da967fec223518e 100644 (file)
@@ -82,7 +82,7 @@ struct representation {
     AVFormatContext *ctx;
     int stream_index;
 
-    char id[20];
+    char *id;
     char *lang;
     int bandwidth;
     AVRational framerate;
@@ -155,13 +155,14 @@ typedef struct DASHContext {
     /* Flags for init section*/
     int is_init_section_common_video;
     int is_init_section_common_audio;
+    int is_init_section_common_subtitle;
 
 } DASHContext;
 
 static int ishttp(char *url)
 {
     const char *proto_name = avio_find_protocol_name(url);
-    return av_strstart(proto_name, "http", NULL);
+    return proto_name && av_strstart(proto_name, "http", NULL);
 }
 
 static int aligned(int val)
@@ -360,6 +361,7 @@ static void free_representation(struct representation *pls)
 
     av_freep(&pls->url_template);
     av_freep(&pls->lang);
+    av_freep(&pls->id);
     av_freep(&pls);
 }
 
@@ -841,7 +843,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
     char *val = NULL;
     xmlNodePtr baseurl_nodes[4];
     xmlNodePtr representation_node = node;
-    char *rep_id_val, *rep_bandwidth_val;
+    char *rep_bandwidth_val;
     enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
 
     // try get information from representation
@@ -875,8 +877,14 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
     representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate");
     representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL");
     representation_segmentlist_node = find_child_node_by_name(representation_node, "SegmentList");
-    rep_id_val        = xmlGetProp(representation_node, "id");
     rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth");
+    val               = xmlGetProp(representation_node, "id");
+    if (val) {
+        rep->id = av_strdup(val);
+        xmlFree(val);
+        if (!rep->id)
+            goto enomem;
+    }
 
     baseurl_nodes[0] = mpd_baseurl_node;
     baseurl_nodes[1] = period_baseurl_node;
@@ -885,7 +893,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
 
     ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4);
     c->max_url_size = aligned(c->max_url_size
-                              + (rep_id_val ? strlen(rep_id_val) : 0)
+                              + (rep->id ? strlen(rep->id) : 0)
                               + (rep_bandwidth_val ? strlen(rep_bandwidth_val) : 0));
     if (ret == AVERROR(ENOMEM) || ret == 0)
         goto free;
@@ -905,7 +913,9 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
                 goto enomem;
             }
             c->max_url_size = aligned(c->max_url_size  + strlen(val));
-            rep->init_section->url = get_content_url(baseurl_nodes, 4,  c->max_url_size, rep_id_val, rep_bandwidth_val, val);
+            rep->init_section->url = get_content_url(baseurl_nodes, 4,
+                                                     c->max_url_size, rep->id,
+                                                     rep_bandwidth_val, val);
             xmlFree(val);
             if (!rep->init_section->url)
                 goto enomem;
@@ -914,7 +924,9 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
         val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media");
         if (val) {
             c->max_url_size = aligned(c->max_url_size  + strlen(val));
-            rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, val);
+            rep->url_template = get_content_url(baseurl_nodes, 4,
+                                                c->max_url_size, rep->id,
+                                                rep_bandwidth_val, val);
             xmlFree(val);
         }
         val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset");
@@ -979,7 +991,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
             av_free(seg);
             goto free;
         }
-        seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL);
+        seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size,
+                                   rep->id, rep_bandwidth_val, NULL);
         if (!seg->url)
             goto enomem;
         seg->size = -1;
@@ -1013,8 +1026,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
         fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node);
         while (fragmenturl_node) {
             ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node,
-                                                baseurl_nodes,
-                                                rep_id_val,
+                                                baseurl_nodes, rep->id,
                                                 rep_bandwidth_val);
             if (ret < 0)
                 goto free;
@@ -1034,14 +1046,14 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
             }
         }
     } else {
-        av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id[%s] \n", rep_id_val);
+        av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id '%s' \n",
+               rep->id ? rep->id : "");
         goto free;
     }
 
     if (rep->fragment_duration > 0 && !rep->fragment_timescale)
         rep->fragment_timescale = 1;
     rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0;
-    strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id));
     rep->framerate = av_make_q(0, 0);
     if (type == AVMEDIA_TYPE_VIDEO) {
         char *rep_framerate_val = xmlGetProp(representation_node, "frameRate");
@@ -1068,8 +1080,6 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
         goto free;
 
 end:
-    if (rep_id_val)
-        xmlFree(rep_id_val);
     if (rep_bandwidth_val)
         xmlFree(rep_bandwidth_val);
 
@@ -1435,7 +1445,7 @@ static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c)
     } else if (c->is_live && pls->fragment_duration) {
         num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time)) * pls->fragment_timescale)  / pls->fragment_duration;
     } else if (pls->fragment_duration) {
-        num = pls->first_seq_no + (c->media_presentation_duration * pls->fragment_timescale) / pls->fragment_duration;
+        num = pls->first_seq_no + av_rescale_rnd(1, c->media_presentation_duration * pls->fragment_timescale, pls->fragment_duration, AV_ROUND_UP);
     }
 
     return num;
@@ -1625,8 +1635,15 @@ static struct fragment *get_current_fragment(struct representation *pls)
         }
     }
     if (seg) {
-        char *tmpfilename= av_mallocz(c->max_url_size);
+        char *tmpfilename;
+        if (!pls->url_template) {
+            av_log(pls->parent, AV_LOG_ERROR, "Cannot get fragment, missing template URL\n");
+            av_free(seg);
+            return NULL;
+        }
+        tmpfilename = av_mallocz(c->max_url_size);
         if (!tmpfilename) {
+            av_free(seg);
             return NULL;
         }
         ff_dash_fill_tmpl_params(tmpfilename, c->max_url_size, pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no));
@@ -1637,6 +1654,7 @@ static struct fragment *get_current_fragment(struct representation *pls)
             if (!seg->url) {
                 av_log(pls->parent, AV_LOG_ERROR, "Cannot resolve template url '%s'\n", pls->url_template);
                 av_free(tmpfilename);
+                av_free(seg);
                 return NULL;
             }
         }
@@ -1861,7 +1879,7 @@ static void close_demux_for_component(struct representation *pls)
 static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls)
 {
     DASHContext *c = s->priv_data;
-    ff_const59 AVInputFormat *in_fmt = NULL;
+    const AVInputFormat *in_fmt = NULL;
     AVDictionary  *in_fmt_opts = NULL;
     uint8_t *avio_ctx_buffer  = NULL;
     int ret = 0, i;
@@ -1992,7 +2010,12 @@ static int is_common_init_section_exist(struct representation **pls, int n_pls)
     url_offset = first_init_section->url_offset;
     size = pls[0]->init_section->size;
     for (i=0;i<n_pls;i++) {
-        if (av_strcasecmp(pls[i]->init_section->url,url) || pls[i]->init_section->url_offset != url_offset || pls[i]->init_section->size != size) {
+        if (!pls[i]->init_section)
+            continue;
+
+        if (av_strcasecmp(pls[i]->init_section->url, url) ||
+            pls[i]->init_section->url_offset != url_offset ||
+            pls[i]->init_section->size != size) {
             return 0;
         }
     }
@@ -2016,6 +2039,14 @@ static int copy_init_section(struct representation *rep_dest, struct representat
 
 static int dash_close(AVFormatContext *s);
 
+static void move_metadata(AVStream *st, const char *key, char **value)
+{
+    if (*value) {
+        av_dict_set(&st->metadata, key, *value, AV_DICT_DONT_STRDUP_VAL);
+        *value = NULL;
+    }
+}
+
 static int dash_read_header(AVFormatContext *s)
 {
     DASHContext *c = s->priv_data;
@@ -2079,11 +2110,11 @@ static int dash_read_header(AVFormatContext *s)
     }
 
     if (c->n_subtitles)
-        c->is_init_section_common_audio = is_common_init_section_exist(c->subtitles, c->n_subtitles);
+        c->is_init_section_common_subtitle = is_common_init_section_exist(c->subtitles, c->n_subtitles);
 
     for (i = 0; i < c->n_subtitles; i++) {
         rep = c->subtitles[i];
-        if (i > 0 && c->is_init_section_common_audio) {
+        if (i > 0 && c->is_init_section_common_subtitle) {
             ret = copy_init_section(rep, c->subtitles[0]);
             if (ret < 0)
                 goto fail;
@@ -2114,8 +2145,7 @@ static int dash_read_header(AVFormatContext *s)
         rep->assoc_stream = s->streams[rep->stream_index];
         if (rep->bandwidth > 0)
             av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0);
-        if (rep->id[0])
-            av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0);
+        move_metadata(rep->assoc_stream, "id", &rep->id);
     }
     for (i = 0; i < c->n_audios; i++) {
         rep = c->audios[i];
@@ -2123,23 +2153,15 @@ static int dash_read_header(AVFormatContext *s)
         rep->assoc_stream = s->streams[rep->stream_index];
         if (rep->bandwidth > 0)
             av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0);
-        if (rep->id[0])
-            av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0);
-        if (rep->lang) {
-            av_dict_set(&rep->assoc_stream->metadata, "language", rep->lang, 0);
-            av_freep(&rep->lang);
-        }
+        move_metadata(rep->assoc_stream, "id", &rep->id);
+        move_metadata(rep->assoc_stream, "language", &rep->lang);
     }
     for (i = 0; i < c->n_subtitles; i++) {
         rep = c->subtitles[i];
         av_program_add_stream_index(s, 0, rep->stream_index);
         rep->assoc_stream = s->streams[rep->stream_index];
-        if (rep->id[0])
-            av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0);
-        if (rep->lang) {
-            av_dict_set(&rep->assoc_stream->metadata, "language", rep->lang, 0);
-            av_freep(&rep->lang);
-        }
+        move_metadata(rep->assoc_stream, "id", &rep->id);
+        move_metadata(rep->assoc_stream, "language", &rep->lang);
     }
 
     return 0;