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