annotate ffmpeg/libavcodec/utvideodec.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 * Ut Video decoder
yading@10 3 * Copyright (c) 2011 Konstantin Shishkov
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 * Ut Video decoder
yading@10 25 */
yading@10 26
yading@10 27 #include <stdlib.h>
yading@10 28
yading@10 29 #include "libavutil/intreadwrite.h"
yading@10 30 #include "avcodec.h"
yading@10 31 #include "bytestream.h"
yading@10 32 #include "get_bits.h"
yading@10 33 #include "dsputil.h"
yading@10 34 #include "thread.h"
yading@10 35 #include "utvideo.h"
yading@10 36
yading@10 37 static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
yading@10 38 {
yading@10 39 int i;
yading@10 40 HuffEntry he[256];
yading@10 41 int last;
yading@10 42 uint32_t codes[256];
yading@10 43 uint8_t bits[256];
yading@10 44 uint8_t syms[256];
yading@10 45 uint32_t code;
yading@10 46
yading@10 47 *fsym = -1;
yading@10 48 for (i = 0; i < 256; i++) {
yading@10 49 he[i].sym = i;
yading@10 50 he[i].len = *src++;
yading@10 51 }
yading@10 52 qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len);
yading@10 53
yading@10 54 if (!he[0].len) {
yading@10 55 *fsym = he[0].sym;
yading@10 56 return 0;
yading@10 57 }
yading@10 58 if (he[0].len > 32)
yading@10 59 return -1;
yading@10 60
yading@10 61 last = 255;
yading@10 62 while (he[last].len == 255 && last)
yading@10 63 last--;
yading@10 64
yading@10 65 code = 1;
yading@10 66 for (i = last; i >= 0; i--) {
yading@10 67 codes[i] = code >> (32 - he[i].len);
yading@10 68 bits[i] = he[i].len;
yading@10 69 syms[i] = he[i].sym;
yading@10 70 code += 0x80000000u >> (he[i].len - 1);
yading@10 71 }
yading@10 72
yading@10 73 return ff_init_vlc_sparse(vlc, FFMIN(he[last].len, 9), last + 1,
yading@10 74 bits, sizeof(*bits), sizeof(*bits),
yading@10 75 codes, sizeof(*codes), sizeof(*codes),
yading@10 76 syms, sizeof(*syms), sizeof(*syms), 0);
yading@10 77 }
yading@10 78
yading@10 79 static int decode_plane(UtvideoContext *c, int plane_no,
yading@10 80 uint8_t *dst, int step, int stride,
yading@10 81 int width, int height,
yading@10 82 const uint8_t *src, int use_pred)
yading@10 83 {
yading@10 84 int i, j, slice, pix;
yading@10 85 int sstart, send;
yading@10 86 VLC vlc;
yading@10 87 GetBitContext gb;
yading@10 88 int prev, fsym;
yading@10 89 const int cmask = ~(!plane_no && c->avctx->pix_fmt == AV_PIX_FMT_YUV420P);
yading@10 90
yading@10 91 if (build_huff(src, &vlc, &fsym)) {
yading@10 92 av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
yading@10 93 return AVERROR_INVALIDDATA;
yading@10 94 }
yading@10 95 if (fsym >= 0) { // build_huff reported a symbol to fill slices with
yading@10 96 send = 0;
yading@10 97 for (slice = 0; slice < c->slices; slice++) {
yading@10 98 uint8_t *dest;
yading@10 99
yading@10 100 sstart = send;
yading@10 101 send = (height * (slice + 1) / c->slices) & cmask;
yading@10 102 dest = dst + sstart * stride;
yading@10 103
yading@10 104 prev = 0x80;
yading@10 105 for (j = sstart; j < send; j++) {
yading@10 106 for (i = 0; i < width * step; i += step) {
yading@10 107 pix = fsym;
yading@10 108 if (use_pred) {
yading@10 109 prev += pix;
yading@10 110 pix = prev;
yading@10 111 }
yading@10 112 dest[i] = pix;
yading@10 113 }
yading@10 114 dest += stride;
yading@10 115 }
yading@10 116 }
yading@10 117 return 0;
yading@10 118 }
yading@10 119
yading@10 120 src += 256;
yading@10 121
yading@10 122 send = 0;
yading@10 123 for (slice = 0; slice < c->slices; slice++) {
yading@10 124 uint8_t *dest;
yading@10 125 int slice_data_start, slice_data_end, slice_size;
yading@10 126
yading@10 127 sstart = send;
yading@10 128 send = (height * (slice + 1) / c->slices) & cmask;
yading@10 129 dest = dst + sstart * stride;
yading@10 130
yading@10 131 // slice offset and size validation was done earlier
yading@10 132 slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;
yading@10 133 slice_data_end = AV_RL32(src + slice * 4);
yading@10 134 slice_size = slice_data_end - slice_data_start;
yading@10 135
yading@10 136 if (!slice_size) {
yading@10 137 av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "
yading@10 138 "yet a slice has a length of zero.\n");
yading@10 139 goto fail;
yading@10 140 }
yading@10 141
yading@10 142 memcpy(c->slice_bits, src + slice_data_start + c->slices * 4,
yading@10 143 slice_size);
yading@10 144 memset(c->slice_bits + slice_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
yading@10 145 c->dsp.bswap_buf((uint32_t *) c->slice_bits, (uint32_t *) c->slice_bits,
yading@10 146 (slice_data_end - slice_data_start + 3) >> 2);
yading@10 147 init_get_bits(&gb, c->slice_bits, slice_size * 8);
yading@10 148
yading@10 149 prev = 0x80;
yading@10 150 for (j = sstart; j < send; j++) {
yading@10 151 for (i = 0; i < width * step; i += step) {
yading@10 152 if (get_bits_left(&gb) <= 0) {
yading@10 153 av_log(c->avctx, AV_LOG_ERROR,
yading@10 154 "Slice decoding ran out of bits\n");
yading@10 155 goto fail;
yading@10 156 }
yading@10 157 pix = get_vlc2(&gb, vlc.table, vlc.bits, 4);
yading@10 158 if (pix < 0) {
yading@10 159 av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
yading@10 160 goto fail;
yading@10 161 }
yading@10 162 if (use_pred) {
yading@10 163 prev += pix;
yading@10 164 pix = prev;
yading@10 165 }
yading@10 166 dest[i] = pix;
yading@10 167 }
yading@10 168 dest += stride;
yading@10 169 }
yading@10 170 if (get_bits_left(&gb) > 32)
yading@10 171 av_log(c->avctx, AV_LOG_WARNING,
yading@10 172 "%d bits left after decoding slice\n", get_bits_left(&gb));
yading@10 173 }
yading@10 174
yading@10 175 ff_free_vlc(&vlc);
yading@10 176
yading@10 177 return 0;
yading@10 178 fail:
yading@10 179 ff_free_vlc(&vlc);
yading@10 180 return AVERROR_INVALIDDATA;
yading@10 181 }
yading@10 182
yading@10 183 static void restore_rgb_planes(uint8_t *src, int step, int stride, int width,
yading@10 184 int height)
yading@10 185 {
yading@10 186 int i, j;
yading@10 187 uint8_t r, g, b;
yading@10 188
yading@10 189 for (j = 0; j < height; j++) {
yading@10 190 for (i = 0; i < width * step; i += step) {
yading@10 191 r = src[i];
yading@10 192 g = src[i + 1];
yading@10 193 b = src[i + 2];
yading@10 194 src[i] = r + g - 0x80;
yading@10 195 src[i + 2] = b + g - 0x80;
yading@10 196 }
yading@10 197 src += stride;
yading@10 198 }
yading@10 199 }
yading@10 200
yading@10 201 static void restore_median(uint8_t *src, int step, int stride,
yading@10 202 int width, int height, int slices, int rmode)
yading@10 203 {
yading@10 204 int i, j, slice;
yading@10 205 int A, B, C;
yading@10 206 uint8_t *bsrc;
yading@10 207 int slice_start, slice_height;
yading@10 208 const int cmask = ~rmode;
yading@10 209
yading@10 210 for (slice = 0; slice < slices; slice++) {
yading@10 211 slice_start = ((slice * height) / slices) & cmask;
yading@10 212 slice_height = ((((slice + 1) * height) / slices) & cmask) -
yading@10 213 slice_start;
yading@10 214
yading@10 215 bsrc = src + slice_start * stride;
yading@10 216
yading@10 217 // first line - left neighbour prediction
yading@10 218 bsrc[0] += 0x80;
yading@10 219 A = bsrc[0];
yading@10 220 for (i = step; i < width * step; i += step) {
yading@10 221 bsrc[i] += A;
yading@10 222 A = bsrc[i];
yading@10 223 }
yading@10 224 bsrc += stride;
yading@10 225 if (slice_height == 1)
yading@10 226 continue;
yading@10 227 // second line - first element has top prediction, the rest uses median
yading@10 228 C = bsrc[-stride];
yading@10 229 bsrc[0] += C;
yading@10 230 A = bsrc[0];
yading@10 231 for (i = step; i < width * step; i += step) {
yading@10 232 B = bsrc[i - stride];
yading@10 233 bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
yading@10 234 C = B;
yading@10 235 A = bsrc[i];
yading@10 236 }
yading@10 237 bsrc += stride;
yading@10 238 // the rest of lines use continuous median prediction
yading@10 239 for (j = 2; j < slice_height; j++) {
yading@10 240 for (i = 0; i < width * step; i += step) {
yading@10 241 B = bsrc[i - stride];
yading@10 242 bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
yading@10 243 C = B;
yading@10 244 A = bsrc[i];
yading@10 245 }
yading@10 246 bsrc += stride;
yading@10 247 }
yading@10 248 }
yading@10 249 }
yading@10 250
yading@10 251 /* UtVideo interlaced mode treats every two lines as a single one,
yading@10 252 * so restoring function should take care of possible padding between
yading@10 253 * two parts of the same "line".
yading@10 254 */
yading@10 255 static void restore_median_il(uint8_t *src, int step, int stride,
yading@10 256 int width, int height, int slices, int rmode)
yading@10 257 {
yading@10 258 int i, j, slice;
yading@10 259 int A, B, C;
yading@10 260 uint8_t *bsrc;
yading@10 261 int slice_start, slice_height;
yading@10 262 const int cmask = ~(rmode ? 3 : 1);
yading@10 263 const int stride2 = stride << 1;
yading@10 264
yading@10 265 for (slice = 0; slice < slices; slice++) {
yading@10 266 slice_start = ((slice * height) / slices) & cmask;
yading@10 267 slice_height = ((((slice + 1) * height) / slices) & cmask) -
yading@10 268 slice_start;
yading@10 269 slice_height >>= 1;
yading@10 270
yading@10 271 bsrc = src + slice_start * stride;
yading@10 272
yading@10 273 // first line - left neighbour prediction
yading@10 274 bsrc[0] += 0x80;
yading@10 275 A = bsrc[0];
yading@10 276 for (i = step; i < width * step; i += step) {
yading@10 277 bsrc[i] += A;
yading@10 278 A = bsrc[i];
yading@10 279 }
yading@10 280 for (i = 0; i < width * step; i += step) {
yading@10 281 bsrc[stride + i] += A;
yading@10 282 A = bsrc[stride + i];
yading@10 283 }
yading@10 284 bsrc += stride2;
yading@10 285 if (slice_height == 1)
yading@10 286 continue;
yading@10 287 // second line - first element has top prediction, the rest uses median
yading@10 288 C = bsrc[-stride2];
yading@10 289 bsrc[0] += C;
yading@10 290 A = bsrc[0];
yading@10 291 for (i = step; i < width * step; i += step) {
yading@10 292 B = bsrc[i - stride2];
yading@10 293 bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
yading@10 294 C = B;
yading@10 295 A = bsrc[i];
yading@10 296 }
yading@10 297 for (i = 0; i < width * step; i += step) {
yading@10 298 B = bsrc[i - stride];
yading@10 299 bsrc[stride + i] += mid_pred(A, B, (uint8_t)(A + B - C));
yading@10 300 C = B;
yading@10 301 A = bsrc[stride + i];
yading@10 302 }
yading@10 303 bsrc += stride2;
yading@10 304 // the rest of lines use continuous median prediction
yading@10 305 for (j = 2; j < slice_height; j++) {
yading@10 306 for (i = 0; i < width * step; i += step) {
yading@10 307 B = bsrc[i - stride2];
yading@10 308 bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
yading@10 309 C = B;
yading@10 310 A = bsrc[i];
yading@10 311 }
yading@10 312 for (i = 0; i < width * step; i += step) {
yading@10 313 B = bsrc[i - stride];
yading@10 314 bsrc[i + stride] += mid_pred(A, B, (uint8_t)(A + B - C));
yading@10 315 C = B;
yading@10 316 A = bsrc[i + stride];
yading@10 317 }
yading@10 318 bsrc += stride2;
yading@10 319 }
yading@10 320 }
yading@10 321 }
yading@10 322
yading@10 323 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
yading@10 324 AVPacket *avpkt)
yading@10 325 {
yading@10 326 const uint8_t *buf = avpkt->data;
yading@10 327 int buf_size = avpkt->size;
yading@10 328 UtvideoContext *c = avctx->priv_data;
yading@10 329 int i, j;
yading@10 330 const uint8_t *plane_start[5];
yading@10 331 int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size;
yading@10 332 int ret;
yading@10 333 GetByteContext gb;
yading@10 334 ThreadFrame frame = { .f = data };
yading@10 335
yading@10 336 if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
yading@10 337 return ret;
yading@10 338
yading@10 339 /* parse plane structure to get frame flags and validate slice offsets */
yading@10 340 bytestream2_init(&gb, buf, buf_size);
yading@10 341 for (i = 0; i < c->planes; i++) {
yading@10 342 plane_start[i] = gb.buffer;
yading@10 343 if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) {
yading@10 344 av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
yading@10 345 return AVERROR_INVALIDDATA;
yading@10 346 }
yading@10 347 bytestream2_skipu(&gb, 256);
yading@10 348 slice_start = 0;
yading@10 349 slice_end = 0;
yading@10 350 for (j = 0; j < c->slices; j++) {
yading@10 351 slice_end = bytestream2_get_le32u(&gb);
yading@10 352 slice_size = slice_end - slice_start;
yading@10 353 if (slice_end < 0 || slice_size < 0 ||
yading@10 354 bytestream2_get_bytes_left(&gb) < slice_end) {
yading@10 355 av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
yading@10 356 return AVERROR_INVALIDDATA;
yading@10 357 }
yading@10 358 slice_start = slice_end;
yading@10 359 max_slice_size = FFMAX(max_slice_size, slice_size);
yading@10 360 }
yading@10 361 plane_size = slice_end;
yading@10 362 bytestream2_skipu(&gb, plane_size);
yading@10 363 }
yading@10 364 plane_start[c->planes] = gb.buffer;
yading@10 365 if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
yading@10 366 av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
yading@10 367 return AVERROR_INVALIDDATA;
yading@10 368 }
yading@10 369 c->frame_info = bytestream2_get_le32u(&gb);
yading@10 370 av_log(avctx, AV_LOG_DEBUG, "frame information flags %X\n", c->frame_info);
yading@10 371
yading@10 372 c->frame_pred = (c->frame_info >> 8) & 3;
yading@10 373
yading@10 374 if (c->frame_pred == PRED_GRADIENT) {
yading@10 375 avpriv_request_sample(avctx, "Frame with gradient prediction");
yading@10 376 return AVERROR_PATCHWELCOME;
yading@10 377 }
yading@10 378
yading@10 379 av_fast_malloc(&c->slice_bits, &c->slice_bits_size,
yading@10 380 max_slice_size + FF_INPUT_BUFFER_PADDING_SIZE);
yading@10 381
yading@10 382 if (!c->slice_bits) {
yading@10 383 av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n");
yading@10 384 return AVERROR(ENOMEM);
yading@10 385 }
yading@10 386
yading@10 387 switch (c->avctx->pix_fmt) {
yading@10 388 case AV_PIX_FMT_RGB24:
yading@10 389 case AV_PIX_FMT_RGBA:
yading@10 390 for (i = 0; i < c->planes; i++) {
yading@10 391 ret = decode_plane(c, i, frame.f->data[0] + ff_ut_rgb_order[i],
yading@10 392 c->planes, frame.f->linesize[0], avctx->width,
yading@10 393 avctx->height, plane_start[i],
yading@10 394 c->frame_pred == PRED_LEFT);
yading@10 395 if (ret)
yading@10 396 return ret;
yading@10 397 if (c->frame_pred == PRED_MEDIAN) {
yading@10 398 if (!c->interlaced) {
yading@10 399 restore_median(frame.f->data[0] + ff_ut_rgb_order[i],
yading@10 400 c->planes, frame.f->linesize[0], avctx->width,
yading@10 401 avctx->height, c->slices, 0);
yading@10 402 } else {
yading@10 403 restore_median_il(frame.f->data[0] + ff_ut_rgb_order[i],
yading@10 404 c->planes, frame.f->linesize[0],
yading@10 405 avctx->width, avctx->height, c->slices,
yading@10 406 0);
yading@10 407 }
yading@10 408 }
yading@10 409 }
yading@10 410 restore_rgb_planes(frame.f->data[0], c->planes, frame.f->linesize[0],
yading@10 411 avctx->width, avctx->height);
yading@10 412 break;
yading@10 413 case AV_PIX_FMT_YUV420P:
yading@10 414 for (i = 0; i < 3; i++) {
yading@10 415 ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i],
yading@10 416 avctx->width >> !!i, avctx->height >> !!i,
yading@10 417 plane_start[i], c->frame_pred == PRED_LEFT);
yading@10 418 if (ret)
yading@10 419 return ret;
yading@10 420 if (c->frame_pred == PRED_MEDIAN) {
yading@10 421 if (!c->interlaced) {
yading@10 422 restore_median(frame.f->data[i], 1, frame.f->linesize[i],
yading@10 423 avctx->width >> !!i, avctx->height >> !!i,
yading@10 424 c->slices, !i);
yading@10 425 } else {
yading@10 426 restore_median_il(frame.f->data[i], 1, frame.f->linesize[i],
yading@10 427 avctx->width >> !!i,
yading@10 428 avctx->height >> !!i,
yading@10 429 c->slices, !i);
yading@10 430 }
yading@10 431 }
yading@10 432 }
yading@10 433 break;
yading@10 434 case AV_PIX_FMT_YUV422P:
yading@10 435 for (i = 0; i < 3; i++) {
yading@10 436 ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i],
yading@10 437 avctx->width >> !!i, avctx->height,
yading@10 438 plane_start[i], c->frame_pred == PRED_LEFT);
yading@10 439 if (ret)
yading@10 440 return ret;
yading@10 441 if (c->frame_pred == PRED_MEDIAN) {
yading@10 442 if (!c->interlaced) {
yading@10 443 restore_median(frame.f->data[i], 1, frame.f->linesize[i],
yading@10 444 avctx->width >> !!i, avctx->height,
yading@10 445 c->slices, 0);
yading@10 446 } else {
yading@10 447 restore_median_il(frame.f->data[i], 1, frame.f->linesize[i],
yading@10 448 avctx->width >> !!i, avctx->height,
yading@10 449 c->slices, 0);
yading@10 450 }
yading@10 451 }
yading@10 452 }
yading@10 453 break;
yading@10 454 }
yading@10 455
yading@10 456 frame.f->key_frame = 1;
yading@10 457 frame.f->pict_type = AV_PICTURE_TYPE_I;
yading@10 458 frame.f->interlaced_frame = !!c->interlaced;
yading@10 459
yading@10 460 *got_frame = 1;
yading@10 461
yading@10 462 /* always report that the buffer was completely consumed */
yading@10 463 return buf_size;
yading@10 464 }
yading@10 465
yading@10 466 static av_cold int decode_init(AVCodecContext *avctx)
yading@10 467 {
yading@10 468 UtvideoContext * const c = avctx->priv_data;
yading@10 469
yading@10 470 c->avctx = avctx;
yading@10 471
yading@10 472 ff_dsputil_init(&c->dsp, avctx);
yading@10 473
yading@10 474 if (avctx->extradata_size < 16) {
yading@10 475 av_log(avctx, AV_LOG_ERROR,
yading@10 476 "Insufficient extradata size %d, should be at least 16\n",
yading@10 477 avctx->extradata_size);
yading@10 478 return AVERROR_INVALIDDATA;
yading@10 479 }
yading@10 480
yading@10 481 av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
yading@10 482 avctx->extradata[3], avctx->extradata[2],
yading@10 483 avctx->extradata[1], avctx->extradata[0]);
yading@10 484 av_log(avctx, AV_LOG_DEBUG, "Original format %X\n",
yading@10 485 AV_RB32(avctx->extradata + 4));
yading@10 486 c->frame_info_size = AV_RL32(avctx->extradata + 8);
yading@10 487 c->flags = AV_RL32(avctx->extradata + 12);
yading@10 488
yading@10 489 if (c->frame_info_size != 4)
yading@10 490 avpriv_request_sample(avctx, "Frame info not 4 bytes");
yading@10 491 av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08X\n", c->flags);
yading@10 492 c->slices = (c->flags >> 24) + 1;
yading@10 493 c->compression = c->flags & 1;
yading@10 494 c->interlaced = c->flags & 0x800;
yading@10 495
yading@10 496 c->slice_bits_size = 0;
yading@10 497
yading@10 498 switch (avctx->codec_tag) {
yading@10 499 case MKTAG('U', 'L', 'R', 'G'):
yading@10 500 c->planes = 3;
yading@10 501 avctx->pix_fmt = AV_PIX_FMT_RGB24;
yading@10 502 break;
yading@10 503 case MKTAG('U', 'L', 'R', 'A'):
yading@10 504 c->planes = 4;
yading@10 505 avctx->pix_fmt = AV_PIX_FMT_RGBA;
yading@10 506 break;
yading@10 507 case MKTAG('U', 'L', 'Y', '0'):
yading@10 508 c->planes = 3;
yading@10 509 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
yading@10 510 break;
yading@10 511 case MKTAG('U', 'L', 'Y', '2'):
yading@10 512 c->planes = 3;
yading@10 513 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
yading@10 514 break;
yading@10 515 default:
yading@10 516 av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n",
yading@10 517 avctx->codec_tag);
yading@10 518 return AVERROR_INVALIDDATA;
yading@10 519 }
yading@10 520
yading@10 521 return 0;
yading@10 522 }
yading@10 523
yading@10 524 static av_cold int decode_end(AVCodecContext *avctx)
yading@10 525 {
yading@10 526 UtvideoContext * const c = avctx->priv_data;
yading@10 527
yading@10 528 av_freep(&c->slice_bits);
yading@10 529
yading@10 530 return 0;
yading@10 531 }
yading@10 532
yading@10 533 AVCodec ff_utvideo_decoder = {
yading@10 534 .name = "utvideo",
yading@10 535 .type = AVMEDIA_TYPE_VIDEO,
yading@10 536 .id = AV_CODEC_ID_UTVIDEO,
yading@10 537 .priv_data_size = sizeof(UtvideoContext),
yading@10 538 .init = decode_init,
yading@10 539 .close = decode_end,
yading@10 540 .decode = decode_frame,
yading@10 541 .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
yading@10 542 .long_name = NULL_IF_CONFIG_SMALL("Ut Video"),
yading@10 543 };