]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/av1.c
avformat/dashenc: Remove deprecated min_seg_duration option
[ffmpeg] / libavformat / av1.c
index 43e40453c83c4f1de30fc1472f5eae3c105fc742..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 "libavcodec/put_bits.h"
 #include "av1.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);
@@ -45,35 +54,70 @@ 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);
-    if (ret < 0)
+    len = ret = av1_filter_obus(NULL, in, *size, &off);
+    if (ret < 0) {
         return ret;
+    }
+    if (off >= 0) {
+        *out    = (uint8_t *)in;
+        *size   = len;
+        *offset = off;
 
-    av_freep(out);
-    *size = avio_close_dyn_buf(pb, out);
+        return 0;
+    }
 
-    return ret;
+    buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!buf)
+        return AVERROR(ENOMEM);
+
+    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;
 }
 
 static inline void uvlc(GetBitContext *gb)
@@ -94,9 +138,12 @@ static inline void uvlc(GetBitContext *gb)
 
 static int parse_color_config(AV1SequenceParameters *seq_params, GetBitContext *gb)
 {
-    seq_params->high_bitdepth = get_bits1(gb);
-    if (seq_params->profile == FF_PROFILE_AV1_PROFESSIONAL && seq_params->high_bitdepth)
-        seq_params->twelve_bit = get_bits1(gb);
+    int twelve_bit = 0;
+    int high_bitdepth = get_bits1(gb);
+    if (seq_params->profile == FF_PROFILE_AV1_PROFESSIONAL && high_bitdepth)
+        twelve_bit = get_bits1(gb);
+
+    seq_params->bitdepth = 8 + (high_bitdepth * 2) + (twelve_bit * 2);
 
     if (seq_params->profile == FF_PROFILE_AV1_HIGH)
         seq_params->monochrome = 0;
@@ -135,7 +182,7 @@ static int parse_color_config(AV1SequenceParameters *seq_params, GetBitContext *
             seq_params->chroma_subsampling_x = 0;
             seq_params->chroma_subsampling_y = 0;
         } else {
-            if (seq_params->twelve_bit) {
+            if (twelve_bit) {
                 seq_params->chroma_subsampling_x = get_bits1(gb);
                 if (seq_params->chroma_subsampling_x)
                     seq_params->chroma_subsampling_y = get_bits1(gb);
@@ -251,7 +298,7 @@ static int parse_sequence_header(AV1SequenceParameters *seq_params, const uint8_
     if (!reduced_still_picture_header) {
         int enable_order_hint, seq_force_screen_content_tools;
 
-        skip_bits(&gb, 4); // enable_intraintra_compound (1), enable_masked_compound (1)
+        skip_bits(&gb, 4); // enable_interintra_compound (1), enable_masked_compound (1)
                            // enable_warped_motion (1), enable_dual_filter (1)
 
         enable_order_hint = get_bits1(&gb);
@@ -316,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 = NULL, *meta = NULL;
+    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;
@@ -328,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,
@@ -354,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) {
@@ -370,8 +429,7 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
         buf  += len;
     }
 
-    seq_size  = avio_close_dyn_buf(seq_pb, &seq);
-    if (!seq_size) {
+    if (!nb_seq) {
         ret = AVERROR_INVALIDDATA;
         goto fail;
     }
@@ -383,8 +441,8 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
     put_bits(&pbc, 3, seq_params.profile);
     put_bits(&pbc, 5, seq_params.level);
     put_bits(&pbc, 1, seq_params.tier);
-    put_bits(&pbc, 1, seq_params.high_bitdepth);
-    put_bits(&pbc, 1, seq_params.twelve_bit);
+    put_bits(&pbc, 1, seq_params.bitdepth > 8);
+    put_bits(&pbc, 1, seq_params.bitdepth == 12);
     put_bits(&pbc, 1, seq_params.monochrome);
     put_bits(&pbc, 1, seq_params.chroma_subsampling_x);
     put_bits(&pbc, 1, seq_params.chroma_subsampling_y);
@@ -395,17 +453,12 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
     avio_write(pb, header, sizeof(header));
     avio_write(pb, seq, seq_size);
 
-    meta_size = avio_close_dyn_buf(meta_pb, &meta);
+    meta_size = avio_get_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);
+    ffio_free_dyn_buf(&meta_pb);
 
     return ret;
 }