GCC4 fix
[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)
60
638c9d91
FB
61/* SDL audio buffer size, in samples. Should be small to have precise
62 A/V sync as SDL does not have hardware buffer fullness info. */
63#define SDL_AUDIO_BUFFER_SIZE 1024
64
65/* no AV sync correction is done if below the AV sync threshold */
7e0140cb 66#define AV_SYNC_THRESHOLD 0.01
638c9d91
FB
67/* no AV correction is done if too big error */
68#define AV_NOSYNC_THRESHOLD 10.0
69
70/* maximum audio speed change to get correct sync */
71#define SAMPLE_CORRECTION_PERCENT_MAX 10
72
73/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
74#define AUDIO_DIFF_AVG_NB 20
75
01310af2
FB
76/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
77#define SAMPLE_ARRAY_SIZE (2*65536)
78
79typedef struct PacketQueue {
80 AVPacketList *first_pkt, *last_pkt;
81 int nb_packets;
82 int size;
83 int abort_request;
84 SDL_mutex *mutex;
85 SDL_cond *cond;
86} PacketQueue;
87
88#define VIDEO_PICTURE_QUEUE_SIZE 1
89
90typedef struct VideoPicture {
638c9d91 91 double pts; /* presentation time stamp for this picture */
01310af2
FB
92 SDL_Overlay *bmp;
93 int width, height; /* source height & width */
94 int allocated;
95} VideoPicture;
96
97enum {
98 AV_SYNC_AUDIO_MASTER, /* default choice */
99 AV_SYNC_VIDEO_MASTER,
638c9d91 100 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
01310af2
FB
101};
102
103typedef struct VideoState {
104 SDL_Thread *parse_tid;
105 SDL_Thread *video_tid;
638c9d91 106 AVInputFormat *iformat;
01310af2
FB
107 int no_background;
108 int abort_request;
109 int paused;
416e3508 110 int last_paused;
72ea344b 111 int seek_req;
3ba1438d 112 int seek_flags;
72ea344b 113 int64_t seek_pos;
01310af2
FB
114 AVFormatContext *ic;
115 int dtg_active_format;
116
117 int audio_stream;
118
119 int av_sync_type;
638c9d91
FB
120 double external_clock; /* external clock base */
121 int64_t external_clock_time;
122
123 double audio_clock;
124 double audio_diff_cum; /* used for AV difference average computation */
125 double audio_diff_avg_coef;
126 double audio_diff_threshold;
127 int audio_diff_avg_count;
01310af2
FB
128 AVStream *audio_st;
129 PacketQueue audioq;
130 int audio_hw_buf_size;
131 /* samples output by the codec. we reserve more space for avsync
132 compensation */
133 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
7fea94ce 134 unsigned int audio_buf_size; /* in bytes */
01310af2
FB
135 int audio_buf_index; /* in bytes */
136 AVPacket audio_pkt;
137 uint8_t *audio_pkt_data;
138 int audio_pkt_size;
01310af2
FB
139
140 int show_audio; /* if true, display audio samples */
141 int16_t sample_array[SAMPLE_ARRAY_SIZE];
142 int sample_array_index;
5e0257e3 143 int last_i_start;
01310af2 144
638c9d91
FB
145 double frame_timer;
146 double frame_last_pts;
147 double frame_last_delay;
148 double video_clock;
01310af2
FB
149 int video_stream;
150 AVStream *video_st;
151 PacketQueue videoq;
638c9d91
FB
152 double video_last_P_pts; /* pts of the last P picture (needed if B
153 frames are present) */
154 double video_current_pts; /* current displayed pts (different from
155 video_clock if frame fifos are used) */
156 int64_t video_current_pts_time; /* time at which we updated
157 video_current_pts - used to
158 have running video pts */
01310af2
FB
159 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
160 int pictq_size, pictq_rindex, pictq_windex;
161 SDL_mutex *pictq_mutex;
162 SDL_cond *pictq_cond;
163
b514ed3c
MN
164 SDL_mutex *video_decoder_mutex;
165 SDL_mutex *audio_decoder_mutex;
166
01310af2
FB
167 // QETimer *video_timer;
168 char filename[1024];
169 int width, height, xleft, ytop;
170} VideoState;
171
172void show_help(void);
638c9d91 173static int audio_write_get_buf_size(VideoState *is);
01310af2
FB
174
175/* options specified by the user */
176static AVInputFormat *file_iformat;
61890b02 177static AVImageFormat *image_format;
01310af2
FB
178static const char *input_filename;
179static int fs_screen_width;
180static int fs_screen_height;
181static int screen_width = 640;
182static int screen_height = 480;
183static int audio_disable;
184static int video_disable;
185static int display_disable;
186static int show_status;
638c9d91 187static int av_sync_type = AV_SYNC_AUDIO_MASTER;
72ea344b 188static int64_t start_time = AV_NOPTS_VALUE;
e26a8335 189static int debug = 0;
0c9bbaec 190static int debug_mv = 0;
bba04f1e 191static int step = 0;
c62c07d3 192static int thread_count = 1;
6387c3e6 193static int workaround_bugs = 1;
6fc5b059 194static int fast = 0;
178fcca8
MN
195static int lowres = 0;
196static int idct = FF_IDCT_AUTO;
01310af2
FB
197
198/* current context */
199static int is_full_screen;
200static VideoState *cur_stream;
5e0257e3 201static int64_t audio_callback_time;
01310af2
FB
202
203#define FF_ALLOC_EVENT (SDL_USEREVENT)
204#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
638c9d91 205#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
01310af2
FB
206
207SDL_Surface *screen;
208
209/* packet queue handling */
210static void packet_queue_init(PacketQueue *q)
211{
212 memset(q, 0, sizeof(PacketQueue));
213 q->mutex = SDL_CreateMutex();
214 q->cond = SDL_CreateCond();
215}
216
72ea344b 217static void packet_queue_flush(PacketQueue *q)
01310af2
FB
218{
219 AVPacketList *pkt, *pkt1;
220
221 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
222 pkt1 = pkt->next;
223 av_free_packet(&pkt->pkt);
da6c4573 224 av_freep(&pkt);
01310af2 225 }
72ea344b
FB
226 q->last_pkt = NULL;
227 q->first_pkt = NULL;
228 q->nb_packets = 0;
229 q->size = 0;
230}
231
232static void packet_queue_end(PacketQueue *q)
233{
234 packet_queue_flush(q);
01310af2
FB
235 SDL_DestroyMutex(q->mutex);
236 SDL_DestroyCond(q->cond);
237}
238
239static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
240{
241 AVPacketList *pkt1;
242
72ea344b
FB
243 /* duplicate the packet */
244 if (av_dup_packet(pkt) < 0)
245 return -1;
246
01310af2
FB
247 pkt1 = av_malloc(sizeof(AVPacketList));
248 if (!pkt1)
249 return -1;
250 pkt1->pkt = *pkt;
251 pkt1->next = NULL;
252
72ea344b 253
01310af2
FB
254 SDL_LockMutex(q->mutex);
255
256 if (!q->last_pkt)
257
258 q->first_pkt = pkt1;
259 else
260 q->last_pkt->next = pkt1;
261 q->last_pkt = pkt1;
262 q->nb_packets++;
263 q->size += pkt1->pkt.size;
264 /* XXX: should duplicate packet data in DV case */
265 SDL_CondSignal(q->cond);
266
267 SDL_UnlockMutex(q->mutex);
268 return 0;
269}
270
271static void packet_queue_abort(PacketQueue *q)
272{
273 SDL_LockMutex(q->mutex);
274
275 q->abort_request = 1;
276
277 SDL_CondSignal(q->cond);
278
279 SDL_UnlockMutex(q->mutex);
280}
281
282/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
283static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
284{
285 AVPacketList *pkt1;
286 int ret;
287
288 SDL_LockMutex(q->mutex);
289
290 for(;;) {
291 if (q->abort_request) {
292 ret = -1;
293 break;
294 }
295
296 pkt1 = q->first_pkt;
297 if (pkt1) {
298 q->first_pkt = pkt1->next;
299 if (!q->first_pkt)
300 q->last_pkt = NULL;
301 q->nb_packets--;
302 q->size -= pkt1->pkt.size;
303 *pkt = pkt1->pkt;
304 av_free(pkt1);
305 ret = 1;
306 break;
307 } else if (!block) {
308 ret = 0;
309 break;
310 } else {
311 SDL_CondWait(q->cond, q->mutex);
312 }
313 }
314 SDL_UnlockMutex(q->mutex);
315 return ret;
316}
317
318static inline void fill_rectangle(SDL_Surface *screen,
319 int x, int y, int w, int h, int color)
320{
321 SDL_Rect rect;
322 rect.x = x;
323 rect.y = y;
324 rect.w = w;
325 rect.h = h;
326 SDL_FillRect(screen, &rect, color);
327}
328
329#if 0
330/* draw only the border of a rectangle */
331void fill_border(VideoState *s, int x, int y, int w, int h, int color)
332{
333 int w1, w2, h1, h2;
334
335 /* fill the background */
336 w1 = x;
337 if (w1 < 0)
338 w1 = 0;
339 w2 = s->width - (x + w);
340 if (w2 < 0)
341 w2 = 0;
342 h1 = y;
343 if (h1 < 0)
344 h1 = 0;
345 h2 = s->height - (y + h);
346 if (h2 < 0)
347 h2 = 0;
348 fill_rectangle(screen,
349 s->xleft, s->ytop,
350 w1, s->height,
351 color);
352 fill_rectangle(screen,
353 s->xleft + s->width - w2, s->ytop,
354 w2, s->height,
355 color);
356 fill_rectangle(screen,
357 s->xleft + w1, s->ytop,
358 s->width - w1 - w2, h1,
359 color);
360 fill_rectangle(screen,
361 s->xleft + w1, s->ytop + s->height - h2,
362 s->width - w1 - w2, h2,
363 color);
364}
365#endif
366
367static void video_image_display(VideoState *is)
368{
369 VideoPicture *vp;
370 float aspect_ratio;
371 int width, height, x, y;
372 SDL_Rect rect;
373
374 vp = &is->pictq[is->pictq_rindex];
375 if (vp->bmp) {
376 /* XXX: use variable in the frame */
72ea344b
FB
377 if (is->video_st->codec.sample_aspect_ratio.num == 0)
378 aspect_ratio = 0;
379 else
380 aspect_ratio = av_q2d(is->video_st->codec.sample_aspect_ratio)
381 * is->video_st->codec.width / is->video_st->codec.height;;
01310af2
FB
382 if (aspect_ratio <= 0.0)
383 aspect_ratio = (float)is->video_st->codec.width /
384 (float)is->video_st->codec.height;
385 /* if an active format is indicated, then it overrides the
386 mpeg format */
387#if 0
388 if (is->video_st->codec.dtg_active_format != is->dtg_active_format) {
389 is->dtg_active_format = is->video_st->codec.dtg_active_format;
390 printf("dtg_active_format=%d\n", is->dtg_active_format);
391 }
392#endif
393#if 0
394 switch(is->video_st->codec.dtg_active_format) {
395 case FF_DTG_AFD_SAME:
396 default:
397 /* nothing to do */
398 break;
399 case FF_DTG_AFD_4_3:
400 aspect_ratio = 4.0 / 3.0;
401 break;
402 case FF_DTG_AFD_16_9:
403 aspect_ratio = 16.0 / 9.0;
404 break;
405 case FF_DTG_AFD_14_9:
406 aspect_ratio = 14.0 / 9.0;
407 break;
408 case FF_DTG_AFD_4_3_SP_14_9:
409 aspect_ratio = 14.0 / 9.0;
410 break;
411 case FF_DTG_AFD_16_9_SP_14_9:
412 aspect_ratio = 14.0 / 9.0;
413 break;
414 case FF_DTG_AFD_SP_4_3:
415 aspect_ratio = 4.0 / 3.0;
416 break;
417 }
418#endif
419
420 /* XXX: we suppose the screen has a 1.0 pixel ratio */
421 height = is->height;
422 width = ((int)rint(height * aspect_ratio)) & -3;
423 if (width > is->width) {
424 width = is->width;
425 height = ((int)rint(width / aspect_ratio)) & -3;
426 }
427 x = (is->width - width) / 2;
428 y = (is->height - height) / 2;
429 if (!is->no_background) {
430 /* fill the background */
431 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
432 } else {
433 is->no_background = 0;
434 }
435 rect.x = is->xleft + x;
436 rect.y = is->xleft + y;
437 rect.w = width;
438 rect.h = height;
439 SDL_DisplayYUVOverlay(vp->bmp, &rect);
440 } else {
441#if 0
442 fill_rectangle(screen,
443 is->xleft, is->ytop, is->width, is->height,
444 QERGB(0x00, 0x00, 0x00));
445#endif
446 }
447}
448
449static inline int compute_mod(int a, int b)
450{
451 a = a % b;
452 if (a >= 0)
453 return a;
454 else
455 return a + b;
456}
457
458static void video_audio_display(VideoState *s)
459{
460 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
461 int ch, channels, h, h2, bgcolor, fgcolor;
462 int16_t time_diff;
463
464 /* compute display index : center on currently output samples */
465 channels = s->audio_st->codec.channels;
466 nb_display_channels = channels;
5e0257e3
FB
467 if (!s->paused) {
468 n = 2 * channels;
469 delay = audio_write_get_buf_size(s);
470 delay /= n;
471
472 /* to be more precise, we take into account the time spent since
473 the last buffer computation */
474 if (audio_callback_time) {
475 time_diff = av_gettime() - audio_callback_time;
476 delay += (time_diff * s->audio_st->codec.sample_rate) / 1000000;
477 }
478
479 delay -= s->width / 2;
480 if (delay < s->width)
481 delay = s->width;
482 i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
483 s->last_i_start = i_start;
484 } else {
485 i_start = s->last_i_start;
01310af2
FB
486 }
487
01310af2
FB
488 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
489 fill_rectangle(screen,
490 s->xleft, s->ytop, s->width, s->height,
491 bgcolor);
492
493 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
494
495 /* total height for one channel */
496 h = s->height / nb_display_channels;
497 /* graph height / 2 */
498 h2 = (h * 9) / 20;
499 for(ch = 0;ch < nb_display_channels; ch++) {
500 i = i_start + ch;
501 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
502 for(x = 0; x < s->width; x++) {
503 y = (s->sample_array[i] * h2) >> 15;
504 if (y < 0) {
505 y = -y;
506 ys = y1 - y;
507 } else {
508 ys = y1;
509 }
510 fill_rectangle(screen,
511 s->xleft + x, ys, 1, y,
512 fgcolor);
513 i += channels;
514 if (i >= SAMPLE_ARRAY_SIZE)
515 i -= SAMPLE_ARRAY_SIZE;
516 }
517 }
518
519 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
520
521 for(ch = 1;ch < nb_display_channels; ch++) {
522 y = s->ytop + ch * h;
523 fill_rectangle(screen,
524 s->xleft, y, s->width, 1,
525 fgcolor);
526 }
527 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
528}
529
530/* display the current picture, if any */
531static void video_display(VideoState *is)
532{
533 if (is->audio_st && is->show_audio)
534 video_audio_display(is);
535 else if (is->video_st)
536 video_image_display(is);
537}
538
539static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
540{
541 SDL_Event event;
542 event.type = FF_REFRESH_EVENT;
543 event.user.data1 = opaque;
544 SDL_PushEvent(&event);
545 return 0; /* 0 means stop timer */
546}
547
548/* schedule a video refresh in 'delay' ms */
549static void schedule_refresh(VideoState *is, int delay)
550{
551 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
552}
553
638c9d91
FB
554/* get the current audio clock value */
555static double get_audio_clock(VideoState *is)
556{
557 double pts;
558 int hw_buf_size, bytes_per_sec;
559 pts = is->audio_clock;
560 hw_buf_size = audio_write_get_buf_size(is);
561 bytes_per_sec = 0;
562 if (is->audio_st) {
563 bytes_per_sec = is->audio_st->codec.sample_rate *
564 2 * is->audio_st->codec.channels;
565 }
566 if (bytes_per_sec)
567 pts -= (double)hw_buf_size / bytes_per_sec;
568 return pts;
569}
570
571/* get the current video clock value */
572static double get_video_clock(VideoState *is)
573{
574 double delta;
04108619 575 if (is->paused) {
72ea344b
FB
576 delta = 0;
577 } else {
578 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
579 }
638c9d91
FB
580 return is->video_current_pts + delta;
581}
582
583/* get the current external clock value */
584static double get_external_clock(VideoState *is)
585{
586 int64_t ti;
587 ti = av_gettime();
588 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
589}
590
591/* get the current master clock value */
592static double get_master_clock(VideoState *is)
593{
594 double val;
595
72ea344b
FB
596 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
597 if (is->video_st)
598 val = get_video_clock(is);
599 else
600 val = get_audio_clock(is);
601 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
602 if (is->audio_st)
603 val = get_audio_clock(is);
604 else
605 val = get_video_clock(is);
606 } else {
638c9d91 607 val = get_external_clock(is);
72ea344b 608 }
638c9d91
FB
609 return val;
610}
611
72ea344b 612/* seek in the stream */
3ba1438d 613static void stream_seek(VideoState *is, int64_t pos, int rel)
72ea344b
FB
614{
615 is->seek_pos = pos;
616 is->seek_req = 1;
3ba1438d 617 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
72ea344b
FB
618}
619
620/* pause or resume the video */
621static void stream_pause(VideoState *is)
622{
623 is->paused = !is->paused;
624 if (is->paused) {
625 is->video_current_pts = get_video_clock(is);
626 }
627}
628
01310af2
FB
629/* called to display each frame */
630static void video_refresh_timer(void *opaque)
631{
632 VideoState *is = opaque;
633 VideoPicture *vp;
638c9d91
FB
634 double actual_delay, delay, sync_threshold, ref_clock, diff;
635
01310af2
FB
636
637 if (is->video_st) {
638 if (is->pictq_size == 0) {
639 /* if no picture, need to wait */
7e0140cb 640 schedule_refresh(is, 1);
01310af2 641 } else {
638c9d91 642 /* dequeue the picture */
01310af2 643 vp = &is->pictq[is->pictq_rindex];
638c9d91
FB
644
645 /* update current video pts */
646 is->video_current_pts = vp->pts;
647 is->video_current_pts_time = av_gettime();
648
649 /* compute nominal delay */
650 delay = vp->pts - is->frame_last_pts;
651 if (delay <= 0 || delay >= 1.0) {
652 /* if incorrect delay, use previous one */
653 delay = is->frame_last_delay;
654 }
655 is->frame_last_delay = delay;
656 is->frame_last_pts = vp->pts;
657
658 /* update delay to follow master synchronisation source */
659 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
660 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
661 /* if video is slave, we try to correct big delays by
662 duplicating or deleting a frame */
663 ref_clock = get_master_clock(is);
664 diff = vp->pts - ref_clock;
665
666 /* skip or repeat frame. We take into account the
667 delay to compute the threshold. I still don't know
668 if it is the best guess */
669 sync_threshold = AV_SYNC_THRESHOLD;
670 if (delay > sync_threshold)
671 sync_threshold = delay;
672 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
673 if (diff <= -sync_threshold)
674 delay = 0;
675 else if (diff >= sync_threshold)
676 delay = 2 * delay;
677 }
678 }
679
680 is->frame_timer += delay;
681 /* compute the REAL delay (we need to do that to avoid
682 long term errors */
683 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
684 if (actual_delay < 0.010) {
685 /* XXX: should skip picture */
686 actual_delay = 0.010;
687 }
01310af2 688 /* launch timer for next picture */
638c9d91
FB
689 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
690
691#if defined(DEBUG_SYNC)
692 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
693 delay, actual_delay, vp->pts, -diff);
694#endif
01310af2
FB
695
696 /* display picture */
697 video_display(is);
698
699 /* update queue size and signal for next picture */
700 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
701 is->pictq_rindex = 0;
702
703 SDL_LockMutex(is->pictq_mutex);
704 is->pictq_size--;
705 SDL_CondSignal(is->pictq_cond);
706 SDL_UnlockMutex(is->pictq_mutex);
707 }
708 } else if (is->audio_st) {
709 /* draw the next audio frame */
710
711 schedule_refresh(is, 40);
712
713 /* if only audio stream, then display the audio bars (better
714 than nothing, just to test the implementation */
715
716 /* display picture */
717 video_display(is);
718 } else {
719 schedule_refresh(is, 100);
720 }
721 if (show_status) {
722 static int64_t last_time;
723 int64_t cur_time;
724 int aqsize, vqsize;
638c9d91 725 double av_diff;
01310af2
FB
726
727 cur_time = av_gettime();
728 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
729 aqsize = 0;
730 vqsize = 0;
731 if (is->audio_st)
732 aqsize = is->audioq.size;
733 if (is->video_st)
734 vqsize = is->videoq.size;
638c9d91
FB
735 av_diff = 0;
736 if (is->audio_st && is->video_st)
737 av_diff = get_audio_clock(is) - get_video_clock(is);
738 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB \r",
739 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024);
01310af2
FB
740 fflush(stdout);
741 last_time = cur_time;
742 }
743 }
744}
745
746/* allocate a picture (needs to do that in main thread to avoid
747 potential locking problems */
748static void alloc_picture(void *opaque)
749{
750 VideoState *is = opaque;
751 VideoPicture *vp;
01310af2
FB
752
753 vp = &is->pictq[is->pictq_windex];
754
755 if (vp->bmp)
756 SDL_FreeYUVOverlay(vp->bmp);
757
61890b02 758#if 0
01310af2 759 /* XXX: use generic function */
61890b02 760 /* XXX: disable overlay if no hardware acceleration or if RGB format */
01310af2
FB
761 switch(is->video_st->codec.pix_fmt) {
762 case PIX_FMT_YUV420P:
763 case PIX_FMT_YUV422P:
764 case PIX_FMT_YUV444P:
765 case PIX_FMT_YUV422:
766 case PIX_FMT_YUV410P:
767 case PIX_FMT_YUV411P:
768 is_yuv = 1;
769 break;
770 default:
771 is_yuv = 0;
772 break;
773 }
01310af2 774#endif
61890b02
FB
775 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec.width,
776 is->video_st->codec.height,
777 SDL_YV12_OVERLAY,
778 screen);
01310af2
FB
779 vp->width = is->video_st->codec.width;
780 vp->height = is->video_st->codec.height;
781
782 SDL_LockMutex(is->pictq_mutex);
783 vp->allocated = 1;
784 SDL_CondSignal(is->pictq_cond);
785 SDL_UnlockMutex(is->pictq_mutex);
786}
787
638c9d91 788static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01310af2
FB
789{
790 VideoPicture *vp;
791 int dst_pix_fmt;
792 AVPicture pict;
01310af2
FB
793
794 /* wait until we have space to put a new picture */
795 SDL_LockMutex(is->pictq_mutex);
796 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
797 !is->videoq.abort_request) {
798 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
799 }
800 SDL_UnlockMutex(is->pictq_mutex);
801
802 if (is->videoq.abort_request)
803 return -1;
804
805 vp = &is->pictq[is->pictq_windex];
806
807 /* alloc or resize hardware picture buffer */
808 if (!vp->bmp ||
809 vp->width != is->video_st->codec.width ||
810 vp->height != is->video_st->codec.height) {
811 SDL_Event event;
812
813 vp->allocated = 0;
814
815 /* the allocation must be done in the main thread to avoid
816 locking problems */
817 event.type = FF_ALLOC_EVENT;
818 event.user.data1 = is;
819 SDL_PushEvent(&event);
820
821 /* wait until the picture is allocated */
822 SDL_LockMutex(is->pictq_mutex);
823 while (!vp->allocated && !is->videoq.abort_request) {
824 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
825 }
826 SDL_UnlockMutex(is->pictq_mutex);
827
828 if (is->videoq.abort_request)
829 return -1;
830 }
831
638c9d91 832 /* if the frame is not skipped, then display it */
01310af2
FB
833 if (vp->bmp) {
834 /* get a pointer on the bitmap */
835 SDL_LockYUVOverlay (vp->bmp);
836
837 dst_pix_fmt = PIX_FMT_YUV420P;
838 pict.data[0] = vp->bmp->pixels[0];
839 pict.data[1] = vp->bmp->pixels[2];
840 pict.data[2] = vp->bmp->pixels[1];
841
842 pict.linesize[0] = vp->bmp->pitches[0];
843 pict.linesize[1] = vp->bmp->pitches[2];
844 pict.linesize[2] = vp->bmp->pitches[1];
01310af2 845 img_convert(&pict, dst_pix_fmt,
638c9d91 846 (AVPicture *)src_frame, is->video_st->codec.pix_fmt,
01310af2
FB
847 is->video_st->codec.width, is->video_st->codec.height);
848 /* update the bitmap content */
849 SDL_UnlockYUVOverlay(vp->bmp);
850
638c9d91 851 vp->pts = pts;
01310af2
FB
852
853 /* now we can update the picture count */
854 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
855 is->pictq_windex = 0;
856 SDL_LockMutex(is->pictq_mutex);
857 is->pictq_size++;
858 SDL_UnlockMutex(is->pictq_mutex);
859 }
638c9d91
FB
860 return 0;
861}
862
863/* compute the exact PTS for the picture if it is omitted in the stream */
864static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
865{
866 double frame_delay, pts;
867
868 pts = pts1;
869
01310af2 870 if (pts != 0) {
638c9d91 871 /* update video clock with pts, if present */
01310af2
FB
872 is->video_clock = pts;
873 } else {
72ea344b
FB
874 pts = is->video_clock;
875 }
876 /* update video clock for next frame */
c0df9d75 877 frame_delay = av_q2d(is->video_st->codec.time_base);
72ea344b
FB
878 /* for MPEG2, the frame can be repeated, so we update the
879 clock accordingly */
880 if (src_frame->repeat_pict) {
881 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
01310af2 882 }
72ea344b 883 is->video_clock += frame_delay;
638c9d91
FB
884
885#if defined(DEBUG_SYNC) && 0
886 {
887 int ftype;
888 if (src_frame->pict_type == FF_B_TYPE)
889 ftype = 'B';
890 else if (src_frame->pict_type == FF_I_TYPE)
891 ftype = 'I';
892 else
893 ftype = 'P';
894 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
72ea344b 895 ftype, pts, pts1);
638c9d91
FB
896 }
897#endif
72ea344b 898 return queue_picture(is, src_frame, pts);
01310af2
FB
899}
900
901static int video_thread(void *arg)
902{
903 VideoState *is = arg;
904 AVPacket pkt1, *pkt = &pkt1;
72ea344b 905 int len1, got_picture;
c6b1edc9 906 AVFrame *frame= avcodec_alloc_frame();
01310af2
FB
907 double pts;
908
909 for(;;) {
910 while (is->paused && !is->videoq.abort_request) {
911 SDL_Delay(10);
912 }
913 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
914 break;
638c9d91
FB
915 /* NOTE: ipts is the PTS of the _first_ picture beginning in
916 this packet, if any */
72ea344b 917 pts = 0;
61c1d8e2 918 if (pkt->dts != AV_NOPTS_VALUE)
c0df9d75 919 pts = av_q2d(is->video_st->time_base)*pkt->dts;
72ea344b 920
b514ed3c 921 SDL_LockMutex(is->video_decoder_mutex);
72ea344b
FB
922 len1 = avcodec_decode_video(&is->video_st->codec,
923 frame, &got_picture,
924 pkt->data, pkt->size);
b514ed3c 925 SDL_UnlockMutex(is->video_decoder_mutex);
fb966f99
MN
926// if (len1 < 0)
927// break;
72ea344b
FB
928 if (got_picture) {
929 if (output_picture2(is, frame, pts) < 0)
930 goto the_end;
01310af2 931 }
01310af2 932 av_free_packet(pkt);
bba04f1e
WH
933 if (step)
934 if (cur_stream)
935 stream_pause(cur_stream);
01310af2
FB
936 }
937 the_end:
c6b1edc9 938 av_free(frame);
01310af2
FB
939 return 0;
940}
941
942/* copy samples for viewing in editor window */
943static void update_sample_display(VideoState *is, short *samples, int samples_size)
944{
945 int size, len, channels;
946
947 channels = is->audio_st->codec.channels;
948
949 size = samples_size / sizeof(short);
950 while (size > 0) {
951 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
952 if (len > size)
953 len = size;
954 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
955 samples += len;
956 is->sample_array_index += len;
957 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
958 is->sample_array_index = 0;
959 size -= len;
960 }
961}
962
01310af2
FB
963/* return the new audio buffer size (samples can be added or deleted
964 to get better sync if video or external master clock) */
965static int synchronize_audio(VideoState *is, short *samples,
638c9d91 966 int samples_size1, double pts)
01310af2 967{
638c9d91 968 int n, samples_size;
01310af2
FB
969 double ref_clock;
970
971 n = 2 * is->audio_st->codec.channels;
638c9d91 972 samples_size = samples_size1;
01310af2 973
01310af2 974 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 975 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
976 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
977 double diff, avg_diff;
01310af2 978 int wanted_size, min_size, max_size, nb_samples;
638c9d91
FB
979
980 ref_clock = get_master_clock(is);
981 diff = get_audio_clock(is) - ref_clock;
01310af2 982
638c9d91
FB
983 if (diff < AV_NOSYNC_THRESHOLD) {
984 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
985 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
986 /* not enough measures to have a correct estimate */
987 is->audio_diff_avg_count++;
988 } else {
989 /* estimate the A-V difference */
990 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
991
992 if (fabs(avg_diff) >= is->audio_diff_threshold) {
993 wanted_size = samples_size + ((int)(diff * is->audio_st->codec.sample_rate) * n);
994 nb_samples = samples_size / n;
995
996 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
997 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
998 if (wanted_size < min_size)
999 wanted_size = min_size;
1000 else if (wanted_size > max_size)
1001 wanted_size = max_size;
1002
1003 /* add or remove samples to correction the synchro */
1004 if (wanted_size < samples_size) {
1005 /* remove samples */
1006 samples_size = wanted_size;
1007 } else if (wanted_size > samples_size) {
1008 uint8_t *samples_end, *q;
1009 int nb;
1010
1011 /* add samples */
1012 nb = (samples_size - wanted_size);
1013 samples_end = (uint8_t *)samples + samples_size - n;
1014 q = samples_end + n;
1015 while (nb > 0) {
1016 memcpy(q, samples_end, n);
1017 q += n;
1018 nb -= n;
1019 }
1020 samples_size = wanted_size;
1021 }
1022 }
1023#if 0
1024 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1025 diff, avg_diff, samples_size - samples_size1,
1026 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1027#endif
01310af2 1028 }
638c9d91
FB
1029 } else {
1030 /* too big difference : may be initial PTS errors, so
1031 reset A-V filter */
1032 is->audio_diff_avg_count = 0;
1033 is->audio_diff_cum = 0;
01310af2
FB
1034 }
1035 }
1036
01310af2
FB
1037 return samples_size;
1038}
1039
1040/* decode one audio frame and returns its uncompressed size */
1041static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1042{
1043 AVPacket *pkt = &is->audio_pkt;
72ea344b 1044 int n, len1, data_size;
01310af2
FB
1045 double pts;
1046
1047 for(;;) {
72ea344b 1048 /* NOTE: the audio packet can contain several frames */
01310af2 1049 while (is->audio_pkt_size > 0) {
b514ed3c 1050 SDL_LockMutex(is->audio_decoder_mutex);
01310af2
FB
1051 len1 = avcodec_decode_audio(&is->audio_st->codec,
1052 (int16_t *)audio_buf, &data_size,
1053 is->audio_pkt_data, is->audio_pkt_size);
b514ed3c 1054 SDL_UnlockMutex(is->audio_decoder_mutex);
72ea344b
FB
1055 if (len1 < 0) {
1056 /* if error, we skip the frame */
1057 is->audio_pkt_size = 0;
01310af2 1058 break;
72ea344b
FB
1059 }
1060
01310af2
FB
1061 is->audio_pkt_data += len1;
1062 is->audio_pkt_size -= len1;
72ea344b
FB
1063 if (data_size <= 0)
1064 continue;
1065 /* if no pts, then compute it */
1066 pts = is->audio_clock;
1067 *pts_ptr = pts;
1068 n = 2 * is->audio_st->codec.channels;
1069 is->audio_clock += (double)data_size /
1070 (double)(n * is->audio_st->codec.sample_rate);
638c9d91 1071#if defined(DEBUG_SYNC)
72ea344b
FB
1072 {
1073 static double last_clock;
1074 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1075 is->audio_clock - last_clock,
1076 is->audio_clock, pts);
1077 last_clock = is->audio_clock;
01310af2 1078 }
72ea344b
FB
1079#endif
1080 return data_size;
01310af2
FB
1081 }
1082
72ea344b
FB
1083 /* free the current packet */
1084 if (pkt->data)
01310af2 1085 av_free_packet(pkt);
72ea344b
FB
1086
1087 if (is->paused || is->audioq.abort_request) {
1088 return -1;
1089 }
1090
01310af2
FB
1091 /* read next packet */
1092 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1093 return -1;
1094 is->audio_pkt_data = pkt->data;
1095 is->audio_pkt_size = pkt->size;
72ea344b
FB
1096
1097 /* if update the audio clock with the pts */
1098 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1099 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1100 }
01310af2
FB
1101 }
1102}
1103
638c9d91
FB
1104/* get the current audio output buffer size, in samples. With SDL, we
1105 cannot have a precise information */
1106static int audio_write_get_buf_size(VideoState *is)
01310af2 1107{
638c9d91 1108 return is->audio_hw_buf_size - is->audio_buf_index;
01310af2
FB
1109}
1110
1111
1112/* prepare a new audio buffer */
1113void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1114{
1115 VideoState *is = opaque;
1116 int audio_size, len1;
1117 double pts;
1118
1119 audio_callback_time = av_gettime();
1120
1121 while (len > 0) {
1122 if (is->audio_buf_index >= is->audio_buf_size) {
1123 audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1124 if (audio_size < 0) {
1125 /* if error, just output silence */
1126 is->audio_buf_size = 1024;
1127 memset(is->audio_buf, 0, is->audio_buf_size);
1128 } else {
1129 if (is->show_audio)
1130 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1131 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1132 pts);
1133 is->audio_buf_size = audio_size;
1134 }
1135 is->audio_buf_index = 0;
1136 }
1137 len1 = is->audio_buf_size - is->audio_buf_index;
1138 if (len1 > len)
1139 len1 = len;
1140 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1141 len -= len1;
1142 stream += len1;
1143 is->audio_buf_index += len1;
1144 }
1145}
1146
1147
1148/* open a given stream. Return 0 if OK */
1149static int stream_component_open(VideoState *is, int stream_index)
1150{
1151 AVFormatContext *ic = is->ic;
1152 AVCodecContext *enc;
1153 AVCodec *codec;
1154 SDL_AudioSpec wanted_spec, spec;
1155
1156 if (stream_index < 0 || stream_index >= ic->nb_streams)
1157 return -1;
1158 enc = &ic->streams[stream_index]->codec;
1159
01310af2
FB
1160 /* prepare audio output */
1161 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1162 wanted_spec.freq = enc->sample_rate;
1163 wanted_spec.format = AUDIO_S16SYS;
638c9d91
FB
1164 /* hack for AC3. XXX: suppress that */
1165 if (enc->channels > 2)
1166 enc->channels = 2;
01310af2
FB
1167 wanted_spec.channels = enc->channels;
1168 wanted_spec.silence = 0;
638c9d91 1169 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
01310af2
FB
1170 wanted_spec.callback = sdl_audio_callback;
1171 wanted_spec.userdata = is;
638c9d91
FB
1172 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1173 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
01310af2 1174 return -1;
638c9d91 1175 }
01310af2
FB
1176 is->audio_hw_buf_size = spec.size;
1177 }
1178
1179 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1180 enc->debug_mv = debug_mv;
1181 enc->debug = debug;
1ab1f099
MN
1182 if(debug)
1183 av_log_set_level(AV_LOG_DEBUG);
6387c3e6 1184 enc->workaround_bugs = workaround_bugs;
178fcca8 1185 enc->lowres = lowres;
61846e9a 1186 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1187 enc->idct_algo= idct;
6fc5b059 1188 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
01310af2
FB
1189 if (!codec ||
1190 avcodec_open(enc, codec) < 0)
1191 return -1;
2450cff2 1192#if defined(HAVE_THREADS)
c62c07d3
MN
1193 if(thread_count>1)
1194 avcodec_thread_init(enc, thread_count);
1195#endif
1196 enc->thread_count= thread_count;
638c9d91 1197 switch(enc->codec_type) {
01310af2
FB
1198 case CODEC_TYPE_AUDIO:
1199 is->audio_stream = stream_index;
1200 is->audio_st = ic->streams[stream_index];
1201 is->audio_buf_size = 0;
1202 is->audio_buf_index = 0;
638c9d91
FB
1203
1204 /* init averaging filter */
1205 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1206 is->audio_diff_avg_count = 0;
1207 /* since we do not have a precise anough audio fifo fullness,
1208 we correct audio sync only if larger than this threshold */
1209 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1210
01310af2
FB
1211 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1212 packet_queue_init(&is->audioq);
1213 SDL_PauseAudio(0);
1214 break;
1215 case CODEC_TYPE_VIDEO:
1216 is->video_stream = stream_index;
1217 is->video_st = ic->streams[stream_index];
1218
638c9d91
FB
1219 is->frame_last_delay = 40e-3;
1220 is->frame_timer = (double)av_gettime() / 1000000.0;
638c9d91
FB
1221 is->video_current_pts_time = av_gettime();
1222
01310af2
FB
1223 packet_queue_init(&is->videoq);
1224 is->video_tid = SDL_CreateThread(video_thread, is);
1225 break;
1226 default:
1227 break;
1228 }
1229 return 0;
1230}
1231
1232static void stream_component_close(VideoState *is, int stream_index)
1233{
1234 AVFormatContext *ic = is->ic;
1235 AVCodecContext *enc;
1236
1237 enc = &ic->streams[stream_index]->codec;
1238
1239 switch(enc->codec_type) {
1240 case CODEC_TYPE_AUDIO:
1241 packet_queue_abort(&is->audioq);
1242
1243 SDL_CloseAudio();
1244
1245 packet_queue_end(&is->audioq);
1246 break;
1247 case CODEC_TYPE_VIDEO:
1248 packet_queue_abort(&is->videoq);
1249
1250 /* note: we also signal this mutex to make sure we deblock the
1251 video thread in all cases */
1252 SDL_LockMutex(is->pictq_mutex);
1253 SDL_CondSignal(is->pictq_cond);
1254 SDL_UnlockMutex(is->pictq_mutex);
1255
1256 SDL_WaitThread(is->video_tid, NULL);
1257
1258 packet_queue_end(&is->videoq);
1259 break;
1260 default:
1261 break;
1262 }
1263
1264 avcodec_close(enc);
1265 switch(enc->codec_type) {
1266 case CODEC_TYPE_AUDIO:
1267 is->audio_st = NULL;
1268 is->audio_stream = -1;
1269 break;
1270 case CODEC_TYPE_VIDEO:
1271 is->video_st = NULL;
1272 is->video_stream = -1;
1273 break;
1274 default:
1275 break;
1276 }
1277}
1278
d0526ecf
FB
1279void dump_stream_info(AVFormatContext *s)
1280{
1281 if (s->track != 0)
1282 fprintf(stderr, "Track: %d\n", s->track);
1283 if (s->title[0] != '\0')
1284 fprintf(stderr, "Title: %s\n", s->title);
1285 if (s->author[0] != '\0')
1286 fprintf(stderr, "Author: %s\n", s->author);
1287 if (s->album[0] != '\0')
1288 fprintf(stderr, "Album: %s\n", s->album);
1289 if (s->year != 0)
1290 fprintf(stderr, "Year: %d\n", s->year);
1291 if (s->genre[0] != '\0')
1292 fprintf(stderr, "Genre: %s\n", s->genre);
1293}
1294
416e3508
FB
1295/* since we have only one decoding thread, we can use a global
1296 variable instead of a thread local variable */
1297static VideoState *global_video_state;
1298
1299static int decode_interrupt_cb(void)
1300{
1301 return (global_video_state && global_video_state->abort_request);
1302}
01310af2
FB
1303
1304/* this thread gets the stream from the disk or the network */
1305static int decode_thread(void *arg)
1306{
1307 VideoState *is = arg;
1308 AVFormatContext *ic;
72ea344b 1309 int err, i, ret, video_index, audio_index, use_play;
01310af2 1310 AVPacket pkt1, *pkt = &pkt1;
61890b02 1311 AVFormatParameters params, *ap = &params;
01310af2
FB
1312
1313 video_index = -1;
1314 audio_index = -1;
1315 is->video_stream = -1;
1316 is->audio_stream = -1;
1317
416e3508
FB
1318 global_video_state = is;
1319 url_set_interrupt_cb(decode_interrupt_cb);
1320
61890b02
FB
1321 memset(ap, 0, sizeof(*ap));
1322 ap->image_format = image_format;
72ea344b
FB
1323 ap->initial_pause = 1; /* we force a pause when starting an RTSP
1324 stream */
1325
61890b02 1326 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1327 if (err < 0) {
1328 print_error(is->filename, err);
1329 ret = -1;
1330 goto fail;
1331 }
01310af2 1332 is->ic = ic;
72ea344b
FB
1333#ifdef CONFIG_NETWORK
1334 use_play = (ic->iformat == &rtsp_demux);
1335#else
1336 use_play = 0;
1337#endif
1338 if (!use_play) {
1339 err = av_find_stream_info(ic);
1340 if (err < 0) {
1341 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1342 ret = -1;
1343 goto fail;
1344 }
2536c5fd 1345 ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
638c9d91 1346 }
72ea344b
FB
1347
1348 /* if seeking requested, we execute it */
1349 if (start_time != AV_NOPTS_VALUE) {
1350 int64_t timestamp;
1351
1352 timestamp = start_time;
1353 /* add the stream start time */
1354 if (ic->start_time != AV_NOPTS_VALUE)
1355 timestamp += ic->start_time;
3ba1438d 1356 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
72ea344b
FB
1357 if (ret < 0) {
1358 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1359 is->filename, (double)timestamp / AV_TIME_BASE);
1360 }
1361 }
1362
1363 /* now we can begin to play (RTSP stream only) */
1364 av_read_play(ic);
1365
1366 if (use_play) {
1367 err = av_find_stream_info(ic);
1368 if (err < 0) {
1369 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1370 ret = -1;
1371 goto fail;
1372 }
1373 }
1374
01310af2
FB
1375 for(i = 0; i < ic->nb_streams; i++) {
1376 AVCodecContext *enc = &ic->streams[i]->codec;
1377 switch(enc->codec_type) {
1378 case CODEC_TYPE_AUDIO:
1379 if (audio_index < 0 && !audio_disable)
1380 audio_index = i;
1381 break;
1382 case CODEC_TYPE_VIDEO:
1383 if (video_index < 0 && !video_disable)
1384 video_index = i;
1385 break;
1386 default:
1387 break;
1388 }
1389 }
1390 if (show_status) {
1391 dump_format(ic, 0, is->filename, 0);
d0526ecf 1392 dump_stream_info(ic);
01310af2
FB
1393 }
1394
1395 /* open the streams */
1396 if (audio_index >= 0) {
1397 stream_component_open(is, audio_index);
1398 }
1399
1400 if (video_index >= 0) {
1401 stream_component_open(is, video_index);
1402 } else {
1403 if (!display_disable)
1404 is->show_audio = 1;
1405 }
1406
1407 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1408 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1409 ret = -1;
01310af2
FB
1410 goto fail;
1411 }
1412
1413 for(;;) {
1414 if (is->abort_request)
1415 break;
400738b1 1416#ifdef CONFIG_NETWORK
416e3508
FB
1417 if (is->paused != is->last_paused) {
1418 is->last_paused = is->paused;
72ea344b
FB
1419 if (is->paused)
1420 av_read_pause(ic);
1421 else
1422 av_read_play(ic);
416e3508
FB
1423 }
1424 if (is->paused && ic->iformat == &rtsp_demux) {
1425 /* wait 10 ms to avoid trying to get another packet */
1426 /* XXX: horrible */
1427 SDL_Delay(10);
1428 continue;
1429 }
400738b1 1430#endif
72ea344b
FB
1431 if (is->seek_req) {
1432 /* XXX: must lock decoder threads */
3ba1438d 1433 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
72ea344b
FB
1434 if (ret < 0) {
1435 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
1436 }else{
1437 if (is->audio_stream >= 0) {
1438 packet_queue_flush(&is->audioq);
1439 }
1440 if (is->video_stream >= 0) {
1441 packet_queue_flush(&is->videoq);
b514ed3c 1442 SDL_LockMutex(is->video_decoder_mutex);
93e1a0a9 1443 avcodec_flush_buffers(&ic->streams[video_index]->codec);
b514ed3c 1444 SDL_UnlockMutex(is->video_decoder_mutex);
e6c0297f 1445 }
72ea344b
FB
1446 }
1447 is->seek_req = 0;
1448 }
416e3508 1449
01310af2
FB
1450 /* if the queue are full, no need to read more */
1451 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
0c904df2
MN
1452 is->videoq.size > MAX_VIDEOQ_SIZE ||
1453 url_feof(&ic->pb)) {
01310af2
FB
1454 /* wait 10 ms */
1455 SDL_Delay(10);
1456 continue;
1457 }
72ea344b 1458 ret = av_read_frame(ic, pkt);
01310af2 1459 if (ret < 0) {
6e1f8725
RS
1460 if (url_feof(&ic->pb) && url_ferror(&ic->pb) == 0) {
1461 SDL_Delay(100); /* wait for user event */
1462 continue;
1463 } else
1464 break;
01310af2
FB
1465 }
1466 if (pkt->stream_index == is->audio_stream) {
1467 packet_queue_put(&is->audioq, pkt);
1468 } else if (pkt->stream_index == is->video_stream) {
1469 packet_queue_put(&is->videoq, pkt);
1470 } else {
1471 av_free_packet(pkt);
1472 }
1473 }
1474 /* wait until the end */
1475 while (!is->abort_request) {
1476 SDL_Delay(100);
1477 }
1478
638c9d91 1479 ret = 0;
01310af2 1480 fail:
416e3508
FB
1481 /* disable interrupting */
1482 global_video_state = NULL;
1483
01310af2
FB
1484 /* close each stream */
1485 if (is->audio_stream >= 0)
1486 stream_component_close(is, is->audio_stream);
1487 if (is->video_stream >= 0)
1488 stream_component_close(is, is->video_stream);
638c9d91
FB
1489 if (is->ic) {
1490 av_close_input_file(is->ic);
1491 is->ic = NULL; /* safety */
1492 }
416e3508
FB
1493 url_set_interrupt_cb(NULL);
1494
638c9d91
FB
1495 if (ret != 0) {
1496 SDL_Event event;
1497
1498 event.type = FF_QUIT_EVENT;
1499 event.user.data1 = is;
1500 SDL_PushEvent(&event);
1501 }
01310af2
FB
1502 return 0;
1503}
1504
638c9d91 1505static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
1506{
1507 VideoState *is;
1508
1509 is = av_mallocz(sizeof(VideoState));
1510 if (!is)
1511 return NULL;
1512 pstrcpy(is->filename, sizeof(is->filename), filename);
638c9d91 1513 is->iformat = iformat;
01310af2
FB
1514 if (screen) {
1515 is->width = screen->w;
1516 is->height = screen->h;
1517 }
1518 is->ytop = 0;
1519 is->xleft = 0;
1520
1521 /* start video display */
1522 is->pictq_mutex = SDL_CreateMutex();
1523 is->pictq_cond = SDL_CreateCond();
b514ed3c
MN
1524
1525 is->audio_decoder_mutex = SDL_CreateMutex();
1526 is->video_decoder_mutex = SDL_CreateMutex();
01310af2
FB
1527
1528 /* add the refresh timer to draw the picture */
1529 schedule_refresh(is, 40);
1530
638c9d91 1531 is->av_sync_type = av_sync_type;
01310af2
FB
1532 is->parse_tid = SDL_CreateThread(decode_thread, is);
1533 if (!is->parse_tid) {
1534 av_free(is);
1535 return NULL;
1536 }
1537 return is;
1538}
1539
1540static void stream_close(VideoState *is)
1541{
1542 VideoPicture *vp;
1543 int i;
1544 /* XXX: use a special url_shutdown call to abort parse cleanly */
1545 is->abort_request = 1;
1546 SDL_WaitThread(is->parse_tid, NULL);
1547
1548 /* free all pictures */
1549 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
1550 vp = &is->pictq[i];
1551 if (vp->bmp) {
1552 SDL_FreeYUVOverlay(vp->bmp);
1553 vp->bmp = NULL;
1554 }
1555 }
1556 SDL_DestroyMutex(is->pictq_mutex);
1557 SDL_DestroyCond(is->pictq_cond);
b514ed3c
MN
1558 SDL_DestroyMutex(is->audio_decoder_mutex);
1559 SDL_DestroyMutex(is->video_decoder_mutex);
01310af2
FB
1560}
1561
638c9d91
FB
1562void stream_cycle_channel(VideoState *is, int codec_type)
1563{
1564 AVFormatContext *ic = is->ic;
1565 int start_index, stream_index;
1566 AVStream *st;
1567
1568 if (codec_type == CODEC_TYPE_VIDEO)
1569 start_index = is->video_stream;
1570 else
1571 start_index = is->audio_stream;
1572 if (start_index < 0)
1573 return;
1574 stream_index = start_index;
1575 for(;;) {
1576 if (++stream_index >= is->ic->nb_streams)
1577 stream_index = 0;
1578 if (stream_index == start_index)
1579 return;
1580 st = ic->streams[stream_index];
1581 if (st->codec.codec_type == codec_type) {
1582 /* check that parameters are OK */
1583 switch(codec_type) {
1584 case CODEC_TYPE_AUDIO:
1585 if (st->codec.sample_rate != 0 &&
1586 st->codec.channels != 0)
1587 goto the_end;
1588 break;
1589 case CODEC_TYPE_VIDEO:
1590 goto the_end;
1591 default:
1592 break;
1593 }
1594 }
1595 }
1596 the_end:
1597 stream_component_close(is, start_index);
1598 stream_component_open(is, stream_index);
1599}
1600
1601
01310af2
FB
1602void toggle_full_screen(void)
1603{
1604 int w, h, flags;
1605 is_full_screen = !is_full_screen;
1606 if (!fs_screen_width) {
1607 /* use default SDL method */
1608 SDL_WM_ToggleFullScreen(screen);
1609 } else {
1610 /* use the recorded resolution */
1611 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1612 if (is_full_screen) {
1613 w = fs_screen_width;
1614 h = fs_screen_height;
1615 flags |= SDL_FULLSCREEN;
1616 } else {
1617 w = screen_width;
1618 h = screen_height;
1619 flags |= SDL_RESIZABLE;
1620 }
1621 screen = SDL_SetVideoMode(w, h, 0, flags);
1622 cur_stream->width = w;
1623 cur_stream->height = h;
1624 }
1625}
1626
1627void toggle_pause(void)
1628{
1629 if (cur_stream)
1630 stream_pause(cur_stream);
bba04f1e
WH
1631 step = 0;
1632}
1633
1634void step_to_next_frame(void)
1635{
1636 if (cur_stream) {
1637 if (cur_stream->paused)
1638 cur_stream->paused=0;
1639 cur_stream->video_current_pts = get_video_clock(cur_stream);
1640 }
1641 step = 1;
01310af2
FB
1642}
1643
1644void do_exit(void)
1645{
1646 if (cur_stream) {
1647 stream_close(cur_stream);
1648 cur_stream = NULL;
1649 }
1650 if (show_status)
1651 printf("\n");
1652 SDL_Quit();
1653 exit(0);
1654}
1655
1656void toggle_audio_display(void)
1657{
1658 if (cur_stream) {
1659 cur_stream->show_audio = !cur_stream->show_audio;
1660 }
1661}
1662
1663/* handle an event sent by the GUI */
1664void event_loop(void)
1665{
1666 SDL_Event event;
a11d11aa 1667 double incr, pos, frac;
01310af2
FB
1668
1669 for(;;) {
1670 SDL_WaitEvent(&event);
1671 switch(event.type) {
1672 case SDL_KEYDOWN:
1673 switch(event.key.keysym.sym) {
1674 case SDLK_ESCAPE:
1675 case SDLK_q:
1676 do_exit();
1677 break;
1678 case SDLK_f:
1679 toggle_full_screen();
1680 break;
1681 case SDLK_p:
1682 case SDLK_SPACE:
1683 toggle_pause();
1684 break;
bba04f1e
WH
1685 case SDLK_s: //S: Step to next frame
1686 step_to_next_frame();
1687 break;
01310af2 1688 case SDLK_a:
638c9d91
FB
1689 if (cur_stream)
1690 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
1691 break;
1692 case SDLK_v:
1693 if (cur_stream)
1694 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
1695 break;
1696 case SDLK_w:
01310af2
FB
1697 toggle_audio_display();
1698 break;
72ea344b
FB
1699 case SDLK_LEFT:
1700 incr = -10.0;
1701 goto do_seek;
1702 case SDLK_RIGHT:
1703 incr = 10.0;
1704 goto do_seek;
1705 case SDLK_UP:
1706 incr = 60.0;
1707 goto do_seek;
1708 case SDLK_DOWN:
1709 incr = -60.0;
1710 do_seek:
1711 if (cur_stream) {
1712 pos = get_master_clock(cur_stream);
1713 pos += incr;
3ba1438d 1714 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
72ea344b
FB
1715 }
1716 break;
01310af2
FB
1717 default:
1718 break;
1719 }
1720 break;
a11d11aa
MB
1721 case SDL_MOUSEBUTTONDOWN:
1722 if (cur_stream) {
1723 int ns, hh, mm, ss;
1724 int tns, thh, tmm, tss;
1725 tns = cur_stream->ic->duration/1000000LL;
1726 thh = tns/3600;
1727 tmm = (tns%3600)/60;
1728 tss = (tns%60);
1729 frac = (double)event.button.x/(double)cur_stream->width;
1730 ns = frac*tns;
1731 hh = ns/3600;
1732 mm = (ns%3600)/60;
1733 ss = (ns%60);
1734 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
1735 hh, mm, ss, thh, tmm, tss);
3ba1438d 1736 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
a11d11aa
MB
1737 }
1738 break;
01310af2
FB
1739 case SDL_VIDEORESIZE:
1740 if (cur_stream) {
1741 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
1742 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
1743 cur_stream->width = event.resize.w;
1744 cur_stream->height = event.resize.h;
1745 }
1746 break;
1747 case SDL_QUIT:
638c9d91 1748 case FF_QUIT_EVENT:
01310af2
FB
1749 do_exit();
1750 break;
1751 case FF_ALLOC_EVENT:
1752 alloc_picture(event.user.data1);
1753 break;
1754 case FF_REFRESH_EVENT:
1755 video_refresh_timer(event.user.data1);
1756 break;
1757 default:
1758 break;
1759 }
1760 }
1761}
1762
1763void opt_width(const char *arg)
1764{
1765 screen_width = atoi(arg);
1766}
1767
1768void opt_height(const char *arg)
1769{
1770 screen_height = atoi(arg);
1771}
1772
1773static void opt_format(const char *arg)
1774{
1775 file_iformat = av_find_input_format(arg);
1776 if (!file_iformat) {
1777 fprintf(stderr, "Unknown input format: %s\n", arg);
1778 exit(1);
1779 }
1780}
61890b02
FB
1781
1782static void opt_image_format(const char *arg)
1783{
1784 AVImageFormat *f;
1785
1786 for(f = first_image_format; f != NULL; f = f->next) {
1787 if (!strcmp(arg, f->name))
1788 break;
1789 }
1790 if (!f) {
1791 fprintf(stderr, "Unknown image format: '%s'\n", arg);
1792 exit(1);
1793 }
1794 image_format = f;
1795}
1796
400738b1 1797#ifdef CONFIG_NETWORK
416e3508
FB
1798void opt_rtp_tcp(void)
1799{
1800 /* only tcp protocol */
1801 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
1802}
400738b1 1803#endif
416e3508 1804
638c9d91
FB
1805void opt_sync(const char *arg)
1806{
1807 if (!strcmp(arg, "audio"))
1808 av_sync_type = AV_SYNC_AUDIO_MASTER;
1809 else if (!strcmp(arg, "video"))
1810 av_sync_type = AV_SYNC_VIDEO_MASTER;
1811 else if (!strcmp(arg, "ext"))
1812 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
1813 else
1814 show_help();
1815}
1816
72ea344b
FB
1817void opt_seek(const char *arg)
1818{
1819 start_time = parse_date(arg, 1);
1820}
1821
e26a8335
WH
1822static void opt_debug(const char *arg)
1823{
1824 debug = atoi(arg);
1825}
1826
0c9bbaec
WH
1827static void opt_vismv(const char *arg)
1828{
1829 debug_mv = atoi(arg);
1830}
c62c07d3
MN
1831
1832static void opt_thread_count(const char *arg)
1833{
1834 thread_count= atoi(arg);
2450cff2 1835#if !defined(HAVE_THREADS)
c62c07d3
MN
1836 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
1837#endif
1838}
0c9bbaec 1839
01310af2 1840const OptionDef options[] = {
e26a8335 1841 { "h", 0, {(void*)show_help}, "show help" },
01310af2
FB
1842 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
1843 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
638c9d91
FB
1844#if 0
1845 /* disabled as SDL/X11 does not support it correctly on application launch */
1846 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
1847#endif
01310af2
FB
1848 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
1849 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
72ea344b 1850 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
01310af2
FB
1851 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
1852 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
61890b02 1853 { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
01310af2 1854 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
e26a8335 1855 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 1856 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
0c9bbaec 1857 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 1858 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
178fcca8
MN
1859 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
1860 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
400738b1 1861#ifdef CONFIG_NETWORK
416e3508 1862 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
400738b1 1863#endif
c62c07d3
MN
1864 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
1865 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
01310af2
FB
1866 { NULL, },
1867};
1868
1869void show_help(void)
1870{
02d504a7
FB
1871 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
1872 "usage: ffplay [options] input_file\n"
01310af2
FB
1873 "Simple media player\n");
1874 printf("\n");
02d504a7
FB
1875 show_help_options(options, "Main options:\n",
1876 OPT_EXPERT, 0);
1877 show_help_options(options, "\nAdvanced options:\n",
1878 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
1879 printf("\nWhile playing:\n"
1880 "q, ESC quit\n"
1881 "f toggle full screen\n"
1882 "p, SPC pause\n"
638c9d91
FB
1883 "a cycle audio channel\n"
1884 "v cycle video channel\n"
1885 "w show audio waves\n"
72ea344b
FB
1886 "left/right seek backward/forward 10 seconds\n"
1887 "down/up seek backward/forward 1 minute\n"
a11d11aa 1888 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2
FB
1889 );
1890 exit(1);
1891}
1892
1893void parse_arg_file(const char *filename)
1894{
e8d83e1c
MN
1895 if (!strcmp(filename, "-"))
1896 filename = "pipe:";
01310af2
FB
1897 input_filename = filename;
1898}
1899
1900/* Called from the main */
1901int main(int argc, char **argv)
1902{
638c9d91 1903 int flags, w, h;
01310af2
FB
1904
1905 /* register all codecs, demux and protocols */
1906 av_register_all();
1907
3ca4b654
MN
1908 #ifdef CONFIG_OS2
1909 MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
1910
1911 // Make stdout and stderr unbuffered
1912 setbuf( stdout, NULL );
1913 setbuf( stderr, NULL );
1914 #endif
1915
01310af2
FB
1916 parse_options(argc, argv, options);
1917
1918 if (!input_filename)
1919 show_help();
1920
1921 if (display_disable) {
1922 video_disable = 1;
1923 }
31319a8c
FB
1924 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
1925#ifndef CONFIG_WIN32
1926 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 */
1927#endif
01310af2 1928 if (SDL_Init (flags)) {
05ab0b76 1929 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
1930 exit(1);
1931 }
1932
1933 if (!display_disable) {
01310af2
FB
1934#ifdef HAVE_X11
1935 /* save the screen resolution... SDL should allow full screen
1936 by resizing the window */
1937 {
1938 Display *dpy;
1939 dpy = XOpenDisplay(NULL);
1940 if (dpy) {
1941 fs_screen_width = DisplayWidth(dpy, DefaultScreen(dpy));
1942 fs_screen_height = DisplayHeight(dpy, DefaultScreen(dpy));
1943 XCloseDisplay(dpy);
1944 }
1945 }
1946#endif
638c9d91
FB
1947 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1948 if (is_full_screen && fs_screen_width) {
1949 w = fs_screen_width;
1950 h = fs_screen_height;
1951 flags |= SDL_FULLSCREEN;
1952 } else {
1953 w = screen_width;
1954 h = screen_height;
1955 flags |= SDL_RESIZABLE;
1956 }
1957 screen = SDL_SetVideoMode(w, h, 0, flags);
1958 if (!screen) {
1959 fprintf(stderr, "SDL: could not set video mode - exiting\n");
1960 exit(1);
1961 }
1962 SDL_WM_SetCaption("FFplay", "FFplay");
01310af2
FB
1963 }
1964
1965 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
1966 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
1967 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
1968 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
1969
638c9d91 1970 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
1971
1972 event_loop();
1973
1974 /* never returns */
1975
1976 return 0;
1977}