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