2 * AVID Meridien decoder
4 * Copyright (c) 2012 Carl Eugen Hoyos
6 * This file is part of FFmpeg.
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.
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.
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
25 #include "libavutil/intreadwrite.h"
27 static av_cold
int avui_decode_init(AVCodecContext
*avctx
)
29 avctx
->pix_fmt
= AV_PIX_FMT_YUVA422P
;
33 static int avui_decode_frame(AVCodecContext
*avctx
, void *data
,
34 int *got_frame
, AVPacket
*avpkt
)
38 const uint8_t *src
= avpkt
->data
, *extradata
= avctx
->extradata
;
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
;
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;
50 if (atom_size
&& atom_size
<= extradata_size
) {
51 extradata
+= atom_size
;
52 extradata_size
-= atom_size
;
57 if (avctx
->height
== 486) {
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
);
67 transparent
= avctx
->bits_per_coded_sample
== 32 &&
68 avpkt
->size
>= opaque_length
* 2 + 4;
69 srca
= src
+ opaque_length
+ 5;
71 if ((ret
= ff_get_buffer(avctx
, pic
, 0)) < 0)
75 pic
->pict_type
= AV_PICTURE_TYPE_I
;
78 src
+= avctx
->width
* skip
;
79 srca
+= avctx
->width
* skip
;
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];
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];
97 for (j
= 0; j
< avctx
->height
>> interlaced
; j
++) {
98 for (k
= 0; k
< avctx
->width
>> 1; k
++) {
101 a
[2 * k
] = 0xFF - (transparent
? *srca
++ : 0);
104 y
[2 * k
+ 1] = *src
++;
105 a
[2 * k
+ 1] = 0xFF - (transparent
? *srca
++ : 0);
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];
122 AVCodec ff_avui_decoder
= {
124 .long_name
= NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"),
125 .type
= AVMEDIA_TYPE_VIDEO
,
126 .id
= AV_CODEC_ID_AVUI
,
127 .init
= avui_decode_init
,
128 .decode
= avui_decode_frame
,
129 .capabilities
= CODEC_CAP_DR1
,