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)

Attachment: signature.asc
Description: PGP signature

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to