Mercurial > mplayer.hg
annotate libmpeg2/decode.c @ 23974:30677153df21
Set lavc_context->channels before opening the codec, it is sufficient to
select the desired number of codecs for ffdca and does not break other codecs
like ffvorbis that do not (re)set the channel number during decode.
author | reimar |
---|---|
date | Wed, 01 Aug 2007 23:36:40 +0000 |
parents | 60a39d71e247 |
children | fd18fa10de53 |
rev | line source |
---|---|
9857 | 1 /* |
2 * decode.c | |
12932 | 3 * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> |
9857 | 4 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> |
5 * | |
6 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. | |
7 * See http://libmpeg2.sourceforge.net/ for updates. | |
8 * | |
9 * mpeg2dec is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * mpeg2dec is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU General Public License | |
20 * along with this program; if not, write to the Free Software | |
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
14732
1385ec491ffb
Mark locally modified files as such to comply more closely with GPL 2a.
diego
parents:
12932
diff
changeset
|
22 * |
21526 | 23 * Modified for use with MPlayer, see libmpeg-0.4.1.diff for the exact changes. |
18783 | 24 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/ |
14732
1385ec491ffb
Mark locally modified files as such to comply more closely with GPL 2a.
diego
parents:
12932
diff
changeset
|
25 * $Id$ |
9857 | 26 */ |
27 | |
28 #include "config.h" | |
29 | |
30 #include <string.h> /* memcmp/memset, try to remove */ | |
31 #include <stdlib.h> | |
32 #include <inttypes.h> | |
33 | |
34 #include "mpeg2.h" | |
12932 | 35 #include "attributes.h" |
9857 | 36 #include "mpeg2_internal.h" |
37 | |
38 static int mpeg2_accels = 0; | |
39 | |
40 #define BUFFER_SIZE (1194 * 1024) | |
41 | |
42 const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec) | |
43 { | |
44 return &(mpeg2dec->info); | |
45 } | |
46 | |
47 static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes) | |
48 { | |
49 uint8_t * current; | |
50 uint32_t shift; | |
51 uint8_t * limit; | |
52 uint8_t byte; | |
53 | |
54 if (!bytes) | |
55 return 0; | |
56 | |
57 current = mpeg2dec->buf_start; | |
58 shift = mpeg2dec->shift; | |
59 limit = current + bytes; | |
60 | |
61 do { | |
62 byte = *current++; | |
63 if (shift == 0x00000100) { | |
64 int skipped; | |
65 | |
66 mpeg2dec->shift = 0xffffff00; | |
67 skipped = current - mpeg2dec->buf_start; | |
68 mpeg2dec->buf_start = current; | |
69 return skipped; | |
70 } | |
71 shift = (shift | byte) << 8; | |
72 } while (current < limit); | |
73 | |
74 mpeg2dec->shift = shift; | |
75 mpeg2dec->buf_start = current; | |
76 return 0; | |
77 } | |
78 | |
79 static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes) | |
80 { | |
81 uint8_t * current; | |
82 uint32_t shift; | |
83 uint8_t * chunk_ptr; | |
84 uint8_t * limit; | |
85 uint8_t byte; | |
86 | |
87 if (!bytes) | |
88 return 0; | |
89 | |
90 current = mpeg2dec->buf_start; | |
91 shift = mpeg2dec->shift; | |
92 chunk_ptr = mpeg2dec->chunk_ptr; | |
93 limit = current + bytes; | |
94 | |
95 do { | |
96 byte = *current++; | |
97 if (shift == 0x00000100) { | |
98 int copied; | |
99 | |
100 mpeg2dec->shift = 0xffffff00; | |
101 mpeg2dec->chunk_ptr = chunk_ptr + 1; | |
102 copied = current - mpeg2dec->buf_start; | |
103 mpeg2dec->buf_start = current; | |
104 return copied; | |
105 } | |
106 shift = (shift | byte) << 8; | |
107 *chunk_ptr++ = byte; | |
108 } while (current < limit); | |
109 | |
110 mpeg2dec->shift = shift; | |
111 mpeg2dec->buf_start = current; | |
112 return 0; | |
113 } | |
114 | |
115 void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end) | |
116 { | |
117 mpeg2dec->buf_start = start; | |
118 mpeg2dec->buf_end = end; | |
119 } | |
120 | |
12932 | 121 int mpeg2_getpos (mpeg2dec_t * mpeg2dec) |
122 { | |
123 return mpeg2dec->buf_end - mpeg2dec->buf_start; | |
124 } | |
125 | |
126 static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec) | |
9857 | 127 { |
128 int size, skipped; | |
129 | |
130 size = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
131 skipped = skip_chunk (mpeg2dec, size); | |
132 if (!skipped) { | |
12932 | 133 mpeg2dec->bytes_since_tag += size; |
134 return STATE_BUFFER; | |
9857 | 135 } |
12932 | 136 mpeg2dec->bytes_since_tag += skipped; |
9857 | 137 mpeg2dec->code = mpeg2dec->buf_start[-1]; |
12932 | 138 return (mpeg2_state_t)-1; |
9857 | 139 } |
140 | |
12932 | 141 mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec) |
9857 | 142 { |
143 while (mpeg2dec->code != 0xb3 && | |
144 ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 && | |
12932 | 145 mpeg2dec->code) || mpeg2dec->sequence.width == (unsigned)-1)) |
146 if (seek_chunk (mpeg2dec) == STATE_BUFFER) | |
147 return STATE_BUFFER; | |
9857 | 148 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; |
12932 | 149 mpeg2dec->user_data_len = 0; |
150 return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) : | |
151 mpeg2_header_picture_start (mpeg2dec)); | |
9857 | 152 } |
153 | |
154 #define RECEIVED(code,state) (((state) << 8) + (code)) | |
155 | |
12932 | 156 mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec) |
9857 | 157 { |
158 int size_buffer, size_chunk, copied; | |
159 | |
12932 | 160 if (mpeg2dec->action) { |
161 mpeg2_state_t state; | |
162 | |
163 state = mpeg2dec->action (mpeg2dec); | |
164 if ((int)state >= 0) | |
165 return state; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
166 } |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
167 |
9857 | 168 while (1) { |
169 while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < | |
170 mpeg2dec->nb_decode_slices) { | |
171 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
172 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - | |
173 mpeg2dec->chunk_ptr); | |
174 if (size_buffer <= size_chunk) { | |
175 copied = copy_chunk (mpeg2dec, size_buffer); | |
176 if (!copied) { | |
12932 | 177 mpeg2dec->bytes_since_tag += size_buffer; |
9857 | 178 mpeg2dec->chunk_ptr += size_buffer; |
12932 | 179 return STATE_BUFFER; |
9857 | 180 } |
181 } else { | |
182 copied = copy_chunk (mpeg2dec, size_chunk); | |
183 if (!copied) { | |
184 /* filled the chunk buffer without finding a start code */ | |
12932 | 185 mpeg2dec->bytes_since_tag += size_chunk; |
9857 | 186 mpeg2dec->action = seek_chunk; |
187 return STATE_INVALID; | |
188 } | |
189 } | |
12932 | 190 mpeg2dec->bytes_since_tag += copied; |
9857 | 191 |
192 mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code, | |
193 mpeg2dec->chunk_start); | |
194 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
195 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; | |
196 } | |
197 if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) | |
198 break; | |
12932 | 199 if (seek_chunk (mpeg2dec) == STATE_BUFFER) |
200 return STATE_BUFFER; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
201 } |
9857 | 202 |
12932 | 203 switch (mpeg2dec->code) { |
204 case 0x00: | |
9857 | 205 mpeg2dec->action = mpeg2_header_picture_start; |
12932 | 206 return mpeg2dec->state; |
207 case 0xb7: | |
9857 | 208 mpeg2dec->action = mpeg2_header_end; |
209 break; | |
12932 | 210 case 0xb3: |
211 case 0xb8: | |
9857 | 212 mpeg2dec->action = mpeg2_parse_header; |
213 break; | |
214 default: | |
12932 | 215 mpeg2dec->action = seek_chunk; |
9857 | 216 return STATE_INVALID; |
217 } | |
12932 | 218 return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID; |
9857 | 219 } |
220 | |
12932 | 221 mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec) |
9857 | 222 { |
223 static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = { | |
224 mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data, | |
225 mpeg2_header_sequence, NULL, NULL, NULL, NULL, mpeg2_header_gop | |
226 }; | |
227 int size_buffer, size_chunk, copied; | |
228 | |
229 mpeg2dec->action = mpeg2_parse_header; | |
12932 | 230 mpeg2dec->info.user_data = NULL; mpeg2dec->info.user_data_len = 0; |
9857 | 231 while (1) { |
232 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
233 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - | |
234 mpeg2dec->chunk_ptr); | |
235 if (size_buffer <= size_chunk) { | |
236 copied = copy_chunk (mpeg2dec, size_buffer); | |
237 if (!copied) { | |
12932 | 238 mpeg2dec->bytes_since_tag += size_buffer; |
9857 | 239 mpeg2dec->chunk_ptr += size_buffer; |
12932 | 240 return STATE_BUFFER; |
9857 | 241 } |
242 } else { | |
243 copied = copy_chunk (mpeg2dec, size_chunk); | |
244 if (!copied) { | |
245 /* filled the chunk buffer without finding a start code */ | |
12932 | 246 mpeg2dec->bytes_since_tag += size_chunk; |
9857 | 247 mpeg2dec->code = 0xb4; |
248 mpeg2dec->action = mpeg2_seek_header; | |
249 return STATE_INVALID; | |
250 } | |
251 } | |
12932 | 252 mpeg2dec->bytes_since_tag += copied; |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
253 |
9857 | 254 if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) { |
255 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
256 mpeg2dec->action = mpeg2_seek_header; | |
257 return STATE_INVALID; | |
258 } | |
259 | |
260 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
261 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) { | |
262 | |
263 /* state transition after a sequence header */ | |
264 case RECEIVED (0x00, STATE_SEQUENCE): | |
265 mpeg2dec->action = mpeg2_header_picture_start; | |
266 case RECEIVED (0xb8, STATE_SEQUENCE): | |
267 mpeg2_header_sequence_finalize (mpeg2dec); | |
268 break; | |
269 | |
270 /* other legal state transitions */ | |
271 case RECEIVED (0x00, STATE_GOP): | |
12932 | 272 mpeg2_header_gop_finalize (mpeg2dec); |
9857 | 273 mpeg2dec->action = mpeg2_header_picture_start; |
274 break; | |
275 case RECEIVED (0x01, STATE_PICTURE): | |
276 case RECEIVED (0x01, STATE_PICTURE_2ND): | |
12932 | 277 mpeg2_header_picture_finalize (mpeg2dec, mpeg2_accels); |
9857 | 278 mpeg2dec->action = mpeg2_header_slice_start; |
279 break; | |
280 | |
281 /* legal headers within a given state */ | |
282 case RECEIVED (0xb2, STATE_SEQUENCE): | |
283 case RECEIVED (0xb2, STATE_GOP): | |
284 case RECEIVED (0xb2, STATE_PICTURE): | |
285 case RECEIVED (0xb2, STATE_PICTURE_2ND): | |
286 case RECEIVED (0xb5, STATE_SEQUENCE): | |
287 case RECEIVED (0xb5, STATE_PICTURE): | |
288 case RECEIVED (0xb5, STATE_PICTURE_2ND): | |
289 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; | |
290 continue; | |
291 | |
292 default: | |
293 mpeg2dec->action = mpeg2_seek_header; | |
294 return STATE_INVALID; | |
295 } | |
296 | |
297 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; | |
12932 | 298 mpeg2dec->user_data_len = 0; |
9857 | 299 return mpeg2dec->state; |
300 } | |
301 } | |
302 | |
12932 | 303 int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg) |
9857 | 304 { |
12932 | 305 mpeg2_convert_init_t convert_init; |
306 int error; | |
9857 | 307 |
12932 | 308 error = convert (MPEG2_CONVERT_SET, NULL, &(mpeg2dec->sequence), 0, |
309 mpeg2_accels, arg, &convert_init); | |
310 if (!error) { | |
311 mpeg2dec->convert = convert; | |
312 mpeg2dec->convert_arg = arg; | |
313 mpeg2dec->convert_id_size = convert_init.id_size; | |
314 mpeg2dec->convert_stride = 0; | |
9857 | 315 } |
12932 | 316 return error; |
317 } | |
9857 | 318 |
12932 | 319 int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride) |
320 { | |
321 if (!mpeg2dec->convert) { | |
322 if (stride < (int) mpeg2dec->sequence.width) | |
323 stride = mpeg2dec->sequence.width; | |
324 mpeg2dec->decoder.stride_frame = stride; | |
325 } else { | |
326 mpeg2_convert_init_t convert_init; | |
327 | |
328 stride = mpeg2dec->convert (MPEG2_CONVERT_STRIDE, NULL, | |
329 &(mpeg2dec->sequence), stride, | |
330 mpeg2_accels, mpeg2dec->convert_arg, | |
331 &convert_init); | |
332 mpeg2dec->convert_id_size = convert_init.id_size; | |
333 mpeg2dec->convert_stride = stride; | |
334 } | |
335 return stride; | |
9857 | 336 } |
337 | |
338 void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id) | |
339 { | |
12932 | 340 mpeg2_fbuf_t * fbuf; |
9857 | 341 |
342 if (mpeg2dec->custom_fbuf) { | |
343 if (mpeg2dec->state == STATE_SEQUENCE) { | |
344 mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; | |
345 mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; | |
346 } | |
12932 | 347 mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type == |
348 PIC_FLAG_CODING_TYPE_B)); | |
349 fbuf = mpeg2dec->fbuf[0]; | |
9857 | 350 } else { |
351 fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf); | |
352 mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index; | |
353 } | |
354 fbuf->buf[0] = buf[0]; | |
355 fbuf->buf[1] = buf[1]; | |
356 fbuf->buf[2] = buf[2]; | |
357 fbuf->id = id; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
358 // HACK! FIXME! At first I frame, copy pointers to prediction frame too! |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
359 if (mpeg2dec->custom_fbuf && !mpeg2dec->fbuf[1]->buf[0]){ |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
360 mpeg2dec->fbuf[1]->buf[0]=buf[0]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
361 mpeg2dec->fbuf[1]->buf[1]=buf[1]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
362 mpeg2dec->fbuf[1]->buf[2]=buf[2]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
363 mpeg2dec->fbuf[1]->id=NULL; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
364 } |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
365 // printf("libmpeg2: FBUF 0:%p 1:%p 2:%p\n", |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
366 // mpeg2dec->fbuf[0]->buf[0],mpeg2dec->fbuf[1]->buf[0],mpeg2dec->fbuf[2]->buf[0]); |
9857 | 367 } |
368 | |
369 void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf) | |
370 { | |
371 mpeg2dec->custom_fbuf = custom_fbuf; | |
372 } | |
373 | |
374 void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip) | |
375 { | |
376 mpeg2dec->first_decode_slice = 1; | |
377 mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1); | |
378 } | |
379 | |
380 void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end) | |
381 { | |
382 start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start; | |
383 end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end; | |
384 mpeg2dec->first_decode_slice = start; | |
385 mpeg2dec->nb_decode_slices = end - start; | |
386 } | |
387 | |
12932 | 388 void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2) |
9857 | 389 { |
12932 | 390 mpeg2dec->tag_previous = mpeg2dec->tag_current; |
391 mpeg2dec->tag2_previous = mpeg2dec->tag2_current; | |
392 mpeg2dec->tag_current = tag; | |
393 mpeg2dec->tag2_current = tag2; | |
394 mpeg2dec->num_tags++; | |
395 mpeg2dec->bytes_since_tag = 0; | |
9857 | 396 } |
397 | |
398 uint32_t mpeg2_accel (uint32_t accel) | |
399 { | |
400 if (!mpeg2_accels) { | |
401 if (accel & MPEG2_ACCEL_DETECT) | |
402 accel |= mpeg2_detect_accel (); | |
403 mpeg2_accels = accel |= MPEG2_ACCEL_DETECT; | |
404 mpeg2_cpu_state_init (accel); | |
405 mpeg2_idct_init (accel); | |
406 mpeg2_mc_init (accel); | |
407 } | |
408 return mpeg2_accels & ~MPEG2_ACCEL_DETECT; | |
409 } | |
410 | |
12932 | 411 void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset) |
412 { | |
413 mpeg2dec->buf_start = mpeg2dec->buf_end = NULL; | |
414 mpeg2dec->num_tags = 0; | |
415 mpeg2dec->shift = 0xffffff00; | |
416 mpeg2dec->code = 0xb4; | |
417 mpeg2dec->action = mpeg2_seek_header; | |
418 mpeg2dec->state = STATE_INVALID; | |
419 mpeg2dec->first = 1; | |
420 | |
421 mpeg2_reset_info(&(mpeg2dec->info)); | |
422 mpeg2dec->info.gop = NULL; | |
423 mpeg2dec->info.user_data = NULL; | |
424 mpeg2dec->info.user_data_len = 0; | |
425 if (full_reset) { | |
426 mpeg2dec->info.sequence = NULL; | |
427 mpeg2_header_state_init (mpeg2dec); | |
428 } | |
429 | |
430 } | |
431 | |
9857 | 432 mpeg2dec_t * mpeg2_init (void) |
433 { | |
434 mpeg2dec_t * mpeg2dec; | |
435 | |
436 mpeg2_accel (MPEG2_ACCEL_DETECT); | |
437 | |
438 mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t), | |
12932 | 439 MPEG2_ALLOC_MPEG2DEC); |
9857 | 440 if (mpeg2dec == NULL) |
441 return NULL; | |
442 | |
12932 | 443 memset (mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t)); |
444 memset (mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t)); | |
9857 | 445 |
446 mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (BUFFER_SIZE + 4, | |
12932 | 447 MPEG2_ALLOC_CHUNK); |
9857 | 448 |
12932 | 449 mpeg2dec->sequence.width = (unsigned)-1; |
450 mpeg2_reset (mpeg2dec, 1); | |
9857 | 451 |
452 return mpeg2dec; | |
453 } | |
454 | |
455 void mpeg2_close (mpeg2dec_t * mpeg2dec) | |
456 { | |
12932 | 457 mpeg2_header_state_init (mpeg2dec); |
9857 | 458 mpeg2_free (mpeg2dec->chunk_buffer); |
459 mpeg2_free (mpeg2dec); | |
460 } |