[FFmpeg-devel] [PATCH 6/6] avformat/av1: Improve filtering AV1 OBUs

James Almer jamrial at gmail.com
Sun Jan 26 17:53:59 EET 2020


On 1/23/2020 1:08 PM, Andreas Rheinhardt wrote:
> Both ISOBMFF as well as Matroska require certain OBUs to be stripped
> before muxing them. There are two functions for this purpose; one writes
> directly into an AVIOContext, the other returns a freshly allocated
> buffer with the undesired units stripped away.
> 
> The latter one actually relies on the former by means of a dynamic
> buffer. This has several drawbacks: The underlying buffer might have to
> be reallocated multiple times; the buffer will eventually be
> overallocated; the data will not be directly copied into the final
> buffer, but rather first in the write buffer (in chunks of 1024 byte)
> and then written in these chunks. Moreover, the API for dynamic buffers
> is defective wrt error checking and as a consequence, the earlier code
> would indicate a length of -AV_INPUT_BUFFER_PADDING_SIZE on allocation
> failure, but it would not return an error; there would also be no error
> in case the arbitrary limit of INT_MAX/2 that is currently imposed on
> dynamic buffers is hit.
> 
> This commit changes this: The buffer is now parsed twice, once to get
> the precise length which will then be allocated; and once to actually
> write the data.
> 
> 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
> 753662 decicycles to 313319 decicycles (based upon 50 runs a 2048 frames
> each); for another 1.5mb/s file (with average framesize of 7.3 kB) it
> improved from 79270 decicycles to 34539 decicycles (based upon 50 runs a
> 4096 frames).
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
> ---
>  libavformat/av1.c | 32 +++++++++++++++++++++-----------
>  libavformat/av1.h |  4 ++--
>  2 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/libavformat/av1.c b/libavformat/av1.c
> index 4ff4bffddf..80c049f62f 100644
> --- a/libavformat/av1.c
> +++ b/libavformat/av1.c
> @@ -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"
> @@ -48,7 +49,8 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
>          case AV1_OBU_PADDING:
>              break;
>          default:
> -            avio_write(pb, buf, len);
> +            if (pb)
> +                avio_write(pb, buf, len);
>              size += len;
>              break;
>          }
> @@ -58,23 +60,31 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
>      return size;
>  }
>  
> -int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size)
> +int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, int *size)
>  {
> -    AVIOContext *pb;
> -    int ret;
> +    AVIOContext pb;
> +    uint8_t *buf;
> +    int len, ret;
>  
> -    ret = avio_open_dyn_buf(&pb);
> -    if (ret < 0)
> -        return ret;
> -
> -    ret = ff_av1_filter_obus(pb, buf, *size);
> +    len = ret = ff_av1_filter_obus(NULL, in, *size);
>      if (ret < 0) {
> -        ffio_free_dyn_buf(&pb);
>          return ret;
>      }
>  
> +    buf = av_malloc((size_t)len + AV_INPUT_BUFFER_PADDING_SIZE);

We never cast the arguments to av_malloc() to size_t, and len here is
guaranteed to be <= size by parse_obu_header(), so it's unnecessary.

Removed it and pushed the patch. Thanks.

> +    if (!buf)
> +        return AVERROR(ENOMEM);
> +
> +    ffio_init_context(&pb, buf, len, 1, NULL, NULL, NULL, NULL);
> +
> +    ret = ff_av1_filter_obus(&pb, in, *size);
> +    av_assert1(ret == len);
> +
> +    memset(buf + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
> +
>      av_freep(out);
> -    *size = avio_close_dyn_buf(pb, out);
> +    *out  = buf;
> +    *size = len;
>  
>      return 0;
>  }
> diff --git a/libavformat/av1.h b/libavformat/av1.h
> index 0578435376..acba12612c 100644
> --- a/libavformat/av1.h
> +++ b/libavformat/av1.h
> @@ -61,7 +61,7 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size);
>   *
>   * @param pb pointer to the AVIOContext where the filtered bitstream shall be
>   *           written
> - * @param buf input data buffer
> + * @param in input data buffer
>   * @param out pointer to pointer that will hold the allocated data buffer
>   * @param size size of the input data buffer. The size of the resulting output
>                 data buffer will be written here
> @@ -69,7 +69,7 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size);
>   * @return 0 in case of success, a negative AVERROR code in case of failure.
>   *         On failure, out and size are unchanged
>   */
> -int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size);
> +int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, int *size);
>  
>  /**
>   * Parses a Sequence Header from the the provided buffer.
> 



More information about the ffmpeg-devel mailing list