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