[FFmpeg-devel] [PATCH 09/20] avformat/matroskaenc: Check for failure when writing SeekHead

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Wed Jan 1 02:58:26 EET 2020


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 at gmail.com>
---
 libavformat/matroskaenc.c | 52 ++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index cecf7589e5..c7948fb643 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -436,31 +436,35 @@ 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 (start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD) < 0) {
-        currentpos = -1;
-        goto fail;
+    if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0) {
+        if (error_on_seek_failure)
+            return ret64;
+        goto seek_back;
     }
 
+    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 +481,12 @@ 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;
+seek_back:
+    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)
@@ -1925,8 +1928,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) {
@@ -2527,7 +2533,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);
-- 
2.20.1



More information about the ffmpeg-devel mailing list