1/*
2 * IBM Ultimotion Video Decoder
3 * Copyright (C) 2004 Konstantin Shishkov
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 * IBM Ultimotion Video Decoder.
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "avcodec.h"
32#include "bytestream.h"
33
34#include "ulti_cb.h"
35
36typedef struct UltimotionDecodeContext {
37    AVCodecContext *avctx;
38    int width, height, blocks;
39    AVFrame frame;
40    const uint8_t *ulti_codebook;
41} UltimotionDecodeContext;
42
43static av_cold int ulti_decode_init(AVCodecContext *avctx)
44{
45    UltimotionDecodeContext *s = avctx->priv_data;
46
47    s->avctx = avctx;
48    s->width = avctx->width;
49    s->height = avctx->height;
50    s->blocks = (s->width / 8) * (s->height / 8);
51    avctx->pix_fmt = PIX_FMT_YUV410P;
52    avctx->coded_frame = (AVFrame*) &s->frame;
53    s->ulti_codebook = ulti_codebook;
54
55    return 0;
56}
57
58static av_cold int ulti_decode_end(AVCodecContext *avctx){
59    UltimotionDecodeContext *s = avctx->priv_data;
60    AVFrame *pic = &s->frame;
61
62    if (pic->data[0])
63        avctx->release_buffer(avctx, pic);
64
65    return 0;
66}
67
68static const int block_coords[8] = // 4x4 block coords in 8x8 superblock
69    { 0, 0, 0, 4, 4, 4, 4, 0};
70
71static const int angle_by_index[4] = { 0, 2, 6, 12};
72
73/* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
74static const uint8_t ulti_lumas[64] =
75    { 0x10, 0x13, 0x17, 0x1A, 0x1E, 0x21, 0x25, 0x28,
76      0x2C, 0x2F, 0x33, 0x36, 0x3A, 0x3D, 0x41, 0x44,
77      0x48, 0x4B, 0x4F, 0x52, 0x56, 0x59, 0x5C, 0x60,
78      0x63, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C,
79      0x7F, 0x83, 0x86, 0x8A, 0x8D, 0x91, 0x94, 0x98,
80      0x9B, 0x9F, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB3,
81      0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 0xCC, 0xCF,
82      0xD3, 0xD6, 0xDA, 0xDD, 0xE1, 0xE4, 0xE8, 0xEB};
83
84static const uint8_t ulti_chromas[16] =
85    { 0x60, 0x67, 0x6D, 0x73, 0x7A, 0x80, 0x86, 0x8D,
86      0x93, 0x99, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC0};
87
88/* convert Ultimotion YUV block (sixteen 6-bit Y samples and
89 two 4-bit chroma samples) into standard YUV and put it into frame */
90static void ulti_convert_yuv(AVFrame *frame, int x, int y,
91                             uint8_t *luma,int chroma)
92{
93    uint8_t *y_plane, *cr_plane, *cb_plane;
94    int i;
95
96    y_plane = frame->data[0] + x + y * frame->linesize[0];
97    cr_plane = frame->data[1] + (x / 4) + (y / 4) * frame->linesize[1];
98    cb_plane = frame->data[2] + (x / 4) + (y / 4) * frame->linesize[2];
99
100    cr_plane[0] = ulti_chromas[chroma >> 4];
101
102    cb_plane[0] = ulti_chromas[chroma & 0xF];
103
104
105    for(i = 0; i < 16; i++){
106        y_plane[i & 3] = ulti_lumas[luma[i]];
107        if((i & 3) == 3) { //next row
108            y_plane += frame->linesize[0];
109        }
110    }
111}
112
113/* generate block like in MS Video1 */
114static void ulti_pattern(AVFrame *frame, int x, int y,
115                         int f0, int f1, int Y0, int Y1, int chroma)
116{
117    uint8_t Luma[16];
118    int mask, i;
119    for(mask = 0x80, i = 0; mask; mask >>= 1, i++) {
120        if(f0 & mask)
121            Luma[i] = Y1;
122        else
123            Luma[i] = Y0;
124    }
125
126    for(mask = 0x80, i = 8; mask; mask >>= 1, i++) {
127        if(f1 & mask)
128            Luma[i] = Y1;
129        else
130            Luma[i] = Y0;
131    }
132
133    ulti_convert_yuv(frame, x, y, Luma, chroma);
134}
135
136/* fill block with some gradient */
137static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle)
138{
139    uint8_t Luma[16];
140    if(angle & 8) { //reverse order
141        int t;
142        angle &= 0x7;
143        t = Y[0];
144        Y[0] = Y[3];
145        Y[3] = t;
146        t = Y[1];
147        Y[1] = Y[2];
148        Y[2] = t;
149    }
150    switch(angle){
151    case 0:
152        Luma[0]  = Y[0]; Luma[1]  = Y[1]; Luma[2]  = Y[2]; Luma[3]  = Y[3];
153        Luma[4]  = Y[0]; Luma[5]  = Y[1]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
154        Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
155        Luma[12] = Y[0]; Luma[13] = Y[1]; Luma[14] = Y[2]; Luma[15] = Y[3];
156        break;
157    case 1:
158        Luma[0]  = Y[1]; Luma[1]  = Y[2]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
159        Luma[4]  = Y[0]; Luma[5]  = Y[1]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
160        Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
161        Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
162        break;
163    case 2:
164        Luma[0]  = Y[1]; Luma[1]  = Y[2]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
165        Luma[4]  = Y[1]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
166        Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
167        Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
168        break;
169    case 3:
170        Luma[0]  = Y[2]; Luma[1]  = Y[3]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
171        Luma[4]  = Y[1]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
172        Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
173        Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[1];
174        break;
175    case 4:
176        Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
177        Luma[4]  = Y[2]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[2];
178        Luma[8]  = Y[1]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[1];
179        Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
180        break;
181    case 5:
182        Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[3]; Luma[3]  = Y[2];
183        Luma[4]  = Y[3]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[1];
184        Luma[8]  = Y[2]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[0];
185        Luma[12] = Y[1]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
186        break;
187    case 6:
188        Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[2]; Luma[3]  = Y[2];
189        Luma[4]  = Y[3]; Luma[5]  = Y[2]; Luma[6]  = Y[1]; Luma[7]  = Y[1];
190        Luma[8]  = Y[2]; Luma[9]  = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
191        Luma[12] = Y[1]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
192        break;
193    case 7:
194        Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[2]; Luma[3]  = Y[1];
195        Luma[4]  = Y[3]; Luma[5]  = Y[2]; Luma[6]  = Y[1]; Luma[7]  = Y[0];
196        Luma[8]  = Y[3]; Luma[9]  = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
197        Luma[12] = Y[2]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
198        break;
199    default:
200        Luma[0]  = Y[0]; Luma[1]  = Y[0]; Luma[2]  = Y[1]; Luma[3]  = Y[1];
201        Luma[4]  = Y[0]; Luma[5]  = Y[0]; Luma[6]  = Y[1]; Luma[7]  = Y[1];
202        Luma[8]  = Y[2]; Luma[9]  = Y[2]; Luma[10] = Y[3]; Luma[11] = Y[3];
203        Luma[12] = Y[2]; Luma[13] = Y[2]; Luma[14] = Y[3]; Luma[15] = Y[3];
204        break;
205    }
206
207    ulti_convert_yuv(frame, x, y, Luma, chroma);
208}
209
210static int ulti_decode_frame(AVCodecContext *avctx,
211                             void *data, int *data_size,
212                             AVPacket *avpkt)
213{
214    const uint8_t *buf = avpkt->data;
215    int buf_size = avpkt->size;
216    UltimotionDecodeContext *s=avctx->priv_data;
217    int modifier = 0;
218    int uniq = 0;
219    int mode = 0;
220    int blocks = 0;
221    int done = 0;
222    int x = 0, y = 0;
223    int i;
224    int skip;
225    int tmp;
226
227    if(s->frame.data[0])
228        avctx->release_buffer(avctx, &s->frame);
229
230    s->frame.reference = 1;
231    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
232    if(avctx->get_buffer(avctx, &s->frame) < 0) {
233        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
234        return -1;
235    }
236
237    while(!done) {
238        int idx;
239        if(blocks >= s->blocks || y >= s->height)
240            break;//all blocks decoded
241
242        idx = *buf++;
243        if((idx & 0xF8) == 0x70) {
244            switch(idx) {
245            case 0x70: //change modifier
246                modifier = *buf++;
247                if(modifier>1)
248                    av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
249                break;
250            case 0x71: // set uniq flag
251                uniq = 1;
252                break;
253            case 0x72: //toggle mode
254                mode = !mode;
255                break;
256            case 0x73: //end-of-frame
257                done = 1;
258                break;
259            case 0x74: //skip some blocks
260                skip = *buf++;
261                if ((blocks + skip) >= s->blocks)
262                    break;
263                blocks += skip;
264                x += skip * 8;
265                while(x >= s->width) {
266                    x -= s->width;
267                    y += 8;
268                }
269                break;
270            default:
271                av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
272            }
273        } else { //handle one block
274            int code;
275            int cf;
276            int angle = 0;
277            uint8_t Y[4]; // luma samples of block
278            int tx = 0, ty = 0; //coords of subblock
279            int chroma = 0;
280            if (mode || uniq) {
281                uniq = 0;
282                cf = 1;
283                chroma = 0;
284            } else {
285                cf = 0;
286                if (idx)
287                    chroma = *buf++;
288            }
289            for (i = 0; i < 4; i++) { // for every subblock
290                code = (idx >> (6 - i*2)) & 3; //extract 2 bits
291                if(!code) //skip subblock
292                    continue;
293                if(cf)
294                    chroma = *buf++;
295                tx = x + block_coords[i * 2];
296                ty = y + block_coords[(i * 2) + 1];
297                switch(code) {
298                case 1:
299                    tmp = *buf++;
300
301                    angle = angle_by_index[(tmp >> 6) & 0x3];
302
303                    Y[0] = tmp & 0x3F;
304                    Y[1] = Y[0];
305
306                    if (angle) {
307                        Y[2] = Y[0]+1;
308                        if (Y[2] > 0x3F)
309                            Y[2] = 0x3F;
310                        Y[3] = Y[2];
311                    } else {
312                        Y[2] = Y[0];
313                        Y[3] = Y[0];
314                    }
315                    break;
316
317                case 2:
318                    if (modifier) { // unpack four luma samples
319                        tmp = bytestream_get_be24(&buf);
320
321                        Y[0] = (tmp >> 18) & 0x3F;
322                        Y[1] = (tmp >> 12) & 0x3F;
323                        Y[2] = (tmp >> 6) & 0x3F;
324                        Y[3] = tmp & 0x3F;
325                        angle = 16;
326                    } else { // retrieve luma samples from codebook
327                        tmp = bytestream_get_be16(&buf);
328
329                        angle = (tmp >> 12) & 0xF;
330                        tmp &= 0xFFF;
331                        tmp <<= 2;
332                        Y[0] = s->ulti_codebook[tmp];
333                        Y[1] = s->ulti_codebook[tmp + 1];
334                        Y[2] = s->ulti_codebook[tmp + 2];
335                        Y[3] = s->ulti_codebook[tmp + 3];
336                    }
337                    break;
338
339                case 3:
340                    if (modifier) { // all 16 luma samples
341                        uint8_t Luma[16];
342
343                        tmp = bytestream_get_be24(&buf);
344                        Luma[0] = (tmp >> 18) & 0x3F;
345                        Luma[1] = (tmp >> 12) & 0x3F;
346                        Luma[2] = (tmp >> 6) & 0x3F;
347                        Luma[3] = tmp & 0x3F;
348
349                        tmp = bytestream_get_be24(&buf);
350                        Luma[4] = (tmp >> 18) & 0x3F;
351                        Luma[5] = (tmp >> 12) & 0x3F;
352                        Luma[6] = (tmp >> 6) & 0x3F;
353                        Luma[7] = tmp & 0x3F;
354
355                        tmp = bytestream_get_be24(&buf);
356                        Luma[8] = (tmp >> 18) & 0x3F;
357                        Luma[9] = (tmp >> 12) & 0x3F;
358                        Luma[10] = (tmp >> 6) & 0x3F;
359                        Luma[11] = tmp & 0x3F;
360
361                        tmp = bytestream_get_be24(&buf);
362                        Luma[12] = (tmp >> 18) & 0x3F;
363                        Luma[13] = (tmp >> 12) & 0x3F;
364                        Luma[14] = (tmp >> 6) & 0x3F;
365                        Luma[15] = tmp & 0x3F;
366
367                        ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
368                    } else {
369                        tmp = *buf++;
370                        if(tmp & 0x80) {
371                            angle = (tmp >> 4) & 0x7;
372                            tmp = (tmp << 8) + *buf++;
373                            Y[0] = (tmp >> 6) & 0x3F;
374                            Y[1] = tmp & 0x3F;
375                            Y[2] = (*buf++) & 0x3F;
376                            Y[3] = (*buf++) & 0x3F;
377                            ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block
378                        } else { // some patterns
379                            int f0, f1;
380                            f0 = *buf++;
381                            f1 = tmp;
382                            Y[0] = (*buf++) & 0x3F;
383                            Y[1] = (*buf++) & 0x3F;
384                            ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
385                        }
386                    }
387                    break;
388                }
389                if(code != 3)
390                    ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block
391            }
392            blocks++;
393                x += 8;
394            if(x >= s->width) {
395                x = 0;
396                y += 8;
397            }
398        }
399    }
400
401    *data_size=sizeof(AVFrame);
402    *(AVFrame*)data= s->frame;
403
404    return buf_size;
405}
406
407AVCodec ulti_decoder = {
408    "ultimotion",
409    AVMEDIA_TYPE_VIDEO,
410    CODEC_ID_ULTI,
411    sizeof(UltimotionDecodeContext),
412    ulti_decode_init,
413    NULL,
414    ulti_decode_end,
415    ulti_decode_frame,
416    CODEC_CAP_DR1,
417    NULL,
418    .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
419};
420
421