Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
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".

  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