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