mirror of https://git.ffmpeg.org/ffmpeg.git
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:
parent
8254011b21
commit
1c37848f90
|
@ -179,7 +179,7 @@ static int write_representation(AVFormatContext *s, AVStream *stream, char *id,
|
||||||
AVDictionaryEntry *bandwidth = av_dict_get(stream->metadata, BANDWIDTH, NULL, 0);
|
AVDictionaryEntry *bandwidth = av_dict_get(stream->metadata, BANDWIDTH, NULL, 0);
|
||||||
if ((w->is_live && (!filename)) ||
|
if ((w->is_live && (!filename)) ||
|
||||||
(!w->is_live && (!irange || !cues_start || !cues_end || !filename || !bandwidth))) {
|
(!w->is_live && (!irange || !cues_start || !cues_end || !filename || !bandwidth))) {
|
||||||
return -1;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
avio_printf(s->pb, "<Representation id=\"%s\"", id);
|
avio_printf(s->pb, "<Representation id=\"%s\"", id);
|
||||||
// FIXME: For live, This should be obtained from the input file or as an AVOption.
|
// 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;
|
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,
|
* Parses a live header filename and computes the representation id,
|
||||||
* initialization pattern and the media pattern. Pass NULL if you don't want to
|
* 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;
|
underscore_pos = temp_pos + 1;
|
||||||
temp_pos = av_stristr(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, ".");
|
period_pos = av_stristr(underscore_pos, ".");
|
||||||
if (!period_pos) return -1;
|
if (!period_pos) return AVERROR_INVALIDDATA;
|
||||||
*(underscore_pos - 1) = 0;
|
*(underscore_pos - 1) = 0;
|
||||||
if (representation_id) {
|
if (representation_id) {
|
||||||
*representation_id = av_malloc(period_pos - underscore_pos + 1);
|
*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++) {
|
for (i = 0; i < as->nb_streams; i++) {
|
||||||
char *representation_id = NULL;
|
char *representation_id = NULL;
|
||||||
|
int ret;
|
||||||
if (w->is_live) {
|
if (w->is_live) {
|
||||||
AVDictionaryEntry *filename =
|
AVDictionaryEntry *filename =
|
||||||
av_dict_get(s->streams[as->streams[i]]->metadata, FILENAME, NULL, 0);
|
av_dict_get(s->streams[as->streams[i]]->metadata, FILENAME, NULL, 0);
|
||||||
if (!filename ||
|
if (!filename ||
|
||||||
parse_filename(filename->value, &representation_id, NULL, NULL)) {
|
(ret = parse_filename(filename->value, &representation_id, NULL, NULL))) {
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
representation_id = av_asprintf("%d", w->representation_id++);
|
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,
|
ret = write_representation(s, s->streams[as->streams[i]],
|
||||||
!width_in_as, !height_in_as, !sample_rate_in_as);
|
representation_id, !width_in_as,
|
||||||
|
!height_in_as, !sample_rate_in_as);
|
||||||
|
if (ret) return ret;
|
||||||
av_free(representation_id);
|
av_free(representation_id);
|
||||||
}
|
}
|
||||||
avio_printf(s->pb, "</AdaptationSet>\n");
|
avio_printf(s->pb, "</AdaptationSet>\n");
|
||||||
|
@ -416,9 +429,11 @@ static int parse_adaptation_sets(AVFormatContext *s)
|
||||||
if (*p == ' ')
|
if (*p == ' ')
|
||||||
continue;
|
continue;
|
||||||
else if (state == new_set && !strncmp(p, "id=", 3)) {
|
else if (state == new_set && !strncmp(p, "id=", 3)) {
|
||||||
w->as = av_realloc(w->as, sizeof(*w->as) * ++w->nb_as);
|
void *mem = av_realloc(w->as, sizeof(*w->as) * (w->nb_as + 1));
|
||||||
if (w->as == NULL)
|
if (mem == NULL)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
w->as = mem;
|
||||||
|
++w->nb_as;
|
||||||
w->as[w->nb_as - 1].nb_streams = 0;
|
w->as[w->nb_as - 1].nb_streams = 0;
|
||||||
w->as[w->nb_as - 1].streams = NULL;
|
w->as[w->nb_as - 1].streams = NULL;
|
||||||
p += 3; // consume "id="
|
p += 3; // consume "id="
|
||||||
|
@ -453,8 +468,13 @@ static int webm_dash_manifest_write_header(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double start = 0.0;
|
double start = 0.0;
|
||||||
|
int ret;
|
||||||
WebMDashMuxContext *w = s->priv_data;
|
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);
|
write_header(s);
|
||||||
avio_printf(s->pb, "<Period id=\"0\"");
|
avio_printf(s->pb, "<Period id=\"0\"");
|
||||||
avio_printf(s->pb, " start=\"PT%gS\"", start);
|
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");
|
avio_printf(s->pb, " >\n");
|
||||||
|
|
||||||
for (i = 0; i < w->nb_as; i++) {
|
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");
|
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)
|
static int webm_dash_manifest_write_trailer(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
WebMDashMuxContext *w = s->priv_data;
|
free_adaptation_sets(s);
|
||||||
int i;
|
|
||||||
for (i = 0; i < w->nb_as; i++) {
|
|
||||||
av_freep(&w->as[i].streams);
|
|
||||||
}
|
|
||||||
av_freep(&w->as);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue