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 #include <unistd.h>
00031
00032 #include "avcodec.h"
00033 #include "bytestream.h"
00034
00035 #include "ulti_cb.h"
00036
00037 typedef struct UltimotionDecodeContext {
00038 AVCodecContext *avctx;
00039 int width, height, blocks;
00040 AVFrame frame;
00041 const uint8_t *ulti_codebook;
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 const int block_coords[8] =
00060 { 0, 0, 0, 4, 4, 4, 4, 0};
00061
00062 static const int angle_by_index[4] = { 0, 2, 6, 12};
00063
00064
00065 static const 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 const 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 const 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 = bytestream_get_be24(&buf);
00309
00310 Y[0] = (tmp >> 18) & 0x3F;
00311 Y[1] = (tmp >> 12) & 0x3F;
00312 Y[2] = (tmp >> 6) & 0x3F;
00313 Y[3] = tmp & 0x3F;
00314 angle = 16;
00315 } else {
00316 tmp = bytestream_get_be16(&buf);
00317
00318 angle = (tmp >> 12) & 0xF;
00319 tmp &= 0xFFF;
00320 tmp <<= 2;
00321 Y[0] = s->ulti_codebook[tmp];
00322 Y[1] = s->ulti_codebook[tmp + 1];
00323 Y[2] = s->ulti_codebook[tmp + 2];
00324 Y[3] = s->ulti_codebook[tmp + 3];
00325 }
00326 break;
00327
00328 case 3:
00329 if (modifier) {
00330 uint8_t Luma[16];
00331
00332 tmp = bytestream_get_be24(&buf);
00333 Luma[0] = (tmp >> 18) & 0x3F;
00334 Luma[1] = (tmp >> 12) & 0x3F;
00335 Luma[2] = (tmp >> 6) & 0x3F;
00336 Luma[3] = tmp & 0x3F;
00337
00338 tmp = bytestream_get_be24(&buf);
00339 Luma[4] = (tmp >> 18) & 0x3F;
00340 Luma[5] = (tmp >> 12) & 0x3F;
00341 Luma[6] = (tmp >> 6) & 0x3F;
00342 Luma[7] = tmp & 0x3F;
00343
00344 tmp = bytestream_get_be24(&buf);
00345 Luma[8] = (tmp >> 18) & 0x3F;
00346 Luma[9] = (tmp >> 12) & 0x3F;
00347 Luma[10] = (tmp >> 6) & 0x3F;
00348 Luma[11] = tmp & 0x3F;
00349
00350 tmp = bytestream_get_be24(&buf);
00351 Luma[12] = (tmp >> 18) & 0x3F;
00352 Luma[13] = (tmp >> 12) & 0x3F;
00353 Luma[14] = (tmp >> 6) & 0x3F;
00354 Luma[15] = tmp & 0x3F;
00355
00356 ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
00357 } else {
00358 tmp = *buf++;
00359 if(tmp & 0x80) {
00360 angle = (tmp >> 4) & 0x7;
00361 tmp = (tmp << 8) + *buf++;
00362 Y[0] = (tmp >> 6) & 0x3F;
00363 Y[1] = tmp & 0x3F;
00364 Y[2] = (*buf++) & 0x3F;
00365 Y[3] = (*buf++) & 0x3F;
00366 ulti_grad(&s->frame, tx, ty, Y, chroma, angle);
00367 } else {
00368 int f0, f1;
00369 f0 = *buf++;
00370 f1 = tmp;
00371 Y[0] = (*buf++) & 0x3F;
00372 Y[1] = (*buf++) & 0x3F;
00373 ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
00374 }
00375 }
00376 break;
00377 }
00378 if(code != 3)
00379 ulti_grad(&s->frame, tx, ty, Y, chroma, angle);
00380 }
00381 blocks++;
00382 x += 8;
00383 if(x >= s->width) {
00384 x = 0;
00385 y += 8;
00386 }
00387 }
00388 }
00389
00390 *data_size=sizeof(AVFrame);
00391 *(AVFrame*)data= s->frame;
00392
00393 return buf_size;
00394 }
00395
00396 static av_cold int ulti_decode_end(AVCodecContext *avctx)
00397 {
00398
00399
00400 return 0;
00401 }
00402
00403 AVCodec ulti_decoder = {
00404 "ultimotion",
00405 CODEC_TYPE_VIDEO,
00406 CODEC_ID_ULTI,
00407 sizeof(UltimotionDecodeContext),
00408 ulti_decode_init,
00409 NULL,
00410 ulti_decode_end,
00411 ulti_decode_frame,
00412 CODEC_CAP_DR1,
00413 NULL,
00414 .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
00415 };
00416