Use Subversion revision for FFMPEG_VERSION.
[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
5509bffa 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
01310af2
FB
18 */
19#define HAVE_AV_CONFIG_H
01310af2
FB
20#include "avformat.h"
21
f1cc88a5 22#include "version.h"
01310af2
FB
23#include "cmdutils.h"
24
25#include <SDL.h>
26#include <SDL_thread.h>
27
31319a8c
FB
28#ifdef CONFIG_WIN32
29#undef main /* We don't want SDL to override our main() */
30#endif
31
3ca4b654
MN
32#ifdef CONFIG_OS2
33#define INCL_DOS
34 #include <os2.h>
35 #include <stdio.h>
115329f1 36
3ca4b654
MN
37 void MorphToPM()
38 {
39 PPIB pib;
40 PTIB tib;
115329f1 41
3ca4b654 42 DosGetInfoBlocks(&tib, &pib);
115329f1 43
3ca4b654
MN
44 // Change flag from VIO to PM:
45 if (pib->pib_ultype==2) pib->pib_ultype = 3;
46 }
47#endif
48
638c9d91
FB
49//#define DEBUG_SYNC
50
01310af2
FB
51#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
52#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
72ce053b 53#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
01310af2 54
638c9d91
FB
55/* SDL audio buffer size, in samples. Should be small to have precise
56 A/V sync as SDL does not have hardware buffer fullness info. */
57#define SDL_AUDIO_BUFFER_SIZE 1024
58
59/* no AV sync correction is done if below the AV sync threshold */
7e0140cb 60#define AV_SYNC_THRESHOLD 0.01
638c9d91
FB
61/* no AV correction is done if too big error */
62#define AV_NOSYNC_THRESHOLD 10.0
63
64/* maximum audio speed change to get correct sync */
65#define SAMPLE_CORRECTION_PERCENT_MAX 10
66
67/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
68#define AUDIO_DIFF_AVG_NB 20
69
01310af2
FB
70/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
71#define SAMPLE_ARRAY_SIZE (2*65536)
72
73typedef struct PacketQueue {
74 AVPacketList *first_pkt, *last_pkt;
75 int nb_packets;
76 int size;
77 int abort_request;
78 SDL_mutex *mutex;
79 SDL_cond *cond;
80} PacketQueue;
81
82#define VIDEO_PICTURE_QUEUE_SIZE 1
72ce053b 83#define SUBPICTURE_QUEUE_SIZE 4
01310af2
FB
84
85typedef struct VideoPicture {
267e9dfa 86 double pts; ///<presentation time stamp for this picture
01310af2
FB
87 SDL_Overlay *bmp;
88 int width, height; /* source height & width */
89 int allocated;
90} VideoPicture;
91
72ce053b
IC
92typedef struct SubPicture {
93 double pts; /* presentation time stamp for this picture */
94 AVSubtitle sub;
95} SubPicture;
96
01310af2
FB
97enum {
98 AV_SYNC_AUDIO_MASTER, /* default choice */
99 AV_SYNC_VIDEO_MASTER,
638c9d91 100 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
01310af2
FB
101};
102
103typedef struct VideoState {
104 SDL_Thread *parse_tid;
105 SDL_Thread *video_tid;
638c9d91 106 AVInputFormat *iformat;
01310af2
FB
107 int no_background;
108 int abort_request;
109 int paused;
416e3508 110 int last_paused;
72ea344b 111 int seek_req;
3ba1438d 112 int seek_flags;
72ea344b 113 int64_t seek_pos;
01310af2
FB
114 AVFormatContext *ic;
115 int dtg_active_format;
116
117 int audio_stream;
115329f1 118
01310af2 119 int av_sync_type;
638c9d91
FB
120 double external_clock; /* external clock base */
121 int64_t external_clock_time;
115329f1 122
638c9d91
FB
123 double audio_clock;
124 double audio_diff_cum; /* used for AV difference average computation */
125 double audio_diff_avg_coef;
126 double audio_diff_threshold;
127 int audio_diff_avg_count;
01310af2
FB
128 AVStream *audio_st;
129 PacketQueue audioq;
130 int audio_hw_buf_size;
131 /* samples output by the codec. we reserve more space for avsync
132 compensation */
115329f1 133 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
7fea94ce 134 unsigned int audio_buf_size; /* in bytes */
01310af2
FB
135 int audio_buf_index; /* in bytes */
136 AVPacket audio_pkt;
137 uint8_t *audio_pkt_data;
138 int audio_pkt_size;
115329f1 139
01310af2
FB
140 int show_audio; /* if true, display audio samples */
141 int16_t sample_array[SAMPLE_ARRAY_SIZE];
142 int sample_array_index;
5e0257e3 143 int last_i_start;
115329f1 144
72ce053b
IC
145 SDL_Thread *subtitle_tid;
146 int subtitle_stream;
147 int subtitle_stream_changed;
148 AVStream *subtitle_st;
149 PacketQueue subtitleq;
150 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
151 int subpq_size, subpq_rindex, subpq_windex;
152 SDL_mutex *subpq_mutex;
153 SDL_cond *subpq_cond;
115329f1 154
638c9d91
FB
155 double frame_timer;
156 double frame_last_pts;
157 double frame_last_delay;
115329f1 158 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
01310af2
FB
159 int video_stream;
160 AVStream *video_st;
161 PacketQueue videoq;
267e9dfa
MN
162 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
163 int64_t video_current_pts_time; ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
01310af2
FB
164 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
165 int pictq_size, pictq_rindex, pictq_windex;
166 SDL_mutex *pictq_mutex;
167 SDL_cond *pictq_cond;
115329f1 168
b514ed3c
MN
169 SDL_mutex *video_decoder_mutex;
170 SDL_mutex *audio_decoder_mutex;
72ce053b 171 SDL_mutex *subtitle_decoder_mutex;
b514ed3c 172
01310af2
FB
173 // QETimer *video_timer;
174 char filename[1024];
175 int width, height, xleft, ytop;
176} VideoState;
177
178void show_help(void);
638c9d91 179static int audio_write_get_buf_size(VideoState *is);
01310af2
FB
180
181/* options specified by the user */
182static AVInputFormat *file_iformat;
61890b02 183static AVImageFormat *image_format;
01310af2
FB
184static const char *input_filename;
185static int fs_screen_width;
186static int fs_screen_height;
187static int screen_width = 640;
188static int screen_height = 480;
189static int audio_disable;
190static int video_disable;
191static int display_disable;
192static int show_status;
638c9d91 193static int av_sync_type = AV_SYNC_AUDIO_MASTER;
72ea344b 194static int64_t start_time = AV_NOPTS_VALUE;
e26a8335 195static int debug = 0;
0c9bbaec 196static int debug_mv = 0;
bba04f1e 197static int step = 0;
c62c07d3 198static int thread_count = 1;
6387c3e6 199static int workaround_bugs = 1;
6fc5b059 200static int fast = 0;
30bc6613 201static int genpts = 0;
178fcca8
MN
202static int lowres = 0;
203static int idct = FF_IDCT_AUTO;
8c3eba7c
MN
204static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
205static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
206static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
1471c6c2 207static int error_resilience = FF_ER_CAREFUL;
1b51e051 208static int error_concealment = 3;
01310af2
FB
209
210/* current context */
211static int is_full_screen;
212static VideoState *cur_stream;
5e0257e3 213static int64_t audio_callback_time;
01310af2
FB
214
215#define FF_ALLOC_EVENT (SDL_USEREVENT)
216#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
638c9d91 217#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
01310af2
FB
218
219SDL_Surface *screen;
220
221/* packet queue handling */
222static void packet_queue_init(PacketQueue *q)
223{
224 memset(q, 0, sizeof(PacketQueue));
225 q->mutex = SDL_CreateMutex();
226 q->cond = SDL_CreateCond();
227}
228
72ea344b 229static void packet_queue_flush(PacketQueue *q)
01310af2
FB
230{
231 AVPacketList *pkt, *pkt1;
232
687fae2b 233 SDL_LockMutex(q->mutex);
01310af2
FB
234 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
235 pkt1 = pkt->next;
236 av_free_packet(&pkt->pkt);
da6c4573 237 av_freep(&pkt);
01310af2 238 }
72ea344b
FB
239 q->last_pkt = NULL;
240 q->first_pkt = NULL;
241 q->nb_packets = 0;
242 q->size = 0;
687fae2b 243 SDL_UnlockMutex(q->mutex);
72ea344b
FB
244}
245
246static void packet_queue_end(PacketQueue *q)
247{
248 packet_queue_flush(q);
01310af2
FB
249 SDL_DestroyMutex(q->mutex);
250 SDL_DestroyCond(q->cond);
251}
252
253static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
254{
255 AVPacketList *pkt1;
256
72ea344b
FB
257 /* duplicate the packet */
258 if (av_dup_packet(pkt) < 0)
259 return -1;
115329f1 260
01310af2
FB
261 pkt1 = av_malloc(sizeof(AVPacketList));
262 if (!pkt1)
263 return -1;
264 pkt1->pkt = *pkt;
265 pkt1->next = NULL;
266
72ea344b 267
01310af2
FB
268 SDL_LockMutex(q->mutex);
269
270 if (!q->last_pkt)
271
272 q->first_pkt = pkt1;
273 else
274 q->last_pkt->next = pkt1;
275 q->last_pkt = pkt1;
276 q->nb_packets++;
277 q->size += pkt1->pkt.size;
278 /* XXX: should duplicate packet data in DV case */
279 SDL_CondSignal(q->cond);
280
281 SDL_UnlockMutex(q->mutex);
282 return 0;
283}
284
285static void packet_queue_abort(PacketQueue *q)
286{
287 SDL_LockMutex(q->mutex);
288
289 q->abort_request = 1;
115329f1 290
01310af2
FB
291 SDL_CondSignal(q->cond);
292
293 SDL_UnlockMutex(q->mutex);
294}
295
296/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
297static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
298{
299 AVPacketList *pkt1;
300 int ret;
301
302 SDL_LockMutex(q->mutex);
303
304 for(;;) {
305 if (q->abort_request) {
306 ret = -1;
307 break;
308 }
115329f1 309
01310af2
FB
310 pkt1 = q->first_pkt;
311 if (pkt1) {
312 q->first_pkt = pkt1->next;
313 if (!q->first_pkt)
314 q->last_pkt = NULL;
315 q->nb_packets--;
316 q->size -= pkt1->pkt.size;
317 *pkt = pkt1->pkt;
318 av_free(pkt1);
319 ret = 1;
320 break;
321 } else if (!block) {
322 ret = 0;
323 break;
324 } else {
325 SDL_CondWait(q->cond, q->mutex);
326 }
327 }
328 SDL_UnlockMutex(q->mutex);
329 return ret;
330}
331
115329f1 332static inline void fill_rectangle(SDL_Surface *screen,
01310af2
FB
333 int x, int y, int w, int h, int color)
334{
335 SDL_Rect rect;
336 rect.x = x;
337 rect.y = y;
338 rect.w = w;
339 rect.h = h;
340 SDL_FillRect(screen, &rect, color);
341}
342
343#if 0
344/* draw only the border of a rectangle */
345void fill_border(VideoState *s, int x, int y, int w, int h, int color)
346{
347 int w1, w2, h1, h2;
348
349 /* fill the background */
350 w1 = x;
351 if (w1 < 0)
352 w1 = 0;
353 w2 = s->width - (x + w);
354 if (w2 < 0)
355 w2 = 0;
356 h1 = y;
357 if (h1 < 0)
358 h1 = 0;
359 h2 = s->height - (y + h);
360 if (h2 < 0)
361 h2 = 0;
115329f1
DB
362 fill_rectangle(screen,
363 s->xleft, s->ytop,
364 w1, s->height,
01310af2 365 color);
115329f1
DB
366 fill_rectangle(screen,
367 s->xleft + s->width - w2, s->ytop,
368 w2, s->height,
01310af2 369 color);
115329f1
DB
370 fill_rectangle(screen,
371 s->xleft + w1, s->ytop,
372 s->width - w1 - w2, h1,
01310af2 373 color);
115329f1 374 fill_rectangle(screen,
01310af2
FB
375 s->xleft + w1, s->ytop + s->height - h2,
376 s->width - w1 - w2, h2,
377 color);
378}
379#endif
380
72ce053b
IC
381
382
383#define SCALEBITS 10
384#define ONE_HALF (1 << (SCALEBITS - 1))
385#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
386
387#define RGB_TO_Y_CCIR(r, g, b) \
388((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
389 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
390
391#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
392(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
393 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
394
395#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
396(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
397 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
398
399#define ALPHA_BLEND(a, oldp, newp, s)\
400((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
401
402#define RGBA_IN(r, g, b, a, s)\
403{\
404 unsigned int v = ((const uint32_t *)(s))[0];\
405 a = (v >> 24) & 0xff;\
406 r = (v >> 16) & 0xff;\
407 g = (v >> 8) & 0xff;\
408 b = v & 0xff;\
409}
410
411#define YUVA_IN(y, u, v, a, s, pal)\
412{\
413 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
414 a = (val >> 24) & 0xff;\
415 y = (val >> 16) & 0xff;\
416 u = (val >> 8) & 0xff;\
417 v = val & 0xff;\
418}
419
420#define YUVA_OUT(d, y, u, v, a)\
421{\
422 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
423}
424
425
426#define BPP 1
427
428static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
429{
430 int wrap, wrap3, width2, skip2;
431 int y, u, v, a, u1, v1, a1, w, h;
432 uint8_t *lum, *cb, *cr;
433 const uint8_t *p;
434 const uint32_t *pal;
435
436 lum = dst->data[0] + rect->y * dst->linesize[0];
437 cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
438 cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
439
440 width2 = (rect->w + 1) >> 1;
441 skip2 = rect->x >> 1;
442 wrap = dst->linesize[0];
443 wrap3 = rect->linesize;
444 p = rect->bitmap;
445 pal = rect->rgba_palette; /* Now in YCrCb! */
115329f1 446
72ce053b
IC
447 if (rect->y & 1) {
448 lum += rect->x;
449 cb += skip2;
450 cr += skip2;
115329f1 451
72ce053b
IC
452 if (rect->x & 1) {
453 YUVA_IN(y, u, v, a, p, pal);
454 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
455 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
456 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
457 cb++;
458 cr++;
459 lum++;
460 p += BPP;
461 }
462 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
463 YUVA_IN(y, u, v, a, p, pal);
464 u1 = u;
465 v1 = v;
466 a1 = a;
467 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
468
469 YUVA_IN(y, u, v, a, p + BPP, pal);
470 u1 += u;
471 v1 += v;
472 a1 += a;
473 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
474 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
475 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
476 cb++;
477 cr++;
478 p += 2 * BPP;
479 lum += 2;
480 }
481 if (w) {
482 YUVA_IN(y, u, v, a, p, pal);
483 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
484 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
485 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
486 }
487 p += wrap3 + (wrap3 - rect->w * BPP);
488 lum += wrap + (wrap - rect->w - rect->x);
489 cb += dst->linesize[1] - width2 - skip2;
490 cr += dst->linesize[2] - width2 - skip2;
491 }
492 for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
493 lum += rect->x;
494 cb += skip2;
495 cr += skip2;
115329f1 496
72ce053b
IC
497 if (rect->x & 1) {
498 YUVA_IN(y, u, v, a, p, pal);
499 u1 = u;
500 v1 = v;
501 a1 = a;
502 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
503 p += wrap3;
504 lum += wrap;
505 YUVA_IN(y, u, v, a, p, pal);
506 u1 += u;
507 v1 += v;
508 a1 += a;
509 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
510 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
511 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
512 cb++;
513 cr++;
514 p += -wrap3 + BPP;
515 lum += -wrap + 1;
516 }
517 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
518 YUVA_IN(y, u, v, a, p, pal);
519 u1 = u;
520 v1 = v;
521 a1 = a;
522 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
523
524 YUVA_IN(y, u, v, a, p, pal);
525 u1 += u;
526 v1 += v;
527 a1 += a;
528 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
529 p += wrap3;
530 lum += wrap;
531
532 YUVA_IN(y, u, v, a, p, pal);
533 u1 += u;
534 v1 += v;
535 a1 += a;
536 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
537
538 YUVA_IN(y, u, v, a, p, pal);
539 u1 += u;
540 v1 += v;
541 a1 += a;
542 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
543
544 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
545 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
546
547 cb++;
548 cr++;
549 p += -wrap3 + 2 * BPP;
550 lum += -wrap + 2;
551 }
552 if (w) {
553 YUVA_IN(y, u, v, a, p, pal);
554 u1 = u;
555 v1 = v;
556 a1 = a;
557 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
558 p += wrap3;
559 lum += wrap;
560 YUVA_IN(y, u, v, a, p, pal);
561 u1 += u;
562 v1 += v;
563 a1 += a;
564 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
565 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
566 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
567 cb++;
568 cr++;
569 p += -wrap3 + BPP;
570 lum += -wrap + 1;
571 }
572 p += wrap3 + (wrap3 - rect->w * BPP);
573 lum += wrap + (wrap - rect->w - rect->x);
574 cb += dst->linesize[1] - width2 - skip2;
575 cr += dst->linesize[2] - width2 - skip2;
576 }
577 /* handle odd height */
578 if (h) {
579 lum += rect->x;
580 cb += skip2;
581 cr += skip2;
115329f1 582
72ce053b
IC
583 if (rect->x & 1) {
584 YUVA_IN(y, u, v, a, p, pal);
585 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
586 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
587 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
588 cb++;
589 cr++;
590 lum++;
591 p += BPP;
592 }
593 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
594 YUVA_IN(y, u, v, a, p, pal);
595 u1 = u;
596 v1 = v;
597 a1 = a;
598 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
599
600 YUVA_IN(y, u, v, a, p + BPP, pal);
601 u1 += u;
602 v1 += v;
603 a1 += a;
604 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
605 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
606 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
607 cb++;
608 cr++;
609 p += 2 * BPP;
610 lum += 2;
611 }
612 if (w) {
613 YUVA_IN(y, u, v, a, p, pal);
614 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
615 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
616 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
617 }
618 }
619}
620
621static void free_subpicture(SubPicture *sp)
622{
623 int i;
115329f1 624
72ce053b
IC
625 for (i = 0; i < sp->sub.num_rects; i++)
626 {
627 av_free(sp->sub.rects[i].bitmap);
628 av_free(sp->sub.rects[i].rgba_palette);
629 }
115329f1 630
72ce053b 631 av_free(sp->sub.rects);
115329f1 632
72ce053b
IC
633 memset(&sp->sub, 0, sizeof(AVSubtitle));
634}
635
01310af2
FB
636static void video_image_display(VideoState *is)
637{
638 VideoPicture *vp;
72ce053b
IC
639 SubPicture *sp;
640 AVPicture pict;
01310af2
FB
641 float aspect_ratio;
642 int width, height, x, y;
643 SDL_Rect rect;
72ce053b 644 int i;
01310af2
FB
645
646 vp = &is->pictq[is->pictq_rindex];
647 if (vp->bmp) {
648 /* XXX: use variable in the frame */
115329f1 649 if (is->video_st->codec->sample_aspect_ratio.num == 0)
72ea344b
FB
650 aspect_ratio = 0;
651 else
115329f1 652 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
01f4895c 653 * is->video_st->codec->width / is->video_st->codec->height;;
01310af2 654 if (aspect_ratio <= 0.0)
115329f1 655 aspect_ratio = (float)is->video_st->codec->width /
01f4895c 656 (float)is->video_st->codec->height;
01310af2
FB
657 /* if an active format is indicated, then it overrides the
658 mpeg format */
659#if 0
01f4895c
MN
660 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
661 is->dtg_active_format = is->video_st->codec->dtg_active_format;
01310af2
FB
662 printf("dtg_active_format=%d\n", is->dtg_active_format);
663 }
664#endif
665#if 0
01f4895c 666 switch(is->video_st->codec->dtg_active_format) {
01310af2
FB
667 case FF_DTG_AFD_SAME:
668 default:
669 /* nothing to do */
670 break;
671 case FF_DTG_AFD_4_3:
672 aspect_ratio = 4.0 / 3.0;
673 break;
674 case FF_DTG_AFD_16_9:
675 aspect_ratio = 16.0 / 9.0;
676 break;
677 case FF_DTG_AFD_14_9:
678 aspect_ratio = 14.0 / 9.0;
679 break;
680 case FF_DTG_AFD_4_3_SP_14_9:
681 aspect_ratio = 14.0 / 9.0;
682 break;
683 case FF_DTG_AFD_16_9_SP_14_9:
684 aspect_ratio = 14.0 / 9.0;
685 break;
686 case FF_DTG_AFD_SP_4_3:
687 aspect_ratio = 4.0 / 3.0;
688 break;
689 }
690#endif
691
72ce053b
IC
692 if (is->subtitle_st)
693 {
694 if (is->subpq_size > 0)
695 {
696 sp = &is->subpq[is->subpq_rindex];
697
698 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
699 {
700 SDL_LockYUVOverlay (vp->bmp);
701
702 pict.data[0] = vp->bmp->pixels[0];
703 pict.data[1] = vp->bmp->pixels[2];
704 pict.data[2] = vp->bmp->pixels[1];
705
706 pict.linesize[0] = vp->bmp->pitches[0];
707 pict.linesize[1] = vp->bmp->pitches[2];
708 pict.linesize[2] = vp->bmp->pitches[1];
709
710 for (i = 0; i < sp->sub.num_rects; i++)
711 blend_subrect(&pict, &sp->sub.rects[i]);
712
713 SDL_UnlockYUVOverlay (vp->bmp);
714 }
715 }
716 }
717
718
01310af2
FB
719 /* XXX: we suppose the screen has a 1.0 pixel ratio */
720 height = is->height;
721 width = ((int)rint(height * aspect_ratio)) & -3;
722 if (width > is->width) {
723 width = is->width;
724 height = ((int)rint(width / aspect_ratio)) & -3;
725 }
726 x = (is->width - width) / 2;
727 y = (is->height - height) / 2;
728 if (!is->no_background) {
729 /* fill the background */
730 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
731 } else {
732 is->no_background = 0;
733 }
734 rect.x = is->xleft + x;
735 rect.y = is->xleft + y;
736 rect.w = width;
737 rect.h = height;
738 SDL_DisplayYUVOverlay(vp->bmp, &rect);
739 } else {
740#if 0
115329f1
DB
741 fill_rectangle(screen,
742 is->xleft, is->ytop, is->width, is->height,
01310af2
FB
743 QERGB(0x00, 0x00, 0x00));
744#endif
745 }
746}
747
748static inline int compute_mod(int a, int b)
749{
750 a = a % b;
115329f1 751 if (a >= 0)
01310af2
FB
752 return a;
753 else
754 return a + b;
755}
756
757static void video_audio_display(VideoState *s)
758{
759 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
760 int ch, channels, h, h2, bgcolor, fgcolor;
761 int16_t time_diff;
115329f1 762
01310af2 763 /* compute display index : center on currently output samples */
01f4895c 764 channels = s->audio_st->codec->channels;
01310af2 765 nb_display_channels = channels;
5e0257e3
FB
766 if (!s->paused) {
767 n = 2 * channels;
768 delay = audio_write_get_buf_size(s);
769 delay /= n;
115329f1 770
5e0257e3
FB
771 /* to be more precise, we take into account the time spent since
772 the last buffer computation */
773 if (audio_callback_time) {
774 time_diff = av_gettime() - audio_callback_time;
01f4895c 775 delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
5e0257e3 776 }
115329f1 777
5e0257e3
FB
778 delay -= s->width / 2;
779 if (delay < s->width)
780 delay = s->width;
781 i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
782 s->last_i_start = i_start;
783 } else {
784 i_start = s->last_i_start;
01310af2
FB
785 }
786
01310af2 787 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
115329f1
DB
788 fill_rectangle(screen,
789 s->xleft, s->ytop, s->width, s->height,
01310af2
FB
790 bgcolor);
791
792 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
793
794 /* total height for one channel */
795 h = s->height / nb_display_channels;
796 /* graph height / 2 */
797 h2 = (h * 9) / 20;
798 for(ch = 0;ch < nb_display_channels; ch++) {
799 i = i_start + ch;
800 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
801 for(x = 0; x < s->width; x++) {
802 y = (s->sample_array[i] * h2) >> 15;
803 if (y < 0) {
804 y = -y;
805 ys = y1 - y;
806 } else {
807 ys = y1;
808 }
115329f1
DB
809 fill_rectangle(screen,
810 s->xleft + x, ys, 1, y,
01310af2
FB
811 fgcolor);
812 i += channels;
813 if (i >= SAMPLE_ARRAY_SIZE)
814 i -= SAMPLE_ARRAY_SIZE;
815 }
816 }
817
818 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
819
820 for(ch = 1;ch < nb_display_channels; ch++) {
821 y = s->ytop + ch * h;
115329f1
DB
822 fill_rectangle(screen,
823 s->xleft, y, s->width, 1,
01310af2
FB
824 fgcolor);
825 }
826 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
827}
828
829/* display the current picture, if any */
830static void video_display(VideoState *is)
831{
115329f1 832 if (is->audio_st && is->show_audio)
01310af2
FB
833 video_audio_display(is);
834 else if (is->video_st)
835 video_image_display(is);
836}
837
838static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
839{
840 SDL_Event event;
841 event.type = FF_REFRESH_EVENT;
842 event.user.data1 = opaque;
843 SDL_PushEvent(&event);
844 return 0; /* 0 means stop timer */
845}
846
847/* schedule a video refresh in 'delay' ms */
848static void schedule_refresh(VideoState *is, int delay)
849{
850 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
851}
852
638c9d91
FB
853/* get the current audio clock value */
854static double get_audio_clock(VideoState *is)
855{
856 double pts;
857 int hw_buf_size, bytes_per_sec;
858 pts = is->audio_clock;
859 hw_buf_size = audio_write_get_buf_size(is);
860 bytes_per_sec = 0;
861 if (is->audio_st) {
115329f1 862 bytes_per_sec = is->audio_st->codec->sample_rate *
01f4895c 863 2 * is->audio_st->codec->channels;
638c9d91
FB
864 }
865 if (bytes_per_sec)
866 pts -= (double)hw_buf_size / bytes_per_sec;
867 return pts;
868}
869
870/* get the current video clock value */
871static double get_video_clock(VideoState *is)
872{
873 double delta;
04108619 874 if (is->paused) {
72ea344b
FB
875 delta = 0;
876 } else {
877 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
878 }
638c9d91
FB
879 return is->video_current_pts + delta;
880}
881
882/* get the current external clock value */
883static double get_external_clock(VideoState *is)
884{
885 int64_t ti;
886 ti = av_gettime();
887 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
888}
889
890/* get the current master clock value */
891static double get_master_clock(VideoState *is)
892{
893 double val;
894
72ea344b
FB
895 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
896 if (is->video_st)
897 val = get_video_clock(is);
898 else
899 val = get_audio_clock(is);
900 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
901 if (is->audio_st)
902 val = get_audio_clock(is);
903 else
904 val = get_video_clock(is);
905 } else {
638c9d91 906 val = get_external_clock(is);
72ea344b 907 }
638c9d91
FB
908 return val;
909}
910
72ea344b 911/* seek in the stream */
3ba1438d 912static void stream_seek(VideoState *is, int64_t pos, int rel)
72ea344b 913{
687fae2b
IW
914 if (!is->seek_req) {
915 is->seek_pos = pos;
916 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
917 is->seek_req = 1;
918 }
72ea344b
FB
919}
920
921/* pause or resume the video */
922static void stream_pause(VideoState *is)
923{
924 is->paused = !is->paused;
925 if (is->paused) {
926 is->video_current_pts = get_video_clock(is);
927 }
928}
929
01310af2
FB
930/* called to display each frame */
931static void video_refresh_timer(void *opaque)
932{
933 VideoState *is = opaque;
934 VideoPicture *vp;
638c9d91
FB
935 double actual_delay, delay, sync_threshold, ref_clock, diff;
936
72ce053b 937 SubPicture *sp, *sp2;
01310af2
FB
938
939 if (is->video_st) {
940 if (is->pictq_size == 0) {
941 /* if no picture, need to wait */
7e0140cb 942 schedule_refresh(is, 1);
01310af2 943 } else {
638c9d91 944 /* dequeue the picture */
01310af2 945 vp = &is->pictq[is->pictq_rindex];
638c9d91
FB
946
947 /* update current video pts */
948 is->video_current_pts = vp->pts;
949 is->video_current_pts_time = av_gettime();
950
951 /* compute nominal delay */
952 delay = vp->pts - is->frame_last_pts;
953 if (delay <= 0 || delay >= 1.0) {
954 /* if incorrect delay, use previous one */
955 delay = is->frame_last_delay;
956 }
957 is->frame_last_delay = delay;
958 is->frame_last_pts = vp->pts;
959
960 /* update delay to follow master synchronisation source */
961 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
962 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
963 /* if video is slave, we try to correct big delays by
964 duplicating or deleting a frame */
965 ref_clock = get_master_clock(is);
966 diff = vp->pts - ref_clock;
115329f1 967
638c9d91
FB
968 /* skip or repeat frame. We take into account the
969 delay to compute the threshold. I still don't know
970 if it is the best guess */
971 sync_threshold = AV_SYNC_THRESHOLD;
972 if (delay > sync_threshold)
973 sync_threshold = delay;
974 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
975 if (diff <= -sync_threshold)
976 delay = 0;
977 else if (diff >= sync_threshold)
978 delay = 2 * delay;
979 }
980 }
981
982 is->frame_timer += delay;
983 /* compute the REAL delay (we need to do that to avoid
984 long term errors */
985 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
986 if (actual_delay < 0.010) {
987 /* XXX: should skip picture */
988 actual_delay = 0.010;
989 }
01310af2 990 /* launch timer for next picture */
638c9d91
FB
991 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
992
993#if defined(DEBUG_SYNC)
115329f1 994 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
638c9d91
FB
995 delay, actual_delay, vp->pts, -diff);
996#endif
01310af2 997
72ce053b
IC
998 if(is->subtitle_st) {
999 if (is->subtitle_stream_changed) {
1000 SDL_LockMutex(is->subpq_mutex);
115329f1 1001
72ce053b
IC
1002 while (is->subpq_size) {
1003 free_subpicture(&is->subpq[is->subpq_rindex]);
115329f1 1004
72ce053b
IC
1005 /* update queue size and signal for next picture */
1006 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1007 is->subpq_rindex = 0;
115329f1 1008
72ce053b
IC
1009 is->subpq_size--;
1010 }
1011 is->subtitle_stream_changed = 0;
1012
1013 SDL_CondSignal(is->subpq_cond);
1014 SDL_UnlockMutex(is->subpq_mutex);
1015 } else {
1016 if (is->subpq_size > 0) {
1017 sp = &is->subpq[is->subpq_rindex];
1018
1019 if (is->subpq_size > 1)
1020 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1021 else
1022 sp2 = NULL;
1023
1024 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1025 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1026 {
1027 free_subpicture(sp);
1028
1029 /* update queue size and signal for next picture */
1030 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1031 is->subpq_rindex = 0;
1032
1033 SDL_LockMutex(is->subpq_mutex);
1034 is->subpq_size--;
1035 SDL_CondSignal(is->subpq_cond);
1036 SDL_UnlockMutex(is->subpq_mutex);
1037 }
1038 }
1039 }
1040 }
1041
01310af2
FB
1042 /* display picture */
1043 video_display(is);
115329f1 1044
01310af2
FB
1045 /* update queue size and signal for next picture */
1046 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1047 is->pictq_rindex = 0;
115329f1 1048
01310af2
FB
1049 SDL_LockMutex(is->pictq_mutex);
1050 is->pictq_size--;
1051 SDL_CondSignal(is->pictq_cond);
1052 SDL_UnlockMutex(is->pictq_mutex);
1053 }
1054 } else if (is->audio_st) {
1055 /* draw the next audio frame */
1056
1057 schedule_refresh(is, 40);
1058
1059 /* if only audio stream, then display the audio bars (better
1060 than nothing, just to test the implementation */
115329f1 1061
01310af2
FB
1062 /* display picture */
1063 video_display(is);
1064 } else {
1065 schedule_refresh(is, 100);
1066 }
1067 if (show_status) {
1068 static int64_t last_time;
1069 int64_t cur_time;
72ce053b 1070 int aqsize, vqsize, sqsize;
638c9d91 1071 double av_diff;
115329f1 1072
01310af2
FB
1073 cur_time = av_gettime();
1074 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1075 aqsize = 0;
1076 vqsize = 0;
72ce053b 1077 sqsize = 0;
01310af2
FB
1078 if (is->audio_st)
1079 aqsize = is->audioq.size;
1080 if (is->video_st)
1081 vqsize = is->videoq.size;
72ce053b
IC
1082 if (is->subtitle_st)
1083 sqsize = is->subtitleq.size;
638c9d91
FB
1084 av_diff = 0;
1085 if (is->audio_st && is->video_st)
1086 av_diff = get_audio_clock(is) - get_video_clock(is);
115329f1 1087 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
72ce053b 1088 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
01310af2
FB
1089 fflush(stdout);
1090 last_time = cur_time;
1091 }
1092 }
1093}
1094
1095/* allocate a picture (needs to do that in main thread to avoid
1096 potential locking problems */
1097static void alloc_picture(void *opaque)
1098{
1099 VideoState *is = opaque;
1100 VideoPicture *vp;
01310af2
FB
1101
1102 vp = &is->pictq[is->pictq_windex];
1103
1104 if (vp->bmp)
1105 SDL_FreeYUVOverlay(vp->bmp);
1106
61890b02 1107#if 0
01310af2 1108 /* XXX: use generic function */
61890b02 1109 /* XXX: disable overlay if no hardware acceleration or if RGB format */
01f4895c 1110 switch(is->video_st->codec->pix_fmt) {
01310af2
FB
1111 case PIX_FMT_YUV420P:
1112 case PIX_FMT_YUV422P:
1113 case PIX_FMT_YUV444P:
1114 case PIX_FMT_YUV422:
1115 case PIX_FMT_YUV410P:
1116 case PIX_FMT_YUV411P:
1117 is_yuv = 1;
1118 break;
1119 default:
1120 is_yuv = 0;
1121 break;
1122 }
01310af2 1123#endif
01f4895c
MN
1124 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1125 is->video_st->codec->height,
115329f1 1126 SDL_YV12_OVERLAY,
61890b02 1127 screen);
01f4895c
MN
1128 vp->width = is->video_st->codec->width;
1129 vp->height = is->video_st->codec->height;
01310af2
FB
1130
1131 SDL_LockMutex(is->pictq_mutex);
1132 vp->allocated = 1;
1133 SDL_CondSignal(is->pictq_cond);
1134 SDL_UnlockMutex(is->pictq_mutex);
1135}
1136
267e9dfa
MN
1137/**
1138 *
1139 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1140 */
638c9d91 1141static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01310af2
FB
1142{
1143 VideoPicture *vp;
1144 int dst_pix_fmt;
1145 AVPicture pict;
115329f1 1146
01310af2
FB
1147 /* wait until we have space to put a new picture */
1148 SDL_LockMutex(is->pictq_mutex);
1149 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1150 !is->videoq.abort_request) {
1151 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1152 }
1153 SDL_UnlockMutex(is->pictq_mutex);
115329f1 1154
01310af2
FB
1155 if (is->videoq.abort_request)
1156 return -1;
1157
1158 vp = &is->pictq[is->pictq_windex];
1159
1160 /* alloc or resize hardware picture buffer */
115329f1 1161 if (!vp->bmp ||
01f4895c
MN
1162 vp->width != is->video_st->codec->width ||
1163 vp->height != is->video_st->codec->height) {
01310af2
FB
1164 SDL_Event event;
1165
1166 vp->allocated = 0;
1167
1168 /* the allocation must be done in the main thread to avoid
1169 locking problems */
1170 event.type = FF_ALLOC_EVENT;
1171 event.user.data1 = is;
1172 SDL_PushEvent(&event);
115329f1 1173
01310af2
FB
1174 /* wait until the picture is allocated */
1175 SDL_LockMutex(is->pictq_mutex);
1176 while (!vp->allocated && !is->videoq.abort_request) {
1177 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1178 }
1179 SDL_UnlockMutex(is->pictq_mutex);
1180
1181 if (is->videoq.abort_request)
1182 return -1;
1183 }
1184
638c9d91 1185 /* if the frame is not skipped, then display it */
01310af2
FB
1186 if (vp->bmp) {
1187 /* get a pointer on the bitmap */
1188 SDL_LockYUVOverlay (vp->bmp);
1189
1190 dst_pix_fmt = PIX_FMT_YUV420P;
1191 pict.data[0] = vp->bmp->pixels[0];
1192 pict.data[1] = vp->bmp->pixels[2];
1193 pict.data[2] = vp->bmp->pixels[1];
1194
1195 pict.linesize[0] = vp->bmp->pitches[0];
1196 pict.linesize[1] = vp->bmp->pitches[2];
1197 pict.linesize[2] = vp->bmp->pitches[1];
115329f1
DB
1198 img_convert(&pict, dst_pix_fmt,
1199 (AVPicture *)src_frame, is->video_st->codec->pix_fmt,
01f4895c 1200 is->video_st->codec->width, is->video_st->codec->height);
01310af2
FB
1201 /* update the bitmap content */
1202 SDL_UnlockYUVOverlay(vp->bmp);
1203
638c9d91 1204 vp->pts = pts;
01310af2
FB
1205
1206 /* now we can update the picture count */
1207 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1208 is->pictq_windex = 0;
1209 SDL_LockMutex(is->pictq_mutex);
1210 is->pictq_size++;
1211 SDL_UnlockMutex(is->pictq_mutex);
1212 }
638c9d91
FB
1213 return 0;
1214}
1215
115329f1
DB
1216/**
1217 * compute the exact PTS for the picture if it is omitted in the stream
267e9dfa
MN
1218 * @param pts1 the dts of the pkt / pts of the frame
1219 */
638c9d91
FB
1220static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1221{
1222 double frame_delay, pts;
115329f1 1223
638c9d91
FB
1224 pts = pts1;
1225
01310af2 1226 if (pts != 0) {
638c9d91 1227 /* update video clock with pts, if present */
01310af2
FB
1228 is->video_clock = pts;
1229 } else {
72ea344b
FB
1230 pts = is->video_clock;
1231 }
1232 /* update video clock for next frame */
01f4895c 1233 frame_delay = av_q2d(is->video_st->codec->time_base);
72ea344b
FB
1234 /* for MPEG2, the frame can be repeated, so we update the
1235 clock accordingly */
267e9dfa 1236 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
72ea344b 1237 is->video_clock += frame_delay;
638c9d91
FB
1238
1239#if defined(DEBUG_SYNC) && 0
1240 {
1241 int ftype;
1242 if (src_frame->pict_type == FF_B_TYPE)
1243 ftype = 'B';
1244 else if (src_frame->pict_type == FF_I_TYPE)
1245 ftype = 'I';
1246 else
1247 ftype = 'P';
115329f1 1248 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
72ea344b 1249 ftype, pts, pts1);
638c9d91
FB
1250 }
1251#endif
72ea344b 1252 return queue_picture(is, src_frame, pts);
01310af2
FB
1253}
1254
1255static int video_thread(void *arg)
1256{
1257 VideoState *is = arg;
1258 AVPacket pkt1, *pkt = &pkt1;
72ea344b 1259 int len1, got_picture;
c6b1edc9 1260 AVFrame *frame= avcodec_alloc_frame();
01310af2
FB
1261 double pts;
1262
1263 for(;;) {
1264 while (is->paused && !is->videoq.abort_request) {
1265 SDL_Delay(10);
1266 }
1267 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1268 break;
638c9d91
FB
1269 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1270 this packet, if any */
72ea344b 1271 pts = 0;
61c1d8e2 1272 if (pkt->dts != AV_NOPTS_VALUE)
c0df9d75 1273 pts = av_q2d(is->video_st->time_base)*pkt->dts;
72ea344b 1274
b514ed3c 1275 SDL_LockMutex(is->video_decoder_mutex);
115329f1
DB
1276 len1 = avcodec_decode_video(is->video_st->codec,
1277 frame, &got_picture,
72ea344b 1278 pkt->data, pkt->size);
b514ed3c 1279 SDL_UnlockMutex(is->video_decoder_mutex);
fb966f99
MN
1280// if (len1 < 0)
1281// break;
72ea344b
FB
1282 if (got_picture) {
1283 if (output_picture2(is, frame, pts) < 0)
1284 goto the_end;
01310af2 1285 }
01310af2 1286 av_free_packet(pkt);
115329f1 1287 if (step)
bba04f1e
WH
1288 if (cur_stream)
1289 stream_pause(cur_stream);
01310af2
FB
1290 }
1291 the_end:
c6b1edc9 1292 av_free(frame);
01310af2
FB
1293 return 0;
1294}
1295
72ce053b
IC
1296static int subtitle_thread(void *arg)
1297{
1298 VideoState *is = arg;
1299 SubPicture *sp;
1300 AVPacket pkt1, *pkt = &pkt1;
1301 int len1, got_subtitle;
1302 double pts;
1303 int i, j;
1304 int r, g, b, y, u, v, a;
1305
1306 for(;;) {
1307 while (is->paused && !is->subtitleq.abort_request) {
1308 SDL_Delay(10);
1309 }
1310 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1311 break;
115329f1 1312
72ce053b
IC
1313 SDL_LockMutex(is->subpq_mutex);
1314 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1315 !is->subtitleq.abort_request) {
1316 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1317 }
1318 SDL_UnlockMutex(is->subpq_mutex);
115329f1 1319
72ce053b
IC
1320 if (is->subtitleq.abort_request)
1321 goto the_end;
115329f1 1322
72ce053b
IC
1323 sp = &is->subpq[is->subpq_windex];
1324
1325 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1326 this packet, if any */
1327 pts = 0;
1328 if (pkt->pts != AV_NOPTS_VALUE)
1329 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1330
1331 SDL_LockMutex(is->subtitle_decoder_mutex);
115329f1
DB
1332 len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
1333 &sp->sub, &got_subtitle,
72ce053b
IC
1334 pkt->data, pkt->size);
1335 SDL_UnlockMutex(is->subtitle_decoder_mutex);
1336// if (len1 < 0)
1337// break;
1338 if (got_subtitle && sp->sub.format == 0) {
1339 sp->pts = pts;
115329f1 1340
72ce053b
IC
1341 for (i = 0; i < sp->sub.num_rects; i++)
1342 {
1343 for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
1344 {
1345 RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
1346 y = RGB_TO_Y_CCIR(r, g, b);
1347 u = RGB_TO_U_CCIR(r, g, b, 0);
1348 v = RGB_TO_V_CCIR(r, g, b, 0);
1349 YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
1350 }
1351 }
1352
1353 /* now we can update the picture count */
1354 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1355 is->subpq_windex = 0;
1356 SDL_LockMutex(is->subpq_mutex);
1357 is->subpq_size++;
1358 SDL_UnlockMutex(is->subpq_mutex);
1359 }
1360 av_free_packet(pkt);
115329f1 1361// if (step)
72ce053b
IC
1362// if (cur_stream)
1363// stream_pause(cur_stream);
1364 }
1365 the_end:
1366 return 0;
1367}
1368
01310af2
FB
1369/* copy samples for viewing in editor window */
1370static void update_sample_display(VideoState *is, short *samples, int samples_size)
1371{
1372 int size, len, channels;
1373
01f4895c 1374 channels = is->audio_st->codec->channels;
01310af2
FB
1375
1376 size = samples_size / sizeof(short);
1377 while (size > 0) {
1378 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1379 if (len > size)
1380 len = size;
1381 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1382 samples += len;
1383 is->sample_array_index += len;
1384 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1385 is->sample_array_index = 0;
1386 size -= len;
1387 }
1388}
1389
01310af2
FB
1390/* return the new audio buffer size (samples can be added or deleted
1391 to get better sync if video or external master clock) */
115329f1 1392static int synchronize_audio(VideoState *is, short *samples,
638c9d91 1393 int samples_size1, double pts)
01310af2 1394{
638c9d91 1395 int n, samples_size;
01310af2 1396 double ref_clock;
115329f1 1397
01f4895c 1398 n = 2 * is->audio_st->codec->channels;
638c9d91 1399 samples_size = samples_size1;
01310af2 1400
01310af2 1401 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 1402 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
1403 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1404 double diff, avg_diff;
01310af2 1405 int wanted_size, min_size, max_size, nb_samples;
115329f1 1406
638c9d91
FB
1407 ref_clock = get_master_clock(is);
1408 diff = get_audio_clock(is) - ref_clock;
115329f1 1409
638c9d91
FB
1410 if (diff < AV_NOSYNC_THRESHOLD) {
1411 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1412 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1413 /* not enough measures to have a correct estimate */
1414 is->audio_diff_avg_count++;
1415 } else {
1416 /* estimate the A-V difference */
1417 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1418
1419 if (fabs(avg_diff) >= is->audio_diff_threshold) {
01f4895c 1420 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
638c9d91 1421 nb_samples = samples_size / n;
115329f1 1422
638c9d91
FB
1423 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1424 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1425 if (wanted_size < min_size)
1426 wanted_size = min_size;
1427 else if (wanted_size > max_size)
1428 wanted_size = max_size;
115329f1 1429
638c9d91
FB
1430 /* add or remove samples to correction the synchro */
1431 if (wanted_size < samples_size) {
1432 /* remove samples */
1433 samples_size = wanted_size;
1434 } else if (wanted_size > samples_size) {
1435 uint8_t *samples_end, *q;
1436 int nb;
115329f1 1437
638c9d91
FB
1438 /* add samples */
1439 nb = (samples_size - wanted_size);
1440 samples_end = (uint8_t *)samples + samples_size - n;
1441 q = samples_end + n;
1442 while (nb > 0) {
1443 memcpy(q, samples_end, n);
1444 q += n;
1445 nb -= n;
1446 }
1447 samples_size = wanted_size;
1448 }
1449 }
1450#if 0
115329f1
DB
1451 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1452 diff, avg_diff, samples_size - samples_size1,
638c9d91
FB
1453 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1454#endif
01310af2 1455 }
638c9d91
FB
1456 } else {
1457 /* too big difference : may be initial PTS errors, so
1458 reset A-V filter */
1459 is->audio_diff_avg_count = 0;
1460 is->audio_diff_cum = 0;
01310af2
FB
1461 }
1462 }
1463
01310af2
FB
1464 return samples_size;
1465}
1466
1467/* decode one audio frame and returns its uncompressed size */
1468static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1469{
1470 AVPacket *pkt = &is->audio_pkt;
72ea344b 1471 int n, len1, data_size;
01310af2
FB
1472 double pts;
1473
1474 for(;;) {
72ea344b 1475 /* NOTE: the audio packet can contain several frames */
01310af2 1476 while (is->audio_pkt_size > 0) {
b514ed3c 1477 SDL_LockMutex(is->audio_decoder_mutex);
115329f1
DB
1478 len1 = avcodec_decode_audio(is->audio_st->codec,
1479 (int16_t *)audio_buf, &data_size,
01310af2 1480 is->audio_pkt_data, is->audio_pkt_size);
b514ed3c 1481 SDL_UnlockMutex(is->audio_decoder_mutex);
72ea344b
FB
1482 if (len1 < 0) {
1483 /* if error, we skip the frame */
1484 is->audio_pkt_size = 0;
01310af2 1485 break;
72ea344b 1486 }
115329f1 1487
01310af2
FB
1488 is->audio_pkt_data += len1;
1489 is->audio_pkt_size -= len1;
72ea344b
FB
1490 if (data_size <= 0)
1491 continue;
1492 /* if no pts, then compute it */
1493 pts = is->audio_clock;
1494 *pts_ptr = pts;
01f4895c 1495 n = 2 * is->audio_st->codec->channels;
115329f1 1496 is->audio_clock += (double)data_size /
01f4895c 1497 (double)(n * is->audio_st->codec->sample_rate);
638c9d91 1498#if defined(DEBUG_SYNC)
72ea344b
FB
1499 {
1500 static double last_clock;
1501 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1502 is->audio_clock - last_clock,
1503 is->audio_clock, pts);
1504 last_clock = is->audio_clock;
01310af2 1505 }
72ea344b
FB
1506#endif
1507 return data_size;
01310af2
FB
1508 }
1509
72ea344b
FB
1510 /* free the current packet */
1511 if (pkt->data)
01310af2 1512 av_free_packet(pkt);
115329f1 1513
72ea344b
FB
1514 if (is->paused || is->audioq.abort_request) {
1515 return -1;
1516 }
115329f1 1517
01310af2
FB
1518 /* read next packet */
1519 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1520 return -1;
1521 is->audio_pkt_data = pkt->data;
1522 is->audio_pkt_size = pkt->size;
115329f1 1523
72ea344b
FB
1524 /* if update the audio clock with the pts */
1525 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1526 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1527 }
01310af2
FB
1528 }
1529}
1530
638c9d91
FB
1531/* get the current audio output buffer size, in samples. With SDL, we
1532 cannot have a precise information */
1533static int audio_write_get_buf_size(VideoState *is)
01310af2 1534{
638c9d91 1535 return is->audio_hw_buf_size - is->audio_buf_index;
01310af2
FB
1536}
1537
1538
1539/* prepare a new audio buffer */
1540void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1541{
1542 VideoState *is = opaque;
1543 int audio_size, len1;
1544 double pts;
1545
1546 audio_callback_time = av_gettime();
115329f1 1547
01310af2
FB
1548 while (len > 0) {
1549 if (is->audio_buf_index >= is->audio_buf_size) {
1550 audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1551 if (audio_size < 0) {
1552 /* if error, just output silence */
1553 is->audio_buf_size = 1024;
1554 memset(is->audio_buf, 0, is->audio_buf_size);
1555 } else {
1556 if (is->show_audio)
1557 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
115329f1 1558 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
01310af2
FB
1559 pts);
1560 is->audio_buf_size = audio_size;
1561 }
1562 is->audio_buf_index = 0;
1563 }
1564 len1 = is->audio_buf_size - is->audio_buf_index;
1565 if (len1 > len)
1566 len1 = len;
1567 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1568 len -= len1;
1569 stream += len1;
1570 is->audio_buf_index += len1;
1571 }
1572}
1573
1574
1575/* open a given stream. Return 0 if OK */
1576static int stream_component_open(VideoState *is, int stream_index)
1577{
1578 AVFormatContext *ic = is->ic;
1579 AVCodecContext *enc;
1580 AVCodec *codec;
1581 SDL_AudioSpec wanted_spec, spec;
1582
1583 if (stream_index < 0 || stream_index >= ic->nb_streams)
1584 return -1;
01f4895c 1585 enc = ic->streams[stream_index]->codec;
115329f1 1586
01310af2
FB
1587 /* prepare audio output */
1588 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1589 wanted_spec.freq = enc->sample_rate;
1590 wanted_spec.format = AUDIO_S16SYS;
638c9d91
FB
1591 /* hack for AC3. XXX: suppress that */
1592 if (enc->channels > 2)
1593 enc->channels = 2;
01310af2
FB
1594 wanted_spec.channels = enc->channels;
1595 wanted_spec.silence = 0;
638c9d91 1596 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
01310af2
FB
1597 wanted_spec.callback = sdl_audio_callback;
1598 wanted_spec.userdata = is;
638c9d91
FB
1599 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1600 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
01310af2 1601 return -1;
638c9d91 1602 }
01310af2
FB
1603 is->audio_hw_buf_size = spec.size;
1604 }
1605
1606 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1607 enc->debug_mv = debug_mv;
1608 enc->debug = debug;
1ab1f099
MN
1609 if(debug)
1610 av_log_set_level(AV_LOG_DEBUG);
6387c3e6 1611 enc->workaround_bugs = workaround_bugs;
178fcca8 1612 enc->lowres = lowres;
61846e9a 1613 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1614 enc->idct_algo= idct;
6fc5b059 1615 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
8c3eba7c
MN
1616 enc->skip_frame= skip_frame;
1617 enc->skip_idct= skip_idct;
1618 enc->skip_loop_filter= skip_loop_filter;
1b51e051
MN
1619 enc->error_resilience= error_resilience;
1620 enc->error_concealment= error_concealment;
01310af2
FB
1621 if (!codec ||
1622 avcodec_open(enc, codec) < 0)
1623 return -1;
2450cff2 1624#if defined(HAVE_THREADS)
c62c07d3
MN
1625 if(thread_count>1)
1626 avcodec_thread_init(enc, thread_count);
1627#endif
1628 enc->thread_count= thread_count;
638c9d91 1629 switch(enc->codec_type) {
01310af2
FB
1630 case CODEC_TYPE_AUDIO:
1631 is->audio_stream = stream_index;
1632 is->audio_st = ic->streams[stream_index];
1633 is->audio_buf_size = 0;
1634 is->audio_buf_index = 0;
638c9d91
FB
1635
1636 /* init averaging filter */
1637 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1638 is->audio_diff_avg_count = 0;
1639 /* since we do not have a precise anough audio fifo fullness,
1640 we correct audio sync only if larger than this threshold */
1641 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1642
01310af2
FB
1643 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1644 packet_queue_init(&is->audioq);
bb270c08 1645 SDL_PauseAudio(0);
01310af2
FB
1646 break;
1647 case CODEC_TYPE_VIDEO:
1648 is->video_stream = stream_index;
1649 is->video_st = ic->streams[stream_index];
1650
638c9d91
FB
1651 is->frame_last_delay = 40e-3;
1652 is->frame_timer = (double)av_gettime() / 1000000.0;
638c9d91
FB
1653 is->video_current_pts_time = av_gettime();
1654
01310af2
FB
1655 packet_queue_init(&is->videoq);
1656 is->video_tid = SDL_CreateThread(video_thread, is);
1657 break;
72ce053b
IC
1658 case CODEC_TYPE_SUBTITLE:
1659 is->subtitle_stream = stream_index;
1660 is->subtitle_st = ic->streams[stream_index];
1661 packet_queue_init(&is->subtitleq);
115329f1 1662
72ce053b
IC
1663 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1664 break;
01310af2
FB
1665 default:
1666 break;
1667 }
1668 return 0;
1669}
1670
1671static void stream_component_close(VideoState *is, int stream_index)
1672{
1673 AVFormatContext *ic = is->ic;
1674 AVCodecContext *enc;
115329f1 1675
72ce053b
IC
1676 if (stream_index < 0 || stream_index >= ic->nb_streams)
1677 return;
01f4895c 1678 enc = ic->streams[stream_index]->codec;
01310af2
FB
1679
1680 switch(enc->codec_type) {
1681 case CODEC_TYPE_AUDIO:
1682 packet_queue_abort(&is->audioq);
1683
1684 SDL_CloseAudio();
1685
1686 packet_queue_end(&is->audioq);
1687 break;
1688 case CODEC_TYPE_VIDEO:
1689 packet_queue_abort(&is->videoq);
1690
1691 /* note: we also signal this mutex to make sure we deblock the
1692 video thread in all cases */
1693 SDL_LockMutex(is->pictq_mutex);
1694 SDL_CondSignal(is->pictq_cond);
1695 SDL_UnlockMutex(is->pictq_mutex);
1696
1697 SDL_WaitThread(is->video_tid, NULL);
1698
1699 packet_queue_end(&is->videoq);
1700 break;
72ce053b
IC
1701 case CODEC_TYPE_SUBTITLE:
1702 packet_queue_abort(&is->subtitleq);
115329f1 1703
72ce053b
IC
1704 /* note: we also signal this mutex to make sure we deblock the
1705 video thread in all cases */
1706 SDL_LockMutex(is->subpq_mutex);
1707 is->subtitle_stream_changed = 1;
115329f1 1708
72ce053b
IC
1709 SDL_CondSignal(is->subpq_cond);
1710 SDL_UnlockMutex(is->subpq_mutex);
1711
1712 SDL_WaitThread(is->subtitle_tid, NULL);
1713
1714 packet_queue_end(&is->subtitleq);
1715 break;
01310af2
FB
1716 default:
1717 break;
1718 }
1719
1720 avcodec_close(enc);
1721 switch(enc->codec_type) {
1722 case CODEC_TYPE_AUDIO:
1723 is->audio_st = NULL;
1724 is->audio_stream = -1;
1725 break;
1726 case CODEC_TYPE_VIDEO:
1727 is->video_st = NULL;
1728 is->video_stream = -1;
1729 break;
72ce053b
IC
1730 case CODEC_TYPE_SUBTITLE:
1731 is->subtitle_st = NULL;
1732 is->subtitle_stream = -1;
1733 break;
01310af2
FB
1734 default:
1735 break;
1736 }
1737}
1738
7b49ce2e 1739static void dump_stream_info(const AVFormatContext *s)
d0526ecf
FB
1740{
1741 if (s->track != 0)
1742 fprintf(stderr, "Track: %d\n", s->track);
1743 if (s->title[0] != '\0')
1744 fprintf(stderr, "Title: %s\n", s->title);
1745 if (s->author[0] != '\0')
1746 fprintf(stderr, "Author: %s\n", s->author);
1747 if (s->album[0] != '\0')
1748 fprintf(stderr, "Album: %s\n", s->album);
1749 if (s->year != 0)
1750 fprintf(stderr, "Year: %d\n", s->year);
1751 if (s->genre[0] != '\0')
1752 fprintf(stderr, "Genre: %s\n", s->genre);
1753}
1754
416e3508
FB
1755/* since we have only one decoding thread, we can use a global
1756 variable instead of a thread local variable */
1757static VideoState *global_video_state;
1758
1759static int decode_interrupt_cb(void)
1760{
1761 return (global_video_state && global_video_state->abort_request);
1762}
01310af2
FB
1763
1764/* this thread gets the stream from the disk or the network */
1765static int decode_thread(void *arg)
1766{
1767 VideoState *is = arg;
1768 AVFormatContext *ic;
72ea344b 1769 int err, i, ret, video_index, audio_index, use_play;
01310af2 1770 AVPacket pkt1, *pkt = &pkt1;
61890b02 1771 AVFormatParameters params, *ap = &params;
01310af2
FB
1772
1773 video_index = -1;
1774 audio_index = -1;
1775 is->video_stream = -1;
1776 is->audio_stream = -1;
72ce053b 1777 is->subtitle_stream = -1;
01310af2 1778
416e3508
FB
1779 global_video_state = is;
1780 url_set_interrupt_cb(decode_interrupt_cb);
1781
61890b02
FB
1782 memset(ap, 0, sizeof(*ap));
1783 ap->image_format = image_format;
72ea344b
FB
1784 ap->initial_pause = 1; /* we force a pause when starting an RTSP
1785 stream */
115329f1 1786
61890b02 1787 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1788 if (err < 0) {
1789 print_error(is->filename, err);
1790 ret = -1;
1791 goto fail;
1792 }
01310af2 1793 is->ic = ic;
72ea344b
FB
1794#ifdef CONFIG_NETWORK
1795 use_play = (ic->iformat == &rtsp_demux);
1796#else
1797 use_play = 0;
1798#endif
30bc6613
MN
1799
1800 if(genpts)
1801 ic->flags |= AVFMT_FLAG_GENPTS;
1802
72ea344b
FB
1803 if (!use_play) {
1804 err = av_find_stream_info(ic);
1805 if (err < 0) {
1806 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1807 ret = -1;
1808 goto fail;
1809 }
2536c5fd 1810 ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
638c9d91 1811 }
72ea344b
FB
1812
1813 /* if seeking requested, we execute it */
1814 if (start_time != AV_NOPTS_VALUE) {
1815 int64_t timestamp;
1816
1817 timestamp = start_time;
1818 /* add the stream start time */
1819 if (ic->start_time != AV_NOPTS_VALUE)
1820 timestamp += ic->start_time;
3ba1438d 1821 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
72ea344b 1822 if (ret < 0) {
115329f1 1823 fprintf(stderr, "%s: could not seek to position %0.3f\n",
72ea344b
FB
1824 is->filename, (double)timestamp / AV_TIME_BASE);
1825 }
1826 }
1827
1828 /* now we can begin to play (RTSP stream only) */
1829 av_read_play(ic);
1830
1831 if (use_play) {
1832 err = av_find_stream_info(ic);
1833 if (err < 0) {
1834 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1835 ret = -1;
1836 goto fail;
1837 }
1838 }
1839
01310af2 1840 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1841 AVCodecContext *enc = ic->streams[i]->codec;
01310af2
FB
1842 switch(enc->codec_type) {
1843 case CODEC_TYPE_AUDIO:
1844 if (audio_index < 0 && !audio_disable)
1845 audio_index = i;
1846 break;
1847 case CODEC_TYPE_VIDEO:
1848 if (video_index < 0 && !video_disable)
1849 video_index = i;
1850 break;
1851 default:
1852 break;
1853 }
1854 }
1855 if (show_status) {
1856 dump_format(ic, 0, is->filename, 0);
d0526ecf 1857 dump_stream_info(ic);
01310af2
FB
1858 }
1859
1860 /* open the streams */
1861 if (audio_index >= 0) {
1862 stream_component_open(is, audio_index);
1863 }
1864
1865 if (video_index >= 0) {
1866 stream_component_open(is, video_index);
1867 } else {
1868 if (!display_disable)
1869 is->show_audio = 1;
1870 }
1871
1872 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1873 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1874 ret = -1;
01310af2
FB
1875 goto fail;
1876 }
1877
1878 for(;;) {
1879 if (is->abort_request)
1880 break;
400738b1 1881#ifdef CONFIG_NETWORK
416e3508
FB
1882 if (is->paused != is->last_paused) {
1883 is->last_paused = is->paused;
72ea344b
FB
1884 if (is->paused)
1885 av_read_pause(ic);
1886 else
1887 av_read_play(ic);
416e3508
FB
1888 }
1889 if (is->paused && ic->iformat == &rtsp_demux) {
1890 /* wait 10 ms to avoid trying to get another packet */
1891 /* XXX: horrible */
1892 SDL_Delay(10);
1893 continue;
1894 }
400738b1 1895#endif
72ea344b
FB
1896 if (is->seek_req) {
1897 /* XXX: must lock decoder threads */
687fae2b
IW
1898 SDL_LockMutex(is->video_decoder_mutex);
1899 SDL_LockMutex(is->audio_decoder_mutex);
72ce053b 1900 SDL_LockMutex(is->subtitle_decoder_mutex);
3ba1438d 1901 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
72ea344b
FB
1902 if (ret < 0) {
1903 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
1904 }else{
1905 if (is->audio_stream >= 0) {
1906 packet_queue_flush(&is->audioq);
1907 }
72ce053b
IC
1908 if (is->subtitle_stream >= 0) {
1909 packet_queue_flush(&is->subtitleq);
1910 }
e6c0297f
MN
1911 if (is->video_stream >= 0) {
1912 packet_queue_flush(&is->videoq);
01f4895c 1913 avcodec_flush_buffers(ic->streams[video_index]->codec);
e6c0297f 1914 }
72ea344b 1915 }
72ce053b 1916 SDL_UnlockMutex(is->subtitle_decoder_mutex);
687fae2b
IW
1917 SDL_UnlockMutex(is->audio_decoder_mutex);
1918 SDL_UnlockMutex(is->video_decoder_mutex);
72ea344b
FB
1919 is->seek_req = 0;
1920 }
416e3508 1921
01310af2
FB
1922 /* if the queue are full, no need to read more */
1923 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
115329f1
DB
1924 is->videoq.size > MAX_VIDEOQ_SIZE ||
1925 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
0c904df2 1926 url_feof(&ic->pb)) {
01310af2
FB
1927 /* wait 10 ms */
1928 SDL_Delay(10);
1929 continue;
1930 }
72ea344b 1931 ret = av_read_frame(ic, pkt);
01310af2 1932 if (ret < 0) {
bb270c08 1933 if (url_ferror(&ic->pb) == 0) {
6e1f8725 1934 SDL_Delay(100); /* wait for user event */
bb270c08
DB
1935 continue;
1936 } else
1937 break;
01310af2
FB
1938 }
1939 if (pkt->stream_index == is->audio_stream) {
1940 packet_queue_put(&is->audioq, pkt);
1941 } else if (pkt->stream_index == is->video_stream) {
1942 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
1943 } else if (pkt->stream_index == is->subtitle_stream) {
1944 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
1945 } else {
1946 av_free_packet(pkt);
1947 }
1948 }
1949 /* wait until the end */
1950 while (!is->abort_request) {
1951 SDL_Delay(100);
1952 }
1953
638c9d91 1954 ret = 0;
01310af2 1955 fail:
416e3508
FB
1956 /* disable interrupting */
1957 global_video_state = NULL;
1958
01310af2
FB
1959 /* close each stream */
1960 if (is->audio_stream >= 0)
1961 stream_component_close(is, is->audio_stream);
1962 if (is->video_stream >= 0)
1963 stream_component_close(is, is->video_stream);
72ce053b
IC
1964 if (is->subtitle_stream >= 0)
1965 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
1966 if (is->ic) {
1967 av_close_input_file(is->ic);
1968 is->ic = NULL; /* safety */
1969 }
416e3508
FB
1970 url_set_interrupt_cb(NULL);
1971
638c9d91
FB
1972 if (ret != 0) {
1973 SDL_Event event;
115329f1 1974
638c9d91
FB
1975 event.type = FF_QUIT_EVENT;
1976 event.user.data1 = is;
1977 SDL_PushEvent(&event);
1978 }
01310af2
FB
1979 return 0;
1980}
1981
638c9d91 1982static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
1983{
1984 VideoState *is;
1985
1986 is = av_mallocz(sizeof(VideoState));
1987 if (!is)
1988 return NULL;
1989 pstrcpy(is->filename, sizeof(is->filename), filename);
638c9d91 1990 is->iformat = iformat;
01310af2
FB
1991 if (screen) {
1992 is->width = screen->w;
1993 is->height = screen->h;
1994 }
1995 is->ytop = 0;
1996 is->xleft = 0;
1997
1998 /* start video display */
1999 is->pictq_mutex = SDL_CreateMutex();
2000 is->pictq_cond = SDL_CreateCond();
115329f1 2001
72ce053b
IC
2002 is->subpq_mutex = SDL_CreateMutex();
2003 is->subpq_cond = SDL_CreateCond();
115329f1 2004
72ce053b 2005 is->subtitle_decoder_mutex = SDL_CreateMutex();
b514ed3c
MN
2006 is->audio_decoder_mutex = SDL_CreateMutex();
2007 is->video_decoder_mutex = SDL_CreateMutex();
01310af2
FB
2008
2009 /* add the refresh timer to draw the picture */
2010 schedule_refresh(is, 40);
2011
638c9d91 2012 is->av_sync_type = av_sync_type;
01310af2
FB
2013 is->parse_tid = SDL_CreateThread(decode_thread, is);
2014 if (!is->parse_tid) {
2015 av_free(is);
2016 return NULL;
2017 }
2018 return is;
2019}
2020
2021static void stream_close(VideoState *is)
2022{
2023 VideoPicture *vp;
2024 int i;
2025 /* XXX: use a special url_shutdown call to abort parse cleanly */
2026 is->abort_request = 1;
2027 SDL_WaitThread(is->parse_tid, NULL);
2028
2029 /* free all pictures */
2030 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2031 vp = &is->pictq[i];
2032 if (vp->bmp) {
2033 SDL_FreeYUVOverlay(vp->bmp);
2034 vp->bmp = NULL;
2035 }
2036 }
2037 SDL_DestroyMutex(is->pictq_mutex);
2038 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2039 SDL_DestroyMutex(is->subpq_mutex);
2040 SDL_DestroyCond(is->subpq_cond);
2041 SDL_DestroyMutex(is->subtitle_decoder_mutex);
b514ed3c
MN
2042 SDL_DestroyMutex(is->audio_decoder_mutex);
2043 SDL_DestroyMutex(is->video_decoder_mutex);
01310af2
FB
2044}
2045
7b49ce2e 2046static void stream_cycle_channel(VideoState *is, int codec_type)
638c9d91
FB
2047{
2048 AVFormatContext *ic = is->ic;
2049 int start_index, stream_index;
2050 AVStream *st;
2051
2052 if (codec_type == CODEC_TYPE_VIDEO)
2053 start_index = is->video_stream;
72ce053b 2054 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2055 start_index = is->audio_stream;
72ce053b
IC
2056 else
2057 start_index = is->subtitle_stream;
2058 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2059 return;
2060 stream_index = start_index;
2061 for(;;) {
2062 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2063 {
2064 if (codec_type == CODEC_TYPE_SUBTITLE)
2065 {
2066 stream_index = -1;
2067 goto the_end;
2068 } else
2069 stream_index = 0;
2070 }
638c9d91
FB
2071 if (stream_index == start_index)
2072 return;
2073 st = ic->streams[stream_index];
01f4895c 2074 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2075 /* check that parameters are OK */
2076 switch(codec_type) {
2077 case CODEC_TYPE_AUDIO:
01f4895c
MN
2078 if (st->codec->sample_rate != 0 &&
2079 st->codec->channels != 0)
638c9d91
FB
2080 goto the_end;
2081 break;
2082 case CODEC_TYPE_VIDEO:
72ce053b 2083 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2084 goto the_end;
2085 default:
2086 break;
2087 }
2088 }
2089 }
2090 the_end:
2091 stream_component_close(is, start_index);
2092 stream_component_open(is, stream_index);
2093}
2094
2095
7b49ce2e 2096static void toggle_full_screen(void)
01310af2
FB
2097{
2098 int w, h, flags;
2099 is_full_screen = !is_full_screen;
29f3b38a
MR
2100 if (!fs_screen_width) {
2101 /* use default SDL method */
2102 SDL_WM_ToggleFullScreen(screen);
01310af2 2103 } else {
29f3b38a
MR
2104 /* use the recorded resolution */
2105 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2106 if (is_full_screen) {
2107 w = fs_screen_width;
2108 h = fs_screen_height;
2109 flags |= SDL_FULLSCREEN;
2110 } else {
2111 w = screen_width;
2112 h = screen_height;
2113 flags |= SDL_RESIZABLE;
2114 }
2115 screen = SDL_SetVideoMode(w, h, 0, flags);
2116 cur_stream->width = w;
2117 cur_stream->height = h;
01310af2
FB
2118 }
2119}
2120
7b49ce2e 2121static void toggle_pause(void)
01310af2
FB
2122{
2123 if (cur_stream)
2124 stream_pause(cur_stream);
bba04f1e
WH
2125 step = 0;
2126}
2127
7b49ce2e 2128static void step_to_next_frame(void)
bba04f1e
WH
2129{
2130 if (cur_stream) {
2131 if (cur_stream->paused)
2132 cur_stream->paused=0;
2133 cur_stream->video_current_pts = get_video_clock(cur_stream);
2134 }
2135 step = 1;
01310af2
FB
2136}
2137
7b49ce2e 2138static void do_exit(void)
01310af2
FB
2139{
2140 if (cur_stream) {
2141 stream_close(cur_stream);
2142 cur_stream = NULL;
2143 }
2144 if (show_status)
2145 printf("\n");
2146 SDL_Quit();
2147 exit(0);
2148}
2149
7b49ce2e 2150static void toggle_audio_display(void)
01310af2
FB
2151{
2152 if (cur_stream) {
2153 cur_stream->show_audio = !cur_stream->show_audio;
2154 }
2155}
2156
2157/* handle an event sent by the GUI */
7b49ce2e 2158static void event_loop(void)
01310af2
FB
2159{
2160 SDL_Event event;
a11d11aa 2161 double incr, pos, frac;
01310af2
FB
2162
2163 for(;;) {
2164 SDL_WaitEvent(&event);
2165 switch(event.type) {
2166 case SDL_KEYDOWN:
2167 switch(event.key.keysym.sym) {
2168 case SDLK_ESCAPE:
2169 case SDLK_q:
2170 do_exit();
2171 break;
2172 case SDLK_f:
2173 toggle_full_screen();
2174 break;
2175 case SDLK_p:
2176 case SDLK_SPACE:
2177 toggle_pause();
2178 break;
bba04f1e
WH
2179 case SDLK_s: //S: Step to next frame
2180 step_to_next_frame();
2181 break;
01310af2 2182 case SDLK_a:
115329f1 2183 if (cur_stream)
638c9d91
FB
2184 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2185 break;
2186 case SDLK_v:
115329f1 2187 if (cur_stream)
638c9d91
FB
2188 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2189 break;
72ce053b 2190 case SDLK_t:
115329f1 2191 if (cur_stream)
72ce053b
IC
2192 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2193 break;
638c9d91 2194 case SDLK_w:
01310af2
FB
2195 toggle_audio_display();
2196 break;
72ea344b
FB
2197 case SDLK_LEFT:
2198 incr = -10.0;
2199 goto do_seek;
2200 case SDLK_RIGHT:
2201 incr = 10.0;
2202 goto do_seek;
2203 case SDLK_UP:
2204 incr = 60.0;
2205 goto do_seek;
2206 case SDLK_DOWN:
2207 incr = -60.0;
2208 do_seek:
2209 if (cur_stream) {
2210 pos = get_master_clock(cur_stream);
2211 pos += incr;
3ba1438d 2212 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
72ea344b
FB
2213 }
2214 break;
01310af2
FB
2215 default:
2216 break;
2217 }
2218 break;
a11d11aa 2219 case SDL_MOUSEBUTTONDOWN:
bb270c08
DB
2220 if (cur_stream) {
2221 int ns, hh, mm, ss;
2222 int tns, thh, tmm, tss;
2223 tns = cur_stream->ic->duration/1000000LL;
2224 thh = tns/3600;
2225 tmm = (tns%3600)/60;
2226 tss = (tns%60);
2227 frac = (double)event.button.x/(double)cur_stream->width;
2228 ns = frac*tns;
2229 hh = ns/3600;
2230 mm = (ns%3600)/60;
2231 ss = (ns%60);
2232 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2233 hh, mm, ss, thh, tmm, tss);
2234 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2235 }
2236 break;
01310af2
FB
2237 case SDL_VIDEORESIZE:
2238 if (cur_stream) {
115329f1 2239 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2
FB
2240 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2241 cur_stream->width = event.resize.w;
2242 cur_stream->height = event.resize.h;
2243 }
2244 break;
2245 case SDL_QUIT:
638c9d91 2246 case FF_QUIT_EVENT:
01310af2
FB
2247 do_exit();
2248 break;
2249 case FF_ALLOC_EVENT:
2250 alloc_picture(event.user.data1);
2251 break;
2252 case FF_REFRESH_EVENT:
2253 video_refresh_timer(event.user.data1);
2254 break;
2255 default:
2256 break;
2257 }
2258 }
2259}
2260
2261void opt_width(const char *arg)
2262{
2263 screen_width = atoi(arg);
2264}
2265
2266void opt_height(const char *arg)
2267{
2268 screen_height = atoi(arg);
2269}
2270
2271static void opt_format(const char *arg)
2272{
2273 file_iformat = av_find_input_format(arg);
2274 if (!file_iformat) {
2275 fprintf(stderr, "Unknown input format: %s\n", arg);
2276 exit(1);
2277 }
2278}
61890b02
FB
2279
2280static void opt_image_format(const char *arg)
2281{
2282 AVImageFormat *f;
115329f1 2283
61890b02
FB
2284 for(f = first_image_format; f != NULL; f = f->next) {
2285 if (!strcmp(arg, f->name))
2286 break;
2287 }
2288 if (!f) {
2289 fprintf(stderr, "Unknown image format: '%s'\n", arg);
2290 exit(1);
2291 }
2292 image_format = f;
2293}
2294
400738b1 2295#ifdef CONFIG_NETWORK
416e3508
FB
2296void opt_rtp_tcp(void)
2297{
2298 /* only tcp protocol */
2299 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
2300}
400738b1 2301#endif
416e3508 2302
638c9d91
FB
2303void opt_sync(const char *arg)
2304{
2305 if (!strcmp(arg, "audio"))
2306 av_sync_type = AV_SYNC_AUDIO_MASTER;
2307 else if (!strcmp(arg, "video"))
2308 av_sync_type = AV_SYNC_VIDEO_MASTER;
2309 else if (!strcmp(arg, "ext"))
2310 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2311 else
2312 show_help();
2313}
2314
72ea344b
FB
2315void opt_seek(const char *arg)
2316{
2317 start_time = parse_date(arg, 1);
2318}
2319
e26a8335
WH
2320static void opt_debug(const char *arg)
2321{
2322 debug = atoi(arg);
2323}
115329f1 2324
0c9bbaec
WH
2325static void opt_vismv(const char *arg)
2326{
2327 debug_mv = atoi(arg);
2328}
c62c07d3
MN
2329
2330static void opt_thread_count(const char *arg)
2331{
2332 thread_count= atoi(arg);
2450cff2 2333#if !defined(HAVE_THREADS)
c62c07d3
MN
2334 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2335#endif
2336}
115329f1 2337
01310af2 2338const OptionDef options[] = {
115329f1 2339 { "h", 0, {(void*)show_help}, "show help" },
01310af2
FB
2340 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
2341 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
638c9d91 2342 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2343 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2344 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
72ea344b 2345 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
01310af2
FB
2346 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2347 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
61890b02 2348 { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
01310af2 2349 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
e26a8335 2350 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2351 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
0c9bbaec 2352 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2353 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2354 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
178fcca8 2355 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2356 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2357 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2358 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2359 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
1b51e051
MN
2360 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
2361 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
400738b1 2362#ifdef CONFIG_NETWORK
416e3508 2363 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
400738b1 2364#endif
c62c07d3
MN
2365 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2366 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
01310af2
FB
2367 { NULL, },
2368};
2369
2370void show_help(void)
2371{
02d504a7
FB
2372 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
2373 "usage: ffplay [options] input_file\n"
01310af2
FB
2374 "Simple media player\n");
2375 printf("\n");
02d504a7
FB
2376 show_help_options(options, "Main options:\n",
2377 OPT_EXPERT, 0);
2378 show_help_options(options, "\nAdvanced options:\n",
2379 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2380 printf("\nWhile playing:\n"
2381 "q, ESC quit\n"
2382 "f toggle full screen\n"
2383 "p, SPC pause\n"
638c9d91
FB
2384 "a cycle audio channel\n"
2385 "v cycle video channel\n"
72ce053b 2386 "t cycle subtitle channel\n"
638c9d91 2387 "w show audio waves\n"
72ea344b
FB
2388 "left/right seek backward/forward 10 seconds\n"
2389 "down/up seek backward/forward 1 minute\n"
a11d11aa 2390 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2
FB
2391 );
2392 exit(1);
2393}
2394
2395void parse_arg_file(const char *filename)
2396{
e8d83e1c
MN
2397 if (!strcmp(filename, "-"))
2398 filename = "pipe:";
01310af2
FB
2399 input_filename = filename;
2400}
2401
2402/* Called from the main */
2403int main(int argc, char **argv)
2404{
638c9d91 2405 int flags, w, h;
115329f1 2406
01310af2
FB
2407 /* register all codecs, demux and protocols */
2408 av_register_all();
2409
3ca4b654
MN
2410 #ifdef CONFIG_OS2
2411 MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
115329f1 2412
3ca4b654
MN
2413 // Make stdout and stderr unbuffered
2414 setbuf( stdout, NULL );
2415 setbuf( stderr, NULL );
2416 #endif
2417
01310af2
FB
2418 parse_options(argc, argv, options);
2419
2420 if (!input_filename)
2421 show_help();
2422
2423 if (display_disable) {
2424 video_disable = 1;
2425 }
31319a8c 2426 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
4b0e85d4
EL
2427#if !defined(CONFIG_WIN32) && !defined(CONFIG_DARWIN)
2428 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 or darwin */
31319a8c 2429#endif
01310af2 2430 if (SDL_Init (flags)) {
05ab0b76 2431 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2432 exit(1);
2433 }
2434
2435 if (!display_disable) {
29f3b38a 2436#ifdef HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2437 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2438 fs_screen_width = vi->current_w;
2439 fs_screen_height = vi->current_h;
29f3b38a 2440#endif
638c9d91
FB
2441 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2442 if (is_full_screen && fs_screen_width) {
2443 w = fs_screen_width;
2444 h = fs_screen_height;
2445 flags |= SDL_FULLSCREEN;
2446 } else {
2447 w = screen_width;
2448 h = screen_height;
2449 flags |= SDL_RESIZABLE;
2450 }
4b0e85d4 2451#ifndef CONFIG_DARWIN
638c9d91 2452 screen = SDL_SetVideoMode(w, h, 0, flags);
4b0e85d4
EL
2453#else
2454 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
2455 screen = SDL_SetVideoMode(w, h, 24, flags);
2456#endif
638c9d91
FB
2457 if (!screen) {
2458 fprintf(stderr, "SDL: could not set video mode - exiting\n");
2459 exit(1);
2460 }
2461 SDL_WM_SetCaption("FFplay", "FFplay");
01310af2
FB
2462 }
2463
2464 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2465 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2466 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2467 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2468
638c9d91 2469 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2470
2471 event_loop();
2472
2473 /* never returns */
2474
2475 return 0;
2476}