From patchwork Wed Sep 8 20:14:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Reboredo X-Patchwork-Id: 30079 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2a4a:0:0:0:0 with SMTP id k10csp759751iov; Wed, 8 Sep 2021 13:15:17 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzZeJNf4yaSCxrleYvzy7cr0CzsUm/MoV0+Q4WSVOrPWeBYopCPtesdWQKJJNRjs3I1vOAW X-Received: by 2002:a50:b410:: with SMTP id b16mr31933edh.157.1631132117240; Wed, 08 Sep 2021 13:15:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631132117; cv=none; d=google.com; s=arc-20160816; b=ftiGUl/tXS6wumFykpMCtAmjg7SsuGynGmNsNtB71POzLgswuIZ8cji8gq7b0A8oC7 w66v/rO4EGdA26MTj1GBsICMR+OA8yDrKk7FvzuCeiIjK8DZDeW4fXUQ8Uk7rb7DCbi6 JpH2bXGRJBtzDhm1Y/Vnu1felj/teHyCo6PYQhMyQyMLVyXQcINgW4Bzclutl7l8SiVX kEWtEwacvjr7ucGjvEDYNTVE8T51gvIvTv+F8gpuku77UW6+3YJM4VaWTaf4Tt20BkGX 0fAwIKOwsm5uwAGidMwKsjwidJAmcxt/Pk4CpPwn9m46S3xpBpJFzVsM/lFeJF6ENOpr /DEg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=tdYZXLyIJUq2RR+TC6c+kBMZksGcQ53UGbSDkZhyWhQ=; b=XlSVNChvP1DLPykg6Vm/M+ZgSvHznoZOam0m2QNhcX8PEhlbqSTN2JNBn1GyW9faWT GnHi6MhB0amoX9wC5Ry0eqdTg3M23vSr0obtUwlHJaAc4eAuwc7Afdr33n7DsJmxgeaF CDjZKp5LTm0/b/SCBlx8LspxKBtyurXnaBubjgkHikrQVWH96leO+BcGSzyreO54LytV 2h1GklRRtGcqQla1sbDdW3KfKM+Q/2XVVK8Z/oHBEzj6evmSaC7/jvtbEoijWNLk6Ry3 uMDjt+rJBSlsD0m4/5pVDfRt4oDZcWwbDEIN2GjsK2y1kwQ0XmluUtYxrrxOec12tkq7 LPjw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=N+9JqZGh; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k5si154752edq.72.2021.09.08.13.14.53; Wed, 08 Sep 2021 13:15:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=N+9JqZGh; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 27E15689B7F; Wed, 8 Sep 2021 23:14:49 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f178.google.com (mail-qk1-f178.google.com [209.85.222.178]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0CD96689B7F for ; Wed, 8 Sep 2021 23:14:42 +0300 (EEST) Received: by mail-qk1-f178.google.com with SMTP id w78so3984765qkb.4 for ; Wed, 08 Sep 2021 13:14:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=pFjLGucHmxHX1ryxJ5tXOOaIBVhs5s1U9Fq2+OZ/YsY=; b=N+9JqZGhM64H37hsLe+xUsqWVTa6Oxos3BSGcnB7ePw5/EsLhzxZvcSn23YQW6pUVN JCjD1JNgOFXDYV/pfeTwcJxA+s+RUQW7awWsIMqkR00X2bs7qitliCyIyjCQSQFgerKq mZ8hOjiGcEjJIFFAraWHbEzJ/sor5fLEQBMAjbq21APZ74sfBlKBI7FB+drEWJPe91B+ hiNI/EzDcTsmPtVMhydHev6q9jEWSwGcBXEoK/1QNOZKJqDsBc8hQylmCFAyhlcduMgP 6LVqRe1yoIFXNhT3jKqoIXoimSCFwokvRnNhDmgp1vUxQwVZ9PK4utWQm6tsXWpHefIJ AD1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=pFjLGucHmxHX1ryxJ5tXOOaIBVhs5s1U9Fq2+OZ/YsY=; b=fRhZbyqTsW1T9KzxJjB62/QUm/yv3kHjOI7S6yoa5KEYCLpyaLOzxFj1WcvM3bRNbh p6OLSJX6yluwCboo4W5by7ga9uNBpCeMSlfpHDPa2u3VIe2Zos/VRCam/p4kDXJsWyAb bbGUsMoxbSu+MdIydrKgioquqlSdvRhG0A20BE7YRk1/ctbSNw6yYz0Kf+W7XJA5a0F0 k3vVkT4sQcVTMTSC9x+1Edy0d3Teo6lS3eF6tk6WnzMs4VstfzP40qpQY4CS59pwKtjh l07hCrq51HyzJV/qtKeHXzm+QjAUc5M8/LxyViU5n09WWoxs3OrWLfc6QpKIRAGQB8d/ AS7Q== X-Gm-Message-State: AOAM531hxeWGtiL1XNqLf/PVCGU1BOO62DARc8C+f6Ndbktttc1HUgwf iIKocVPlVkG9M9ktmI6N9nBreQvLc+M= X-Received: by 2002:a37:8d3:: with SMTP id 202mr5158642qki.417.1631132079756; Wed, 08 Sep 2021 13:14:39 -0700 (PDT) Received: from localhost.localdomain (static.218.11.itcsa.net. [190.15.218.11]) by smtp.gmail.com with ESMTPSA id s18sm122275qkj.87.2021.09.08.13.14.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Sep 2021 13:14:39 -0700 (PDT) From: Martin Reboredo To: ffmpeg-devel@ffmpeg.org Date: Wed, 8 Sep 2021 17:14:33 -0300 Message-Id: <20210908201434.3658940-1-yakoyoku@gmail.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 1/2] avformat/webpdec: WebP demuxer implementation X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: mm4XYJY9rea9 FFmpeg has the ability to mux encoded WebP packets, but it cannot demux the format. The purpose of this patch is to add a way to extract pictures from a WebP stream. Any other side data processing (mainly ICC profiles) is left up for later work. Although we have a demuxer with `image2`, it doesn't have support for animated frames like this patch. The WebP format is based on RIFF, and due to the charasteristics of the latter, I've took advantage from chunking for processing purposes. Package reading is done by taking chunks in a specific way. Starts by splitting the `RIFF`/`WEBP` header, then it goes by any of the three `VP8 ` (lossy)/`VP8L` (lossless)/`VP8X` (extended format). In the case of a `VP8X` chunk we check for relevant flags. We then follow by grabbing the `VP8 `/`ALPH` (alpha frame) + `VP8 `/`VP8L` chunks accourdingly. If the container specifies that is an animated package we take `ANIM` for the animation parameters and the many `ANMF` animation frames, which every of them contains an image chunk (`VP8 `/`ALPH` + `VP8 `/`VP8L`). Otherwise, if an unknown chunk is found, we just simply ignore it. Tested by remuxing WebP images (using `ffmpeg -i testa.webp -codec:v copy testb.webp`), viewed the images in my browser and compared the checksums. Mostly followed the WebP container specification [1] for the implementation, the VP8 bitstream [2] and the WebP lossless specs were used too. Partially fixes #4907. [1]: https://developers.google.com/speed/webp/docs/riff_container [2]: https://datatracker.ietf.org/doc/html/rfc6386 [3]: https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification Signed-off-by: Martin Reboredo --- MAINTAINERS | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/riff.c | 1 + libavformat/webpdec.c | 326 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 330 insertions(+) create mode 100644 libavformat/webpdec.c diff --git a/MAINTAINERS b/MAINTAINERS index dcac46003e..f2d8f5eb17 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -505,6 +505,7 @@ Muxers/Demuxers: wav.c Michael Niedermayer wc3movie.c Mike Melanson webm dash (matroskaenc.c) Vignesh Venkatasubramanian + webp*.c Martin Reboredo webvtt* Matthew J Heaney westwood.c Mike Melanson wtv.c Peter Ross diff --git a/libavformat/Makefile b/libavformat/Makefile index f7e47563da..aec2833c52 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -581,6 +581,7 @@ OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o OBJS-$(CONFIG_WEBM_CHUNK_MUXER) += webm_chunk.o OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o +OBJS-$(CONFIG_WEBP_DEMUXER) += webpdec.o OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 5471f7c16f..55f3c9a956 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -473,6 +473,7 @@ extern const AVOutputFormat ff_webm_muxer; extern const AVInputFormat ff_webm_dash_manifest_demuxer; extern const AVOutputFormat ff_webm_dash_manifest_muxer; extern const AVOutputFormat ff_webm_chunk_muxer; +extern const AVInputFormat ff_webp_demuxer; extern const AVOutputFormat ff_webp_muxer; extern const AVInputFormat ff_webvtt_demuxer; extern const AVOutputFormat ff_webvtt_muxer; diff --git a/libavformat/riff.c b/libavformat/riff.c index 27a9706510..9bd940ba52 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -321,6 +321,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_VP7, MKTAG('V', 'P', '7', '1') }, { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') }, { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, + { AV_CODEC_ID_WEBP, MKTAG('W', 'E', 'B', 'P') }, { AV_CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') }, { AV_CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') }, { AV_CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') }, diff --git a/libavformat/webpdec.c b/libavformat/webpdec.c new file mode 100644 index 0000000000..53b0a29a89 --- /dev/null +++ b/libavformat/webpdec.c @@ -0,0 +1,326 @@ +/* + * webp demuxer + * Copyright (c) 2021 Martin Reboredo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "avformat.h" +#include "internal.h" + +typedef struct WebpDemuxContext { + AVClass *class; + int width; + int height; + AVPacket last_pkt; + int size; + int loop; + int read_webp_header; + int using_webp_anim_decoder; + int vp8x; + int lossless; + int alpha; + int icc; +} WebpDemuxContext; + +static int webpdec_read_probe(const AVProbeData * p) +{ + if (AV_RL32(p->buf) != AV_RL32("RIFF")) + return 0; + + if (AV_RL32(&p->buf[8]) != AV_RL32("WEBP")) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int parse_animation_frame_duration(AVFormatContext * s, AVPacket * pkt) +{ + pkt->duration = av_rescale_q(AV_RL24(pkt->data + 20), + (AVRational) { 1, 1000 }, + s->streams[0]->time_base); + + return 0; +} + +static int parse_vp8x_chunk(AVFormatContext * s, AVPacket * pkt) +{ + WebpDemuxContext *w = s->priv_data; + AVIOContext *pb = s->pb; + int bgcolor = 0xFFFFFFFF; + int cont = 1, anim_frame = 0, alpha_frame = 0; + int64_t ret = 0; + + s->packet_size = 0; + + while (cont && ret >= 0) { + int skip = 0, rewind = 1; + int fourcc = avio_rl32(pb); + int size = avio_rl32(pb); + int padded_size = size + (size & 1); + int chunk_size = padded_size + 8; + s->packet_size += chunk_size; + + if (padded_size == 0) + return AVERROR_EOF; + + switch (fourcc) { + case MKTAG('V', 'P', '8', 'X'): + return AVERROR_INVALIDDATA; + /* case MKTAG('I', 'C', 'C', 'P'): + avio_read(pb, w->iccp_data, padded_size); */ + case MKTAG('A', 'L', 'P', 'H'): + if (!w->alpha || alpha_frame == 1) + return AVERROR_INVALIDDATA; + if (w->using_webp_anim_decoder && anim_frame == 0) + return AVERROR_INVALIDDATA; + + alpha_frame = 1; + break; + case MKTAG('V', 'P', '8', 'L'): + alpha_frame = 1; + case MKTAG('V', 'P', '8', ' '): + if (w->alpha && alpha_frame == 0) + return AVERROR_INVALIDDATA; + if (w->using_webp_anim_decoder && anim_frame == 0) + return AVERROR_INVALIDDATA; + + cont = 0; + break; + case MKTAG('A', 'N', 'I', 'M'): + if (w->loop == -1) { + bgcolor = avio_rl32(pb); + w->loop = avio_rl16(pb); + + ret = avio_seek(pb, -14, SEEK_CUR); + if (ret < 0) + return ret; + + ret = av_get_packet(pb, pkt, s->packet_size); + if (ret < 0) + return ret; + + return 0; + } + cont = 0; + break; + case MKTAG('A', 'N', 'M', 'F'): + if (!w->using_webp_anim_decoder || anim_frame == 1) + return AVERROR_INVALIDDATA; + + ret = avio_seek(pb, -8, SEEK_CUR); + if (ret < 0) + return ret; + + ret = av_get_packet(pb, pkt, s->packet_size); + if (ret < 0) + return ret; + + ret = parse_animation_frame_duration(s, pkt); + if (ret < 0) + return ret; + + anim_frame = 1; + rewind = 0; + return 0; + default: + s->packet_size -= chunk_size; + skip = 1; + rewind = 0; + break; + } + + if (skip) { + ret = avio_skip(pb, padded_size); + } + if (rewind) { + ret = avio_seek(pb, -8, SEEK_CUR); + if (ret < 0) + return ret; + ret = av_append_packet(pb, pkt, chunk_size); + } + } + + return ret; +} + +static int parse_header(AVFormatContext * s) +{ + WebpDemuxContext *w = s->priv_data; + AVIOContext *pb = s->pb; + int size; + unsigned int flags = 0; + int ret = 0; + + if (avio_rl32(pb) != AV_RL32("RIFF")) + return AVERROR_INVALIDDATA; + w->size = avio_rl32(pb) + 8; + if (avio_rl32(pb) != AV_RL32("WEBP")) + return AVERROR_INVALIDDATA; + + if (avio_rl24(pb) != AV_RL24("VP8")) + return AVERROR_INVALIDDATA; + switch (avio_r8(pb)) { + case 'X': + w->vp8x = 1; + break; + case 'L': + w->lossless = 1; + case ' ': + break; + default: + return AVERROR_INVALIDDATA; + } + size = avio_rl32(pb); + if (w->vp8x) { + flags = avio_r8(pb); + + if (flags & 0x02) + w->using_webp_anim_decoder = 1; + if (flags & 0x10) + w->alpha = 1; + if (flags & 0x20) + w->icc = 1; + + ret = avio_skip(pb, 3); + if (ret < 0) + return ret; + + w->width = avio_rl24(pb) + 1; + w->height = avio_rl24(pb) + 1; + + ret = avio_seek(pb, -30, SEEK_CUR); + } else if (w->lossless) { + avio_r8(pb); + flags = avio_rl32(pb); + w->width = (flags & 0x3FFF) + 1; + w->height = ((flags >> 14) & 0x3FFF) + 1; + w->alpha = (flags >> 28) & 0x01; + + ret = avio_seek(pb, -25, SEEK_CUR); + } else { + ret = avio_skip(pb, 6); + if (ret < 0) + return ret; + + w->width = (avio_rl16(pb) & 0x3FFF); + w->height = (avio_rl16(pb) & 0x3FFF); + + ret = avio_seek(pb, -30, SEEK_CUR); + } + + return ret; +} + +static int webpdec_read_header(AVFormatContext * s) +{ + WebpDemuxContext *w = s->priv_data; + AVStream *st; + int ret; + + w->width = -1; + w->height = -1; + w->loop = -1; + w->read_webp_header = 0; + + ret = parse_header(s); + if (ret < 0) + return ret; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_WEBP; + st->codecpar->width = w->width; + st->codecpar->height = w->height; + st->codecpar->format = w->alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; + + st->start_time = 0; + + avpriv_set_pts_info(st, 24, 1, 1000); + + return 0; +} + +static int webpdec_read_packet(AVFormatContext * s, AVPacket * pkt) +{ + WebpDemuxContext *w = s->priv_data; + AVIOContext *pb = s->pb; + int ret; + + ret = avio_feof(pb); + if (ret < 0) + return ret; + else if (ret > 0) + return AVERROR_EOF; + + if (!w->read_webp_header) { + s->packet_size = w->vp8x ? 30 : 12; + + ret = av_get_packet(pb, pkt, s->packet_size); + if (ret < 0) + return ret; + + w->read_webp_header = 1; + + return 0; + } + + if (!w->using_webp_anim_decoder) + pkt->duration = + av_rescale_q(33, (AVRational) { 1, 1000 }, + s->streams[0]->time_base); + + if (w->vp8x) { + ret = parse_vp8x_chunk(s, pkt); + if (ret < 0) + return ret; + } else { + int fourcc = avio_rl32(pb); + int size = avio_rl32(pb) + 8; + size = size + (size & 1); + if (fourcc != AV_RL32("VP8 ") && fourcc != AV_RL32("VP8L")) + return AVERROR_INVALIDDATA; + ret = avio_seek(pb, -8, SEEK_CUR); + if (ret < 0) + return ret; + ret = av_get_packet(pb, pkt, size); + if (ret < 0) + return ret; + } + + pkt->stream_index = 0; + + return 0; +} + +const AVInputFormat ff_webp_demuxer = { + .name = "webp", + .long_name = NULL_IF_CONFIG_SMALL("WebP"), + .extensions = "webp", + .mime_type = "image/webp", + .priv_data_size = sizeof(WebpDemuxContext), + .read_probe = webpdec_read_probe, + .read_header = webpdec_read_header, + .read_packet = webpdec_read_packet, + .flags = AVFMT_VARIABLE_FPS, +}; From patchwork Wed Sep 8 20:14:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Reboredo X-Patchwork-Id: 30080 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2a4a:0:0:0:0 with SMTP id k10csp759882iov; Wed, 8 Sep 2021 13:15:28 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzAXpciIYp84UFO0dIMfMYSZSPKEymLv4M/HXEEJU40qoqfdljB2zwuIQBuoIVbkieKgY+S X-Received: by 2002:a50:ed06:: with SMTP id j6mr70774eds.148.1631132128249; Wed, 08 Sep 2021 13:15:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631132128; cv=none; d=google.com; s=arc-20160816; b=zShWmzNZwPoWTgWzrZ6m42eRu3MAP6kRZM7edxMqkKbnG0wrU6AQXKdNHs7NwiRM+M o5kA6bFiNOshMR0c+NN2YjQzH8XlFs0wPCmuwCe4uRDmO5xY00GYNeX0ob6a+Jkt4rkC dGkdSAojvUcbvNKEq6nRsBXsPFTZJ4axkxwPBO/PV7aw1+MLHYR1JLgniyPidbYp2Glv +Mq2CRk0G94FCcixXQrHzm/9HQnfxsNRoCIN439QEp4512b6x/T2DRCk814uFxGRki2U RDfn19o+IxQNbHtzZLTl31X66twsOBCYYOfph3G9DYLAsGUb9XHvJalMf2B8XFDFlraf Xd+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to; bh=nTWNAIYMyMms6WSvgjziUP3X8UVkFm8kOp1YcXeIIAk=; b=Zk6x5gBRj+zynsU7X6aLFpqTd0WAd0c2hi7H8U8QDv61xQa5OHhNGTkHPGG2AveEWK vhWeRuQb682Dihq983gsBJPthPjA0AMmiwYllJbjLaq3cDSGG54NufjKAzMNNjcUgGbi WUuZAUGbCkfdhjAHNc/MYTrrOBuVzlOoItUHmHSC1CnFmE88O4RnbEocm/x7w837u2X0 iIVXN2rpxo/Ip/xfmkOUDu+HeONh9bDKQ2wo/AZIAyWtflQ//AUXunp+w+Ovv5U9ufr+ Bln/7JFeQv6QgYc5KcivXE8MAGwvu4TQn3+h3RsVTl5cZBX1+UZloQrjMXzTFgyTCK+s BJ2w== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b="jfd/Qsr/"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id c9si44031ejj.296.2021.09.08.13.15.04; Wed, 08 Sep 2021 13:15:28 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b="jfd/Qsr/"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5331F68A6A1; Wed, 8 Sep 2021 23:14:50 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f178.google.com (mail-qk1-f178.google.com [209.85.222.178]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3A51C689B7F for ; Wed, 8 Sep 2021 23:14:42 +0300 (EEST) Received: by mail-qk1-f178.google.com with SMTP id bk29so3960059qkb.8 for ; Wed, 08 Sep 2021 13:14:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=p/zR5k45Z1cljUs7P1pz8EIpvlAIyMdBfZ1asn8Y3wA=; b=jfd/Qsr/iAYOMJT8iMA62iQMJ6tJN1hNRUjgvycVS0PpMxtbqbi7u9t7FldJU5FVg6 1H/gwfq5F6YtPcl0347AvQ/3jOmnecW54L5NImnaNWQ4FJsWFPa9uvqq7RVowV8BuKbr Hqg4bg7TFXMwu5XFMj8Thp8bN7Sgc2HY2Wwpr1oKkC/pMFzvlLsO7OwwCnoVCdaeaOVp Tf0lz9HDyK3K0hH1tuojHJ0YNcV8MT8m1gBJmwWL8uZ6q3wBzxyPXV5cM/qL12Ly1Pwy VsaWpAlZCC6Mz+CdNqdEuRQymPfMhzE66RTsutN8BvDrxeFLEQrx6wQllOO8j7xGRhkT hKPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=p/zR5k45Z1cljUs7P1pz8EIpvlAIyMdBfZ1asn8Y3wA=; b=YTb9rJrIHOHpZlQTXEQwwdVzNd15EU9GzldZyuMrROiLoesrxCCj8aW7K6d9m8G5Sk +PPlwlDoqn+22bnPkdxzaqSU2p00hbZ5jn0t99R/1l0dyu26sZVG4sqZ/oW5S++rROc4 bQ9sImosazIgCEsJPJAzhDYqmVbP4An1wPI/ret1l6QSgAvzkbd+w5CpB8Ei9qU20d6W GPPmqlZN51q0eKPwBSkdd/8ge0W2JYCYsl4CDEyqNR+0mF4S8yAMyOex6KWgN+l1EH+o o/TBngmrEazyxKlD51tK2fQ5IVkf+RazdB5iRGjdEQa6SY38Dv1lM70CIwc/ZENrTv8m 02yg== X-Gm-Message-State: AOAM533H3dG9f6koq/kZIF+1Inc4gMox42y60EwMKM5cuH00raGMGdwo pcRhaYxwVxhsWh9eq3VMvZe2tvETzIU= X-Received: by 2002:a37:624f:: with SMTP id w76mr5189022qkb.284.1631132080883; Wed, 08 Sep 2021 13:14:40 -0700 (PDT) Received: from localhost.localdomain (static.218.11.itcsa.net. [190.15.218.11]) by smtp.gmail.com with ESMTPSA id s18sm122275qkj.87.2021.09.08.13.14.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Sep 2021 13:14:40 -0700 (PDT) From: Martin Reboredo To: ffmpeg-devel@ffmpeg.org Date: Wed, 8 Sep 2021 17:14:34 -0300 Message-Id: <20210908201434.3658940-2-yakoyoku@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210908201434.3658940-1-yakoyoku@gmail.com> References: <20210908201434.3658940-1-yakoyoku@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 2/2] avformat/webpenc: better detection of anim chunks X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: yBwver72posU Receiving RIFF chunks as `av_packet`s from `webpdec.c` in `webpenc.c` it wasn't doing proper animated frame detection/enumeration. Check for `ANIM`/`ANMF` chunks to see if the package is an animated WebP packet and for the `ANMF`/`ALPH`/`VP8 `/`VP8L` chunks if it's an actual frame. Signed-off-by: Martin Reboredo --- libavformat/webpenc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c index 9599fe7b85..50bee91910 100644 --- a/libavformat/webpenc.c +++ b/libavformat/webpenc.c @@ -55,13 +55,18 @@ static int is_animated_webp_packet(AVPacket *pkt) { int skip = 0; unsigned flags = 0; + int fourcc = AV_RL32(pkt->data); if (pkt->size < 4) return AVERROR_INVALIDDATA; - if (AV_RL32(pkt->data) == AV_RL32("RIFF")) + if (fourcc == AV_RL32("RIFF")) skip = 12; + else if (fourcc == AV_RL32("ANIM")) + return 1; + else if (fourcc == AV_RL32("ANMF")) + return 1; // Safe to do this as a valid WebP bitstream is >=30 bytes. - if (pkt->size < skip + 4) + if (pkt->size < skip + 4 && pkt->size != 12) return AVERROR_INVALIDDATA; if (AV_RL32(pkt->data + skip) == AV_RL32("VP8X")) { flags |= pkt->data[skip + 4 + 4]; @@ -143,6 +148,7 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts) static int webp_write_packet(AVFormatContext *s, AVPacket *pkt) { WebpContext *w = s->priv_data; + int fourcc = AV_RL32(pkt->data); int ret; if (!pkt->size) @@ -161,7 +167,9 @@ static int webp_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; av_packet_ref(&w->last_pkt, pkt); } - ++w->frame_count; + if (fourcc == AV_RL32("ANMF") || fourcc == AV_RL32("ALPH") || + fourcc == AV_RL32("VP8 ") || fourcc == AV_RL32("VP8L")) + ++w->frame_count; return 0; }