[FFmpeg-devel,2/2] avformat/av1: reorder av1C OBUs before writting them

Submitted by James Almer on July 30, 2018, 11:35 p.m.

Details

Message ID 20180730233540.11100-2-jamrial@gmail.com
State New
Headers show

Commit Message

James Almer July 30, 2018, 11:35 p.m.
Make sure Sequence Header is first, and only allow one of its kind.

Signed-off-by: James Almer <jamrial@gmail.com>
---
Both these patches should be applied before "[PATCH 5/5] avformat/matroskaenc:
update AV1 support"

Was not planning on sending them until
https://github.com/AOMediaCodec/av1-isobmff/issues/50 and all the quoted issues
were dealt with, but might as well just get this up to date to the current
revision in the meantime.

 libavformat/av1.c | 61 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/av1.c b/libavformat/av1.c
index 7c55a100bf..14e2abd3ff 100644
--- a/libavformat/av1.c
+++ b/libavformat/av1.c
@@ -79,33 +79,72 @@  int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size)
 
 int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
 {
+    AVIOContext *seq_pb = NULL, *meta_pb = NULL;
+    uint8_t *seq = NULL, *meta = NULL;
     int64_t obu_size;
     int start_pos, type, temporal_id, spatial_id;
+    int ret, nb_seq = 0, seq_size, meta_size;
 
     if (size <= 0)
         return AVERROR_INVALIDDATA;
 
+    ret = avio_open_dyn_buf(&seq_pb);
+    if (ret < 0)
+        return ret;
+    ret = avio_open_dyn_buf(&meta_pb);
+    if (ret < 0)
+        goto fail;
+
     while (size > 0) {
-        int ret = parse_obu_header(buf, size, &obu_size, &start_pos,
+        int len = parse_obu_header(buf, size, &obu_size, &start_pos,
                                    &type, &temporal_id, &spatial_id);
-        if (ret < 0)
-            return ret;
-
-        obu_size += start_pos;
-        if (obu_size > INT_MAX)
-            return AVERROR_INVALIDDATA;
+        if (len < 0) {
+            ret = AVERROR_INVALIDDATA;
+            goto fail;
+        }
 
         switch (type) {
         case AV1_OBU_SEQUENCE_HEADER:
+            nb_seq++;
+
+            if (!obu_size || nb_seq > 1) {
+                ret = AVERROR_INVALIDDATA;
+                goto fail;
+            }
+            avio_write(seq_pb, buf, len);
+            break;
         case AV1_OBU_METADATA:
-            avio_write(pb, buf, obu_size);
+            if (!obu_size) {
+                ret = AVERROR_INVALIDDATA;
+                goto fail;
+            }
+            avio_write(meta_pb, buf, len);
             break;
         default:
             break;
         }
-        size -= obu_size;
-        buf  += obu_size;
+        size -= len;
+        buf  += len;
     }
 
-    return 0;
+    seq_size  = avio_close_dyn_buf(seq_pb, &seq);
+    if (!seq_size) {
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+    avio_write(pb, seq, seq_size);
+
+    meta_size = avio_close_dyn_buf(meta_pb, &meta);
+    if (meta_size)
+        avio_write(pb, meta, meta_size);
+
+fail:
+    if (!seq)
+        avio_close_dyn_buf(seq_pb, &seq);
+    if (!meta)
+        avio_close_dyn_buf(meta_pb, &meta);
+    av_free(seq);
+    av_free(meta);
+
+    return ret;
 }