Libav
|
00001 /* 00002 * IBM Ultimotion Video Decoder 00003 * Copyright (C) 2004 Konstantin Shishkov 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <string.h> 00030 00031 #include "avcodec.h" 00032 #include "bytestream.h" 00033 00034 #include "ulti_cb.h" 00035 00036 typedef struct UltimotionDecodeContext { 00037 AVCodecContext *avctx; 00038 int width, height, blocks; 00039 AVFrame frame; 00040 const uint8_t *ulti_codebook; 00041 } UltimotionDecodeContext; 00042 00043 static av_cold int ulti_decode_init(AVCodecContext *avctx) 00044 { 00045 UltimotionDecodeContext *s = avctx->priv_data; 00046 00047 s->avctx = avctx; 00048 s->width = avctx->width; 00049 s->height = avctx->height; 00050 s->blocks = (s->width / 8) * (s->height / 8); 00051 avctx->pix_fmt = PIX_FMT_YUV410P; 00052 avctx->coded_frame = (AVFrame*) &s->frame; 00053 s->ulti_codebook = ulti_codebook; 00054 00055 return 0; 00056 } 00057 00058 static av_cold int ulti_decode_end(AVCodecContext *avctx){ 00059 UltimotionDecodeContext *s = avctx->priv_data; 00060 AVFrame *pic = &s->frame; 00061 00062 if (pic->data[0]) 00063 avctx->release_buffer(avctx, pic); 00064 00065 return 0; 00066 } 00067 00068 static const int block_coords[8] = // 4x4 block coords in 8x8 superblock 00069 { 0, 0, 0, 4, 4, 4, 4, 0}; 00070 00071 static const int angle_by_index[4] = { 0, 2, 6, 12}; 00072 00073 /* Lookup tables for luma and chroma - used by ulti_convert_yuv() */ 00074 static const uint8_t ulti_lumas[64] = 00075 { 0x10, 0x13, 0x17, 0x1A, 0x1E, 0x21, 0x25, 0x28, 00076 0x2C, 0x2F, 0x33, 0x36, 0x3A, 0x3D, 0x41, 0x44, 00077 0x48, 0x4B, 0x4F, 0x52, 0x56, 0x59, 0x5C, 0x60, 00078 0x63, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C, 00079 0x7F, 0x83, 0x86, 0x8A, 0x8D, 0x91, 0x94, 0x98, 00080 0x9B, 0x9F, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB3, 00081 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 0xCC, 0xCF, 00082 0xD3, 0xD6, 0xDA, 0xDD, 0xE1, 0xE4, 0xE8, 0xEB}; 00083 00084 static const uint8_t ulti_chromas[16] = 00085 { 0x60, 0x67, 0x6D, 0x73, 0x7A, 0x80, 0x86, 0x8D, 00086 0x93, 0x99, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC0}; 00087 00088 /* convert Ultimotion YUV block (sixteen 6-bit Y samples and 00089 two 4-bit chroma samples) into standard YUV and put it into frame */ 00090 static void ulti_convert_yuv(AVFrame *frame, int x, int y, 00091 uint8_t *luma,int chroma) 00092 { 00093 uint8_t *y_plane, *cr_plane, *cb_plane; 00094 int i; 00095 00096 y_plane = frame->data[0] + x + y * frame->linesize[0]; 00097 cr_plane = frame->data[1] + (x / 4) + (y / 4) * frame->linesize[1]; 00098 cb_plane = frame->data[2] + (x / 4) + (y / 4) * frame->linesize[2]; 00099 00100 cr_plane[0] = ulti_chromas[chroma >> 4]; 00101 00102 cb_plane[0] = ulti_chromas[chroma & 0xF]; 00103 00104 00105 for(i = 0; i < 16; i++){ 00106 y_plane[i & 3] = ulti_lumas[luma[i]]; 00107 if((i & 3) == 3) { //next row 00108 y_plane += frame->linesize[0]; 00109 } 00110 } 00111 } 00112 00113 /* generate block like in MS Video1 */ 00114 static void ulti_pattern(AVFrame *frame, int x, int y, 00115 int f0, int f1, int Y0, int Y1, int chroma) 00116 { 00117 uint8_t Luma[16]; 00118 int mask, i; 00119 for(mask = 0x80, i = 0; mask; mask >>= 1, i++) { 00120 if(f0 & mask) 00121 Luma[i] = Y1; 00122 else 00123 Luma[i] = Y0; 00124 } 00125 00126 for(mask = 0x80, i = 8; mask; mask >>= 1, i++) { 00127 if(f1 & mask) 00128 Luma[i] = Y1; 00129 else 00130 Luma[i] = Y0; 00131 } 00132 00133 ulti_convert_yuv(frame, x, y, Luma, chroma); 00134 } 00135 00136 /* fill block with some gradient */ 00137 static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle) 00138 { 00139 uint8_t Luma[16]; 00140 if(angle & 8) { //reverse order 00141 int t; 00142 angle &= 0x7; 00143 t = Y[0]; 00144 Y[0] = Y[3]; 00145 Y[3] = t; 00146 t = Y[1]; 00147 Y[1] = Y[2]; 00148 Y[2] = t; 00149 } 00150 switch(angle){ 00151 case 0: 00152 Luma[0] = Y[0]; Luma[1] = Y[1]; Luma[2] = Y[2]; Luma[3] = Y[3]; 00153 Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3]; 00154 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3]; 00155 Luma[12] = Y[0]; Luma[13] = Y[1]; Luma[14] = Y[2]; Luma[15] = Y[3]; 00156 break; 00157 case 1: 00158 Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3]; 00159 Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3]; 00160 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3]; 00161 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2]; 00162 break; 00163 case 2: 00164 Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3]; 00165 Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3]; 00166 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2]; 00167 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2]; 00168 break; 00169 case 3: 00170 Luma[0] = Y[2]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3]; 00171 Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3]; 00172 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2]; 00173 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[1]; 00174 break; 00175 case 4: 00176 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3]; 00177 Luma[4] = Y[2]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[2]; 00178 Luma[8] = Y[1]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[1]; 00179 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0]; 00180 break; 00181 case 5: 00182 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[2]; 00183 Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[1]; 00184 Luma[8] = Y[2]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[0]; 00185 Luma[12] = Y[1]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0]; 00186 break; 00187 case 6: 00188 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[2]; 00189 Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[1]; 00190 Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0]; 00191 Luma[12] = Y[1]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0]; 00192 break; 00193 case 7: 00194 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[1]; 00195 Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[0]; 00196 Luma[8] = Y[3]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0]; 00197 Luma[12] = Y[2]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0]; 00198 break; 00199 default: 00200 Luma[0] = Y[0]; Luma[1] = Y[0]; Luma[2] = Y[1]; Luma[3] = Y[1]; 00201 Luma[4] = Y[0]; Luma[5] = Y[0]; Luma[6] = Y[1]; Luma[7] = Y[1]; 00202 Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[3]; Luma[11] = Y[3]; 00203 Luma[12] = Y[2]; Luma[13] = Y[2]; Luma[14] = Y[3]; Luma[15] = Y[3]; 00204 break; 00205 } 00206 00207 ulti_convert_yuv(frame, x, y, Luma, chroma); 00208 } 00209 00210 static int ulti_decode_frame(AVCodecContext *avctx, 00211 void *data, int *data_size, 00212 AVPacket *avpkt) 00213 { 00214 const uint8_t *buf = avpkt->data; 00215 int buf_size = avpkt->size; 00216 UltimotionDecodeContext *s=avctx->priv_data; 00217 int modifier = 0; 00218 int uniq = 0; 00219 int mode = 0; 00220 int blocks = 0; 00221 int done = 0; 00222 int x = 0, y = 0; 00223 int i; 00224 int skip; 00225 int tmp; 00226 00227 if(s->frame.data[0]) 00228 avctx->release_buffer(avctx, &s->frame); 00229 00230 s->frame.reference = 1; 00231 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00232 if(avctx->get_buffer(avctx, &s->frame) < 0) { 00233 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00234 return -1; 00235 } 00236 00237 while(!done) { 00238 int idx; 00239 if(blocks >= s->blocks || y >= s->height) 00240 break;//all blocks decoded 00241 00242 idx = *buf++; 00243 if((idx & 0xF8) == 0x70) { 00244 switch(idx) { 00245 case 0x70: //change modifier 00246 modifier = *buf++; 00247 if(modifier>1) 00248 av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); 00249 break; 00250 case 0x71: // set uniq flag 00251 uniq = 1; 00252 break; 00253 case 0x72: //toggle mode 00254 mode = !mode; 00255 break; 00256 case 0x73: //end-of-frame 00257 done = 1; 00258 break; 00259 case 0x74: //skip some blocks 00260 skip = *buf++; 00261 if ((blocks + skip) >= s->blocks) 00262 break; 00263 blocks += skip; 00264 x += skip * 8; 00265 while(x >= s->width) { 00266 x -= s->width; 00267 y += 8; 00268 } 00269 break; 00270 default: 00271 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx); 00272 } 00273 } else { //handle one block 00274 int code; 00275 int cf; 00276 int angle = 0; 00277 uint8_t Y[4]; // luma samples of block 00278 int tx = 0, ty = 0; //coords of subblock 00279 int chroma = 0; 00280 if (mode || uniq) { 00281 uniq = 0; 00282 cf = 1; 00283 chroma = 0; 00284 } else { 00285 cf = 0; 00286 if (idx) 00287 chroma = *buf++; 00288 } 00289 for (i = 0; i < 4; i++) { // for every subblock 00290 code = (idx >> (6 - i*2)) & 3; //extract 2 bits 00291 if(!code) //skip subblock 00292 continue; 00293 if(cf) 00294 chroma = *buf++; 00295 tx = x + block_coords[i * 2]; 00296 ty = y + block_coords[(i * 2) + 1]; 00297 switch(code) { 00298 case 1: 00299 tmp = *buf++; 00300 00301 angle = angle_by_index[(tmp >> 6) & 0x3]; 00302 00303 Y[0] = tmp & 0x3F; 00304 Y[1] = Y[0]; 00305 00306 if (angle) { 00307 Y[2] = Y[0]+1; 00308 if (Y[2] > 0x3F) 00309 Y[2] = 0x3F; 00310 Y[3] = Y[2]; 00311 } else { 00312 Y[2] = Y[0]; 00313 Y[3] = Y[0]; 00314 } 00315 break; 00316 00317 case 2: 00318 if (modifier) { // unpack four luma samples 00319 tmp = bytestream_get_be24(&buf); 00320 00321 Y[0] = (tmp >> 18) & 0x3F; 00322 Y[1] = (tmp >> 12) & 0x3F; 00323 Y[2] = (tmp >> 6) & 0x3F; 00324 Y[3] = tmp & 0x3F; 00325 angle = 16; 00326 } else { // retrieve luma samples from codebook 00327 tmp = bytestream_get_be16(&buf); 00328 00329 angle = (tmp >> 12) & 0xF; 00330 tmp &= 0xFFF; 00331 tmp <<= 2; 00332 Y[0] = s->ulti_codebook[tmp]; 00333 Y[1] = s->ulti_codebook[tmp + 1]; 00334 Y[2] = s->ulti_codebook[tmp + 2]; 00335 Y[3] = s->ulti_codebook[tmp + 3]; 00336 } 00337 break; 00338 00339 case 3: 00340 if (modifier) { // all 16 luma samples 00341 uint8_t Luma[16]; 00342 00343 tmp = bytestream_get_be24(&buf); 00344 Luma[0] = (tmp >> 18) & 0x3F; 00345 Luma[1] = (tmp >> 12) & 0x3F; 00346 Luma[2] = (tmp >> 6) & 0x3F; 00347 Luma[3] = tmp & 0x3F; 00348 00349 tmp = bytestream_get_be24(&buf); 00350 Luma[4] = (tmp >> 18) & 0x3F; 00351 Luma[5] = (tmp >> 12) & 0x3F; 00352 Luma[6] = (tmp >> 6) & 0x3F; 00353 Luma[7] = tmp & 0x3F; 00354 00355 tmp = bytestream_get_be24(&buf); 00356 Luma[8] = (tmp >> 18) & 0x3F; 00357 Luma[9] = (tmp >> 12) & 0x3F; 00358 Luma[10] = (tmp >> 6) & 0x3F; 00359 Luma[11] = tmp & 0x3F; 00360 00361 tmp = bytestream_get_be24(&buf); 00362 Luma[12] = (tmp >> 18) & 0x3F; 00363 Luma[13] = (tmp >> 12) & 0x3F; 00364 Luma[14] = (tmp >> 6) & 0x3F; 00365 Luma[15] = tmp & 0x3F; 00366 00367 ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); 00368 } else { 00369 tmp = *buf++; 00370 if(tmp & 0x80) { 00371 angle = (tmp >> 4) & 0x7; 00372 tmp = (tmp << 8) + *buf++; 00373 Y[0] = (tmp >> 6) & 0x3F; 00374 Y[1] = tmp & 0x3F; 00375 Y[2] = (*buf++) & 0x3F; 00376 Y[3] = (*buf++) & 0x3F; 00377 ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block 00378 } else { // some patterns 00379 int f0, f1; 00380 f0 = *buf++; 00381 f1 = tmp; 00382 Y[0] = (*buf++) & 0x3F; 00383 Y[1] = (*buf++) & 0x3F; 00384 ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); 00385 } 00386 } 00387 break; 00388 } 00389 if(code != 3) 00390 ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block 00391 } 00392 blocks++; 00393 x += 8; 00394 if(x >= s->width) { 00395 x = 0; 00396 y += 8; 00397 } 00398 } 00399 } 00400 00401 *data_size=sizeof(AVFrame); 00402 *(AVFrame*)data= s->frame; 00403 00404 return buf_size; 00405 } 00406 00407 AVCodec ulti_decoder = { 00408 "ultimotion", 00409 AVMEDIA_TYPE_VIDEO, 00410 CODEC_ID_ULTI, 00411 sizeof(UltimotionDecodeContext), 00412 ulti_decode_init, 00413 NULL, 00414 ulti_decode_end, 00415 ulti_decode_frame, 00416 CODEC_CAP_DR1, 00417 NULL, 00418 .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"), 00419 }; 00420