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

Windows CE

开发平台:

C/C++

  1. /*
  2.  * Quicktime Graphics (SMC) 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 smc.c
  22.  * QT SMC Video Decoder by Mike Melanson (melanson@pcisys.net)
  23.  * For more information about the SMC format, visit:
  24.  *   http://www.pcisys.net/~melanson/codecs/
  25.  *
  26.  * The SMC decoder outputs PAL8 colorspace data.
  27.  */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. #include "common.h"
  33. #include "avcodec.h"
  34. #include "dsputil.h"
  35. #define CPAIR 2
  36. #define CQUAD 4
  37. #define COCTET 8
  38. #define COLORS_PER_TABLE 256
  39. typedef struct SmcContext {
  40.     AVCodecContext *avctx;
  41.     DSPContext dsp;
  42.     AVFrame frame;
  43.     unsigned char *buf;
  44.     int size;
  45.     /* SMC color tables */
  46.     unsigned char color_pairs[COLORS_PER_TABLE * CPAIR];
  47.     unsigned char color_quads[COLORS_PER_TABLE * CQUAD];
  48.     unsigned char color_octets[COLORS_PER_TABLE * COCTET];
  49. } SmcContext;
  50. #define GET_BLOCK_COUNT() 
  51.   (opcode & 0x10) ? (1 + s->buf[stream_ptr++]) : 1 + (opcode & 0x0F);
  52. #define ADVANCE_BLOCK() 
  53.     pixel_ptr += 4; 
  54.     if (pixel_ptr >= width) 
  55.     { 
  56.         pixel_ptr = 0; 
  57.         row_ptr += stride * 4; 
  58.     } 
  59.     total_blocks--; 
  60.     if (total_blocks < 0) 
  61.     { 
  62.         av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)n"); 
  63.         return; 
  64.     } 
  65. }
  66. static void smc_decode_stream(SmcContext *s)
  67. {
  68.     int width = s->avctx->width;
  69.     int height = s->avctx->height;
  70.     int stride = s->frame.linesize[0];
  71.     int i;
  72.     int stream_ptr = 0;
  73.     int chunk_size;
  74.     unsigned char opcode;
  75.     int n_blocks;
  76.     unsigned int color_flags;
  77.     unsigned int color_flags_a;
  78.     unsigned int color_flags_b;
  79.     unsigned int flag_mask;
  80.     unsigned char *pixels = s->frame.data[0];
  81.     int image_size = height * s->frame.linesize[0];
  82.     int row_ptr = 0;
  83.     int pixel_ptr = 0;
  84.     int pixel_x, pixel_y;
  85.     int row_inc = stride - 4;
  86.     int block_ptr;
  87.     int prev_block_ptr;
  88.     int prev_block_ptr1, prev_block_ptr2;
  89.     int prev_block_flag;
  90.     int total_blocks;
  91.     int color_table_index;  /* indexes to color pair, quad, or octet tables */
  92.     int pixel;
  93.     int color_pair_index = 0;
  94.     int color_quad_index = 0;
  95.     int color_octet_index = 0;
  96.     /* make the palette available */
  97.     memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
  98.     if (s->avctx->palctrl->palette_changed) {
  99.         s->frame.palette_has_changed = 1;
  100.         s->avctx->palctrl->palette_changed = 0;
  101.     }
  102.     chunk_size = BE_32(&s->buf[stream_ptr]) & 0x00FFFFFF;
  103.     stream_ptr += 4;
  104.     if (chunk_size != s->size)
  105.         av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk sizen",
  106.             chunk_size, s->size);
  107.     chunk_size = s->size;
  108.     total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
  109.     /* traverse through the blocks */
  110.     while (total_blocks) {
  111.         /* sanity checks */
  112.         /* make sure stream ptr hasn't gone out of bounds */
  113.         if (stream_ptr > chunk_size) {
  114.             av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)n",
  115.                 stream_ptr, chunk_size);
  116.             return;
  117.         }
  118.         /* make sure the row pointer hasn't gone wild */
  119.         if (row_ptr >= image_size) {
  120.             av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)n",
  121.                 row_ptr, image_size);
  122.             return;
  123.         }
  124.         opcode = s->buf[stream_ptr++];
  125.         switch (opcode & 0xF0) {
  126.         /* skip n blocks */
  127.         case 0x00:
  128.         case 0x10:
  129.             n_blocks = GET_BLOCK_COUNT();
  130.             while (n_blocks--) {
  131.                 ADVANCE_BLOCK();
  132.             }
  133.             break;
  134.         /* repeat last block n times */
  135.         case 0x20:
  136.         case 0x30:
  137.             n_blocks = GET_BLOCK_COUNT();
  138.             /* sanity check */
  139.             if ((row_ptr == 0) && (pixel_ptr == 0)) {
  140.                 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yetn",
  141.                     opcode & 0xF0);
  142.                 break;
  143.             }
  144.             /* figure out where the previous block started */
  145.             if (pixel_ptr == 0)
  146.                 prev_block_ptr1 = 
  147.                     (row_ptr - s->avctx->width * 4) + s->avctx->width - 4;
  148.             else
  149.                 prev_block_ptr1 = row_ptr + pixel_ptr - 4;
  150.             while (n_blocks--) {
  151.                 block_ptr = row_ptr + pixel_ptr;
  152.                 prev_block_ptr = prev_block_ptr1;
  153.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  154.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  155.                         pixels[block_ptr++] = pixels[prev_block_ptr++];
  156.                     }
  157.                     block_ptr += row_inc;
  158.                     prev_block_ptr += row_inc;
  159.                 }
  160.                 ADVANCE_BLOCK();
  161.             }
  162.             break;
  163.         /* repeat previous pair of blocks n times */
  164.         case 0x40:
  165.         case 0x50:
  166.             n_blocks = GET_BLOCK_COUNT();
  167.             n_blocks *= 2;
  168.             /* sanity check */
  169.             if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
  170.          av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yetn",
  171.                     opcode & 0xF0);
  172.                 break;
  173.             }
  174.             /* figure out where the previous 2 blocks started */
  175.             if (pixel_ptr == 0)
  176.                 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + 
  177.                     s->avctx->width - 4 * 2;
  178.             else if (pixel_ptr == 4)
  179.                 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc;
  180.             else
  181.                 prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2;
  182.             if (pixel_ptr == 0)
  183.                 prev_block_ptr2 = (row_ptr - s->avctx->width * 4) + row_inc;
  184.             else
  185.                 prev_block_ptr2 = row_ptr + pixel_ptr - 4;
  186.             prev_block_flag = 0;
  187.             while (n_blocks--) {
  188.                 block_ptr = row_ptr + pixel_ptr;
  189.                 if (prev_block_flag)
  190.                     prev_block_ptr = prev_block_ptr2;
  191.                 else
  192.                     prev_block_ptr = prev_block_ptr1;
  193.                 prev_block_flag = !prev_block_flag;
  194.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  195.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  196.                         pixels[block_ptr++] = pixels[prev_block_ptr++];
  197.                     }
  198.                     block_ptr += row_inc;
  199.                     prev_block_ptr += row_inc;
  200.                 }
  201.                 ADVANCE_BLOCK();
  202.             }
  203.             break;
  204.         /* 1-color block encoding */
  205.         case 0x60:
  206.         case 0x70:
  207.             n_blocks = GET_BLOCK_COUNT();
  208.             pixel = s->buf[stream_ptr++];
  209.             while (n_blocks--) {
  210.                 block_ptr = row_ptr + pixel_ptr;
  211.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  212.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  213.                         pixels[block_ptr++] = pixel;
  214.                     }
  215.                     block_ptr += row_inc;
  216.                 }
  217.                 ADVANCE_BLOCK();
  218.             }
  219.             break;
  220.         /* 2-color block encoding */
  221.         case 0x80:
  222.         case 0x90:
  223.             n_blocks = (opcode & 0x0F) + 1;
  224.             /* figure out which color pair to use to paint the 2-color block */
  225.             if ((opcode & 0xF0) == 0x80) {
  226.                 /* fetch the next 2 colors from bytestream and store in next
  227.                  * available entry in the color pair table */
  228.                 for (i = 0; i < CPAIR; i++) {
  229.                     pixel = s->buf[stream_ptr++];
  230.                     color_table_index = CPAIR * color_pair_index + i;
  231.                     s->color_pairs[color_table_index] = pixel;
  232.                 }
  233.                 /* this is the base index to use for this block */
  234.                 color_table_index = CPAIR * color_pair_index;
  235.                 color_pair_index++;
  236.                 /* wraparound */
  237.                 if (color_pair_index == COLORS_PER_TABLE)
  238.                     color_pair_index = 0;
  239.             } else
  240.                 color_table_index = CPAIR * s->buf[stream_ptr++];
  241.             while (n_blocks--) {
  242.                 color_flags = BE_16(&s->buf[stream_ptr]);
  243.                 stream_ptr += 2;
  244.                 flag_mask = 0x8000;
  245.                 block_ptr = row_ptr + pixel_ptr;
  246.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  247.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  248.                         if (color_flags & flag_mask)
  249.                             pixel = color_table_index + 1;
  250.                         else
  251.                             pixel = color_table_index;
  252.                         flag_mask >>= 1;
  253.                         pixels[block_ptr++] = s->color_pairs[pixel];
  254.                     }
  255.                     block_ptr += row_inc;
  256.                 }
  257.                 ADVANCE_BLOCK();
  258.             }
  259.             break;
  260.         /* 4-color block encoding */
  261.         case 0xA0:
  262.         case 0xB0:
  263.             n_blocks = (opcode & 0x0F) + 1;
  264.             /* figure out which color quad to use to paint the 4-color block */
  265.             if ((opcode & 0xF0) == 0xA0) {
  266.                 /* fetch the next 4 colors from bytestream and store in next
  267.                  * available entry in the color quad table */
  268.                 for (i = 0; i < CQUAD; i++) {
  269.                     pixel = s->buf[stream_ptr++];
  270.                     color_table_index = CQUAD * color_quad_index + i;
  271.                     s->color_quads[color_table_index] = pixel;
  272.                 }
  273.                 /* this is the base index to use for this block */
  274.                 color_table_index = CQUAD * color_quad_index;
  275.                 color_quad_index++;
  276.                 /* wraparound */
  277.                 if (color_quad_index == COLORS_PER_TABLE)
  278.                     color_quad_index = 0;
  279.             } else
  280.                 color_table_index = CQUAD * s->buf[stream_ptr++];
  281.             while (n_blocks--) {
  282.                 color_flags = BE_32(&s->buf[stream_ptr]);
  283.                 stream_ptr += 4;
  284.                 /* flag mask actually acts as a bit shift count here */
  285.                 flag_mask = 30;
  286.                 block_ptr = row_ptr + pixel_ptr;
  287.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  288.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  289.                         pixel = color_table_index + 
  290.                             ((color_flags >> flag_mask) & 0x03);
  291.                         flag_mask -= 2;
  292.                         pixels[block_ptr++] = s->color_quads[pixel];
  293.                     }
  294.                     block_ptr += row_inc;
  295.                 }
  296.                 ADVANCE_BLOCK();
  297.             }
  298.             break;
  299.         /* 8-color block encoding */
  300.         case 0xC0:
  301.         case 0xD0:
  302.             n_blocks = (opcode & 0x0F) + 1;
  303.             /* figure out which color octet to use to paint the 8-color block */
  304.             if ((opcode & 0xF0) == 0xC0) {
  305.                 /* fetch the next 8 colors from bytestream and store in next
  306.                  * available entry in the color octet table */
  307.                 for (i = 0; i < COCTET; i++) {
  308.                     pixel = s->buf[stream_ptr++];
  309.                     color_table_index = COCTET * color_octet_index + i;
  310.                     s->color_octets[color_table_index] = pixel;
  311.                 }
  312.                 /* this is the base index to use for this block */
  313.                 color_table_index = COCTET * color_octet_index;
  314.                 color_octet_index++;
  315.                 /* wraparound */
  316.                 if (color_octet_index == COLORS_PER_TABLE)
  317.                     color_octet_index = 0;
  318.             } else
  319.                 color_table_index = COCTET * s->buf[stream_ptr++];
  320.             while (n_blocks--) {
  321.                 /*
  322.                   For this input of 6 hex bytes:
  323.                     01 23 45 67 89 AB
  324.                   Mangle it to this output:
  325.                     flags_a = xx012456, flags_b = xx89A37B
  326.                 */
  327.                 /* build the color flags */
  328.                 color_flags_a = color_flags_b = 0;
  329.                 color_flags_a =
  330.                     (s->buf[stream_ptr + 0] << 16) |
  331.                     ((s->buf[stream_ptr + 1] & 0xF0) << 8) |
  332.                     ((s->buf[stream_ptr + 2] & 0xF0) << 4) |
  333.                     ((s->buf[stream_ptr + 2] & 0x0F) << 4) |
  334.                     ((s->buf[stream_ptr + 3] & 0xF0) >> 4);
  335.                 color_flags_b =
  336.                     (s->buf[stream_ptr + 4] << 16) |
  337.                     ((s->buf[stream_ptr + 5] & 0xF0) << 8) |
  338.                     ((s->buf[stream_ptr + 1] & 0x0F) << 8) |
  339.                     ((s->buf[stream_ptr + 3] & 0x0F) << 4) |
  340.                     (s->buf[stream_ptr + 5] & 0x0F);
  341.                 stream_ptr += 6;
  342.                 color_flags = color_flags_a;
  343.                 /* flag mask actually acts as a bit shift count here */
  344.                 flag_mask = 21;
  345.                 block_ptr = row_ptr + pixel_ptr;
  346.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  347.                     /* reload flags at third row (iteration pixel_y == 2) */
  348.                     if (pixel_y == 2) {
  349.                         color_flags = color_flags_b;
  350.                         flag_mask = 21;
  351.                     }
  352.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  353.                         pixel = color_table_index + 
  354.                             ((color_flags >> flag_mask) & 0x07);
  355.                         flag_mask -= 3;
  356.                         pixels[block_ptr++] = s->color_octets[pixel];
  357.                     }
  358.                     block_ptr += row_inc;
  359.                 }
  360.                 ADVANCE_BLOCK();
  361.             }
  362.             break;
  363.         /* 16-color block encoding (every pixel is a different color) */
  364.         case 0xE0:
  365.             n_blocks = (opcode & 0x0F) + 1;
  366.             while (n_blocks--) {
  367.                 block_ptr = row_ptr + pixel_ptr;
  368.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  369.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  370.                         pixels[block_ptr++] = s->buf[stream_ptr++];
  371.                     }
  372.                     block_ptr += row_inc;
  373.                 }
  374.                 ADVANCE_BLOCK();
  375.             }
  376.             break;
  377.         case 0xF0:
  378.             av_log(s->avctx, AV_LOG_INFO, "0xF0 opcode seen in SMC chunk (contact the developers)n");
  379.             break;
  380.         }
  381.     }
  382. }
  383. static int smc_decode_init(AVCodecContext *avctx)
  384. {
  385.     SmcContext *s = (SmcContext *)avctx->priv_data;
  386.     s->avctx = avctx;
  387.     avctx->pix_fmt = PIX_FMT_PAL8;
  388.     avctx->has_b_frames = 0;
  389.     dsputil_init(&s->dsp, avctx);
  390.     s->frame.data[0] = NULL;
  391.     return 0;
  392. }
  393. static int smc_decode_frame(AVCodecContext *avctx,
  394.                              void *data, int *data_size,
  395.                              uint8_t *buf, int buf_size)
  396. {
  397.     SmcContext *s = (SmcContext *)avctx->priv_data;
  398.     s->buf = buf;
  399.     s->size = buf_size;
  400.     s->frame.reference = 1;
  401.     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | 
  402.                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
  403.     if (avctx->reget_buffer(avctx, &s->frame)) {
  404.         av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failedn");
  405.         return -1;
  406.     }
  407.     smc_decode_stream(s);
  408.     *data_size = sizeof(AVFrame);
  409.     *(AVFrame*)data = s->frame;
  410.     /* always report that the buffer was completely consumed */
  411.     return buf_size;
  412. }
  413. static int smc_decode_end(AVCodecContext *avctx)
  414. {
  415.     SmcContext *s = (SmcContext *)avctx->priv_data;
  416.     if (s->frame.data[0])
  417.         avctx->release_buffer(avctx, &s->frame);
  418.     return 0;
  419. }
  420. AVCodec smc_decoder = {
  421.     "smc",
  422.     CODEC_TYPE_VIDEO,
  423.     CODEC_ID_SMC,
  424.     sizeof(SmcContext),
  425.     smc_decode_init,
  426.     NULL,
  427.     smc_decode_end,
  428.     smc_decode_frame,
  429.     CODEC_CAP_DR1,
  430. };