Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Motion Pixels Video Decoder
  3.  * Copyright (c) 2008 Gregory Montoir (cyx@users.sourceforge.net)
  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. #include "avcodec.h"
  23. #include "get_bits.h"
  24. #include "dsputil.h"
  25. #include "internal.h"
  26.  
  27. #define MAX_HUFF_CODES 16
  28.  
  29. #include "motionpixels_tablegen.h"
  30.  
  31. typedef struct HuffCode {
  32.     int code;
  33.     uint8_t size;
  34.     uint8_t delta;
  35. } HuffCode;
  36.  
  37. typedef struct MotionPixelsContext {
  38.     AVCodecContext *avctx;
  39.     AVFrame frame;
  40.     DSPContext dsp;
  41.     uint8_t *changes_map;
  42.     int offset_bits_len;
  43.     int codes_count, current_codes_count;
  44.     int max_codes_bits;
  45.     HuffCode codes[MAX_HUFF_CODES];
  46.     VLC vlc;
  47.     YuvPixel *vpt, *hpt;
  48.     uint8_t gradient_scale[3];
  49.     uint8_t *bswapbuf;
  50.     int bswapbuf_size;
  51. } MotionPixelsContext;
  52.  
  53. static av_cold int mp_decode_init(AVCodecContext *avctx)
  54. {
  55.     MotionPixelsContext *mp = avctx->priv_data;
  56.     int w4 = (avctx->width  + 3) & ~3;
  57.     int h4 = (avctx->height + 3) & ~3;
  58.  
  59.     if(avctx->extradata_size < 2){
  60.         av_log(avctx, AV_LOG_ERROR, "extradata too small\n");
  61.         return AVERROR_INVALIDDATA;
  62.     }
  63.  
  64.     motionpixels_tableinit();
  65.     mp->avctx = avctx;
  66.     ff_dsputil_init(&mp->dsp, avctx);
  67.     mp->changes_map = av_mallocz(avctx->width * h4);
  68.     mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1;
  69.     mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel));
  70.     mp->hpt = av_mallocz(h4 * w4 / 16 * sizeof(YuvPixel));
  71.     if (!mp->changes_map || !mp->vpt || !mp->hpt) {
  72.         av_freep(&mp->changes_map);
  73.         av_freep(&mp->vpt);
  74.         av_freep(&mp->hpt);
  75.         return AVERROR(ENOMEM);
  76.     }
  77.     avctx->pix_fmt = AV_PIX_FMT_RGB555;
  78.     avcodec_get_frame_defaults(&mp->frame);
  79.     return 0;
  80. }
  81.  
  82. static void mp_read_changes_map(MotionPixelsContext *mp, GetBitContext *gb, int count, int bits_len, int read_color)
  83. {
  84.     uint16_t *pixels;
  85.     int offset, w, h, color = 0, x, y, i;
  86.  
  87.     while (count--) {
  88.         offset = get_bits_long(gb, mp->offset_bits_len);
  89.         w      = get_bits(gb, bits_len) + 1;
  90.         h      = get_bits(gb, bits_len) + 1;
  91.         if (read_color)
  92.             color = get_bits(gb, 15);
  93.         x = offset % mp->avctx->width;
  94.         y = offset / mp->avctx->width;
  95.         if (y >= mp->avctx->height)
  96.             continue;
  97.         w = FFMIN(w, mp->avctx->width  - x);
  98.         h = FFMIN(h, mp->avctx->height - y);
  99.         pixels = (uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
  100.         while (h--) {
  101.             mp->changes_map[offset] = w;
  102.             if (read_color)
  103.                 for (i = 0; i < w; ++i)
  104.                     pixels[i] = color;
  105.             offset += mp->avctx->width;
  106.             pixels += mp->frame.linesize[0] / 2;
  107.         }
  108.     }
  109. }
  110.  
  111. static int mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code)
  112. {
  113.     while (get_bits1(gb)) {
  114.         ++size;
  115.         if (size > mp->max_codes_bits) {
  116.             av_log(mp->avctx, AV_LOG_ERROR, "invalid code size %d/%d\n", size, mp->max_codes_bits);
  117.             return AVERROR_INVALIDDATA;
  118.         }
  119.         code <<= 1;
  120.         if (mp_get_code(mp, gb, size, code + 1) < 0)
  121.             return AVERROR_INVALIDDATA;
  122.     }
  123.     if (mp->current_codes_count >= MAX_HUFF_CODES) {
  124.         av_log(mp->avctx, AV_LOG_ERROR, "too many codes\n");
  125.         return AVERROR_INVALIDDATA;
  126.     }
  127.  
  128.     mp->codes[mp->current_codes_count  ].code = code;
  129.     mp->codes[mp->current_codes_count++].size = size;
  130.     return 0;
  131. }
  132.  
  133. static int mp_read_codes_table(MotionPixelsContext *mp, GetBitContext *gb)
  134. {
  135.     if (mp->codes_count == 1) {
  136.         mp->codes[0].delta = get_bits(gb, 4);
  137.     } else {
  138.         int i;
  139.         int ret;
  140.  
  141.         mp->max_codes_bits = get_bits(gb, 4);
  142.         for (i = 0; i < mp->codes_count; ++i)
  143.             mp->codes[i].delta = get_bits(gb, 4);
  144.         mp->current_codes_count = 0;
  145.         if ((ret = mp_get_code(mp, gb, 0, 0)) < 0)
  146.             return ret;
  147.         if (mp->current_codes_count < mp->codes_count) {
  148.             av_log(mp->avctx, AV_LOG_ERROR, "too few codes\n");
  149.             return AVERROR_INVALIDDATA;
  150.         }
  151.    }
  152.    return 0;
  153. }
  154.  
  155. static int mp_gradient(MotionPixelsContext *mp, int component, int v)
  156. {
  157.     int delta;
  158.  
  159.     delta = (v - 7) * mp->gradient_scale[component];
  160.     mp->gradient_scale[component] = (v == 0 || v == 14) ? 2 : 1;
  161.     return delta;
  162. }
  163.  
  164. static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y)
  165. {
  166.     int color;
  167.  
  168.     color = *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
  169.     return mp_rgb_yuv_table[color];
  170. }
  171.  
  172. static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p)
  173. {
  174.     int color;
  175.  
  176.     color = mp_yuv_to_rgb(p->y, p->v, p->u, 1);
  177.     *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2] = color;
  178. }
  179.  
  180. static int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb)
  181. {
  182.     int i;
  183.  
  184.     i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1);
  185.     return mp->codes[i].delta;
  186. }
  187.  
  188. static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y)
  189. {
  190.     YuvPixel p;
  191.     const int y0 = y * mp->avctx->width;
  192.     int w, i, x = 0;
  193.  
  194.     p = mp->vpt[y];
  195.     if (mp->changes_map[y0 + x] == 0) {
  196.         memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
  197.         ++x;
  198.     }
  199.     while (x < mp->avctx->width) {
  200.         w = mp->changes_map[y0 + x];
  201.         if (w != 0) {
  202.             if ((y & 3) == 0) {
  203.                 if (mp->changes_map[y0 + x + mp->avctx->width] < w ||
  204.                     mp->changes_map[y0 + x + mp->avctx->width * 2] < w ||
  205.                     mp->changes_map[y0 + x + mp->avctx->width * 3] < w) {
  206.                     for (i = (x + 3) & ~3; i < x + w; i += 4) {
  207.                         mp->hpt[((y / 4) * mp->avctx->width + i) / 4] = mp_get_yuv_from_rgb(mp, i, y);
  208.                     }
  209.                 }
  210.             }
  211.             x += w;
  212.             memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
  213.             p = mp_get_yuv_from_rgb(mp, x - 1, y);
  214.         } else {
  215.             p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
  216.             p.y = av_clip(p.y, 0, 31);
  217.             if ((x & 3) == 0) {
  218.                 if ((y & 3) == 0) {
  219.                     p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
  220.                     p.v = av_clip(p.v, -32, 31);
  221.                     p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
  222.                     p.u = av_clip(p.u, -32, 31);
  223.                     mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p;
  224.                 } else {
  225.                     p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v;
  226.                     p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u;
  227.                 }
  228.             }
  229.             mp_set_rgb_from_yuv(mp, x, y, &p);
  230.             ++x;
  231.         }
  232.     }
  233. }
  234.  
  235. static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb)
  236. {
  237.     YuvPixel p;
  238.     int y, y0;
  239.  
  240.     av_assert1(mp->changes_map[0]);
  241.  
  242.     for (y = 0; y < mp->avctx->height; ++y) {
  243.         if (mp->changes_map[y * mp->avctx->width] != 0) {
  244.             memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
  245.             p = mp_get_yuv_from_rgb(mp, 0, y);
  246.         } else {
  247.             p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
  248.             p.y = av_clip(p.y, 0, 31);
  249.             if ((y & 3) == 0) {
  250.                 p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
  251.                 p.v = av_clip(p.v, -32, 31);
  252.                 p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
  253.                 p.u = av_clip(p.u, -32, 31);
  254.             }
  255.             mp->vpt[y] = p;
  256.             mp_set_rgb_from_yuv(mp, 0, y, &p);
  257.         }
  258.     }
  259.     for (y0 = 0; y0 < 2; ++y0)
  260.         for (y = y0; y < mp->avctx->height; y += 2)
  261.             mp_decode_line(mp, gb, y);
  262. }
  263.  
  264. static int mp_decode_frame(AVCodecContext *avctx,
  265.                                  void *data, int *got_frame,
  266.                                  AVPacket *avpkt)
  267. {
  268.     const uint8_t *buf = avpkt->data;
  269.     int buf_size = avpkt->size;
  270.     MotionPixelsContext *mp = avctx->priv_data;
  271.     GetBitContext gb;
  272.     int i, count1, count2, sz, ret;
  273.  
  274.     if ((ret = ff_reget_buffer(avctx, &mp->frame)) < 0)
  275.         return ret;
  276.  
  277.     /* le32 bitstream msb first */
  278.     av_fast_malloc(&mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
  279.     if (!mp->bswapbuf)
  280.         return AVERROR(ENOMEM);
  281.     mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4);
  282.     if (buf_size & 3)
  283.         memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3);
  284.     memset(mp->bswapbuf + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
  285.     init_get_bits(&gb, mp->bswapbuf, buf_size * 8);
  286.  
  287.     memset(mp->changes_map, 0, avctx->width * avctx->height);
  288.     for (i = !(avctx->extradata[1] & 2); i < 2; ++i) {
  289.         count1 = get_bits(&gb, 12);
  290.         count2 = get_bits(&gb, 12);
  291.         mp_read_changes_map(mp, &gb, count1, 8, i);
  292.         mp_read_changes_map(mp, &gb, count2, 4, i);
  293.     }
  294.  
  295.     mp->codes_count = get_bits(&gb, 4);
  296.     if (mp->codes_count == 0)
  297.         goto end;
  298.  
  299.     if (mp->changes_map[0] == 0) {
  300.         *(uint16_t *)mp->frame.data[0] = get_bits(&gb, 15);
  301.         mp->changes_map[0] = 1;
  302.     }
  303.     if (mp_read_codes_table(mp, &gb) < 0)
  304.         goto end;
  305.  
  306.     sz = get_bits(&gb, 18);
  307.     if (avctx->extradata[0] != 5)
  308.         sz += get_bits(&gb, 18);
  309.     if (sz == 0)
  310.         goto end;
  311.  
  312.     if (mp->max_codes_bits <= 0)
  313.         goto end;
  314.     if (init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0))
  315.         goto end;
  316.     mp_decode_frame_helper(mp, &gb);
  317.     ff_free_vlc(&mp->vlc);
  318.  
  319. end:
  320.     if ((ret = av_frame_ref(data, &mp->frame)) < 0)
  321.         return ret;
  322.     *got_frame       = 1;
  323.     return buf_size;
  324. }
  325.  
  326. static av_cold int mp_decode_end(AVCodecContext *avctx)
  327. {
  328.     MotionPixelsContext *mp = avctx->priv_data;
  329.  
  330.     av_freep(&mp->changes_map);
  331.     av_freep(&mp->vpt);
  332.     av_freep(&mp->hpt);
  333.     av_freep(&mp->bswapbuf);
  334.     av_frame_unref(&mp->frame);
  335.  
  336.     return 0;
  337. }
  338.  
  339. AVCodec ff_motionpixels_decoder = {
  340.     .name           = "motionpixels",
  341.     .long_name      = NULL_IF_CONFIG_SMALL("Motion Pixels video"),
  342.     .type           = AVMEDIA_TYPE_VIDEO,
  343.     .id             = AV_CODEC_ID_MOTIONPIXELS,
  344.     .priv_data_size = sizeof(MotionPixelsContext),
  345.     .init           = mp_decode_init,
  346.     .close          = mp_decode_end,
  347.     .decode         = mp_decode_frame,
  348.     .capabilities   = CODEC_CAP_DR1,
  349. };
  350.