rpza.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:9k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * Quicktime Video (RPZA) Video Decoder
  3.  * Copyright (C) 2003 the ffmpeg project
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  */
  20. /**
  21.  * @file rpza.c
  22.  * QT RPZA Video Decoder by Roberto Togni <rtogni@bresciaonline.it>
  23.  * For more information about the RPZA format, visit:
  24.  *   http://www.pcisys.net/~melanson/codecs/
  25.  *
  26.  * The RPZA decoder outputs RGB555 colorspace data.
  27.  *
  28.  * Note that this decoder reads big endian RGB555 pixel values from the
  29.  * bytestream, arranges them in the host's endian order, and outputs
  30.  * them to the final rendered map in the same host endian order. This is
  31.  * intended behavior as the ffmpeg documentation states that RGB555 pixels
  32.  * shall be stored in native CPU endianness.
  33.  */
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <unistd.h>
  38. #include "common.h"
  39. #include "avcodec.h"
  40. #include "dsputil.h"
  41. typedef struct RpzaContext {
  42.     AVCodecContext *avctx;
  43.     DSPContext dsp;
  44.     AVFrame frame;
  45.     unsigned char *buf;
  46.     int size;
  47. } RpzaContext;
  48. #define ADVANCE_BLOCK() 
  49.     pixel_ptr += 4; 
  50.     if (pixel_ptr >= width) 
  51.     { 
  52.         pixel_ptr = 0; 
  53.         row_ptr += stride * 4; 
  54.     } 
  55.     total_blocks--; 
  56.     if (total_blocks < 0) 
  57.     { 
  58.         av_log(s->avctx, AV_LOG_ERROR, "warning: block counter just went negative (this should not happen)n"); 
  59.         return; 
  60.     } 
  61. }
  62. static void rpza_decode_stream(RpzaContext *s)
  63. {
  64.     int width = s->avctx->width;
  65.     int stride = s->frame.linesize[0] / 2;
  66.     int row_inc = stride - 4;
  67.     int stream_ptr = 0;
  68.     int chunk_size;
  69.     unsigned char opcode;
  70.     int n_blocks;
  71.     unsigned short colorA = 0, colorB;
  72.     unsigned short color4[4];
  73.     unsigned char index, idx;
  74.     unsigned short ta, tb;
  75.     unsigned short *pixels = (unsigned short *)s->frame.data[0];
  76.     int row_ptr = 0;
  77.     int pixel_ptr = 0;
  78.     int block_ptr;
  79.     int pixel_x, pixel_y;
  80.     int total_blocks;
  81.     /* First byte is always 0xe1. Warn if it's different */
  82.     if (s->buf[stream_ptr] != 0xe1)
  83.         av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0xe1n",
  84.             s->buf[stream_ptr]);
  85.     /* Get chunk size, ingnoring first byte */
  86.     chunk_size = BE_32(&s->buf[stream_ptr]) & 0x00FFFFFF;
  87.     stream_ptr += 4;
  88.     /* If length mismatch use size from MOV file and try to decode anyway */
  89.     if (chunk_size != s->size)
  90.         av_log(s->avctx, AV_LOG_ERROR, "MOV chunk size != encoded chunk size; using MOV chunk sizen");
  91.     chunk_size = s->size;
  92.     /* Number of 4x4 blocks in frame. */
  93.     total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
  94.     /* Process chunk data */
  95.     while (stream_ptr < chunk_size) {
  96.         opcode = s->buf[stream_ptr++]; /* Get opcode */
  97.         n_blocks = (opcode & 0x1f) + 1; /* Extract block counter from opcode */
  98.         /* If opcode MSbit is 0, we need more data to decide what to do */
  99.         if ((opcode & 0x80) == 0) {
  100.             colorA = (opcode << 8) | (s->buf[stream_ptr++]);
  101.             opcode = 0;
  102.             if ((s->buf[stream_ptr] & 0x80) != 0) {
  103.                 /* Must behave as opcode 110xxxxx, using colorA computed 
  104.                  * above. Use fake opcode 0x20 to enter switch block at 
  105.                  * the right place */
  106.                 opcode = 0x20;
  107.                 n_blocks = 1;
  108.             }
  109.         }
  110.         switch (opcode & 0xe0) {
  111.         /* Skip blocks */
  112.         case 0x80:
  113.             while (n_blocks--) {
  114.               ADVANCE_BLOCK();
  115.             }
  116.             break;
  117.         /* Fill blocks with one color */
  118.         case 0xa0:
  119.             colorA = BE_16 (&s->buf[stream_ptr]);
  120.             stream_ptr += 2;
  121.             while (n_blocks--) {
  122.                 block_ptr = row_ptr + pixel_ptr;
  123.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  124.                     for (pixel_x = 0; pixel_x < 4; pixel_x++){
  125.                         pixels[block_ptr] = colorA;
  126.                         block_ptr++;
  127.                     }
  128.                     block_ptr += row_inc;
  129.                 }
  130.                 ADVANCE_BLOCK();
  131.             }
  132.             break;
  133.         /* Fill blocks with 4 colors */
  134.         case 0xc0:
  135.             colorA = BE_16 (&s->buf[stream_ptr]);
  136.             stream_ptr += 2;
  137.         case 0x20:
  138.             colorB = BE_16 (&s->buf[stream_ptr]);
  139.             stream_ptr += 2;
  140.             /* sort out the colors */
  141.             color4[0] = colorB;
  142.             color4[1] = 0;
  143.             color4[2] = 0;
  144.             color4[3] = colorA;
  145.             /* red components */
  146.             ta = (colorA >> 10) & 0x1F;
  147.             tb = (colorB >> 10) & 0x1F;
  148.             color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10;
  149.             color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10;
  150.             /* green components */
  151.             ta = (colorA >> 5) & 0x1F;
  152.             tb = (colorB >> 5) & 0x1F;
  153.             color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5;
  154.             color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5;
  155.             /* blue components */
  156.             ta = colorA & 0x1F;
  157.             tb = colorB & 0x1F;
  158.             color4[1] |= ((11 * ta + 21 * tb) >> 5);
  159.             color4[2] |= ((21 * ta + 11 * tb) >> 5);
  160.             while (n_blocks--) {
  161.                 block_ptr = row_ptr + pixel_ptr;
  162.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  163.                     index = s->buf[stream_ptr++];
  164.                     for (pixel_x = 0; pixel_x < 4; pixel_x++){
  165.                         idx = (index >> (2 * (3 - pixel_x))) & 0x03;
  166.                         pixels[block_ptr] = color4[idx];
  167.                         block_ptr++;
  168.                     }
  169.                     block_ptr += row_inc;
  170.                 }
  171.                 ADVANCE_BLOCK();
  172.             }
  173.             break;
  174.         /* Fill block with 16 colors */
  175.         case 0x00:
  176.             block_ptr = row_ptr + pixel_ptr;
  177.             for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  178.                 for (pixel_x = 0; pixel_x < 4; pixel_x++){
  179.                     /* We already have color of upper left pixel */
  180.                     if ((pixel_y != 0) || (pixel_x !=0)) {
  181.                         colorA = BE_16 (&s->buf[stream_ptr]);
  182.                         stream_ptr += 2;
  183.                     }
  184.                     pixels[block_ptr] = colorA;
  185.                     block_ptr++;
  186.                 }
  187.                 block_ptr += row_inc;
  188.             }
  189.             ADVANCE_BLOCK();
  190.             break;
  191.         /* Unknown opcode */
  192.         default:
  193.             av_log(s->avctx, AV_LOG_ERROR, "Unknown opcode %d in rpza chunk."
  194.                  " Skip remaining %d bytes of chunk data.n", opcode,
  195.                  chunk_size - stream_ptr);
  196.             return;
  197.         } /* Opcode switch */
  198.     }
  199. }
  200. static int rpza_decode_init(AVCodecContext *avctx)
  201. {
  202.     RpzaContext *s = (RpzaContext *)avctx->priv_data;
  203.     s->avctx = avctx;
  204.     avctx->pix_fmt = PIX_FMT_RGB555;
  205.     avctx->has_b_frames = 0;
  206.     dsputil_init(&s->dsp, avctx);
  207.     s->frame.data[0] = NULL;
  208.     return 0;
  209. }
  210. static int rpza_decode_frame(AVCodecContext *avctx,
  211.                              void *data, int *data_size,
  212.                              uint8_t *buf, int buf_size)
  213. {
  214.     RpzaContext *s = (RpzaContext *)avctx->priv_data;
  215.     s->buf = buf;
  216.     s->size = buf_size;
  217.     s->frame.reference = 1;
  218.     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
  219.     if (avctx->reget_buffer(avctx, &s->frame)) {
  220.         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failedn");
  221.         return -1;
  222.     }
  223.     rpza_decode_stream(s);
  224.     *data_size = sizeof(AVFrame);
  225.     *(AVFrame*)data = s->frame;
  226.     /* always report that the buffer was completely consumed */
  227.     return buf_size;
  228. }
  229. static int rpza_decode_end(AVCodecContext *avctx)
  230. {
  231.     RpzaContext *s = (RpzaContext *)avctx->priv_data;
  232.     if (s->frame.data[0])
  233.         avctx->release_buffer(avctx, &s->frame);
  234.     return 0;
  235. }
  236. AVCodec rpza_decoder = {
  237.     "rpza",
  238.     CODEC_TYPE_VIDEO,
  239.     CODEC_ID_RPZA,
  240.     sizeof(RpzaContext),
  241.     rpza_decode_init,
  242.     NULL,
  243.     rpza_decode_end,
  244.     rpza_decode_frame,
  245.     CODEC_CAP_DR1,
  246. };