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