[PATCH] Simplify vqa_decode_chunk part II

Adam Iglewski adam.iglewski
Sat May 9 12:12:05 CEST 2009


---
 libavcodec/vqavideo.c |  320 ++++++++-----------------------------------------
 1 files changed, 50 insertions(+), 270 deletions(-)

diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c
index e991cdd..8f41fb8 100644
--- a/libavcodec/vqavideo.c
+++ b/libavcodec/vqavideo.c
@@ -466,301 +466,81 @@ static void vqa_join_partial_codebook(VqaContext *s,unsigned int chunk_type,cons
 
 static void vqa_decode_chunk(VqaContext *s)
 {
-    unsigned int chunk_type;
-    unsigned int chunk_size;
-    int byte_skip;
-    unsigned int index = 0;
     int i;
-    unsigned char r, g, b;
-    int index_shift;
-
-    int cbf0_chunk = -1;
-    int cbfz_chunk = -1;
-    int cbp0_chunk = -1;
-    int cbpz_chunk = -1;
-    int cpl0_chunk = -1;
-    int cplz_chunk = -1;
-    int vptz_chunk = -1;
-    int vptr_chunk = -1;
-    int vprz_chunk = -1;
-
-    int x, y;
-    int lines = 0;
-    int pixel_ptr;
-    int vector_index = 0;
-    int lobyte = 0;
-    int hibyte = 0;
-    int lobytes = 0;
-    int hibytes = s->decode_buffer_size / 2;
-
-    /* first, traverse through the frame and find the subchunks */
-    while (index < s->size) {
-
-        chunk_type = AV_RB32(&s->buf[index]);
-        chunk_size = AV_RB32(&s->buf[index + 4]);
-
-        switch (chunk_type) {
-
-        case CBF0_TAG:
-            cbf0_chunk = index;
-            break;
-
-        case CBFZ_TAG:
-            cbfz_chunk = index;
-            break;
-
-        case CBP0_TAG:
-            cbp0_chunk = index;
-            break;
-
-        case CBPZ_TAG:
-            cbpz_chunk = index;
-            break;
-
-        case CPL0_TAG:
-            cpl0_chunk = index;
-            break;
-
-        case CPLZ_TAG:
-            cplz_chunk = index;
-            break;
-
-        case VPTZ_TAG:
-            vptz_chunk = index;
-            break;
-
-        case VPTR_TAG:
-            vptr_chunk = index;
-            break;
-
-        case VPRZ_TAG:
-            vprz_chunk = index;
-            break;
-
-        default:
-            av_log(s->avctx, AV_LOG_ERROR, "  VQA video: Found unknown chunk type: %c%c%c%c (%08X)\n",
-            (chunk_type >> 24) & 0xFF,
-            (chunk_type >> 16) & 0xFF,
-            (chunk_type >>  8) & 0xFF,
-            (chunk_type >>  0) & 0xFF,
-            chunk_type);
-            break;
-        }
-
-        byte_skip = chunk_size & 0x01;
-        index += (CHUNK_PREAMBLE_SIZE + chunk_size + byte_skip);
-    }
-
-    /* next, deal with the palette */
-    if ((cpl0_chunk != -1) && (cplz_chunk != -1)) {
-
-        /* a chunk should not have both chunk types */
-        av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: found both CPL0 and CPLZ chunks\n");
-        return;
-    }
-
-    /* decompress the palette chunk */
-    if (cplz_chunk != -1) {
-
-/* yet to be handled */
-
-    }
+    const unsigned char *current_chunk;
+    unsigned int current_chunk_size;
 
     /* convert the RGB palette into the machine's endian format */
-    if (cpl0_chunk != -1) {
+    current_chunk = vqa_get_chunk(CPL0_TAG,s->buf,s->size,&current_chunk_size);
+    if (current_chunk) {
 
-        chunk_size = AV_RB32(&s->buf[cpl0_chunk + 4]);
         /* sanity check the palette size */
-        if (chunk_size / 3 > 256) {
+        if (current_chunk_size / 3 > 256) {
             av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: found a palette chunk with %d colors\n",
-                chunk_size / 3);
+                current_chunk_size / 3);
             return;
         }
-        cpl0_chunk += CHUNK_PREAMBLE_SIZE;
-        for (i = 0; i < chunk_size / 3; i++) {
+        for (i = 0; i < current_chunk_size / 3; i++) {
             /* scale by 4 to transform 6-bit palette -> 8-bit */
-            r = s->buf[cpl0_chunk++] * 4;
-            g = s->buf[cpl0_chunk++] * 4;
-            b = s->buf[cpl0_chunk++] * 4;
-            s->palette[i] = (r << 16) | (g << 8) | (b);
+            s->palette[i]  = *current_chunk++ << 18;
+            s->palette[i] |= *current_chunk++ << 10;
+            s->palette[i] |= *current_chunk++ <<  2;
         }
     }
 
-    /* next, look for a full codebook */
-    if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) {
-
-        /* a chunk should not have both chunk types */
-        av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: found both CBF0 and CBFZ chunks\n");
-        return;
-    }
-
     /* decompress the full codebook chunk */
-    if (cbfz_chunk != -1) {
-
-        chunk_size = AV_RB32(&s->buf[cbfz_chunk + 4]);
-        cbfz_chunk += CHUNK_PREAMBLE_SIZE;
-        decode_format80(&s->buf[cbfz_chunk], chunk_size,
-            s->codebook, s->codebook_size, 0);
-    }
+      current_chunk = vqa_get_chunk(CBFZ_TAG,s->buf,s->size,&current_chunk_size);
+      if (current_chunk) {
+          decode_format80(current_chunk, current_chunk_size,
+                           s->codebook, s->codebook_size, 0);
+          s->is_codebook = 1;
+      }
 
     /* copy a full codebook */
-    if (cbf0_chunk != -1) {
-
-        chunk_size = AV_RB32(&s->buf[cbf0_chunk + 4]);
-        /* sanity check the full codebook size */
-        if (chunk_size > MAX_CODEBOOK_SIZE) {
-            av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: CBF0 chunk too large (0x%X bytes)\n",
-                chunk_size);
+    current_chunk = vqa_get_chunk(CBF0_TAG,s->buf,s->size,&current_chunk_size);
+    if (current_chunk) {
+        if (current_chunk_size > MAX_CODEBOOK_SIZE) {
+            av_log(s->avctx, AV_LOG_ERROR, "  problem: CBF0 chunk too large (0x%X bytes)\n",
+                    current_chunk_size);
             return;
         }
-        cbf0_chunk += CHUNK_PREAMBLE_SIZE;
-
-        memcpy(s->codebook, &s->buf[cbf0_chunk], chunk_size);
+        memcpy(s->codebook, current_chunk, current_chunk_size);
+        s->is_codebook = 1;
     }
 
-    /* decode the frame */
-    if ((vptz_chunk == -1) && (vptr_chunk == -1) && (vprz_chunk == -1) && (cbfz_chunk==-1)) {
-
-        /* something is wrong if there is no VPTZ chunk */
-        av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: no VPTZ or VPTR or VPRZ chunk found\n");
+    if (!s->is_codebook) {
+        av_log(s->avctx, AV_LOG_ERROR, "  problem: no codebook available for decoding frame data\n");
         return;
     }
 
-    if (vptz_chunk != -1) {
-
-    chunk_size = AV_RB32(&s->buf[vptz_chunk + 4]);
-    vptz_chunk += CHUNK_PREAMBLE_SIZE;
-    decode_format80(&s->buf[vptz_chunk], chunk_size,
-        s->decode_buffer, s->decode_buffer_size, 1);
-
-    /* render the final PAL8 frame */
-    if (s->vector_height == 4)
-        index_shift = 4;
-    else
-        index_shift = 3;
-    for (y = 0; y < s->frame.linesize[0] * s->height;
-        y += s->frame.linesize[0] * s->vector_height) {
-
-        for (x = y; x < y + s->width; x += 4, lobytes++, hibytes++) {
-            pixel_ptr = x;
-
-            /* get the vector index, the method for which varies according to
-             * VQA file version */
-            switch (s->vqa_version) {
-
-            case 1:
-/* still need sample media for this case (only one game, "Legend of
- * Kyrandia III : Malcolm's Revenge", is known to use this version) */
-                lobyte = s->decode_buffer[lobytes * 2];
-                hibyte = s->decode_buffer[(lobytes * 2) + 1];
-                vector_index = ((hibyte << 8) | lobyte) >> 3;
-                vector_index <<= index_shift;
-                lines = s->vector_height;
-                /* uniform color fill - a quick hack */
-                if (hibyte == 0xFF) {
-                    while (lines--) {
-                        s->frame.data[0][pixel_ptr + 0] = 255 - lobyte;
-                        s->frame.data[0][pixel_ptr + 1] = 255 - lobyte;
-                        s->frame.data[0][pixel_ptr + 2] = 255 - lobyte;
-                        s->frame.data[0][pixel_ptr + 3] = 255 - lobyte;
-                        pixel_ptr += s->frame.linesize[0];
-                    }
-                    lines=0;
-                }
-                break;
-
-            case 2:
-                lobyte = s->decode_buffer[lobytes];
-                hibyte = s->decode_buffer[hibytes];
-                vector_index = (hibyte << 8) | lobyte;
-                vector_index <<= index_shift;
-                lines = s->vector_height;
-                break;
-
-            case 3:
-/* not implemented yet */
-                lines = 0;
-                break;
-            }
-
-            while (lines--) {
-                s->frame.data[0][pixel_ptr + 0] = s->codebook[vector_index++];
-                s->frame.data[0][pixel_ptr + 1] = s->codebook[vector_index++];
-                s->frame.data[0][pixel_ptr + 2] = s->codebook[vector_index++];
-                s->frame.data[0][pixel_ptr + 3] = s->codebook[vector_index++];
-                pixel_ptr += s->frame.linesize[0];
-            }
-        }
-    }
-    }
+      /* decode the PAL frame */
+      current_chunk = vqa_get_chunk(VPTZ_TAG,s->buf,s->size,&current_chunk_size);
+      if (current_chunk) {
+          decode_format80(current_chunk, current_chunk_size,
+                           s->decode_buffer, s->decode_buffer_size, 1);
+          vqa_decode_pal8_video_frame(s,s->decode_buffer,s->decode_buffer_size);
+      }
+
+    /* decode the 16bit frame */
+    current_chunk = vqa_get_chunk(VPTR_TAG,s->buf,s->size,&current_chunk_size);
+    if(current_chunk)
+        vqa_decode_hc_video_frame(s,current_chunk,current_chunk_size);
+
+      current_chunk = vqa_get_chunk(VPRZ_TAG,s->buf,s->size,&current_chunk_size);
+      if(current_chunk) {
+          decode_format80(current_chunk, current_chunk_size,
+                           s->decode_buffer, s->decode_buffer_size, 0);
+          vqa_decode_hc_video_frame(s,s->decode_buffer,s->decode_buffer_size);
+      }
 
     /* handle partial codebook */
-    if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
-        /* a chunk should not have both chunk types */
-        av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: found both CBP0 and CBPZ chunks\n");
-        return;
-    }
-
-    if (cbp0_chunk != -1) {
+    current_chunk = vqa_get_chunk(CBP0_TAG,s->buf,s->size,&current_chunk_size);
+    if (current_chunk)
+        vqa_join_partial_codebook(s,CBP0_TAG,current_chunk,current_chunk_size);
 
-        chunk_size = AV_RB32(&s->buf[cbp0_chunk + 4]);
-        cbp0_chunk += CHUNK_PREAMBLE_SIZE;
-
-        /* accumulate partial codebook */
-        memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
-            &s->buf[cbp0_chunk], chunk_size);
-        s->next_codebook_buffer_index += chunk_size;
-
-        s->partial_countdown--;
-        if (s->partial_countdown == 0) {
-
-            /* time to replace codebook */
-            memcpy(s->codebook, s->next_codebook_buffer,
-                s->next_codebook_buffer_index);
-
-            /* reset accounting */
-            s->next_codebook_buffer_index = 0;
-            s->partial_countdown = s->partial_count;
-        }
-    }
-
-    if (cbpz_chunk != -1) {
-
-        chunk_size = AV_RB32(&s->buf[cbpz_chunk + 4]);
-        cbpz_chunk += CHUNK_PREAMBLE_SIZE;
-
-        /* accumulate partial codebook */
-        memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
-            &s->buf[cbpz_chunk], chunk_size);
-        s->next_codebook_buffer_index += chunk_size;
-
-        s->partial_countdown--;
-        if (s->partial_countdown == 0) {
-
-            /* decompress codebook */
-            decode_format80(s->next_codebook_buffer,
-                s->next_codebook_buffer_index,
-                s->codebook, s->codebook_size, 0);
-
-            /* reset accounting */
-            s->next_codebook_buffer_index = 0;
-            s->partial_countdown = s->partial_count;
-        }
-    }
-
-    if(vptr_chunk != -1) {
-        chunk_size = AV_RB32(&s->buf[vptr_chunk + 4]);
-        vptr_chunk += CHUNK_PREAMBLE_SIZE;
-        vqa_decode_hc_video_frame(s,&s->buf[vptr_chunk],chunk_size);
-    }
-
-    if(vprz_chunk != -1) {
-        chunk_size = AV_RB32(&s->buf[vprz_chunk + 4]);
-        vprz_chunk += CHUNK_PREAMBLE_SIZE;
-        decode_format80(&s->buf[vprz_chunk], chunk_size,
-            s->decode_buffer, s->decode_buffer_size, 0);
-        vqa_decode_hc_video_frame(s,s->decode_buffer,s->decode_buffer_size);
-    }
+    current_chunk = vqa_get_chunk(CBPZ_TAG,s->buf,s->size,&current_chunk_size);
+    if (current_chunk)
+        vqa_join_partial_codebook(s,CBPZ_TAG,current_chunk,current_chunk_size);
 }
 
 static int vqa_decode_frame(AVCodecContext *avctx,
-- 
1.6.0.4



--------------000406070301060204010203--



More information about the ffmpeg-devel mailing list