• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • 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     avcodec_get_frame_defaults(&s->frame);
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] = // 4x4 block coords in 8x8 superblock
00070     { 0, 0, 0, 4, 4, 4, 4, 0};
00071 
00072 static const int angle_by_index[4] = { 0, 2, 6, 12};
00073 
00074 /* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
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 /* convert Ultimotion YUV block (sixteen 6-bit Y samples and
00090  two 4-bit chroma samples) into standard YUV and put it into frame */
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) { //next row
00109             y_plane += frame->linesize[0];
00110         }
00111     }
00112 }
00113 
00114 /* generate block like in MS Video1 */
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 /* fill block with some gradient */
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) { //reverse order
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     while(!done) {
00236         int idx;
00237         if(blocks >= s->blocks || y >= s->height)
00238             break;//all blocks decoded
00239 
00240         idx = *buf++;
00241         if((idx & 0xF8) == 0x70) {
00242             switch(idx) {
00243             case 0x70: //change modifier
00244                 modifier = *buf++;
00245                 if(modifier>1)
00246                     av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
00247                 break;
00248             case 0x71: // set uniq flag
00249                 uniq = 1;
00250                 break;
00251             case 0x72: //toggle mode
00252                 mode = !mode;
00253                 break;
00254             case 0x73: //end-of-frame
00255                 done = 1;
00256                 break;
00257             case 0x74: //skip some blocks
00258                 skip = *buf++;
00259                 if ((blocks + skip) >= s->blocks)
00260                     break;
00261                 blocks += skip;
00262                 x += skip * 8;
00263                 while(x >= s->width) {
00264                     x -= s->width;
00265                     y += 8;
00266                 }
00267                 break;
00268             default:
00269                 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
00270             }
00271         } else { //handle one block
00272             int code;
00273             int cf;
00274             int angle = 0;
00275             uint8_t Y[4]; // luma samples of block
00276             int tx = 0, ty = 0; //coords of subblock
00277             int chroma = 0;
00278             if (mode || uniq) {
00279                 uniq = 0;
00280                 cf = 1;
00281                 chroma = 0;
00282             } else {
00283                 cf = 0;
00284                 if (idx)
00285                     chroma = *buf++;
00286             }
00287             for (i = 0; i < 4; i++) { // for every subblock
00288                 code = (idx >> (6 - i*2)) & 3; //extract 2 bits
00289                 if(!code) //skip subblock
00290                     continue;
00291                 if(cf)
00292                     chroma = *buf++;
00293                 tx = x + block_coords[i * 2];
00294                 ty = y + block_coords[(i * 2) + 1];
00295                 switch(code) {
00296                 case 1:
00297                     tmp = *buf++;
00298 
00299                     angle = angle_by_index[(tmp >> 6) & 0x3];
00300 
00301                     Y[0] = tmp & 0x3F;
00302                     Y[1] = Y[0];
00303 
00304                     if (angle) {
00305                         Y[2] = Y[0]+1;
00306                         if (Y[2] > 0x3F)
00307                             Y[2] = 0x3F;
00308                         Y[3] = Y[2];
00309                     } else {
00310                         Y[2] = Y[0];
00311                         Y[3] = Y[0];
00312                     }
00313                     break;
00314 
00315                 case 2:
00316                     if (modifier) { // unpack four luma samples
00317                         tmp = bytestream_get_be24(&buf);
00318 
00319                         Y[0] = (tmp >> 18) & 0x3F;
00320                         Y[1] = (tmp >> 12) & 0x3F;
00321                         Y[2] = (tmp >> 6) & 0x3F;
00322                         Y[3] = tmp & 0x3F;
00323                         angle = 16;
00324                     } else { // retrieve luma samples from codebook
00325                         tmp = bytestream_get_be16(&buf);
00326 
00327                         angle = (tmp >> 12) & 0xF;
00328                         tmp &= 0xFFF;
00329                         tmp <<= 2;
00330                         Y[0] = s->ulti_codebook[tmp];
00331                         Y[1] = s->ulti_codebook[tmp + 1];
00332                         Y[2] = s->ulti_codebook[tmp + 2];
00333                         Y[3] = s->ulti_codebook[tmp + 3];
00334                     }
00335                     break;
00336 
00337                 case 3:
00338                     if (modifier) { // all 16 luma samples
00339                         uint8_t Luma[16];
00340 
00341                         tmp = bytestream_get_be24(&buf);
00342                         Luma[0] = (tmp >> 18) & 0x3F;
00343                         Luma[1] = (tmp >> 12) & 0x3F;
00344                         Luma[2] = (tmp >> 6) & 0x3F;
00345                         Luma[3] = tmp & 0x3F;
00346 
00347                         tmp = bytestream_get_be24(&buf);
00348                         Luma[4] = (tmp >> 18) & 0x3F;
00349                         Luma[5] = (tmp >> 12) & 0x3F;
00350                         Luma[6] = (tmp >> 6) & 0x3F;
00351                         Luma[7] = tmp & 0x3F;
00352 
00353                         tmp = bytestream_get_be24(&buf);
00354                         Luma[8] = (tmp >> 18) & 0x3F;
00355                         Luma[9] = (tmp >> 12) & 0x3F;
00356                         Luma[10] = (tmp >> 6) & 0x3F;
00357                         Luma[11] = tmp & 0x3F;
00358 
00359                         tmp = bytestream_get_be24(&buf);
00360                         Luma[12] = (tmp >> 18) & 0x3F;
00361                         Luma[13] = (tmp >> 12) & 0x3F;
00362                         Luma[14] = (tmp >> 6) & 0x3F;
00363                         Luma[15] = tmp & 0x3F;
00364 
00365                         ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
00366                     } else {
00367                         tmp = *buf++;
00368                         if(tmp & 0x80) {
00369                             angle = (tmp >> 4) & 0x7;
00370                             tmp = (tmp << 8) + *buf++;
00371                             Y[0] = (tmp >> 6) & 0x3F;
00372                             Y[1] = tmp & 0x3F;
00373                             Y[2] = (*buf++) & 0x3F;
00374                             Y[3] = (*buf++) & 0x3F;
00375                             ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block
00376                         } else { // some patterns
00377                             int f0, f1;
00378                             f0 = *buf++;
00379                             f1 = tmp;
00380                             Y[0] = (*buf++) & 0x3F;
00381                             Y[1] = (*buf++) & 0x3F;
00382                             ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
00383                         }
00384                     }
00385                     break;
00386                 }
00387                 if(code != 3)
00388                     ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block
00389             }
00390             blocks++;
00391                 x += 8;
00392             if(x >= s->width) {
00393                 x = 0;
00394                 y += 8;
00395             }
00396         }
00397     }
00398 
00399     *data_size=sizeof(AVFrame);
00400     *(AVFrame*)data= s->frame;
00401 
00402     return buf_size;
00403 }
00404 
00405 AVCodec ff_ulti_decoder = {
00406     "ultimotion",
00407     AVMEDIA_TYPE_VIDEO,
00408     CODEC_ID_ULTI,
00409     sizeof(UltimotionDecodeContext),
00410     ulti_decode_init,
00411     NULL,
00412     ulti_decode_end,
00413     ulti_decode_frame,
00414     CODEC_CAP_DR1,
00415     NULL,
00416     .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
00417 };
00418 

Generated on Fri Feb 22 2013 07:24:29 for FFmpeg by  doxygen 1.7.1