]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/av1.c
avcodec/vaapi: Remove old and deprecated VAAPI context and header
[ffmpeg] / libavformat / av1.c
index 4ff4bffddf3861aaab799bde97fe8634f8c27299..5512c4e0f7748a53b9957ca435879a26966bf995 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/avassert.h"
 #include "libavutil/mem.h"
 #include "libavcodec/av1.h"
 #include "libavcodec/av1_parse.h"
 #include "avio.h"
 #include "avio_internal.h"
 
-int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
+static int av1_filter_obus(AVIOContext *pb, const uint8_t *buf,
+                           int size, int *offset)
 {
-    const uint8_t *end = buf + size;
+    const uint8_t *start = buf, *end = buf + size;
     int64_t obu_size;
-    int start_pos, type, temporal_id, spatial_id;
-
-    size = 0;
+    int off, start_pos, type, temporal_id, spatial_id;
+    enum {
+        START_NOT_FOUND,
+        START_FOUND,
+        END_FOUND,
+        OFFSET_IMPOSSIBLE,
+    } state = START_NOT_FOUND;
+
+    off = size = 0;
     while (buf < end) {
         int len = parse_obu_header(buf, end - buf, &obu_size, &start_pos,
                                    &type, &temporal_id, &spatial_id);
@@ -46,35 +54,68 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
         case AV1_OBU_REDUNDANT_FRAME_HEADER:
         case AV1_OBU_TILE_LIST:
         case AV1_OBU_PADDING:
+            if (state == START_FOUND)
+                state = END_FOUND;
             break;
         default:
-            avio_write(pb, buf, len);
+            if (state == START_NOT_FOUND) {
+                off   = buf - start;
+                state = START_FOUND;
+            } else if (state == END_FOUND) {
+                state = OFFSET_IMPOSSIBLE;
+            }
+            if (pb)
+                avio_write(pb, buf, len);
             size += len;
             break;
         }
         buf += len;
     }
 
+    if (offset)
+        *offset = state != OFFSET_IMPOSSIBLE ? off : -1;
+
     return size;
 }
 
-int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size)
+int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
 {
-    AVIOContext *pb;
-    int ret;
+    return av1_filter_obus(pb, buf, size, NULL);
+}
 
-    ret = avio_open_dyn_buf(&pb);
-    if (ret < 0)
-        return ret;
+int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
+                           int *size, int *offset)
+{
+    AVIOContext pb;
+    uint8_t *buf;
+    int len, off, ret;
 
-    ret = ff_av1_filter_obus(pb, buf, *size);
+    len = ret = av1_filter_obus(NULL, in, *size, &off);
     if (ret < 0) {
-        ffio_free_dyn_buf(&pb);
         return ret;
     }
+    if (off >= 0) {
+        *out    = (uint8_t *)in;
+        *size   = len;
+        *offset = off;
+
+        return 0;
+    }
+
+    buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!buf)
+        return AVERROR(ENOMEM);
 
-    av_freep(out);
-    *size = avio_close_dyn_buf(pb, out);
+    ffio_init_context(&pb, buf, len, 1, NULL, NULL, NULL, NULL);
+
+    ret = av1_filter_obus(&pb, in, *size, NULL);
+    av_assert1(ret == len);
+
+    memset(buf + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+    *out  = buf;
+    *size = len;
+    *offset = 0;
 
     return 0;
 }
@@ -322,11 +363,11 @@ int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int
 
 int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
 {
-    AVIOContext *seq_pb = NULL, *meta_pb = NULL;
+    AVIOContext *meta_pb;
     AV1SequenceParameters seq_params;
     PutBitContext pbc;
-    uint8_t header[4];
-    uint8_t *seq, *meta;
+    uint8_t header[4], *meta;
+    const uint8_t *seq;
     int64_t obu_size;
     int start_pos, type, temporal_id, spatial_id;
     int ret, nb_seq = 0, seq_size, meta_size;
@@ -334,12 +375,23 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
     if (size <= 0)
         return AVERROR_INVALIDDATA;
 
-    ret = avio_open_dyn_buf(&seq_pb);
-    if (ret < 0)
-        return ret;
+    if (buf[0] & 0x80) {
+        // first bit is nonzero, the passed data does not consist purely of
+        // OBUs. Expect that the data is already in AV1CodecConfigurationRecord
+        // format.
+        int config_record_version = buf[0] & 0x7f;
+        if (config_record_version != 1 || size < 4) {
+            return AVERROR_INVALIDDATA;
+        }
+
+        avio_write(pb, buf, size);
+
+        return 0;
+    }
+
     ret = avio_open_dyn_buf(&meta_pb);
     if (ret < 0)
-        goto fail;
+        return ret;
 
     while (size > 0) {
         int len = parse_obu_header(buf, size, &obu_size, &start_pos,
@@ -360,7 +412,8 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
             if (ret < 0)
                 goto fail;
 
-            avio_write(seq_pb, buf, len);
+            seq      = buf;
+            seq_size = len;
             break;
         case AV1_OBU_METADATA:
             if (!obu_size) {
@@ -376,8 +429,7 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
         buf  += len;
     }
 
-    seq_size  = avio_get_dyn_buf(seq_pb, &seq);
-    if (!seq_size) {
+    if (!nb_seq) {
         ret = AVERROR_INVALIDDATA;
         goto fail;
     }
@@ -406,7 +458,6 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
         avio_write(pb, meta, meta_size);
 
 fail:
-    ffio_free_dyn_buf(&seq_pb);
     ffio_free_dyn_buf(&meta_pb);
 
     return ret;