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