Mercurial > libavcodec.hg
annotate roqvideodec.c @ 6018:9d1654835629 libavcodec
Ensure that our total reference frame count does not exceed the SPS
max frame count, which is limited to less than the size of the
reference buffers, thereby preventing overflow.
Part of fix for issue 281.
author | heydowns |
---|---|
date | Fri, 14 Dec 2007 06:25:23 +0000 |
parents | f47bc5359101 |
children | dfdff1ca78a7 |
rev | line source |
---|---|
5080 | 1 /* |
2 * Copyright (C) 2003 the ffmpeg project | |
3 * | |
4 * This file is part of FFmpeg. | |
5 * | |
6 * FFmpeg is free software; you can redistribute it and/or | |
7 * modify it under the terms of the GNU Lesser General Public | |
8 * License as published by the Free Software Foundation; either | |
9 * version 2.1 of the License, or (at your option) any later version. | |
10 * | |
11 * FFmpeg is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
17 * License along with FFmpeg; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 */ | |
20 | |
21 /** | |
22 * @file roqvideodec.c | |
23 * Id RoQ Video Decoder by Dr. Tim Ferguson | |
24 * For more information about the Id RoQ format, visit: | |
25 * http://www.csse.monash.edu.au/~timf/ | |
26 */ | |
27 | |
28 #include <stdio.h> | |
29 #include <stdlib.h> | |
30 #include <string.h> | |
31 #include <unistd.h> | |
32 | |
33 #include "avcodec.h" | |
34 #include "bytestream.h" | |
35 #include "dsputil.h" | |
36 #include "roqvideo.h" | |
37 | |
38 static void roqvideo_decode_frame(RoqContext *ri) | |
39 { | |
40 unsigned int chunk_id = 0, chunk_arg = 0; | |
41 unsigned long chunk_size = 0; | |
42 int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; | |
43 int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my; | |
44 int frame_stats[2][4] = {{0},{0}}; | |
45 roq_qcell *qcell; | |
46 unsigned char *buf = ri->buf; | |
47 unsigned char *buf_end = ri->buf + ri->size; | |
48 | |
49 while (buf < buf_end) { | |
50 chunk_id = bytestream_get_le16(&buf); | |
51 chunk_size = bytestream_get_le32(&buf); | |
52 chunk_arg = bytestream_get_le16(&buf); | |
53 | |
54 if(chunk_id == RoQ_QUAD_VQ) | |
55 break; | |
56 if(chunk_id == RoQ_QUAD_CODEBOOK) { | |
57 if((nv1 = chunk_arg >> 8) == 0) | |
58 nv1 = 256; | |
59 if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) | |
60 nv2 = 256; | |
61 for(i = 0; i < nv1; i++) { | |
5104 | 62 ri->cb2x2[i].y[0] = *buf++; |
63 ri->cb2x2[i].y[1] = *buf++; | |
64 ri->cb2x2[i].y[2] = *buf++; | |
65 ri->cb2x2[i].y[3] = *buf++; | |
66 ri->cb2x2[i].u = *buf++; | |
67 ri->cb2x2[i].v = *buf++; | |
5080 | 68 } |
69 for(i = 0; i < nv2; i++) | |
70 for(j = 0; j < 4; j++) | |
5104 | 71 ri->cb4x4[i].idx[j] = *buf++; |
5080 | 72 } |
73 } | |
74 | |
75 bpos = xpos = ypos = 0; | |
76 while(bpos < chunk_size) { | |
77 for (yp = ypos; yp < ypos + 16; yp += 8) | |
78 for (xp = xpos; xp < xpos + 16; xp += 8) { | |
79 if (vqflg_pos < 0) { | |
80 vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8); | |
81 vqflg_pos = 7; | |
82 } | |
83 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
84 frame_stats[0][vqid]++; | |
85 vqflg_pos--; | |
86 | |
87 switch(vqid) { | |
88 case RoQ_ID_MOT: | |
89 break; | |
90 case RoQ_ID_FCC: | |
91 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
92 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
93 ff_apply_motion_8x8(ri, xp, yp, mx, my); | |
94 break; | |
95 case RoQ_ID_SLD: | |
5104 | 96 qcell = ri->cb4x4 + buf[bpos++]; |
97 ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]); | |
98 ff_apply_vector_4x4(ri, xp+4, yp, ri->cb2x2 + qcell->idx[1]); | |
99 ff_apply_vector_4x4(ri, xp, yp+4, ri->cb2x2 + qcell->idx[2]); | |
100 ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cb2x2 + qcell->idx[3]); | |
5080 | 101 break; |
102 case RoQ_ID_CCC: | |
103 for (k = 0; k < 4; k++) { | |
104 x = xp; y = yp; | |
105 if(k & 0x01) x += 4; | |
106 if(k & 0x02) y += 4; | |
107 | |
108 if (vqflg_pos < 0) { | |
109 vqflg = buf[bpos++]; | |
110 vqflg |= (buf[bpos++] << 8); | |
111 vqflg_pos = 7; | |
112 } | |
113 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
114 frame_stats[1][vqid]++; | |
115 vqflg_pos--; | |
116 switch(vqid) { | |
117 case RoQ_ID_MOT: | |
118 break; | |
119 case RoQ_ID_FCC: | |
120 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
121 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
122 ff_apply_motion_4x4(ri, x, y, mx, my); | |
123 break; | |
124 case RoQ_ID_SLD: | |
5104 | 125 qcell = ri->cb4x4 + buf[bpos++]; |
126 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]); | |
127 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + qcell->idx[1]); | |
128 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + qcell->idx[2]); | |
129 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + qcell->idx[3]); | |
5080 | 130 break; |
131 case RoQ_ID_CCC: | |
5104 | 132 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + buf[bpos]); |
133 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + buf[bpos+1]); | |
134 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + buf[bpos+2]); | |
135 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + buf[bpos+3]); | |
5080 | 136 bpos += 4; |
137 break; | |
138 } | |
139 } | |
140 break; | |
141 default: | |
142 av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid); | |
143 } | |
144 } | |
145 | |
146 xpos += 16; | |
5188 | 147 if (xpos >= ri->width) { |
148 xpos -= ri->width; | |
5080 | 149 ypos += 16; |
150 } | |
5188 | 151 if(ypos >= ri->height) |
5080 | 152 break; |
153 } | |
154 } | |
155 | |
156 | |
157 static int roq_decode_init(AVCodecContext *avctx) | |
158 { | |
159 RoqContext *s = avctx->priv_data; | |
160 | |
161 s->avctx = avctx; | |
5188 | 162 s->width = avctx->width; |
163 s->height = avctx->height; | |
5080 | 164 s->last_frame = &s->frames[0]; |
165 s->current_frame = &s->frames[1]; | |
5099
133329117637
Convert RoQ decoder to use YUV 4:4:4 unpacked macroblocks
benoit
parents:
5090
diff
changeset
|
166 avctx->pix_fmt = PIX_FMT_YUV444P; |
5080 | 167 dsputil_init(&s->dsp, avctx); |
168 | |
169 return 0; | |
170 } | |
171 | |
172 static int roq_decode_frame(AVCodecContext *avctx, | |
173 void *data, int *data_size, | |
174 uint8_t *buf, int buf_size) | |
175 { | |
176 RoqContext *s = avctx->priv_data; | |
5524
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
177 int copy= !s->current_frame->data[0]; |
5080 | 178 |
5088 | 179 if (avctx->reget_buffer(avctx, s->current_frame)) { |
5080 | 180 av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n"); |
181 return -1; | |
182 } | |
183 | |
5524
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
184 if(copy) |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
185 av_picture_copy((AVPicture*)s->current_frame, (AVPicture*)s->last_frame, |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
186 avctx->pix_fmt, avctx->width, avctx->height); |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
187 |
5080 | 188 s->buf = buf; |
189 s->size = buf_size; | |
190 roqvideo_decode_frame(s); | |
191 | |
192 *data_size = sizeof(AVFrame); | |
193 *(AVFrame*)data = *s->current_frame; | |
194 | |
195 /* shuffle frames */ | |
196 FFSWAP(AVFrame *, s->current_frame, s->last_frame); | |
197 | |
198 return buf_size; | |
199 } | |
200 | |
201 static int roq_decode_end(AVCodecContext *avctx) | |
202 { | |
203 RoqContext *s = avctx->priv_data; | |
204 | |
205 /* release the last frame */ | |
206 if (s->last_frame->data[0]) | |
207 avctx->release_buffer(avctx, s->last_frame); | |
5088 | 208 if (s->current_frame->data[0]) |
209 avctx->release_buffer(avctx, s->current_frame); | |
5080 | 210 |
211 return 0; | |
212 } | |
213 | |
214 AVCodec roq_decoder = { | |
215 "roqvideo", | |
216 CODEC_TYPE_VIDEO, | |
217 CODEC_ID_ROQ, | |
218 sizeof(RoqContext), | |
219 roq_decode_init, | |
220 NULL, | |
221 roq_decode_end, | |
222 roq_decode_frame, | |
223 CODEC_CAP_DR1, | |
224 }; |