Libav 0.7.1
libavcodec/ulti.c
Go to the documentation of this file.
00001 /*
00002  * IBM Ultimotion Video Decoder
00003  * Copyright (C) 2004 Konstantin Shishkov
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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] = // 4x4 block coords in 8x8 superblock
00069     { 0, 0, 0, 4, 4, 4, 4, 0};
00070 
00071 static const int angle_by_index[4] = { 0, 2, 6, 12};
00072 
00073 /* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
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 /* convert Ultimotion YUV block (sixteen 6-bit Y samples and
00089  two 4-bit chroma samples) into standard YUV and put it into frame */
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) { //next row
00108             y_plane += frame->linesize[0];
00109         }
00110     }
00111 }
00112 
00113 /* generate block like in MS Video1 */
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 /* fill block with some gradient */
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) { //reverse order
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     s->frame.reference = 1;
00228     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00229     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00230         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00231         return -1;
00232     }
00233 
00234     while(!done) {
00235         int idx;
00236         if(blocks >= s->blocks || y >= s->height)
00237             break;//all blocks decoded
00238 
00239         idx = *buf++;
00240         if((idx & 0xF8) == 0x70) {
00241             switch(idx) {
00242             case 0x70: //change modifier
00243                 modifier = *buf++;
00244                 if(modifier>1)
00245                     av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
00246                 break;
00247             case 0x71: // set uniq flag
00248                 uniq = 1;
00249                 break;
00250             case 0x72: //toggle mode
00251                 mode = !mode;
00252                 break;
00253             case 0x73: //end-of-frame
00254                 done = 1;
00255                 break;
00256             case 0x74: //skip some blocks
00257                 skip = *buf++;
00258                 if ((blocks + skip) >= s->blocks)
00259                     break;
00260                 blocks += skip;
00261                 x += skip * 8;
00262                 while(x >= s->width) {
00263                     x -= s->width;
00264                     y += 8;
00265                 }
00266                 break;
00267             default:
00268                 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
00269             }
00270         } else { //handle one block
00271             int code;
00272             int cf;
00273             int angle = 0;
00274             uint8_t Y[4]; // luma samples of block
00275             int tx = 0, ty = 0; //coords of subblock
00276             int chroma = 0;
00277             if (mode || uniq) {
00278                 uniq = 0;
00279                 cf = 1;
00280                 chroma = 0;
00281             } else {
00282                 cf = 0;
00283                 if (idx)
00284                     chroma = *buf++;
00285             }
00286             for (i = 0; i < 4; i++) { // for every subblock
00287                 code = (idx >> (6 - i*2)) & 3; //extract 2 bits
00288                 if(!code) //skip subblock
00289                     continue;
00290                 if(cf)
00291                     chroma = *buf++;
00292                 tx = x + block_coords[i * 2];
00293                 ty = y + block_coords[(i * 2) + 1];
00294                 switch(code) {
00295                 case 1:
00296                     tmp = *buf++;
00297 
00298                     angle = angle_by_index[(tmp >> 6) & 0x3];
00299 
00300                     Y[0] = tmp & 0x3F;
00301                     Y[1] = Y[0];
00302 
00303                     if (angle) {
00304                         Y[2] = Y[0]+1;
00305                         if (Y[2] > 0x3F)
00306                             Y[2] = 0x3F;
00307                         Y[3] = Y[2];
00308                     } else {
00309                         Y[2] = Y[0];
00310                         Y[3] = Y[0];
00311                     }
00312                     break;
00313 
00314                 case 2:
00315                     if (modifier) { // unpack four luma samples
00316                         tmp = bytestream_get_be24(&buf);
00317 
00318                         Y[0] = (tmp >> 18) & 0x3F;
00319                         Y[1] = (tmp >> 12) & 0x3F;
00320                         Y[2] = (tmp >> 6) & 0x3F;
00321                         Y[3] = tmp & 0x3F;
00322                         angle = 16;
00323                     } else { // retrieve luma samples from codebook
00324                         tmp = bytestream_get_be16(&buf);
00325 
00326                         angle = (tmp >> 12) & 0xF;
00327                         tmp &= 0xFFF;
00328                         tmp <<= 2;
00329                         Y[0] = s->ulti_codebook[tmp];
00330                         Y[1] = s->ulti_codebook[tmp + 1];
00331                         Y[2] = s->ulti_codebook[tmp + 2];
00332                         Y[3] = s->ulti_codebook[tmp + 3];
00333                     }
00334                     break;
00335 
00336                 case 3:
00337                     if (modifier) { // all 16 luma samples
00338                         uint8_t Luma[16];
00339 
00340                         tmp = bytestream_get_be24(&buf);
00341                         Luma[0] = (tmp >> 18) & 0x3F;
00342                         Luma[1] = (tmp >> 12) & 0x3F;
00343                         Luma[2] = (tmp >> 6) & 0x3F;
00344                         Luma[3] = tmp & 0x3F;
00345 
00346                         tmp = bytestream_get_be24(&buf);
00347                         Luma[4] = (tmp >> 18) & 0x3F;
00348                         Luma[5] = (tmp >> 12) & 0x3F;
00349                         Luma[6] = (tmp >> 6) & 0x3F;
00350                         Luma[7] = tmp & 0x3F;
00351 
00352                         tmp = bytestream_get_be24(&buf);
00353                         Luma[8] = (tmp >> 18) & 0x3F;
00354                         Luma[9] = (tmp >> 12) & 0x3F;
00355                         Luma[10] = (tmp >> 6) & 0x3F;
00356                         Luma[11] = tmp & 0x3F;
00357 
00358                         tmp = bytestream_get_be24(&buf);
00359                         Luma[12] = (tmp >> 18) & 0x3F;
00360                         Luma[13] = (tmp >> 12) & 0x3F;
00361                         Luma[14] = (tmp >> 6) & 0x3F;
00362                         Luma[15] = tmp & 0x3F;
00363 
00364                         ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
00365                     } else {
00366                         tmp = *buf++;
00367                         if(tmp & 0x80) {
00368                             angle = (tmp >> 4) & 0x7;
00369                             tmp = (tmp << 8) + *buf++;
00370                             Y[0] = (tmp >> 6) & 0x3F;
00371                             Y[1] = tmp & 0x3F;
00372                             Y[2] = (*buf++) & 0x3F;
00373                             Y[3] = (*buf++) & 0x3F;
00374                             ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block
00375                         } else { // some patterns
00376                             int f0, f1;
00377                             f0 = *buf++;
00378                             f1 = tmp;
00379                             Y[0] = (*buf++) & 0x3F;
00380                             Y[1] = (*buf++) & 0x3F;
00381                             ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
00382                         }
00383                     }
00384                     break;
00385                 }
00386                 if(code != 3)
00387                     ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block
00388             }
00389             blocks++;
00390                 x += 8;
00391             if(x >= s->width) {
00392                 x = 0;
00393                 y += 8;
00394             }
00395         }
00396     }
00397 
00398     *data_size=sizeof(AVFrame);
00399     *(AVFrame*)data= s->frame;
00400 
00401     return buf_size;
00402 }
00403 
00404 AVCodec ff_ulti_decoder = {
00405     "ultimotion",
00406     AVMEDIA_TYPE_VIDEO,
00407     CODEC_ID_ULTI,
00408     sizeof(UltimotionDecodeContext),
00409     ulti_decode_init,
00410     NULL,
00411     ulti_decode_end,
00412     ulti_decode_frame,
00413     CODEC_CAP_DR1,
00414     NULL,
00415     .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
00416 };
00417