]> git.sesse.net Git - ffmpeg/commitdiff
avcodec/xbmenc: Allow for making UW images
authorJose Da Silva <digital@joescat.com>
Tue, 19 Jan 2021 05:43:13 +0000 (21:43 -0800)
committerPaul B Mahol <onemda@gmail.com>
Thu, 28 Jan 2021 14:50:37 +0000 (15:50 +0100)
I've run into some bugs where I was downloading a bunch of data and began
seeing weird hiccups. For example, javascript promises to allow you to push
some very long lines of data, but the hiccups I saw was with data larger
than 2k in length (windows) pushed out of a child process stdout piped into
the stdin of the calling parent program.
Soo much for smooth promises, this was broken and would run into similar
problems on a linux PC with 32k line limits.
The solution was to break the data into smaller chunks than 2k - and then
these data hiccups disappeared (windows PC).

It would be expected to be similar for linux PCs (32k I think) and other
OSes with different sizes.

If the ANSI required minimum needs to be 509 chars or larger (assuming
509+<CR>+<LF>+<0>=512), then 509 was chosen as the shortest worst-case
scenario) in this patch.
Most small pictures will go output looking pretty much the same data out
until you get to about 84bytes (672 pixels wide), where lines out begin to
be split. For example a UW 4K will exceed a 2k readln and a UW 10K picture
approaches an 8k readln

The purpose for this patch is to ensure that data remains below the
readline limits (of 509 chars), so that programs (like javascript) can push
data in large chunks without breaking into hiccups because the data length
is too long to be pushed cleanly in one go.
Subject: [PATCH 3/3] avcodec/xbmenc: Allow for making UW images

Worst-case ANSI must allow for 509 chars, while Windows allows for 2048
and Linux for 32K line length. This allows an OS with a small readline
access limitation to fetch very wide images (created from ffmpeg).

libavcodec/xbmenc.c

index 193ced652a2b54a052e00de82732a0468627ffc5..1cf13f6f0b08d7b0dd18b75a5445949de9f703d9 100644 (file)
 #include "internal.h"
 #include "mathops.h"
 
+#define ANSI_MIN_READLINE 509
+
 static int xbm_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                             const AVFrame *p, int *got_packet)
 {
-    int i, j, commas, ret, size, linesize;
+    int i, j, l, commas, ret, size, linesize, lineout, rowsout;
     uint8_t *ptr, *buf;
 
-    linesize = (avctx->width + 7) / 8;
+    linesize = lineout = (avctx->width + 7) / 8;
     commas   = avctx->height * linesize;
-    size     = avctx->height * (linesize * 6 + 1) + 106;
+
+    /* ANSI worst case minimum readline is 509 chars. */
+    rowsout  = avctx->height;
+    if (lineout > (ANSI_MIN_READLINE / 6)) {
+        lineout = ANSI_MIN_READLINE / 6;
+        rowsout = (commas + lineout - 1) / lineout;
+    }
+
+    size     = rowsout * (lineout * 6 + 1) + 106;
     if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0)
         return ret;
 
@@ -42,14 +52,20 @@ static int xbm_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     buf += snprintf(buf, 32, "#define image_width %u\n", avctx->width);
     buf += snprintf(buf, 33, "#define image_height %u\n", avctx->height);
     buf += snprintf(buf, 39, "static unsigned char image_bits[] = {\n");
-    for (i = 0; i < avctx->height; i++) {
+    for (i = 0, l = lineout; i < avctx->height; i++) {
         for (j = 0; j < linesize; j++) {
             buf += snprintf(buf, 6, " 0x%02X", ff_reverse[*ptr++]);
-            if (--commas > 0)
-                buf += snprintf(buf, 2, ",");
+            if (--commas <= 0) {
+                buf += snprintf(buf, 2, "\n");
+                break;
+            }
+            buf += snprintf(buf, 2, ",");
+            if (--l <= 0) {
+                buf += snprintf(buf, 2, "\n");
+                l = lineout;
+            }
         }
         ptr += p->linesize[0] - linesize;
-        buf += snprintf(buf, 2, "\n");
     }
     buf += snprintf(buf, 5, " };\n");