sanm.c
Go to the documentation of this file.
1 /*
2  * LucasArts Smush video decoder
3  * Copyright (c) 2006 Cyril Zorin
4  * Copyright (c) 2011 Konstantin Shishkov
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 // #define DEBUG 1
24 
25 #include "avcodec.h"
26 #include "copy_block.h"
27 #include "bytestream.h"
28 #include "internal.h"
29 #include "libavutil/bswap.h"
30 #include "libavutil/imgutils.h"
31 #include "sanm_data.h"
32 #include "libavutil/avassert.h"
33 
34 #define NGLYPHS 256
35 
36 typedef struct {
39 
40  int version, subversion;
41  uint32_t pal[256];
42  int16_t delta_pal[768];
43 
44  int pitch;
45  int width, height;
46  int aligned_width, aligned_height;
47  int prev_seq;
48 
50  uint16_t *frm0, *frm1, *frm2;
52  uint32_t frm0_size, frm1_size, frm2_size;
54 
56  unsigned int rle_buf_size;
57 
59 
60  long npixels, buf_size;
61 
62  uint16_t codebook[256];
63  uint16_t small_codebook[4];
64 
65  int8_t p4x4glyphs[NGLYPHS][16];
66  int8_t p8x8glyphs[NGLYPHS][64];
68 
69 typedef struct {
70  int seq_num, codec, rotate_code, rle_output_size;
71 
72  uint16_t bg_color;
73  uint32_t width, height;
75 
76 enum GlyphEdge {
82 };
83 
84 enum GlyphDir {
90 };
91 
92 /**
93  * Return enum GlyphEdge of box where point (x, y) lies.
94  *
95  * @param x x point coordinate
96  * @param y y point coordinate
97  * @param edge_size box width/height.
98  */
99 static enum GlyphEdge which_edge(int x, int y, int edge_size)
100 {
101  const int edge_max = edge_size - 1;
102 
103  if (!y) {
104  return BOTTOM_EDGE;
105  } else if (y == edge_max) {
106  return TOP_EDGE;
107  } else if (!x) {
108  return LEFT_EDGE;
109  } else if (x == edge_max) {
110  return RIGHT_EDGE;
111  } else {
112  return NO_EDGE;
113  }
114 }
115 
116 static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
117 {
118  if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
119  (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
120  (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
121  (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE)) {
122  return DIR_UP;
123  } else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
124  (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE)) {
125  return DIR_DOWN;
126  } else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
127  (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE)) {
128  return DIR_LEFT;
129  } else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
130  (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
131  (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
132  (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE)) {
133  return DIR_RIGHT;
134  }
135 
136  return NO_DIR;
137 }
138 
139 /**
140  * Interpolate two points.
141  */
142 static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
143  int pos, int npoints)
144 {
145  if (npoints) {
146  points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
147  points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
148  } else {
149  points[0] = x0;
150  points[1] = y0;
151  }
152 }
153 
154 /**
155  * Construct glyphs by iterating through vectors coordinates.
156  *
157  * @param pglyphs pointer to table where glyphs are stored
158  * @param xvec pointer to x component of vectors coordinates
159  * @param yvec pointer to y component of vectors coordinates
160  * @param side_length glyph width/height.
161  */
162 static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
163  const int side_length)
164 {
165  const int glyph_size = side_length * side_length;
166  int8_t *pglyph = pglyphs;
167 
168  int i, j;
169  for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
170  int x0 = xvec[i];
171  int y0 = yvec[i];
172  enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
173 
174  for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
175  int x1 = xvec[j];
176  int y1 = yvec[j];
177  enum GlyphEdge edge1 = which_edge(x1, y1, side_length);
178  enum GlyphDir dir = which_direction(edge0, edge1);
179  int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
180  int ipoint;
181 
182  for (ipoint = 0; ipoint <= npoints; ipoint++) {
183  int8_t point[2];
184  int irow, icol;
185 
186  interp_point(point, x0, y0, x1, y1, ipoint, npoints);
187 
188  switch (dir) {
189  case DIR_UP:
190  for (irow = point[1]; irow >= 0; irow--)
191  pglyph[point[0] + irow * side_length] = 1;
192  break;
193 
194  case DIR_DOWN:
195  for (irow = point[1]; irow < side_length; irow++)
196  pglyph[point[0] + irow * side_length] = 1;
197  break;
198 
199  case DIR_LEFT:
200  for (icol = point[0]; icol >= 0; icol--)
201  pglyph[icol + point[1] * side_length] = 1;
202  break;
203 
204  case DIR_RIGHT:
205  for (icol = point[0]; icol < side_length; icol++)
206  pglyph[icol + point[1] * side_length] = 1;
207  break;
208  }
209  }
210  }
211  }
212 }
213 
214 static void init_sizes(SANMVideoContext *ctx, int width, int height)
215 {
216  ctx->width = width;
217  ctx->height = height;
218  ctx->npixels = width * height;
219 
220  ctx->aligned_width = FFALIGN(width, 8);
221  ctx->aligned_height = FFALIGN(height, 8);
222 
223  ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
224  ctx->pitch = width;
225 }
226 
228 {
229  av_freep(&ctx->frm0);
230  av_freep(&ctx->frm1);
231  av_freep(&ctx->frm2);
232  av_freep(&ctx->stored_frame);
233  av_freep(&ctx->rle_buf);
234  ctx->frm0_size =
235  ctx->frm1_size =
236  ctx->frm2_size = 0;
237 }
238 
240 {
241  av_fast_padded_malloc(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
242  av_fast_padded_malloc(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
243  av_fast_padded_malloc(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
244  if (!ctx->version)
246 
247  if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || (!ctx->stored_frame && !ctx->version)) {
248  destroy_buffers(ctx);
249  return AVERROR(ENOMEM);
250  }
251 
252  return 0;
253 }
254 
255 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
256 {
257  av_dlog(ctx->avctx, "rotate %d\n", rotate_code);
258  if (rotate_code == 2)
259  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
260  FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
261 }
262 
264 {
265  SANMVideoContext *ctx = avctx->priv_data;
266 
267  ctx->avctx = avctx;
268  ctx->version = !avctx->extradata_size;
269 
271 
272  init_sizes(ctx, avctx->width, avctx->height);
273  if (init_buffers(ctx)) {
274  av_log(avctx, AV_LOG_ERROR, "error allocating buffers\n");
275  return AVERROR(ENOMEM);
276  }
277 
278  make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
279  make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
280 
281  if (!ctx->version) {
282  int i;
283 
284  if (avctx->extradata_size < 1026) {
285  av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
286  return AVERROR_INVALIDDATA;
287  }
288 
289  ctx->subversion = AV_RL16(avctx->extradata);
290  for (i = 0; i < 256; i++)
291  ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
292  }
293 
294  return 0;
295 }
296 
298 {
299  SANMVideoContext *ctx = avctx->priv_data;
300 
301  destroy_buffers(ctx);
302 
303  return 0;
304 }
305 
306 static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
307 {
308  int opcode, color, run_len, left = out_size;
309 
310  while (left > 0) {
311  opcode = bytestream2_get_byte(&ctx->gb);
312  run_len = (opcode >> 1) + 1;
313  if (run_len > left || bytestream2_get_bytes_left(&ctx->gb) <= 0)
314  return AVERROR_INVALIDDATA;
315 
316  if (opcode & 1) {
317  color = bytestream2_get_byte(&ctx->gb);
318  memset(dst, color, run_len);
319  } else {
320  if (bytestream2_get_bytes_left(&ctx->gb) < run_len)
321  return AVERROR_INVALIDDATA;
322  bytestream2_get_bufferu(&ctx->gb, dst, run_len);
323  }
324 
325  dst += run_len;
326  left -= run_len;
327  }
328 
329  return 0;
330 }
331 
332 static int old_codec1(SANMVideoContext *ctx, int top,
333  int left, int width, int height)
334 {
335  uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * ctx->pitch;
336  int i, j, len, flag, code, val, pos, end;
337 
338  for (i = 0; i < height; i++) {
339  pos = 0;
340 
341  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
342  return AVERROR_INVALIDDATA;
343 
344  len = bytestream2_get_le16u(&ctx->gb);
345  end = bytestream2_tell(&ctx->gb) + len;
346 
347  while (bytestream2_tell(&ctx->gb) < end) {
348  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
349  return AVERROR_INVALIDDATA;
350 
351  code = bytestream2_get_byteu(&ctx->gb);
352  flag = code & 1;
353  code = (code >> 1) + 1;
354  if (pos + code > width)
355  return AVERROR_INVALIDDATA;
356  if (flag) {
357  val = bytestream2_get_byteu(&ctx->gb);
358  if (val)
359  memset(dst + pos, val, code);
360  pos += code;
361  } else {
362  if (bytestream2_get_bytes_left(&ctx->gb) < code)
363  return AVERROR_INVALIDDATA;
364  for (j = 0; j < code; j++) {
365  val = bytestream2_get_byteu(&ctx->gb);
366  if (val)
367  dst[pos] = val;
368  pos++;
369  }
370  }
371  }
372  dst += ctx->pitch;
373  }
374  ctx->rotate_code = 0;
375 
376  return 0;
377 }
378 
379 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
380  int height, int stride, int x, int y)
381 {
382  int pos, i, j;
383 
384  pos = x + y * stride;
385  for (j = 0; j < 4; j++) {
386  for (i = 0; i < 4; i++) {
387  if ((pos + i) < 0 || (pos + i) >= height * stride)
388  dst[i] = 0;
389  else
390  dst[i] = src[i];
391  }
392  dst += stride;
393  src += stride;
394  pos += stride;
395  }
396 }
397 
398 static int old_codec37(SANMVideoContext *ctx, int top,
399  int left, int width, int height)
400 {
401  int stride = ctx->pitch;
402  int i, j, k, t;
403  int skip_run = 0;
404  int compr, mvoff, seq, flags;
405  uint32_t decoded_size;
406  uint8_t *dst, *prev;
407 
408  compr = bytestream2_get_byte(&ctx->gb);
409  mvoff = bytestream2_get_byte(&ctx->gb);
410  seq = bytestream2_get_le16(&ctx->gb);
411  decoded_size = bytestream2_get_le32(&ctx->gb);
412  bytestream2_skip(&ctx->gb, 4);
413  flags = bytestream2_get_byte(&ctx->gb);
414  bytestream2_skip(&ctx->gb, 3);
415 
416  if (decoded_size > ctx->height * stride - left - top * stride) {
417  decoded_size = ctx->height * stride - left - top * stride;
418  av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n");
419  }
420 
421  ctx->rotate_code = 0;
422 
423  if (((seq & 1) || !(flags & 1)) && (compr && compr != 2))
424  rotate_bufs(ctx, 1);
425 
426  dst = ((uint8_t*)ctx->frm0) + left + top * stride;
427  prev = ((uint8_t*)ctx->frm2) + left + top * stride;
428 
429  if (mvoff > 2) {
430  av_log(ctx->avctx, AV_LOG_ERROR, "invalid motion base value %d\n", mvoff);
431  return AVERROR_INVALIDDATA;
432  }
433  av_dlog(ctx->avctx, "compression %d\n", compr);
434  switch (compr) {
435  case 0:
436  for (i = 0; i < height; i++) {
437  bytestream2_get_buffer(&ctx->gb, dst, width);
438  dst += stride;
439  }
440  memset(ctx->frm1, 0, ctx->height * stride);
441  memset(ctx->frm2, 0, ctx->height * stride);
442  break;
443  case 2:
444  if (rle_decode(ctx, dst, decoded_size))
445  return AVERROR_INVALIDDATA;
446  memset(ctx->frm1, 0, ctx->frm1_size);
447  memset(ctx->frm2, 0, ctx->frm2_size);
448  break;
449  case 3:
450  case 4:
451  if (flags & 4) {
452  for (j = 0; j < height; j += 4) {
453  for (i = 0; i < width; i += 4) {
454  int code;
455  if (skip_run) {
456  skip_run--;
457  copy_block4(dst + i, prev + i, stride, stride, 4);
458  continue;
459  }
460  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
461  return AVERROR_INVALIDDATA;
462  code = bytestream2_get_byteu(&ctx->gb);
463  switch (code) {
464  case 0xFF:
465  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
466  return AVERROR_INVALIDDATA;
467  for (k = 0; k < 4; k++)
468  bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
469  break;
470  case 0xFE:
471  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
472  return AVERROR_INVALIDDATA;
473  for (k = 0; k < 4; k++)
474  memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
475  break;
476  case 0xFD:
477  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
478  return AVERROR_INVALIDDATA;
479  t = bytestream2_get_byteu(&ctx->gb);
480  for (k = 0; k < 4; k++)
481  memset(dst + i + k * stride, t, 4);
482  break;
483  default:
484  if (compr == 4 && !code) {
485  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
486  return AVERROR_INVALIDDATA;
487  skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
488  i -= 4;
489  } else {
490  int mx, my;
491 
492  mx = c37_mv[(mvoff * 255 + code) * 2 ];
493  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
494  codec37_mv(dst + i, prev + i + mx + my * stride,
495  ctx->height, stride, i + mx, j + my);
496  }
497  }
498  }
499  dst += stride * 4;
500  prev += stride * 4;
501  }
502  } else {
503  for (j = 0; j < height; j += 4) {
504  for (i = 0; i < width; i += 4) {
505  int code;
506  if (skip_run) {
507  skip_run--;
508  copy_block4(dst + i, prev + i, stride, stride, 4);
509  continue;
510  }
511  code = bytestream2_get_byte(&ctx->gb);
512  if (code == 0xFF) {
513  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
514  return AVERROR_INVALIDDATA;
515  for (k = 0; k < 4; k++)
516  bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
517  } else if (compr == 4 && !code) {
518  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
519  return AVERROR_INVALIDDATA;
520  skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
521  i -= 4;
522  } else {
523  int mx, my;
524 
525  mx = c37_mv[(mvoff * 255 + code) * 2];
526  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
527  codec37_mv(dst + i, prev + i + mx + my * stride,
528  ctx->height, stride, i + mx, j + my);
529  }
530  }
531  dst += stride * 4;
532  prev += stride * 4;
533  }
534  }
535  break;
536  default:
537  av_log(ctx->avctx, AV_LOG_ERROR,
538  "subcodec 37 compression %d not implemented\n", compr);
539  return AVERROR_PATCHWELCOME;
540  }
541 
542  return 0;
543 }
544 
546  uint8_t *prev2, int stride, int tbl, int size)
547 {
548  int code, k, t;
549  uint8_t colors[2];
550  int8_t *pglyph;
551 
552  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
553  return AVERROR_INVALIDDATA;
554 
555  code = bytestream2_get_byteu(&ctx->gb);
556  if (code >= 0xF8) {
557  switch (code) {
558  case 0xFF:
559  if (size == 2) {
560  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
561  return AVERROR_INVALIDDATA;
562  dst[0] = bytestream2_get_byteu(&ctx->gb);
563  dst[1] = bytestream2_get_byteu(&ctx->gb);
564  dst[0+stride] = bytestream2_get_byteu(&ctx->gb);
565  dst[1+stride] = bytestream2_get_byteu(&ctx->gb);
566  } else {
567  size >>= 1;
568  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
569  return AVERROR_INVALIDDATA;
570  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
571  stride, tbl, size))
572  return AVERROR_INVALIDDATA;
573  dst += size * stride;
574  prev1 += size * stride;
575  prev2 += size * stride;
576  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
577  return AVERROR_INVALIDDATA;
578  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
579  stride, tbl, size))
580  return AVERROR_INVALIDDATA;
581  }
582  break;
583  case 0xFE:
584  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
585  return AVERROR_INVALIDDATA;
586 
587  t = bytestream2_get_byteu(&ctx->gb);
588  for (k = 0; k < size; k++)
589  memset(dst + k * stride, t, size);
590  break;
591  case 0xFD:
592  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
593  return AVERROR_INVALIDDATA;
594 
595  code = bytestream2_get_byteu(&ctx->gb);
596  pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
597  bytestream2_get_bufferu(&ctx->gb, colors, 2);
598 
599  for (k = 0; k < size; k++)
600  for (t = 0; t < size; t++)
601  dst[t + k * stride] = colors[!*pglyph++];
602  break;
603  case 0xFC:
604  for (k = 0; k < size; k++)
605  memcpy(dst + k * stride, prev1 + k * stride, size);
606  break;
607  default:
608  k = bytestream2_tell(&ctx->gb);
609  bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
610  t = bytestream2_get_byte(&ctx->gb);
611  bytestream2_seek(&ctx->gb, k, SEEK_SET);
612  for (k = 0; k < size; k++)
613  memset(dst + k * stride, t, size);
614  }
615  } else {
616  int mx = motion_vectors[code][0];
617  int my = motion_vectors[code][1];
618  int index = prev2 - (const uint8_t*)ctx->frm2;
619 
620  av_assert2(index >= 0 && index < (ctx->buf_size>>1));
621 
622  if (index < - mx - my*stride ||
623  (ctx->buf_size>>1) - index < mx + size + (my + size - 1)*stride) {
624  av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid \n");
625  return AVERROR_INVALIDDATA;
626  }
627 
628  for (k = 0; k < size; k++)
629  memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
630  }
631 
632  return 0;
633 }
634 
635 static int old_codec47(SANMVideoContext *ctx, int top,
636  int left, int width, int height)
637 {
638  int i, j, seq, compr, new_rot, tbl_pos, skip;
639  int stride = ctx->pitch;
640  uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * stride;
641  uint8_t *prev1 = (uint8_t*)ctx->frm1;
642  uint8_t *prev2 = (uint8_t*)ctx->frm2;
643  uint32_t decoded_size;
644 
645  tbl_pos = bytestream2_tell(&ctx->gb);
646  seq = bytestream2_get_le16(&ctx->gb);
647  compr = bytestream2_get_byte(&ctx->gb);
648  new_rot = bytestream2_get_byte(&ctx->gb);
649  skip = bytestream2_get_byte(&ctx->gb);
650  bytestream2_skip(&ctx->gb, 9);
651  decoded_size = bytestream2_get_le32(&ctx->gb);
652  bytestream2_skip(&ctx->gb, 8);
653 
654  if (decoded_size > ctx->height * stride - left - top * stride) {
655  decoded_size = ctx->height * stride - left - top * stride;
656  av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n");
657  }
658 
659  if (skip & 1)
660  bytestream2_skip(&ctx->gb, 0x8080);
661  if (!seq) {
662  ctx->prev_seq = -1;
663  memset(prev1, 0, ctx->height * stride);
664  memset(prev2, 0, ctx->height * stride);
665  }
666  av_dlog(ctx->avctx, "compression %d\n", compr);
667  switch (compr) {
668  case 0:
669  if (bytestream2_get_bytes_left(&ctx->gb) < width * height)
670  return AVERROR_INVALIDDATA;
671  for (j = 0; j < height; j++) {
672  bytestream2_get_bufferu(&ctx->gb, dst, width);
673  dst += stride;
674  }
675  break;
676  case 1:
677  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
678  return AVERROR_INVALIDDATA;
679  for (j = 0; j < height; j += 2) {
680  for (i = 0; i < width; i += 2) {
681  dst[i] = dst[i + 1] =
682  dst[stride + i] = dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb);
683  }
684  dst += stride * 2;
685  }
686  break;
687  case 2:
688  if (seq == ctx->prev_seq + 1) {
689  for (j = 0; j < height; j += 8) {
690  for (i = 0; i < width; i += 8) {
691  if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
692  tbl_pos + 8, 8))
693  return AVERROR_INVALIDDATA;
694  }
695  dst += stride * 8;
696  prev1 += stride * 8;
697  prev2 += stride * 8;
698  }
699  }
700  break;
701  case 3:
702  memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
703  break;
704  case 4:
705  memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
706  break;
707  case 5:
708  if (rle_decode(ctx, dst, decoded_size))
709  return AVERROR_INVALIDDATA;
710  break;
711  default:
712  av_log(ctx->avctx, AV_LOG_ERROR,
713  "subcodec 47 compression %d not implemented\n", compr);
714  return AVERROR_PATCHWELCOME;
715  }
716  if (seq == ctx->prev_seq + 1)
717  ctx->rotate_code = new_rot;
718  else
719  ctx->rotate_code = 0;
720  ctx->prev_seq = seq;
721 
722  return 0;
723 }
724 
726 {
727  uint16_t codec, top, left, w, h;
728 
729  codec = bytestream2_get_le16u(&ctx->gb);
730  left = bytestream2_get_le16u(&ctx->gb);
731  top = bytestream2_get_le16u(&ctx->gb);
732  w = bytestream2_get_le16u(&ctx->gb);
733  h = bytestream2_get_le16u(&ctx->gb);
734 
735  if (ctx->width < left + w || ctx->height < top + h) {
736  if (av_image_check_size(FFMAX(left + w, ctx->width),
737  FFMAX(top + h, ctx->height), 0, ctx->avctx) < 0)
738  return AVERROR_INVALIDDATA;
739  avcodec_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
740  FFMAX(top + h, ctx->height));
741  init_sizes(ctx, FFMAX(left + w, ctx->width),
742  FFMAX(top + h, ctx->height));
743  if (init_buffers(ctx)) {
744  av_log(ctx->avctx, AV_LOG_ERROR, "error resizing buffers\n");
745  return AVERROR(ENOMEM);
746  }
747  }
748  bytestream2_skip(&ctx->gb, 4);
749 
750  av_dlog(ctx->avctx, "subcodec %d\n", codec);
751  switch (codec) {
752  case 1:
753  case 3:
754  return old_codec1(ctx, top, left, w, h);
755  break;
756  case 37:
757  return old_codec37(ctx, top, left, w, h);
758  break;
759  case 47:
760  return old_codec47(ctx, top, left, w, h);
761  break;
762  default:
763  avpriv_request_sample(ctx->avctx, "unknown subcodec %d", codec);
764  return AVERROR_PATCHWELCOME;
765  }
766 }
767 
768 static int decode_0(SANMVideoContext *ctx)
769 {
770  uint16_t *frm = ctx->frm0;
771  int x, y;
772 
773  if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
774  av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for raw frame\n");
775  return AVERROR_INVALIDDATA;
776  }
777  for (y = 0; y < ctx->height; y++) {
778  for (x = 0; x < ctx->width; x++)
779  frm[x] = bytestream2_get_le16u(&ctx->gb);
780  frm += ctx->pitch;
781  }
782  return 0;
783 }
784 
785 static int decode_nop(SANMVideoContext *ctx)
786 {
787  avpriv_request_sample(ctx->avctx, "unknown/unsupported compression type");
788  return AVERROR_PATCHWELCOME;
789 }
790 
791 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, int pitch)
792 {
793  uint8_t *dst = (uint8_t *)pdest;
794  uint8_t *src = (uint8_t *)psrc;
795  int stride = pitch * 2;
796 
797  switch (block_size) {
798  case 2:
799  copy_block4(dst, src, stride, stride, 2);
800  break;
801  case 4:
802  copy_block8(dst, src, stride, stride, 4);
803  break;
804  case 8:
805  copy_block16(dst, src, stride, stride, 8);
806  break;
807  }
808 }
809 
810 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitch)
811 {
812  int x, y;
813 
814  pitch -= block_size;
815  for (y = 0; y < block_size; y++, pdest += pitch)
816  for (x = 0; x < block_size; x++)
817  *pdest++ = color;
818 }
819 
820 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color,
821  uint16_t bg_color, int block_size, int pitch)
822 {
823  int8_t *pglyph;
824  uint16_t colors[2] = { fg_color, bg_color };
825  int x, y;
826 
827  if (index >= NGLYPHS) {
828  av_log(ctx->avctx, AV_LOG_ERROR, "ignoring nonexistent glyph #%u\n", index);
829  return AVERROR_INVALIDDATA;
830  }
831 
832  pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
833  pitch -= block_size;
834 
835  for (y = 0; y < block_size; y++, dst += pitch)
836  for (x = 0; x < block_size; x++)
837  *dst++ = colors[*pglyph++];
838  return 0;
839 }
840 
841 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
842 {
843  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
844 
845  if (block_size == 2) {
846  uint32_t indices;
847 
848  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
849  return AVERROR_INVALIDDATA;
850 
851  indices = bytestream2_get_le32u(&ctx->gb);
852  dst[0] = ctx->codebook[indices & 0xFF]; indices >>= 8;
853  dst[1] = ctx->codebook[indices & 0xFF]; indices >>= 8;
854  dst[pitch] = ctx->codebook[indices & 0xFF]; indices >>= 8;
855  dst[pitch + 1] = ctx->codebook[indices & 0xFF];
856  } else {
857  uint16_t fgcolor, bgcolor;
858  int glyph;
859 
860  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
861  return AVERROR_INVALIDDATA;
862 
863  glyph = bytestream2_get_byteu(&ctx->gb);
864  bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
865  fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
866 
867  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
868  }
869  return 0;
870 }
871 
872 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
873 {
874  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
875 
876  if (block_size == 2) {
877  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
878  return AVERROR_INVALIDDATA;
879 
880  dst[0] = bytestream2_get_le16u(&ctx->gb);
881  dst[1] = bytestream2_get_le16u(&ctx->gb);
882  dst[pitch] = bytestream2_get_le16u(&ctx->gb);
883  dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
884  } else {
885  uint16_t fgcolor, bgcolor;
886  int glyph;
887 
888  if (bytestream2_get_bytes_left(&ctx->gb) < 5)
889  return AVERROR_INVALIDDATA;
890 
891  glyph = bytestream2_get_byteu(&ctx->gb);
892  bgcolor = bytestream2_get_le16u(&ctx->gb);
893  fgcolor = bytestream2_get_le16u(&ctx->gb);
894 
895  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
896  }
897  return 0;
898 }
899 
900 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
901  int block_size)
902 {
903  int start_pos = cx + mx + (cy + my) * ctx->pitch;
904  int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
905 
906  int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
907 
908  if (!good) {
909  av_log(ctx->avctx, AV_LOG_ERROR, "ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
910  cx + mx, cy + my, cx, cy, block_size);
911  }
912 
913  return good;
914 }
915 
916 static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
917 {
918  int16_t mx, my, index;
919  int opcode;
920 
921  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
922  return AVERROR_INVALIDDATA;
923 
924  opcode = bytestream2_get_byteu(&ctx->gb);
925 
926  av_dlog(ctx->avctx, "opcode 0x%0X cx %d cy %d blk %d\n", opcode, cx, cy, blk_size);
927  switch (opcode) {
928  default:
929  mx = motion_vectors[opcode][0];
930  my = motion_vectors[opcode][1];
931 
932  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
933  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
934  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
935  blk_size, ctx->pitch);
936  }
937  break;
938  case 0xF5:
939  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
940  return AVERROR_INVALIDDATA;
941  index = bytestream2_get_le16u(&ctx->gb);
942 
943  mx = index % ctx->width;
944  my = index / ctx->width;
945 
946  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
947  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
948  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
949  blk_size, ctx->pitch);
950  }
951  break;
952  case 0xF6:
953  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
954  ctx->frm1 + cx + ctx->pitch * cy,
955  blk_size, ctx->pitch);
956  break;
957  case 0xF7:
958  opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
959  break;
960 
961  case 0xF8:
962  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
963  break;
964  case 0xF9:
965  case 0xFA:
966  case 0xFB:
967  case 0xFC:
968  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
969  ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
970  break;
971  case 0xFD:
972  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
973  return AVERROR_INVALIDDATA;
974  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
975  ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
976  break;
977  case 0xFE:
978  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
979  return AVERROR_INVALIDDATA;
980  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
981  bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
982  break;
983  case 0xFF:
984  if (blk_size == 2) {
985  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
986  } else {
987  blk_size >>= 1;
988  if (codec2subblock(ctx, cx , cy , blk_size))
989  return AVERROR_INVALIDDATA;
990  if (codec2subblock(ctx, cx + blk_size, cy , blk_size))
991  return AVERROR_INVALIDDATA;
992  if (codec2subblock(ctx, cx , cy + blk_size, blk_size))
993  return AVERROR_INVALIDDATA;
994  if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
995  return AVERROR_INVALIDDATA;
996  }
997  break;
998  }
999  return 0;
1000 }
1001 
1002 static int decode_2(SANMVideoContext *ctx)
1003 {
1004  int cx, cy, ret;
1005 
1006  for (cy = 0; cy < ctx->aligned_height; cy += 8) {
1007  for (cx = 0; cx < ctx->aligned_width; cx += 8) {
1008  if (ret = codec2subblock(ctx, cx, cy, 8))
1009  return ret;
1010  }
1011  }
1012 
1013  return 0;
1014 }
1015 
1016 static int decode_3(SANMVideoContext *ctx)
1017 {
1018  memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
1019  return 0;
1020 }
1021 
1022 static int decode_4(SANMVideoContext *ctx)
1023 {
1024  memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
1025  return 0;
1026 }
1027 
1028 static int decode_5(SANMVideoContext *ctx)
1029 {
1030 #if HAVE_BIGENDIAN
1031  uint16_t *frm;
1032  int npixels;
1033 #endif
1034  uint8_t *dst = (uint8_t*)ctx->frm0;
1035 
1036  if (rle_decode(ctx, dst, ctx->buf_size))
1037  return AVERROR_INVALIDDATA;
1038 
1039 #if HAVE_BIGENDIAN
1040  npixels = ctx->npixels;
1041  frm = ctx->frm0;
1042  while (npixels--)
1043  *frm++ = av_bswap16(*frm);
1044 #endif
1045 
1046  return 0;
1047 }
1048 
1049 static int decode_6(SANMVideoContext *ctx)
1050 {
1051  int npixels = ctx->npixels;
1052  uint16_t *frm = ctx->frm0;
1053 
1054  if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
1055  av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for frame\n");
1056  return AVERROR_INVALIDDATA;
1057  }
1058  while (npixels--)
1059  *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1060 
1061  return 0;
1062 }
1063 
1064 static int decode_8(SANMVideoContext *ctx)
1065 {
1066  uint16_t *pdest = ctx->frm0;
1067  uint8_t *rsrc;
1068  long npixels = ctx->npixels;
1069 
1070  av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
1071  if (!ctx->rle_buf) {
1072  av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed\n");
1073  return AVERROR(ENOMEM);
1074  }
1075  rsrc = ctx->rle_buf;
1076 
1077  if (rle_decode(ctx, rsrc, npixels))
1078  return AVERROR_INVALIDDATA;
1079 
1080  while (npixels--)
1081  *pdest++ = ctx->codebook[*rsrc++];
1082 
1083  return 0;
1084 }
1085 
1086 typedef int (*frm_decoder)(SANMVideoContext *ctx);
1087 
1088 static const frm_decoder v1_decoders[] = {
1091 };
1092 
1094 {
1095  int i, ret;
1096 
1097  if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
1098  av_log(ctx->avctx, AV_LOG_ERROR, "too short input frame (%d bytes)\n",
1099  ret);
1100  return AVERROR_INVALIDDATA;
1101  }
1102  bytestream2_skip(&ctx->gb, 8); // skip pad
1103 
1104  hdr->width = bytestream2_get_le32u(&ctx->gb);
1105  hdr->height = bytestream2_get_le32u(&ctx->gb);
1106 
1107  if (hdr->width != ctx->width || hdr->height != ctx->height) {
1108  av_log(ctx->avctx, AV_LOG_ERROR, "variable size frames are not implemented\n");
1109  return AVERROR_PATCHWELCOME;
1110  }
1111 
1112  hdr->seq_num = bytestream2_get_le16u(&ctx->gb);
1113  hdr->codec = bytestream2_get_byteu(&ctx->gb);
1114  hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
1115 
1116  bytestream2_skip(&ctx->gb, 4); // skip pad
1117 
1118  for (i = 0; i < 4; i++)
1119  ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
1120  hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
1121 
1122  bytestream2_skip(&ctx->gb, 2); // skip pad
1123 
1124  hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
1125  for (i = 0; i < 256; i++)
1126  ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
1127 
1128  bytestream2_skip(&ctx->gb, 8); // skip pad
1129 
1130  av_dlog(ctx->avctx, "subcodec %d\n", hdr->codec);
1131  return 0;
1132 }
1133 
1134 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
1135 {
1136  while (buf_size--)
1137  *pbuf++ = color;
1138 }
1139 
1141 {
1142  uint8_t *dst;
1143  const uint8_t *src = (uint8_t*) ctx->frm0;
1144  int ret, dstpitch, height = ctx->height;
1145  int srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
1146 
1147  if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
1148  return ret;
1149 
1150  dst = ctx->frame->data[0];
1151  dstpitch = ctx->frame->linesize[0];
1152 
1153  while (height--) {
1154  memcpy(dst, src, srcpitch);
1155  src += srcpitch;
1156  dst += dstpitch;
1157  }
1158 
1159  return 0;
1160 }
1161 
1162 static int decode_frame(AVCodecContext *avctx, void *data,
1163  int *got_frame_ptr, AVPacket *pkt)
1164 {
1165  SANMVideoContext *ctx = avctx->priv_data;
1166  int i, ret;
1167 
1168  ctx->frame = data;
1169  bytestream2_init(&ctx->gb, pkt->data, pkt->size);
1170 
1171  if (!ctx->version) {
1172  int to_store = 0;
1173 
1174  while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
1175  uint32_t sig, size;
1176  int pos;
1177 
1178  sig = bytestream2_get_be32u(&ctx->gb);
1179  size = bytestream2_get_be32u(&ctx->gb);
1180  pos = bytestream2_tell(&ctx->gb);
1181 
1182  if (bytestream2_get_bytes_left(&ctx->gb) < size) {
1183  av_log(avctx, AV_LOG_ERROR, "incorrect chunk size %d\n", size);
1184  break;
1185  }
1186  switch (sig) {
1187  case MKBETAG('N', 'P', 'A', 'L'):
1188  if (size != 256 * 3) {
1189  av_log(avctx, AV_LOG_ERROR, "incorrect palette block size %d\n",
1190  size);
1191  return AVERROR_INVALIDDATA;
1192  }
1193  for (i = 0; i < 256; i++)
1194  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1195  break;
1196  case MKBETAG('F', 'O', 'B', 'J'):
1197  if (size < 16)
1198  return AVERROR_INVALIDDATA;
1199  if (ret = process_frame_obj(ctx))
1200  return ret;
1201  break;
1202  case MKBETAG('X', 'P', 'A', 'L'):
1203  if (size == 6 || size == 4) {
1204  uint8_t tmp[3];
1205  int j;
1206 
1207  for (i = 0; i < 256; i++) {
1208  for (j = 0; j < 3; j++) {
1209  int t = (ctx->pal[i] >> (16 - j * 8)) & 0xFF;
1210  tmp[j] = av_clip_uint8((t * 129 + ctx->delta_pal[i * 3 + j]) >> 7);
1211  }
1212  ctx->pal[i] = 0xFFU << 24 | AV_RB24(tmp);
1213  }
1214  } else {
1215  if (size < 768 * 2 + 4) {
1216  av_log(avctx, AV_LOG_ERROR, "incorrect palette change block size %d\n",
1217  size);
1218  return AVERROR_INVALIDDATA;
1219  }
1220  bytestream2_skipu(&ctx->gb, 4);
1221  for (i = 0; i < 768; i++)
1222  ctx->delta_pal[i] = bytestream2_get_le16u(&ctx->gb);
1223  if (size >= 768 * 5 + 4) {
1224  for (i = 0; i < 256; i++)
1225  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1226  } else {
1227  memset(ctx->pal, 0, sizeof(ctx->pal));
1228  }
1229  }
1230  break;
1231  case MKBETAG('S', 'T', 'O', 'R'):
1232  to_store = 1;
1233  break;
1234  case MKBETAG('F', 'T', 'C', 'H'):
1235  memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
1236  break;
1237  default:
1238  bytestream2_skip(&ctx->gb, size);
1239  av_log(avctx, AV_LOG_DEBUG, "unknown/unsupported chunk %x\n", sig);
1240  break;
1241  }
1242 
1243  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
1244  if (size & 1)
1245  bytestream2_skip(&ctx->gb, 1);
1246  }
1247  if (to_store)
1248  memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
1249  if ((ret = copy_output(ctx, NULL)))
1250  return ret;
1251  memcpy(ctx->frame->data[1], ctx->pal, 1024);
1252  } else {
1253  SANMFrameHeader header;
1254 
1255  if ((ret = read_frame_header(ctx, &header)))
1256  return ret;
1257 
1258  ctx->rotate_code = header.rotate_code;
1259  if ((ctx->frame->key_frame = !header.seq_num)) {
1261  fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
1262  fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
1263  } else {
1265  }
1266 
1267  if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
1268  if ((ret = v1_decoders[header.codec](ctx))) {
1269  av_log(avctx, AV_LOG_ERROR,
1270  "subcodec %d: error decoding frame\n", header.codec);
1271  return ret;
1272  }
1273  } else {
1274  avpriv_request_sample(avctx, "subcodec %d",
1275  header.codec);
1276  return AVERROR_PATCHWELCOME;
1277  }
1278 
1279  if ((ret = copy_output(ctx, &header)))
1280  return ret;
1281  }
1282  if (ctx->rotate_code)
1283  rotate_bufs(ctx, ctx->rotate_code);
1284 
1285  *got_frame_ptr = 1;
1286 
1287  return pkt->size;
1288 }
1289 
1291  .name = "sanm",
1292  .type = AVMEDIA_TYPE_VIDEO,
1293  .id = AV_CODEC_ID_SANM,
1294  .priv_data_size = sizeof(SANMVideoContext),
1295  .init = decode_init,
1296  .close = decode_end,
1297  .decode = decode_frame,
1298  .capabilities = CODEC_CAP_DR1,
1299  .long_name = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"),
1300 };
static const int8_t c37_mv[]
Definition: sanm_data.h:93
Definition: sanm.c:88
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static int process_frame_obj(SANMVideoContext *ctx)
Definition: sanm.c:725
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:1093
int8_t p4x4glyphs[NGLYPHS][16]
Definition: sanm.c:65
int aligned_height
Definition: sanm.c:46
misc image utilities
static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
Definition: sanm.c:1134
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm_data.h:29
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
static void copy_block16(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h)
Definition: copy_block.h:59
void avcodec_set_dimensions(AVCodecContext *s, int width, int height)
static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
Definition: sanm.c:872
y1
Definition: lab5.m:33
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *pkt)
Definition: sanm.c:1162
uint8_t * stored_frame
Definition: sanm.c:51
#define av_bswap16
Definition: sh4/bswap.h:31
#define AV_RB24
int16_t delta_pal[768]
Definition: sanm.c:42
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
GlyphEdge
Definition: sanm.c:76
#define AV_RL16
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional FF_INPUT_BUFFER_PADDING_SIZE at the end w...
static enum GlyphEdge which_edge(int x, int y, int edge_size)
Return enum GlyphEdge of box where point (x, y) lies.
Definition: sanm.c:99
x1
Definition: genspecsines3.m:7
Definition: sanm.c:85
Definition: sanm.c:81
#define FF_ARRAY_ELEMS(a)
av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (%s)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic?ac->func_descr_generic:ac->func_descr)
uint32_t width
Definition: sanm.c:73
uint16_t * frm0
Definition: sanm.c:50
int stride
Definition: mace.c:144
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:268
output residual component w
#define FFALIGN(x, a)
Definition: common.h:63
Definition: sanm.c:89
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
static const uint8_t run_len[7][16]
Definition: h264_cavlc.c:219
int rotate_code
Definition: sanm.c:70
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color, uint16_t bg_color, int block_size, int pitch)
Definition: sanm.c:820
uint8_t
#define av_cold
Definition: attributes.h:78
static av_cold int decode_init(AVCodecContext *avctx)
Definition: sanm.c:263
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:63
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:77
static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, int block_size)
Definition: sanm.c:900
static AVPacket pkt
Definition: demuxing.c:56
uint16_t bg_color
Definition: sanm.c:72
end end
static void codec37_mv(uint8_t *dst, const uint8_t *src, int height, int stride, int x, int y)
Definition: sanm.c:379
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
AVFrame * frame
Definition: sanm.c:49
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE]
Definition: sanm_data.h:31
int(* frm_decoder)(SANMVideoContext *ctx)
Definition: sanm.c:1086
static av_always_inline void bytestream2_skipu(GetByteContext *g, unsigned int size)
Definition: bytestream.h:165
GetByteContext gb
Definition: sanm.c:38
static int decode_5(SANMVideoContext *ctx)
Definition: sanm.c:1028
uint16_t small_codebook[4]
Definition: sanm.c:63
Discrete Time axis x
#define U(x)
uint32_t height
Definition: sanm.c:73
static av_cold int decode_end(AVCodecContext *avctx)
Definition: sanm.c:297
int codec
Definition: sanm.c:70
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:159
static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
Definition: sanm.c:306
Definition: sanm.c:77
#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_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:258
int rle_output_size
Definition: sanm.c:70
int subversion
Definition: sanm.c:40
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
uint16_t * frm1
Definition: sanm.c:50
long npixels
Definition: sanm.c:60
AVCodecContext * avctx
Definition: sanm.c:37
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
static int decode_3(SANMVideoContext *ctx)
Definition: sanm.c:1016
const char * name
Name of the codec implementation.
static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
Definition: sanm.c:116
static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, const int side_length)
Construct glyphs by iterating through vectors coordinates.
Definition: sanm.c:162
uint32_t frm1_size
Definition: sanm.c:52
#define FFMAX(a, b)
Definition: common.h:56
external API header
int size
uint32_t stored_frame_size
Definition: sanm.c:53
uint32_t frm2_size
Definition: sanm.c:52
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:231
int aligned_width
Definition: sanm.c:46
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:144
GlyphDir
Definition: sanm.c:84
ret
Definition: avfilter.c:821
int width
picture width / height.
static void destroy_buffers(SANMVideoContext *ctx)
Definition: sanm.c:227
t
Definition: genspecsines3.m:6
static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, int pos, int npoints)
Interpolate two points.
Definition: sanm.c:142
static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, int pitch)
Definition: sanm.c:791
static int old_codec47(SANMVideoContext *ctx, int top, int left, int width, int height)
Definition: sanm.c:635
#define FFABS(a)
Definition: common.h:53
int seq_num
Definition: sanm.c:70
static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:1140
Definition: sanm.c:78
#define AV_RL32
#define GLYPH_COORD_VECT_SIZE
Definition: sanm_data.h:27
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static av_cold int init_buffers(SANMVideoContext *ctx)
Definition: sanm.c:239
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:183
for k
NULL
Definition: eval.c:55
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 width
Definition: tests/utils.c:158
AVS_Value src
Definition: avisynth_c.h:523
static int decode_nop(SANMVideoContext *ctx)
Definition: sanm.c:785
static int decode_6(SANMVideoContext *ctx)
Definition: sanm.c:1049
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm_data.h:33
main external API structure.
static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
Definition: sanm.c:916
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
int version
Definition: sanm.c:40
static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, uint8_t *prev2, int stride, int tbl, int size)
Definition: sanm.c:545
static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
Definition: sanm.c:841
static int decode_2(SANMVideoContext *ctx)
Definition: sanm.c:1002
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
#define NGLYPHS
Definition: sanm.c:34
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
static const int8_t motion_vectors[256][2]
Definition: sanm_data.h:38
byte swapping routines
static int decode_8(SANMVideoContext *ctx)
Definition: sanm.c:1064
static int decode_0(SANMVideoContext *ctx)
Definition: sanm.c:768
uint16_t * frm2
Definition: sanm.c:50
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
Definition: sanm.c:255
static const frm_decoder v1_decoders[]
Definition: sanm.c:1088
Definition: sanm.c:86
static int flags
Definition: cpu.c:23
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitch)
Definition: sanm.c:810
unsigned int rle_buf_size
Definition: sanm.c:56
uint32_t pal[256]
Definition: sanm.c:41
static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE]
Definition: sanm_data.h:35
static int old_codec37(SANMVideoContext *ctx, int top, int left, int width, int height)
Definition: sanm.c:398
uint16_t codebook[256]
Definition: sanm.c:62
common internal api header.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
static void init_sizes(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:214
function y
Definition: D.m:1
long buf_size
Definition: sanm.c:60
#define MKBETAG(a, b, c, d)
Definition: common.h:283
static int decode_4(SANMVideoContext *ctx)
Definition: sanm.c:1022
int len
static void copy_block4(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h)
Definition: copy_block.h:37
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:139
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:203
static void copy_block8(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h)
Definition: copy_block.h:48
AVCodec ff_sanm_decoder
Definition: sanm.c:1290
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:268
int prev_seq
Definition: sanm.c:47
static int old_codec1(SANMVideoContext *ctx, int top, int left, int width, int height)
Definition: sanm.c:332
int rotate_code
Definition: sanm.c:58
int8_t p8x8glyphs[NGLYPHS][64]
Definition: sanm.c:66
Definition: sanm.c:87
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
uint32_t frm0_size
Definition: sanm.c:52
#define FFSWAP(type, a, b)
Definition: common.h:61
int height
Definition: sanm.c:45
uint8_t * rle_buf
Definition: sanm.c:55
This structure stores compressed data.
Predicted.
Definition: avutil.h:217