ulti.c
Go to the documentation of this file.
1 /*
2  * IBM Ultimotion Video Decoder
3  * Copyright (C) 2004 Konstantin Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * IBM Ultimotion Video Decoder.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "avcodec.h"
32 #include "bytestream.h"
33 #include "internal.h"
34 
35 #include "ulti_cb.h"
36 
37 typedef struct UltimotionDecodeContext {
44 
46 {
48 
49  s->avctx = avctx;
50  s->width = avctx->width;
51  s->height = avctx->height;
52  s->blocks = (s->width / 8) * (s->height / 8);
53  avctx->pix_fmt = AV_PIX_FMT_YUV410P;
54  avctx->coded_frame = &s->frame;
55  avctx->coded_frame = (AVFrame*) &s->frame;
58 
59  return 0;
60 }
61 
64  AVFrame *pic = &s->frame;
65 
66  av_frame_unref(pic);
67 
68  return 0;
69 }
70 
71 static const int block_coords[8] = // 4x4 block coords in 8x8 superblock
72  { 0, 0, 0, 4, 4, 4, 4, 0};
73 
74 static const int angle_by_index[4] = { 0, 2, 6, 12};
75 
76 /* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
77 static const uint8_t ulti_lumas[64] =
78  { 0x10, 0x13, 0x17, 0x1A, 0x1E, 0x21, 0x25, 0x28,
79  0x2C, 0x2F, 0x33, 0x36, 0x3A, 0x3D, 0x41, 0x44,
80  0x48, 0x4B, 0x4F, 0x52, 0x56, 0x59, 0x5C, 0x60,
81  0x63, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C,
82  0x7F, 0x83, 0x86, 0x8A, 0x8D, 0x91, 0x94, 0x98,
83  0x9B, 0x9F, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB3,
84  0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 0xCC, 0xCF,
85  0xD3, 0xD6, 0xDA, 0xDD, 0xE1, 0xE4, 0xE8, 0xEB};
86 
87 static const uint8_t ulti_chromas[16] =
88  { 0x60, 0x67, 0x6D, 0x73, 0x7A, 0x80, 0x86, 0x8D,
89  0x93, 0x99, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC0};
90 
91 /* convert Ultimotion YUV block (sixteen 6-bit Y samples and
92  two 4-bit chroma samples) into standard YUV and put it into frame */
93 static void ulti_convert_yuv(AVFrame *frame, int x, int y,
94  uint8_t *luma,int chroma)
95 {
96  uint8_t *y_plane, *cr_plane, *cb_plane;
97  int i;
98 
99  y_plane = frame->data[0] + x + y * frame->linesize[0];
100  cr_plane = frame->data[1] + (x / 4) + (y / 4) * frame->linesize[1];
101  cb_plane = frame->data[2] + (x / 4) + (y / 4) * frame->linesize[2];
102 
103  cr_plane[0] = ulti_chromas[chroma >> 4];
104 
105  cb_plane[0] = ulti_chromas[chroma & 0xF];
106 
107 
108  for(i = 0; i < 16; i++){
109  y_plane[i & 3] = ulti_lumas[luma[i]];
110  if((i & 3) == 3) { //next row
111  y_plane += frame->linesize[0];
112  }
113  }
114 }
115 
116 /* generate block like in MS Video1 */
117 static void ulti_pattern(AVFrame *frame, int x, int y,
118  int f0, int f1, int Y0, int Y1, int chroma)
119 {
120  uint8_t Luma[16];
121  int mask, i;
122  for(mask = 0x80, i = 0; mask; mask >>= 1, i++) {
123  if(f0 & mask)
124  Luma[i] = Y1;
125  else
126  Luma[i] = Y0;
127  }
128 
129  for(mask = 0x80, i = 8; mask; mask >>= 1, i++) {
130  if(f1 & mask)
131  Luma[i] = Y1;
132  else
133  Luma[i] = Y0;
134  }
135 
136  ulti_convert_yuv(frame, x, y, Luma, chroma);
137 }
138 
139 /* fill block with some gradient */
140 static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle)
141 {
142  uint8_t Luma[16];
143  if(angle & 8) { //reverse order
144  int t;
145  angle &= 0x7;
146  t = Y[0];
147  Y[0] = Y[3];
148  Y[3] = t;
149  t = Y[1];
150  Y[1] = Y[2];
151  Y[2] = t;
152  }
153  switch(angle){
154  case 0:
155  Luma[0] = Y[0]; Luma[1] = Y[1]; Luma[2] = Y[2]; Luma[3] = Y[3];
156  Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3];
157  Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
158  Luma[12] = Y[0]; Luma[13] = Y[1]; Luma[14] = Y[2]; Luma[15] = Y[3];
159  break;
160  case 1:
161  Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3];
162  Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3];
163  Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
164  Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
165  break;
166  case 2:
167  Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3];
168  Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3];
169  Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
170  Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
171  break;
172  case 3:
173  Luma[0] = Y[2]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3];
174  Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3];
175  Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
176  Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[1];
177  break;
178  case 4:
179  Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3];
180  Luma[4] = Y[2]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[2];
181  Luma[8] = Y[1]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[1];
182  Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
183  break;
184  case 5:
185  Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[2];
186  Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[1];
187  Luma[8] = Y[2]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[0];
188  Luma[12] = Y[1]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
189  break;
190  case 6:
191  Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[2];
192  Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[1];
193  Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
194  Luma[12] = Y[1]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
195  break;
196  case 7:
197  Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[1];
198  Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[0];
199  Luma[8] = Y[3]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
200  Luma[12] = Y[2]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
201  break;
202  default:
203  Luma[0] = Y[0]; Luma[1] = Y[0]; Luma[2] = Y[1]; Luma[3] = Y[1];
204  Luma[4] = Y[0]; Luma[5] = Y[0]; Luma[6] = Y[1]; Luma[7] = Y[1];
205  Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[3]; Luma[11] = Y[3];
206  Luma[12] = Y[2]; Luma[13] = Y[2]; Luma[14] = Y[3]; Luma[15] = Y[3];
207  break;
208  }
209 
210  ulti_convert_yuv(frame, x, y, Luma, chroma);
211 }
212 
214  void *data, int *got_frame,
215  AVPacket *avpkt)
216 {
217  const uint8_t *buf = avpkt->data;
218  int buf_size = avpkt->size;
220  int modifier = 0;
221  int uniq = 0;
222  int mode = 0;
223  int blocks = 0;
224  int done = 0;
225  int x = 0, y = 0;
226  int i, ret;
227  int skip;
228  int tmp;
229 
230  if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0)
231  return ret;
232 
233  bytestream2_init(&s->gb, buf, buf_size);
234 
235  while(!done) {
236  int idx;
237  if(blocks >= s->blocks || y >= s->height)
238  break;//all blocks decoded
239 
240  if (bytestream2_get_bytes_left(&s->gb) < 1)
241  goto err;
242  idx = bytestream2_get_byteu(&s->gb);
243  if((idx & 0xF8) == 0x70) {
244  switch(idx) {
245  case 0x70: //change modifier
246  modifier = bytestream2_get_byte(&s->gb);
247  if(modifier>1)
248  av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
249  break;
250  case 0x71: // set uniq flag
251  uniq = 1;
252  break;
253  case 0x72: //toggle mode
254  mode = !mode;
255  break;
256  case 0x73: //end-of-frame
257  done = 1;
258  break;
259  case 0x74: //skip some blocks
260  skip = bytestream2_get_byte(&s->gb);
261  if ((blocks + skip) >= s->blocks)
262  break;
263  blocks += skip;
264  x += skip * 8;
265  while(x >= s->width) {
266  x -= s->width;
267  y += 8;
268  }
269  break;
270  default:
271  av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
272  }
273  } else { //handle one block
274  int code;
275  int cf;
276  int angle = 0;
277  uint8_t Y[4]; // luma samples of block
278  int tx = 0, ty = 0; //coords of subblock
279  int chroma = 0;
280  if (mode || uniq) {
281  uniq = 0;
282  cf = 1;
283  chroma = 0;
284  } else {
285  cf = 0;
286  if (idx) {
287  chroma = bytestream2_get_byte(&s->gb);
288  }
289  }
290  for (i = 0; i < 4; i++) { // for every subblock
291  code = (idx >> (6 - i*2)) & 3; //extract 2 bits
292  if(!code) //skip subblock
293  continue;
294  if(cf) {
295  chroma = bytestream2_get_byte(&s->gb);
296  }
297  tx = x + block_coords[i * 2];
298  ty = y + block_coords[(i * 2) + 1];
299  switch(code) {
300  case 1:
301  tmp = bytestream2_get_byte(&s->gb);
302 
303  angle = angle_by_index[(tmp >> 6) & 0x3];
304 
305  Y[0] = tmp & 0x3F;
306  Y[1] = Y[0];
307 
308  if (angle) {
309  Y[2] = Y[0]+1;
310  if (Y[2] > 0x3F)
311  Y[2] = 0x3F;
312  Y[3] = Y[2];
313  } else {
314  Y[2] = Y[0];
315  Y[3] = Y[0];
316  }
317  break;
318 
319  case 2:
320  if (modifier) { // unpack four luma samples
321  tmp = bytestream2_get_be24(&s->gb);
322 
323  Y[0] = (tmp >> 18) & 0x3F;
324  Y[1] = (tmp >> 12) & 0x3F;
325  Y[2] = (tmp >> 6) & 0x3F;
326  Y[3] = tmp & 0x3F;
327  angle = 16;
328  } else { // retrieve luma samples from codebook
329  tmp = bytestream2_get_be16(&s->gb);
330 
331  angle = (tmp >> 12) & 0xF;
332  tmp &= 0xFFF;
333  tmp <<= 2;
334  Y[0] = s->ulti_codebook[tmp];
335  Y[1] = s->ulti_codebook[tmp + 1];
336  Y[2] = s->ulti_codebook[tmp + 2];
337  Y[3] = s->ulti_codebook[tmp + 3];
338  }
339  break;
340 
341  case 3:
342  if (modifier) { // all 16 luma samples
343  uint8_t Luma[16];
344 
345  if (bytestream2_get_bytes_left(&s->gb) < 12)
346  goto err;
347  tmp = bytestream2_get_be24u(&s->gb);
348  Luma[0] = (tmp >> 18) & 0x3F;
349  Luma[1] = (tmp >> 12) & 0x3F;
350  Luma[2] = (tmp >> 6) & 0x3F;
351  Luma[3] = tmp & 0x3F;
352 
353  tmp = bytestream2_get_be24u(&s->gb);
354  Luma[4] = (tmp >> 18) & 0x3F;
355  Luma[5] = (tmp >> 12) & 0x3F;
356  Luma[6] = (tmp >> 6) & 0x3F;
357  Luma[7] = tmp & 0x3F;
358 
359  tmp = bytestream2_get_be24u(&s->gb);
360  Luma[8] = (tmp >> 18) & 0x3F;
361  Luma[9] = (tmp >> 12) & 0x3F;
362  Luma[10] = (tmp >> 6) & 0x3F;
363  Luma[11] = tmp & 0x3F;
364 
365  tmp = bytestream2_get_be24u(&s->gb);
366  Luma[12] = (tmp >> 18) & 0x3F;
367  Luma[13] = (tmp >> 12) & 0x3F;
368  Luma[14] = (tmp >> 6) & 0x3F;
369  Luma[15] = tmp & 0x3F;
370 
371  ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma);
372  } else {
373  if (bytestream2_get_bytes_left(&s->gb) < 4)
374  goto err;
375  tmp = bytestream2_get_byteu(&s->gb);
376  if(tmp & 0x80) {
377  angle = (tmp >> 4) & 0x7;
378  tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb);
379  Y[0] = (tmp >> 6) & 0x3F;
380  Y[1] = tmp & 0x3F;
381  Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F;
382  Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F;
383  ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block
384  } else { // some patterns
385  int f0, f1;
386  f0 = bytestream2_get_byteu(&s->gb);
387  f1 = tmp;
388  Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F;
389  Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F;
390  ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma);
391  }
392  }
393  break;
394  }
395  if(code != 3)
396  ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block
397  }
398  blocks++;
399  x += 8;
400  if(x >= s->width) {
401  x = 0;
402  y += 8;
403  }
404  }
405  }
406 
407  *got_frame = 1;
408  if ((ret = av_frame_ref(data, &s->frame)) < 0)
409  return ret;
410 
411  return buf_size;
412 
413 err:
414  av_log(avctx, AV_LOG_ERROR,
415  "Insufficient data\n");
416  return AVERROR_INVALIDDATA;
417 }
418 
420  .name = "ultimotion",
421  .type = AVMEDIA_TYPE_VIDEO,
422  .id = AV_CODEC_ID_ULTI,
423  .priv_data_size = sizeof(UltimotionDecodeContext),
427  .capabilities = CODEC_CAP_DR1,
428  .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
429 };
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
static av_cold int ulti_decode_end(AVCodecContext *avctx)
Definition: ulti.c:62
AVFrame * coded_frame
the picture in the bitstream
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
the sinusoids Y1
Definition: lab5.m:33
AVCodec ff_ulti_decoder
Definition: ulti.c:419
uint8_t
#define av_cold
Definition: attributes.h:78
mode
Definition: f_perms.c:27
#define Y
Definition: vf_boxblur.c:76
GetByteContext gb
Definition: ulti.c:42
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
function f0
Discrete Time axis x
static const uint16_t mask[17]
Definition: lzw.c:37
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
external API header
AVCodecContext * avctx
Definition: ulti.c:38
static const int angle_by_index[4]
Definition: ulti.c:74
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
Identical in function to av_frame_make_writable(), except it uses ff_get_buffer() to allocate the buf...
ret
Definition: avfilter.c:821
int width
picture width / height.
t
Definition: genspecsines3.m:6
struct UltimotionDecodeContext UltimotionDecodeContext
or the Software in violation of any applicable export control laws in any jurisdiction Except as provided by mandatorily applicable UPF has no obligation to provide you with source code to the Software In the event Software contains any source code
static int ulti_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: ulti.c:213
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
static av_cold int ulti_decode_init(AVCodecContext *avctx)
Definition: ulti.c:45
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:74
void avcodec_get_frame_defaults(AVFrame *frame)
Set the fields of the given AVFrame to default values.
const uint8_t * ulti_codebook
Definition: ulti.c:41
synthesis window for stochastic i
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:330
static void ulti_convert_yuv(AVFrame *frame, int x, int y, uint8_t *luma, int chroma)
Definition: ulti.c:93
int av_frame_ref(AVFrame *dst, AVFrame *src)
Setup a new reference to the data described by an given frame.
Definition: frame.c:228
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
common internal api header.
function y
Definition: D.m:1
static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle)
Definition: ulti.c:140
#define AV_LOG_INFO
Definition: log.h:156
static void ulti_pattern(AVFrame *frame, int x, int y, int f0, int f1, int Y0, int Y1, int chroma)
Definition: ulti.c:117
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
static const uint8_t ulti_chromas[16]
Definition: ulti.c:87
static const int block_coords[8]
Definition: ulti.c:71
This structure stores compressed data.
f1
Definition: genspecsines3.m:3
static const uint8_t ulti_lumas[64]
Definition: ulti.c:77