From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Subject: [FFmpeg-devel] [PATCH 3/3] avformat/webpenc: Write correct size for single images when unseekable
Date: Fri, 3 Nov 2023 17:11:01 +0100
Message-ID: <AS8P250MB07444AD30FFF07FE99D3880E8FA5A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <AS8P250MB0744B198F01BF81A60ED7DD18FA5A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM>
The earlier code writes the file and then tries to patch up
the size later. This is avoidable for the common case of
a single image because one can know the complete size
in advance and write it.
Fixes ticket #4609.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavformat/webpenc.c | 68 ++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 27 deletions(-)
diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c
index d4acea7ba6..ea7a321975 100644
--- a/libavformat/webpenc.c
+++ b/libavformat/webpenc.c
@@ -21,6 +21,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
+#include "libavcodec/bytestream.h"
#include "avformat.h"
#include "internal.h"
#include "mux.h"
@@ -76,11 +77,16 @@ static int is_animated_webp_packet(AVPacket *pkt)
return 0;
}
+/**
+ * Returns 1 if it has written a RIFF header with a correct length field
+ */
static int flush(AVFormatContext *s, int trailer, int64_t pts)
{
WebpContext *w = s->priv_data;
AVStream *st = s->streams[0];
- int skip = 0;
+ uint8_t buf[12 /* RIFF+WEBP */ + 18 /* VP8X */ +
+ 14 /* ANIM */ + 24 /* ANMF */], *bufp = buf;
+ int writing_webp_header = 0, skip = 0;
unsigned flags = 0;
int vp8x = 0;
@@ -97,7 +103,10 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts)
}
if (!w->wrote_webp_header) {
- avio_write(s->pb, "RIFF\0\0\0\0WEBP", 12);
+ bytestream_put_le32(&bufp, MKTAG('R', 'I', 'F', 'F'));
+ bytestream_put_le32(&bufp, 0); /* Size to be patched later */
+ bytestream_put_le32(&bufp, MKTAG('W', 'E', 'B', 'P'));
+ writing_webp_header = 1;
w->wrote_webp_header = 1;
if (w->frame_count > 1) // first non-empty packet
w->frame_count = 1; // so we don't count previous empty packets.
@@ -110,38 +119,41 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts)
}
if (vp8x) {
- avio_write(s->pb, "VP8X", 4);
- avio_wl32(s->pb, 10);
- avio_w8(s->pb, flags);
- avio_wl24(s->pb, 0);
- avio_wl24(s->pb, st->codecpar->width - 1);
- avio_wl24(s->pb, st->codecpar->height - 1);
+ bytestream_put_le32(&bufp, MKTAG('V', 'P', '8', 'X'));
+ bytestream_put_le32(&bufp, 10);
+ bytestream_put_byte(&bufp, flags);
+ bytestream_put_le24(&bufp, 0);
+ bytestream_put_le24(&bufp, st->codecpar->width - 1);
+ bytestream_put_le24(&bufp, st->codecpar->height - 1);
}
if (!trailer) {
- avio_write(s->pb, "ANIM", 4);
- avio_wl32(s->pb, 6);
- avio_wl32(s->pb, 0xFFFFFFFF);
- avio_wl16(s->pb, w->loop);
+ bytestream_put_le32(&bufp, MKTAG('A', 'N', 'I', 'M'));
+ bytestream_put_le32(&bufp, 6);
+ bytestream_put_le32(&bufp, 0xFFFFFFFF);
+ bytestream_put_le16(&bufp, w->loop);
}
}
if (w->frame_count > trailer) {
- avio_write(s->pb, "ANMF", 4);
- avio_wl32(s->pb, 16 + w->last_pkt->size - skip);
- avio_wl24(s->pb, 0);
- avio_wl24(s->pb, 0);
- avio_wl24(s->pb, st->codecpar->width - 1);
- avio_wl24(s->pb, st->codecpar->height - 1);
+ bytestream_put_le32(&bufp, MKTAG('A', 'N', 'M', 'F'));
+ bytestream_put_le32(&bufp, 16 + w->last_pkt->size - skip);
+ bytestream_put_le24(&bufp, 0);
+ bytestream_put_le24(&bufp, 0);
+ bytestream_put_le24(&bufp, st->codecpar->width - 1);
+ bytestream_put_le24(&bufp, st->codecpar->height - 1);
if (w->last_pkt->pts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE) {
- avio_wl24(s->pb, pts - w->last_pkt->pts);
+ bytestream_put_le24(&bufp, pts - w->last_pkt->pts);
} else
- avio_wl24(s->pb, w->last_pkt->duration);
- avio_w8(s->pb, 0);
+ bytestream_put_le24(&bufp, w->last_pkt->duration);
+ bytestream_put_byte(&bufp, 0);
}
+ if (trailer && writing_webp_header)
+ AV_WL32(buf + 4, bufp - (buf + 8) + w->last_pkt->size - skip);
+ avio_write(s->pb, buf, bufp - buf);
avio_write(s->pb, w->last_pkt->data + skip, w->last_pkt->size - skip);
av_packet_unref(w->last_pkt);
- return 0;
+ return trailer && writing_webp_header;
}
static int webp_write_packet(AVFormatContext *s, AVPacket *pkt)
@@ -185,11 +197,13 @@ static int webp_write_trailer(AVFormatContext *s)
if ((ret = flush(s, 1, AV_NOPTS_VALUE)) < 0)
return ret;
- filesize = avio_tell(s->pb);
- if (avio_seek(s->pb, 4, SEEK_SET) == 4) {
- avio_wl32(s->pb, filesize - 8);
- // Note: without the following, avio only writes 8 bytes to the file.
- avio_seek(s->pb, filesize, SEEK_SET);
+ if (!ret) {
+ filesize = avio_tell(s->pb);
+ if (avio_seek(s->pb, 4, SEEK_SET) == 4) {
+ avio_wl32(s->pb, filesize - 8);
+ // Note: without the following, avio only writes 8 bytes to the file.
+ avio_seek(s->pb, filesize, SEEK_SET);
+ }
}
}
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-11-03 16:10 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-03 16:09 [FFmpeg-devel] [PATCH 1/3] avformat/webpenc: Return early to reduce indentation Andreas Rheinhardt
2023-11-03 16:11 ` [FFmpeg-devel] [PATCH 2/3] avformat/webpenc: Reindent after the previous commit Andreas Rheinhardt
2023-11-03 16:11 ` Andreas Rheinhardt [this message]
2023-12-07 18:29 ` [FFmpeg-devel] [PATCH 1/3] avformat/webpenc: Return early to reduce indentation Andreas Rheinhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AS8P250MB07444AD30FFF07FE99D3880E8FA5A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM \
--to=andreas.rheinhardt@outlook.com \
--cc=ffmpeg-devel@ffmpeg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git