Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c | 597 |
1 files changed, 597 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c new file mode 100644 index 0000000..a9f113e --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c | |||
@@ -0,0 +1,597 @@ | |||
1 | #include "../libmpeg3.h" | ||
2 | #include "../mpeg3protos.h" | ||
3 | #include "mpeg3video.h" | ||
4 | #include "mpeg3videoprotos.h" | ||
5 | #include <stdlib.h> | ||
6 | |||
7 | unsigned char mpeg3_zig_zag_scan_mmx[64] = | ||
8 | { | ||
9 | 0*8+0 /* 0*/, 1*8+0 /* 1*/, 0*8+1 /* 8*/, 0*8+2 /*16*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 3*8+0 /* 3*/, 2*8+1 /*10*/, | ||
10 | 1*8+2 /*17*/, 0*8+3 /*24*/, 0*8+4 /*32*/, 1*8+3 /*25*/, 2*8+2 /*18*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 5*8+0 /* 5*/, | ||
11 | 4*8+1 /*12*/, 5*8+2 /*19*/, 2*8+3 /*26*/, 1*8+4 /*33*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 1*8+5 /*41*/, 2*8+4 /*34*/, | ||
12 | 3*8+3 /*27*/, 4*8+2 /*20*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 7*8+0 /* 7*/, 6*8+1 /*14*/, 5*8+2 /*21*/, 4*8+3 /*28*/, | ||
13 | 3*8+4 /*35*/, 2*8+5 /*42*/, 1*8+6 /*49*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 2*8+6 /*50*/, 3*8+5 /*43*/, 4*8+4 /*36*/, | ||
14 | 5*8+3 /*29*/, 6*8+2 /*22*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 6*8+3 /*30*/, 5*8+4 /*37*/, 4*8+5 /*44*/, 3*8+6 /*51*/, | ||
15 | 2*8+7 /*58*/, 3*8+7 /*59*/, 4*8+6 /*52*/, 5*8+5 /*45*/, 6*8+4 /*38*/, 7*8+3 /*31*/, 7*8+4 /*39*/, 6*8+5 /*46*/, | ||
16 | 7*8+6 /*53*/, 4*8+7 /*60*/, 5*8+7 /*61*/, 6*8+6 /*54*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 6*8+7 /*62*/, 7*8+7 /*63*/ | ||
17 | }; | ||
18 | |||
19 | /* alternate scan */ | ||
20 | unsigned char mpeg3_alternate_scan_mmx[64] = | ||
21 | { | ||
22 | 0*8+0 /*0 */, 0*8+1 /* 8*/, 0*8+2 /*16*/, 0*8+3 /*24*/, 1*8+0 /* 1*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 2*8+1 /*10*/, | ||
23 | 1*8+2 /*17*/, 1*8+3 /*25*/, 0*8+4 /*32*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 1*8+6 /*49*/, | ||
24 | 1*8+5 /*41*/, 1*8+4 /*33*/, 2*8+3 /*26*/, 2*8+2 /*18*/, 3*8+0 /* 3*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 4*8+1 /*12*/, | ||
25 | 3*8+2 /*19*/, 3*8+3 /*27*/, 2*8+4 /*34*/, 2*8+5 /*42*/, 2*8+6 /*50*/, 2*8+7 /*58*/, 3*8+4 /*35*/, 3*8+5 /*43*/, | ||
26 | 3*8+6 /*51*/, 3*8+7 /*59*/, 4*8+2 /*20*/, 4*8+3 /*28*/, 5*8+0 /* 5*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 6*8+1 /*14*/, | ||
27 | 5*8+2 /*21*/, 5*8+3 /*29*/, 4*8+4 /*36*/, 4*8+5 /*44*/, 4*8+6 /*52*/, 4*8+7 /*60*/, 5*8+4 /*37*/, 5*8+5 /*45*/, | ||
28 | 5*8+6 /*53*/, 5*8+7 /*61*/, 6*8+2 /*22*/, 6*8+3 /*30*/, 7*8+0 /* 7*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 7*8+3 /*31*/, | ||
29 | 6*8+4 /*38*/, 6*8+5 /*46*/, 6*8+6 /*54*/, 6*8+7 /*62*/, 7*8+4 /*39*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 7*8+6 /*63*/ | ||
30 | }; | ||
31 | |||
32 | |||
33 | |||
34 | /* zig-zag scan */ | ||
35 | unsigned char mpeg3_zig_zag_scan_nommx[64] = | ||
36 | { | ||
37 | 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, | ||
38 | 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, | ||
39 | 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, | ||
40 | 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 | ||
41 | }; | ||
42 | |||
43 | /* alternate scan */ | ||
44 | unsigned char mpeg3_alternate_scan_nommx[64] = | ||
45 | { | ||
46 | 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, | ||
47 | 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, | ||
48 | 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, | ||
49 | 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 | ||
50 | }; | ||
51 | |||
52 | /* default intra quantization matrix */ | ||
53 | unsigned char mpeg3_default_intra_quantizer_matrix[64] = | ||
54 | { | ||
55 | 8, 16, 19, 22, 26, 27, 29, 34, | ||
56 | 16, 16, 22, 24, 27, 29, 34, 37, | ||
57 | 19, 22, 26, 27, 29, 34, 34, 38, | ||
58 | 22, 22, 26, 27, 29, 34, 37, 40, | ||
59 | 22, 26, 27, 29, 32, 35, 40, 48, | ||
60 | 26, 27, 29, 32, 35, 40, 48, 58, | ||
61 | 26, 27, 29, 34, 38, 46, 56, 69, | ||
62 | 27, 29, 35, 38, 46, 56, 69, 83 | ||
63 | }; | ||
64 | |||
65 | unsigned char mpeg3_non_linear_mquant_table[32] = | ||
66 | { | ||
67 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
68 | 8, 10, 12, 14, 16, 18, 20, 22, | ||
69 | 24, 28, 32, 36, 40, 44, 48, 52, | ||
70 | 56, 64, 72, 80, 88, 96, 104, 112 | ||
71 | }; | ||
72 | |||
73 | double mpeg3_frame_rate_table[16] = | ||
74 | { | ||
75 | 0.0, /* Pad */ | ||
76 | 24000.0/1001.0, /* Official frame rates */ | ||
77 | 24.0, | ||
78 | 25.0, | ||
79 | 30000.0/1001.0, | ||
80 | 30.0, | ||
81 | 50.0, | ||
82 | ((60.0*1000.0)/1001.0), | ||
83 | 60.0, | ||
84 | |||
85 | 1, /* Unofficial economy rates */ | ||
86 | 5, | ||
87 | 10, | ||
88 | 12, | ||
89 | 15, | ||
90 | 0, | ||
91 | 0, | ||
92 | }; | ||
93 | |||
94 | int mpeg3video_initdecoder(mpeg3video_t *video) | ||
95 | { | ||
96 | int blk_cnt_tab[3] = {6, 8, 12}; | ||
97 | int cc; | ||
98 | int i; | ||
99 | long size[4], padding[2]; /* Size of Y, U, and V buffers */ | ||
100 | |||
101 | if(!video->mpeg2) | ||
102 | { | ||
103 | /* force MPEG-1 parameters */ | ||
104 | video->prog_seq = 1; | ||
105 | video->prog_frame = 1; | ||
106 | video->pict_struct = FRAME_PICTURE; | ||
107 | video->frame_pred_dct = 1; | ||
108 | video->chroma_format = CHROMA420; | ||
109 | video->matrix_coefficients = 5; | ||
110 | } | ||
111 | |||
112 | /* Get dimensions rounded to nearest multiple of coded macroblocks */ | ||
113 | video->mb_width = (video->horizontal_size + 15) / 16; | ||
114 | video->mb_height = (video->mpeg2 && !video->prog_seq) ? | ||
115 | (2 * ((video->vertical_size + 31) / 32)) : | ||
116 | ((video->vertical_size + 15) / 16); | ||
117 | video->coded_picture_width = 16 * video->mb_width; | ||
118 | video->coded_picture_height = 16 * video->mb_height; | ||
119 | video->chrom_width = (video->chroma_format == CHROMA444) ? | ||
120 | video->coded_picture_width : | ||
121 | (video->coded_picture_width >> 1); | ||
122 | video->chrom_height = (video->chroma_format != CHROMA420) ? | ||
123 | video->coded_picture_height : | ||
124 | (video->coded_picture_height >> 1); | ||
125 | video->blk_cnt = blk_cnt_tab[video->chroma_format - 1]; | ||
126 | |||
127 | /* Get sizes of YUV buffers */ | ||
128 | padding[0] = 16 * video->coded_picture_width; | ||
129 | size[0] = video->coded_picture_width * video->coded_picture_height + padding[0] * 2; | ||
130 | |||
131 | padding[1] = 16 * video->chrom_width; | ||
132 | size[1] = video->chrom_width * video->chrom_height + 2 * padding[1]; | ||
133 | |||
134 | size[2] = (video->llw * video->llh); | ||
135 | size[3] = (video->llw * video->llh) / 4; | ||
136 | |||
137 | /* Allocate contiguous fragments for YUV buffers for hardware YUV decoding */ | ||
138 | video->yuv_buffer[0] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); | ||
139 | video->yuv_buffer[1] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); | ||
140 | video->yuv_buffer[2] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); | ||
141 | |||
142 | if(video->scalable_mode == SC_SPAT) | ||
143 | { | ||
144 | video->yuv_buffer[3] = (unsigned char*)calloc(1, size[2] + 2 * size[3]); | ||
145 | video->yuv_buffer[4] = (unsigned char*)calloc(1, size[2] + 2 * size[3]); | ||
146 | } | ||
147 | |||
148 | /* Direct pointers to areas of contiguous fragments in YVU order per Microsoft */ | ||
149 | for(cc = 0; cc < 3; cc++) | ||
150 | { | ||
151 | video->llframe0[cc] = 0; | ||
152 | video->llframe1[cc] = 0; | ||
153 | video->newframe[cc] = 0; | ||
154 | } | ||
155 | |||
156 | video->refframe[0] = video->yuv_buffer[0]; | ||
157 | video->oldrefframe[0] = video->yuv_buffer[1]; | ||
158 | video->auxframe[0] = video->yuv_buffer[2]; | ||
159 | video->refframe[2] = video->yuv_buffer[0] + size[0] + padding[0]; | ||
160 | video->oldrefframe[2] = video->yuv_buffer[1] + size[0] + padding[0]; | ||
161 | video->auxframe[2] = video->yuv_buffer[2] + size[0] + padding[0]; | ||
162 | video->refframe[1] = video->yuv_buffer[0] + size[0] + padding[0] + size[1] + padding[1]; | ||
163 | video->oldrefframe[1] = video->yuv_buffer[1] + size[0] + padding[0] + size[1] + padding[1]; | ||
164 | video->auxframe[1] = video->yuv_buffer[2] + size[0] + padding[0] + size[1] + padding[1]; | ||
165 | |||
166 | if(video->scalable_mode == SC_SPAT) | ||
167 | { | ||
168 | /* this assumes lower layer is 4:2:0 */ | ||
169 | video->llframe0[0] = video->yuv_buffer[3] + padding[0] ; | ||
170 | video->llframe1[0] = video->yuv_buffer[4] + padding[0] ; | ||
171 | video->llframe0[2] = video->yuv_buffer[3] + padding[1] + size[2] ; | ||
172 | video->llframe1[2] = video->yuv_buffer[4] + padding[1] + size[2] ; | ||
173 | video->llframe0[1] = video->yuv_buffer[3] + padding[1] + size[2] + size[3]; | ||
174 | video->llframe1[1] = video->yuv_buffer[4] + padding[1] + size[2] + size[3]; | ||
175 | } | ||
176 | |||
177 | /* Initialize the YUV tables for software YUV decoding */ | ||
178 | video->cr_to_r = (long*)malloc(sizeof(long) * 256); | ||
179 | video->cr_to_g = (long*)malloc(sizeof(long) * 256); | ||
180 | video->cb_to_g = (long*)malloc(sizeof(long) * 256); | ||
181 | video->cb_to_b = (long*)malloc(sizeof(long) * 256); | ||
182 | video->cr_to_r_ptr = video->cr_to_r + 128; | ||
183 | video->cr_to_g_ptr = video->cr_to_g + 128; | ||
184 | video->cb_to_g_ptr = video->cb_to_g + 128; | ||
185 | video->cb_to_b_ptr = video->cb_to_b + 128; | ||
186 | |||
187 | for(i = -128; i < 128; i++) | ||
188 | { | ||
189 | video->cr_to_r_ptr[i] = (long)( 1.371 * 65536 * i); | ||
190 | video->cr_to_g_ptr[i] = (long)(-0.698 * 65536 * i); | ||
191 | video->cb_to_g_ptr[i] = (long)(-0.336 * 65536 * i); | ||
192 | video->cb_to_b_ptr[i] = (long)( 1.732 * 65536 * i); | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | int mpeg3video_deletedecoder(mpeg3video_t *video) | ||
199 | { | ||
200 | int i, padding; | ||
201 | |||
202 | free(video->yuv_buffer[0]); | ||
203 | free(video->yuv_buffer[1]); | ||
204 | free(video->yuv_buffer[2]); | ||
205 | |||
206 | if(video->llframe0[0]) | ||
207 | { | ||
208 | free(video->yuv_buffer[3]); | ||
209 | free(video->yuv_buffer[4]); | ||
210 | } | ||
211 | |||
212 | free(video->cr_to_r); | ||
213 | free(video->cr_to_g); | ||
214 | free(video->cb_to_g); | ||
215 | free(video->cb_to_b); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | void mpeg3video_init_scantables(mpeg3video_t *video) | ||
220 | { | ||
221 | #ifdef HAVE_MMX | ||
222 | if(video->have_mmx) | ||
223 | { | ||
224 | video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_mmx; | ||
225 | video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_mmx; | ||
226 | } | ||
227 | else | ||
228 | #endif | ||
229 | { | ||
230 | video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_nommx; | ||
231 | video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_nommx; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | mpeg3video_t* mpeg3video_allocate_struct(mpeg3_t *file, mpeg3_vtrack_t *track) | ||
236 | { | ||
237 | int i; | ||
238 | mpeg3video_t *video = (mpeg3video_t*)calloc(1, sizeof(mpeg3video_t)); | ||
239 | pthread_mutexattr_t mutex_attr; | ||
240 | |||
241 | video->file = file; | ||
242 | video->track = track; | ||
243 | video->vstream = mpeg3bits_new_stream(file, track->demuxer); | ||
244 | video->last_number = -1; | ||
245 | |||
246 | /* First frame is all green */ | ||
247 | video->framenum = -1; | ||
248 | video->have_mmx = file->have_mmx; | ||
249 | |||
250 | video->percentage_seek = -1; | ||
251 | video->frame_seek = -1; | ||
252 | |||
253 | mpeg3video_init_scantables(video); | ||
254 | mpeg3video_init_output(); | ||
255 | |||
256 | pthread_mutexattr_init(&mutex_attr); | ||
257 | pthread_mutex_init(&(video->test_lock), &mutex_attr); | ||
258 | pthread_mutex_init(&(video->slice_lock), &mutex_attr); | ||
259 | return video; | ||
260 | } | ||
261 | |||
262 | int mpeg3video_delete_struct(mpeg3video_t *video) | ||
263 | { | ||
264 | int i; | ||
265 | mpeg3bits_delete_stream(video->vstream); | ||
266 | pthread_mutex_destroy(&(video->test_lock)); | ||
267 | pthread_mutex_destroy(&(video->slice_lock)); | ||
268 | if(video->x_table) | ||
269 | { | ||
270 | free(video->x_table); | ||
271 | free(video->y_table); | ||
272 | } | ||
273 | if(video->total_slice_decoders) | ||
274 | { | ||
275 | for(i = 0; i < video->total_slice_decoders; i++) | ||
276 | mpeg3_delete_slice_decoder(&video->slice_decoders[i]); | ||
277 | } | ||
278 | for(i = 0; i < video->slice_buffers_initialized; i++) | ||
279 | mpeg3_delete_slice_buffer(&(video->slice_buffers[i])); | ||
280 | |||
281 | free(video); | ||
282 | } | ||
283 | |||
284 | |||
285 | int mpeg3video_read_frame_backend(mpeg3video_t *video, int skip_bframes) | ||
286 | { | ||
287 | int result = 0; | ||
288 | |||
289 | if(mpeg3bits_eof(video->vstream)) result = 1; | ||
290 | |||
291 | if(!result) result = mpeg3video_get_header(video, 0); | ||
292 | |||
293 | //printf("frame type %d\n", video->pict_type); | ||
294 | /* skip_bframes is the number of bframes we can skip successfully. */ | ||
295 | /* This is in case a skipped B-frame is repeated and the second repeat happens */ | ||
296 | /* to be a B frame we need. */ | ||
297 | video->skip_bframes = skip_bframes; | ||
298 | |||
299 | if(!result) | ||
300 | result = mpeg3video_getpicture(video, video->framenum); | ||
301 | |||
302 | #ifdef HAVE_MMX | ||
303 | if(video->have_mmx) | ||
304 | __asm__ __volatile__ ("emms"); | ||
305 | #endif | ||
306 | |||
307 | if(!result) | ||
308 | { | ||
309 | video->last_number = video->framenum; | ||
310 | video->framenum++; | ||
311 | } | ||
312 | return result; | ||
313 | } | ||
314 | |||
315 | int* mpeg3video_get_scaletable(int input_w, int output_w) | ||
316 | { | ||
317 | int *result = (int*)malloc(sizeof(int) * output_w); | ||
318 | float i; | ||
319 | float scale = (float)input_w / output_w; | ||
320 | for(i = 0; i < output_w; i++) | ||
321 | { | ||
322 | result[(int)i] = (int)(scale * i); | ||
323 | } | ||
324 | return result; | ||
325 | } | ||
326 | |||
327 | /* Get the first frame read. */ | ||
328 | int mpeg3video_get_firstframe(mpeg3video_t *video) | ||
329 | { | ||
330 | int result = 0; | ||
331 | if(video->framenum < 0) | ||
332 | { | ||
333 | video->repeat_count = video->current_repeat = 0; | ||
334 | result = mpeg3video_read_frame_backend(video, 0); | ||
335 | mpeg3bits_seek_byte(video->vstream, 0); | ||
336 | mpeg3video_match_refframes(video); | ||
337 | } | ||
338 | return result; | ||
339 | } | ||
340 | |||
341 | |||
342 | /* ======================================================================= */ | ||
343 | /* ENTRY POINTS */ | ||
344 | /* ======================================================================= */ | ||
345 | |||
346 | |||
347 | |||
348 | mpeg3video_t* mpeg3video_new(mpeg3_t *file, mpeg3_vtrack_t *track) | ||
349 | { | ||
350 | mpeg3video_t *video; | ||
351 | int result = 0; | ||
352 | |||
353 | video = mpeg3video_allocate_struct(file, track); | ||
354 | result = mpeg3video_get_header(video, 1); | ||
355 | |||
356 | if(!result) | ||
357 | { | ||
358 | int hour, minute, second, frame; | ||
359 | int gop_found; | ||
360 | |||
361 | mpeg3video_initdecoder(video); | ||
362 | video->decoder_initted = 1; | ||
363 | track->width = video->horizontal_size; | ||
364 | track->height = video->vertical_size; | ||
365 | track->frame_rate = video->frame_rate; | ||
366 | |||
367 | /* Get the length of the file from an elementary stream */ | ||
368 | if(file->is_video_stream) | ||
369 | { | ||
370 | /* Load the first GOP */ | ||
371 | mpeg3bits_seek_start(video->vstream); | ||
372 | result = mpeg3video_next_code(video->vstream, MPEG3_GOP_START_CODE); | ||
373 | if(!result) mpeg3bits_getbits(video->vstream, 32); | ||
374 | if(!result) result = mpeg3video_getgophdr(video); | ||
375 | |||
376 | hour = video->gop_timecode.hour; | ||
377 | minute = video->gop_timecode.minute; | ||
378 | second = video->gop_timecode.second; | ||
379 | frame = video->gop_timecode.frame; | ||
380 | video->first_frame = (long)(hour * 3600 * video->frame_rate + | ||
381 | minute * 60 * video->frame_rate + | ||
382 | second * video->frame_rate + | ||
383 | frame); | ||
384 | |||
385 | /* GOPs always have 16 frames */ | ||
386 | video->frames_per_gop = 16; | ||
387 | |||
388 | /* Read the last GOP in the file by seeking backward. */ | ||
389 | mpeg3bits_seek_end(video->vstream); | ||
390 | mpeg3bits_start_reverse(video->vstream); | ||
391 | result = mpeg3video_prev_code(video->vstream, MPEG3_GOP_START_CODE); | ||
392 | mpeg3bits_start_forward(video->vstream); | ||
393 | mpeg3bits_getbits(video->vstream, 8); | ||
394 | if(!result) result = mpeg3video_getgophdr(video); | ||
395 | |||
396 | hour = video->gop_timecode.hour; | ||
397 | minute = video->gop_timecode.minute; | ||
398 | second = video->gop_timecode.second; | ||
399 | frame = video->gop_timecode.frame; | ||
400 | |||
401 | video->last_frame = (long)(hour * 3600 * video->frame_rate + | ||
402 | minute * 60 * video->frame_rate + | ||
403 | second * video->frame_rate + | ||
404 | frame); | ||
405 | |||
406 | /* Count number of frames to end */ | ||
407 | while(!result) | ||
408 | { | ||
409 | result = mpeg3video_next_code(video->vstream, MPEG3_PICTURE_START_CODE); | ||
410 | if(!result) | ||
411 | { | ||
412 | mpeg3bits_getbyte_noptr(video->vstream); | ||
413 | video->last_frame++; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | track->total_frames = video->last_frame - video->first_frame + 1; | ||
418 | mpeg3bits_seek_start(video->vstream); | ||
419 | } | ||
420 | else | ||
421 | { | ||
422 | /* Gross approximation from a multiplexed file. */ | ||
423 | video->first_frame = 0; | ||
424 | track->total_frames = video->last_frame = | ||
425 | (long)(mpeg3demux_length(video->vstream->demuxer) * | ||
426 | video->frame_rate); | ||
427 | video->first_frame = 0; | ||
428 | } | ||
429 | |||
430 | video->maxframe = track->total_frames; | ||
431 | mpeg3bits_seek_start(video->vstream); | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | mpeg3video_delete(video); | ||
436 | video = 0; | ||
437 | } | ||
438 | |||
439 | return video; | ||
440 | } | ||
441 | |||
442 | int mpeg3video_delete(mpeg3video_t *video) | ||
443 | { | ||
444 | if(video->decoder_initted) | ||
445 | { | ||
446 | mpeg3video_deletedecoder(video); | ||
447 | } | ||
448 | mpeg3video_delete_struct(video); | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | int mpeg3video_set_cpus(mpeg3video_t *video, int cpus) | ||
453 | { | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | int mpeg3video_set_mmx(mpeg3video_t *video, int use_mmx) | ||
458 | { | ||
459 | video->have_mmx = use_mmx; | ||
460 | mpeg3video_init_scantables(video); | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage) | ||
465 | { | ||
466 | video->percentage_seek = percentage; | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | int mpeg3video_previous_frame(mpeg3video_t *video) | ||
471 | { | ||
472 | if(mpeg3bits_tell_percentage(video->vstream) <= 0) return 1; | ||
473 | mpeg3bits_start_reverse(video->vstream); | ||
474 | mpeg3video_prev_code(video->vstream, MPEG3_PICTURE_START_CODE); | ||
475 | mpeg3bits_getbits_reverse(video->vstream, 32); | ||
476 | |||
477 | if(mpeg3bits_bof(video->vstream)) mpeg3bits_seek_percentage(video->vstream, 0); | ||
478 | mpeg3bits_start_forward(video->vstream); | ||
479 | video->repeat_count = 0; | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | int mpeg3video_seek_frame(mpeg3video_t *video, long frame) | ||
484 | { | ||
485 | video->frame_seek = frame; | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /* Read all the way up to and including the next picture start code */ | ||
490 | int mpeg3video_read_raw(mpeg3video_t *video, unsigned char *output, long *size, long max_size) | ||
491 | { | ||
492 | unsigned MPEG3_INT32 code = 0; | ||
493 | mpeg3_bits_t *vstream = video->vstream; | ||
494 | |||
495 | *size = 0; | ||
496 | while(code != MPEG3_PICTURE_START_CODE && | ||
497 | code != MPEG3_SEQUENCE_END_CODE && | ||
498 | *size < max_size && | ||
499 | !mpeg3bits_eof(vstream)) | ||
500 | { | ||
501 | code <<= 8; | ||
502 | *output = mpeg3bits_getbyte_noptr(vstream); | ||
503 | code |= *output++; | ||
504 | (*size)++; | ||
505 | } | ||
506 | return mpeg3bits_eof(vstream); | ||
507 | } | ||
508 | |||
509 | int mpeg3video_read_frame(mpeg3video_t *video, | ||
510 | long frame_number, | ||
511 | unsigned char **output_rows, | ||
512 | int in_x, | ||
513 | int in_y, | ||
514 | int in_w, | ||
515 | int in_h, | ||
516 | int out_w, | ||
517 | int out_h, | ||
518 | int color_model) | ||
519 | { | ||
520 | int result = 0; | ||
521 | |||
522 | video->want_yvu = 0; | ||
523 | video->output_rows = output_rows; | ||
524 | video->color_model = color_model; | ||
525 | |||
526 | /* Get scaling tables */ | ||
527 | if(video->out_w != out_w || video->out_h != out_h || | ||
528 | video->in_w != in_w || video->in_h != in_h || | ||
529 | video->in_x != in_x || video->in_y != in_y) | ||
530 | { | ||
531 | if(video->x_table) | ||
532 | { | ||
533 | free(video->x_table); | ||
534 | free(video->y_table); | ||
535 | video->x_table = 0; | ||
536 | video->y_table = 0; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | video->out_w = out_w; | ||
541 | video->out_h = out_h; | ||
542 | video->in_w = in_w; | ||
543 | video->in_h = in_h; | ||
544 | video->in_x = in_x; | ||
545 | video->in_y = in_y; | ||
546 | |||
547 | if(!video->x_table) | ||
548 | { | ||
549 | video->x_table = mpeg3video_get_scaletable(video->in_w, video->out_w); | ||
550 | video->y_table = mpeg3video_get_scaletable(video->in_h, video->out_h); | ||
551 | } | ||
552 | |||
553 | mpeg3video_get_firstframe(video); | ||
554 | |||
555 | if(!result) result = mpeg3video_seek(video); | ||
556 | |||
557 | if(!result) result = mpeg3video_read_frame_backend(video, 0); | ||
558 | |||
559 | if(video->output_src) mpeg3video_present_frame(video); | ||
560 | |||
561 | video->percentage_seek = -1; | ||
562 | return result; | ||
563 | } | ||
564 | |||
565 | int mpeg3video_read_yuvframe(mpeg3video_t *video, | ||
566 | long frame_number, | ||
567 | char *y_output, | ||
568 | char *u_output, | ||
569 | char *v_output, | ||
570 | int in_x, | ||
571 | int in_y, | ||
572 | int in_w, | ||
573 | int in_h) | ||
574 | { | ||
575 | int result = 0; | ||
576 | |||
577 | video->want_yvu = 1; | ||
578 | video->y_output = y_output; | ||
579 | video->u_output = u_output; | ||
580 | video->v_output = v_output; | ||
581 | video->in_x = in_x; | ||
582 | video->in_y = in_y; | ||
583 | video->in_w = in_w; | ||
584 | video->in_h = in_h; | ||
585 | |||
586 | mpeg3video_get_firstframe(video); | ||
587 | |||
588 | if(!result) result = mpeg3video_seek(video); | ||
589 | |||
590 | if(!result) result = mpeg3video_read_frame_backend(video, 0); | ||
591 | |||
592 | if(video->output_src) mpeg3video_present_frame(video); | ||
593 | |||
594 | video->want_yvu = 0; | ||
595 | video->percentage_seek = -1; | ||
596 | return result; | ||
597 | } | ||