• 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 #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] = // 4x4 block coords in 8x8 superblock
00060     { 0, 0, 0, 4, 4, 4, 4, 0};
00061 
00062 static const int angle_by_index[4] = { 0, 2, 6, 12};
00063 
00064 /* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
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 /* convert Ultimotion YUV block (sixteen 6-bit Y samples and
00080  two 4-bit chroma samples) into standard YUV and put it into frame */
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) { //next row
00099             y_plane += frame->linesize[0];
00100         }
00101     }
00102 }
00103 
00104 /* generate block like in MS Video1 */
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 /* fill block with some gradient */
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) { //reverse order
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;//all blocks decoded
00230 
00231         idx = *buf++;
00232         if((idx & 0xF8) == 0x70) {
00233             switch(idx) {
00234             case 0x70: //change modifier
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: // set uniq flag
00240                 uniq = 1;
00241                 break;
00242             case 0x72: //toggle mode
00243                 mode = !mode;
00244                 break;
00245             case 0x73: //end-of-frame
00246                 done = 1;
00247                 break;
00248             case 0x74: //skip some blocks
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 { //handle one block
00263             int code;
00264             int cf;
00265             int angle = 0;
00266             uint8_t Y[4]; // luma samples of block
00267             int tx = 0, ty = 0; //coords of subblock
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++) { // for every subblock
00279                 code = (idx >> (6 - i*2)) & 3; //extract 2 bits
00280                 if(!code) //skip subblock
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) { // unpack four luma samples
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 { // retrieve luma samples from codebook
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) { // all 16 luma samples
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); //draw block
00367                         } else { // some patterns
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); // draw block
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 /*    UltimotionDecodeContext *s = avctx->priv_data;*/
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 

Generated on Tue Nov 4 2014 12:59:23 for ffmpeg by  doxygen 1.7.1