diff options
author | Andreas Rheinhardt <andreas.rheinhardt@gmail.com> | 2019-12-29 09:57:44 +0100 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@gmail.com> | 2020-03-30 05:25:11 +0200 |
commit | 8c89fc18e6125ae0449091d82a2fe200ed848c43 (patch) | |
tree | facf0a1fad84fdb60ab4bd7a5ebd44f784baaaf0 | |
parent | e6ea75a38de192c3133b9eebe603979bffeed20b (diff) | |
download | ffmpeg-8c89fc18e6125ae0449091d82a2fe200ed848c43.tar.gz |
avformat/matroskaenc: Check for failure when writing SeekHead
mkv_write_seekhead() would up until now try to seek to the position where
the SeekHead ought to be written, write the SeekHead and seek back. The
first of these seeks was checked as was writing, yet the seek back was
unchecked. Moreover the return value of mkv_write_seekhead() was unchecked
(the ordinary return value was the position where the SeekHead was written).
This commit changes this: Everything is checked. In the unseekable case
(where the first seek may nevertheless work when it happens in the buffer)
a failure at the first seek is not considered an error. In any case,
failure to seek back is an error.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
-rw-r--r-- | libavformat/matroskaenc.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index c484d95c2f..8eb968445d 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -436,30 +436,31 @@ static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid, } /** - * Write the SeekHead to the file at the location reserved for it. + * Write the SeekHead to the file at the location reserved for it + * and seek back to the initial position. When error_on_seek_failure + * is not set, failure to seek to the position designated for the + * SeekHead is not considered an error; failure to seek back afterwards + * is always an error. * - * @return The file offset where the seekhead was written, - * -1 if an error occurred. + * @return 0 on success, < 0 on error. */ -static int64_t mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv) +static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv, + int error_on_seek_failure) { AVIOContext *dyn_cp; mkv_seekhead *seekhead = &mkv->seekhead; ebml_master seekentry; - int64_t currentpos, remaining; - int i; + int64_t currentpos, remaining, ret64; + int i, ret; currentpos = avio_tell(pb); - if (avio_seek(pb, seekhead->filepos, SEEK_SET) < 0) { - currentpos = -1; - goto fail; - } + if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0) + return error_on_seek_failure ? ret64 : 0; - if (start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD) < 0) { - currentpos = -1; - goto fail; - } + ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD); + if (ret < 0) + return ret; for (i = 0; i < seekhead->num_entries; i++) { mkv_seekhead_entry *entry = &seekhead->entries[i]; @@ -477,13 +478,11 @@ static int64_t mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv) remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); put_ebml_void(pb, remaining); - avio_seek(pb, currentpos, SEEK_SET); - currentpos = seekhead->filepos; + if ((ret64 = avio_seek(pb, currentpos, SEEK_SET)) < 0) + return ret64; -fail: - - return currentpos; + return 0; } static mkv_cues *mkv_start_cues(int64_t segment_offset) @@ -1927,8 +1926,11 @@ static int mkv_write_header(AVFormatContext *s) if (ret < 0) return ret; - if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - mkv_write_seekhead(pb, mkv); + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { + ret = mkv_write_seekhead(pb, mkv, 0); + if (ret < 0) + return ret; + } mkv->cues = mkv_start_cues(mkv->segment_offset); if (!mkv->cues) { @@ -2537,7 +2539,9 @@ static int mkv_write_trailer(AVFormatContext *s) mkv_add_seekhead_entry(mkv, MATROSKA_ID_CUES, cuespos); } - mkv_write_seekhead(pb, mkv); + ret = mkv_write_seekhead(pb, mkv, 1); + if (ret < 0) + return ret; // update the duration av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); |