⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xan.c

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Wing Commander/Xan Video Decoder * Copyright (C) 2003 the ffmpeg project * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//** * @file xan.c * Xan video decoder for Wing Commander III & IV computer games * by Mario Brito (mbrito@student.dei.uc.pt) * and Mike Melanson (melanson@pcisys.net) * * The xan_wc3 decoder outputs the following colorspaces natively: *   PAL8 (default), RGB555, RGB565, RGB24, BGR24, RGBA32, YUV444P */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "common.h"#include "avcodec.h"#include "dsputil.h"#define PALETTE_COUNT 256#define PALETTE_CONTROL_SIZE ((256 * 3) + 1)typedef struct XanContext {    AVCodecContext *avctx;    DSPContext dsp;    AVFrame last_frame;    AVFrame current_frame;    unsigned char *buf;    int size;    unsigned char palette[PALETTE_COUNT * 4];    /* scratch space */    unsigned char *buffer1;    unsigned char *buffer2;} XanContext;#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \                   (((uint8_t*)(x))[2] << 16) | \                   (((uint8_t*)(x))[1] << 8) | \                    ((uint8_t*)(x))[0])/* RGB -> YUV conversion stuff */#define SCALEFACTOR 65536#define CENTERSAMPLE 128#define COMPUTE_Y(r, g, b) \  (unsigned char) \  ((y_r_table[r] + y_g_table[g] + y_b_table[b]) / SCALEFACTOR)#define COMPUTE_U(r, g, b) \  (unsigned char) \  ((u_r_table[r] + u_g_table[g] + u_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)#define COMPUTE_V(r, g, b) \  (unsigned char) \  ((v_r_table[r] + v_g_table[g] + v_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)#define Y_R (SCALEFACTOR *  0.29900)#define Y_G (SCALEFACTOR *  0.58700)#define Y_B (SCALEFACTOR *  0.11400)#define U_R (SCALEFACTOR * -0.16874)#define U_G (SCALEFACTOR * -0.33126)#define U_B (SCALEFACTOR *  0.50000)#define V_R (SCALEFACTOR *  0.50000)#define V_G (SCALEFACTOR * -0.41869)#define V_B (SCALEFACTOR * -0.08131)/* * Precalculate all of the YUV tables since it requires fewer than * 10 kilobytes to store them. */static int y_r_table[256];static int y_g_table[256];static int y_b_table[256];static int u_r_table[256];static int u_g_table[256];static int u_b_table[256];static int v_r_table[256];static int v_g_table[256];static int v_b_table[256];static int xan_decode_init(AVCodecContext *avctx){    XanContext *s = avctx->priv_data;    int i;    s->avctx = avctx;    if ((avctx->codec->id == CODEC_ID_XAN_WC3) &&         (s->avctx->palctrl == NULL)) {        av_log(avctx, AV_LOG_ERROR, " WC3 Xan video: palette expected.\n");        return -1;    }    avctx->pix_fmt = PIX_FMT_PAL8;    avctx->has_b_frames = 0;    dsputil_init(&s->dsp, avctx);    /* initialize the RGB -> YUV tables */    for (i = 0; i < 256; i++) {        y_r_table[i] = Y_R * i;        y_g_table[i] = Y_G * i;        y_b_table[i] = Y_B * i;        u_r_table[i] = U_R * i;        u_g_table[i] = U_G * i;        u_b_table[i] = U_B * i;        v_r_table[i] = V_R * i;        v_g_table[i] = V_G * i;        v_b_table[i] = V_B * i;    }    s->buffer1 = av_malloc(avctx->width * avctx->height);    s->buffer2 = av_malloc(avctx->width * avctx->height);    if (!s->buffer1 || !s->buffer2)        return -1;    return 0;}/* This function is used in lieu of memcpy(). This decoder can not 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, 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, unsigned char *src){    unsigned char byte = *src++;    unsigned char ival = byte + 0x16;    unsigned char * ptr = src + byte*2;    unsigned char val = ival;    int counter = 0;    unsigned char bits = *ptr++;    while ( val != 0x16 ) {        if ( (1 << counter) & bits )            val = src[byte + val - 0x17];        else            val = src[val - 0x17];        if ( val < 0x16 ) {            *dest++ = val;            val = ival;        }        if (counter++ == 7) {            counter = 0;            bits = *ptr++;        }    }    return 0;}static void xan_unpack(unsigned char *dest, unsigned char *src){    unsigned char opcode;    int size;    int offset;    int byte1, byte2, byte3;    for (;;) {        opcode = *src++;        if ( (opcode & 0x80) == 0 ) {            offset = *src++;            size = opcode & 3;            bytecopy(dest, src, size);  dest += size;  src += size;            size = ((opcode & 0x1c) >> 2) + 3;            bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);            dest += size;        } else if ( (opcode & 0x40) == 0 ) {            byte1 = *src++;            byte2 = *src++;            size = byte1 >> 6;            bytecopy (dest, src, size);  dest += size;  src += size;            size = (opcode & 0x3f) + 4;            bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);            dest += size;        } else if ( (opcode & 0x20) == 0 ) {            byte1 = *src++;            byte2 = *src++;            byte3 = *src++;            size = opcode & 3;            bytecopy (dest, src, size);  dest += size;  src += size;            size = byte3 + 5 + ((opcode & 0xc) << 6);            bytecopy (dest,                dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),                size);            dest += size;        } else {            size = ((opcode & 0x1f) << 2) + 4;            if (size > 0x70)                break;            bytecopy (dest, src, size);  dest += size;  src += size;        }    }    size = opcode & 3;    bytecopy(dest, src, size);  dest += size;  src += size;}static void inline xan_wc3_build_palette(XanContext *s,     unsigned int *palette_data){    int i;    unsigned char r, g, b;    unsigned short *palette16;    unsigned int *palette32;    unsigned int pal_elem;    /* transform the palette passed through the palette control structure     * into the necessary internal format depending on colorspace */    switch (s->avctx->pix_fmt) {    case PIX_FMT_RGB555:        palette16 = (unsigned short *)s->palette;        for (i = 0; i < PALETTE_COUNT; i++) {            pal_elem = palette_data[i];            r = (pal_elem >> 16) & 0xff;            g = (pal_elem >> 8) & 0xff;            b = pal_elem & 0xff;            palette16[i] =                 ((r >> 3) << 10) |                ((g >> 3) <<  5) |                ((b >> 3) <<  0);        }        break;    case PIX_FMT_RGB565:        palette16 = (unsigned short *)s->palette;        for (i = 0; i < PALETTE_COUNT; i++) {            pal_elem = palette_data[i];            r = (pal_elem >> 16) & 0xff;            g = (pal_elem >> 8) & 0xff;            b = pal_elem & 0xff;            palette16[i] =                 ((r >> 3) << 11) |                ((g >> 2) <<  5) |                ((b >> 3) <<  0);        }        break;    case PIX_FMT_RGB24:        for (i = 0; i < PALETTE_COUNT; i++) {            pal_elem = palette_data[i];            r = (pal_elem >> 16) & 0xff;            g = (pal_elem >> 8) & 0xff;            b = pal_elem & 0xff;            s->palette[i * 4 + 0] = r;            s->palette[i * 4 + 1] = g;            s->palette[i * 4 + 2] = b;        }        break;    case PIX_FMT_BGR24:        for (i = 0; i < PALETTE_COUNT; i++) {            pal_elem = palette_data[i];            r = (pal_elem >> 16) & 0xff;            g = (pal_elem >> 8) & 0xff;            b = pal_elem & 0xff;            s->palette[i * 4 + 0] = b;            s->palette[i * 4 + 1] = g;            s->palette[i * 4 + 2] = r;        }        break;    case PIX_FMT_PAL8:    case PIX_FMT_RGBA32:        palette32 = (unsigned int *)s->palette;        memcpy (palette32, palette_data, PALETTE_COUNT * sizeof(unsigned int));        break;    case PIX_FMT_YUV444P:        for (i = 0; i < PALETTE_COUNT; i++) {            pal_elem = palette_data[i];            r = (pal_elem >> 16) & 0xff;            g = (pal_elem >> 8) & 0xff;            b = pal_elem & 0xff;            s->palette[i * 4 + 0] = COMPUTE_Y(r, g, b);            s->palette[i * 4 + 1] = COMPUTE_U(r, g, b);            s->palette[i * 4 + 2] = COMPUTE_V(r, g, b);        }        break;    default:        av_log(s->avctx, AV_LOG_ERROR, " Xan WC3: Unhandled colorspace\n");        break;    }}/* advance current_x variable; reset accounting variables if current_x * moves beyond width */#define ADVANCE_CURRENT_X() \    current_x++; \    if (current_x >= width) { \        index += line_inc; \        current_x = 0; \    }static void inline xan_wc3_output_pixel_run(XanContext *s,     unsigned char *pixel_buffer, int x, int y, int pixel_count){    int stride;    int line_inc;    int index;    int current_x;    int width = s->avctx->width;    unsigned char pix;    unsigned char *palette_plane;    unsigned char *y_plane;    unsigned char *u_plane;    unsigned char *v_plane;    unsigned char *rgb_plane;    unsigned short *rgb16_plane;    unsigned short *palette16;    unsigned int *rgb32_plane;    unsigned int *palette32;    switch (s->avctx->pix_fmt) {    case PIX_FMT_PAL8:        palette_plane = s->current_frame.data[0];        stride = s->current_frame.linesize[0];        line_inc = stride - width;        index = y * stride + x;        current_x = x;        while(pixel_count--) {            /* don't do a memcpy() here; keyframes generally copy an entire             * frame of data and the stride needs to be accounted for */            palette_plane[index++] = *pixel_buffer++;            ADVANCE_CURRENT_X();        }        break;    case PIX_FMT_RGB555:    case PIX_FMT_RGB565:        rgb16_plane = (unsigned short *)s->current_frame.data[0];        palette16 = (unsigned short *)s->palette;        stride = s->current_frame.linesize[0] / 2;        line_inc = stride - width;        index = y * stride + x;        current_x = x;        while(pixel_count--) {            rgb16_plane[index++] = palette16[*pixel_buffer++];            ADVANCE_CURRENT_X();        }        break;    case PIX_FMT_RGB24:    case PIX_FMT_BGR24:        rgb_plane = s->current_frame.data[0];        stride = s->current_frame.linesize[0];        line_inc = stride - width * 3;        index = y * stride + x * 3;        current_x = x;        while(pixel_count--) {            pix = *pixel_buffer++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -