summaryrefslogtreecommitdiff
path: root/libavformat/av1.c
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>2020-01-24 23:48:33 +0100
committerJames Almer <jamrial@gmail.com>2020-01-26 12:41:32 -0300
commita3e43e0cf3d368663acbfc56c294216651f7fbab (patch)
tree1cab12cc83626143fc41e611f122c34916cd991c /libavformat/av1.c
parent2eee34372ff2ae4a4efc348362b904632b1e7cee (diff)
avformat/av1: Avoid allocation + copying when filtering OBUs
Certain types of OBUs are stripped away before muxing into Matroska and ISOBMFF; there are two functions to do this: One that outputs by directly writing in an AVIOContext and one that returns a freshly allocated buffer with the units not stripped away copied into it. The latter option is bad for performance, especially when the input does already not contain any of the units intended to be stripped away (this covers typical remuxing scenarios). Therefore this commit changes this by avoiding allocating and copying when possible; it is possible if the OBUs to be retained are consecutively in the input buffer (without an OBU to be discarded between them). In this case, the caller receives the offset as well as the length of the part of the buffer that contains the units to be kept. This also avoids copying when e.g. the only unit to be discarded is a temporal delimiter at the front. For a 22.7mb/s file with average framesize 113 kB this improved the time for the calls to ff_av1_filter_obus_buf() when writing Matroska from 313319 decicycles to 2368 decicycles; for another file with 1.5mb/s (average framesize 7.3 kB) it improved from 34539 decicycles to 1922 decicyles. For these files the only units that needed to be stripped away were temporal unit delimiters at the front. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com> Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavformat/av1.c')
-rw-r--r--libavformat/av1.c50
1 files changed, 41 insertions, 9 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;
}