Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Quicktime Graphics (SMC) Video Decoder
  3.  * Copyright (C) 2003 the ffmpeg project
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * QT SMC Video Decoder by Mike Melanson (melanson@pcisys.net)
  25.  * For more information about the SMC format, visit:
  26.  *   http://www.pcisys.net/~melanson/codecs/
  27.  *
  28.  * The SMC decoder outputs PAL8 colorspace data.
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34.  
  35. #include "libavutil/intreadwrite.h"
  36. #include "avcodec.h"
  37. #include "bytestream.h"
  38. #include "internal.h"
  39.  
  40. #define CPAIR 2
  41. #define CQUAD 4
  42. #define COCTET 8
  43.  
  44. #define COLORS_PER_TABLE 256
  45.  
  46. typedef struct SmcContext {
  47.  
  48.     AVCodecContext *avctx;
  49.     AVFrame frame;
  50.  
  51.     GetByteContext gb;
  52.  
  53.     /* SMC color tables */
  54.     unsigned char color_pairs[COLORS_PER_TABLE * CPAIR];
  55.     unsigned char color_quads[COLORS_PER_TABLE * CQUAD];
  56.     unsigned char color_octets[COLORS_PER_TABLE * COCTET];
  57.  
  58.     uint32_t pal[256];
  59. } SmcContext;
  60.  
  61. #define GET_BLOCK_COUNT() \
  62.   (opcode & 0x10) ? (1 + bytestream2_get_byte(&s->gb)) : 1 + (opcode & 0x0F);
  63.  
  64. #define ADVANCE_BLOCK() \
  65. { \
  66.     pixel_ptr += 4; \
  67.     if (pixel_ptr >= width) \
  68.     { \
  69.         pixel_ptr = 0; \
  70.         row_ptr += stride * 4; \
  71.     } \
  72.     total_blocks--; \
  73.     if (total_blocks < 0) \
  74.     { \
  75.         av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)\n"); \
  76.         return; \
  77.     } \
  78. }
  79.  
  80. static void smc_decode_stream(SmcContext *s)
  81. {
  82.     int width = s->avctx->width;
  83.     int height = s->avctx->height;
  84.     int stride = s->frame.linesize[0];
  85.     int i;
  86.     int chunk_size;
  87.     int buf_size = bytestream2_size(&s->gb);
  88.     unsigned char opcode;
  89.     int n_blocks;
  90.     unsigned int color_flags;
  91.     unsigned int color_flags_a;
  92.     unsigned int color_flags_b;
  93.     unsigned int flag_mask;
  94.  
  95.     unsigned char *pixels = s->frame.data[0];
  96.  
  97.     int image_size = height * s->frame.linesize[0];
  98.     int row_ptr = 0;
  99.     int pixel_ptr = 0;
  100.     int pixel_x, pixel_y;
  101.     int row_inc = stride - 4;
  102.     int block_ptr;
  103.     int prev_block_ptr;
  104.     int prev_block_ptr1, prev_block_ptr2;
  105.     int prev_block_flag;
  106.     int total_blocks;
  107.     int color_table_index;  /* indexes to color pair, quad, or octet tables */
  108.     int pixel;
  109.  
  110.     int color_pair_index = 0;
  111.     int color_quad_index = 0;
  112.     int color_octet_index = 0;
  113.  
  114.     /* make the palette available */
  115.     memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
  116.  
  117.     bytestream2_skip(&s->gb, 1);
  118.     chunk_size = bytestream2_get_be24(&s->gb);
  119.     if (chunk_size != buf_size)
  120.         av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
  121.             chunk_size, buf_size);
  122.  
  123.     chunk_size = buf_size;
  124.     total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
  125.  
  126.     /* traverse through the blocks */
  127.     while (total_blocks) {
  128.         /* sanity checks */
  129.         /* make sure the row pointer hasn't gone wild */
  130.         if (row_ptr >= image_size) {
  131.             av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)\n",
  132.                 row_ptr, image_size);
  133.             return;
  134.         }
  135.  
  136.         opcode = bytestream2_get_byte(&s->gb);
  137.         switch (opcode & 0xF0) {
  138.         /* skip n blocks */
  139.         case 0x00:
  140.         case 0x10:
  141.             n_blocks = GET_BLOCK_COUNT();
  142.             while (n_blocks--) {
  143.                 ADVANCE_BLOCK();
  144.             }
  145.             break;
  146.  
  147.         /* repeat last block n times */
  148.         case 0x20:
  149.         case 0x30:
  150.             n_blocks = GET_BLOCK_COUNT();
  151.  
  152.             /* sanity check */
  153.             if ((row_ptr == 0) && (pixel_ptr == 0)) {
  154.                 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yet\n",
  155.                     opcode & 0xF0);
  156.                 return;
  157.             }
  158.  
  159.             /* figure out where the previous block started */
  160.             if (pixel_ptr == 0)
  161.                 prev_block_ptr1 =
  162.                     (row_ptr - s->avctx->width * 4) + s->avctx->width - 4;
  163.             else
  164.                 prev_block_ptr1 = row_ptr + pixel_ptr - 4;
  165.  
  166.             while (n_blocks--) {
  167.                 block_ptr = row_ptr + pixel_ptr;
  168.                 prev_block_ptr = prev_block_ptr1;
  169.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  170.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  171.                         pixels[block_ptr++] = pixels[prev_block_ptr++];
  172.                     }
  173.                     block_ptr += row_inc;
  174.                     prev_block_ptr += row_inc;
  175.                 }
  176.                 ADVANCE_BLOCK();
  177.             }
  178.             break;
  179.  
  180.         /* repeat previous pair of blocks n times */
  181.         case 0x40:
  182.         case 0x50:
  183.             n_blocks = GET_BLOCK_COUNT();
  184.             n_blocks *= 2;
  185.  
  186.             /* sanity check */
  187.             if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
  188.                 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
  189.                     opcode & 0xF0);
  190.                 return;
  191.             }
  192.  
  193.             /* figure out where the previous 2 blocks started */
  194.             if (pixel_ptr == 0)
  195.                 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) +
  196.                     s->avctx->width - 4 * 2;
  197.             else if (pixel_ptr == 4)
  198.                 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc;
  199.             else
  200.                 prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2;
  201.  
  202.             if (pixel_ptr == 0)
  203.                 prev_block_ptr2 = (row_ptr - s->avctx->width * 4) + row_inc;
  204.             else
  205.                 prev_block_ptr2 = row_ptr + pixel_ptr - 4;
  206.  
  207.             prev_block_flag = 0;
  208.             while (n_blocks--) {
  209.                 block_ptr = row_ptr + pixel_ptr;
  210.                 if (prev_block_flag)
  211.                     prev_block_ptr = prev_block_ptr2;
  212.                 else
  213.                     prev_block_ptr = prev_block_ptr1;
  214.                 prev_block_flag = !prev_block_flag;
  215.  
  216.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  217.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  218.                         pixels[block_ptr++] = pixels[prev_block_ptr++];
  219.                     }
  220.                     block_ptr += row_inc;
  221.                     prev_block_ptr += row_inc;
  222.                 }
  223.                 ADVANCE_BLOCK();
  224.             }
  225.             break;
  226.  
  227.         /* 1-color block encoding */
  228.         case 0x60:
  229.         case 0x70:
  230.             n_blocks = GET_BLOCK_COUNT();
  231.             pixel = bytestream2_get_byte(&s->gb);
  232.  
  233.             while (n_blocks--) {
  234.                 block_ptr = row_ptr + pixel_ptr;
  235.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  236.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  237.                         pixels[block_ptr++] = pixel;
  238.                     }
  239.                     block_ptr += row_inc;
  240.                 }
  241.                 ADVANCE_BLOCK();
  242.             }
  243.             break;
  244.  
  245.         /* 2-color block encoding */
  246.         case 0x80:
  247.         case 0x90:
  248.             n_blocks = (opcode & 0x0F) + 1;
  249.  
  250.             /* figure out which color pair to use to paint the 2-color block */
  251.             if ((opcode & 0xF0) == 0x80) {
  252.                 /* fetch the next 2 colors from bytestream and store in next
  253.                  * available entry in the color pair table */
  254.                 for (i = 0; i < CPAIR; i++) {
  255.                     pixel = bytestream2_get_byte(&s->gb);
  256.                     color_table_index = CPAIR * color_pair_index + i;
  257.                     s->color_pairs[color_table_index] = pixel;
  258.                 }
  259.                 /* this is the base index to use for this block */
  260.                 color_table_index = CPAIR * color_pair_index;
  261.                 color_pair_index++;
  262.                 /* wraparound */
  263.                 if (color_pair_index == COLORS_PER_TABLE)
  264.                     color_pair_index = 0;
  265.             } else
  266.                 color_table_index = CPAIR * bytestream2_get_byte(&s->gb);
  267.  
  268.             while (n_blocks--) {
  269.                 color_flags = bytestream2_get_be16(&s->gb);
  270.                 flag_mask = 0x8000;
  271.                 block_ptr = row_ptr + pixel_ptr;
  272.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  273.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  274.                         if (color_flags & flag_mask)
  275.                             pixel = color_table_index + 1;
  276.                         else
  277.                             pixel = color_table_index;
  278.                         flag_mask >>= 1;
  279.                         pixels[block_ptr++] = s->color_pairs[pixel];
  280.                     }
  281.                     block_ptr += row_inc;
  282.                 }
  283.                 ADVANCE_BLOCK();
  284.             }
  285.             break;
  286.  
  287.         /* 4-color block encoding */
  288.         case 0xA0:
  289.         case 0xB0:
  290.             n_blocks = (opcode & 0x0F) + 1;
  291.  
  292.             /* figure out which color quad to use to paint the 4-color block */
  293.             if ((opcode & 0xF0) == 0xA0) {
  294.                 /* fetch the next 4 colors from bytestream and store in next
  295.                  * available entry in the color quad table */
  296.                 for (i = 0; i < CQUAD; i++) {
  297.                     pixel = bytestream2_get_byte(&s->gb);
  298.                     color_table_index = CQUAD * color_quad_index + i;
  299.                     s->color_quads[color_table_index] = pixel;
  300.                 }
  301.                 /* this is the base index to use for this block */
  302.                 color_table_index = CQUAD * color_quad_index;
  303.                 color_quad_index++;
  304.                 /* wraparound */
  305.                 if (color_quad_index == COLORS_PER_TABLE)
  306.                     color_quad_index = 0;
  307.             } else
  308.                 color_table_index = CQUAD * bytestream2_get_byte(&s->gb);
  309.  
  310.             while (n_blocks--) {
  311.                 color_flags = bytestream2_get_be32(&s->gb);
  312.                 /* flag mask actually acts as a bit shift count here */
  313.                 flag_mask = 30;
  314.                 block_ptr = row_ptr + pixel_ptr;
  315.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  316.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  317.                         pixel = color_table_index +
  318.                             ((color_flags >> flag_mask) & 0x03);
  319.                         flag_mask -= 2;
  320.                         pixels[block_ptr++] = s->color_quads[pixel];
  321.                     }
  322.                     block_ptr += row_inc;
  323.                 }
  324.                 ADVANCE_BLOCK();
  325.             }
  326.             break;
  327.  
  328.         /* 8-color block encoding */
  329.         case 0xC0:
  330.         case 0xD0:
  331.             n_blocks = (opcode & 0x0F) + 1;
  332.  
  333.             /* figure out which color octet to use to paint the 8-color block */
  334.             if ((opcode & 0xF0) == 0xC0) {
  335.                 /* fetch the next 8 colors from bytestream and store in next
  336.                  * available entry in the color octet table */
  337.                 for (i = 0; i < COCTET; i++) {
  338.                     pixel = bytestream2_get_byte(&s->gb);
  339.                     color_table_index = COCTET * color_octet_index + i;
  340.                     s->color_octets[color_table_index] = pixel;
  341.                 }
  342.                 /* this is the base index to use for this block */
  343.                 color_table_index = COCTET * color_octet_index;
  344.                 color_octet_index++;
  345.                 /* wraparound */
  346.                 if (color_octet_index == COLORS_PER_TABLE)
  347.                     color_octet_index = 0;
  348.             } else
  349.                 color_table_index = COCTET * bytestream2_get_byte(&s->gb);
  350.  
  351.             while (n_blocks--) {
  352.                 /*
  353.                   For this input of 6 hex bytes:
  354.                     01 23 45 67 89 AB
  355.                   Mangle it to this output:
  356.                     flags_a = xx012456, flags_b = xx89A37B
  357.                 */
  358.                 /* build the color flags */
  359.                 int val1 = bytestream2_get_be16(&s->gb);
  360.                 int val2 = bytestream2_get_be16(&s->gb);
  361.                 int val3 = bytestream2_get_be16(&s->gb);
  362.                 color_flags_a = ((val1 & 0xFFF0) << 8) | (val2 >> 4);
  363.                 color_flags_b = ((val3 & 0xFFF0) << 8) |
  364.                     ((val1 & 0x0F) << 8) | ((val2 & 0x0F) << 4) | (val3 & 0x0F);
  365.  
  366.                 color_flags = color_flags_a;
  367.                 /* flag mask actually acts as a bit shift count here */
  368.                 flag_mask = 21;
  369.                 block_ptr = row_ptr + pixel_ptr;
  370.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  371.                     /* reload flags at third row (iteration pixel_y == 2) */
  372.                     if (pixel_y == 2) {
  373.                         color_flags = color_flags_b;
  374.                         flag_mask = 21;
  375.                     }
  376.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  377.                         pixel = color_table_index +
  378.                             ((color_flags >> flag_mask) & 0x07);
  379.                         flag_mask -= 3;
  380.                         pixels[block_ptr++] = s->color_octets[pixel];
  381.                     }
  382.                     block_ptr += row_inc;
  383.                 }
  384.                 ADVANCE_BLOCK();
  385.             }
  386.             break;
  387.  
  388.         /* 16-color block encoding (every pixel is a different color) */
  389.         case 0xE0:
  390.             n_blocks = (opcode & 0x0F) + 1;
  391.  
  392.             while (n_blocks--) {
  393.                 block_ptr = row_ptr + pixel_ptr;
  394.                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  395.                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  396.                         pixels[block_ptr++] = bytestream2_get_byte(&s->gb);
  397.                     }
  398.                     block_ptr += row_inc;
  399.                 }
  400.                 ADVANCE_BLOCK();
  401.             }
  402.             break;
  403.  
  404.         case 0xF0:
  405.             avpriv_request_sample(s->avctx, "0xF0 opcode");
  406.             break;
  407.         }
  408.     }
  409.  
  410.     return;
  411. }
  412.  
  413. static av_cold int smc_decode_init(AVCodecContext *avctx)
  414. {
  415.     SmcContext *s = avctx->priv_data;
  416.  
  417.     s->avctx = avctx;
  418.     avctx->pix_fmt = AV_PIX_FMT_PAL8;
  419.  
  420.     avcodec_get_frame_defaults(&s->frame);
  421.  
  422.     return 0;
  423. }
  424.  
  425. static int smc_decode_frame(AVCodecContext *avctx,
  426.                              void *data, int *got_frame,
  427.                              AVPacket *avpkt)
  428. {
  429.     const uint8_t *buf = avpkt->data;
  430.     int buf_size = avpkt->size;
  431.     SmcContext *s = avctx->priv_data;
  432.     const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
  433.     int ret;
  434.  
  435.     bytestream2_init(&s->gb, buf, buf_size);
  436.  
  437.     if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0)
  438.         return ret;
  439.  
  440.     if (pal) {
  441.         s->frame.palette_has_changed = 1;
  442.         memcpy(s->pal, pal, AVPALETTE_SIZE);
  443.     }
  444.  
  445.     smc_decode_stream(s);
  446.  
  447.     *got_frame      = 1;
  448.     if ((ret = av_frame_ref(data, &s->frame)) < 0)
  449.         return ret;
  450.  
  451.     /* always report that the buffer was completely consumed */
  452.     return buf_size;
  453. }
  454.  
  455. static av_cold int smc_decode_end(AVCodecContext *avctx)
  456. {
  457.     SmcContext *s = avctx->priv_data;
  458.  
  459.     av_frame_unref(&s->frame);
  460.  
  461.     return 0;
  462. }
  463.  
  464. AVCodec ff_smc_decoder = {
  465.     .name           = "smc",
  466.     .long_name      = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"),
  467.     .type           = AVMEDIA_TYPE_VIDEO,
  468.     .id             = AV_CODEC_ID_SMC,
  469.     .priv_data_size = sizeof(SmcContext),
  470.     .init           = smc_decode_init,
  471.     .close          = smc_decode_end,
  472.     .decode         = smc_decode_frame,
  473.     .capabilities   = CODEC_CAP_DR1,
  474. };
  475.