summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c') (more/less context) (show whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c597
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
7unsigned 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 */
20unsigned 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 */
35unsigned 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 */
44unsigned 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 */
53unsigned 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
65unsigned 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
73double 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
94int 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
198int 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
219void 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
235mpeg3video_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
262int 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
285int 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
315int* 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. */
328int 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
348mpeg3video_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
442int 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
452int mpeg3video_set_cpus(mpeg3video_t *video, int cpus)
453{
454 return 0;
455}
456
457int 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
464int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage)
465{
466 video->percentage_seek = percentage;
467 return 0;
468}
469
470int 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
483int 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 */
490int 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
509int 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
565int 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}