[PATCH] Add 16 bit video decoding

Adam Iglewski none szwagros
Wed May 6 22:14:30 CEST 2009


---
 libavcodec/vqavideo.c |  141 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c
index 5026989..da2ff8f 100644
--- a/libavcodec/vqavideo.c
+++ b/libavcodec/vqavideo.c
@@ -70,6 +70,7 @@
 
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
+#include "bytestream.h"
 
 #define PALETTE_COUNT 256
 #define VQA_HEADER_SIZE 0x2A
@@ -89,6 +90,8 @@
 #define CPL0_TAG MKBETAG('C', 'P', 'L', '0')
 #define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z')
 #define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z')
+#define VPTR_TAG MKBETAG('V', 'P', 'T', 'R')
+#define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z')
 
 #define VQA_DEBUG 0
 
@@ -135,7 +138,6 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx)
     int i, j, codebook_index;
 
     s->avctx = avctx;
-    avctx->pix_fmt = PIX_FMT_PAL8;
 
     /* make sure the extradata made it */
     if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
@@ -156,6 +158,11 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx)
     s->vector_height = vqa_header[11];
     s->partial_count = s->partial_countdown = vqa_header[13];
 
+    if(!AV_RL16(&vqa_header[14]))
+        avctx->pix_fmt = PIX_FMT_RGB555;
+    else
+        avctx->pix_fmt = PIX_FMT_PAL8;
+
     /* the vector dimensions have to meet very stringent requirements */
     if ((s->vector_width != 4) ||
         ((s->vector_height != 2) && (s->vector_height != 4))) {
@@ -205,11 +212,17 @@ static void decode_format80(const unsigned char *src, int src_size,
 
     int src_index = 0;
     int dest_index = 0;
+    int new_format = 0;
     int count;
     int src_pos;
     unsigned char color;
     int i;
 
+    if (!src[src_index] || src_size > 0xffff) {
+        new_format = 1;
+        src_index++;
+    }
+
     while (src_index < src_size) {
 
         vqa_debug("      opcode %02X: ", src[src_index]);
@@ -230,6 +243,8 @@ static void decode_format80(const unsigned char *src, int src_size,
             count = AV_RL16(&src[src_index]);
             src_index += 2;
             src_pos = AV_RL16(&src[src_index]);
+            if(new_format)
+                src_pos = dest_index-src_pos;
             src_index += 2;
             vqa_debug("(1) copy %X bytes from absolute pos %X\n", count, src_pos);
             CHECK_COUNT();
@@ -252,6 +267,8 @@ static void decode_format80(const unsigned char *src, int src_size,
 
             count = (src[src_index++] & 0x3F) + 3;
             src_pos = AV_RL16(&src[src_index]);
+            if(new_format)
+                src_pos = dest_index-src_pos;
             src_index += 2;
             vqa_debug("(3) copy %X bytes from absolute pos %X\n", count, src_pos);
             CHECK_COUNT();
@@ -291,6 +308,86 @@ static void decode_format80(const unsigned char *src, int src_size,
                 dest_index, dest_size);
 }
 
+static inline void vqa_copy_hc_block(uint16_t *pixels,int stride,const uint16_t *codebook,
+                                      int block_h)
+{
+    while(block_h--) {
+        memcpy(pixels,codebook,8);
+        pixels += stride;
+        codebook += 4;
+    }
+}
+
+static void vqa_decode_hc_video_chunk(VqaContext *s,const unsigned char *src,unsigned int src_size)
+{
+    int block_x, block_y;          /* block width and height iterators */
+    int blocks_wide, blocks_high;  /* width and height in 4x4|2 blocks */
+    int block_inc;
+    int index_shift;
+    int i;
+
+    /* decoding parameters */
+    uint16_t *pixels,*frame_end;
+    uint16_t *codebook = (uint16_t *)s->codebook;
+    int stride = s->frame.linesize[0] >> 1;
+
+    int type,code;
+    int vector_index = 0;
+
+    blocks_wide = s->width >> 2;
+    blocks_high = s->height / s->vector_height;
+    block_inc = 4;
+    frame_end = (uint16_t *)s->frame.data[0] + s->height * stride + s->width;
+
+    if (s->vector_height == 4)
+        index_shift = 4;
+    else
+        index_shift = 3;
+
+    for(block_y=0; block_y < blocks_high; block_y ++) {
+        pixels = (uint16_t *)s->frame.data[0] + (block_y * s->vector_height * stride);
+
+        for(block_x=0; block_x < blocks_wide; ) {
+            int blocks_done;
+            code = bytestream_get_le16(&src);
+            type = code >> 13;
+            code &= 0x1fff;
+
+            if(!type) {
+                    blocks_done = code;
+                    block_x += blocks_done;
+                    pixels += blocks_done * block_inc;
+                    continue;
+            } else if (type < 3) {
+                    vector_index = (code & 0xff) << index_shift;
+                    blocks_done = ((code & 0x1f00) >> 7) + 1 + type;
+            } else if (type == 3 || type == 5) {
+                    vector_index = code << index_shift;
+                    if (type == 3)
+                        blocks_done = 1;
+                    else
+                        blocks_done = *src++;
+            } else {
+                    av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type);
+                    return;
+            }
+
+            if(pixels + s->vector_height * stride + blocks_done * block_inc > frame_end) {
+                av_log(s->avctx, AV_LOG_ERROR, " too many blocks in frame.\n");
+                return;
+            }
+
+            for(i=0; i < blocks_done; i++) {
+                if(i && (type == 2))
+                    vector_index = *src++ << index_shift;
+                vqa_copy_hc_block(pixels,stride,&codebook[vector_index],s->vector_height);
+                pixels += block_inc;
+            }
+            block_x += blocks_done;
+        }
+    }
+}
+
 static void vqa_decode_chunk(VqaContext *s)
 {
     unsigned int chunk_type;
@@ -308,6 +405,8 @@ static void vqa_decode_chunk(VqaContext *s)
     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;
@@ -354,6 +453,14 @@ static void vqa_decode_chunk(VqaContext *s)
             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,
@@ -436,13 +543,15 @@ static void vqa_decode_chunk(VqaContext *s)
     }
 
     /* decode the frame */
-    if (vptz_chunk == -1) {
+    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 chunk found\n");
+        av_log(s->avctx, AV_LOG_ERROR, "  VQA video: problem: no VPTZ or VPTR or VPRZ chunk found\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,
@@ -507,6 +616,7 @@ static void vqa_decode_chunk(VqaContext *s)
             }
         }
     }
+    }
 
     /* handle partial codebook */
     if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) {
@@ -561,6 +671,20 @@ static void vqa_decode_chunk(VqaContext *s)
             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_chunk(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_chunk(s,s->decode_buffer,s->decode_buffer_size);
+    }
 }
 
 static int vqa_decode_frame(AVCodecContext *avctx,
@@ -574,6 +698,7 @@ static int vqa_decode_frame(AVCodecContext *avctx,
     s->buf = buf;
     s->size = buf_size;
 
+    if (s->avctx->pix_fmt == PIX_FMT_PAL8) {
     if (s->frame.data[0])
         avctx->release_buffer(avctx, &s->frame);
 
@@ -581,12 +706,22 @@ static int vqa_decode_frame(AVCodecContext *avctx,
         av_log(s->avctx, AV_LOG_ERROR, "  VQA Video: get_buffer() failed\n");
         return -1;
     }
+    } else {
+        s->frame.reference = 1;
+        s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+        if (avctx->reget_buffer(avctx, &s->frame)) {
+            av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+            return -1;
+        }
+    }
 
     vqa_decode_chunk(s);
 
+    if (s->avctx->pix_fmt == PIX_FMT_PAL8) {
     /* make the palette available on the way out */
     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
     s->frame.palette_has_changed = 1;
+    }
 
     *data_size = sizeof(AVFrame);
     *(AVFrame*)data = s->frame;
-- 
1.6.0.4


--------------010706080102070000040602
Content-Type: text/x-diff;
 name="0002-Add-IMA_WS_V3-codec-id.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0002-Add-IMA_WS_V3-codec-id.patch"




More information about the ffmpeg-devel mailing list