FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
avuidec.c
Go to the documentation of this file.
1 /*
2  * AVID Meridien decoder
3  *
4  * Copyright (c) 2012 Carl Eugen Hoyos
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 #include "avcodec.h"
24 #include "internal.h"
25 #include "libavutil/intreadwrite.h"
26 
28 {
30  return 0;
31 }
32 
33 static int avui_decode_frame(AVCodecContext *avctx, void *data,
34  int *got_frame, AVPacket *avpkt)
35 {
36  int ret;
37  AVFrame *pic = data;
38  const uint8_t *src = avpkt->data, *extradata = avctx->extradata;
39  const uint8_t *srca;
40  uint8_t *y, *u, *v, *a;
41  int transparent, interlaced = 1, skip, opaque_length, i, j, k;
42  uint32_t extradata_size = avctx->extradata_size;
43 
44  while (extradata_size >= 24) {
45  uint32_t atom_size = AV_RB32(extradata);
46  if (!memcmp(&extradata[4], "APRGAPRG0001", 12)) {
47  interlaced = extradata[19] != 1;
48  break;
49  }
50  if (atom_size && atom_size <= extradata_size) {
51  extradata += atom_size;
52  extradata_size -= atom_size;
53  } else {
54  break;
55  }
56  }
57  if (avctx->height == 486) {
58  skip = 10;
59  } else {
60  skip = 16;
61  }
62  opaque_length = 2 * avctx->width * (avctx->height + skip) + 4 * interlaced;
63  if (avpkt->size < opaque_length) {
64  av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
65  return AVERROR(EINVAL);
66  }
67  transparent = avctx->bits_per_coded_sample == 32 &&
68  avpkt->size >= opaque_length * 2 + 4;
69  srca = src + opaque_length + 5;
70 
71  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
72  return ret;
73 
74  pic->key_frame = 1;
76 
77  if (!interlaced) {
78  src += avctx->width * skip;
79  srca += avctx->width * skip;
80  }
81 
82  for (i = 0; i < interlaced + 1; i++) {
83  src += avctx->width * skip;
84  srca += avctx->width * skip;
85  if (interlaced && avctx->height == 486) {
86  y = pic->data[0] + (1 - i) * pic->linesize[0];
87  u = pic->data[1] + (1 - i) * pic->linesize[1];
88  v = pic->data[2] + (1 - i) * pic->linesize[2];
89  a = pic->data[3] + (1 - i) * pic->linesize[3];
90  } else {
91  y = pic->data[0] + i * pic->linesize[0];
92  u = pic->data[1] + i * pic->linesize[1];
93  v = pic->data[2] + i * pic->linesize[2];
94  a = pic->data[3] + i * pic->linesize[3];
95  }
96 
97  for (j = 0; j < avctx->height >> interlaced; j++) {
98  for (k = 0; k < avctx->width >> 1; k++) {
99  u[ k ] = *src++;
100  y[2 * k ] = *src++;
101  a[2 * k ] = 0xFF - (transparent ? *srca++ : 0);
102  srca++;
103  v[ k ] = *src++;
104  y[2 * k + 1] = *src++;
105  a[2 * k + 1] = 0xFF - (transparent ? *srca++ : 0);
106  srca++;
107  }
108 
109  y += (interlaced + 1) * pic->linesize[0];
110  u += (interlaced + 1) * pic->linesize[1];
111  v += (interlaced + 1) * pic->linesize[2];
112  a += (interlaced + 1) * pic->linesize[3];
113  }
114  src += 4;
115  srca += 4;
116  }
117  *got_frame = 1;
118 
119  return avpkt->size;
120 }
121 
123  .name = "avui",
124  .type = AVMEDIA_TYPE_VIDEO,
125  .id = AV_CODEC_ID_AVUI,
126  .init = avui_decode_init,
127  .decode = avui_decode_frame,
128  .capabilities = CODEC_CAP_DR1,
129  .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"),
130 };