00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 avcodec_get_frame_defaults(&s->frame);
00053 avctx->coded_frame = (AVFrame*) &s->frame;
00054 s->ulti_codebook = ulti_codebook;
00055
00056 return 0;
00057 }
00058
00059 static av_cold int ulti_decode_end(AVCodecContext *avctx){
00060 UltimotionDecodeContext *s = avctx->priv_data;
00061 AVFrame *pic = &s->frame;
00062
00063 if (pic->data[0])
00064 avctx->release_buffer(avctx, pic);
00065
00066 return 0;
00067 }
00068
00069 static const int block_coords[8] =
00070 { 0, 0, 0, 4, 4, 4, 4, 0};
00071
00072 static const int angle_by_index[4] = { 0, 2, 6, 12};
00073
00074
00075 static const uint8_t ulti_lumas[64] =
00076 { 0x10, 0x13, 0x17, 0x1A, 0x1E, 0x21, 0x25, 0x28,
00077 0x2C, 0x2F, 0x33, 0x36, 0x3A, 0x3D, 0x41, 0x44,
00078 0x48, 0x4B, 0x4F, 0x52, 0x56, 0x59, 0x5C, 0x60,
00079 0x63, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C,
00080 0x7F, 0x83, 0x86, 0x8A, 0x8D, 0x91, 0x94, 0x98,
00081 0x9B, 0x9F, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB3,
00082 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 0xCC, 0xCF,
00083 0xD3, 0xD6, 0xDA, 0xDD, 0xE1, 0xE4, 0xE8, 0xEB};
00084
00085 static const uint8_t ulti_chromas[16] =
00086 { 0x60, 0x67, 0x6D, 0x73, 0x7A, 0x80, 0x86, 0x8D,
00087 0x93, 0x99, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC0};
00088
00089
00090
00091 static void ulti_convert_yuv(AVFrame *frame, int x, int y,
00092 uint8_t *luma,int chroma)
00093 {
00094 uint8_t *y_plane, *cr_plane, *cb_plane;
00095 int i;
00096
00097 y_plane = frame->data[0] + x + y * frame->linesize[0];
00098 cr_plane = frame->data[1] + (x / 4) + (y / 4) * frame->linesize[1];
00099 cb_plane = frame->data[2] + (x / 4) + (y / 4) * frame->linesize[2];
00100
00101 cr_plane[0] = ulti_chromas[chroma >> 4];
00102
00103 cb_plane[0] = ulti_chromas[chroma & 0xF];
00104
00105
00106 for(i = 0; i < 16; i++){
00107 y_plane[i & 3] = ulti_lumas[luma[i]];
00108 if((i & 3) == 3) {
00109 y_plane += frame->linesize[0];
00110 }
00111 }
00112 }
00113
00114
00115 static void ulti_pattern(AVFrame *frame, int x, int y,
00116 int f0, int f1, int Y0, int Y1, int chroma)
00117 {
00118 uint8_t Luma[16];
00119 int mask, i;
00120 for(mask = 0x80, i = 0; mask; mask >>= 1, i++) {
00121 if(f0 & mask)
00122 Luma[i] = Y1;
00123 else
00124 Luma[i] = Y0;
00125 }
00126
00127 for(mask = 0x80, i = 8; mask; mask >>= 1, i++) {
00128 if(f1 & mask)
00129 Luma[i] = Y1;
00130 else
00131 Luma[i] = Y0;
00132 }
00133
00134 ulti_convert_yuv(frame, x, y, Luma, chroma);
00135 }
00136
00137
00138 static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle)
00139 {
00140 uint8_t Luma[16];
00141 if(angle & 8) {
00142 int t;
00143 angle &= 0x7;
00144 t = Y[0];
00145 Y[0] = Y[3];
00146 Y[3] = t;
00147 t = Y[1];
00148 Y[1] = Y[2];
00149 Y[2] = t;
00150 }
00151 switch(angle){
00152 case 0:
00153 Luma[0] = Y[0]; Luma[1] = Y[1]; Luma[2] = Y[2]; Luma[3] = Y[3];
00154 Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3];
00155 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
00156 Luma[12] = Y[0]; Luma[13] = Y[1]; Luma[14] = Y[2]; Luma[15] = Y[3];
00157 break;
00158 case 1:
00159 Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3];
00160 Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3];
00161 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
00162 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
00163 break;
00164 case 2:
00165 Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3];
00166 Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3];
00167 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
00168 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
00169 break;
00170 case 3:
00171 Luma[0] = Y[2]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3];
00172 Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3];
00173 Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
00174 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[1];
00175 break;
00176 case 4:
00177 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3];
00178 Luma[4] = Y[2]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[2];
00179 Luma[8] = Y[1]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[1];
00180 Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
00181 break;
00182 case 5:
00183 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[2];
00184 Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[1];
00185 Luma[8] = Y[2]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[0];
00186 Luma[12] = Y[1]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
00187 break;
00188 case 6:
00189 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[2];
00190 Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[1];
00191 Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
00192 Luma[12] = Y[1]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
00193 break;
00194 case 7:
00195 Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[1];
00196 Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[0];
00197 Luma[8] = Y[3]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
00198 Luma[12] = Y[2]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
00199 break;
00200 default:
00201 Luma[0] = Y[0]; Luma[1] = Y[0]; Luma[2] = Y[1]; Luma[3] = Y[1];
00202 Luma[4] = Y[0]; Luma[5] = Y[0]; Luma[6] = Y[1]; Luma[7] = Y[1];
00203 Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[3]; Luma[11] = Y[3];
00204 Luma[12] = Y[2]; Luma[13] = Y[2]; Luma[14] = Y[3]; Luma[15] = Y[3];
00205 break;
00206 }
00207
00208 ulti_convert_yuv(frame, x, y, Luma, chroma);
00209 }
00210
00211 static int ulti_decode_frame(AVCodecContext *avctx,
00212 void *data, int *data_size,
00213 AVPacket *avpkt)
00214 {
00215 const uint8_t *buf = avpkt->data;
00216 int buf_size = avpkt->size;
00217 UltimotionDecodeContext *s=avctx->priv_data;
00218 int modifier = 0;
00219 int uniq = 0;
00220 int mode = 0;
00221 int blocks = 0;
00222 int done = 0;
00223 int x = 0, y = 0;
00224 int i;
00225 int skip;
00226 int tmp;
00227
00228 s->frame.reference = 1;
00229 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00230 if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00231 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00232 return -1;
00233 }
00234
00235 while(!done) {
00236 int idx;
00237 if(blocks >= s->blocks || y >= s->height)
00238 break;
00239
00240 idx = *buf++;
00241 if((idx & 0xF8) == 0x70) {
00242 switch(idx) {
00243 case 0x70:
00244 modifier = *buf++;
00245 if(modifier>1)
00246 av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
00247 break;
00248 case 0x71:
00249 uniq = 1;
00250 break;
00251 case 0x72:
00252 mode = !mode;
00253 break;
00254 case 0x73:
00255 done = 1;
00256 break;
00257 case 0x74:
00258 skip = *buf++;
00259 if ((blocks + skip) >= s->blocks)
00260 break;
00261 blocks += skip;
00262 x += skip * 8;
00263 while(x >= s->width) {
00264 x -= s->width;
00265 y += 8;
00266 }
00267 break;
00268 default:
00269 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
00270 }
00271 } else {
00272 int code;
00273 int cf;
00274 int angle = 0;
00275 uint8_t Y[4];
00276 int tx = 0, ty = 0;
00277 int chroma = 0;
00278 if (mode || uniq) {
00279 uniq = 0;
00280 cf = 1;
00281 chroma = 0;
00282 } else {
00283 cf = 0;
00284 if (idx)
00285 chroma = *buf++;
00286 }
00287 for (i = 0; i < 4; i++) {
00288 code = (idx >> (6 - i*2)) & 3;
00289 if(!code)
00290 continue;
00291 if(cf)
00292 chroma = *buf++;
00293 tx = x + block_coords[i * 2];
00294 ty = y + block_coords[(i * 2) + 1];
00295 switch(code) {
00296 case 1:
00297 tmp = *buf++;
00298
00299 angle = angle_by_index[(tmp >> 6) & 0x3];
00300
00301 Y[0] = tmp & 0x3F;
00302 Y[1] = Y[0];
00303
00304 if (angle) {
00305 Y[2] = Y[0]+1;
00306 if (Y[2] > 0x3F)
00307 Y[2] = 0x3F;
00308 Y[3] = Y[2];
00309 } else {
00310 Y[2] = Y[0];
00311 Y[3] = Y[0];
00312 }
00313 break;
00314
00315 case 2:
00316 if (modifier) {
00317 tmp = bytestream_get_be24(&buf);
00318
00319 Y[0] = (tmp >> 18) & 0x3F;
00320 Y[1] = (tmp >> 12) & 0x3F;
00321 Y[2] = (tmp >> 6) & 0x3F;
00322 Y[3] = tmp & 0x3F;
00323 angle = 16;
00324 } else {
00325 tmp = bytestream_get_be16(&buf);
00326
00327 angle = (tmp >> 12) & 0xF;
00328 tmp &= 0xFFF;
00329 tmp <<= 2;
00330 Y[0] = s->ulti_codebook[tmp];
00331 Y[1] = s->ulti_codebook[tmp + 1];
00332 Y[2] = s->ulti_codebook[tmp + 2];
00333 Y[3] = s->ulti_codebook[tmp + 3];
00334 }
00335 break;
00336
00337 case 3:
00338 if (modifier) {
00339 uint8_t Luma[16];
00340
00341 tmp = bytestream_get_be24(&buf);
00342 Luma[0] = (tmp >> 18) & 0x3F;
00343 Luma[1] = (tmp >> 12) & 0x3F;
00344 Luma[2] = (tmp >> 6) & 0x3F;
00345 Luma[3] = tmp & 0x3F;
00346
00347 tmp = bytestream_get_be24(&buf);
00348 Luma[4] = (tmp >> 18) & 0x3F;
00349 Luma[5] = (tmp >> 12) & 0x3F;
00350 Luma[6] = (tmp >> 6) & 0x3F;
00351 Luma[7] = tmp & 0x3F;
00352
00353 tmp = bytestream_get_be24(&buf);
00354 Luma[8] = (tmp >> 18) & 0x3F;
00355 Luma[9] = (tmp >> 12) & 0x3F;
00356 Luma[10] = (tmp >> 6) & 0x3F;
00357 Luma[11] = tmp & 0x3F;
00358
00359 tmp = bytestream_get_be24(&buf);
00360 Luma[12] = (tmp >> 18) & 0x3F;
00361 Luma[13] = (tmp >> 12) & 0x3F;
00362 Luma[14] = (tmp >> 6) & 0x3F;
00363 Luma[15] = tmp & 0x3F;
00364
00365 ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
00366 } else {
00367 tmp = *buf++;
00368 if(tmp & 0x80) {
00369 angle = (tmp >> 4) & 0x7;
00370 tmp = (tmp << 8) + *buf++;
00371 Y[0] = (tmp >> 6) & 0x3F;
00372 Y[1] = tmp & 0x3F;
00373 Y[2] = (*buf++) & 0x3F;
00374 Y[3] = (*buf++) & 0x3F;
00375 ulti_grad(&s->frame, tx, ty, Y, chroma, angle);
00376 } else {
00377 int f0, f1;
00378 f0 = *buf++;
00379 f1 = tmp;
00380 Y[0] = (*buf++) & 0x3F;
00381 Y[1] = (*buf++) & 0x3F;
00382 ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
00383 }
00384 }
00385 break;
00386 }
00387 if(code != 3)
00388 ulti_grad(&s->frame, tx, ty, Y, chroma, angle);
00389 }
00390 blocks++;
00391 x += 8;
00392 if(x >= s->width) {
00393 x = 0;
00394 y += 8;
00395 }
00396 }
00397 }
00398
00399 *data_size=sizeof(AVFrame);
00400 *(AVFrame*)data= s->frame;
00401
00402 return buf_size;
00403 }
00404
00405 AVCodec ff_ulti_decoder = {
00406 "ultimotion",
00407 AVMEDIA_TYPE_VIDEO,
00408 CODEC_ID_ULTI,
00409 sizeof(UltimotionDecodeContext),
00410 ulti_decode_init,
00411 NULL,
00412 ulti_decode_end,
00413 ulti_decode_frame,
00414 CODEC_CAP_DR1,
00415 NULL,
00416 .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
00417 };
00418