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