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