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 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] =
00069 { 0, 0, 0, 4, 4, 4, 4, 0};
00070
00071 static const int angle_by_index[4] = { 0, 2, 6, 12};
00072
00073
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
00089
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) {
00108 y_plane += frame->linesize[0];
00109 }
00110 }
00111 }
00112
00113
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
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) {
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;
00241
00242 idx = *buf++;
00243 if((idx & 0xF8) == 0x70) {
00244 switch(idx) {
00245 case 0x70:
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:
00251 uniq = 1;
00252 break;
00253 case 0x72:
00254 mode = !mode;
00255 break;
00256 case 0x73:
00257 done = 1;
00258 break;
00259 case 0x74:
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 {
00274 int code;
00275 int cf;
00276 int angle = 0;
00277 uint8_t Y[4];
00278 int tx = 0, ty = 0;
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++) {
00290 code = (idx >> (6 - i*2)) & 3;
00291 if(!code)
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) {
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 {
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) {
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);
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 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