]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blobdiff - libavcodec/xan.c
frsh: Export information about the last RTP contract and VRES
[frescor/ffmpeg.git] / libavcodec / xan.c
index 36e944fdb1a4d54ced040f0b0f0aff5037acee4b..aacdcc1b830fd8c7130e9eca74f959c5b8e04a55 100644 (file)
 
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
+#include "bytestream.h"
+#define ALT_BITSTREAM_READER_LE
+#include "get_bits.h"
+// for av_memcpy_backptr
+#include "libavutil/lzo.h"
 
 typedef struct XanContext {
 
@@ -76,26 +81,13 @@ static av_cold int xan_decode_init(AVCodecContext *avctx)
     s->buffer1_size = avctx->width * avctx->height;
     s->buffer1 = av_malloc(s->buffer1_size);
     s->buffer2_size = avctx->width * avctx->height;
-    s->buffer2 = av_malloc(s->buffer2_size);
+    s->buffer2 = av_malloc(s->buffer2_size + 130);
     if (!s->buffer1 || !s->buffer2)
         return -1;
 
     return 0;
 }
 
-/* This function is used in lieu of memcpy(). This decoder cannot use
- * memcpy because the memory locations often overlap and
- * memcpy doesn't like that; it's not uncommon, for example, for
- * dest = src+1, to turn byte A into  pattern AAAAAAAA.
- * This was originally repz movsb in Intel x86 ASM. */
-static inline void bytecopy(unsigned char *dest, const unsigned char *src, int count)
-{
-    int i;
-
-    for (i = 0; i < count; i++)
-        dest[i] = src[i];
-}
-
 static int xan_huffman_decode(unsigned char *dest, const unsigned char *src,
     int dest_len)
 {
@@ -103,107 +95,80 @@ static int xan_huffman_decode(unsigned char *dest, const unsigned char *src,
     unsigned char ival = byte + 0x16;
     const unsigned char * ptr = src + byte*2;
     unsigned char val = ival;
-    int counter = 0;
     unsigned char *dest_end = dest + dest_len;
+    GetBitContext gb;
 
-    unsigned char bits = *ptr++;
+    init_get_bits(&gb, ptr, 0); // FIXME: no src size available
 
     while ( val != 0x16 ) {
-        if ( (1 << counter) & bits )
-            val = src[byte + val - 0x17];
-        else
-            val = src[val - 0x17];
+        val = src[val - 0x17 + get_bits1(&gb) * byte];
 
         if ( val < 0x16 ) {
-            if (dest + 1 > dest_end)
+            if (dest >= dest_end)
                 return 0;
             *dest++ = val;
             val = ival;
         }
-
-        if (counter++ == 7) {
-            counter = 0;
-            bits = *ptr++;
-        }
     }
 
     return 0;
 }
 
+/**
+ * unpack simple compression
+ *
+ * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
+ */
 static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len)
 {
     unsigned char opcode;
     int size;
-    int offset;
-    int byte1, byte2, byte3;
     unsigned char *dest_end = dest + dest_len;
 
-    for (;;) {
+    while (dest < dest_end) {
         opcode = *src++;
 
-        if ( (opcode & 0x80) == 0 ) {
+        if (opcode < 0xe0) {
+            int size2, back;
+            if ( (opcode & 0x80) == 0 ) {
 
-            offset = *src++;
+                size = opcode & 3;
 
-            size = opcode & 3;
-            if (dest + size > dest_end)
-                return;
-            memcpy(dest, src, size);  dest += size;  src += size;
+                back  = ((opcode & 0x60) << 3) + *src++ + 1;
+                size2 = ((opcode & 0x1c) >> 2) + 3;
 
-            size = ((opcode & 0x1c) >> 2) + 3;
-            if (dest + size > dest_end)
-                return;
-            bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
-            dest += size;
+            } else if ( (opcode & 0x40) == 0 ) {
 
-        } else if ( (opcode & 0x40) == 0 ) {
+                size = *src >> 6;
 
-            byte1 = *src++;
-            byte2 = *src++;
-
-            size = byte1 >> 6;
-            if (dest + size > dest_end)
-                return;
-            memcpy(dest, src, size);  dest += size;  src += size;
+                back  = (bytestream_get_be16(&src) & 0x3fff) + 1;
+                size2 = (opcode & 0x3f) + 4;
 
-            size = (opcode & 0x3f) + 4;
-            if (dest + size > dest_end)
-                return;
-            bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
-            dest += size;
-
-        } else if ( (opcode & 0x20) == 0 ) {
+            } else {
 
-            byte1 = *src++;
-            byte2 = *src++;
-            byte3 = *src++;
+                size = opcode & 3;
 
-            size = opcode & 3;
-            if (dest + size > dest_end)
-                return;
+                back  = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
+                size2 = ((opcode & 0x0c) <<  6) + *src++ + 5;
+                if (size + size2 > dest_end - dest)
+                    return;
+            }
             memcpy(dest, src, size);  dest += size;  src += size;
-
-            size = byte3 + 5 + ((opcode & 0xc) << 6);
-            if (dest + size > dest_end)
-                return;
-            bytecopy (dest,
-                dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
-                size);
-            dest += size;
+            av_memcpy_backptr(dest, back, size2);
+            dest += size2;
         } else {
+            int finish;
             size = ((opcode & 0x1f) << 2) + 4;
 
-            if (size > 0x70)
-                break;
+            finish = size > 0x70;
+            if (finish)
+                size = opcode & 3;
 
-            if (dest + size > dest_end)
-                return;
             memcpy(dest, src, size);  dest += size;  src += size;
+            if (finish)
+                return;
         }
     }
-
-    size = opcode & 3;
-    memcpy(dest, src, size);  dest += size;  src += size;
 }
 
 static inline void xan_wc3_output_pixel_run(XanContext *s,
@@ -369,16 +334,10 @@ static void xan_wc3_decode_frame(XanContext *s) {
             }
         } else {
             /* run-based motion compensation from last frame */
-            motion_x = (*vector_segment >> 4) & 0xF;
-            motion_y = *vector_segment & 0xF;
+            motion_x = sign_extend(*vector_segment >> 4,  4);
+            motion_y = sign_extend(*vector_segment & 0xF, 4);
             vector_segment++;
 
-            /* sign extension */
-            if (motion_x & 0x8)
-                motion_x |= 0xFFFFFFF0;
-            if (motion_y & 0x8)
-                motion_y |= 0xFFFFFFF0;
-
             /* copy a run of pixels from the previous frame */
             xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
 
@@ -387,16 +346,8 @@ static void xan_wc3_decode_frame(XanContext *s) {
 
         /* coordinate accounting */
         total_pixels -= size;
-        while (size) {
-            if (x + size >= width) {
-                y++;
-                size -= (width - x);
-                x = 0;
-            } else {
-                x += size;
-                size = 0;
-            }
-        }
+        y += (x + size) / width;
+        x  = (x + size) % width;
     }
 }