Mercurial > mplayer.hg
annotate libmpeg2/decode.c @ 10898:716edc005b18
patch from Pierre Lombard <p_l@gmx.fr>
If the sound channel is already busy the async open fails and returns
-EBUSY. There's no need to try to open it synchronously as it will block
mplayer till the sound channel is released.
(Granted there's a very slight chance your sound device happen to be
freed between those two calls but it's not the common case).
The behavior is changed by this oneliner to match the ao_oss behavior
(disable sound if the sound device is busy).
author | attila |
---|---|
date | Sun, 21 Sep 2003 09:49:05 +0000 |
parents | 9af61fc7955c |
children | d0a8810e155c |
rev | line source |
---|---|
9857 | 1 /* |
2 * decode.c | |
3 * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> | |
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" | |
31 #include "mpeg2_internal.h" | |
32 #include "convert.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 * chunk_ptr; | |
48 uint8_t * limit; | |
49 uint8_t byte; | |
50 | |
51 if (!bytes) | |
52 return 0; | |
53 | |
54 current = mpeg2dec->buf_start; | |
55 shift = mpeg2dec->shift; | |
56 chunk_ptr = mpeg2dec->chunk_ptr; | |
57 limit = current + bytes; | |
58 | |
59 do { | |
60 byte = *current++; | |
61 if (shift == 0x00000100) { | |
62 int skipped; | |
63 | |
64 mpeg2dec->shift = 0xffffff00; | |
65 skipped = current - mpeg2dec->buf_start; | |
66 mpeg2dec->buf_start = current; | |
67 return skipped; | |
68 } | |
69 shift = (shift | byte) << 8; | |
70 } while (current < limit); | |
71 | |
72 mpeg2dec->shift = shift; | |
73 mpeg2dec->buf_start = current; | |
74 return 0; | |
75 } | |
76 | |
77 static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes) | |
78 { | |
79 uint8_t * current; | |
80 uint32_t shift; | |
81 uint8_t * chunk_ptr; | |
82 uint8_t * limit; | |
83 uint8_t byte; | |
84 | |
85 if (!bytes) | |
86 return 0; | |
87 | |
88 current = mpeg2dec->buf_start; | |
89 shift = mpeg2dec->shift; | |
90 chunk_ptr = mpeg2dec->chunk_ptr; | |
91 limit = current + bytes; | |
92 | |
93 do { | |
94 byte = *current++; | |
95 if (shift == 0x00000100) { | |
96 int copied; | |
97 | |
98 mpeg2dec->shift = 0xffffff00; | |
99 mpeg2dec->chunk_ptr = chunk_ptr + 1; | |
100 copied = current - mpeg2dec->buf_start; | |
101 mpeg2dec->buf_start = current; | |
102 return copied; | |
103 } | |
104 shift = (shift | byte) << 8; | |
105 *chunk_ptr++ = byte; | |
106 } while (current < limit); | |
107 | |
108 mpeg2dec->shift = shift; | |
109 mpeg2dec->buf_start = current; | |
110 return 0; | |
111 } | |
112 | |
113 void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end) | |
114 { | |
115 mpeg2dec->buf_start = start; | |
116 mpeg2dec->buf_end = end; | |
117 } | |
118 | |
119 static inline int seek_chunk (mpeg2dec_t * mpeg2dec) | |
120 { | |
121 int size, skipped; | |
122 | |
123 size = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
124 skipped = skip_chunk (mpeg2dec, size); | |
125 if (!skipped) { | |
126 mpeg2dec->bytes_since_pts += size; | |
127 return -1; | |
128 } | |
129 mpeg2dec->bytes_since_pts += skipped; | |
130 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
131 return 0; | |
132 } | |
133 | |
134 int mpeg2_seek_header (mpeg2dec_t * mpeg2dec) | |
135 { | |
136 while (mpeg2dec->code != 0xb3 && | |
137 ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 && | |
138 mpeg2dec->code) || mpeg2dec->sequence.width == -1)) | |
139 if (seek_chunk (mpeg2dec)) | |
140 return -1; | |
141 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; | |
142 return mpeg2_parse_header (mpeg2dec); | |
143 } | |
144 | |
145 int mpeg2_seek_sequence (mpeg2dec_t * mpeg2dec) | |
146 { | |
147 mpeg2dec->sequence.width = -1; | |
148 return mpeg2_seek_header (mpeg2dec); | |
149 } | |
150 | |
151 #define RECEIVED(code,state) (((state) << 8) + (code)) | |
152 | |
153 int mpeg2_parse (mpeg2dec_t * mpeg2dec) | |
154 { | |
155 int size_buffer, size_chunk, copied; | |
156 | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
157 if(mpeg2dec->code==0xff){ |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
158 // FIXME: we need to resync stream (esp. mpeg2dec-->code) as we |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
159 // left parser at 0x1FF last time at the end of prev. chunk. |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
160 // Why? mpeg2dec->action is set to mpeg2_header_picture_start, but |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
161 // it will call mpeg2_parse_header() too... |
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 // following code copied from mpeg2_seek_header(): |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
164 while (mpeg2dec->code != 0xb3 && |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
165 ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 && |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
166 mpeg2dec->code) || mpeg2dec->sequence.width == -1)) |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
167 if (seek_chunk (mpeg2dec)) |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
168 return -1; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
169 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
170 } |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
171 |
9857 | 172 if (mpeg2dec->action) { |
173 int state; | |
174 | |
175 state = mpeg2dec->action (mpeg2dec); | |
176 if (state) | |
177 return state; | |
178 } | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
179 |
9857 | 180 while (1) { |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
181 //printf("code=0x%X \n",mpeg2dec->code); |
9857 | 182 while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < |
183 mpeg2dec->nb_decode_slices) { | |
184 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
185 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - | |
186 mpeg2dec->chunk_ptr); | |
187 if (size_buffer <= size_chunk) { | |
188 copied = copy_chunk (mpeg2dec, size_buffer); | |
189 if (!copied) { | |
190 mpeg2dec->bytes_since_pts += size_buffer; | |
191 mpeg2dec->chunk_ptr += size_buffer; | |
192 return -1; | |
193 } | |
194 } else { | |
195 copied = copy_chunk (mpeg2dec, size_chunk); | |
196 if (!copied) { | |
197 /* filled the chunk buffer without finding a start code */ | |
198 mpeg2dec->bytes_since_pts += size_chunk; | |
199 mpeg2dec->action = seek_chunk; | |
200 return STATE_INVALID; | |
201 } | |
202 } | |
203 mpeg2dec->bytes_since_pts += copied; | |
204 | |
205 mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code, | |
206 mpeg2dec->chunk_start); | |
207 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
208 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; | |
209 } | |
210 if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) | |
211 break; | |
212 if (seek_chunk (mpeg2dec)) | |
213 return -1; | |
214 } | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
215 |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
216 //printf("next_code=0x%X state=%d \n",mpeg2dec->code,mpeg2dec->state); |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
217 |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
218 if(mpeg2dec->code==0xff){ |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
219 mpeg2dec->action = mpeg2_header_picture_start; //mpeg2_seek_header; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
220 return mpeg2dec->state; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
221 } |
9857 | 222 |
223 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) { | |
224 case RECEIVED (0x00, STATE_SLICE_1ST): | |
225 case RECEIVED (0x00, STATE_SLICE): | |
226 mpeg2dec->action = mpeg2_header_picture_start; | |
227 break; | |
228 case RECEIVED (0xb7, STATE_SLICE): | |
229 mpeg2dec->action = mpeg2_header_end; | |
230 break; | |
231 case RECEIVED (0xb3, STATE_SLICE): | |
232 case RECEIVED (0xb8, STATE_SLICE): | |
233 mpeg2dec->action = mpeg2_parse_header; | |
234 break; | |
235 default: | |
236 mpeg2dec->action = mpeg2_seek_header; | |
237 return STATE_INVALID; | |
238 } | |
239 return mpeg2dec->state; | |
240 } | |
241 | |
242 int mpeg2_parse_header (mpeg2dec_t * mpeg2dec) | |
243 { | |
244 static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = { | |
245 mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data, | |
246 mpeg2_header_sequence, NULL, NULL, NULL, NULL, mpeg2_header_gop | |
247 }; | |
248 int size_buffer, size_chunk, copied; | |
249 | |
250 mpeg2dec->action = mpeg2_parse_header; | |
251 while (1) { | |
252 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
253 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - | |
254 mpeg2dec->chunk_ptr); | |
255 if (size_buffer <= size_chunk) { | |
256 copied = copy_chunk (mpeg2dec, size_buffer); | |
257 if (!copied) { | |
258 mpeg2dec->bytes_since_pts += size_buffer; | |
259 mpeg2dec->chunk_ptr += size_buffer; | |
260 return -1; | |
261 } | |
262 } else { | |
263 copied = copy_chunk (mpeg2dec, size_chunk); | |
264 if (!copied) { | |
265 /* filled the chunk buffer without finding a start code */ | |
266 mpeg2dec->bytes_since_pts += size_chunk; | |
267 mpeg2dec->code = 0xb4; | |
268 mpeg2dec->action = mpeg2_seek_header; | |
269 return STATE_INVALID; | |
270 } | |
271 } | |
272 mpeg2dec->bytes_since_pts += copied; | |
273 | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
274 //printf("header_code=0x%X state=%d \n",mpeg2dec->code,mpeg2dec->state); |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
275 |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
276 // if(!mpeg2dec->code && mpeg2dec->state==7) |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
277 |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
278 |
9857 | 279 if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) { |
280 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
281 mpeg2dec->action = mpeg2_seek_header; | |
282 return STATE_INVALID; | |
283 } | |
284 | |
285 mpeg2dec->code = mpeg2dec->buf_start[-1]; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
286 |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
287 //printf("next_header_code=0x%X state=%d \n",mpeg2dec->code,mpeg2dec->state); |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
288 |
9857 | 289 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) { |
290 | |
291 /* state transition after a sequence header */ | |
292 case RECEIVED (0x00, STATE_SEQUENCE): | |
293 mpeg2dec->action = mpeg2_header_picture_start; | |
294 case RECEIVED (0xb8, STATE_SEQUENCE): | |
295 mpeg2_header_sequence_finalize (mpeg2dec); | |
296 break; | |
297 | |
298 /* other legal state transitions */ | |
299 case RECEIVED (0x00, STATE_GOP): | |
300 mpeg2dec->action = mpeg2_header_picture_start; | |
301 break; | |
302 case RECEIVED (0x01, STATE_PICTURE): | |
303 case RECEIVED (0x01, STATE_PICTURE_2ND): | |
304 mpeg2dec->action = mpeg2_header_slice_start; | |
305 break; | |
306 | |
307 /* legal headers within a given state */ | |
308 case RECEIVED (0xb2, STATE_SEQUENCE): | |
309 case RECEIVED (0xb2, STATE_GOP): | |
310 case RECEIVED (0xb2, STATE_PICTURE): | |
311 case RECEIVED (0xb2, STATE_PICTURE_2ND): | |
312 case RECEIVED (0xb5, STATE_SEQUENCE): | |
313 case RECEIVED (0xb5, STATE_PICTURE): | |
314 case RECEIVED (0xb5, STATE_PICTURE_2ND): | |
315 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; | |
316 continue; | |
317 | |
318 default: | |
319 mpeg2dec->action = mpeg2_seek_header; | |
320 return STATE_INVALID; | |
321 } | |
322 | |
323 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; | |
324 return mpeg2dec->state; | |
325 } | |
326 } | |
327 | |
328 void mpeg2_convert (mpeg2dec_t * mpeg2dec, | |
329 void (* convert) (int, int, uint32_t, void *, | |
330 struct convert_init_s *), void * arg) | |
331 { | |
332 convert_init_t convert_init; | |
333 int size; | |
334 | |
335 convert_init.id = NULL; | |
336 convert (mpeg2dec->decoder.width, mpeg2dec->decoder.height, | |
337 mpeg2_accels, arg, &convert_init); | |
338 if (convert_init.id_size) { | |
339 convert_init.id = mpeg2dec->convert_id = | |
340 mpeg2_malloc (convert_init.id_size, ALLOC_CONVERT_ID); | |
341 convert (mpeg2dec->decoder.width, mpeg2dec->decoder.height, | |
342 mpeg2_accels, arg, &convert_init); | |
343 } | |
344 mpeg2dec->convert_size[0] = size = convert_init.buf_size[0]; | |
345 mpeg2dec->convert_size[1] = size += convert_init.buf_size[1]; | |
346 mpeg2dec->convert_size[2] = size += convert_init.buf_size[2]; | |
347 mpeg2dec->convert_start = convert_init.start; | |
348 mpeg2dec->convert_copy = convert_init.copy; | |
349 | |
350 size = mpeg2dec->decoder.width * mpeg2dec->decoder.height >> 2; | |
351 mpeg2dec->yuv_buf[0][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV); | |
352 mpeg2dec->yuv_buf[0][1] = mpeg2dec->yuv_buf[0][0] + 4 * size; | |
353 mpeg2dec->yuv_buf[0][2] = mpeg2dec->yuv_buf[0][0] + 5 * size; | |
354 mpeg2dec->yuv_buf[1][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV); | |
355 mpeg2dec->yuv_buf[1][1] = mpeg2dec->yuv_buf[1][0] + 4 * size; | |
356 mpeg2dec->yuv_buf[1][2] = mpeg2dec->yuv_buf[1][0] + 5 * size; | |
357 size = mpeg2dec->decoder.width * 8; | |
358 mpeg2dec->yuv_buf[2][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV); | |
359 mpeg2dec->yuv_buf[2][1] = mpeg2dec->yuv_buf[2][0] + 4 * size; | |
360 mpeg2dec->yuv_buf[2][2] = mpeg2dec->yuv_buf[2][0] + 5 * size; | |
361 } | |
362 | |
363 void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id) | |
364 { | |
365 fbuf_t * fbuf; | |
366 | |
367 if (mpeg2dec->custom_fbuf) { | |
368 mpeg2_set_fbuf (mpeg2dec, mpeg2dec->decoder.coding_type); | |
369 fbuf = mpeg2dec->fbuf[0]; | |
370 if (mpeg2dec->state == STATE_SEQUENCE) { | |
371 mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; | |
372 mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; | |
373 } | |
374 } else { | |
375 fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf); | |
376 mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index; | |
377 } | |
378 fbuf->buf[0] = buf[0]; | |
379 fbuf->buf[1] = buf[1]; | |
380 fbuf->buf[2] = buf[2]; | |
381 fbuf->id = id; | |
9858
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
382 // 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
|
383 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
|
384 mpeg2dec->fbuf[1]->buf[0]=buf[0]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
385 mpeg2dec->fbuf[1]->buf[1]=buf[1]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
386 mpeg2dec->fbuf[1]->buf[2]=buf[2]; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
387 mpeg2dec->fbuf[1]->id=NULL; |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
388 } |
9af61fc7955c
changed input and output buffer handling to be mplayer-compatible...
arpi
parents:
9857
diff
changeset
|
389 // 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
|
390 // mpeg2dec->fbuf[0]->buf[0],mpeg2dec->fbuf[1]->buf[0],mpeg2dec->fbuf[2]->buf[0]); |
9857 | 391 } |
392 | |
393 void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf) | |
394 { | |
395 mpeg2dec->custom_fbuf = custom_fbuf; | |
396 } | |
397 | |
398 void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip) | |
399 { | |
400 mpeg2dec->first_decode_slice = 1; | |
401 mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1); | |
402 } | |
403 | |
404 void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end) | |
405 { | |
406 start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start; | |
407 end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end; | |
408 mpeg2dec->first_decode_slice = start; | |
409 mpeg2dec->nb_decode_slices = end - start; | |
410 } | |
411 | |
412 void mpeg2_pts (mpeg2dec_t * mpeg2dec, uint32_t pts) | |
413 { | |
414 mpeg2dec->pts_previous = mpeg2dec->pts_current; | |
415 mpeg2dec->pts_current = pts; | |
416 mpeg2dec->num_pts++; | |
417 mpeg2dec->bytes_since_pts = 0; | |
418 } | |
419 | |
420 uint32_t mpeg2_accel (uint32_t accel) | |
421 { | |
422 if (!mpeg2_accels) { | |
423 if (accel & MPEG2_ACCEL_DETECT) | |
424 accel |= mpeg2_detect_accel (); | |
425 mpeg2_accels = accel |= MPEG2_ACCEL_DETECT; | |
426 mpeg2_cpu_state_init (accel); | |
427 mpeg2_idct_init (accel); | |
428 mpeg2_mc_init (accel); | |
429 } | |
430 return mpeg2_accels & ~MPEG2_ACCEL_DETECT; | |
431 } | |
432 | |
433 mpeg2dec_t * mpeg2_init (void) | |
434 { | |
435 mpeg2dec_t * mpeg2dec; | |
436 | |
437 mpeg2_accel (MPEG2_ACCEL_DETECT); | |
438 | |
439 mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t), | |
440 ALLOC_MPEG2DEC); | |
441 if (mpeg2dec == NULL) | |
442 return NULL; | |
443 | |
444 memset (mpeg2dec, 0, sizeof (mpeg2dec_t)); | |
445 | |
446 mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (BUFFER_SIZE + 4, | |
447 ALLOC_CHUNK); | |
448 | |
449 mpeg2dec->shift = 0xffffff00; | |
450 mpeg2dec->action = mpeg2_seek_sequence; | |
451 mpeg2dec->code = 0xb4; | |
452 mpeg2dec->first_decode_slice = 1; | |
453 mpeg2dec->nb_decode_slices = 0xb0 - 1; | |
454 mpeg2dec->convert_id = NULL; | |
455 | |
456 /* initialize substructures */ | |
457 mpeg2_header_state_init (mpeg2dec); | |
458 | |
459 return mpeg2dec; | |
460 } | |
461 | |
462 void mpeg2_close (mpeg2dec_t * mpeg2dec) | |
463 { | |
464 int i; | |
465 | |
466 /* static uint8_t finalizer[] = {0,0,1,0xb4}; */ | |
467 /* mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4); */ | |
468 | |
469 mpeg2_free (mpeg2dec->chunk_buffer); | |
470 if (!mpeg2dec->custom_fbuf) | |
471 for (i = mpeg2dec->alloc_index_user; i < mpeg2dec->alloc_index; i++) | |
472 mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[0]); | |
473 if (mpeg2dec->convert_start) | |
474 for (i = 0; i < 3; i++) | |
475 mpeg2_free (mpeg2dec->yuv_buf[i][0]); | |
476 if (mpeg2dec->convert_id) | |
477 mpeg2_free (mpeg2dec->convert_id); | |
478 mpeg2_free (mpeg2dec); | |
479 } |