Mercurial > mplayer.hg
annotate libmpeg2/decode.c @ 13395:07708ec98d87
New MD5 sum video output driver. For every frame, it calculates the MD5 sum
and writes a list of those sums to an, optionally specified, output file.
It does not rely on external programs to be installed. The MD5 sum code is
borrowed from the uCIFS library, written by Christopher R. Hertel in 2004
and released under the LGPL license.
Note: This driver is not yet activated and will not be compiled and linked
to libvo. A separate patch will take care of that. This is just for adding
the files to the repository.
author | ivo |
---|---|
date | Mon, 20 Sep 2004 01:01:08 +0000 |
parents | d0a8810e155c |
children | 1385ec491ffb |
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 | |
22 */ | |
23 | |
24 #include "config.h" | |
25 | |
26 #include <string.h> /* memcmp/memset, try to remove */ | |
27 #include <stdlib.h> | |
28 #include <inttypes.h> | |
29 | |
30 #include "mpeg2.h" | |
12932 | 31 #include "attributes.h" |
9857 | 32 #include "mpeg2_internal.h" |
33 | |
34 static int mpeg2_accels = 0; | |
35 | |
36 #define BUFFER_SIZE (1194 * 1024) | |
37 | |
38 const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec) | |
39 { | |
40 return &(mpeg2dec->info); | |
41 } | |
42 | |
43 static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes) | |
44 { | |
45 uint8_t * current; | |
46 uint32_t shift; | |
47 uint8_t * limit; | |
48 uint8_t byte; | |
49 | |
50 if (!bytes) | |
51 return 0; | |
52 | |
53 current = mpeg2dec->buf_start; | |
54 shift = mpeg2dec->shift; | |
55 limit = current + bytes; | |
56 | |
57 do { | |
58 byte = *current++; | |
59 if (shift == 0x00000100) { | |
60 int skipped; | |
61 | |
62 mpeg2dec->shift = 0xffffff00; | |
63 skipped = current - mpeg2dec->buf_start; | |
64 mpeg2dec->buf_start = current; | |
65 return skipped; | |
66 } | |
67 shift = (shift | byte) << 8; | |
68 } while (current < limit); | |
69 | |
70 mpeg2dec->shift = shift; | |
71 mpeg2dec->buf_start = current; | |
72 return 0; | |
73 } | |
74 | |
75 static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes) | |
76 { | |
77 uint8_t * current; | |
78 uint32_t shift; | |
79 uint8_t * chunk_ptr; | |
80 uint8_t * limit; | |
81 uint8_t byte; | |
82 | |
83 if (!bytes) | |
84 return 0; | |
85 | |
86 current = mpeg2dec->buf_start; | |
87 shift = mpeg2dec->shift; | |
88 chunk_ptr = mpeg2dec->chunk_ptr; | |
89 limit = current + bytes; | |
90 | |
91 do { | |
92 byte = *current++; | |
93 if (shift == 0x00000100) { | |
94 int copied; | |
95 | |
96 mpeg2dec->shift = 0xffffff00; | |
97 mpeg2dec->chunk_ptr = chunk_ptr + 1; | |
98 copied = current - mpeg2dec->buf_start; | |
99 mpeg2dec->buf_start = current; | |
100 return copied; | |
101 } | |
102 shift = (shift | byte) << 8; | |
103 *chunk_ptr++ = byte; | |
104 } while (current < limit); | |
105 | |
106 mpeg2dec->shift = shift; | |
107 mpeg2dec->buf_start = current; | |
108 return 0; | |
109 } | |
110 | |
111 void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end) | |
112 { | |
113 mpeg2dec->buf_start = start; | |
114 mpeg2dec->buf_end = end; | |
115 } | |
116 | |
12932 | 117 int mpeg2_getpos (mpeg2dec_t * mpeg2dec) |
118 { | |
119 return mpeg2dec->buf_end - mpeg2dec->buf_start; | |
120 } | |
121 | |
122 static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec) | |
9857 | 123 { |
124 int size, skipped; | |
125 | |
126 size = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
127 skipped = skip_chunk (mpeg2dec, size); | |
128 if (!skipped) { | |
12932 | 129 mpeg2dec->bytes_since_tag += size; |
130 return STATE_BUFFER; | |
9857 | 131 } |
12932 | 132 mpeg2dec->bytes_since_tag += skipped; |
9857 | 133 mpeg2dec->code = mpeg2dec->buf_start[-1]; |
12932 | 134 return (mpeg2_state_t)-1; |
9857 | 135 } |
136 | |
12932 | 137 mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec) |
9857 | 138 { |
139 while (mpeg2dec->code != 0xb3 && | |
140 ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 && | |
12932 | 141 mpeg2dec->code) || mpeg2dec->sequence.width == (unsigned)-1)) |
142 if (seek_chunk (mpeg2dec) == STATE_BUFFER) | |
143 return STATE_BUFFER; | |
9857 | 144 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; |
12932 | 145 mpeg2dec->user_data_len = 0; |
146 return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) : | |
147 mpeg2_header_picture_start (mpeg2dec)); | |
9857 | 148 } |
149 | |
150 #define RECEIVED(code,state) (((state) << 8) + (code)) | |
151 | |
12932 | 152 mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec) |
9857 | 153 { |
154 int size_buffer, size_chunk, copied; | |
155 | |
12932 | 156 if (mpeg2dec->action) { |
157 mpeg2_state_t state; | |
158 | |
159 state = mpeg2dec->action (mpeg2dec); | |
160 if ((int)state >= 0) | |
161 return state; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
162 } |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
163 |
9857 | 164 while (1) { |
165 while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < | |
166 mpeg2dec->nb_decode_slices) { | |
167 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
168 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - | |
169 mpeg2dec->chunk_ptr); | |
170 if (size_buffer <= size_chunk) { | |
171 copied = copy_chunk (mpeg2dec, size_buffer); | |
172 if (!copied) { | |
12932 | 173 mpeg2dec->bytes_since_tag += size_buffer; |
9857 | 174 mpeg2dec->chunk_ptr += size_buffer; |
12932 | 175 return STATE_BUFFER; |
9857 | 176 } |
177 } else { | |
178 copied = copy_chunk (mpeg2dec, size_chunk); | |
179 if (!copied) { | |
180 /* filled the chunk buffer without finding a start code */ | |
12932 | 181 mpeg2dec->bytes_since_tag += size_chunk; |
9857 | 182 mpeg2dec->action = seek_chunk; |
183 return STATE_INVALID; | |
184 } | |
185 } | |
12932 | 186 mpeg2dec->bytes_since_tag += copied; |
9857 | 187 |
188 mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code, | |
189 mpeg2dec->chunk_start); | |
190 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
191 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; | |
192 } | |
193 if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) | |
194 break; | |
12932 | 195 if (seek_chunk (mpeg2dec) == STATE_BUFFER) |
196 return STATE_BUFFER; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
197 } |
9857 | 198 |
12932 | 199 switch (mpeg2dec->code) { |
200 case 0x00: | |
9857 | 201 mpeg2dec->action = mpeg2_header_picture_start; |
12932 | 202 return mpeg2dec->state; |
203 case 0xb7: | |
9857 | 204 mpeg2dec->action = mpeg2_header_end; |
205 break; | |
12932 | 206 case 0xb3: |
207 case 0xb8: | |
9857 | 208 mpeg2dec->action = mpeg2_parse_header; |
209 break; | |
210 default: | |
12932 | 211 mpeg2dec->action = seek_chunk; |
9857 | 212 return STATE_INVALID; |
213 } | |
12932 | 214 return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID; |
9857 | 215 } |
216 | |
12932 | 217 mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec) |
9857 | 218 { |
219 static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = { | |
220 mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data, | |
221 mpeg2_header_sequence, NULL, NULL, NULL, NULL, mpeg2_header_gop | |
222 }; | |
223 int size_buffer, size_chunk, copied; | |
224 | |
225 mpeg2dec->action = mpeg2_parse_header; | |
12932 | 226 mpeg2dec->info.user_data = NULL; mpeg2dec->info.user_data_len = 0; |
9857 | 227 while (1) { |
228 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
229 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - | |
230 mpeg2dec->chunk_ptr); | |
231 if (size_buffer <= size_chunk) { | |
232 copied = copy_chunk (mpeg2dec, size_buffer); | |
233 if (!copied) { | |
12932 | 234 mpeg2dec->bytes_since_tag += size_buffer; |
9857 | 235 mpeg2dec->chunk_ptr += size_buffer; |
12932 | 236 return STATE_BUFFER; |
9857 | 237 } |
238 } else { | |
239 copied = copy_chunk (mpeg2dec, size_chunk); | |
240 if (!copied) { | |
241 /* filled the chunk buffer without finding a start code */ | |
12932 | 242 mpeg2dec->bytes_since_tag += size_chunk; |
9857 | 243 mpeg2dec->code = 0xb4; |
244 mpeg2dec->action = mpeg2_seek_header; | |
245 return STATE_INVALID; | |
246 } | |
247 } | |
12932 | 248 mpeg2dec->bytes_since_tag += copied; |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
249 |
9857 | 250 if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) { |
251 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
252 mpeg2dec->action = mpeg2_seek_header; | |
253 return STATE_INVALID; | |
254 } | |
255 | |
256 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
257 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) { | |
258 | |
259 /* state transition after a sequence header */ | |
260 case RECEIVED (0x00, STATE_SEQUENCE): | |
261 mpeg2dec->action = mpeg2_header_picture_start; | |
262 case RECEIVED (0xb8, STATE_SEQUENCE): | |
263 mpeg2_header_sequence_finalize (mpeg2dec); | |
264 break; | |
265 | |
266 /* other legal state transitions */ | |
267 case RECEIVED (0x00, STATE_GOP): | |
12932 | 268 mpeg2_header_gop_finalize (mpeg2dec); |
9857 | 269 mpeg2dec->action = mpeg2_header_picture_start; |
270 break; | |
271 case RECEIVED (0x01, STATE_PICTURE): | |
272 case RECEIVED (0x01, STATE_PICTURE_2ND): | |
12932 | 273 mpeg2_header_picture_finalize (mpeg2dec, mpeg2_accels); |
9857 | 274 mpeg2dec->action = mpeg2_header_slice_start; |
275 break; | |
276 | |
277 /* legal headers within a given state */ | |
278 case RECEIVED (0xb2, STATE_SEQUENCE): | |
279 case RECEIVED (0xb2, STATE_GOP): | |
280 case RECEIVED (0xb2, STATE_PICTURE): | |
281 case RECEIVED (0xb2, STATE_PICTURE_2ND): | |
282 case RECEIVED (0xb5, STATE_SEQUENCE): | |
283 case RECEIVED (0xb5, STATE_PICTURE): | |
284 case RECEIVED (0xb5, STATE_PICTURE_2ND): | |
285 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; | |
286 continue; | |
287 | |
288 default: | |
289 mpeg2dec->action = mpeg2_seek_header; | |
290 return STATE_INVALID; | |
291 } | |
292 | |
293 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; | |
12932 | 294 mpeg2dec->user_data_len = 0; |
9857 | 295 return mpeg2dec->state; |
296 } | |
297 } | |
298 | |
12932 | 299 int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg) |
9857 | 300 { |
12932 | 301 mpeg2_convert_init_t convert_init; |
302 int error; | |
9857 | 303 |
12932 | 304 error = convert (MPEG2_CONVERT_SET, NULL, &(mpeg2dec->sequence), 0, |
305 mpeg2_accels, arg, &convert_init); | |
306 if (!error) { | |
307 mpeg2dec->convert = convert; | |
308 mpeg2dec->convert_arg = arg; | |
309 mpeg2dec->convert_id_size = convert_init.id_size; | |
310 mpeg2dec->convert_stride = 0; | |
9857 | 311 } |
12932 | 312 return error; |
313 } | |
9857 | 314 |
12932 | 315 int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride) |
316 { | |
317 if (!mpeg2dec->convert) { | |
318 if (stride < (int) mpeg2dec->sequence.width) | |
319 stride = mpeg2dec->sequence.width; | |
320 mpeg2dec->decoder.stride_frame = stride; | |
321 } else { | |
322 mpeg2_convert_init_t convert_init; | |
323 | |
324 stride = mpeg2dec->convert (MPEG2_CONVERT_STRIDE, NULL, | |
325 &(mpeg2dec->sequence), stride, | |
326 mpeg2_accels, mpeg2dec->convert_arg, | |
327 &convert_init); | |
328 mpeg2dec->convert_id_size = convert_init.id_size; | |
329 mpeg2dec->convert_stride = stride; | |
330 } | |
331 return stride; | |
9857 | 332 } |
333 | |
334 void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id) | |
335 { | |
12932 | 336 mpeg2_fbuf_t * fbuf; |
9857 | 337 |
338 if (mpeg2dec->custom_fbuf) { | |
339 if (mpeg2dec->state == STATE_SEQUENCE) { | |
340 mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; | |
341 mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; | |
342 } | |
12932 | 343 mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type == |
344 PIC_FLAG_CODING_TYPE_B)); | |
345 fbuf = mpeg2dec->fbuf[0]; | |
9857 | 346 } else { |
347 fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf); | |
348 mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index; | |
349 } | |
350 fbuf->buf[0] = buf[0]; | |
351 fbuf->buf[1] = buf[1]; | |
352 fbuf->buf[2] = buf[2]; | |
353 fbuf->id = id; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
354 // 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
|
355 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
|
356 mpeg2dec->fbuf[1]->buf[0]=buf[0]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
357 mpeg2dec->fbuf[1]->buf[1]=buf[1]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
358 mpeg2dec->fbuf[1]->buf[2]=buf[2]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
359 mpeg2dec->fbuf[1]->id=NULL; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
360 } |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
361 // 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
|
362 // mpeg2dec->fbuf[0]->buf[0],mpeg2dec->fbuf[1]->buf[0],mpeg2dec->fbuf[2]->buf[0]); |
9857 | 363 } |
364 | |
365 void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf) | |
366 { | |
367 mpeg2dec->custom_fbuf = custom_fbuf; | |
368 } | |
369 | |
370 void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip) | |
371 { | |
372 mpeg2dec->first_decode_slice = 1; | |
373 mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1); | |
374 } | |
375 | |
376 void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end) | |
377 { | |
378 start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start; | |
379 end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end; | |
380 mpeg2dec->first_decode_slice = start; | |
381 mpeg2dec->nb_decode_slices = end - start; | |
382 } | |
383 | |
12932 | 384 void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2) |
9857 | 385 { |
12932 | 386 mpeg2dec->tag_previous = mpeg2dec->tag_current; |
387 mpeg2dec->tag2_previous = mpeg2dec->tag2_current; | |
388 mpeg2dec->tag_current = tag; | |
389 mpeg2dec->tag2_current = tag2; | |
390 mpeg2dec->num_tags++; | |
391 mpeg2dec->bytes_since_tag = 0; | |
9857 | 392 } |
393 | |
394 uint32_t mpeg2_accel (uint32_t accel) | |
395 { | |
396 if (!mpeg2_accels) { | |
397 if (accel & MPEG2_ACCEL_DETECT) | |
398 accel |= mpeg2_detect_accel (); | |
399 mpeg2_accels = accel |= MPEG2_ACCEL_DETECT; | |
400 mpeg2_cpu_state_init (accel); | |
401 mpeg2_idct_init (accel); | |
402 mpeg2_mc_init (accel); | |
403 } | |
404 return mpeg2_accels & ~MPEG2_ACCEL_DETECT; | |
405 } | |
406 | |
12932 | 407 void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset) |
408 { | |
409 mpeg2dec->buf_start = mpeg2dec->buf_end = NULL; | |
410 mpeg2dec->num_tags = 0; | |
411 mpeg2dec->shift = 0xffffff00; | |
412 mpeg2dec->code = 0xb4; | |
413 mpeg2dec->action = mpeg2_seek_header; | |
414 mpeg2dec->state = STATE_INVALID; | |
415 mpeg2dec->first = 1; | |
416 | |
417 mpeg2_reset_info(&(mpeg2dec->info)); | |
418 mpeg2dec->info.gop = NULL; | |
419 mpeg2dec->info.user_data = NULL; | |
420 mpeg2dec->info.user_data_len = 0; | |
421 if (full_reset) { | |
422 mpeg2dec->info.sequence = NULL; | |
423 mpeg2_header_state_init (mpeg2dec); | |
424 } | |
425 | |
426 } | |
427 | |
9857 | 428 mpeg2dec_t * mpeg2_init (void) |
429 { | |
430 mpeg2dec_t * mpeg2dec; | |
431 | |
432 mpeg2_accel (MPEG2_ACCEL_DETECT); | |
433 | |
434 mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t), | |
12932 | 435 MPEG2_ALLOC_MPEG2DEC); |
9857 | 436 if (mpeg2dec == NULL) |
437 return NULL; | |
438 | |
12932 | 439 memset (mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t)); |
440 memset (mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t)); | |
9857 | 441 |
442 mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (BUFFER_SIZE + 4, | |
12932 | 443 MPEG2_ALLOC_CHUNK); |
9857 | 444 |
12932 | 445 mpeg2dec->sequence.width = (unsigned)-1; |
446 mpeg2_reset (mpeg2dec, 1); | |
9857 | 447 |
448 return mpeg2dec; | |
449 } | |
450 | |
451 void mpeg2_close (mpeg2dec_t * mpeg2dec) | |
452 { | |
12932 | 453 mpeg2_header_state_init (mpeg2dec); |
9857 | 454 mpeg2_free (mpeg2dec->chunk_buffer); |
455 mpeg2_free (mpeg2dec); | |
456 } |