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