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