Mercurial > libavcodec.hg
annotate roqvideodec.c @ 8991:ca768cb2bfb6 libavcodec
Use last decoded SPS as current SPS in order to parse picture timing SEI
correctly. This works around an apparent H.264 standard deficiency.
Patch by Ivan Schreter, schreter gmx net
author | cehoyos |
---|---|
date | Fri, 20 Feb 2009 16:20:01 +0000 |
parents | e9d9d946f213 |
children | 54bc8a2727b0 |
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 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
7041
diff
changeset
|
22 * @file libavcodec/roqvideodec.c |
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 #include <unistd.h> | |
32 | |
33 #include "avcodec.h" | |
34 #include "bytestream.h" | |
35 #include "roqvideo.h" | |
36 | |
37 static void roqvideo_decode_frame(RoqContext *ri) | |
38 { | |
39 unsigned int chunk_id = 0, chunk_arg = 0; | |
40 unsigned long chunk_size = 0; | |
41 int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; | |
42 int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my; | |
43 int frame_stats[2][4] = {{0},{0}}; | |
44 roq_qcell *qcell; | |
6218 | 45 const unsigned char *buf = ri->buf; |
6314 | 46 const unsigned char *buf_end = ri->buf + ri->size; |
5080 | 47 |
48 while (buf < buf_end) { | |
49 chunk_id = bytestream_get_le16(&buf); | |
50 chunk_size = bytestream_get_le32(&buf); | |
51 chunk_arg = bytestream_get_le16(&buf); | |
52 | |
53 if(chunk_id == RoQ_QUAD_VQ) | |
54 break; | |
55 if(chunk_id == RoQ_QUAD_CODEBOOK) { | |
56 if((nv1 = chunk_arg >> 8) == 0) | |
57 nv1 = 256; | |
58 if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) | |
59 nv2 = 256; | |
60 for(i = 0; i < nv1; i++) { | |
5104 | 61 ri->cb2x2[i].y[0] = *buf++; |
62 ri->cb2x2[i].y[1] = *buf++; | |
63 ri->cb2x2[i].y[2] = *buf++; | |
64 ri->cb2x2[i].y[3] = *buf++; | |
65 ri->cb2x2[i].u = *buf++; | |
66 ri->cb2x2[i].v = *buf++; | |
5080 | 67 } |
68 for(i = 0; i < nv2; i++) | |
69 for(j = 0; j < 4; j++) | |
5104 | 70 ri->cb4x4[i].idx[j] = *buf++; |
5080 | 71 } |
72 } | |
73 | |
74 bpos = xpos = ypos = 0; | |
75 while(bpos < chunk_size) { | |
76 for (yp = ypos; yp < ypos + 16; yp += 8) | |
77 for (xp = xpos; xp < xpos + 16; xp += 8) { | |
78 if (vqflg_pos < 0) { | |
79 vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8); | |
80 vqflg_pos = 7; | |
81 } | |
82 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
83 frame_stats[0][vqid]++; | |
84 vqflg_pos--; | |
85 | |
86 switch(vqid) { | |
87 case RoQ_ID_MOT: | |
88 break; | |
89 case RoQ_ID_FCC: | |
90 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
91 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
92 ff_apply_motion_8x8(ri, xp, yp, mx, my); | |
93 break; | |
94 case RoQ_ID_SLD: | |
5104 | 95 qcell = ri->cb4x4 + buf[bpos++]; |
96 ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]); | |
97 ff_apply_vector_4x4(ri, xp+4, yp, ri->cb2x2 + qcell->idx[1]); | |
98 ff_apply_vector_4x4(ri, xp, yp+4, ri->cb2x2 + qcell->idx[2]); | |
99 ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cb2x2 + qcell->idx[3]); | |
5080 | 100 break; |
101 case RoQ_ID_CCC: | |
102 for (k = 0; k < 4; k++) { | |
103 x = xp; y = yp; | |
104 if(k & 0x01) x += 4; | |
105 if(k & 0x02) y += 4; | |
106 | |
107 if (vqflg_pos < 0) { | |
108 vqflg = buf[bpos++]; | |
109 vqflg |= (buf[bpos++] << 8); | |
110 vqflg_pos = 7; | |
111 } | |
112 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
113 frame_stats[1][vqid]++; | |
114 vqflg_pos--; | |
115 switch(vqid) { | |
116 case RoQ_ID_MOT: | |
117 break; | |
118 case RoQ_ID_FCC: | |
119 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
120 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
121 ff_apply_motion_4x4(ri, x, y, mx, my); | |
122 break; | |
123 case RoQ_ID_SLD: | |
5104 | 124 qcell = ri->cb4x4 + buf[bpos++]; |
125 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]); | |
126 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + qcell->idx[1]); | |
127 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + qcell->idx[2]); | |
128 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + qcell->idx[3]); | |
5080 | 129 break; |
130 case RoQ_ID_CCC: | |
5104 | 131 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + buf[bpos]); |
132 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + buf[bpos+1]); | |
133 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + buf[bpos+2]); | |
134 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + buf[bpos+3]); | |
5080 | 135 bpos += 4; |
136 break; | |
137 } | |
138 } | |
139 break; | |
140 default: | |
141 av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid); | |
142 } | |
143 } | |
144 | |
145 xpos += 16; | |
5188 | 146 if (xpos >= ri->width) { |
147 xpos -= ri->width; | |
5080 | 148 ypos += 16; |
149 } | |
5188 | 150 if(ypos >= ri->height) |
5080 | 151 break; |
152 } | |
153 } | |
154 | |
155 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6484
diff
changeset
|
156 static av_cold int roq_decode_init(AVCodecContext *avctx) |
5080 | 157 { |
158 RoqContext *s = avctx->priv_data; | |
159 | |
160 s->avctx = avctx; | |
5188 | 161 s->width = avctx->width; |
162 s->height = avctx->height; | |
5080 | 163 s->last_frame = &s->frames[0]; |
164 s->current_frame = &s->frames[1]; | |
5099
133329117637
Convert RoQ decoder to use YUV 4:4:4 unpacked macroblocks
benoit
parents:
5090
diff
changeset
|
165 avctx->pix_fmt = PIX_FMT_YUV444P; |
5080 | 166 |
167 return 0; | |
168 } | |
169 | |
170 static int roq_decode_frame(AVCodecContext *avctx, | |
171 void *data, int *data_size, | |
6279 | 172 const uint8_t *buf, int buf_size) |
5080 | 173 { |
174 RoqContext *s = avctx->priv_data; | |
5524
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
175 int copy= !s->current_frame->data[0]; |
5080 | 176 |
5088 | 177 if (avctx->reget_buffer(avctx, s->current_frame)) { |
5080 | 178 av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n"); |
179 return -1; | |
180 } | |
181 | |
5524
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
182 if(copy) |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
183 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
|
184 avctx->pix_fmt, avctx->width, avctx->height); |
f47bc5359101
fix decoding of samples.mplayerhq.hu/game-formats/idroq/demoEnd.roq
michael
parents:
5215
diff
changeset
|
185 |
5080 | 186 s->buf = buf; |
187 s->size = buf_size; | |
188 roqvideo_decode_frame(s); | |
189 | |
190 *data_size = sizeof(AVFrame); | |
191 *(AVFrame*)data = *s->current_frame; | |
192 | |
193 /* shuffle frames */ | |
194 FFSWAP(AVFrame *, s->current_frame, s->last_frame); | |
195 | |
196 return buf_size; | |
197 } | |
198 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6484
diff
changeset
|
199 static av_cold int roq_decode_end(AVCodecContext *avctx) |
5080 | 200 { |
201 RoqContext *s = avctx->priv_data; | |
202 | |
203 /* release the last frame */ | |
204 if (s->last_frame->data[0]) | |
205 avctx->release_buffer(avctx, s->last_frame); | |
5088 | 206 if (s->current_frame->data[0]) |
207 avctx->release_buffer(avctx, s->current_frame); | |
5080 | 208 |
209 return 0; | |
210 } | |
211 | |
212 AVCodec roq_decoder = { | |
213 "roqvideo", | |
214 CODEC_TYPE_VIDEO, | |
215 CODEC_ID_ROQ, | |
216 sizeof(RoqContext), | |
217 roq_decode_init, | |
218 NULL, | |
219 roq_decode_end, | |
220 roq_decode_frame, | |
221 CODEC_CAP_DR1, | |
7041
ade9051a6a4c
Cosmetics: s/Id/id/ in libavcodec/roqvideodec.c when Id refers to id Software
stefano
parents:
7040
diff
changeset
|
222 .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), |
5080 | 223 }; |