Libav 0.7.1
|
00001 /* 00002 * IBM Ultimotion Video Decoder 00003 * Copyright (C) 2004 Konstantin Shishkov 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 s->frame.reference = 1; 00228 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00229 if (avctx->reget_buffer(avctx, &s->frame) < 0) { 00230 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 00231 return -1; 00232 } 00233 00234 while(!done) { 00235 int idx; 00236 if(blocks >= s->blocks || y >= s->height) 00237 break;//all blocks decoded 00238 00239 idx = *buf++; 00240 if((idx & 0xF8) == 0x70) { 00241 switch(idx) { 00242 case 0x70: //change modifier 00243 modifier = *buf++; 00244 if(modifier>1) 00245 av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); 00246 break; 00247 case 0x71: // set uniq flag 00248 uniq = 1; 00249 break; 00250 case 0x72: //toggle mode 00251 mode = !mode; 00252 break; 00253 case 0x73: //end-of-frame 00254 done = 1; 00255 break; 00256 case 0x74: //skip some blocks 00257 skip = *buf++; 00258 if ((blocks + skip) >= s->blocks) 00259 break; 00260 blocks += skip; 00261 x += skip * 8; 00262 while(x >= s->width) { 00263 x -= s->width; 00264 y += 8; 00265 } 00266 break; 00267 default: 00268 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx); 00269 } 00270 } else { //handle one block 00271 int code; 00272 int cf; 00273 int angle = 0; 00274 uint8_t Y[4]; // luma samples of block 00275 int tx = 0, ty = 0; //coords of subblock 00276 int chroma = 0; 00277 if (mode || uniq) { 00278 uniq = 0; 00279 cf = 1; 00280 chroma = 0; 00281 } else { 00282 cf = 0; 00283 if (idx) 00284 chroma = *buf++; 00285 } 00286 for (i = 0; i < 4; i++) { // for every subblock 00287 code = (idx >> (6 - i*2)) & 3; //extract 2 bits 00288 if(!code) //skip subblock 00289 continue; 00290 if(cf) 00291 chroma = *buf++; 00292 tx = x + block_coords[i * 2]; 00293 ty = y + block_coords[(i * 2) + 1]; 00294 switch(code) { 00295 case 1: 00296 tmp = *buf++; 00297 00298 angle = angle_by_index[(tmp >> 6) & 0x3]; 00299 00300 Y[0] = tmp & 0x3F; 00301 Y[1] = Y[0]; 00302 00303 if (angle) { 00304 Y[2] = Y[0]+1; 00305 if (Y[2] > 0x3F) 00306 Y[2] = 0x3F; 00307 Y[3] = Y[2]; 00308 } else { 00309 Y[2] = Y[0]; 00310 Y[3] = Y[0]; 00311 } 00312 break; 00313 00314 case 2: 00315 if (modifier) { // unpack four luma samples 00316 tmp = bytestream_get_be24(&buf); 00317 00318 Y[0] = (tmp >> 18) & 0x3F; 00319 Y[1] = (tmp >> 12) & 0x3F; 00320 Y[2] = (tmp >> 6) & 0x3F; 00321 Y[3] = tmp & 0x3F; 00322 angle = 16; 00323 } else { // retrieve luma samples from codebook 00324 tmp = bytestream_get_be16(&buf); 00325 00326 angle = (tmp >> 12) & 0xF; 00327 tmp &= 0xFFF; 00328 tmp <<= 2; 00329 Y[0] = s->ulti_codebook[tmp]; 00330 Y[1] = s->ulti_codebook[tmp + 1]; 00331 Y[2] = s->ulti_codebook[tmp + 2]; 00332 Y[3] = s->ulti_codebook[tmp + 3]; 00333 } 00334 break; 00335 00336 case 3: 00337 if (modifier) { // all 16 luma samples 00338 uint8_t Luma[16]; 00339 00340 tmp = bytestream_get_be24(&buf); 00341 Luma[0] = (tmp >> 18) & 0x3F; 00342 Luma[1] = (tmp >> 12) & 0x3F; 00343 Luma[2] = (tmp >> 6) & 0x3F; 00344 Luma[3] = tmp & 0x3F; 00345 00346 tmp = bytestream_get_be24(&buf); 00347 Luma[4] = (tmp >> 18) & 0x3F; 00348 Luma[5] = (tmp >> 12) & 0x3F; 00349 Luma[6] = (tmp >> 6) & 0x3F; 00350 Luma[7] = tmp & 0x3F; 00351 00352 tmp = bytestream_get_be24(&buf); 00353 Luma[8] = (tmp >> 18) & 0x3F; 00354 Luma[9] = (tmp >> 12) & 0x3F; 00355 Luma[10] = (tmp >> 6) & 0x3F; 00356 Luma[11] = tmp & 0x3F; 00357 00358 tmp = bytestream_get_be24(&buf); 00359 Luma[12] = (tmp >> 18) & 0x3F; 00360 Luma[13] = (tmp >> 12) & 0x3F; 00361 Luma[14] = (tmp >> 6) & 0x3F; 00362 Luma[15] = tmp & 0x3F; 00363 00364 ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); 00365 } else { 00366 tmp = *buf++; 00367 if(tmp & 0x80) { 00368 angle = (tmp >> 4) & 0x7; 00369 tmp = (tmp << 8) + *buf++; 00370 Y[0] = (tmp >> 6) & 0x3F; 00371 Y[1] = tmp & 0x3F; 00372 Y[2] = (*buf++) & 0x3F; 00373 Y[3] = (*buf++) & 0x3F; 00374 ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block 00375 } else { // some patterns 00376 int f0, f1; 00377 f0 = *buf++; 00378 f1 = tmp; 00379 Y[0] = (*buf++) & 0x3F; 00380 Y[1] = (*buf++) & 0x3F; 00381 ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); 00382 } 00383 } 00384 break; 00385 } 00386 if(code != 3) 00387 ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block 00388 } 00389 blocks++; 00390 x += 8; 00391 if(x >= s->width) { 00392 x = 0; 00393 y += 8; 00394 } 00395 } 00396 } 00397 00398 *data_size=sizeof(AVFrame); 00399 *(AVFrame*)data= s->frame; 00400 00401 return buf_size; 00402 } 00403 00404 AVCodec ff_ulti_decoder = { 00405 "ultimotion", 00406 AVMEDIA_TYPE_VIDEO, 00407 CODEC_ID_ULTI, 00408 sizeof(UltimotionDecodeContext), 00409 ulti_decode_init, 00410 NULL, 00411 ulti_decode_end, 00412 ulti_decode_frame, 00413 CODEC_CAP_DR1, 00414 NULL, 00415 .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"), 00416 }; 00417