init AVFrame with defaults
[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
01310af2
FB
31#if defined(__linux__)
32#define HAVE_X11
33#endif
34
35#ifdef HAVE_X11
36#include <X11/Xlib.h>
37#endif
38
638c9d91
FB
39//#define DEBUG_SYNC
40
01310af2
FB
41#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
42#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
43
638c9d91
FB
44/* SDL audio buffer size, in samples. Should be small to have precise
45 A/V sync as SDL does not have hardware buffer fullness info. */
46#define SDL_AUDIO_BUFFER_SIZE 1024
47
48/* no AV sync correction is done if below the AV sync threshold */
49#define AV_SYNC_THRESHOLD 0.08
50/* no AV correction is done if too big error */
51#define AV_NOSYNC_THRESHOLD 10.0
52
53/* maximum audio speed change to get correct sync */
54#define SAMPLE_CORRECTION_PERCENT_MAX 10
55
56/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
57#define AUDIO_DIFF_AVG_NB 20
58
01310af2
FB
59/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
60#define SAMPLE_ARRAY_SIZE (2*65536)
61
62typedef struct PacketQueue {
63 AVPacketList *first_pkt, *last_pkt;
64 int nb_packets;
65 int size;
66 int abort_request;
67 SDL_mutex *mutex;
68 SDL_cond *cond;
69} PacketQueue;
70
71#define VIDEO_PICTURE_QUEUE_SIZE 1
72
73typedef struct VideoPicture {
638c9d91 74 double pts; /* presentation time stamp for this picture */
01310af2
FB
75 SDL_Overlay *bmp;
76 int width, height; /* source height & width */
77 int allocated;
78} VideoPicture;
79
80enum {
81 AV_SYNC_AUDIO_MASTER, /* default choice */
82 AV_SYNC_VIDEO_MASTER,
638c9d91 83 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
01310af2
FB
84};
85
86typedef struct VideoState {
87 SDL_Thread *parse_tid;
88 SDL_Thread *video_tid;
638c9d91 89 AVInputFormat *iformat;
01310af2
FB
90 int no_background;
91 int abort_request;
92 int paused;
416e3508 93 int last_paused;
01310af2
FB
94 AVFormatContext *ic;
95 int dtg_active_format;
96
97 int audio_stream;
98
99 int av_sync_type;
638c9d91
FB
100 double external_clock; /* external clock base */
101 int64_t external_clock_time;
102
103 double audio_clock;
104 double audio_diff_cum; /* used for AV difference average computation */
105 double audio_diff_avg_coef;
106 double audio_diff_threshold;
107 int audio_diff_avg_count;
01310af2
FB
108 AVStream *audio_st;
109 PacketQueue audioq;
110 int audio_hw_buf_size;
111 /* samples output by the codec. we reserve more space for avsync
112 compensation */
113 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
114 int audio_buf_size; /* in bytes */
115 int audio_buf_index; /* in bytes */
116 AVPacket audio_pkt;
117 uint8_t *audio_pkt_data;
118 int audio_pkt_size;
119 int64_t audio_pkt_ipts;
120
121 int show_audio; /* if true, display audio samples */
122 int16_t sample_array[SAMPLE_ARRAY_SIZE];
123 int sample_array_index;
5e0257e3 124 int last_i_start;
01310af2 125
638c9d91
FB
126 double frame_timer;
127 double frame_last_pts;
128 double frame_last_delay;
129 double video_clock;
01310af2
FB
130 int video_stream;
131 AVStream *video_st;
132 PacketQueue videoq;
638c9d91
FB
133 int64_t ipts;
134 int picture_start; /* true if picture starts */
135 double video_last_P_pts; /* pts of the last P picture (needed if B
136 frames are present) */
137 double video_current_pts; /* current displayed pts (different from
138 video_clock if frame fifos are used) */
139 int64_t video_current_pts_time; /* time at which we updated
140 video_current_pts - used to
141 have running video pts */
01310af2
FB
142 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
143 int pictq_size, pictq_rindex, pictq_windex;
144 SDL_mutex *pictq_mutex;
145 SDL_cond *pictq_cond;
146
147 // QETimer *video_timer;
148 char filename[1024];
149 int width, height, xleft, ytop;
150} VideoState;
151
152void show_help(void);
638c9d91 153static int audio_write_get_buf_size(VideoState *is);
01310af2
FB
154
155/* options specified by the user */
156static AVInputFormat *file_iformat;
61890b02 157static AVImageFormat *image_format;
01310af2
FB
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;
01310af2
FB
676
677 vp = &is->pictq[is->pictq_windex];
678
679 if (vp->bmp)
680 SDL_FreeYUVOverlay(vp->bmp);
681
61890b02 682#if 0
01310af2 683 /* XXX: use generic function */
61890b02 684 /* XXX: disable overlay if no hardware acceleration or if RGB format */
01310af2
FB
685 switch(is->video_st->codec.pix_fmt) {
686 case PIX_FMT_YUV420P:
687 case PIX_FMT_YUV422P:
688 case PIX_FMT_YUV444P:
689 case PIX_FMT_YUV422:
690 case PIX_FMT_YUV410P:
691 case PIX_FMT_YUV411P:
692 is_yuv = 1;
693 break;
694 default:
695 is_yuv = 0;
696 break;
697 }
01310af2 698#endif
61890b02
FB
699 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec.width,
700 is->video_st->codec.height,
701 SDL_YV12_OVERLAY,
702 screen);
01310af2
FB
703 vp->width = is->video_st->codec.width;
704 vp->height = is->video_st->codec.height;
705
706 SDL_LockMutex(is->pictq_mutex);
707 vp->allocated = 1;
708 SDL_CondSignal(is->pictq_cond);
709 SDL_UnlockMutex(is->pictq_mutex);
710}
711
638c9d91 712static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01310af2
FB
713{
714 VideoPicture *vp;
715 int dst_pix_fmt;
716 AVPicture pict;
01310af2
FB
717
718 /* wait until we have space to put a new picture */
719 SDL_LockMutex(is->pictq_mutex);
720 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
721 !is->videoq.abort_request) {
722 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
723 }
724 SDL_UnlockMutex(is->pictq_mutex);
725
726 if (is->videoq.abort_request)
727 return -1;
728
729 vp = &is->pictq[is->pictq_windex];
730
731 /* alloc or resize hardware picture buffer */
732 if (!vp->bmp ||
733 vp->width != is->video_st->codec.width ||
734 vp->height != is->video_st->codec.height) {
735 SDL_Event event;
736
737 vp->allocated = 0;
738
739 /* the allocation must be done in the main thread to avoid
740 locking problems */
741 event.type = FF_ALLOC_EVENT;
742 event.user.data1 = is;
743 SDL_PushEvent(&event);
744
745 /* wait until the picture is allocated */
746 SDL_LockMutex(is->pictq_mutex);
747 while (!vp->allocated && !is->videoq.abort_request) {
748 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
749 }
750 SDL_UnlockMutex(is->pictq_mutex);
751
752 if (is->videoq.abort_request)
753 return -1;
754 }
755
638c9d91 756 /* if the frame is not skipped, then display it */
01310af2
FB
757 if (vp->bmp) {
758 /* get a pointer on the bitmap */
759 SDL_LockYUVOverlay (vp->bmp);
760
761 dst_pix_fmt = PIX_FMT_YUV420P;
762 pict.data[0] = vp->bmp->pixels[0];
763 pict.data[1] = vp->bmp->pixels[2];
764 pict.data[2] = vp->bmp->pixels[1];
765
766 pict.linesize[0] = vp->bmp->pitches[0];
767 pict.linesize[1] = vp->bmp->pitches[2];
768 pict.linesize[2] = vp->bmp->pitches[1];
769
770 img_convert(&pict, dst_pix_fmt,
638c9d91 771 (AVPicture *)src_frame, is->video_st->codec.pix_fmt,
01310af2
FB
772 is->video_st->codec.width, is->video_st->codec.height);
773 /* update the bitmap content */
774 SDL_UnlockYUVOverlay(vp->bmp);
775
638c9d91 776 vp->pts = pts;
01310af2
FB
777
778 /* now we can update the picture count */
779 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
780 is->pictq_windex = 0;
781 SDL_LockMutex(is->pictq_mutex);
782 is->pictq_size++;
783 SDL_UnlockMutex(is->pictq_mutex);
784 }
638c9d91
FB
785 return 0;
786}
787
788/* compute the exact PTS for the picture if it is omitted in the stream */
789static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
790{
791 double frame_delay, pts;
792
793 pts = pts1;
794
795 /* if B frames are present, and if the current picture is a I
796 or P frame, we use the last pts */
797 if (is->video_st->codec.has_b_frames &&
798 src_frame->pict_type != FF_B_TYPE) {
799 /* use last pts */
800 pts = is->video_last_P_pts;
801 /* get the pts for the next I or P frame if present */
802 is->video_last_P_pts = pts1;
803 }
01310af2 804
01310af2 805 if (pts != 0) {
638c9d91 806 /* update video clock with pts, if present */
01310af2
FB
807 is->video_clock = pts;
808 } else {
638c9d91 809 frame_delay = (double)is->video_st->codec.frame_rate_base /
01310af2 810 (double)is->video_st->codec.frame_rate;
638c9d91
FB
811 is->video_clock += frame_delay;
812 /* for MPEG2, the frame can be repeated, so we update the
813 clock accordingly */
814 if (src_frame->repeat_pict) {
815 is->video_clock += src_frame->repeat_pict * (frame_delay * 0.5);
816 }
01310af2 817 }
638c9d91
FB
818
819#if defined(DEBUG_SYNC) && 0
820 {
821 int ftype;
822 if (src_frame->pict_type == FF_B_TYPE)
823 ftype = 'B';
824 else if (src_frame->pict_type == FF_I_TYPE)
825 ftype = 'I';
826 else
827 ftype = 'P';
828 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
829 ftype, is->video_clock, pts1);
830 }
831#endif
832 return queue_picture(is, src_frame, is->video_clock);
01310af2
FB
833}
834
835static int video_thread(void *arg)
836{
837 VideoState *is = arg;
838 AVPacket pkt1, *pkt = &pkt1;
839 unsigned char *ptr;
638c9d91 840 int len, len1, got_picture;
c6b1edc9 841 AVFrame *frame= avcodec_alloc_frame();
01310af2
FB
842 int64_t ipts;
843 double pts;
844
845 for(;;) {
846 while (is->paused && !is->videoq.abort_request) {
847 SDL_Delay(10);
848 }
849 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
850 break;
638c9d91
FB
851 /* NOTE: ipts is the PTS of the _first_ picture beginning in
852 this packet, if any */
01310af2
FB
853 ipts = pkt->pts;
854 ptr = pkt->data;
855 if (is->video_st->codec.codec_id == CODEC_ID_RAWVIDEO) {
c6b1edc9 856 avpicture_fill((AVPicture *)frame, ptr,
01310af2
FB
857 is->video_st->codec.pix_fmt,
858 is->video_st->codec.width,
859 is->video_st->codec.height);
860 pts = 0;
861 if (ipts != AV_NOPTS_VALUE)
862 pts = (double)ipts * is->ic->pts_num / is->ic->pts_den;
c6b1edc9
MN
863 frame->pict_type = FF_I_TYPE;
864 if (output_picture2(is, frame, pts) < 0)
01310af2
FB
865 goto the_end;
866 } else {
867 len = pkt->size;
868 while (len > 0) {
638c9d91
FB
869 if (is->picture_start) {
870 is->ipts = ipts;
871 is->picture_start = 0;
872 ipts = AV_NOPTS_VALUE;
873 }
01310af2 874 len1 = avcodec_decode_video(&is->video_st->codec,
c6b1edc9 875 frame, &got_picture, ptr, len);
01310af2
FB
876 if (len1 < 0)
877 break;
878 if (got_picture) {
01310af2 879 pts = 0;
638c9d91
FB
880 if (is->ipts != AV_NOPTS_VALUE)
881 pts = (double)is->ipts * is->ic->pts_num / is->ic->pts_den;
c6b1edc9 882 if (output_picture2(is, frame, pts) < 0)
01310af2 883 goto the_end;
638c9d91 884 is->picture_start = 1;
01310af2
FB
885 }
886 ptr += len1;
887 len -= len1;
888 }
889 }
890 av_free_packet(pkt);
891 }
892 the_end:
c6b1edc9 893 av_free(frame);
01310af2
FB
894 return 0;
895}
896
897/* copy samples for viewing in editor window */
898static void update_sample_display(VideoState *is, short *samples, int samples_size)
899{
900 int size, len, channels;
901
902 channels = is->audio_st->codec.channels;
903
904 size = samples_size / sizeof(short);
905 while (size > 0) {
906 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
907 if (len > size)
908 len = size;
909 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
910 samples += len;
911 is->sample_array_index += len;
912 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
913 is->sample_array_index = 0;
914 size -= len;
915 }
916}
917
01310af2
FB
918/* return the new audio buffer size (samples can be added or deleted
919 to get better sync if video or external master clock) */
920static int synchronize_audio(VideoState *is, short *samples,
638c9d91 921 int samples_size1, double pts)
01310af2 922{
638c9d91 923 int n, samples_size;
01310af2
FB
924 double ref_clock;
925
926 n = 2 * is->audio_st->codec.channels;
638c9d91 927 samples_size = samples_size1;
01310af2 928
01310af2 929 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 930 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
931 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
932 double diff, avg_diff;
01310af2 933 int wanted_size, min_size, max_size, nb_samples;
638c9d91
FB
934
935 ref_clock = get_master_clock(is);
936 diff = get_audio_clock(is) - ref_clock;
01310af2 937
638c9d91
FB
938 if (diff < AV_NOSYNC_THRESHOLD) {
939 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
940 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
941 /* not enough measures to have a correct estimate */
942 is->audio_diff_avg_count++;
943 } else {
944 /* estimate the A-V difference */
945 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
946
947 if (fabs(avg_diff) >= is->audio_diff_threshold) {
948 wanted_size = samples_size + ((int)(diff * is->audio_st->codec.sample_rate) * n);
949 nb_samples = samples_size / n;
950
951 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
952 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
953 if (wanted_size < min_size)
954 wanted_size = min_size;
955 else if (wanted_size > max_size)
956 wanted_size = max_size;
957
958 /* add or remove samples to correction the synchro */
959 if (wanted_size < samples_size) {
960 /* remove samples */
961 samples_size = wanted_size;
962 } else if (wanted_size > samples_size) {
963 uint8_t *samples_end, *q;
964 int nb;
965
966 /* add samples */
967 nb = (samples_size - wanted_size);
968 samples_end = (uint8_t *)samples + samples_size - n;
969 q = samples_end + n;
970 while (nb > 0) {
971 memcpy(q, samples_end, n);
972 q += n;
973 nb -= n;
974 }
975 samples_size = wanted_size;
976 }
977 }
978#if 0
979 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
980 diff, avg_diff, samples_size - samples_size1,
981 is->audio_clock, is->video_clock, is->audio_diff_threshold);
982#endif
01310af2 983 }
638c9d91
FB
984 } else {
985 /* too big difference : may be initial PTS errors, so
986 reset A-V filter */
987 is->audio_diff_avg_count = 0;
988 is->audio_diff_cum = 0;
01310af2
FB
989 }
990 }
991
01310af2
FB
992 return samples_size;
993}
994
995/* decode one audio frame and returns its uncompressed size */
996static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
997{
998 AVPacket *pkt = &is->audio_pkt;
999 int len1, data_size;
1000 double pts;
1001
1002 for(;;) {
1003 if (is->paused || is->audioq.abort_request) {
1004 return -1;
1005 }
1006 while (is->audio_pkt_size > 0) {
1007 len1 = avcodec_decode_audio(&is->audio_st->codec,
1008 (int16_t *)audio_buf, &data_size,
1009 is->audio_pkt_data, is->audio_pkt_size);
1010 if (len1 < 0)
1011 break;
1012 is->audio_pkt_data += len1;
1013 is->audio_pkt_size -= len1;
1014 if (data_size > 0) {
1015 pts = 0;
1016 if (is->audio_pkt_ipts != AV_NOPTS_VALUE)
1017 pts = (double)is->audio_pkt_ipts * is->ic->pts_num / is->ic->pts_den;
638c9d91
FB
1018 /* if no pts, then compute it */
1019 if (pts != 0) {
1020 is->audio_clock = pts;
1021 } else {
1022 int n;
1023 n = 2 * is->audio_st->codec.channels;
1024 is->audio_clock += (double)data_size / (double)(n * is->audio_st->codec.sample_rate);
1025 }
1026#if defined(DEBUG_SYNC)
1027 {
1028 static double last_clock;
1029 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1030 is->audio_clock - last_clock,
1031 is->audio_clock, pts);
1032 last_clock = is->audio_clock;
1033 }
1034#endif
1035 *pts_ptr = is->audio_clock;
01310af2
FB
1036 is->audio_pkt_ipts = AV_NOPTS_VALUE;
1037 /* we got samples : we can exit now */
1038 return data_size;
1039 }
1040 }
1041
1042 /* free previous packet if any */
1043 if (pkt->destruct)
1044 av_free_packet(pkt);
1045
1046 /* read next packet */
1047 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1048 return -1;
1049 is->audio_pkt_data = pkt->data;
1050 is->audio_pkt_size = pkt->size;
1051 is->audio_pkt_ipts = pkt->pts;
1052 }
1053}
1054
638c9d91
FB
1055/* get the current audio output buffer size, in samples. With SDL, we
1056 cannot have a precise information */
1057static int audio_write_get_buf_size(VideoState *is)
01310af2 1058{
638c9d91 1059 return is->audio_hw_buf_size - is->audio_buf_index;
01310af2
FB
1060}
1061
1062
1063/* prepare a new audio buffer */
1064void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1065{
1066 VideoState *is = opaque;
1067 int audio_size, len1;
1068 double pts;
1069
1070 audio_callback_time = av_gettime();
1071
1072 while (len > 0) {
1073 if (is->audio_buf_index >= is->audio_buf_size) {
1074 audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1075 if (audio_size < 0) {
1076 /* if error, just output silence */
1077 is->audio_buf_size = 1024;
1078 memset(is->audio_buf, 0, is->audio_buf_size);
1079 } else {
1080 if (is->show_audio)
1081 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1082 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1083 pts);
1084 is->audio_buf_size = audio_size;
1085 }
1086 is->audio_buf_index = 0;
1087 }
1088 len1 = is->audio_buf_size - is->audio_buf_index;
1089 if (len1 > len)
1090 len1 = len;
1091 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1092 len -= len1;
1093 stream += len1;
1094 is->audio_buf_index += len1;
1095 }
1096}
1097
1098
1099/* open a given stream. Return 0 if OK */
1100static int stream_component_open(VideoState *is, int stream_index)
1101{
1102 AVFormatContext *ic = is->ic;
1103 AVCodecContext *enc;
1104 AVCodec *codec;
1105 SDL_AudioSpec wanted_spec, spec;
1106
1107 if (stream_index < 0 || stream_index >= ic->nb_streams)
1108 return -1;
1109 enc = &ic->streams[stream_index]->codec;
1110
01310af2
FB
1111 /* prepare audio output */
1112 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1113 wanted_spec.freq = enc->sample_rate;
1114 wanted_spec.format = AUDIO_S16SYS;
638c9d91
FB
1115 /* hack for AC3. XXX: suppress that */
1116 if (enc->channels > 2)
1117 enc->channels = 2;
01310af2
FB
1118 wanted_spec.channels = enc->channels;
1119 wanted_spec.silence = 0;
638c9d91 1120 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
01310af2
FB
1121 wanted_spec.callback = sdl_audio_callback;
1122 wanted_spec.userdata = is;
638c9d91
FB
1123 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1124 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
01310af2 1125 return -1;
638c9d91 1126 }
01310af2
FB
1127 is->audio_hw_buf_size = spec.size;
1128 }
1129
1130 codec = avcodec_find_decoder(enc->codec_id);
1131 if (!codec ||
1132 avcodec_open(enc, codec) < 0)
1133 return -1;
638c9d91 1134 switch(enc->codec_type) {
01310af2
FB
1135 case CODEC_TYPE_AUDIO:
1136 is->audio_stream = stream_index;
1137 is->audio_st = ic->streams[stream_index];
1138 is->audio_buf_size = 0;
1139 is->audio_buf_index = 0;
1140 is->audio_pkt_size = 0;
638c9d91
FB
1141
1142 /* init averaging filter */
1143 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1144 is->audio_diff_avg_count = 0;
1145 /* since we do not have a precise anough audio fifo fullness,
1146 we correct audio sync only if larger than this threshold */
1147 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1148
01310af2
FB
1149 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1150 packet_queue_init(&is->audioq);
1151 SDL_PauseAudio(0);
1152 break;
1153 case CODEC_TYPE_VIDEO:
1154 is->video_stream = stream_index;
1155 is->video_st = ic->streams[stream_index];
1156
638c9d91
FB
1157 is->frame_last_delay = 40e-3;
1158 is->frame_timer = (double)av_gettime() / 1000000.0;
1159 is->picture_start = 1;
1160 is->video_current_pts_time = av_gettime();
1161
01310af2
FB
1162 packet_queue_init(&is->videoq);
1163 is->video_tid = SDL_CreateThread(video_thread, is);
1164 break;
1165 default:
1166 break;
1167 }
1168 return 0;
1169}
1170
1171static void stream_component_close(VideoState *is, int stream_index)
1172{
1173 AVFormatContext *ic = is->ic;
1174 AVCodecContext *enc;
1175
1176 enc = &ic->streams[stream_index]->codec;
1177
1178 switch(enc->codec_type) {
1179 case CODEC_TYPE_AUDIO:
1180 packet_queue_abort(&is->audioq);
1181
1182 SDL_CloseAudio();
1183
1184 packet_queue_end(&is->audioq);
1185 break;
1186 case CODEC_TYPE_VIDEO:
1187 packet_queue_abort(&is->videoq);
1188
1189 /* note: we also signal this mutex to make sure we deblock the
1190 video thread in all cases */
1191 SDL_LockMutex(is->pictq_mutex);
1192 SDL_CondSignal(is->pictq_cond);
1193 SDL_UnlockMutex(is->pictq_mutex);
1194
1195 SDL_WaitThread(is->video_tid, NULL);
1196
1197 packet_queue_end(&is->videoq);
1198 break;
1199 default:
1200 break;
1201 }
1202
1203 avcodec_close(enc);
1204 switch(enc->codec_type) {
1205 case CODEC_TYPE_AUDIO:
1206 is->audio_st = NULL;
1207 is->audio_stream = -1;
1208 break;
1209 case CODEC_TYPE_VIDEO:
1210 is->video_st = NULL;
1211 is->video_stream = -1;
1212 break;
1213 default:
1214 break;
1215 }
1216}
1217
d0526ecf
FB
1218void dump_stream_info(AVFormatContext *s)
1219{
1220 if (s->track != 0)
1221 fprintf(stderr, "Track: %d\n", s->track);
1222 if (s->title[0] != '\0')
1223 fprintf(stderr, "Title: %s\n", s->title);
1224 if (s->author[0] != '\0')
1225 fprintf(stderr, "Author: %s\n", s->author);
1226 if (s->album[0] != '\0')
1227 fprintf(stderr, "Album: %s\n", s->album);
1228 if (s->year != 0)
1229 fprintf(stderr, "Year: %d\n", s->year);
1230 if (s->genre[0] != '\0')
1231 fprintf(stderr, "Genre: %s\n", s->genre);
1232}
1233
416e3508
FB
1234/* since we have only one decoding thread, we can use a global
1235 variable instead of a thread local variable */
1236static VideoState *global_video_state;
1237
1238static int decode_interrupt_cb(void)
1239{
1240 return (global_video_state && global_video_state->abort_request);
1241}
01310af2
FB
1242
1243/* this thread gets the stream from the disk or the network */
1244static int decode_thread(void *arg)
1245{
1246 VideoState *is = arg;
1247 AVFormatContext *ic;
1248 int err, i, ret, video_index, audio_index;
1249 AVPacket pkt1, *pkt = &pkt1;
61890b02 1250 AVFormatParameters params, *ap = &params;
01310af2
FB
1251
1252 video_index = -1;
1253 audio_index = -1;
1254 is->video_stream = -1;
1255 is->audio_stream = -1;
1256
416e3508
FB
1257 global_video_state = is;
1258 url_set_interrupt_cb(decode_interrupt_cb);
1259
61890b02
FB
1260 memset(ap, 0, sizeof(*ap));
1261 ap->image_format = image_format;
1262
1263 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1264 if (err < 0) {
1265 print_error(is->filename, err);
1266 ret = -1;
1267 goto fail;
1268 }
01310af2
FB
1269 is->ic = ic;
1270 err = av_find_stream_info(ic);
638c9d91
FB
1271 if (err < 0) {
1272 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1273 ret = -1;
01310af2 1274 goto fail;
638c9d91
FB
1275 }
1276
01310af2
FB
1277 for(i = 0; i < ic->nb_streams; i++) {
1278 AVCodecContext *enc = &ic->streams[i]->codec;
1279 switch(enc->codec_type) {
1280 case CODEC_TYPE_AUDIO:
1281 if (audio_index < 0 && !audio_disable)
1282 audio_index = i;
1283 break;
1284 case CODEC_TYPE_VIDEO:
1285 if (video_index < 0 && !video_disable)
1286 video_index = i;
1287 break;
1288 default:
1289 break;
1290 }
1291 }
1292 if (show_status) {
1293 dump_format(ic, 0, is->filename, 0);
d0526ecf 1294 dump_stream_info(ic);
01310af2
FB
1295 }
1296
1297 /* open the streams */
1298 if (audio_index >= 0) {
1299 stream_component_open(is, audio_index);
1300 }
1301
1302 if (video_index >= 0) {
1303 stream_component_open(is, video_index);
1304 } else {
1305 if (!display_disable)
1306 is->show_audio = 1;
1307 }
1308
1309 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1310 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1311 ret = -1;
01310af2
FB
1312 goto fail;
1313 }
1314
1315 for(;;) {
1316 if (is->abort_request)
1317 break;
400738b1 1318#ifdef CONFIG_NETWORK
416e3508
FB
1319 if (is->paused != is->last_paused) {
1320 is->last_paused = is->paused;
1321 if (ic->iformat == &rtsp_demux) {
1322 if (is->paused)
1323 rtsp_pause(ic);
1324 else
1325 rtsp_resume(ic);
1326 }
1327 }
1328 if (is->paused && ic->iformat == &rtsp_demux) {
1329 /* wait 10 ms to avoid trying to get another packet */
1330 /* XXX: horrible */
1331 SDL_Delay(10);
1332 continue;
1333 }
400738b1 1334#endif
416e3508 1335
01310af2
FB
1336 /* if the queue are full, no need to read more */
1337 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1338 is->videoq.size > MAX_VIDEOQ_SIZE) {
1339 /* wait 10 ms */
1340 SDL_Delay(10);
1341 continue;
1342 }
1343 ret = av_read_packet(ic, pkt);
1344 if (ret < 0) {
1345 break;
1346 }
1347 if (pkt->stream_index == is->audio_stream) {
1348 packet_queue_put(&is->audioq, pkt);
1349 } else if (pkt->stream_index == is->video_stream) {
1350 packet_queue_put(&is->videoq, pkt);
1351 } else {
1352 av_free_packet(pkt);
1353 }
1354 }
1355 /* wait until the end */
1356 while (!is->abort_request) {
1357 SDL_Delay(100);
1358 }
1359
638c9d91 1360 ret = 0;
01310af2 1361 fail:
416e3508
FB
1362 /* disable interrupting */
1363 global_video_state = NULL;
1364
01310af2
FB
1365 /* close each stream */
1366 if (is->audio_stream >= 0)
1367 stream_component_close(is, is->audio_stream);
1368 if (is->video_stream >= 0)
1369 stream_component_close(is, is->video_stream);
638c9d91
FB
1370 if (is->ic) {
1371 av_close_input_file(is->ic);
1372 is->ic = NULL; /* safety */
1373 }
416e3508
FB
1374 url_set_interrupt_cb(NULL);
1375
638c9d91
FB
1376 if (ret != 0) {
1377 SDL_Event event;
1378
1379 event.type = FF_QUIT_EVENT;
1380 event.user.data1 = is;
1381 SDL_PushEvent(&event);
1382 }
01310af2
FB
1383 return 0;
1384}
1385
1386/* pause or resume the video */
1387static void stream_pause(VideoState *is)
1388{
1389 is->paused = !is->paused;
1390}
1391
638c9d91 1392static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
1393{
1394 VideoState *is;
1395
1396 is = av_mallocz(sizeof(VideoState));
1397 if (!is)
1398 return NULL;
1399 pstrcpy(is->filename, sizeof(is->filename), filename);
638c9d91 1400 is->iformat = iformat;
01310af2
FB
1401 if (screen) {
1402 is->width = screen->w;
1403 is->height = screen->h;
1404 }
1405 is->ytop = 0;
1406 is->xleft = 0;
1407
1408 /* start video display */
1409 is->pictq_mutex = SDL_CreateMutex();
1410 is->pictq_cond = SDL_CreateCond();
1411
1412 /* add the refresh timer to draw the picture */
1413 schedule_refresh(is, 40);
1414
638c9d91 1415 is->av_sync_type = av_sync_type;
01310af2
FB
1416 is->parse_tid = SDL_CreateThread(decode_thread, is);
1417 if (!is->parse_tid) {
1418 av_free(is);
1419 return NULL;
1420 }
1421 return is;
1422}
1423
1424static void stream_close(VideoState *is)
1425{
1426 VideoPicture *vp;
1427 int i;
1428 /* XXX: use a special url_shutdown call to abort parse cleanly */
1429 is->abort_request = 1;
1430 SDL_WaitThread(is->parse_tid, NULL);
1431
1432 /* free all pictures */
1433 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
1434 vp = &is->pictq[i];
1435 if (vp->bmp) {
1436 SDL_FreeYUVOverlay(vp->bmp);
1437 vp->bmp = NULL;
1438 }
1439 }
1440 SDL_DestroyMutex(is->pictq_mutex);
1441 SDL_DestroyCond(is->pictq_cond);
1442}
1443
638c9d91
FB
1444void stream_cycle_channel(VideoState *is, int codec_type)
1445{
1446 AVFormatContext *ic = is->ic;
1447 int start_index, stream_index;
1448 AVStream *st;
1449
1450 if (codec_type == CODEC_TYPE_VIDEO)
1451 start_index = is->video_stream;
1452 else
1453 start_index = is->audio_stream;
1454 if (start_index < 0)
1455 return;
1456 stream_index = start_index;
1457 for(;;) {
1458 if (++stream_index >= is->ic->nb_streams)
1459 stream_index = 0;
1460 if (stream_index == start_index)
1461 return;
1462 st = ic->streams[stream_index];
1463 if (st->codec.codec_type == codec_type) {
1464 /* check that parameters are OK */
1465 switch(codec_type) {
1466 case CODEC_TYPE_AUDIO:
1467 if (st->codec.sample_rate != 0 &&
1468 st->codec.channels != 0)
1469 goto the_end;
1470 break;
1471 case CODEC_TYPE_VIDEO:
1472 goto the_end;
1473 default:
1474 break;
1475 }
1476 }
1477 }
1478 the_end:
1479 stream_component_close(is, start_index);
1480 stream_component_open(is, stream_index);
1481}
1482
1483
01310af2
FB
1484void toggle_full_screen(void)
1485{
1486 int w, h, flags;
1487 is_full_screen = !is_full_screen;
1488 if (!fs_screen_width) {
1489 /* use default SDL method */
1490 SDL_WM_ToggleFullScreen(screen);
1491 } else {
1492 /* use the recorded resolution */
1493 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1494 if (is_full_screen) {
1495 w = fs_screen_width;
1496 h = fs_screen_height;
1497 flags |= SDL_FULLSCREEN;
1498 } else {
1499 w = screen_width;
1500 h = screen_height;
1501 flags |= SDL_RESIZABLE;
1502 }
1503 screen = SDL_SetVideoMode(w, h, 0, flags);
1504 cur_stream->width = w;
1505 cur_stream->height = h;
1506 }
1507}
1508
1509void toggle_pause(void)
1510{
1511 if (cur_stream)
1512 stream_pause(cur_stream);
1513}
1514
1515void do_exit(void)
1516{
1517 if (cur_stream) {
1518 stream_close(cur_stream);
1519 cur_stream = NULL;
1520 }
1521 if (show_status)
1522 printf("\n");
1523 SDL_Quit();
1524 exit(0);
1525}
1526
1527void toggle_audio_display(void)
1528{
1529 if (cur_stream) {
1530 cur_stream->show_audio = !cur_stream->show_audio;
1531 }
1532}
1533
1534/* handle an event sent by the GUI */
1535void event_loop(void)
1536{
1537 SDL_Event event;
1538
1539 for(;;) {
1540 SDL_WaitEvent(&event);
1541 switch(event.type) {
1542 case SDL_KEYDOWN:
1543 switch(event.key.keysym.sym) {
1544 case SDLK_ESCAPE:
1545 case SDLK_q:
1546 do_exit();
1547 break;
1548 case SDLK_f:
1549 toggle_full_screen();
1550 break;
1551 case SDLK_p:
1552 case SDLK_SPACE:
1553 toggle_pause();
1554 break;
1555 case SDLK_a:
638c9d91
FB
1556 if (cur_stream)
1557 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
1558 break;
1559 case SDLK_v:
1560 if (cur_stream)
1561 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
1562 break;
1563 case SDLK_w:
01310af2
FB
1564 toggle_audio_display();
1565 break;
1566 default:
1567 break;
1568 }
1569 break;
1570 case SDL_VIDEORESIZE:
1571 if (cur_stream) {
1572 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
1573 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
1574 cur_stream->width = event.resize.w;
1575 cur_stream->height = event.resize.h;
1576 }
1577 break;
1578 case SDL_QUIT:
638c9d91 1579 case FF_QUIT_EVENT:
01310af2
FB
1580 do_exit();
1581 break;
1582 case FF_ALLOC_EVENT:
1583 alloc_picture(event.user.data1);
1584 break;
1585 case FF_REFRESH_EVENT:
1586 video_refresh_timer(event.user.data1);
1587 break;
1588 default:
1589 break;
1590 }
1591 }
1592}
1593
1594void opt_width(const char *arg)
1595{
1596 screen_width = atoi(arg);
1597}
1598
1599void opt_height(const char *arg)
1600{
1601 screen_height = atoi(arg);
1602}
1603
1604static void opt_format(const char *arg)
1605{
1606 file_iformat = av_find_input_format(arg);
1607 if (!file_iformat) {
1608 fprintf(stderr, "Unknown input format: %s\n", arg);
1609 exit(1);
1610 }
1611}
61890b02
FB
1612
1613static void opt_image_format(const char *arg)
1614{
1615 AVImageFormat *f;
1616
1617 for(f = first_image_format; f != NULL; f = f->next) {
1618 if (!strcmp(arg, f->name))
1619 break;
1620 }
1621 if (!f) {
1622 fprintf(stderr, "Unknown image format: '%s'\n", arg);
1623 exit(1);
1624 }
1625 image_format = f;
1626}
1627
400738b1 1628#ifdef CONFIG_NETWORK
416e3508
FB
1629void opt_rtp_tcp(void)
1630{
1631 /* only tcp protocol */
1632 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
1633}
400738b1 1634#endif
416e3508 1635
638c9d91
FB
1636void opt_sync(const char *arg)
1637{
1638 if (!strcmp(arg, "audio"))
1639 av_sync_type = AV_SYNC_AUDIO_MASTER;
1640 else if (!strcmp(arg, "video"))
1641 av_sync_type = AV_SYNC_VIDEO_MASTER;
1642 else if (!strcmp(arg, "ext"))
1643 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
1644 else
1645 show_help();
1646}
1647
01310af2
FB
1648const OptionDef options[] = {
1649 { "h", 0, {(void*)show_help}, "show help" },
1650 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
1651 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
638c9d91
FB
1652#if 0
1653 /* disabled as SDL/X11 does not support it correctly on application launch */
1654 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
1655#endif
01310af2
FB
1656 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
1657 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
1658 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
1659 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
61890b02 1660 { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
01310af2 1661 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
400738b1 1662#ifdef CONFIG_NETWORK
416e3508 1663 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
400738b1 1664#endif
638c9d91 1665 { "sync", HAS_ARG | OPT_EXPERT, {(void*)&opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
01310af2
FB
1666 { NULL, },
1667};
1668
1669void show_help(void)
1670{
02d504a7
FB
1671 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
1672 "usage: ffplay [options] input_file\n"
01310af2
FB
1673 "Simple media player\n");
1674 printf("\n");
02d504a7
FB
1675 show_help_options(options, "Main options:\n",
1676 OPT_EXPERT, 0);
1677 show_help_options(options, "\nAdvanced options:\n",
1678 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
1679 printf("\nWhile playing:\n"
1680 "q, ESC quit\n"
1681 "f toggle full screen\n"
1682 "p, SPC pause\n"
638c9d91
FB
1683 "a cycle audio channel\n"
1684 "v cycle video channel\n"
1685 "w show audio waves\n"
01310af2
FB
1686 );
1687 exit(1);
1688}
1689
1690void parse_arg_file(const char *filename)
1691{
e8d83e1c
MN
1692 if (!strcmp(filename, "-"))
1693 filename = "pipe:";
01310af2
FB
1694 input_filename = filename;
1695}
1696
1697/* Called from the main */
1698int main(int argc, char **argv)
1699{
638c9d91 1700 int flags, w, h;
01310af2
FB
1701
1702 /* register all codecs, demux and protocols */
1703 av_register_all();
1704
1705 parse_options(argc, argv, options);
1706
1707 if (!input_filename)
1708 show_help();
1709
1710 if (display_disable) {
1711 video_disable = 1;
1712 }
31319a8c
FB
1713 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
1714#ifndef CONFIG_WIN32
1715 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 */
1716#endif
01310af2
FB
1717 if (SDL_Init (flags)) {
1718 fprintf(stderr, "Could not initialize SDL - exiting\n");
1719 exit(1);
1720 }
1721
1722 if (!display_disable) {
01310af2
FB
1723#ifdef HAVE_X11
1724 /* save the screen resolution... SDL should allow full screen
1725 by resizing the window */
1726 {
1727 Display *dpy;
1728 dpy = XOpenDisplay(NULL);
1729 if (dpy) {
1730 fs_screen_width = DisplayWidth(dpy, DefaultScreen(dpy));
1731 fs_screen_height = DisplayHeight(dpy, DefaultScreen(dpy));
1732 XCloseDisplay(dpy);
1733 }
1734 }
1735#endif
638c9d91
FB
1736 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1737 if (is_full_screen && fs_screen_width) {
1738 w = fs_screen_width;
1739 h = fs_screen_height;
1740 flags |= SDL_FULLSCREEN;
1741 } else {
1742 w = screen_width;
1743 h = screen_height;
1744 flags |= SDL_RESIZABLE;
1745 }
1746 screen = SDL_SetVideoMode(w, h, 0, flags);
1747 if (!screen) {
1748 fprintf(stderr, "SDL: could not set video mode - exiting\n");
1749 exit(1);
1750 }
1751 SDL_WM_SetCaption("FFplay", "FFplay");
01310af2
FB
1752 }
1753
1754 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
1755 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
1756 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
1757 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
1758
638c9d91 1759 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
1760
1761 event_loop();
1762
1763 /* never returns */
1764
1765 return 0;
1766}