• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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     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;//all blocks decoded
00241 
00242         idx = *buf++;
00243         if((idx & 0xF8) == 0x70) {
00244             switch(idx) {
00245             case 0x70: //change modifier
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: // set uniq flag
00251                 uniq = 1;
00252                 break;
00253             case 0x72: //toggle mode
00254                 mode = !mode;
00255                 break;
00256             case 0x73: //end-of-frame
00257                 done = 1;
00258                 break;
00259             case 0x74: //skip some blocks
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 { //handle one block
00274             int code;
00275             int cf;
00276             int angle = 0;
00277             uint8_t Y[4]; // luma samples of block
00278             int tx = 0, ty = 0; //coords of subblock
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++) { // for every subblock
00290                 code = (idx >> (6 - i*2)) & 3; //extract 2 bits
00291                 if(!code) //skip subblock
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) { // unpack four luma samples
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 { // retrieve luma samples from codebook
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) { // all 16 luma samples
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); //draw block
00378                         } else { // some patterns
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); // draw block
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 

Generated on Fri Sep 16 2011 17:17:44 for FFmpeg by  doxygen 1.7.1