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