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