annotate ffmpeg/libavcodec/interplayvideo.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Interplay MVE Video Decoder
yading@10 3 * Copyright (C) 2003 the ffmpeg project
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
yading@10 25 * For more information about the Interplay MVE format, visit:
yading@10 26 * http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
yading@10 27 * This code is written in such a way that the identifiers match up
yading@10 28 * with the encoding descriptions in the document.
yading@10 29 *
yading@10 30 * This decoder presently only supports a PAL8 output colorspace.
yading@10 31 *
yading@10 32 * An Interplay video frame consists of 2 parts: The decoding map and
yading@10 33 * the video data. A demuxer must load these 2 parts together in a single
yading@10 34 * buffer before sending it through the stream to this decoder.
yading@10 35 */
yading@10 36
yading@10 37 #include <stdio.h>
yading@10 38 #include <stdlib.h>
yading@10 39 #include <string.h>
yading@10 40
yading@10 41 #include "avcodec.h"
yading@10 42 #include "bytestream.h"
yading@10 43 #include "hpeldsp.h"
yading@10 44 #define BITSTREAM_READER_LE
yading@10 45 #include "get_bits.h"
yading@10 46 #include "internal.h"
yading@10 47
yading@10 48 #define PALETTE_COUNT 256
yading@10 49
yading@10 50 typedef struct IpvideoContext {
yading@10 51
yading@10 52 AVCodecContext *avctx;
yading@10 53 HpelDSPContext hdsp;
yading@10 54 AVFrame *second_last_frame;
yading@10 55 AVFrame *last_frame;
yading@10 56 const unsigned char *decoding_map;
yading@10 57 int decoding_map_size;
yading@10 58
yading@10 59 int is_16bpp;
yading@10 60 GetByteContext stream_ptr, mv_ptr;
yading@10 61 unsigned char *pixel_ptr;
yading@10 62 int line_inc;
yading@10 63 int stride;
yading@10 64 int upper_motion_limit_offset;
yading@10 65
yading@10 66 uint32_t pal[256];
yading@10 67 } IpvideoContext;
yading@10 68
yading@10 69 static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y)
yading@10 70 {
yading@10 71 int current_offset = s->pixel_ptr - dst->data[0];
yading@10 72 int motion_offset = current_offset + delta_y * dst->linesize[0]
yading@10 73 + delta_x * (1 + s->is_16bpp);
yading@10 74 if (motion_offset < 0) {
yading@10 75 av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset);
yading@10 76 return AVERROR_INVALIDDATA;
yading@10 77 } else if (motion_offset > s->upper_motion_limit_offset) {
yading@10 78 av_log(s->avctx, AV_LOG_ERROR, "motion offset above limit (%d >= %d)\n",
yading@10 79 motion_offset, s->upper_motion_limit_offset);
yading@10 80 return AVERROR_INVALIDDATA;
yading@10 81 }
yading@10 82 if (src->data[0] == NULL) {
yading@10 83 av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
yading@10 84 return AVERROR(EINVAL);
yading@10 85 }
yading@10 86 s->hdsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset,
yading@10 87 dst->linesize[0], 8);
yading@10 88 return 0;
yading@10 89 }
yading@10 90
yading@10 91 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s, AVFrame *frame)
yading@10 92 {
yading@10 93 return copy_from(s, s->last_frame, frame, 0, 0);
yading@10 94 }
yading@10 95
yading@10 96 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s, AVFrame *frame)
yading@10 97 {
yading@10 98 return copy_from(s, s->second_last_frame, frame, 0, 0);
yading@10 99 }
yading@10 100
yading@10 101 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s, AVFrame *frame)
yading@10 102 {
yading@10 103 unsigned char B;
yading@10 104 int x, y;
yading@10 105
yading@10 106 /* copy block from 2 frames ago using a motion vector; need 1 more byte */
yading@10 107 if (!s->is_16bpp) {
yading@10 108 B = bytestream2_get_byte(&s->stream_ptr);
yading@10 109 } else {
yading@10 110 B = bytestream2_get_byte(&s->mv_ptr);
yading@10 111 }
yading@10 112
yading@10 113 if (B < 56) {
yading@10 114 x = 8 + (B % 7);
yading@10 115 y = B / 7;
yading@10 116 } else {
yading@10 117 x = -14 + ((B - 56) % 29);
yading@10 118 y = 8 + ((B - 56) / 29);
yading@10 119 }
yading@10 120
yading@10 121 av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
yading@10 122 return copy_from(s, s->second_last_frame, frame, x, y);
yading@10 123 }
yading@10 124
yading@10 125 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s, AVFrame *frame)
yading@10 126 {
yading@10 127 unsigned char B;
yading@10 128 int x, y;
yading@10 129
yading@10 130 /* copy 8x8 block from current frame from an up/left block */
yading@10 131
yading@10 132 /* need 1 more byte for motion */
yading@10 133 if (!s->is_16bpp) {
yading@10 134 B = bytestream2_get_byte(&s->stream_ptr);
yading@10 135 } else {
yading@10 136 B = bytestream2_get_byte(&s->mv_ptr);
yading@10 137 }
yading@10 138
yading@10 139 if (B < 56) {
yading@10 140 x = -(8 + (B % 7));
yading@10 141 y = -(B / 7);
yading@10 142 } else {
yading@10 143 x = -(-14 + ((B - 56) % 29));
yading@10 144 y = -( 8 + ((B - 56) / 29));
yading@10 145 }
yading@10 146
yading@10 147 av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
yading@10 148 return copy_from(s, frame, frame, x, y);
yading@10 149 }
yading@10 150
yading@10 151 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s, AVFrame *frame)
yading@10 152 {
yading@10 153 int x, y;
yading@10 154 unsigned char B, BL, BH;
yading@10 155
yading@10 156 /* copy a block from the previous frame; need 1 more byte */
yading@10 157 if (!s->is_16bpp) {
yading@10 158 B = bytestream2_get_byte(&s->stream_ptr);
yading@10 159 } else {
yading@10 160 B = bytestream2_get_byte(&s->mv_ptr);
yading@10 161 }
yading@10 162
yading@10 163 BL = B & 0x0F;
yading@10 164 BH = (B >> 4) & 0x0F;
yading@10 165 x = -8 + BL;
yading@10 166 y = -8 + BH;
yading@10 167
yading@10 168 av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
yading@10 169 return copy_from(s, s->last_frame, frame, x, y);
yading@10 170 }
yading@10 171
yading@10 172 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s, AVFrame *frame)
yading@10 173 {
yading@10 174 signed char x, y;
yading@10 175
yading@10 176 /* copy a block from the previous frame using an expanded range;
yading@10 177 * need 2 more bytes */
yading@10 178 x = bytestream2_get_byte(&s->stream_ptr);
yading@10 179 y = bytestream2_get_byte(&s->stream_ptr);
yading@10 180
yading@10 181 av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y);
yading@10 182 return copy_from(s, s->last_frame, frame, x, y);
yading@10 183 }
yading@10 184
yading@10 185 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s, AVFrame *frame)
yading@10 186 {
yading@10 187 /* mystery opcode? skip multiple blocks? */
yading@10 188 av_log(s->avctx, AV_LOG_ERROR, "Help! Mystery opcode 0x6 seen\n");
yading@10 189
yading@10 190 /* report success */
yading@10 191 return 0;
yading@10 192 }
yading@10 193
yading@10 194 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s, AVFrame *frame)
yading@10 195 {
yading@10 196 int x, y;
yading@10 197 unsigned char P[2];
yading@10 198 unsigned int flags;
yading@10 199
yading@10 200 /* 2-color encoding */
yading@10 201 P[0] = bytestream2_get_byte(&s->stream_ptr);
yading@10 202 P[1] = bytestream2_get_byte(&s->stream_ptr);
yading@10 203
yading@10 204 if (P[0] <= P[1]) {
yading@10 205
yading@10 206 /* need 8 more bytes from the stream */
yading@10 207 for (y = 0; y < 8; y++) {
yading@10 208 flags = bytestream2_get_byte(&s->stream_ptr) | 0x100;
yading@10 209 for (; flags != 1; flags >>= 1)
yading@10 210 *s->pixel_ptr++ = P[flags & 1];
yading@10 211 s->pixel_ptr += s->line_inc;
yading@10 212 }
yading@10 213
yading@10 214 } else {
yading@10 215
yading@10 216 /* need 2 more bytes from the stream */
yading@10 217 flags = bytestream2_get_le16(&s->stream_ptr);
yading@10 218 for (y = 0; y < 8; y += 2) {
yading@10 219 for (x = 0; x < 8; x += 2, flags >>= 1) {
yading@10 220 s->pixel_ptr[x ] =
yading@10 221 s->pixel_ptr[x + 1 ] =
yading@10 222 s->pixel_ptr[x + s->stride] =
yading@10 223 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
yading@10 224 }
yading@10 225 s->pixel_ptr += s->stride * 2;
yading@10 226 }
yading@10 227 }
yading@10 228
yading@10 229 /* report success */
yading@10 230 return 0;
yading@10 231 }
yading@10 232
yading@10 233 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s, AVFrame *frame)
yading@10 234 {
yading@10 235 int x, y;
yading@10 236 unsigned char P[4];
yading@10 237 unsigned int flags = 0;
yading@10 238
yading@10 239 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
yading@10 240 * either top and bottom or left and right halves */
yading@10 241 P[0] = bytestream2_get_byte(&s->stream_ptr);
yading@10 242 P[1] = bytestream2_get_byte(&s->stream_ptr);
yading@10 243
yading@10 244 if (P[0] <= P[1]) {
yading@10 245 for (y = 0; y < 16; y++) {
yading@10 246 // new values for each 4x4 block
yading@10 247 if (!(y & 3)) {
yading@10 248 if (y) {
yading@10 249 P[0] = bytestream2_get_byte(&s->stream_ptr);
yading@10 250 P[1] = bytestream2_get_byte(&s->stream_ptr);
yading@10 251 }
yading@10 252 flags = bytestream2_get_le16(&s->stream_ptr);
yading@10 253 }
yading@10 254
yading@10 255 for (x = 0; x < 4; x++, flags >>= 1)
yading@10 256 *s->pixel_ptr++ = P[flags & 1];
yading@10 257 s->pixel_ptr += s->stride - 4;
yading@10 258 // switch to right half
yading@10 259 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
yading@10 260 }
yading@10 261
yading@10 262 } else {
yading@10 263 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 264 P[2] = bytestream2_get_byte(&s->stream_ptr);
yading@10 265 P[3] = bytestream2_get_byte(&s->stream_ptr);
yading@10 266
yading@10 267 if (P[2] <= P[3]) {
yading@10 268
yading@10 269 /* vertical split; left & right halves are 2-color encoded */
yading@10 270
yading@10 271 for (y = 0; y < 16; y++) {
yading@10 272 for (x = 0; x < 4; x++, flags >>= 1)
yading@10 273 *s->pixel_ptr++ = P[flags & 1];
yading@10 274 s->pixel_ptr += s->stride - 4;
yading@10 275 // switch to right half
yading@10 276 if (y == 7) {
yading@10 277 s->pixel_ptr -= 8 * s->stride - 4;
yading@10 278 P[0] = P[2];
yading@10 279 P[1] = P[3];
yading@10 280 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 281 }
yading@10 282 }
yading@10 283
yading@10 284 } else {
yading@10 285
yading@10 286 /* horizontal split; top & bottom halves are 2-color encoded */
yading@10 287
yading@10 288 for (y = 0; y < 8; y++) {
yading@10 289 if (y == 4) {
yading@10 290 P[0] = P[2];
yading@10 291 P[1] = P[3];
yading@10 292 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 293 }
yading@10 294
yading@10 295 for (x = 0; x < 8; x++, flags >>= 1)
yading@10 296 *s->pixel_ptr++ = P[flags & 1];
yading@10 297 s->pixel_ptr += s->line_inc;
yading@10 298 }
yading@10 299 }
yading@10 300 }
yading@10 301
yading@10 302 /* report success */
yading@10 303 return 0;
yading@10 304 }
yading@10 305
yading@10 306 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s, AVFrame *frame)
yading@10 307 {
yading@10 308 int x, y;
yading@10 309 unsigned char P[4];
yading@10 310
yading@10 311 /* 4-color encoding */
yading@10 312 bytestream2_get_buffer(&s->stream_ptr, P, 4);
yading@10 313
yading@10 314 if (P[0] <= P[1]) {
yading@10 315 if (P[2] <= P[3]) {
yading@10 316
yading@10 317 /* 1 of 4 colors for each pixel, need 16 more bytes */
yading@10 318 for (y = 0; y < 8; y++) {
yading@10 319 /* get the next set of 8 2-bit flags */
yading@10 320 int flags = bytestream2_get_le16(&s->stream_ptr);
yading@10 321 for (x = 0; x < 8; x++, flags >>= 2)
yading@10 322 *s->pixel_ptr++ = P[flags & 0x03];
yading@10 323 s->pixel_ptr += s->line_inc;
yading@10 324 }
yading@10 325
yading@10 326 } else {
yading@10 327 uint32_t flags;
yading@10 328
yading@10 329 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
yading@10 330 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 331
yading@10 332 for (y = 0; y < 8; y += 2) {
yading@10 333 for (x = 0; x < 8; x += 2, flags >>= 2) {
yading@10 334 s->pixel_ptr[x ] =
yading@10 335 s->pixel_ptr[x + 1 ] =
yading@10 336 s->pixel_ptr[x + s->stride] =
yading@10 337 s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
yading@10 338 }
yading@10 339 s->pixel_ptr += s->stride * 2;
yading@10 340 }
yading@10 341
yading@10 342 }
yading@10 343 } else {
yading@10 344 uint64_t flags;
yading@10 345
yading@10 346 /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
yading@10 347 flags = bytestream2_get_le64(&s->stream_ptr);
yading@10 348 if (P[2] <= P[3]) {
yading@10 349 for (y = 0; y < 8; y++) {
yading@10 350 for (x = 0; x < 8; x += 2, flags >>= 2) {
yading@10 351 s->pixel_ptr[x ] =
yading@10 352 s->pixel_ptr[x + 1] = P[flags & 0x03];
yading@10 353 }
yading@10 354 s->pixel_ptr += s->stride;
yading@10 355 }
yading@10 356 } else {
yading@10 357 for (y = 0; y < 8; y += 2) {
yading@10 358 for (x = 0; x < 8; x++, flags >>= 2) {
yading@10 359 s->pixel_ptr[x ] =
yading@10 360 s->pixel_ptr[x + s->stride] = P[flags & 0x03];
yading@10 361 }
yading@10 362 s->pixel_ptr += s->stride * 2;
yading@10 363 }
yading@10 364 }
yading@10 365 }
yading@10 366
yading@10 367 /* report success */
yading@10 368 return 0;
yading@10 369 }
yading@10 370
yading@10 371 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s, AVFrame *frame)
yading@10 372 {
yading@10 373 int x, y;
yading@10 374 unsigned char P[8];
yading@10 375 int flags = 0;
yading@10 376
yading@10 377 bytestream2_get_buffer(&s->stream_ptr, P, 4);
yading@10 378
yading@10 379 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
yading@10 380 * either top and bottom or left and right halves */
yading@10 381 if (P[0] <= P[1]) {
yading@10 382
yading@10 383 /* 4-color encoding for each quadrant; need 32 bytes */
yading@10 384 for (y = 0; y < 16; y++) {
yading@10 385 // new values for each 4x4 block
yading@10 386 if (!(y & 3)) {
yading@10 387 if (y) bytestream2_get_buffer(&s->stream_ptr, P, 4);
yading@10 388 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 389 }
yading@10 390
yading@10 391 for (x = 0; x < 4; x++, flags >>= 2)
yading@10 392 *s->pixel_ptr++ = P[flags & 0x03];
yading@10 393
yading@10 394 s->pixel_ptr += s->stride - 4;
yading@10 395 // switch to right half
yading@10 396 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
yading@10 397 }
yading@10 398
yading@10 399 } else {
yading@10 400 // vertical split?
yading@10 401 int vert;
yading@10 402 uint64_t flags = bytestream2_get_le64(&s->stream_ptr);
yading@10 403
yading@10 404 bytestream2_get_buffer(&s->stream_ptr, P + 4, 4);
yading@10 405 vert = P[4] <= P[5];
yading@10 406
yading@10 407 /* 4-color encoding for either left and right or top and bottom
yading@10 408 * halves */
yading@10 409
yading@10 410 for (y = 0; y < 16; y++) {
yading@10 411 for (x = 0; x < 4; x++, flags >>= 2)
yading@10 412 *s->pixel_ptr++ = P[flags & 0x03];
yading@10 413
yading@10 414 if (vert) {
yading@10 415 s->pixel_ptr += s->stride - 4;
yading@10 416 // switch to right half
yading@10 417 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
yading@10 418 } else if (y & 1) s->pixel_ptr += s->line_inc;
yading@10 419
yading@10 420 // load values for second half
yading@10 421 if (y == 7) {
yading@10 422 memcpy(P, P + 4, 4);
yading@10 423 flags = bytestream2_get_le64(&s->stream_ptr);
yading@10 424 }
yading@10 425 }
yading@10 426 }
yading@10 427
yading@10 428 /* report success */
yading@10 429 return 0;
yading@10 430 }
yading@10 431
yading@10 432 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s, AVFrame *frame)
yading@10 433 {
yading@10 434 int y;
yading@10 435
yading@10 436 /* 64-color encoding (each pixel in block is a different color) */
yading@10 437 for (y = 0; y < 8; y++) {
yading@10 438 bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8);
yading@10 439 s->pixel_ptr += s->stride;
yading@10 440 }
yading@10 441
yading@10 442 /* report success */
yading@10 443 return 0;
yading@10 444 }
yading@10 445
yading@10 446 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s, AVFrame *frame)
yading@10 447 {
yading@10 448 int x, y;
yading@10 449
yading@10 450 /* 16-color block encoding: each 2x2 block is a different color */
yading@10 451 for (y = 0; y < 8; y += 2) {
yading@10 452 for (x = 0; x < 8; x += 2) {
yading@10 453 s->pixel_ptr[x ] =
yading@10 454 s->pixel_ptr[x + 1 ] =
yading@10 455 s->pixel_ptr[x + s->stride] =
yading@10 456 s->pixel_ptr[x + 1 + s->stride] = bytestream2_get_byte(&s->stream_ptr);
yading@10 457 }
yading@10 458 s->pixel_ptr += s->stride * 2;
yading@10 459 }
yading@10 460
yading@10 461 /* report success */
yading@10 462 return 0;
yading@10 463 }
yading@10 464
yading@10 465 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s, AVFrame *frame)
yading@10 466 {
yading@10 467 int y;
yading@10 468 unsigned char P[2];
yading@10 469
yading@10 470 /* 4-color block encoding: each 4x4 block is a different color */
yading@10 471 for (y = 0; y < 8; y++) {
yading@10 472 if (!(y & 3)) {
yading@10 473 P[0] = bytestream2_get_byte(&s->stream_ptr);
yading@10 474 P[1] = bytestream2_get_byte(&s->stream_ptr);
yading@10 475 }
yading@10 476 memset(s->pixel_ptr, P[0], 4);
yading@10 477 memset(s->pixel_ptr + 4, P[1], 4);
yading@10 478 s->pixel_ptr += s->stride;
yading@10 479 }
yading@10 480
yading@10 481 /* report success */
yading@10 482 return 0;
yading@10 483 }
yading@10 484
yading@10 485 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s, AVFrame *frame)
yading@10 486 {
yading@10 487 int y;
yading@10 488 unsigned char pix;
yading@10 489
yading@10 490 /* 1-color encoding: the whole block is 1 solid color */
yading@10 491 pix = bytestream2_get_byte(&s->stream_ptr);
yading@10 492
yading@10 493 for (y = 0; y < 8; y++) {
yading@10 494 memset(s->pixel_ptr, pix, 8);
yading@10 495 s->pixel_ptr += s->stride;
yading@10 496 }
yading@10 497
yading@10 498 /* report success */
yading@10 499 return 0;
yading@10 500 }
yading@10 501
yading@10 502 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s, AVFrame *frame)
yading@10 503 {
yading@10 504 int x, y;
yading@10 505 unsigned char sample[2];
yading@10 506
yading@10 507 /* dithered encoding */
yading@10 508 sample[0] = bytestream2_get_byte(&s->stream_ptr);
yading@10 509 sample[1] = bytestream2_get_byte(&s->stream_ptr);
yading@10 510
yading@10 511 for (y = 0; y < 8; y++) {
yading@10 512 for (x = 0; x < 8; x += 2) {
yading@10 513 *s->pixel_ptr++ = sample[ y & 1 ];
yading@10 514 *s->pixel_ptr++ = sample[!(y & 1)];
yading@10 515 }
yading@10 516 s->pixel_ptr += s->line_inc;
yading@10 517 }
yading@10 518
yading@10 519 /* report success */
yading@10 520 return 0;
yading@10 521 }
yading@10 522
yading@10 523 static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s, AVFrame *frame)
yading@10 524 {
yading@10 525 signed char x, y;
yading@10 526
yading@10 527 /* copy a block from the second last frame using an expanded range */
yading@10 528 x = bytestream2_get_byte(&s->stream_ptr);
yading@10 529 y = bytestream2_get_byte(&s->stream_ptr);
yading@10 530
yading@10 531 av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y);
yading@10 532 return copy_from(s, s->second_last_frame, frame, x, y);
yading@10 533 }
yading@10 534
yading@10 535 static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s, AVFrame *frame)
yading@10 536 {
yading@10 537 int x, y;
yading@10 538 uint16_t P[2];
yading@10 539 unsigned int flags;
yading@10 540 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 541
yading@10 542 /* 2-color encoding */
yading@10 543 P[0] = bytestream2_get_le16(&s->stream_ptr);
yading@10 544 P[1] = bytestream2_get_le16(&s->stream_ptr);
yading@10 545
yading@10 546 if (!(P[0] & 0x8000)) {
yading@10 547
yading@10 548 for (y = 0; y < 8; y++) {
yading@10 549 flags = bytestream2_get_byte(&s->stream_ptr) | 0x100;
yading@10 550 for (; flags != 1; flags >>= 1)
yading@10 551 *pixel_ptr++ = P[flags & 1];
yading@10 552 pixel_ptr += s->line_inc;
yading@10 553 }
yading@10 554
yading@10 555 } else {
yading@10 556
yading@10 557 flags = bytestream2_get_le16(&s->stream_ptr);
yading@10 558 for (y = 0; y < 8; y += 2) {
yading@10 559 for (x = 0; x < 8; x += 2, flags >>= 1) {
yading@10 560 pixel_ptr[x ] =
yading@10 561 pixel_ptr[x + 1 ] =
yading@10 562 pixel_ptr[x + s->stride] =
yading@10 563 pixel_ptr[x + 1 + s->stride] = P[flags & 1];
yading@10 564 }
yading@10 565 pixel_ptr += s->stride * 2;
yading@10 566 }
yading@10 567 }
yading@10 568
yading@10 569 return 0;
yading@10 570 }
yading@10 571
yading@10 572 static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s, AVFrame *frame)
yading@10 573 {
yading@10 574 int x, y;
yading@10 575 uint16_t P[4];
yading@10 576 unsigned int flags = 0;
yading@10 577 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 578
yading@10 579 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
yading@10 580 * either top and bottom or left and right halves */
yading@10 581 P[0] = bytestream2_get_le16(&s->stream_ptr);
yading@10 582 P[1] = bytestream2_get_le16(&s->stream_ptr);
yading@10 583
yading@10 584 if (!(P[0] & 0x8000)) {
yading@10 585
yading@10 586 for (y = 0; y < 16; y++) {
yading@10 587 // new values for each 4x4 block
yading@10 588 if (!(y & 3)) {
yading@10 589 if (y) {
yading@10 590 P[0] = bytestream2_get_le16(&s->stream_ptr);
yading@10 591 P[1] = bytestream2_get_le16(&s->stream_ptr);
yading@10 592 }
yading@10 593 flags = bytestream2_get_le16(&s->stream_ptr);
yading@10 594 }
yading@10 595
yading@10 596 for (x = 0; x < 4; x++, flags >>= 1)
yading@10 597 *pixel_ptr++ = P[flags & 1];
yading@10 598 pixel_ptr += s->stride - 4;
yading@10 599 // switch to right half
yading@10 600 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
yading@10 601 }
yading@10 602
yading@10 603 } else {
yading@10 604
yading@10 605 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 606 P[2] = bytestream2_get_le16(&s->stream_ptr);
yading@10 607 P[3] = bytestream2_get_le16(&s->stream_ptr);
yading@10 608
yading@10 609 if (!(P[2] & 0x8000)) {
yading@10 610
yading@10 611 /* vertical split; left & right halves are 2-color encoded */
yading@10 612
yading@10 613 for (y = 0; y < 16; y++) {
yading@10 614 for (x = 0; x < 4; x++, flags >>= 1)
yading@10 615 *pixel_ptr++ = P[flags & 1];
yading@10 616 pixel_ptr += s->stride - 4;
yading@10 617 // switch to right half
yading@10 618 if (y == 7) {
yading@10 619 pixel_ptr -= 8 * s->stride - 4;
yading@10 620 P[0] = P[2];
yading@10 621 P[1] = P[3];
yading@10 622 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 623 }
yading@10 624 }
yading@10 625
yading@10 626 } else {
yading@10 627
yading@10 628 /* horizontal split; top & bottom halves are 2-color encoded */
yading@10 629
yading@10 630 for (y = 0; y < 8; y++) {
yading@10 631 if (y == 4) {
yading@10 632 P[0] = P[2];
yading@10 633 P[1] = P[3];
yading@10 634 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 635 }
yading@10 636
yading@10 637 for (x = 0; x < 8; x++, flags >>= 1)
yading@10 638 *pixel_ptr++ = P[flags & 1];
yading@10 639 pixel_ptr += s->line_inc;
yading@10 640 }
yading@10 641 }
yading@10 642 }
yading@10 643
yading@10 644 /* report success */
yading@10 645 return 0;
yading@10 646 }
yading@10 647
yading@10 648 static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s, AVFrame *frame)
yading@10 649 {
yading@10 650 int x, y;
yading@10 651 uint16_t P[4];
yading@10 652 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 653
yading@10 654 /* 4-color encoding */
yading@10 655 for (x = 0; x < 4; x++)
yading@10 656 P[x] = bytestream2_get_le16(&s->stream_ptr);
yading@10 657
yading@10 658 if (!(P[0] & 0x8000)) {
yading@10 659 if (!(P[2] & 0x8000)) {
yading@10 660
yading@10 661 /* 1 of 4 colors for each pixel */
yading@10 662 for (y = 0; y < 8; y++) {
yading@10 663 /* get the next set of 8 2-bit flags */
yading@10 664 int flags = bytestream2_get_le16(&s->stream_ptr);
yading@10 665 for (x = 0; x < 8; x++, flags >>= 2)
yading@10 666 *pixel_ptr++ = P[flags & 0x03];
yading@10 667 pixel_ptr += s->line_inc;
yading@10 668 }
yading@10 669
yading@10 670 } else {
yading@10 671 uint32_t flags;
yading@10 672
yading@10 673 /* 1 of 4 colors for each 2x2 block */
yading@10 674 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 675
yading@10 676 for (y = 0; y < 8; y += 2) {
yading@10 677 for (x = 0; x < 8; x += 2, flags >>= 2) {
yading@10 678 pixel_ptr[x ] =
yading@10 679 pixel_ptr[x + 1 ] =
yading@10 680 pixel_ptr[x + s->stride] =
yading@10 681 pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
yading@10 682 }
yading@10 683 pixel_ptr += s->stride * 2;
yading@10 684 }
yading@10 685
yading@10 686 }
yading@10 687 } else {
yading@10 688 uint64_t flags;
yading@10 689
yading@10 690 /* 1 of 4 colors for each 2x1 or 1x2 block */
yading@10 691 flags = bytestream2_get_le64(&s->stream_ptr);
yading@10 692 if (!(P[2] & 0x8000)) {
yading@10 693 for (y = 0; y < 8; y++) {
yading@10 694 for (x = 0; x < 8; x += 2, flags >>= 2) {
yading@10 695 pixel_ptr[x ] =
yading@10 696 pixel_ptr[x + 1] = P[flags & 0x03];
yading@10 697 }
yading@10 698 pixel_ptr += s->stride;
yading@10 699 }
yading@10 700 } else {
yading@10 701 for (y = 0; y < 8; y += 2) {
yading@10 702 for (x = 0; x < 8; x++, flags >>= 2) {
yading@10 703 pixel_ptr[x ] =
yading@10 704 pixel_ptr[x + s->stride] = P[flags & 0x03];
yading@10 705 }
yading@10 706 pixel_ptr += s->stride * 2;
yading@10 707 }
yading@10 708 }
yading@10 709 }
yading@10 710
yading@10 711 /* report success */
yading@10 712 return 0;
yading@10 713 }
yading@10 714
yading@10 715 static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s, AVFrame *frame)
yading@10 716 {
yading@10 717 int x, y;
yading@10 718 uint16_t P[8];
yading@10 719 int flags = 0;
yading@10 720 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 721
yading@10 722 for (x = 0; x < 4; x++)
yading@10 723 P[x] = bytestream2_get_le16(&s->stream_ptr);
yading@10 724
yading@10 725 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
yading@10 726 * either top and bottom or left and right halves */
yading@10 727 if (!(P[0] & 0x8000)) {
yading@10 728
yading@10 729 /* 4-color encoding for each quadrant */
yading@10 730 for (y = 0; y < 16; y++) {
yading@10 731 // new values for each 4x4 block
yading@10 732 if (!(y & 3)) {
yading@10 733 if (y)
yading@10 734 for (x = 0; x < 4; x++)
yading@10 735 P[x] = bytestream2_get_le16(&s->stream_ptr);
yading@10 736 flags = bytestream2_get_le32(&s->stream_ptr);
yading@10 737 }
yading@10 738
yading@10 739 for (x = 0; x < 4; x++, flags >>= 2)
yading@10 740 *pixel_ptr++ = P[flags & 0x03];
yading@10 741
yading@10 742 pixel_ptr += s->stride - 4;
yading@10 743 // switch to right half
yading@10 744 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
yading@10 745 }
yading@10 746
yading@10 747 } else {
yading@10 748 // vertical split?
yading@10 749 int vert;
yading@10 750 uint64_t flags = bytestream2_get_le64(&s->stream_ptr);
yading@10 751
yading@10 752 for (x = 4; x < 8; x++)
yading@10 753 P[x] = bytestream2_get_le16(&s->stream_ptr);
yading@10 754 vert = !(P[4] & 0x8000);
yading@10 755
yading@10 756 /* 4-color encoding for either left and right or top and bottom
yading@10 757 * halves */
yading@10 758
yading@10 759 for (y = 0; y < 16; y++) {
yading@10 760 for (x = 0; x < 4; x++, flags >>= 2)
yading@10 761 *pixel_ptr++ = P[flags & 0x03];
yading@10 762
yading@10 763 if (vert) {
yading@10 764 pixel_ptr += s->stride - 4;
yading@10 765 // switch to right half
yading@10 766 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
yading@10 767 } else if (y & 1) pixel_ptr += s->line_inc;
yading@10 768
yading@10 769 // load values for second half
yading@10 770 if (y == 7) {
yading@10 771 memcpy(P, P + 4, 8);
yading@10 772 flags = bytestream2_get_le64(&s->stream_ptr);
yading@10 773 }
yading@10 774 }
yading@10 775 }
yading@10 776
yading@10 777 /* report success */
yading@10 778 return 0;
yading@10 779 }
yading@10 780
yading@10 781 static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s, AVFrame *frame)
yading@10 782 {
yading@10 783 int x, y;
yading@10 784 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 785
yading@10 786 /* 64-color encoding (each pixel in block is a different color) */
yading@10 787 for (y = 0; y < 8; y++) {
yading@10 788 for (x = 0; x < 8; x++)
yading@10 789 pixel_ptr[x] = bytestream2_get_le16(&s->stream_ptr);
yading@10 790 pixel_ptr += s->stride;
yading@10 791 }
yading@10 792
yading@10 793 /* report success */
yading@10 794 return 0;
yading@10 795 }
yading@10 796
yading@10 797 static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s, AVFrame *frame)
yading@10 798 {
yading@10 799 int x, y;
yading@10 800 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 801
yading@10 802 /* 16-color block encoding: each 2x2 block is a different color */
yading@10 803 for (y = 0; y < 8; y += 2) {
yading@10 804 for (x = 0; x < 8; x += 2) {
yading@10 805 pixel_ptr[x ] =
yading@10 806 pixel_ptr[x + 1 ] =
yading@10 807 pixel_ptr[x + s->stride] =
yading@10 808 pixel_ptr[x + 1 + s->stride] = bytestream2_get_le16(&s->stream_ptr);
yading@10 809 }
yading@10 810 pixel_ptr += s->stride * 2;
yading@10 811 }
yading@10 812
yading@10 813 /* report success */
yading@10 814 return 0;
yading@10 815 }
yading@10 816
yading@10 817 static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s, AVFrame *frame)
yading@10 818 {
yading@10 819 int x, y;
yading@10 820 uint16_t P[2];
yading@10 821 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 822
yading@10 823 /* 4-color block encoding: each 4x4 block is a different color */
yading@10 824 for (y = 0; y < 8; y++) {
yading@10 825 if (!(y & 3)) {
yading@10 826 P[0] = bytestream2_get_le16(&s->stream_ptr);
yading@10 827 P[1] = bytestream2_get_le16(&s->stream_ptr);
yading@10 828 }
yading@10 829 for (x = 0; x < 8; x++)
yading@10 830 pixel_ptr[x] = P[x >> 2];
yading@10 831 pixel_ptr += s->stride;
yading@10 832 }
yading@10 833
yading@10 834 /* report success */
yading@10 835 return 0;
yading@10 836 }
yading@10 837
yading@10 838 static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s, AVFrame *frame)
yading@10 839 {
yading@10 840 int x, y;
yading@10 841 uint16_t pix;
yading@10 842 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
yading@10 843
yading@10 844 /* 1-color encoding: the whole block is 1 solid color */
yading@10 845 pix = bytestream2_get_le16(&s->stream_ptr);
yading@10 846
yading@10 847 for (y = 0; y < 8; y++) {
yading@10 848 for (x = 0; x < 8; x++)
yading@10 849 pixel_ptr[x] = pix;
yading@10 850 pixel_ptr += s->stride;
yading@10 851 }
yading@10 852
yading@10 853 /* report success */
yading@10 854 return 0;
yading@10 855 }
yading@10 856
yading@10 857 static int (* const ipvideo_decode_block[])(IpvideoContext *s, AVFrame *frame) = {
yading@10 858 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
yading@10 859 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
yading@10 860 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
yading@10 861 ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
yading@10 862 ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9,
yading@10 863 ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
yading@10 864 ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
yading@10 865 ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
yading@10 866 };
yading@10 867
yading@10 868 static int (* const ipvideo_decode_block16[])(IpvideoContext *s, AVFrame *frame) = {
yading@10 869 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
yading@10 870 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
yading@10 871 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
yading@10 872 ipvideo_decode_block_opcode_0x6_16, ipvideo_decode_block_opcode_0x7_16,
yading@10 873 ipvideo_decode_block_opcode_0x8_16, ipvideo_decode_block_opcode_0x9_16,
yading@10 874 ipvideo_decode_block_opcode_0xA_16, ipvideo_decode_block_opcode_0xB_16,
yading@10 875 ipvideo_decode_block_opcode_0xC_16, ipvideo_decode_block_opcode_0xD_16,
yading@10 876 ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1,
yading@10 877 };
yading@10 878
yading@10 879 static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame)
yading@10 880 {
yading@10 881 int x, y;
yading@10 882 unsigned char opcode;
yading@10 883 int ret;
yading@10 884 GetBitContext gb;
yading@10 885
yading@10 886 bytestream2_skip(&s->stream_ptr, 14); /* data starts 14 bytes in */
yading@10 887 if (!s->is_16bpp) {
yading@10 888 /* this is PAL8, so make the palette available */
yading@10 889 memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
yading@10 890
yading@10 891 s->stride = frame->linesize[0];
yading@10 892 } else {
yading@10 893 s->stride = frame->linesize[0] >> 1;
yading@10 894 s->mv_ptr = s->stream_ptr;
yading@10 895 bytestream2_skip(&s->mv_ptr, bytestream2_get_le16(&s->stream_ptr));
yading@10 896 }
yading@10 897 s->line_inc = s->stride - 8;
yading@10 898 s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0]
yading@10 899 + (s->avctx->width - 8) * (1 + s->is_16bpp);
yading@10 900
yading@10 901 init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8);
yading@10 902 for (y = 0; y < s->avctx->height; y += 8) {
yading@10 903 for (x = 0; x < s->avctx->width; x += 8) {
yading@10 904 opcode = get_bits(&gb, 4);
yading@10 905
yading@10 906 av_dlog(s->avctx,
yading@10 907 " block @ (%3d, %3d): encoding 0x%X, data ptr offset %d\n",
yading@10 908 x, y, opcode, bytestream2_tell(&s->stream_ptr));
yading@10 909
yading@10 910 if (!s->is_16bpp) {
yading@10 911 s->pixel_ptr = frame->data[0] + x
yading@10 912 + y*frame->linesize[0];
yading@10 913 ret = ipvideo_decode_block[opcode](s, frame);
yading@10 914 } else {
yading@10 915 s->pixel_ptr = frame->data[0] + x*2
yading@10 916 + y*frame->linesize[0];
yading@10 917 ret = ipvideo_decode_block16[opcode](s, frame);
yading@10 918 }
yading@10 919 if (ret != 0) {
yading@10 920 av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n",
yading@10 921 s->avctx->frame_number, x, y);
yading@10 922 return;
yading@10 923 }
yading@10 924 }
yading@10 925 }
yading@10 926 if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) {
yading@10 927 av_log(s->avctx, AV_LOG_ERROR,
yading@10 928 "decode finished with %d bytes left over\n",
yading@10 929 bytestream2_get_bytes_left(&s->stream_ptr));
yading@10 930 }
yading@10 931 }
yading@10 932
yading@10 933 static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
yading@10 934 {
yading@10 935 IpvideoContext *s = avctx->priv_data;
yading@10 936
yading@10 937 s->avctx = avctx;
yading@10 938
yading@10 939 s->is_16bpp = avctx->bits_per_coded_sample == 16;
yading@10 940 avctx->pix_fmt = s->is_16bpp ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_PAL8;
yading@10 941
yading@10 942 ff_hpeldsp_init(&s->hdsp, avctx->flags);
yading@10 943
yading@10 944 s->last_frame = av_frame_alloc();
yading@10 945 s->second_last_frame = av_frame_alloc();
yading@10 946 if (!s->last_frame || !s->second_last_frame) {
yading@10 947 av_frame_free(&s->last_frame);
yading@10 948 av_frame_free(&s->second_last_frame);
yading@10 949 return AVERROR(ENOMEM);
yading@10 950 }
yading@10 951
yading@10 952 return 0;
yading@10 953 }
yading@10 954
yading@10 955 static int ipvideo_decode_frame(AVCodecContext *avctx,
yading@10 956 void *data, int *got_frame,
yading@10 957 AVPacket *avpkt)
yading@10 958 {
yading@10 959 const uint8_t *buf = avpkt->data;
yading@10 960 int buf_size = avpkt->size;
yading@10 961 IpvideoContext *s = avctx->priv_data;
yading@10 962 AVFrame *frame = data;
yading@10 963 int ret;
yading@10 964
yading@10 965 /* decoding map contains 4 bits of information per 8x8 block */
yading@10 966 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
yading@10 967
yading@10 968 /* compressed buffer needs to be large enough to at least hold an entire
yading@10 969 * decoding map */
yading@10 970 if (buf_size < s->decoding_map_size)
yading@10 971 return buf_size;
yading@10 972
yading@10 973 if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
yading@10 974 av_frame_unref(s->last_frame);
yading@10 975 av_frame_unref(s->second_last_frame);
yading@10 976 }
yading@10 977
yading@10 978 s->decoding_map = buf;
yading@10 979 bytestream2_init(&s->stream_ptr, buf + s->decoding_map_size,
yading@10 980 buf_size - s->decoding_map_size);
yading@10 981
yading@10 982 if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
yading@10 983 return ret;
yading@10 984
yading@10 985 if (!s->is_16bpp) {
yading@10 986 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
yading@10 987 if (pal) {
yading@10 988 frame->palette_has_changed = 1;
yading@10 989 memcpy(s->pal, pal, AVPALETTE_SIZE);
yading@10 990 }
yading@10 991 }
yading@10 992
yading@10 993 ipvideo_decode_opcodes(s, frame);
yading@10 994
yading@10 995 *got_frame = 1;
yading@10 996
yading@10 997 /* shuffle frames */
yading@10 998 av_frame_unref(s->second_last_frame);
yading@10 999 FFSWAP(AVFrame*, s->second_last_frame, s->last_frame);
yading@10 1000 if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
yading@10 1001 return ret;
yading@10 1002
yading@10 1003 /* report that the buffer was completely consumed */
yading@10 1004 return buf_size;
yading@10 1005 }
yading@10 1006
yading@10 1007 static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
yading@10 1008 {
yading@10 1009 IpvideoContext *s = avctx->priv_data;
yading@10 1010
yading@10 1011 av_frame_free(&s->last_frame);
yading@10 1012 av_frame_free(&s->second_last_frame);
yading@10 1013
yading@10 1014 return 0;
yading@10 1015 }
yading@10 1016
yading@10 1017 AVCodec ff_interplay_video_decoder = {
yading@10 1018 .name = "interplayvideo",
yading@10 1019 .type = AVMEDIA_TYPE_VIDEO,
yading@10 1020 .id = AV_CODEC_ID_INTERPLAY_VIDEO,
yading@10 1021 .priv_data_size = sizeof(IpvideoContext),
yading@10 1022 .init = ipvideo_decode_init,
yading@10 1023 .close = ipvideo_decode_end,
yading@10 1024 .decode = ipvideo_decode_frame,
yading@10 1025 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE,
yading@10 1026 .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
yading@10 1027 };