webmdashenc: Add better error handling
authorVignesh Venkatasubramanian <vigneshv@google.com>
Fri, 17 Apr 2015 00:32:21 +0000 (17:32 -0700)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 17 Apr 2015 02:48:29 +0000 (04:48 +0200)
Return appropriate error codes and propagate the error codes from
helper functions to the outer calls. Also fix a potential leak in
call to av_realloc.

Signed-off-by: Vignesh Venkatasubramanian <vigneshv@google.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavformat/webmdashenc.c

index c5d7158..a8eb8ac 100644 (file)
@@ -179,7 +179,7 @@ static int write_representation(AVFormatContext *s, AVStream *stream, char *id,
     AVDictionaryEntry *bandwidth = av_dict_get(stream->metadata, BANDWIDTH, NULL, 0);
     if ((w->is_live && (!filename)) ||
         (!w->is_live && (!irange || !cues_start || !cues_end || !filename || !bandwidth))) {
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
     avio_printf(s->pb, "<Representation id=\"%s\"", id);
     // FIXME: For live, This should be obtained from the input file or as an AVOption.
@@ -252,6 +252,16 @@ static int check_matching_sample_rate(AVFormatContext *s, AdaptationSet *as) {
     return 1;
 }
 
+static void free_adaptation_sets(AVFormatContext *s) {
+    WebMDashMuxContext *w = s->priv_data;
+    int i;
+    for (i = 0; i < w->nb_as; i++) {
+        av_freep(&w->as[i].streams);
+    }
+    av_freep(&w->as);
+    w->nb_as = 0;
+}
+
 /*
  * Parses a live header filename and computes the representation id,
  * initialization pattern and the media pattern. Pass NULL if you don't want to
@@ -274,9 +284,9 @@ static int parse_filename(char *filename, char **representation_id,
         underscore_pos = temp_pos + 1;
         temp_pos = av_stristr(temp_pos + 1, "_");
     }
-    if (!underscore_pos) return -1;
+    if (!underscore_pos) return AVERROR_INVALIDDATA;
     period_pos = av_stristr(underscore_pos, ".");
-    if (!period_pos) return -1;
+    if (!period_pos) return AVERROR_INVALIDDATA;
     *(underscore_pos - 1) = 0;
     if (representation_id) {
         *representation_id = av_malloc(period_pos - underscore_pos + 1);
@@ -373,19 +383,22 @@ static int write_adaptation_set(AVFormatContext *s, int as_index)
 
     for (i = 0; i < as->nb_streams; i++) {
         char *representation_id = NULL;
+        int ret;
         if (w->is_live) {
             AVDictionaryEntry *filename =
                 av_dict_get(s->streams[as->streams[i]]->metadata, FILENAME, NULL, 0);
             if (!filename ||
-                parse_filename(filename->value, &representation_id, NULL, NULL)) {
-                return -1;
+                (ret = parse_filename(filename->value, &representation_id, NULL, NULL))) {
+                return ret;
             }
         } else {
             representation_id = av_asprintf("%d", w->representation_id++);
-            if (!representation_id) return -1;
+            if (!representation_id) return AVERROR(ENOMEM);
         }
-        write_representation(s, s->streams[as->streams[i]], representation_id,
-                             !width_in_as, !height_in_as, !sample_rate_in_as);
+        ret = write_representation(s, s->streams[as->streams[i]],
+                                   representation_id, !width_in_as,
+                                   !height_in_as, !sample_rate_in_as);
+        if (ret) return ret;
         av_free(representation_id);
     }
     avio_printf(s->pb, "</AdaptationSet>\n");
@@ -416,9 +429,11 @@ static int parse_adaptation_sets(AVFormatContext *s)
         if (*p == ' ')
             continue;
         else if (state == new_set && !strncmp(p, "id=", 3)) {
-            w->as = av_realloc(w->as, sizeof(*w->as) * ++w->nb_as);
-            if (w->as == NULL)
+            void *mem = av_realloc(w->as, sizeof(*w->as) * (w->nb_as + 1));
+            if (mem == NULL)
                 return AVERROR(ENOMEM);
+            w->as = mem;
+            ++w->nb_as;
             w->as[w->nb_as - 1].nb_streams = 0;
             w->as[w->nb_as - 1].streams = NULL;
             p += 3; // consume "id="
@@ -453,8 +468,13 @@ static int webm_dash_manifest_write_header(AVFormatContext *s)
 {
     int i;
     double start = 0.0;
+    int ret;
     WebMDashMuxContext *w = s->priv_data;
-    parse_adaptation_sets(s);
+    ret = parse_adaptation_sets(s);
+    if (ret < 0) {
+        free_adaptation_sets(s);
+        return ret;
+    }
     write_header(s);
     avio_printf(s->pb, "<Period id=\"0\"");
     avio_printf(s->pb, " start=\"PT%gS\"", start);
@@ -464,7 +484,11 @@ static int webm_dash_manifest_write_header(AVFormatContext *s)
     avio_printf(s->pb, " >\n");
 
     for (i = 0; i < w->nb_as; i++) {
-        if (write_adaptation_set(s, i) < 0) return -1;
+        ret = write_adaptation_set(s, i);
+        if (ret < 0) {
+            free_adaptation_sets(s);
+            return ret;
+        }
     }
 
     avio_printf(s->pb, "</Period>\n");
@@ -479,12 +503,7 @@ static int webm_dash_manifest_write_packet(AVFormatContext *s, AVPacket *pkt)
 
 static int webm_dash_manifest_write_trailer(AVFormatContext *s)
 {
-    WebMDashMuxContext *w = s->priv_data;
-    int i;
-    for (i = 0; i < w->nb_as; i++) {
-        av_freep(&w->as[i].streams);
-    }
-    av_freep(&w->as);
+    free_adaptation_sets(s);
     return 0;
 }