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 GetByteContext gb;
00042 } UltimotionDecodeContext;
00043
00044 static av_cold int ulti_decode_init(AVCodecContext *avctx)
00045 {
00046 UltimotionDecodeContext *s = avctx->priv_data;
00047
00048 s->avctx = avctx;
00049 s->width = avctx->width;
00050 s->height = avctx->height;
00051 s->blocks = (s->width / 8) * (s->height / 8);
00052 avctx->pix_fmt = PIX_FMT_YUV410P;
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 bytestream2_init(&s->gb, buf, buf_size);
00236
00237 while(!done) {
00238 int idx;
00239 if(blocks >= s->blocks || y >= s->height)
00240 break;
00241
00242 if (bytestream2_get_bytes_left(&s->gb) < 1)
00243 goto err;
00244 idx = bytestream2_get_byteu(&s->gb);
00245 if((idx & 0xF8) == 0x70) {
00246 switch(idx) {
00247 case 0x70:
00248 modifier = bytestream2_get_byte(&s->gb);
00249 if(modifier>1)
00250 av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
00251 break;
00252 case 0x71:
00253 uniq = 1;
00254 break;
00255 case 0x72:
00256 mode = !mode;
00257 break;
00258 case 0x73:
00259 done = 1;
00260 break;
00261 case 0x74:
00262 skip = bytestream2_get_byte(&s->gb);
00263 if ((blocks + skip) >= s->blocks)
00264 break;
00265 blocks += skip;
00266 x += skip * 8;
00267 while(x >= s->width) {
00268 x -= s->width;
00269 y += 8;
00270 }
00271 break;
00272 default:
00273 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
00274 }
00275 } else {
00276 int code;
00277 int cf;
00278 int angle = 0;
00279 uint8_t Y[4];
00280 int tx = 0, ty = 0;
00281 int chroma = 0;
00282 if (mode || uniq) {
00283 uniq = 0;
00284 cf = 1;
00285 chroma = 0;
00286 } else {
00287 cf = 0;
00288 if (idx) {
00289 chroma = bytestream2_get_byte(&s->gb);
00290 }
00291 }
00292 for (i = 0; i < 4; i++) {
00293 code = (idx >> (6 - i*2)) & 3;
00294 if(!code)
00295 continue;
00296 if(cf) {
00297 chroma = bytestream2_get_byte(&s->gb);
00298 }
00299 tx = x + block_coords[i * 2];
00300 ty = y + block_coords[(i * 2) + 1];
00301 switch(code) {
00302 case 1:
00303 tmp = bytestream2_get_byte(&s->gb);
00304
00305 angle = angle_by_index[(tmp >> 6) & 0x3];
00306
00307 Y[0] = tmp & 0x3F;
00308 Y[1] = Y[0];
00309
00310 if (angle) {
00311 Y[2] = Y[0]+1;
00312 if (Y[2] > 0x3F)
00313 Y[2] = 0x3F;
00314 Y[3] = Y[2];
00315 } else {
00316 Y[2] = Y[0];
00317 Y[3] = Y[0];
00318 }
00319 break;
00320
00321 case 2:
00322 if (modifier) {
00323 tmp = bytestream2_get_be24(&s->gb);
00324
00325 Y[0] = (tmp >> 18) & 0x3F;
00326 Y[1] = (tmp >> 12) & 0x3F;
00327 Y[2] = (tmp >> 6) & 0x3F;
00328 Y[3] = tmp & 0x3F;
00329 angle = 16;
00330 } else {
00331 tmp = bytestream2_get_be16(&s->gb);
00332
00333 angle = (tmp >> 12) & 0xF;
00334 tmp &= 0xFFF;
00335 tmp <<= 2;
00336 Y[0] = s->ulti_codebook[tmp];
00337 Y[1] = s->ulti_codebook[tmp + 1];
00338 Y[2] = s->ulti_codebook[tmp + 2];
00339 Y[3] = s->ulti_codebook[tmp + 3];
00340 }
00341 break;
00342
00343 case 3:
00344 if (modifier) {
00345 uint8_t Luma[16];
00346
00347 if (bytestream2_get_bytes_left(&s->gb) < 12)
00348 goto err;
00349 tmp = bytestream2_get_be24u(&s->gb);
00350 Luma[0] = (tmp >> 18) & 0x3F;
00351 Luma[1] = (tmp >> 12) & 0x3F;
00352 Luma[2] = (tmp >> 6) & 0x3F;
00353 Luma[3] = tmp & 0x3F;
00354
00355 tmp = bytestream2_get_be24u(&s->gb);
00356 Luma[4] = (tmp >> 18) & 0x3F;
00357 Luma[5] = (tmp >> 12) & 0x3F;
00358 Luma[6] = (tmp >> 6) & 0x3F;
00359 Luma[7] = tmp & 0x3F;
00360
00361 tmp = bytestream2_get_be24u(&s->gb);
00362 Luma[8] = (tmp >> 18) & 0x3F;
00363 Luma[9] = (tmp >> 12) & 0x3F;
00364 Luma[10] = (tmp >> 6) & 0x3F;
00365 Luma[11] = tmp & 0x3F;
00366
00367 tmp = bytestream2_get_be24u(&s->gb);
00368 Luma[12] = (tmp >> 18) & 0x3F;
00369 Luma[13] = (tmp >> 12) & 0x3F;
00370 Luma[14] = (tmp >> 6) & 0x3F;
00371 Luma[15] = tmp & 0x3F;
00372
00373 ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
00374 } else {
00375 if (bytestream2_get_bytes_left(&s->gb) < 4)
00376 goto err;
00377 tmp = bytestream2_get_byteu(&s->gb);
00378 if(tmp & 0x80) {
00379 angle = (tmp >> 4) & 0x7;
00380 tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb);
00381 Y[0] = (tmp >> 6) & 0x3F;
00382 Y[1] = tmp & 0x3F;
00383 Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F;
00384 Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F;
00385 ulti_grad(&s->frame, tx, ty, Y, chroma, angle);
00386 } else {
00387 int f0, f1;
00388 f0 = bytestream2_get_byteu(&s->gb);
00389 f1 = tmp;
00390 Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F;
00391 Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F;
00392 ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
00393 }
00394 }
00395 break;
00396 }
00397 if(code != 3)
00398 ulti_grad(&s->frame, tx, ty, Y, chroma, angle);
00399 }
00400 blocks++;
00401 x += 8;
00402 if(x >= s->width) {
00403 x = 0;
00404 y += 8;
00405 }
00406 }
00407 }
00408
00409 *data_size=sizeof(AVFrame);
00410 *(AVFrame*)data= s->frame;
00411
00412 return buf_size;
00413
00414 err:
00415 av_log(avctx, AV_LOG_ERROR,
00416 "Insufficient data\n");
00417 return AVERROR_INVALIDDATA;
00418 }
00419
00420 AVCodec ff_ulti_decoder = {
00421 .name = "ultimotion",
00422 .type = AVMEDIA_TYPE_VIDEO,
00423 .id = CODEC_ID_ULTI,
00424 .priv_data_size = sizeof(UltimotionDecodeContext),
00425 .init = ulti_decode_init,
00426 .close = ulti_decode_end,
00427 .decode = ulti_decode_frame,
00428 .capabilities = CODEC_CAP_DR1,
00429 .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
00430 };
00431