summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/av1.c50
-rw-r--r--libavformat/av1.h13
-rw-r--r--libavformat/matroskaenc.c2
-rw-r--r--libavformat/movenc.c11
4 files changed, 58 insertions, 18 deletions
diff --git a/libavformat/av1.c b/libavformat/av1.c
index 709484b361..1e7a67d2f2 100644
--- a/libavformat/av1.c
+++ b/libavformat/av1.c
@@ -29,13 +29,20 @@
#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);
@@ -47,8 +54,16 @@ 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:
+ 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;
@@ -57,19 +72,35 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
buf += len;
}
+ if (offset)
+ *offset = state != OFFSET_IMPOSSIBLE ? off : -1;
+
return size;
}
-int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, int *size)
+int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
+{
+ return av1_filter_obus(pb, buf, size, NULL);
+}
+
+int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
+ int *size, int *offset)
{
AVIOContext pb;
uint8_t *buf;
- int len, ret;
+ int len, off, ret;
- len = ret = ff_av1_filter_obus(NULL, in, *size);
+ 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;
+
+ return 0;
+ }
buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
if (!buf)
@@ -77,13 +108,14 @@ int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, int *size)
ffio_init_context(&pb, buf, len, 1, NULL, NULL, NULL, NULL);
- ret = ff_av1_filter_obus(&pb, in, *size);
+ 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;
}
diff --git a/libavformat/av1.h b/libavformat/av1.h
index 6cc3fcaad2..dd5b47dc25 100644
--- a/libavformat/av1.h
+++ b/libavformat/av1.h
@@ -56,19 +56,24 @@ typedef struct AV1SequenceParameters {
int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size);
/**
- * Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and write
- * the resulting bitstream to a newly allocated data buffer.
+ * Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and return
+ * the result in a data buffer, avoiding allocations and copies if possible.
*
* @param in input data buffer
- * @param out pointer to pointer that will hold the allocated data buffer
+ * @param out pointer to pointer for the returned buffer. In case of success,
+ * it is independently allocated if and only if `*out` differs from in.
* @param size size of the input data buffer. The size of the resulting output
* data buffer will be written here
+ * @param offset offset of the returned data inside `*out`: It runs from
+ * `*out + offset` (inclusive) to `*out + offset + size`
+ * (exclusive); is zero if `*out` is independently allocated.
*
* @return 0 in case of success, a negative AVERROR code in case of failure.
* On failure, *out and *size are unchanged
* @note *out will be treated as unintialized on input and will not be freed.
*/
-int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, int *size);
+int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
+ int *size, int *offset);
/**
* Parses a Sequence Header from the the provided buffer.
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 20bad95262..618f07c769 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -2112,7 +2112,7 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb,
/* extradata is Annex B, assume the bitstream is too and convert it */
err = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL);
} else if (par->codec_id == AV_CODEC_ID_AV1) {
- err = ff_av1_filter_obus_buf(pkt->data, &data, &size);
+ err = ff_av1_filter_obus_buf(pkt->data, &data, &size, &offset);
} else if (par->codec_id == AV_CODEC_ID_WAVPACK) {
err = mkv_strip_wavpack(pkt->data, &data, &size);
} else
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index c0a5e1f2e0..9de8a61d2e 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5374,7 +5374,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
AVCodecParameters *par = trk->par;
AVProducerReferenceTime *prft;
unsigned int samples_in_chunk = 0;
- int size = pkt->size, ret = 0;
+ int size = pkt->size, ret = 0, offset = 0;
int prft_size;
uint8_t *reformatted_data = NULL;
@@ -5491,7 +5491,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
}
} else if (par->codec_id == AV_CODEC_ID_AV1) {
if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
- ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data, &size);
+ ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
+ &size, &offset);
if (ret < 0)
return ret;
avio_write(pb, reformatted_data, size);
@@ -5667,12 +5668,14 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
- reformatted_data, size);
+ reformatted_data ? reformatted_data + offset
+ : NULL, size);
end:
err:
- av_free(reformatted_data);
+ if (pkt->data != reformatted_data)
+ av_free(reformatted_data);
return ret;
}