malloc padding to avoid reading past the malloc()ed area.
[libav.git] / ffplay.c
CommitLineData
01310af2
FB
1/*
2 * FFplay : Simple Media Player based on the ffmpeg libraries
3 * Copyright (c) 2003 Fabrice Bellard
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#define HAVE_AV_CONFIG_H
01310af2
FB
20#include "avformat.h"
21
22#include "cmdutils.h"
23
24#include <SDL.h>
25#include <SDL_thread.h>
26
31319a8c
FB
27#ifdef CONFIG_WIN32
28#undef main /* We don't want SDL to override our main() */
29#endif
30
3ca4b654
MN
31#ifdef CONFIG_OS2
32#define INCL_DOS
33 #include <os2.h>
34 #include <stdio.h>
35
36 void MorphToPM()
37 {
38 PPIB pib;
39 PTIB tib;
40
41 DosGetInfoBlocks(&tib, &pib);
42
43 // Change flag from VIO to PM:
44 if (pib->pib_ultype==2) pib->pib_ultype = 3;
45 }
46#endif
47
01310af2
FB
48#if defined(__linux__)
49#define HAVE_X11
50#endif
51
52#ifdef HAVE_X11
53#include <X11/Xlib.h>
54#endif
55
638c9d91
FB
56//#define DEBUG_SYNC
57
01310af2
FB
58#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
59#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
72ce053b 60#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
01310af2 61
638c9d91
FB
62/* SDL audio buffer size, in samples. Should be small to have precise
63 A/V sync as SDL does not have hardware buffer fullness info. */
64#define SDL_AUDIO_BUFFER_SIZE 1024
65
66/* no AV sync correction is done if below the AV sync threshold */
7e0140cb 67#define AV_SYNC_THRESHOLD 0.01
638c9d91
FB
68/* no AV correction is done if too big error */
69#define AV_NOSYNC_THRESHOLD 10.0
70
71/* maximum audio speed change to get correct sync */
72#define SAMPLE_CORRECTION_PERCENT_MAX 10
73
74/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
75#define AUDIO_DIFF_AVG_NB 20
76
01310af2
FB
77/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
78#define SAMPLE_ARRAY_SIZE (2*65536)
79
80typedef struct PacketQueue {
81 AVPacketList *first_pkt, *last_pkt;
82 int nb_packets;
83 int size;
84 int abort_request;
85 SDL_mutex *mutex;
86 SDL_cond *cond;
87} PacketQueue;
88
89#define VIDEO_PICTURE_QUEUE_SIZE 1
72ce053b 90#define SUBPICTURE_QUEUE_SIZE 4
01310af2
FB
91
92typedef struct VideoPicture {
267e9dfa 93 double pts; ///<presentation time stamp for this picture
01310af2
FB
94 SDL_Overlay *bmp;
95 int width, height; /* source height & width */
96 int allocated;
97} VideoPicture;
98
72ce053b
IC
99typedef struct SubPicture {
100 double pts; /* presentation time stamp for this picture */
101 AVSubtitle sub;
102} SubPicture;
103
01310af2
FB
104enum {
105 AV_SYNC_AUDIO_MASTER, /* default choice */
106 AV_SYNC_VIDEO_MASTER,
638c9d91 107 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
01310af2
FB
108};
109
110typedef struct VideoState {
111 SDL_Thread *parse_tid;
112 SDL_Thread *video_tid;
638c9d91 113 AVInputFormat *iformat;
01310af2
FB
114 int no_background;
115 int abort_request;
116 int paused;
416e3508 117 int last_paused;
72ea344b 118 int seek_req;
3ba1438d 119 int seek_flags;
72ea344b 120 int64_t seek_pos;
01310af2
FB
121 AVFormatContext *ic;
122 int dtg_active_format;
123
124 int audio_stream;
125
126 int av_sync_type;
638c9d91
FB
127 double external_clock; /* external clock base */
128 int64_t external_clock_time;
129
130 double audio_clock;
131 double audio_diff_cum; /* used for AV difference average computation */
132 double audio_diff_avg_coef;
133 double audio_diff_threshold;
134 int audio_diff_avg_count;
01310af2
FB
135 AVStream *audio_st;
136 PacketQueue audioq;
137 int audio_hw_buf_size;
138 /* samples output by the codec. we reserve more space for avsync
139 compensation */
140 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
7fea94ce 141 unsigned int audio_buf_size; /* in bytes */
01310af2
FB
142 int audio_buf_index; /* in bytes */
143 AVPacket audio_pkt;
144 uint8_t *audio_pkt_data;
145 int audio_pkt_size;
01310af2
FB
146
147 int show_audio; /* if true, display audio samples */
148 int16_t sample_array[SAMPLE_ARRAY_SIZE];
149 int sample_array_index;
5e0257e3 150 int last_i_start;
01310af2 151
72ce053b
IC
152 SDL_Thread *subtitle_tid;
153 int subtitle_stream;
154 int subtitle_stream_changed;
155 AVStream *subtitle_st;
156 PacketQueue subtitleq;
157 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
158 int subpq_size, subpq_rindex, subpq_windex;
159 SDL_mutex *subpq_mutex;
160 SDL_cond *subpq_cond;
161
638c9d91
FB
162 double frame_timer;
163 double frame_last_pts;
164 double frame_last_delay;
267e9dfa 165 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
01310af2
FB
166 int video_stream;
167 AVStream *video_st;
168 PacketQueue videoq;
267e9dfa
MN
169 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
170 int64_t video_current_pts_time; ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
01310af2
FB
171 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
172 int pictq_size, pictq_rindex, pictq_windex;
173 SDL_mutex *pictq_mutex;
174 SDL_cond *pictq_cond;
175
b514ed3c
MN
176 SDL_mutex *video_decoder_mutex;
177 SDL_mutex *audio_decoder_mutex;
72ce053b 178 SDL_mutex *subtitle_decoder_mutex;
b514ed3c 179
01310af2
FB
180 // QETimer *video_timer;
181 char filename[1024];
182 int width, height, xleft, ytop;
183} VideoState;
184
185void show_help(void);
638c9d91 186static int audio_write_get_buf_size(VideoState *is);
01310af2
FB
187
188/* options specified by the user */
189static AVInputFormat *file_iformat;
61890b02 190static AVImageFormat *image_format;
01310af2
FB
191static const char *input_filename;
192static int fs_screen_width;
193static int fs_screen_height;
194static int screen_width = 640;
195static int screen_height = 480;
196static int audio_disable;
197static int video_disable;
198static int display_disable;
199static int show_status;
638c9d91 200static int av_sync_type = AV_SYNC_AUDIO_MASTER;
72ea344b 201static int64_t start_time = AV_NOPTS_VALUE;
e26a8335 202static int debug = 0;
0c9bbaec 203static int debug_mv = 0;
bba04f1e 204static int step = 0;
c62c07d3 205static int thread_count = 1;
6387c3e6 206static int workaround_bugs = 1;
6fc5b059 207static int fast = 0;
30bc6613 208static int genpts = 0;
178fcca8
MN
209static int lowres = 0;
210static int idct = FF_IDCT_AUTO;
8c3eba7c
MN
211static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
212static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
213static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
1471c6c2 214static int error_resilience = FF_ER_CAREFUL;
1b51e051 215static int error_concealment = 3;
01310af2
FB
216
217/* current context */
218static int is_full_screen;
219static VideoState *cur_stream;
5e0257e3 220static int64_t audio_callback_time;
01310af2
FB
221
222#define FF_ALLOC_EVENT (SDL_USEREVENT)
223#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
638c9d91 224#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
01310af2
FB
225
226SDL_Surface *screen;
227
228/* packet queue handling */
229static void packet_queue_init(PacketQueue *q)
230{
231 memset(q, 0, sizeof(PacketQueue));
232 q->mutex = SDL_CreateMutex();
233 q->cond = SDL_CreateCond();
234}
235
72ea344b 236static void packet_queue_flush(PacketQueue *q)
01310af2
FB
237{
238 AVPacketList *pkt, *pkt1;
239
687fae2b 240 SDL_LockMutex(q->mutex);
01310af2
FB
241 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
242 pkt1 = pkt->next;
243 av_free_packet(&pkt->pkt);
da6c4573 244 av_freep(&pkt);
01310af2 245 }
72ea344b
FB
246 q->last_pkt = NULL;
247 q->first_pkt = NULL;
248 q->nb_packets = 0;
249 q->size = 0;
687fae2b 250 SDL_UnlockMutex(q->mutex);
72ea344b
FB
251}
252
253static void packet_queue_end(PacketQueue *q)
254{
255 packet_queue_flush(q);
01310af2
FB
256 SDL_DestroyMutex(q->mutex);
257 SDL_DestroyCond(q->cond);
258}
259
260static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
261{
262 AVPacketList *pkt1;
263
72ea344b
FB
264 /* duplicate the packet */
265 if (av_dup_packet(pkt) < 0)
266 return -1;
267
01310af2
FB
268 pkt1 = av_malloc(sizeof(AVPacketList));
269 if (!pkt1)
270 return -1;
271 pkt1->pkt = *pkt;
272 pkt1->next = NULL;
273
72ea344b 274
01310af2
FB
275 SDL_LockMutex(q->mutex);
276
277 if (!q->last_pkt)
278
279 q->first_pkt = pkt1;
280 else
281 q->last_pkt->next = pkt1;
282 q->last_pkt = pkt1;
283 q->nb_packets++;
284 q->size += pkt1->pkt.size;
285 /* XXX: should duplicate packet data in DV case */
286 SDL_CondSignal(q->cond);
287
288 SDL_UnlockMutex(q->mutex);
289 return 0;
290}
291
292static void packet_queue_abort(PacketQueue *q)
293{
294 SDL_LockMutex(q->mutex);
295
296 q->abort_request = 1;
297
298 SDL_CondSignal(q->cond);
299
300 SDL_UnlockMutex(q->mutex);
301}
302
303/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
304static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
305{
306 AVPacketList *pkt1;
307 int ret;
308
309 SDL_LockMutex(q->mutex);
310
311 for(;;) {
312 if (q->abort_request) {
313 ret = -1;
314 break;
315 }
316
317 pkt1 = q->first_pkt;
318 if (pkt1) {
319 q->first_pkt = pkt1->next;
320 if (!q->first_pkt)
321 q->last_pkt = NULL;
322 q->nb_packets--;
323 q->size -= pkt1->pkt.size;
324 *pkt = pkt1->pkt;
325 av_free(pkt1);
326 ret = 1;
327 break;
328 } else if (!block) {
329 ret = 0;
330 break;
331 } else {
332 SDL_CondWait(q->cond, q->mutex);
333 }
334 }
335 SDL_UnlockMutex(q->mutex);
336 return ret;
337}
338
339static inline void fill_rectangle(SDL_Surface *screen,
340 int x, int y, int w, int h, int color)
341{
342 SDL_Rect rect;
343 rect.x = x;
344 rect.y = y;
345 rect.w = w;
346 rect.h = h;
347 SDL_FillRect(screen, &rect, color);
348}
349
350#if 0
351/* draw only the border of a rectangle */
352void fill_border(VideoState *s, int x, int y, int w, int h, int color)
353{
354 int w1, w2, h1, h2;
355
356 /* fill the background */
357 w1 = x;
358 if (w1 < 0)
359 w1 = 0;
360 w2 = s->width - (x + w);
361 if (w2 < 0)
362 w2 = 0;
363 h1 = y;
364 if (h1 < 0)
365 h1 = 0;
366 h2 = s->height - (y + h);
367 if (h2 < 0)
368 h2 = 0;
369 fill_rectangle(screen,
370 s->xleft, s->ytop,
371 w1, s->height,
372 color);
373 fill_rectangle(screen,
374 s->xleft + s->width - w2, s->ytop,
375 w2, s->height,
376 color);
377 fill_rectangle(screen,
378 s->xleft + w1, s->ytop,
379 s->width - w1 - w2, h1,
380 color);
381 fill_rectangle(screen,
382 s->xleft + w1, s->ytop + s->height - h2,
383 s->width - w1 - w2, h2,
384 color);
385}
386#endif
387
72ce053b
IC
388
389
390#define SCALEBITS 10
391#define ONE_HALF (1 << (SCALEBITS - 1))
392#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
393
394#define RGB_TO_Y_CCIR(r, g, b) \
395((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
396 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
397
398#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
399(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
400 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
401
402#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
403(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
404 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
405
406#define ALPHA_BLEND(a, oldp, newp, s)\
407((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
408
409#define RGBA_IN(r, g, b, a, s)\
410{\
411 unsigned int v = ((const uint32_t *)(s))[0];\
412 a = (v >> 24) & 0xff;\
413 r = (v >> 16) & 0xff;\
414 g = (v >> 8) & 0xff;\
415 b = v & 0xff;\
416}
417
418#define YUVA_IN(y, u, v, a, s, pal)\
419{\
420 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
421 a = (val >> 24) & 0xff;\
422 y = (val >> 16) & 0xff;\
423 u = (val >> 8) & 0xff;\
424 v = val & 0xff;\
425}
426
427#define YUVA_OUT(d, y, u, v, a)\
428{\
429 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
430}
431
432
433#define BPP 1
434
435static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
436{
437 int wrap, wrap3, width2, skip2;
438 int y, u, v, a, u1, v1, a1, w, h;
439 uint8_t *lum, *cb, *cr;
440 const uint8_t *p;
441 const uint32_t *pal;
442
443 lum = dst->data[0] + rect->y * dst->linesize[0];
444 cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
445 cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
446
447 width2 = (rect->w + 1) >> 1;
448 skip2 = rect->x >> 1;
449 wrap = dst->linesize[0];
450 wrap3 = rect->linesize;
451 p = rect->bitmap;
452 pal = rect->rgba_palette; /* Now in YCrCb! */
453
454 if (rect->y & 1) {
455 lum += rect->x;
456 cb += skip2;
457 cr += skip2;
458
459 if (rect->x & 1) {
460 YUVA_IN(y, u, v, a, p, pal);
461 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
462 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
463 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
464 cb++;
465 cr++;
466 lum++;
467 p += BPP;
468 }
469 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
470 YUVA_IN(y, u, v, a, p, pal);
471 u1 = u;
472 v1 = v;
473 a1 = a;
474 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
475
476 YUVA_IN(y, u, v, a, p + BPP, pal);
477 u1 += u;
478 v1 += v;
479 a1 += a;
480 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
481 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
482 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
483 cb++;
484 cr++;
485 p += 2 * BPP;
486 lum += 2;
487 }
488 if (w) {
489 YUVA_IN(y, u, v, a, p, pal);
490 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
491 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
492 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
493 }
494 p += wrap3 + (wrap3 - rect->w * BPP);
495 lum += wrap + (wrap - rect->w - rect->x);
496 cb += dst->linesize[1] - width2 - skip2;
497 cr += dst->linesize[2] - width2 - skip2;
498 }
499 for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
500 lum += rect->x;
501 cb += skip2;
502 cr += skip2;
503
504 if (rect->x & 1) {
505 YUVA_IN(y, u, v, a, p, pal);
506 u1 = u;
507 v1 = v;
508 a1 = a;
509 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
510 p += wrap3;
511 lum += wrap;
512 YUVA_IN(y, u, v, a, p, pal);
513 u1 += u;
514 v1 += v;
515 a1 += a;
516 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
517 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
518 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
519 cb++;
520 cr++;
521 p += -wrap3 + BPP;
522 lum += -wrap + 1;
523 }
524 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
525 YUVA_IN(y, u, v, a, p, pal);
526 u1 = u;
527 v1 = v;
528 a1 = a;
529 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
530
531 YUVA_IN(y, u, v, a, p, pal);
532 u1 += u;
533 v1 += v;
534 a1 += a;
535 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
536 p += wrap3;
537 lum += wrap;
538
539 YUVA_IN(y, u, v, a, p, pal);
540 u1 += u;
541 v1 += v;
542 a1 += a;
543 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
544
545 YUVA_IN(y, u, v, a, p, pal);
546 u1 += u;
547 v1 += v;
548 a1 += a;
549 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
550
551 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
552 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
553
554 cb++;
555 cr++;
556 p += -wrap3 + 2 * BPP;
557 lum += -wrap + 2;
558 }
559 if (w) {
560 YUVA_IN(y, u, v, a, p, pal);
561 u1 = u;
562 v1 = v;
563 a1 = a;
564 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
565 p += wrap3;
566 lum += wrap;
567 YUVA_IN(y, u, v, a, p, pal);
568 u1 += u;
569 v1 += v;
570 a1 += a;
571 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
572 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
573 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
574 cb++;
575 cr++;
576 p += -wrap3 + BPP;
577 lum += -wrap + 1;
578 }
579 p += wrap3 + (wrap3 - rect->w * BPP);
580 lum += wrap + (wrap - rect->w - rect->x);
581 cb += dst->linesize[1] - width2 - skip2;
582 cr += dst->linesize[2] - width2 - skip2;
583 }
584 /* handle odd height */
585 if (h) {
586 lum += rect->x;
587 cb += skip2;
588 cr += skip2;
589
590 if (rect->x & 1) {
591 YUVA_IN(y, u, v, a, p, pal);
592 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
593 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
594 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
595 cb++;
596 cr++;
597 lum++;
598 p += BPP;
599 }
600 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
601 YUVA_IN(y, u, v, a, p, pal);
602 u1 = u;
603 v1 = v;
604 a1 = a;
605 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
606
607 YUVA_IN(y, u, v, a, p + BPP, pal);
608 u1 += u;
609 v1 += v;
610 a1 += a;
611 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
612 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
613 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
614 cb++;
615 cr++;
616 p += 2 * BPP;
617 lum += 2;
618 }
619 if (w) {
620 YUVA_IN(y, u, v, a, p, pal);
621 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
622 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
623 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
624 }
625 }
626}
627
628static void free_subpicture(SubPicture *sp)
629{
630 int i;
631
632 for (i = 0; i < sp->sub.num_rects; i++)
633 {
634 av_free(sp->sub.rects[i].bitmap);
635 av_free(sp->sub.rects[i].rgba_palette);
636 }
637
638 av_free(sp->sub.rects);
639
640 memset(&sp->sub, 0, sizeof(AVSubtitle));
641}
642
01310af2
FB
643static void video_image_display(VideoState *is)
644{
645 VideoPicture *vp;
72ce053b
IC
646 SubPicture *sp;
647 AVPicture pict;
01310af2
FB
648 float aspect_ratio;
649 int width, height, x, y;
650 SDL_Rect rect;
72ce053b 651 int i;
01310af2
FB
652
653 vp = &is->pictq[is->pictq_rindex];
654 if (vp->bmp) {
655 /* XXX: use variable in the frame */
01f4895c 656 if (is->video_st->codec->sample_aspect_ratio.num == 0)
72ea344b
FB
657 aspect_ratio = 0;
658 else
01f4895c
MN
659 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
660 * is->video_st->codec->width / is->video_st->codec->height;;
01310af2 661 if (aspect_ratio <= 0.0)
01f4895c
MN
662 aspect_ratio = (float)is->video_st->codec->width /
663 (float)is->video_st->codec->height;
01310af2
FB
664 /* if an active format is indicated, then it overrides the
665 mpeg format */
666#if 0
01f4895c
MN
667 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
668 is->dtg_active_format = is->video_st->codec->dtg_active_format;
01310af2
FB
669 printf("dtg_active_format=%d\n", is->dtg_active_format);
670 }
671#endif
672#if 0
01f4895c 673 switch(is->video_st->codec->dtg_active_format) {
01310af2
FB
674 case FF_DTG_AFD_SAME:
675 default:
676 /* nothing to do */
677 break;
678 case FF_DTG_AFD_4_3:
679 aspect_ratio = 4.0 / 3.0;
680 break;
681 case FF_DTG_AFD_16_9:
682 aspect_ratio = 16.0 / 9.0;
683 break;
684 case FF_DTG_AFD_14_9:
685 aspect_ratio = 14.0 / 9.0;
686 break;
687 case FF_DTG_AFD_4_3_SP_14_9:
688 aspect_ratio = 14.0 / 9.0;
689 break;
690 case FF_DTG_AFD_16_9_SP_14_9:
691 aspect_ratio = 14.0 / 9.0;
692 break;
693 case FF_DTG_AFD_SP_4_3:
694 aspect_ratio = 4.0 / 3.0;
695 break;
696 }
697#endif
698
72ce053b
IC
699 if (is->subtitle_st)
700 {
701 if (is->subpq_size > 0)
702 {
703 sp = &is->subpq[is->subpq_rindex];
704
705 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
706 {
707 SDL_LockYUVOverlay (vp->bmp);
708
709 pict.data[0] = vp->bmp->pixels[0];
710 pict.data[1] = vp->bmp->pixels[2];
711 pict.data[2] = vp->bmp->pixels[1];
712
713 pict.linesize[0] = vp->bmp->pitches[0];
714 pict.linesize[1] = vp->bmp->pitches[2];
715 pict.linesize[2] = vp->bmp->pitches[1];
716
717 for (i = 0; i < sp->sub.num_rects; i++)
718 blend_subrect(&pict, &sp->sub.rects[i]);
719
720 SDL_UnlockYUVOverlay (vp->bmp);
721 }
722 }
723 }
724
725
01310af2
FB
726 /* XXX: we suppose the screen has a 1.0 pixel ratio */
727 height = is->height;
728 width = ((int)rint(height * aspect_ratio)) & -3;
729 if (width > is->width) {
730 width = is->width;
731 height = ((int)rint(width / aspect_ratio)) & -3;
732 }
733 x = (is->width - width) / 2;
734 y = (is->height - height) / 2;
735 if (!is->no_background) {
736 /* fill the background */
737 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
738 } else {
739 is->no_background = 0;
740 }
741 rect.x = is->xleft + x;
742 rect.y = is->xleft + y;
743 rect.w = width;
744 rect.h = height;
745 SDL_DisplayYUVOverlay(vp->bmp, &rect);
746 } else {
747#if 0
748 fill_rectangle(screen,
749 is->xleft, is->ytop, is->width, is->height,
750 QERGB(0x00, 0x00, 0x00));
751#endif
752 }
753}
754
755static inline int compute_mod(int a, int b)
756{
757 a = a % b;
758 if (a >= 0)
759 return a;
760 else
761 return a + b;
762}
763
764static void video_audio_display(VideoState *s)
765{
766 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
767 int ch, channels, h, h2, bgcolor, fgcolor;
768 int16_t time_diff;
769
770 /* compute display index : center on currently output samples */
01f4895c 771 channels = s->audio_st->codec->channels;
01310af2 772 nb_display_channels = channels;
5e0257e3
FB
773 if (!s->paused) {
774 n = 2 * channels;
775 delay = audio_write_get_buf_size(s);
776 delay /= n;
777
778 /* to be more precise, we take into account the time spent since
779 the last buffer computation */
780 if (audio_callback_time) {
781 time_diff = av_gettime() - audio_callback_time;
01f4895c 782 delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
5e0257e3
FB
783 }
784
785 delay -= s->width / 2;
786 if (delay < s->width)
787 delay = s->width;
788 i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
789 s->last_i_start = i_start;
790 } else {
791 i_start = s->last_i_start;
01310af2
FB
792 }
793
01310af2
FB
794 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
795 fill_rectangle(screen,
796 s->xleft, s->ytop, s->width, s->height,
797 bgcolor);
798
799 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
800
801 /* total height for one channel */
802 h = s->height / nb_display_channels;
803 /* graph height / 2 */
804 h2 = (h * 9) / 20;
805 for(ch = 0;ch < nb_display_channels; ch++) {
806 i = i_start + ch;
807 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
808 for(x = 0; x < s->width; x++) {
809 y = (s->sample_array[i] * h2) >> 15;
810 if (y < 0) {
811 y = -y;
812 ys = y1 - y;
813 } else {
814 ys = y1;
815 }
816 fill_rectangle(screen,
817 s->xleft + x, ys, 1, y,
818 fgcolor);
819 i += channels;
820 if (i >= SAMPLE_ARRAY_SIZE)
821 i -= SAMPLE_ARRAY_SIZE;
822 }
823 }
824
825 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
826
827 for(ch = 1;ch < nb_display_channels; ch++) {
828 y = s->ytop + ch * h;
829 fill_rectangle(screen,
830 s->xleft, y, s->width, 1,
831 fgcolor);
832 }
833 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
834}
835
836/* display the current picture, if any */
837static void video_display(VideoState *is)
838{
839 if (is->audio_st && is->show_audio)
840 video_audio_display(is);
841 else if (is->video_st)
842 video_image_display(is);
843}
844
845static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
846{
847 SDL_Event event;
848 event.type = FF_REFRESH_EVENT;
849 event.user.data1 = opaque;
850 SDL_PushEvent(&event);
851 return 0; /* 0 means stop timer */
852}
853
854/* schedule a video refresh in 'delay' ms */
855static void schedule_refresh(VideoState *is, int delay)
856{
857 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
858}
859
638c9d91
FB
860/* get the current audio clock value */
861static double get_audio_clock(VideoState *is)
862{
863 double pts;
864 int hw_buf_size, bytes_per_sec;
865 pts = is->audio_clock;
866 hw_buf_size = audio_write_get_buf_size(is);
867 bytes_per_sec = 0;
868 if (is->audio_st) {
01f4895c
MN
869 bytes_per_sec = is->audio_st->codec->sample_rate *
870 2 * is->audio_st->codec->channels;
638c9d91
FB
871 }
872 if (bytes_per_sec)
873 pts -= (double)hw_buf_size / bytes_per_sec;
874 return pts;
875}
876
877/* get the current video clock value */
878static double get_video_clock(VideoState *is)
879{
880 double delta;
04108619 881 if (is->paused) {
72ea344b
FB
882 delta = 0;
883 } else {
884 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
885 }
638c9d91
FB
886 return is->video_current_pts + delta;
887}
888
889/* get the current external clock value */
890static double get_external_clock(VideoState *is)
891{
892 int64_t ti;
893 ti = av_gettime();
894 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
895}
896
897/* get the current master clock value */
898static double get_master_clock(VideoState *is)
899{
900 double val;
901
72ea344b
FB
902 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
903 if (is->video_st)
904 val = get_video_clock(is);
905 else
906 val = get_audio_clock(is);
907 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
908 if (is->audio_st)
909 val = get_audio_clock(is);
910 else
911 val = get_video_clock(is);
912 } else {
638c9d91 913 val = get_external_clock(is);
72ea344b 914 }
638c9d91
FB
915 return val;
916}
917
72ea344b 918/* seek in the stream */
3ba1438d 919static void stream_seek(VideoState *is, int64_t pos, int rel)
72ea344b 920{
687fae2b
IW
921 if (!is->seek_req) {
922 is->seek_pos = pos;
923 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
924 is->seek_req = 1;
925 }
72ea344b
FB
926}
927
928/* pause or resume the video */
929static void stream_pause(VideoState *is)
930{
931 is->paused = !is->paused;
932 if (is->paused) {
933 is->video_current_pts = get_video_clock(is);
934 }
935}
936
01310af2
FB
937/* called to display each frame */
938static void video_refresh_timer(void *opaque)
939{
940 VideoState *is = opaque;
941 VideoPicture *vp;
638c9d91
FB
942 double actual_delay, delay, sync_threshold, ref_clock, diff;
943
72ce053b 944 SubPicture *sp, *sp2;
01310af2
FB
945
946 if (is->video_st) {
947 if (is->pictq_size == 0) {
948 /* if no picture, need to wait */
7e0140cb 949 schedule_refresh(is, 1);
01310af2 950 } else {
638c9d91 951 /* dequeue the picture */
01310af2 952 vp = &is->pictq[is->pictq_rindex];
638c9d91
FB
953
954 /* update current video pts */
955 is->video_current_pts = vp->pts;
956 is->video_current_pts_time = av_gettime();
957
958 /* compute nominal delay */
959 delay = vp->pts - is->frame_last_pts;
960 if (delay <= 0 || delay >= 1.0) {
961 /* if incorrect delay, use previous one */
962 delay = is->frame_last_delay;
963 }
964 is->frame_last_delay = delay;
965 is->frame_last_pts = vp->pts;
966
967 /* update delay to follow master synchronisation source */
968 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
969 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
970 /* if video is slave, we try to correct big delays by
971 duplicating or deleting a frame */
972 ref_clock = get_master_clock(is);
973 diff = vp->pts - ref_clock;
974
975 /* skip or repeat frame. We take into account the
976 delay to compute the threshold. I still don't know
977 if it is the best guess */
978 sync_threshold = AV_SYNC_THRESHOLD;
979 if (delay > sync_threshold)
980 sync_threshold = delay;
981 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
982 if (diff <= -sync_threshold)
983 delay = 0;
984 else if (diff >= sync_threshold)
985 delay = 2 * delay;
986 }
987 }
988
989 is->frame_timer += delay;
990 /* compute the REAL delay (we need to do that to avoid
991 long term errors */
992 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
993 if (actual_delay < 0.010) {
994 /* XXX: should skip picture */
995 actual_delay = 0.010;
996 }
01310af2 997 /* launch timer for next picture */
638c9d91
FB
998 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
999
1000#if defined(DEBUG_SYNC)
1001 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1002 delay, actual_delay, vp->pts, -diff);
1003#endif
01310af2 1004
72ce053b
IC
1005 if(is->subtitle_st) {
1006 if (is->subtitle_stream_changed) {
1007 SDL_LockMutex(is->subpq_mutex);
1008
1009 while (is->subpq_size) {
1010 free_subpicture(&is->subpq[is->subpq_rindex]);
1011
1012 /* update queue size and signal for next picture */
1013 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1014 is->subpq_rindex = 0;
1015
1016 is->subpq_size--;
1017 }
1018 is->subtitle_stream_changed = 0;
1019
1020 SDL_CondSignal(is->subpq_cond);
1021 SDL_UnlockMutex(is->subpq_mutex);
1022 } else {
1023 if (is->subpq_size > 0) {
1024 sp = &is->subpq[is->subpq_rindex];
1025
1026 if (is->subpq_size > 1)
1027 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1028 else
1029 sp2 = NULL;
1030
1031 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1032 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1033 {
1034 free_subpicture(sp);
1035
1036 /* update queue size and signal for next picture */
1037 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1038 is->subpq_rindex = 0;
1039
1040 SDL_LockMutex(is->subpq_mutex);
1041 is->subpq_size--;
1042 SDL_CondSignal(is->subpq_cond);
1043 SDL_UnlockMutex(is->subpq_mutex);
1044 }
1045 }
1046 }
1047 }
1048
01310af2
FB
1049 /* display picture */
1050 video_display(is);
1051
1052 /* update queue size and signal for next picture */
1053 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1054 is->pictq_rindex = 0;
1055
1056 SDL_LockMutex(is->pictq_mutex);
1057 is->pictq_size--;
1058 SDL_CondSignal(is->pictq_cond);
1059 SDL_UnlockMutex(is->pictq_mutex);
1060 }
1061 } else if (is->audio_st) {
1062 /* draw the next audio frame */
1063
1064 schedule_refresh(is, 40);
1065
1066 /* if only audio stream, then display the audio bars (better
1067 than nothing, just to test the implementation */
1068
1069 /* display picture */
1070 video_display(is);
1071 } else {
1072 schedule_refresh(is, 100);
1073 }
1074 if (show_status) {
1075 static int64_t last_time;
1076 int64_t cur_time;
72ce053b 1077 int aqsize, vqsize, sqsize;
638c9d91 1078 double av_diff;
01310af2
FB
1079
1080 cur_time = av_gettime();
1081 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1082 aqsize = 0;
1083 vqsize = 0;
72ce053b 1084 sqsize = 0;
01310af2
FB
1085 if (is->audio_st)
1086 aqsize = is->audioq.size;
1087 if (is->video_st)
1088 vqsize = is->videoq.size;
72ce053b
IC
1089 if (is->subtitle_st)
1090 sqsize = is->subtitleq.size;
638c9d91
FB
1091 av_diff = 0;
1092 if (is->audio_st && is->video_st)
1093 av_diff = get_audio_clock(is) - get_video_clock(is);
72ce053b
IC
1094 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
1095 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
01310af2
FB
1096 fflush(stdout);
1097 last_time = cur_time;
1098 }
1099 }
1100}
1101
1102/* allocate a picture (needs to do that in main thread to avoid
1103 potential locking problems */
1104static void alloc_picture(void *opaque)
1105{
1106 VideoState *is = opaque;
1107 VideoPicture *vp;
01310af2
FB
1108
1109 vp = &is->pictq[is->pictq_windex];
1110
1111 if (vp->bmp)
1112 SDL_FreeYUVOverlay(vp->bmp);
1113
61890b02 1114#if 0
01310af2 1115 /* XXX: use generic function */
61890b02 1116 /* XXX: disable overlay if no hardware acceleration or if RGB format */
01f4895c 1117 switch(is->video_st->codec->pix_fmt) {
01310af2
FB
1118 case PIX_FMT_YUV420P:
1119 case PIX_FMT_YUV422P:
1120 case PIX_FMT_YUV444P:
1121 case PIX_FMT_YUV422:
1122 case PIX_FMT_YUV410P:
1123 case PIX_FMT_YUV411P:
1124 is_yuv = 1;
1125 break;
1126 default:
1127 is_yuv = 0;
1128 break;
1129 }
01310af2 1130#endif
01f4895c
MN
1131 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1132 is->video_st->codec->height,
61890b02
FB
1133 SDL_YV12_OVERLAY,
1134 screen);
01f4895c
MN
1135 vp->width = is->video_st->codec->width;
1136 vp->height = is->video_st->codec->height;
01310af2
FB
1137
1138 SDL_LockMutex(is->pictq_mutex);
1139 vp->allocated = 1;
1140 SDL_CondSignal(is->pictq_cond);
1141 SDL_UnlockMutex(is->pictq_mutex);
1142}
1143
267e9dfa
MN
1144/**
1145 *
1146 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1147 */
638c9d91 1148static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01310af2
FB
1149{
1150 VideoPicture *vp;
1151 int dst_pix_fmt;
1152 AVPicture pict;
01310af2
FB
1153
1154 /* wait until we have space to put a new picture */
1155 SDL_LockMutex(is->pictq_mutex);
1156 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1157 !is->videoq.abort_request) {
1158 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1159 }
1160 SDL_UnlockMutex(is->pictq_mutex);
1161
1162 if (is->videoq.abort_request)
1163 return -1;
1164
1165 vp = &is->pictq[is->pictq_windex];
1166
1167 /* alloc or resize hardware picture buffer */
1168 if (!vp->bmp ||
01f4895c
MN
1169 vp->width != is->video_st->codec->width ||
1170 vp->height != is->video_st->codec->height) {
01310af2
FB
1171 SDL_Event event;
1172
1173 vp->allocated = 0;
1174
1175 /* the allocation must be done in the main thread to avoid
1176 locking problems */
1177 event.type = FF_ALLOC_EVENT;
1178 event.user.data1 = is;
1179 SDL_PushEvent(&event);
1180
1181 /* wait until the picture is allocated */
1182 SDL_LockMutex(is->pictq_mutex);
1183 while (!vp->allocated && !is->videoq.abort_request) {
1184 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1185 }
1186 SDL_UnlockMutex(is->pictq_mutex);
1187
1188 if (is->videoq.abort_request)
1189 return -1;
1190 }
1191
638c9d91 1192 /* if the frame is not skipped, then display it */
01310af2
FB
1193 if (vp->bmp) {
1194 /* get a pointer on the bitmap */
1195 SDL_LockYUVOverlay (vp->bmp);
1196
1197 dst_pix_fmt = PIX_FMT_YUV420P;
1198 pict.data[0] = vp->bmp->pixels[0];
1199 pict.data[1] = vp->bmp->pixels[2];
1200 pict.data[2] = vp->bmp->pixels[1];
1201
1202 pict.linesize[0] = vp->bmp->pitches[0];
1203 pict.linesize[1] = vp->bmp->pitches[2];
1204 pict.linesize[2] = vp->bmp->pitches[1];
01310af2 1205 img_convert(&pict, dst_pix_fmt,
01f4895c
MN
1206 (AVPicture *)src_frame, is->video_st->codec->pix_fmt,
1207 is->video_st->codec->width, is->video_st->codec->height);
01310af2
FB
1208 /* update the bitmap content */
1209 SDL_UnlockYUVOverlay(vp->bmp);
1210
638c9d91 1211 vp->pts = pts;
01310af2
FB
1212
1213 /* now we can update the picture count */
1214 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1215 is->pictq_windex = 0;
1216 SDL_LockMutex(is->pictq_mutex);
1217 is->pictq_size++;
1218 SDL_UnlockMutex(is->pictq_mutex);
1219 }
638c9d91
FB
1220 return 0;
1221}
1222
267e9dfa
MN
1223/**
1224 * compute the exact PTS for the picture if it is omitted in the stream
1225 * @param pts1 the dts of the pkt / pts of the frame
1226 */
638c9d91
FB
1227static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1228{
1229 double frame_delay, pts;
1230
1231 pts = pts1;
1232
01310af2 1233 if (pts != 0) {
638c9d91 1234 /* update video clock with pts, if present */
01310af2
FB
1235 is->video_clock = pts;
1236 } else {
72ea344b
FB
1237 pts = is->video_clock;
1238 }
1239 /* update video clock for next frame */
01f4895c 1240 frame_delay = av_q2d(is->video_st->codec->time_base);
72ea344b
FB
1241 /* for MPEG2, the frame can be repeated, so we update the
1242 clock accordingly */
267e9dfa 1243 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
72ea344b 1244 is->video_clock += frame_delay;
638c9d91
FB
1245
1246#if defined(DEBUG_SYNC) && 0
1247 {
1248 int ftype;
1249 if (src_frame->pict_type == FF_B_TYPE)
1250 ftype = 'B';
1251 else if (src_frame->pict_type == FF_I_TYPE)
1252 ftype = 'I';
1253 else
1254 ftype = 'P';
1255 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
72ea344b 1256 ftype, pts, pts1);
638c9d91
FB
1257 }
1258#endif
72ea344b 1259 return queue_picture(is, src_frame, pts);
01310af2
FB
1260}
1261
1262static int video_thread(void *arg)
1263{
1264 VideoState *is = arg;
1265 AVPacket pkt1, *pkt = &pkt1;
72ea344b 1266 int len1, got_picture;
c6b1edc9 1267 AVFrame *frame= avcodec_alloc_frame();
01310af2
FB
1268 double pts;
1269
1270 for(;;) {
1271 while (is->paused && !is->videoq.abort_request) {
1272 SDL_Delay(10);
1273 }
1274 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1275 break;
638c9d91
FB
1276 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1277 this packet, if any */
72ea344b 1278 pts = 0;
61c1d8e2 1279 if (pkt->dts != AV_NOPTS_VALUE)
c0df9d75 1280 pts = av_q2d(is->video_st->time_base)*pkt->dts;
72ea344b 1281
b514ed3c 1282 SDL_LockMutex(is->video_decoder_mutex);
01f4895c 1283 len1 = avcodec_decode_video(is->video_st->codec,
72ea344b
FB
1284 frame, &got_picture,
1285 pkt->data, pkt->size);
b514ed3c 1286 SDL_UnlockMutex(is->video_decoder_mutex);
fb966f99
MN
1287// if (len1 < 0)
1288// break;
72ea344b
FB
1289 if (got_picture) {
1290 if (output_picture2(is, frame, pts) < 0)
1291 goto the_end;
01310af2 1292 }
01310af2 1293 av_free_packet(pkt);
bba04f1e
WH
1294 if (step)
1295 if (cur_stream)
1296 stream_pause(cur_stream);
01310af2
FB
1297 }
1298 the_end:
c6b1edc9 1299 av_free(frame);
01310af2
FB
1300 return 0;
1301}
1302
72ce053b
IC
1303static int subtitle_thread(void *arg)
1304{
1305 VideoState *is = arg;
1306 SubPicture *sp;
1307 AVPacket pkt1, *pkt = &pkt1;
1308 int len1, got_subtitle;
1309 double pts;
1310 int i, j;
1311 int r, g, b, y, u, v, a;
1312
1313 for(;;) {
1314 while (is->paused && !is->subtitleq.abort_request) {
1315 SDL_Delay(10);
1316 }
1317 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1318 break;
1319
1320 SDL_LockMutex(is->subpq_mutex);
1321 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1322 !is->subtitleq.abort_request) {
1323 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1324 }
1325 SDL_UnlockMutex(is->subpq_mutex);
1326
1327 if (is->subtitleq.abort_request)
1328 goto the_end;
1329
1330 sp = &is->subpq[is->subpq_windex];
1331
1332 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1333 this packet, if any */
1334 pts = 0;
1335 if (pkt->pts != AV_NOPTS_VALUE)
1336 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1337
1338 SDL_LockMutex(is->subtitle_decoder_mutex);
1339 len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
1340 &sp->sub, &got_subtitle,
1341 pkt->data, pkt->size);
1342 SDL_UnlockMutex(is->subtitle_decoder_mutex);
1343// if (len1 < 0)
1344// break;
1345 if (got_subtitle && sp->sub.format == 0) {
1346 sp->pts = pts;
1347
1348 for (i = 0; i < sp->sub.num_rects; i++)
1349 {
1350 for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
1351 {
1352 RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
1353 y = RGB_TO_Y_CCIR(r, g, b);
1354 u = RGB_TO_U_CCIR(r, g, b, 0);
1355 v = RGB_TO_V_CCIR(r, g, b, 0);
1356 YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
1357 }
1358 }
1359
1360 /* now we can update the picture count */
1361 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1362 is->subpq_windex = 0;
1363 SDL_LockMutex(is->subpq_mutex);
1364 is->subpq_size++;
1365 SDL_UnlockMutex(is->subpq_mutex);
1366 }
1367 av_free_packet(pkt);
1368// if (step)
1369// if (cur_stream)
1370// stream_pause(cur_stream);
1371 }
1372 the_end:
1373 return 0;
1374}
1375
01310af2
FB
1376/* copy samples for viewing in editor window */
1377static void update_sample_display(VideoState *is, short *samples, int samples_size)
1378{
1379 int size, len, channels;
1380
01f4895c 1381 channels = is->audio_st->codec->channels;
01310af2
FB
1382
1383 size = samples_size / sizeof(short);
1384 while (size > 0) {
1385 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1386 if (len > size)
1387 len = size;
1388 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1389 samples += len;
1390 is->sample_array_index += len;
1391 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1392 is->sample_array_index = 0;
1393 size -= len;
1394 }
1395}
1396
01310af2
FB
1397/* return the new audio buffer size (samples can be added or deleted
1398 to get better sync if video or external master clock) */
1399static int synchronize_audio(VideoState *is, short *samples,
638c9d91 1400 int samples_size1, double pts)
01310af2 1401{
638c9d91 1402 int n, samples_size;
01310af2
FB
1403 double ref_clock;
1404
01f4895c 1405 n = 2 * is->audio_st->codec->channels;
638c9d91 1406 samples_size = samples_size1;
01310af2 1407
01310af2 1408 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 1409 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
1410 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1411 double diff, avg_diff;
01310af2 1412 int wanted_size, min_size, max_size, nb_samples;
638c9d91
FB
1413
1414 ref_clock = get_master_clock(is);
1415 diff = get_audio_clock(is) - ref_clock;
01310af2 1416
638c9d91
FB
1417 if (diff < AV_NOSYNC_THRESHOLD) {
1418 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1419 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1420 /* not enough measures to have a correct estimate */
1421 is->audio_diff_avg_count++;
1422 } else {
1423 /* estimate the A-V difference */
1424 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1425
1426 if (fabs(avg_diff) >= is->audio_diff_threshold) {
01f4895c 1427 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
638c9d91
FB
1428 nb_samples = samples_size / n;
1429
1430 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1431 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1432 if (wanted_size < min_size)
1433 wanted_size = min_size;
1434 else if (wanted_size > max_size)
1435 wanted_size = max_size;
1436
1437 /* add or remove samples to correction the synchro */
1438 if (wanted_size < samples_size) {
1439 /* remove samples */
1440 samples_size = wanted_size;
1441 } else if (wanted_size > samples_size) {
1442 uint8_t *samples_end, *q;
1443 int nb;
1444
1445 /* add samples */
1446 nb = (samples_size - wanted_size);
1447 samples_end = (uint8_t *)samples + samples_size - n;
1448 q = samples_end + n;
1449 while (nb > 0) {
1450 memcpy(q, samples_end, n);
1451 q += n;
1452 nb -= n;
1453 }
1454 samples_size = wanted_size;
1455 }
1456 }
1457#if 0
1458 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1459 diff, avg_diff, samples_size - samples_size1,
1460 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1461#endif
01310af2 1462 }
638c9d91
FB
1463 } else {
1464 /* too big difference : may be initial PTS errors, so
1465 reset A-V filter */
1466 is->audio_diff_avg_count = 0;
1467 is->audio_diff_cum = 0;
01310af2
FB
1468 }
1469 }
1470
01310af2
FB
1471 return samples_size;
1472}
1473
1474/* decode one audio frame and returns its uncompressed size */
1475static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1476{
1477 AVPacket *pkt = &is->audio_pkt;
72ea344b 1478 int n, len1, data_size;
01310af2
FB
1479 double pts;
1480
1481 for(;;) {
72ea344b 1482 /* NOTE: the audio packet can contain several frames */
01310af2 1483 while (is->audio_pkt_size > 0) {
b514ed3c 1484 SDL_LockMutex(is->audio_decoder_mutex);
01f4895c 1485 len1 = avcodec_decode_audio(is->audio_st->codec,
01310af2
FB
1486 (int16_t *)audio_buf, &data_size,
1487 is->audio_pkt_data, is->audio_pkt_size);
b514ed3c 1488 SDL_UnlockMutex(is->audio_decoder_mutex);
72ea344b
FB
1489 if (len1 < 0) {
1490 /* if error, we skip the frame */
1491 is->audio_pkt_size = 0;
01310af2 1492 break;
72ea344b
FB
1493 }
1494
01310af2
FB
1495 is->audio_pkt_data += len1;
1496 is->audio_pkt_size -= len1;
72ea344b
FB
1497 if (data_size <= 0)
1498 continue;
1499 /* if no pts, then compute it */
1500 pts = is->audio_clock;
1501 *pts_ptr = pts;
01f4895c 1502 n = 2 * is->audio_st->codec->channels;
72ea344b 1503 is->audio_clock += (double)data_size /
01f4895c 1504 (double)(n * is->audio_st->codec->sample_rate);
638c9d91 1505#if defined(DEBUG_SYNC)
72ea344b
FB
1506 {
1507 static double last_clock;
1508 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1509 is->audio_clock - last_clock,
1510 is->audio_clock, pts);
1511 last_clock = is->audio_clock;
01310af2 1512 }
72ea344b
FB
1513#endif
1514 return data_size;
01310af2
FB
1515 }
1516
72ea344b
FB
1517 /* free the current packet */
1518 if (pkt->data)
01310af2 1519 av_free_packet(pkt);
72ea344b
FB
1520
1521 if (is->paused || is->audioq.abort_request) {
1522 return -1;
1523 }
1524
01310af2
FB
1525 /* read next packet */
1526 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1527 return -1;
1528 is->audio_pkt_data = pkt->data;
1529 is->audio_pkt_size = pkt->size;
72ea344b
FB
1530
1531 /* if update the audio clock with the pts */
1532 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1533 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1534 }
01310af2
FB
1535 }
1536}
1537
638c9d91
FB
1538/* get the current audio output buffer size, in samples. With SDL, we
1539 cannot have a precise information */
1540static int audio_write_get_buf_size(VideoState *is)
01310af2 1541{
638c9d91 1542 return is->audio_hw_buf_size - is->audio_buf_index;
01310af2
FB
1543}
1544
1545
1546/* prepare a new audio buffer */
1547void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1548{
1549 VideoState *is = opaque;
1550 int audio_size, len1;
1551 double pts;
1552
1553 audio_callback_time = av_gettime();
1554
1555 while (len > 0) {
1556 if (is->audio_buf_index >= is->audio_buf_size) {
1557 audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1558 if (audio_size < 0) {
1559 /* if error, just output silence */
1560 is->audio_buf_size = 1024;
1561 memset(is->audio_buf, 0, is->audio_buf_size);
1562 } else {
1563 if (is->show_audio)
1564 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1565 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1566 pts);
1567 is->audio_buf_size = audio_size;
1568 }
1569 is->audio_buf_index = 0;
1570 }
1571 len1 = is->audio_buf_size - is->audio_buf_index;
1572 if (len1 > len)
1573 len1 = len;
1574 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1575 len -= len1;
1576 stream += len1;
1577 is->audio_buf_index += len1;
1578 }
1579}
1580
1581
1582/* open a given stream. Return 0 if OK */
1583static int stream_component_open(VideoState *is, int stream_index)
1584{
1585 AVFormatContext *ic = is->ic;
1586 AVCodecContext *enc;
1587 AVCodec *codec;
1588 SDL_AudioSpec wanted_spec, spec;
1589
1590 if (stream_index < 0 || stream_index >= ic->nb_streams)
1591 return -1;
01f4895c 1592 enc = ic->streams[stream_index]->codec;
01310af2 1593
01310af2
FB
1594 /* prepare audio output */
1595 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1596 wanted_spec.freq = enc->sample_rate;
1597 wanted_spec.format = AUDIO_S16SYS;
638c9d91
FB
1598 /* hack for AC3. XXX: suppress that */
1599 if (enc->channels > 2)
1600 enc->channels = 2;
01310af2
FB
1601 wanted_spec.channels = enc->channels;
1602 wanted_spec.silence = 0;
638c9d91 1603 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
01310af2
FB
1604 wanted_spec.callback = sdl_audio_callback;
1605 wanted_spec.userdata = is;
638c9d91
FB
1606 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1607 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
01310af2 1608 return -1;
638c9d91 1609 }
01310af2
FB
1610 is->audio_hw_buf_size = spec.size;
1611 }
1612
1613 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1614 enc->debug_mv = debug_mv;
1615 enc->debug = debug;
1ab1f099
MN
1616 if(debug)
1617 av_log_set_level(AV_LOG_DEBUG);
6387c3e6 1618 enc->workaround_bugs = workaround_bugs;
178fcca8 1619 enc->lowres = lowres;
61846e9a 1620 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1621 enc->idct_algo= idct;
6fc5b059 1622 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
8c3eba7c
MN
1623 enc->skip_frame= skip_frame;
1624 enc->skip_idct= skip_idct;
1625 enc->skip_loop_filter= skip_loop_filter;
1b51e051
MN
1626 enc->error_resilience= error_resilience;
1627 enc->error_concealment= error_concealment;
01310af2
FB
1628 if (!codec ||
1629 avcodec_open(enc, codec) < 0)
1630 return -1;
2450cff2 1631#if defined(HAVE_THREADS)
c62c07d3
MN
1632 if(thread_count>1)
1633 avcodec_thread_init(enc, thread_count);
1634#endif
1635 enc->thread_count= thread_count;
638c9d91 1636 switch(enc->codec_type) {
01310af2
FB
1637 case CODEC_TYPE_AUDIO:
1638 is->audio_stream = stream_index;
1639 is->audio_st = ic->streams[stream_index];
1640 is->audio_buf_size = 0;
1641 is->audio_buf_index = 0;
638c9d91
FB
1642
1643 /* init averaging filter */
1644 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1645 is->audio_diff_avg_count = 0;
1646 /* since we do not have a precise anough audio fifo fullness,
1647 we correct audio sync only if larger than this threshold */
1648 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1649
01310af2
FB
1650 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1651 packet_queue_init(&is->audioq);
1652 SDL_PauseAudio(0);
1653 break;
1654 case CODEC_TYPE_VIDEO:
1655 is->video_stream = stream_index;
1656 is->video_st = ic->streams[stream_index];
1657
638c9d91
FB
1658 is->frame_last_delay = 40e-3;
1659 is->frame_timer = (double)av_gettime() / 1000000.0;
638c9d91
FB
1660 is->video_current_pts_time = av_gettime();
1661
01310af2
FB
1662 packet_queue_init(&is->videoq);
1663 is->video_tid = SDL_CreateThread(video_thread, is);
1664 break;
72ce053b
IC
1665 case CODEC_TYPE_SUBTITLE:
1666 is->subtitle_stream = stream_index;
1667 is->subtitle_st = ic->streams[stream_index];
1668 packet_queue_init(&is->subtitleq);
1669
1670 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1671 break;
01310af2
FB
1672 default:
1673 break;
1674 }
1675 return 0;
1676}
1677
1678static void stream_component_close(VideoState *is, int stream_index)
1679{
1680 AVFormatContext *ic = is->ic;
1681 AVCodecContext *enc;
1682
72ce053b
IC
1683 if (stream_index < 0 || stream_index >= ic->nb_streams)
1684 return;
01f4895c 1685 enc = ic->streams[stream_index]->codec;
01310af2
FB
1686
1687 switch(enc->codec_type) {
1688 case CODEC_TYPE_AUDIO:
1689 packet_queue_abort(&is->audioq);
1690
1691 SDL_CloseAudio();
1692
1693 packet_queue_end(&is->audioq);
1694 break;
1695 case CODEC_TYPE_VIDEO:
1696 packet_queue_abort(&is->videoq);
1697
1698 /* note: we also signal this mutex to make sure we deblock the
1699 video thread in all cases */
1700 SDL_LockMutex(is->pictq_mutex);
1701 SDL_CondSignal(is->pictq_cond);
1702 SDL_UnlockMutex(is->pictq_mutex);
1703
1704 SDL_WaitThread(is->video_tid, NULL);
1705
1706 packet_queue_end(&is->videoq);
1707 break;
72ce053b
IC
1708 case CODEC_TYPE_SUBTITLE:
1709 packet_queue_abort(&is->subtitleq);
1710
1711 /* note: we also signal this mutex to make sure we deblock the
1712 video thread in all cases */
1713 SDL_LockMutex(is->subpq_mutex);
1714 is->subtitle_stream_changed = 1;
1715
1716 SDL_CondSignal(is->subpq_cond);
1717 SDL_UnlockMutex(is->subpq_mutex);
1718
1719 SDL_WaitThread(is->subtitle_tid, NULL);
1720
1721 packet_queue_end(&is->subtitleq);
1722 break;
01310af2
FB
1723 default:
1724 break;
1725 }
1726
1727 avcodec_close(enc);
1728 switch(enc->codec_type) {
1729 case CODEC_TYPE_AUDIO:
1730 is->audio_st = NULL;
1731 is->audio_stream = -1;
1732 break;
1733 case CODEC_TYPE_VIDEO:
1734 is->video_st = NULL;
1735 is->video_stream = -1;
1736 break;
72ce053b
IC
1737 case CODEC_TYPE_SUBTITLE:
1738 is->subtitle_st = NULL;
1739 is->subtitle_stream = -1;
1740 break;
01310af2
FB
1741 default:
1742 break;
1743 }
1744}
1745
d0526ecf
FB
1746void dump_stream_info(AVFormatContext *s)
1747{
1748 if (s->track != 0)
1749 fprintf(stderr, "Track: %d\n", s->track);
1750 if (s->title[0] != '\0')
1751 fprintf(stderr, "Title: %s\n", s->title);
1752 if (s->author[0] != '\0')
1753 fprintf(stderr, "Author: %s\n", s->author);
1754 if (s->album[0] != '\0')
1755 fprintf(stderr, "Album: %s\n", s->album);
1756 if (s->year != 0)
1757 fprintf(stderr, "Year: %d\n", s->year);
1758 if (s->genre[0] != '\0')
1759 fprintf(stderr, "Genre: %s\n", s->genre);
1760}
1761
416e3508
FB
1762/* since we have only one decoding thread, we can use a global
1763 variable instead of a thread local variable */
1764static VideoState *global_video_state;
1765
1766static int decode_interrupt_cb(void)
1767{
1768 return (global_video_state && global_video_state->abort_request);
1769}
01310af2
FB
1770
1771/* this thread gets the stream from the disk or the network */
1772static int decode_thread(void *arg)
1773{
1774 VideoState *is = arg;
1775 AVFormatContext *ic;
72ea344b 1776 int err, i, ret, video_index, audio_index, use_play;
01310af2 1777 AVPacket pkt1, *pkt = &pkt1;
61890b02 1778 AVFormatParameters params, *ap = &params;
01310af2
FB
1779
1780 video_index = -1;
1781 audio_index = -1;
1782 is->video_stream = -1;
1783 is->audio_stream = -1;
72ce053b 1784 is->subtitle_stream = -1;
01310af2 1785
416e3508
FB
1786 global_video_state = is;
1787 url_set_interrupt_cb(decode_interrupt_cb);
1788
61890b02
FB
1789 memset(ap, 0, sizeof(*ap));
1790 ap->image_format = image_format;
72ea344b
FB
1791 ap->initial_pause = 1; /* we force a pause when starting an RTSP
1792 stream */
1793
61890b02 1794 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1795 if (err < 0) {
1796 print_error(is->filename, err);
1797 ret = -1;
1798 goto fail;
1799 }
01310af2 1800 is->ic = ic;
72ea344b
FB
1801#ifdef CONFIG_NETWORK
1802 use_play = (ic->iformat == &rtsp_demux);
1803#else
1804 use_play = 0;
1805#endif
30bc6613
MN
1806
1807 if(genpts)
1808 ic->flags |= AVFMT_FLAG_GENPTS;
1809
72ea344b
FB
1810 if (!use_play) {
1811 err = av_find_stream_info(ic);
1812 if (err < 0) {
1813 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1814 ret = -1;
1815 goto fail;
1816 }
2536c5fd 1817 ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
638c9d91 1818 }
72ea344b
FB
1819
1820 /* if seeking requested, we execute it */
1821 if (start_time != AV_NOPTS_VALUE) {
1822 int64_t timestamp;
1823
1824 timestamp = start_time;
1825 /* add the stream start time */
1826 if (ic->start_time != AV_NOPTS_VALUE)
1827 timestamp += ic->start_time;
3ba1438d 1828 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
72ea344b
FB
1829 if (ret < 0) {
1830 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1831 is->filename, (double)timestamp / AV_TIME_BASE);
1832 }
1833 }
1834
1835 /* now we can begin to play (RTSP stream only) */
1836 av_read_play(ic);
1837
1838 if (use_play) {
1839 err = av_find_stream_info(ic);
1840 if (err < 0) {
1841 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1842 ret = -1;
1843 goto fail;
1844 }
1845 }
1846
01310af2 1847 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1848 AVCodecContext *enc = ic->streams[i]->codec;
01310af2
FB
1849 switch(enc->codec_type) {
1850 case CODEC_TYPE_AUDIO:
1851 if (audio_index < 0 && !audio_disable)
1852 audio_index = i;
1853 break;
1854 case CODEC_TYPE_VIDEO:
1855 if (video_index < 0 && !video_disable)
1856 video_index = i;
1857 break;
1858 default:
1859 break;
1860 }
1861 }
1862 if (show_status) {
1863 dump_format(ic, 0, is->filename, 0);
d0526ecf 1864 dump_stream_info(ic);
01310af2
FB
1865 }
1866
1867 /* open the streams */
1868 if (audio_index >= 0) {
1869 stream_component_open(is, audio_index);
1870 }
1871
1872 if (video_index >= 0) {
1873 stream_component_open(is, video_index);
1874 } else {
1875 if (!display_disable)
1876 is->show_audio = 1;
1877 }
1878
1879 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1880 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1881 ret = -1;
01310af2
FB
1882 goto fail;
1883 }
1884
1885 for(;;) {
1886 if (is->abort_request)
1887 break;
400738b1 1888#ifdef CONFIG_NETWORK
416e3508
FB
1889 if (is->paused != is->last_paused) {
1890 is->last_paused = is->paused;
72ea344b
FB
1891 if (is->paused)
1892 av_read_pause(ic);
1893 else
1894 av_read_play(ic);
416e3508
FB
1895 }
1896 if (is->paused && ic->iformat == &rtsp_demux) {
1897 /* wait 10 ms to avoid trying to get another packet */
1898 /* XXX: horrible */
1899 SDL_Delay(10);
1900 continue;
1901 }
400738b1 1902#endif
72ea344b
FB
1903 if (is->seek_req) {
1904 /* XXX: must lock decoder threads */
687fae2b
IW
1905 SDL_LockMutex(is->video_decoder_mutex);
1906 SDL_LockMutex(is->audio_decoder_mutex);
72ce053b 1907 SDL_LockMutex(is->subtitle_decoder_mutex);
3ba1438d 1908 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
72ea344b
FB
1909 if (ret < 0) {
1910 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
1911 }else{
1912 if (is->audio_stream >= 0) {
1913 packet_queue_flush(&is->audioq);
1914 }
72ce053b
IC
1915 if (is->subtitle_stream >= 0) {
1916 packet_queue_flush(&is->subtitleq);
1917 }
e6c0297f
MN
1918 if (is->video_stream >= 0) {
1919 packet_queue_flush(&is->videoq);
01f4895c 1920 avcodec_flush_buffers(ic->streams[video_index]->codec);
e6c0297f 1921 }
72ea344b 1922 }
72ce053b 1923 SDL_UnlockMutex(is->subtitle_decoder_mutex);
687fae2b
IW
1924 SDL_UnlockMutex(is->audio_decoder_mutex);
1925 SDL_UnlockMutex(is->video_decoder_mutex);
72ea344b
FB
1926 is->seek_req = 0;
1927 }
416e3508 1928
01310af2
FB
1929 /* if the queue are full, no need to read more */
1930 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
0c904df2 1931 is->videoq.size > MAX_VIDEOQ_SIZE ||
72ce053b 1932 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
0c904df2 1933 url_feof(&ic->pb)) {
01310af2
FB
1934 /* wait 10 ms */
1935 SDL_Delay(10);
1936 continue;
1937 }
72ea344b 1938 ret = av_read_frame(ic, pkt);
01310af2 1939 if (ret < 0) {
22e50022 1940 if (url_ferror(&ic->pb) == 0) {
6e1f8725
RS
1941 SDL_Delay(100); /* wait for user event */
1942 continue;
1943 } else
1944 break;
01310af2
FB
1945 }
1946 if (pkt->stream_index == is->audio_stream) {
1947 packet_queue_put(&is->audioq, pkt);
1948 } else if (pkt->stream_index == is->video_stream) {
1949 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
1950 } else if (pkt->stream_index == is->subtitle_stream) {
1951 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
1952 } else {
1953 av_free_packet(pkt);
1954 }
1955 }
1956 /* wait until the end */
1957 while (!is->abort_request) {
1958 SDL_Delay(100);
1959 }
1960
638c9d91 1961 ret = 0;
01310af2 1962 fail:
416e3508
FB
1963 /* disable interrupting */
1964 global_video_state = NULL;
1965
01310af2
FB
1966 /* close each stream */
1967 if (is->audio_stream >= 0)
1968 stream_component_close(is, is->audio_stream);
1969 if (is->video_stream >= 0)
1970 stream_component_close(is, is->video_stream);
72ce053b
IC
1971 if (is->subtitle_stream >= 0)
1972 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
1973 if (is->ic) {
1974 av_close_input_file(is->ic);
1975 is->ic = NULL; /* safety */
1976 }
416e3508
FB
1977 url_set_interrupt_cb(NULL);
1978
638c9d91
FB
1979 if (ret != 0) {
1980 SDL_Event event;
1981
1982 event.type = FF_QUIT_EVENT;
1983 event.user.data1 = is;
1984 SDL_PushEvent(&event);
1985 }
01310af2
FB
1986 return 0;
1987}
1988
638c9d91 1989static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
1990{
1991 VideoState *is;
1992
1993 is = av_mallocz(sizeof(VideoState));
1994 if (!is)
1995 return NULL;
1996 pstrcpy(is->filename, sizeof(is->filename), filename);
638c9d91 1997 is->iformat = iformat;
01310af2
FB
1998 if (screen) {
1999 is->width = screen->w;
2000 is->height = screen->h;
2001 }
2002 is->ytop = 0;
2003 is->xleft = 0;
2004
2005 /* start video display */
2006 is->pictq_mutex = SDL_CreateMutex();
2007 is->pictq_cond = SDL_CreateCond();
b514ed3c 2008
72ce053b
IC
2009 is->subpq_mutex = SDL_CreateMutex();
2010 is->subpq_cond = SDL_CreateCond();
2011
2012 is->subtitle_decoder_mutex = SDL_CreateMutex();
b514ed3c
MN
2013 is->audio_decoder_mutex = SDL_CreateMutex();
2014 is->video_decoder_mutex = SDL_CreateMutex();
01310af2
FB
2015
2016 /* add the refresh timer to draw the picture */
2017 schedule_refresh(is, 40);
2018
638c9d91 2019 is->av_sync_type = av_sync_type;
01310af2
FB
2020 is->parse_tid = SDL_CreateThread(decode_thread, is);
2021 if (!is->parse_tid) {
2022 av_free(is);
2023 return NULL;
2024 }
2025 return is;
2026}
2027
2028static void stream_close(VideoState *is)
2029{
2030 VideoPicture *vp;
2031 int i;
2032 /* XXX: use a special url_shutdown call to abort parse cleanly */
2033 is->abort_request = 1;
2034 SDL_WaitThread(is->parse_tid, NULL);
2035
2036 /* free all pictures */
2037 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2038 vp = &is->pictq[i];
2039 if (vp->bmp) {
2040 SDL_FreeYUVOverlay(vp->bmp);
2041 vp->bmp = NULL;
2042 }
2043 }
2044 SDL_DestroyMutex(is->pictq_mutex);
2045 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2046 SDL_DestroyMutex(is->subpq_mutex);
2047 SDL_DestroyCond(is->subpq_cond);
2048 SDL_DestroyMutex(is->subtitle_decoder_mutex);
b514ed3c
MN
2049 SDL_DestroyMutex(is->audio_decoder_mutex);
2050 SDL_DestroyMutex(is->video_decoder_mutex);
01310af2
FB
2051}
2052
638c9d91
FB
2053void stream_cycle_channel(VideoState *is, int codec_type)
2054{
2055 AVFormatContext *ic = is->ic;
2056 int start_index, stream_index;
2057 AVStream *st;
2058
2059 if (codec_type == CODEC_TYPE_VIDEO)
2060 start_index = is->video_stream;
72ce053b 2061 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2062 start_index = is->audio_stream;
72ce053b
IC
2063 else
2064 start_index = is->subtitle_stream;
2065 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2066 return;
2067 stream_index = start_index;
2068 for(;;) {
2069 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2070 {
2071 if (codec_type == CODEC_TYPE_SUBTITLE)
2072 {
2073 stream_index = -1;
2074 goto the_end;
2075 } else
2076 stream_index = 0;
2077 }
638c9d91
FB
2078 if (stream_index == start_index)
2079 return;
2080 st = ic->streams[stream_index];
01f4895c 2081 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2082 /* check that parameters are OK */
2083 switch(codec_type) {
2084 case CODEC_TYPE_AUDIO:
01f4895c
MN
2085 if (st->codec->sample_rate != 0 &&
2086 st->codec->channels != 0)
638c9d91
FB
2087 goto the_end;
2088 break;
2089 case CODEC_TYPE_VIDEO:
72ce053b 2090 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2091 goto the_end;
2092 default:
2093 break;
2094 }
2095 }
2096 }
2097 the_end:
2098 stream_component_close(is, start_index);
2099 stream_component_open(is, stream_index);
2100}
2101
2102
01310af2
FB
2103void toggle_full_screen(void)
2104{
2105 int w, h, flags;
2106 is_full_screen = !is_full_screen;
2107 if (!fs_screen_width) {
2108 /* use default SDL method */
2109 SDL_WM_ToggleFullScreen(screen);
2110 } else {
2111 /* use the recorded resolution */
2112 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2113 if (is_full_screen) {
2114 w = fs_screen_width;
2115 h = fs_screen_height;
2116 flags |= SDL_FULLSCREEN;
2117 } else {
2118 w = screen_width;
2119 h = screen_height;
2120 flags |= SDL_RESIZABLE;
2121 }
2122 screen = SDL_SetVideoMode(w, h, 0, flags);
2123 cur_stream->width = w;
2124 cur_stream->height = h;
2125 }
2126}
2127
2128void toggle_pause(void)
2129{
2130 if (cur_stream)
2131 stream_pause(cur_stream);
bba04f1e
WH
2132 step = 0;
2133}
2134
2135void step_to_next_frame(void)
2136{
2137 if (cur_stream) {
2138 if (cur_stream->paused)
2139 cur_stream->paused=0;
2140 cur_stream->video_current_pts = get_video_clock(cur_stream);
2141 }
2142 step = 1;
01310af2
FB
2143}
2144
2145void do_exit(void)
2146{
2147 if (cur_stream) {
2148 stream_close(cur_stream);
2149 cur_stream = NULL;
2150 }
2151 if (show_status)
2152 printf("\n");
2153 SDL_Quit();
2154 exit(0);
2155}
2156
2157void toggle_audio_display(void)
2158{
2159 if (cur_stream) {
2160 cur_stream->show_audio = !cur_stream->show_audio;
2161 }
2162}
2163
2164/* handle an event sent by the GUI */
2165void event_loop(void)
2166{
2167 SDL_Event event;
a11d11aa 2168 double incr, pos, frac;
01310af2
FB
2169
2170 for(;;) {
2171 SDL_WaitEvent(&event);
2172 switch(event.type) {
2173 case SDL_KEYDOWN:
2174 switch(event.key.keysym.sym) {
2175 case SDLK_ESCAPE:
2176 case SDLK_q:
2177 do_exit();
2178 break;
2179 case SDLK_f:
2180 toggle_full_screen();
2181 break;
2182 case SDLK_p:
2183 case SDLK_SPACE:
2184 toggle_pause();
2185 break;
bba04f1e
WH
2186 case SDLK_s: //S: Step to next frame
2187 step_to_next_frame();
2188 break;
01310af2 2189 case SDLK_a:
638c9d91
FB
2190 if (cur_stream)
2191 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2192 break;
2193 case SDLK_v:
2194 if (cur_stream)
2195 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2196 break;
72ce053b
IC
2197 case SDLK_t:
2198 if (cur_stream)
2199 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2200 break;
638c9d91 2201 case SDLK_w:
01310af2
FB
2202 toggle_audio_display();
2203 break;
72ea344b
FB
2204 case SDLK_LEFT:
2205 incr = -10.0;
2206 goto do_seek;
2207 case SDLK_RIGHT:
2208 incr = 10.0;
2209 goto do_seek;
2210 case SDLK_UP:
2211 incr = 60.0;
2212 goto do_seek;
2213 case SDLK_DOWN:
2214 incr = -60.0;
2215 do_seek:
2216 if (cur_stream) {
2217 pos = get_master_clock(cur_stream);
2218 pos += incr;
3ba1438d 2219 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
72ea344b
FB
2220 }
2221 break;
01310af2
FB
2222 default:
2223 break;
2224 }
2225 break;
a11d11aa
MB
2226 case SDL_MOUSEBUTTONDOWN:
2227 if (cur_stream) {
2228 int ns, hh, mm, ss;
2229 int tns, thh, tmm, tss;
2230 tns = cur_stream->ic->duration/1000000LL;
2231 thh = tns/3600;
2232 tmm = (tns%3600)/60;
2233 tss = (tns%60);
2234 frac = (double)event.button.x/(double)cur_stream->width;
2235 ns = frac*tns;
2236 hh = ns/3600;
2237 mm = (ns%3600)/60;
2238 ss = (ns%60);
2239 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2240 hh, mm, ss, thh, tmm, tss);
3ba1438d 2241 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
a11d11aa
MB
2242 }
2243 break;
01310af2
FB
2244 case SDL_VIDEORESIZE:
2245 if (cur_stream) {
2246 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2247 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2248 cur_stream->width = event.resize.w;
2249 cur_stream->height = event.resize.h;
2250 }
2251 break;
2252 case SDL_QUIT:
638c9d91 2253 case FF_QUIT_EVENT:
01310af2
FB
2254 do_exit();
2255 break;
2256 case FF_ALLOC_EVENT:
2257 alloc_picture(event.user.data1);
2258 break;
2259 case FF_REFRESH_EVENT:
2260 video_refresh_timer(event.user.data1);
2261 break;
2262 default:
2263 break;
2264 }
2265 }
2266}
2267
2268void opt_width(const char *arg)
2269{
2270 screen_width = atoi(arg);
2271}
2272
2273void opt_height(const char *arg)
2274{
2275 screen_height = atoi(arg);
2276}
2277
2278static void opt_format(const char *arg)
2279{
2280 file_iformat = av_find_input_format(arg);
2281 if (!file_iformat) {
2282 fprintf(stderr, "Unknown input format: %s\n", arg);
2283 exit(1);
2284 }
2285}
61890b02
FB
2286
2287static void opt_image_format(const char *arg)
2288{
2289 AVImageFormat *f;
2290
2291 for(f = first_image_format; f != NULL; f = f->next) {
2292 if (!strcmp(arg, f->name))
2293 break;
2294 }
2295 if (!f) {
2296 fprintf(stderr, "Unknown image format: '%s'\n", arg);
2297 exit(1);
2298 }
2299 image_format = f;
2300}
2301
400738b1 2302#ifdef CONFIG_NETWORK
416e3508
FB
2303void opt_rtp_tcp(void)
2304{
2305 /* only tcp protocol */
2306 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
2307}
400738b1 2308#endif
416e3508 2309
638c9d91
FB
2310void opt_sync(const char *arg)
2311{
2312 if (!strcmp(arg, "audio"))
2313 av_sync_type = AV_SYNC_AUDIO_MASTER;
2314 else if (!strcmp(arg, "video"))
2315 av_sync_type = AV_SYNC_VIDEO_MASTER;
2316 else if (!strcmp(arg, "ext"))
2317 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2318 else
2319 show_help();
2320}
2321
72ea344b
FB
2322void opt_seek(const char *arg)
2323{
2324 start_time = parse_date(arg, 1);
2325}
2326
e26a8335
WH
2327static void opt_debug(const char *arg)
2328{
2329 debug = atoi(arg);
2330}
2331
0c9bbaec
WH
2332static void opt_vismv(const char *arg)
2333{
2334 debug_mv = atoi(arg);
2335}
c62c07d3
MN
2336
2337static void opt_thread_count(const char *arg)
2338{
2339 thread_count= atoi(arg);
2450cff2 2340#if !defined(HAVE_THREADS)
c62c07d3
MN
2341 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2342#endif
2343}
0c9bbaec 2344
01310af2 2345const OptionDef options[] = {
e26a8335 2346 { "h", 0, {(void*)show_help}, "show help" },
01310af2
FB
2347 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
2348 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
638c9d91
FB
2349#if 0
2350 /* disabled as SDL/X11 does not support it correctly on application launch */
2351 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
2352#endif
01310af2
FB
2353 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2354 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
72ea344b 2355 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
01310af2
FB
2356 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2357 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
61890b02 2358 { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
01310af2 2359 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
e26a8335 2360 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2361 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
0c9bbaec 2362 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2363 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2364 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
178fcca8 2365 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2366 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2367 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2368 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2369 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
1b51e051
MN
2370 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
2371 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
400738b1 2372#ifdef CONFIG_NETWORK
416e3508 2373 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
400738b1 2374#endif
c62c07d3
MN
2375 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2376 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
01310af2
FB
2377 { NULL, },
2378};
2379
2380void show_help(void)
2381{
02d504a7
FB
2382 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
2383 "usage: ffplay [options] input_file\n"
01310af2
FB
2384 "Simple media player\n");
2385 printf("\n");
02d504a7
FB
2386 show_help_options(options, "Main options:\n",
2387 OPT_EXPERT, 0);
2388 show_help_options(options, "\nAdvanced options:\n",
2389 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2390 printf("\nWhile playing:\n"
2391 "q, ESC quit\n"
2392 "f toggle full screen\n"
2393 "p, SPC pause\n"
638c9d91
FB
2394 "a cycle audio channel\n"
2395 "v cycle video channel\n"
72ce053b 2396 "t cycle subtitle channel\n"
638c9d91 2397 "w show audio waves\n"
72ea344b
FB
2398 "left/right seek backward/forward 10 seconds\n"
2399 "down/up seek backward/forward 1 minute\n"
a11d11aa 2400 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2
FB
2401 );
2402 exit(1);
2403}
2404
2405void parse_arg_file(const char *filename)
2406{
e8d83e1c
MN
2407 if (!strcmp(filename, "-"))
2408 filename = "pipe:";
01310af2
FB
2409 input_filename = filename;
2410}
2411
2412/* Called from the main */
2413int main(int argc, char **argv)
2414{
638c9d91 2415 int flags, w, h;
01310af2
FB
2416
2417 /* register all codecs, demux and protocols */
2418 av_register_all();
2419
3ca4b654
MN
2420 #ifdef CONFIG_OS2
2421 MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
2422
2423 // Make stdout and stderr unbuffered
2424 setbuf( stdout, NULL );
2425 setbuf( stderr, NULL );
2426 #endif
2427
01310af2
FB
2428 parse_options(argc, argv, options);
2429
2430 if (!input_filename)
2431 show_help();
2432
2433 if (display_disable) {
2434 video_disable = 1;
2435 }
31319a8c
FB
2436 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2437#ifndef CONFIG_WIN32
2438 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 */
2439#endif
01310af2 2440 if (SDL_Init (flags)) {
05ab0b76 2441 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2442 exit(1);
2443 }
2444
2445 if (!display_disable) {
01310af2
FB
2446#ifdef HAVE_X11
2447 /* save the screen resolution... SDL should allow full screen
2448 by resizing the window */
2449 {
2450 Display *dpy;
2451 dpy = XOpenDisplay(NULL);
2452 if (dpy) {
2453 fs_screen_width = DisplayWidth(dpy, DefaultScreen(dpy));
2454 fs_screen_height = DisplayHeight(dpy, DefaultScreen(dpy));
2455 XCloseDisplay(dpy);
2456 }
2457 }
2458#endif
638c9d91
FB
2459 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2460 if (is_full_screen && fs_screen_width) {
2461 w = fs_screen_width;
2462 h = fs_screen_height;
2463 flags |= SDL_FULLSCREEN;
2464 } else {
2465 w = screen_width;
2466 h = screen_height;
2467 flags |= SDL_RESIZABLE;
2468 }
2469 screen = SDL_SetVideoMode(w, h, 0, flags);
2470 if (!screen) {
2471 fprintf(stderr, "SDL: could not set video mode - exiting\n");
2472 exit(1);
2473 }
2474 SDL_WM_SetCaption("FFplay", "FFplay");
01310af2
FB
2475 }
2476
2477 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2478 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2479 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2480 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2481
638c9d91 2482 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2483
2484 event_loop();
2485
2486 /* never returns */
2487
2488 return 0;
2489}