[FFmpeg-devel] [PATCH V3] [RFC] GSoC: FLIF16 Image format parser

Jai Luthra me at jailuthra.in
Sat Mar 14 22:45:33 EET 2020


Hi Anamitra,

Good progres on the parser, I tested it on the samples you provided, lgtm. 
Comments inline.

On Fri, Mar 06, 2020 at 06:10:04PM +0000, Anamitra Ghorui wrote:
>The parser has been tested and is able to correctly identify the start
>of the compressed bitstream. The patch has a set of printf statements
>which print a "tracing table" of the behaviour. Upon Nicolas George's
>suggestion I have made it so that the varints are read into a uint64_t.
>Hence the varints are limited in the range 0 to 2^64 - 1.
>The test cases are as follows:
>1. 1x1 png image (a.flif)
>2. 1x1 png image with dummy EXIF data (a1.flif)
>3. 2x2 png image (b.flif)
>4. 300x200 png image (d.flif)
>5. 10x10 gif image, 2 frames (f.flif)
>These have been provided as an attachment.
>The way I have used AVERROR in the parser may be wrong.
>
>The testing code has been adapted from:
>https://ffmpeg.org/doxygen/trunk/decode_video_8c-example.html
>The concerned part is (available as attachment):
>...
>	while (!feof(f)) {
>        /* read raw data from the input file */
>        data_size = fread(inbuf, 1, INBUF_SIZE, f);
>        if (!data_size)
>            break;
>        /* use the parser to split the data into frames */
>        data = inbuf;
>        while (data_size > 0) {
>            ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,
>                                   data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
>            if (ret < 0) {
>                fprintf(stderr, "Error while parsing\n");
>                exit(1);
>            }
>            data      += ret;
>            data_size -= ret;
>            if (pkt->size > 0)
>            {
>                printf("Reached bitstream at 0x%x (%dd)\n", pkt->size,
>                       pkt->size);
>                goto end;
>            }
>        }
>    }
>    end:
>...
>

Yes afaics parser does not generally return errors. Usually the parser splits 
the frames out if it is able to, and the decoder verifies if something is 
wrong within the packet bitstream.

I am not certain how this should be handled here as you plan to do entropy 
decoding within the parser.

Parser's ret value being < 0 usually implies that frame start was in previous 
packet, but look around other parsers and ask in #ffmpeg-devel if your 
approach is feasible.

>Now comes the part of decompressing the bitstream and finding the bounds
>of the data. I haven't yet properly gone through the reference
>implementation due to a lack of time (I will have now), but I'm thinking
>of defining a few functions:
>
>int ff_flif16_read_rac(uint8_t *buf, unsigned int buf_size,
>					unsinged int offset,
>					FLIF16ChanceTable chance);
>int ff_flif16_read_uni_int(int min, int max);
>int ff_flif16_read_nz_int(int min, int max,  FLIF16ChanceTable context);
>int ff_flif16_read_gnz_int(int min, int max, FLIF16ChanceTable context);
>(...)

I haven't heard from the other applicant who was working on the entropy 
decoding task, so I would suggest you can go ahead with implementing this. I 
think you may be able to use/modify the existing range coder ffmpeg module.

>
>The decoder itself will not handle decompressing or decoding the
>bitstream, rather we will alter the buffer to add in the decompressed
>bitstream, then run it through the parser and add it to the AVPacket,
>and finally pass it to the decoder. The decoder will then decode all
>the frames from that single packet.
>


>+typedef struct FLIF16ParseContext {
>+    ParseContext pc;
>+    int state;              ///< The section of the file the parser is in currently.
>+    unsigned int index;     ///< An index based on the current state.
>+    uint8_t iac;            ///< Interlaced, animated, color palette info

For testing this is good enough, but I think it would be a better idea to have 
separate fields in the context for interlaced/animated/color pallete etc. so 
that you don't need to do bitshifts everywhere you need to use them as done 
below.

>+    uint8_t varint;         ///< Number of varints to process in sequence
>+    uint64_t width;
>+    uint64_t height;
>+    uint64_t frames;
>+    uint64_t meta;          ///< Size of a meta chunk
>+    uint64_t count;
>+} FLIF16ParseContext;
>+
>+static int flif16_find_frame(FLIF16ParseContext *f, const uint8_t *buf,
>+                             int buf_size)
>+{
>+    int next = END_NOT_FOUND;
>+    int index;
>+
>+    printf("pos\tfindex\tstate\tval\tw\th\tframes\tmeta\tvarintn\n");
>+    for (index = 0; index < buf_size; index++) {
>+        printf("%d\t%d\t%d\t0x%x\t0x%lx\t0x%lx\t%lx\t%lx\t%d\n", index,
>+               f->index, f->state, buf[index], f->width, f->height, f->frames,
>+               f->meta, f->varint);
>+        if (!f->state) {
>+            if (!memcmp(flif16_header, buf + index, 4))
>+                f->state = FLIF16_HEADER;
>+            ++f->index;
>+        } else if (f->state == FLIF16_HEADER) {
>+            if (f->index == 3 + 1) { // Interlaced/animated/color palette info
>+                f->iac = buf[index];
>+            } else if (f->index == (3 + 1 + 1)) { // Start - 1 of the first varint
>+                f->varint = 1;
>+            } else if (f->varint) {
>+                if (f->count == 9)
>+                        return AVERROR(ENOMEM);
>+
>+                switch (f->varint) {
>+                        case 1:
>+                            FF_FLIF16_VARINT_APPEND(f->width, buf[index]);
>+                            break;
>+
>+                        case 2:
>+                            FF_FLIF16_VARINT_APPEND(f->height, buf[index]);
>+                            break;
>+
>+                        case 3:
>+                            FF_FLIF16_VARINT_APPEND(f->frames, buf[index]);
>+                            break;
>+                }
>+                if (buf[index] < 128) {
>+                    if (f->varint < (2 + (((f->iac >> 4) > 4)?1:0))) {
>+                        switch (f->varint) {
>+                            case 1: f->width++;  break;
>+                            case 2: f->height++; break;
>+                        }
>+                        f->varint++;
>+                        f->count = 0;
>+                    } else {
>+                        if (f->varint == 2)
>+                            f->height++;
>+                        if ((f->iac >> 4) > 4)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20200315/9d4d12da/attachment.sig>


More information about the ffmpeg-devel mailing list