Mercurial > libavcodec.hg
annotate eacmv.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | ffb3668ff7af |
children |
rev | line source |
---|---|
7222 | 1 /* |
2 * Electronic Arts CMV Video Decoder | |
3 * Copyright (c) 2007-2008 Peter Ross | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
23 * @file |
7222 | 24 * Electronic Arts CMV Video Decoder |
10825 | 25 * by Peter Ross (pross@xvid.org) |
7222 | 26 * |
27 * Technical details here: | |
28 * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_CMV | |
29 */ | |
30 | |
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7222
diff
changeset
|
31 #include "libavutil/intreadwrite.h" |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11644
diff
changeset
|
32 #include "libavcore/imgutils.h" |
7222 | 33 #include "avcodec.h" |
34 | |
35 typedef struct CmvContext { | |
36 AVCodecContext *avctx; | |
37 AVFrame frame; ///< current | |
38 AVFrame last_frame; ///< last | |
39 AVFrame last2_frame; ///< second-last | |
40 int width, height; | |
41 unsigned int palette[AVPALETTE_COUNT]; | |
42 } CmvContext; | |
43 | |
44 static av_cold int cmv_decode_init(AVCodecContext *avctx){ | |
45 CmvContext *s = avctx->priv_data; | |
46 s->avctx = avctx; | |
47 avctx->pix_fmt = PIX_FMT_PAL8; | |
48 return 0; | |
49 } | |
50 | |
51 static void cmv_decode_intra(CmvContext * s, const uint8_t *buf, const uint8_t *buf_end){ | |
52 unsigned char *dst = s->frame.data[0]; | |
53 int i; | |
54 | |
55 for (i=0; i < s->avctx->height && buf+s->avctx->width<=buf_end; i++) { | |
56 memcpy(dst, buf, s->avctx->width); | |
57 dst += s->frame.linesize[0]; | |
58 buf += s->avctx->width; | |
59 } | |
60 } | |
61 | |
62 static void cmv_motcomp(unsigned char *dst, int dst_stride, | |
63 const unsigned char *src, int src_stride, | |
64 int x, int y, | |
65 int xoffset, int yoffset, | |
66 int width, int height){ | |
67 int i,j; | |
68 | |
69 for(j=y;j<y+4;j++) | |
70 for(i=x;i<x+4;i++) | |
71 { | |
72 if (i+xoffset>=0 && i+xoffset<width && | |
73 j+yoffset>=0 && j+yoffset<height) { | |
74 dst[j*dst_stride + i] = src[(j+yoffset)*src_stride + i+xoffset]; | |
75 }else{ | |
76 dst[j*dst_stride + i] = 0; | |
77 } | |
78 } | |
79 } | |
80 | |
81 static void cmv_decode_inter(CmvContext * s, const uint8_t *buf, const uint8_t *buf_end){ | |
82 const uint8_t *raw = buf + (s->avctx->width*s->avctx->height/16); | |
83 int x,y,i; | |
84 | |
85 i = 0; | |
86 for(y=0; y<s->avctx->height/4; y++) | |
87 for(x=0; x<s->avctx->width/4 && buf+i<buf_end; x++) { | |
88 if (buf[i]==0xFF) { | |
89 unsigned char *dst = s->frame.data[0] + (y*4)*s->frame.linesize[0] + x*4; | |
90 if (raw+16<buf_end && *raw==0xFF) { /* intra */ | |
91 raw++; | |
92 memcpy(dst, raw, 4); | |
93 memcpy(dst+s->frame.linesize[0], raw+4, 4); | |
94 memcpy(dst+2*s->frame.linesize[0], raw+8, 4); | |
95 memcpy(dst+3*s->frame.linesize[0], raw+12, 4); | |
96 raw+=16; | |
97 }else if(raw<buf_end) { /* inter using second-last frame as reference */ | |
98 int xoffset = (*raw & 0xF) - 7; | |
99 int yoffset = ((*raw >> 4)) - 7; | |
100 cmv_motcomp(s->frame.data[0], s->frame.linesize[0], | |
101 s->last2_frame.data[0], s->last2_frame.linesize[0], | |
102 x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height); | |
103 raw++; | |
104 } | |
105 }else{ /* inter using last frame as reference */ | |
106 int xoffset = (buf[i] & 0xF) - 7; | |
107 int yoffset = ((buf[i] >> 4)) - 7; | |
108 cmv_motcomp(s->frame.data[0], s->frame.linesize[0], | |
109 s->last_frame.data[0], s->last_frame.linesize[0], | |
110 x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height); | |
111 } | |
112 i++; | |
113 } | |
114 } | |
115 | |
116 static void cmv_process_header(CmvContext *s, const uint8_t *buf, const uint8_t *buf_end) | |
117 { | |
118 int pal_start, pal_count, i; | |
119 | |
120 if(buf+16>=buf_end) { | |
121 av_log(s->avctx, AV_LOG_WARNING, "truncated header\n"); | |
122 return; | |
123 } | |
124 | |
125 s->width = AV_RL16(&buf[4]); | |
126 s->height = AV_RL16(&buf[6]); | |
127 if (s->avctx->width!=s->width || s->avctx->height!=s->height) | |
128 avcodec_set_dimensions(s->avctx, s->width, s->height); | |
129 | |
130 s->avctx->time_base.num = 1; | |
131 s->avctx->time_base.den = AV_RL16(&buf[10]); | |
132 | |
133 pal_start = AV_RL16(&buf[12]); | |
134 pal_count = AV_RL16(&buf[14]); | |
135 | |
136 buf += 16; | |
137 for (i=pal_start; i<pal_start+pal_count && i<AVPALETTE_COUNT && buf+2<buf_end; i++) { | |
138 s->palette[i] = AV_RB24(buf); | |
139 buf += 3; | |
140 } | |
141 } | |
142 | |
143 #define EA_PREAMBLE_SIZE 8 | |
144 #define MVIh_TAG MKTAG('M', 'V', 'I', 'h') | |
145 | |
146 static int cmv_decode_frame(AVCodecContext *avctx, | |
147 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9083
diff
changeset
|
148 AVPacket *avpkt) |
7222 | 149 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9083
diff
changeset
|
150 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9083
diff
changeset
|
151 int buf_size = avpkt->size; |
7222 | 152 CmvContext *s = avctx->priv_data; |
153 const uint8_t *buf_end = buf + buf_size; | |
154 | |
155 if (AV_RL32(buf)==MVIh_TAG||AV_RB32(buf)==MVIh_TAG) { | |
156 cmv_process_header(s, buf+EA_PREAMBLE_SIZE, buf_end); | |
157 return buf_size; | |
158 } | |
159 | |
12462
ffb3668ff7af
Use new imgutils.h API names, fix deprecation warnings.
stefano
parents:
12372
diff
changeset
|
160 if (av_image_check_size(s->width, s->height, 0, s->avctx)) |
7222 | 161 return -1; |
162 | |
163 /* shuffle */ | |
164 if (s->last2_frame.data[0]) | |
165 avctx->release_buffer(avctx, &s->last2_frame); | |
166 FFSWAP(AVFrame, s->last_frame, s->last2_frame); | |
167 FFSWAP(AVFrame, s->frame, s->last_frame); | |
168 | |
169 s->frame.reference = 1; | |
170 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID; | |
171 if (avctx->get_buffer(avctx, &s->frame)<0) { | |
172 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
173 return -1; | |
174 } | |
175 | |
176 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); | |
177 | |
178 buf += EA_PREAMBLE_SIZE; | |
179 if ((buf[0]&1)) { // subtype | |
180 cmv_decode_inter(s, buf+2, buf_end); | |
181 s->frame.key_frame = 0; | |
182 s->frame.pict_type = FF_P_TYPE; | |
183 }else{ | |
184 s->frame.key_frame = 1; | |
185 s->frame.pict_type = FF_I_TYPE; | |
186 cmv_decode_intra(s, buf+2, buf_end); | |
187 } | |
188 | |
189 *data_size = sizeof(AVFrame); | |
190 *(AVFrame*)data = s->frame; | |
191 | |
192 return buf_size; | |
193 } | |
194 | |
195 static av_cold int cmv_decode_end(AVCodecContext *avctx){ | |
196 CmvContext *s = avctx->priv_data; | |
197 if (s->frame.data[0]) | |
198 s->avctx->release_buffer(avctx, &s->frame); | |
199 if (s->last_frame.data[0]) | |
200 s->avctx->release_buffer(avctx, &s->last_frame); | |
201 if (s->last2_frame.data[0]) | |
202 s->avctx->release_buffer(avctx, &s->last2_frame); | |
203 | |
204 return 0; | |
205 } | |
206 | |
207 AVCodec eacmv_decoder = { | |
208 "eacmv", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10825
diff
changeset
|
209 AVMEDIA_TYPE_VIDEO, |
7222 | 210 CODEC_ID_CMV, |
211 sizeof(CmvContext), | |
212 cmv_decode_init, | |
213 NULL, | |
214 cmv_decode_end, | |
215 cmv_decode_frame, | |
216 CODEC_CAP_DR1, | |
9083
bf274494b66e
Change a bunch of codec long_names to be more consistent and descriptive.
diego
parents:
8718
diff
changeset
|
217 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts CMV video"), |
7222 | 218 }; |