[PATCH] Simplify vqa_decode_chunk part I

Adam Iglewski adam.iglewski
Sat May 9 11:42:25 CEST 2009


---
 libavcodec/vqavideo.c |  119 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c
index 9646d67..e991cdd 100644
--- a/libavcodec/vqavideo.c
+++ b/libavcodec/vqavideo.c
@@ -121,6 +121,7 @@ typedef struct VqaContext {
     int codebook_size;
     unsigned char *next_codebook_buffer;  /* accumulator for next codebook */
     int next_codebook_buffer_index;
+    int is_codebook;
 
     unsigned char *decode_buffer;
     int decode_buffer_size;
@@ -188,6 +189,7 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx)
                 s->codebook[codebook_index++] = i;
     }
     s->next_codebook_buffer_index = 0;
+    s->is_codebook = 0;
 
     /* allocate decode buffer */
     s->decode_buffer_size = (s->width / s->vector_width) *
@@ -345,6 +347,123 @@ static void vqa_decode_hc_video_frame(VqaContext *s,const unsigned char *src,uns
     }
 }
 
+static void vqa_decode_pal8_video_frame(VqaContext *s,const unsigned char *src,unsigned int src_size)
+{
+    int x, y;
+    int lines;
+    int vector_index;
+    int index_shift;
+
+    unsigned char *pixels, *frame_end;
+    const unsigned char *mid_src = src + (src_size>>1);
+    unsigned int *codebook = (unsigned int *)s->codebook;
+
+    frame_end = s->frame.data[0] + s->height * s->frame.linesize[0] + s->width;
+
+    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) {
+            pixels = s->frame.data[0] + x;
+            lines = s->vector_height;
+
+            /* 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) */
+
+                vector_index = bytestream_get_le16(&src);
+
+                /* uniform color fill - a quick hack */
+                if((vector_index & 0xff00) == 0xff00) {
+                    while(lines--) {
+                        memset(pixels,255-(vector_index & 0x00ff),4);
+                        pixels += s->frame.linesize[0];
+                    }
+                    continue;
+                }
+                vector_index >>= 3;
+                break;
+
+            case 2:
+                vector_index = (*mid_src++ << 8) | *src++;
+                break;
+            }
+
+            codebook = (unsigned int *) (s->codebook + (vector_index << index_shift));
+            while (lines--) {
+                *(unsigned int *) pixels = *codebook++;
+                pixels += s->frame.linesize[0];
+            }
+        }
+    }
+}
+
+static const unsigned char* vqa_get_chunk(unsigned int chunk_type, const unsigned char *buff,
+                                     unsigned int buff_size,unsigned int *chunk_size)
+{
+    const unsigned char *buff_end = buff + buff_size;
+    unsigned int curr_chunk_type;
+    unsigned int curr_chunk_size;
+
+    while(buff + CHUNK_PREAMBLE_SIZE < buff_end)
+    {
+        curr_chunk_type = bytestream_get_be32(&buff);
+        curr_chunk_size = bytestream_get_be32(&buff);
+        if(chunk_type == curr_chunk_type)
+        {
+            if(curr_chunk_size + buff > buff_end) {
+                av_log(NULL, AV_LOG_ERROR, "  VQA video: problem: chunk exceeded packet size\n");
+                return 0;
+            }
+            *chunk_size = curr_chunk_size;
+            return buff;
+        }
+        buff += curr_chunk_size + (curr_chunk_size & 0x01);
+    }
+
+    return 0;
+}
+
+static void vqa_join_partial_codebook(VqaContext *s,unsigned int chunk_type,const unsigned char *chunk,
+                                       unsigned int chunk_size)
+{
+    if (s->next_codebook_buffer_index + chunk_size > MAX_CODEBOOK_SIZE) {
+        av_log(s->avctx, AV_LOG_ERROR, "  problem: partial codebook bigger than max allowed size\n");
+        return;
+    }
+    /* accumulate partial codebook */
+    memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
+            chunk, chunk_size);
+    s->next_codebook_buffer_index += chunk_size;
+
+    s->partial_countdown--;
+    if (!s->partial_countdown) {
+
+        /* time to replace codebook */
+        if (chunk_type == CBP0_TAG)
+            memcpy(s->codebook, s->next_codebook_buffer,
+                    s->next_codebook_buffer_index);
+        else
+            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;
+        s->is_codebook = 1;
+    }
+}
+
 static void vqa_decode_chunk(VqaContext *s)
 {
     unsigned int chunk_type;
-- 
1.6.0.4



--------------000406070301060204010203
Content-Type: text/x-diff;
 name="0007-Simplify-vqa_decode_chunk-part-II.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0007-Simplify-vqa_decode_chunk-part-II.patch"




More information about the ffmpeg-devel mailing list