[FFmpeg-devel] [PATCH v3 1/4] avcodec/webp: compatibilize with avformat/webpdec
Martin Reboredo
yakoyoku at gmail.com
Sun Sep 12 23:20:07 EEST 2021
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();
+
+ 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;
--
2.32.0
More information about the ffmpeg-devel
mailing list