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