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 /**
23 * @file
24 * Electronic Arts CMV Video Decoder
25 * by Peter Ross (pross@xvid.org)
26 *
27 * Technical details here:
28 * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_CMV
29 */
30
37
45
48
51
54 if (!
s->last_frame || !
s->last2_frame)
56
57 return 0;
58 }
59
61 const uint8_t *buf, const uint8_t *buf_end)
62 {
65
66 for (
i=0;
i <
s->avctx->height && buf_end - buf >=
s->avctx->width;
i++) {
67 memcpy(
dst, buf,
s->avctx->width);
69 buf +=
s->avctx->width;
70 }
71 }
72
74 const unsigned char *
src, ptrdiff_t src_stride,
75 int x, int y,
76 int xoffset, int yoffset,
79
80 for(j=y;j<y+4;j++)
82 {
83 if (
i+xoffset>=0 &&
i+xoffset<
width &&
84 j+yoffset>=0 && j+yoffset<
height) {
85 dst[j*dst_stride +
i] =
src[(j+yoffset)*src_stride +
i+xoffset];
86 }else{
87 dst[j*dst_stride +
i] = 0;
88 }
89 }
90 }
91
93 const uint8_t *buf_end)
94 {
95 const uint8_t *raw = buf + (
s->avctx->width*
s->avctx->height/16);
97
99 for(y=0; y<
s->avctx->height/4; y++)
100 for(x=0; x<
s->avctx->width/4 && buf_end - buf >
i; x++) {
102 unsigned char *
dst =
frame->data[0] + (y*4)*
frame->linesize[0] + x*4;
103 if (raw+16<buf_end && *raw==0xFF) {
/* intra */
104 raw++;
106 memcpy(
dst +
frame->linesize[0], raw+4, 4);
107 memcpy(
dst + 2 *
frame->linesize[0], raw+8, 4);
108 memcpy(
dst + 3 *
frame->linesize[0], raw+12, 4);
109 raw+=16;
110 }else if(raw<buf_end) { /* inter using second-last frame as reference */
111 int xoffset = (*raw & 0xF) - 7;
112 int yoffset = ((*raw >> 4)) - 7;
113 if (
s->last2_frame->data[0])
115 s->last2_frame->data[0],
s->last2_frame->linesize[0],
116 x*4, y*4, xoffset, yoffset,
s->avctx->width,
s->avctx->height);
117 raw++;
118 }
119 }else{ /* inter using last frame as reference */
120 int xoffset = (buf[
i] & 0xF) - 7;
121 int yoffset = ((buf[
i] >> 4)) - 7;
122 if (
s->last_frame->data[0])
124 s->last_frame->data[0],
s->last_frame->linesize[0],
125 x*4, y*4, xoffset, yoffset,
s->avctx->width,
s->avctx->height);
126 }
128 }
129 }
130
132 {
133 int pal_start, pal_count,
i,
ret, fps;
134
135 if(buf_end - buf < 16) {
138 }
139
142
143 if (
s->width !=
s->avctx->width ||
144 s->height !=
s->avctx->height) {
147 }
148
152
154 if (fps > 0)
156
159
160 buf += 16;
163 buf += 3;
164 }
165
166 return 0;
167 }
168
169 #define EA_PREAMBLE_SIZE 8
170 #define MVIh_TAG MKTAG('M', 'V', 'I', 'h')
171
174 {
175 const uint8_t *buf = avpkt->
data;
176 int buf_size = avpkt->
size;
178 const uint8_t *buf_end = buf + buf_size;
180
183
192 }
193
196
198 if (!(buf[0]&1) && buf_end - buf < s->
width *
s->height * (
int64_t)(100 -
s->avctx->discard_damaged_percentage) / 100)
200
203
205
206 if ((buf[0]&1)) { // subtype
210 }else{
214 }
215
219
220 *got_frame = 1;
221
222 return buf_size;
223 }
224
227
230
231 return 0;
232 }
233
245 };