[FFmpeg-devel] [PATCH v3 1/4] avcodec/webp: compatibilize with avformat/webpdec
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Sun Sep 12 23:24:10 EEST 2021
Martin Reboredo:
> The demuxer implementation splits some RIFF chunks (`RIFF`/`VP8X`/`ANMF` + frame chunk) or sends the picture chunks separately.
> The internal WebP decoder waits for a complete file instead and by consequence it needs to be modified to support this kind of fractioned input.
>
> Fixes FATE tests with WebP.
>
> Signed-off-by: Martin Reboredo <yakoyoku at gmail.com>
> ---
> libavcodec/webp.c | 41 ++++++++++++++++++++++++++++++++---------
> 1 file changed, 32 insertions(+), 9 deletions(-)
>
> diff --git a/libavcodec/webp.c b/libavcodec/webp.c
> index 3efd4438d9..7858d69481 100644
> --- a/libavcodec/webp.c
> +++ b/libavcodec/webp.c
> @@ -40,6 +40,7 @@
> * - XMP metadata
> */
>
> +#include "libavformat/internal.h"
> #include "libavutil/imgutils.h"
>
> #define BITSTREAM_READER_LE
> @@ -191,6 +192,7 @@ typedef struct WebPContext {
> AVFrame *alpha_frame; /* AVFrame for alpha data decompressed from VP8L */
> AVPacket *pkt; /* AVPacket to be passed to the underlying VP8 decoder */
> AVCodecContext *avctx; /* parent AVCodecContext */
> + int read_header; /* RIFF header has been read */
> int initialized; /* set once the VP8 context is initialized */
> int has_alpha; /* has a separate alpha chunk */
> enum AlphaCompression alpha_compression; /* compression type for alpha chunk */
> @@ -1353,17 +1355,36 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
> if (bytestream2_get_bytes_left(&gb) < 12)
> return AVERROR_INVALIDDATA;
>
> - if (bytestream2_get_le32(&gb) != MKTAG('R', 'I', 'F', 'F')) {
> - av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n");
> - return AVERROR_INVALIDDATA;
> - }
> -
> + chunk_type = bytestream2_get_le32(&gb);
> chunk_size = bytestream2_get_le32(&gb);
> - if (bytestream2_get_bytes_left(&gb) < chunk_size)
> - return AVERROR_INVALIDDATA;
>
> - if (bytestream2_get_le32(&gb) != MKTAG('W', 'E', 'B', 'P')) {
> - av_log(avctx, AV_LOG_ERROR, "missing WEBP tag\n");
> + for (int i = 0; !s->read_header && i < 4; i++) {
> + ff_lock_avformat();
1. Why are you locking avformat? What is this lock supposed to guard?
2. You can't lock avformat from avcodec at all: The ff_-prefix means
that this function is intra-library (in this case libavformat) only. It
will work with static builds, but it won't work with shared builds.
> +
> + if (s->read_header) {
> + ff_unlock_avformat();
> + break;
> + }
> +
> + if (chunk_type == MKTAG('R', 'I', 'F', 'F')) {
> + int left = bytestream2_get_bytes_left(&gb);
> + if (left < chunk_size && left != 22) {
> + ff_unlock_avformat();
> + return AVERROR_INVALIDDATA;
> + }
> + if (bytestream2_get_le32(&gb) != MKTAG('W', 'E', 'B', 'P')) {
> + av_log(avctx, AV_LOG_ERROR, "missing WEBP tag\n");
> + ff_unlock_avformat();
> + return AVERROR_INVALIDDATA;
> + }
> + s->read_header = 1;
> + }
> +
> + ff_unlock_avformat();
> + }
> +
> + if (!s->read_header) {
> + av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n");
> return AVERROR_INVALIDDATA;
> }
>
> @@ -1416,6 +1437,8 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
> ret = av_image_check_size(s->width, s->height, 0, avctx);
> if (ret < 0)
> return ret;
> + if (bytestream2_get_bytes_left(&gb) == 0)
> + return AVERROR(EAGAIN);
> break;
> case MKTAG('A', 'L', 'P', 'H'): {
> int alpha_header, filter_m, compression;
>
More information about the ffmpeg-devel
mailing list