webmdashenc: Add better error handling

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>
This commit is contained in:
Vignesh Venkatasubramanian 2015-04-16 17:32:21 -07:00 committed by Michael Niedermayer
parent 8254011b21
commit 1c37848f90
1 changed files with 37 additions and 18 deletions

View 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;
}