Mercurial > libavcodec.hg
annotate roqvideodec.c @ 12092:de9e45d04063 libavcodec
DCA: Occasionally a false XCH sync word can turn up after the core DTS data,
to verify the sync word the extension fsize field should be compared to
the core data length field.
Patch by nick.nbrereton@net
author | banan |
---|---|
date | Mon, 05 Jul 2010 08:16:43 +0000 |
parents | 7dd2a45249a9 |
children |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
22 * @file |
7041
ade9051a6a4c
Cosmetics: s/Id/id/ in libavcodec/roqvideodec.c when Id refers to id Software
stefano
parents:
7040
diff
changeset
|
23 * id RoQ Video Decoder by Dr. Tim Ferguson |
ade9051a6a4c
Cosmetics: s/Id/id/ in libavcodec/roqvideodec.c when Id refers to id Software
stefano
parents:
7040
diff
changeset
|
24 * For more information about the id RoQ format, visit: |
5080 | 25 * http://www.csse.monash.edu.au/~timf/ |
26 */ | |
27 | |
28 #include <stdio.h> | |
29 #include <stdlib.h> | |
30 #include <string.h> | |
31 | |
32 #include "avcodec.h" | |
33 #include "bytestream.h" | |
34 #include "roqvideo.h" | |
35 | |
36 static void roqvideo_decode_frame(RoqContext *ri) | |
37 { | |
38 unsigned int chunk_id = 0, chunk_arg = 0; | |
39 unsigned long chunk_size = 0; | |
40 int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; | |
41 int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my; | |
42 int frame_stats[2][4] = {{0},{0}}; | |
43 roq_qcell *qcell; | |
6218 | 44 const unsigned char *buf = ri->buf; |
6314 | 45 const unsigned char *buf_end = ri->buf + ri->size; |
5080 | 46 |
47 while (buf < buf_end) { | |
48 chunk_id = bytestream_get_le16(&buf); | |
49 chunk_size = bytestream_get_le32(&buf); | |
50 chunk_arg = bytestream_get_le16(&buf); | |
51 | |
52 if(chunk_id == RoQ_QUAD_VQ) | |
53 break; | |
54 if(chunk_id == RoQ_QUAD_CODEBOOK) { | |
55 if((nv1 = chunk_arg >> 8) == 0) | |
56 nv1 = 256; | |
57 if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) | |
58 nv2 = 256; | |
59 for(i = 0; i < nv1; i++) { | |
5104 | 60 ri->cb2x2[i].y[0] = *buf++; |
61 ri->cb2x2[i].y[1] = *buf++; | |
62 ri->cb2x2[i].y[2] = *buf++; | |
63 ri->cb2x2[i].y[3] = *buf++; | |
64 ri->cb2x2[i].u = *buf++; | |
65 ri->cb2x2[i].v = *buf++; | |
5080 | 66 } |
67 for(i = 0; i < nv2; i++) | |
68 for(j = 0; j < 4; j++) | |
5104 | 69 ri->cb4x4[i].idx[j] = *buf++; |
5080 | 70 } |
71 } | |
72 | |
73 bpos = xpos = ypos = 0; | |
74 while(bpos < chunk_size) { | |
75 for (yp = ypos; yp < ypos + 16; yp += 8) | |
76 for (xp = xpos; xp < xpos + 16; xp += 8) { | |
77 if (vqflg_pos < 0) { | |
78 vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8); | |
79 vqflg_pos = 7; | |
80 } | |
81 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
82 frame_stats[0][vqid]++; | |
83 vqflg_pos--; | |
84 | |
85 switch(vqid) { | |
86 case RoQ_ID_MOT: | |
87 break; | |
88 case RoQ_ID_FCC: | |
89 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
90 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
91 ff_apply_motion_8x8(ri, xp, yp, mx, my); | |
92 break; | |
93 case RoQ_ID_SLD: | |
5104 | 94 qcell = ri->cb4x4 + buf[bpos++]; |
95 ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]); | |
96 ff_apply_vector_4x4(ri, xp+4, yp, ri->cb2x2 + qcell->idx[1]); | |
97 ff_apply_vector_4x4(ri, xp, yp+4, ri->cb2x2 + qcell->idx[2]); | |
98 ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cb2x2 + qcell->idx[3]); | |
5080 | 99 break; |
100 case RoQ_ID_CCC: | |
101 for (k = 0; k < 4; k++) { | |
102 x = xp; y = yp; | |
103 if(k & 0x01) x += 4; | |
104 if(k & 0x02) y += 4; | |
105 | |
106 if (vqflg_pos < 0) { | |
107 vqflg = buf[bpos++]; | |
108 vqflg |= (buf[bpos++] << 8); | |
109 vqflg_pos = 7; | |
110 } | |
111 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
112 frame_stats[1][vqid]++; | |
113 vqflg_pos--; | |
114 switch(vqid) { | |
115 case RoQ_ID_MOT: | |
116 break; | |
117 case RoQ_ID_FCC: | |
118 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
119 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
120 ff_apply_motion_4x4(ri, x, y, mx, my); | |
121 break; | |
122 case RoQ_ID_SLD: | |
5104 | 123 qcell = ri->cb4x4 + buf[bpos++]; |
124 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]); | |
125 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + qcell->idx[1]); | |
126 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + qcell->idx[2]); | |
127 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + qcell->idx[3]); | |
5080 | 128 break; |
129 case RoQ_ID_CCC: | |
5104 | 130 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + buf[bpos]); |
131 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + buf[bpos+1]); | |
132 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + buf[bpos+2]); | |
133 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + buf[bpos+3]); | |
5080 | 134 bpos += 4; |
135 break; | |
136 } | |
137 } | |
138 break; | |
139 default: | |
140 av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid); | |
141 } | |
142 } | |
143 | |
144 xpos += 16; | |
5188 | 145 if (xpos >= ri->width) { |
146 xpos -= ri->width; | |
5080 | 147 ypos += 16; |
148 } | |
5188 | 149 if(ypos >= ri->height) |
5080 | 150 break; |
151 } | |
152 } | |
153 | |
154 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6484
diff
changeset
|
155 static av_cold int roq_decode_init(AVCodecContext *avctx) |
5080 | 156 { |
157 RoqContext *s = avctx->priv_data; | |
158 | |
159 s->avctx = avctx; | |
5188 | 160 s->width = avctx->width; |
161 s->height = avctx->height; | |
5080 | 162 s->last_frame = &s->frames[0]; |
163 s->current_frame = &s->frames[1]; | |
5099
133329117637
Convert RoQ decoder to use YUV 4:4:4 unpacked macroblocks
benoit
parents:
5090
diff
changeset
|
164 avctx->pix_fmt = PIX_FMT_YUV444P; |
5080 | 165 |
166 return 0; | |
167 } | |
168 | |
169 static int roq_decode_frame(AVCodecContext *avctx, | |
170 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
171 AVPacket *avpkt) |
5080 | 172 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
173 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
174 int buf_size = avpkt->size; |
5080 | 175 RoqContext *s = avctx->priv_data; |
5524
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
176 int copy= !s->current_frame->data[0]; |
5080 | 177 |
5088 | 178 if (avctx->reget_buffer(avctx, s->current_frame)) { |
5080 | 179 av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n"); |
180 return -1; | |
181 } | |
182 | |
5524
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
183 if(copy) |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
184 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
|
185 avctx->pix_fmt, avctx->width, avctx->height); |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
186 |
5080 | 187 s->buf = buf; |
188 s->size = buf_size; | |
189 roqvideo_decode_frame(s); | |
190 | |
191 *data_size = sizeof(AVFrame); | |
192 *(AVFrame*)data = *s->current_frame; | |
193 | |
194 /* shuffle frames */ | |
195 FFSWAP(AVFrame *, s->current_frame, s->last_frame); | |
196 | |
197 return buf_size; | |
198 } | |
199 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6484
diff
changeset
|
200 static av_cold int roq_decode_end(AVCodecContext *avctx) |
5080 | 201 { |
202 RoqContext *s = avctx->priv_data; | |
203 | |
204 /* release the last frame */ | |
205 if (s->last_frame->data[0]) | |
206 avctx->release_buffer(avctx, s->last_frame); | |
5088 | 207 if (s->current_frame->data[0]) |
208 avctx->release_buffer(avctx, s->current_frame); | |
5080 | 209 |
210 return 0; | |
211 } | |
212 | |
213 AVCodec roq_decoder = { | |
214 "roqvideo", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
9981
diff
changeset
|
215 AVMEDIA_TYPE_VIDEO, |
5080 | 216 CODEC_ID_ROQ, |
217 sizeof(RoqContext), | |
218 roq_decode_init, | |
219 NULL, | |
220 roq_decode_end, | |
221 roq_decode_frame, | |
222 CODEC_CAP_DR1, | |
7041
ade9051a6a4c
Cosmetics: s/Id/id/ in libavcodec/roqvideodec.c when Id refers to id Software
stefano
parents:
7040
diff
changeset
|
223 .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), |
5080 | 224 }; |