check x/y validity
[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
990c8438
MN
832static int video_open(VideoState *is){
833 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
834 int w,h;
835
836 if (is_full_screen && fs_screen_width) {
837 w = fs_screen_width;
838 h = fs_screen_height;
839 flags |= SDL_FULLSCREEN;
840 } else {
841 if(screen_width){
842 w = screen_width;
843 h = screen_height;
844 }else if (is->video_st && is->video_st->codec->width){
845 w = is->video_st->codec->width;
846 h = is->video_st->codec->height;
847 } else {
848 w = 640;
849 h = 480;
850 }
851 flags |= SDL_RESIZABLE;
852 }
853#ifndef CONFIG_DARWIN
854 screen = SDL_SetVideoMode(w, h, 0, flags);
855#else
856 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
857 screen = SDL_SetVideoMode(w, h, 24, flags);
858#endif
859 if (!screen) {
860 fprintf(stderr, "SDL: could not set video mode - exiting\n");
861 return -1;
862 }
863 SDL_WM_SetCaption("FFplay", "FFplay");
864
865 is->width = screen->w;
866 is->height = screen->h;
867
868 return 0;
869}
8c982c5d 870
01310af2
FB
871/* display the current picture, if any */
872static void video_display(VideoState *is)
873{
8c982c5d
MN
874 if(!screen)
875 video_open(cur_stream);
115329f1 876 if (is->audio_st && is->show_audio)
01310af2
FB
877 video_audio_display(is);
878 else if (is->video_st)
879 video_image_display(is);
880}
881
882static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
883{
884 SDL_Event event;
885 event.type = FF_REFRESH_EVENT;
886 event.user.data1 = opaque;
887 SDL_PushEvent(&event);
888 return 0; /* 0 means stop timer */
889}
890
891/* schedule a video refresh in 'delay' ms */
892static void schedule_refresh(VideoState *is, int delay)
893{
894 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
895}
896
638c9d91
FB
897/* get the current audio clock value */
898static double get_audio_clock(VideoState *is)
899{
900 double pts;
901 int hw_buf_size, bytes_per_sec;
902 pts = is->audio_clock;
903 hw_buf_size = audio_write_get_buf_size(is);
904 bytes_per_sec = 0;
905 if (is->audio_st) {
115329f1 906 bytes_per_sec = is->audio_st->codec->sample_rate *
01f4895c 907 2 * is->audio_st->codec->channels;
638c9d91
FB
908 }
909 if (bytes_per_sec)
910 pts -= (double)hw_buf_size / bytes_per_sec;
911 return pts;
912}
913
914/* get the current video clock value */
915static double get_video_clock(VideoState *is)
916{
917 double delta;
04108619 918 if (is->paused) {
72ea344b
FB
919 delta = 0;
920 } else {
921 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
922 }
638c9d91
FB
923 return is->video_current_pts + delta;
924}
925
926/* get the current external clock value */
927static double get_external_clock(VideoState *is)
928{
929 int64_t ti;
930 ti = av_gettime();
931 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
932}
933
934/* get the current master clock value */
935static double get_master_clock(VideoState *is)
936{
937 double val;
938
72ea344b
FB
939 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
940 if (is->video_st)
941 val = get_video_clock(is);
942 else
943 val = get_audio_clock(is);
944 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
945 if (is->audio_st)
946 val = get_audio_clock(is);
947 else
948 val = get_video_clock(is);
949 } else {
638c9d91 950 val = get_external_clock(is);
72ea344b 951 }
638c9d91
FB
952 return val;
953}
954
72ea344b 955/* seek in the stream */
3ba1438d 956static void stream_seek(VideoState *is, int64_t pos, int rel)
72ea344b 957{
687fae2b
IW
958 if (!is->seek_req) {
959 is->seek_pos = pos;
960 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
94b594c6
SH
961 if (seek_by_bytes)
962 is->seek_flags |= AVSEEK_FLAG_BYTE;
687fae2b
IW
963 is->seek_req = 1;
964 }
72ea344b
FB
965}
966
967/* pause or resume the video */
968static void stream_pause(VideoState *is)
969{
970 is->paused = !is->paused;
971 if (is->paused) {
972 is->video_current_pts = get_video_clock(is);
973 }
974}
975
01310af2
FB
976/* called to display each frame */
977static void video_refresh_timer(void *opaque)
978{
979 VideoState *is = opaque;
980 VideoPicture *vp;
638c9d91
FB
981 double actual_delay, delay, sync_threshold, ref_clock, diff;
982
72ce053b 983 SubPicture *sp, *sp2;
01310af2
FB
984
985 if (is->video_st) {
986 if (is->pictq_size == 0) {
987 /* if no picture, need to wait */
7e0140cb 988 schedule_refresh(is, 1);
01310af2 989 } else {
638c9d91 990 /* dequeue the picture */
01310af2 991 vp = &is->pictq[is->pictq_rindex];
638c9d91
FB
992
993 /* update current video pts */
994 is->video_current_pts = vp->pts;
995 is->video_current_pts_time = av_gettime();
996
997 /* compute nominal delay */
998 delay = vp->pts - is->frame_last_pts;
999 if (delay <= 0 || delay >= 1.0) {
1000 /* if incorrect delay, use previous one */
1001 delay = is->frame_last_delay;
1002 }
1003 is->frame_last_delay = delay;
1004 is->frame_last_pts = vp->pts;
1005
1006 /* update delay to follow master synchronisation source */
1007 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1008 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1009 /* if video is slave, we try to correct big delays by
1010 duplicating or deleting a frame */
1011 ref_clock = get_master_clock(is);
1012 diff = vp->pts - ref_clock;
115329f1 1013
638c9d91
FB
1014 /* skip or repeat frame. We take into account the
1015 delay to compute the threshold. I still don't know
1016 if it is the best guess */
1017 sync_threshold = AV_SYNC_THRESHOLD;
1018 if (delay > sync_threshold)
1019 sync_threshold = delay;
1020 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1021 if (diff <= -sync_threshold)
1022 delay = 0;
1023 else if (diff >= sync_threshold)
1024 delay = 2 * delay;
1025 }
1026 }
1027
1028 is->frame_timer += delay;
1029 /* compute the REAL delay (we need to do that to avoid
1030 long term errors */
1031 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
1032 if (actual_delay < 0.010) {
1033 /* XXX: should skip picture */
1034 actual_delay = 0.010;
1035 }
01310af2 1036 /* launch timer for next picture */
638c9d91
FB
1037 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
1038
1039#if defined(DEBUG_SYNC)
115329f1 1040 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
638c9d91
FB
1041 delay, actual_delay, vp->pts, -diff);
1042#endif
01310af2 1043
72ce053b
IC
1044 if(is->subtitle_st) {
1045 if (is->subtitle_stream_changed) {
1046 SDL_LockMutex(is->subpq_mutex);
115329f1 1047
72ce053b
IC
1048 while (is->subpq_size) {
1049 free_subpicture(&is->subpq[is->subpq_rindex]);
115329f1 1050
72ce053b
IC
1051 /* update queue size and signal for next picture */
1052 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1053 is->subpq_rindex = 0;
115329f1 1054
72ce053b
IC
1055 is->subpq_size--;
1056 }
1057 is->subtitle_stream_changed = 0;
1058
1059 SDL_CondSignal(is->subpq_cond);
1060 SDL_UnlockMutex(is->subpq_mutex);
1061 } else {
1062 if (is->subpq_size > 0) {
1063 sp = &is->subpq[is->subpq_rindex];
1064
1065 if (is->subpq_size > 1)
1066 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1067 else
1068 sp2 = NULL;
1069
1070 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1071 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1072 {
1073 free_subpicture(sp);
1074
1075 /* update queue size and signal for next picture */
1076 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1077 is->subpq_rindex = 0;
1078
1079 SDL_LockMutex(is->subpq_mutex);
1080 is->subpq_size--;
1081 SDL_CondSignal(is->subpq_cond);
1082 SDL_UnlockMutex(is->subpq_mutex);
1083 }
1084 }
1085 }
1086 }
1087
01310af2
FB
1088 /* display picture */
1089 video_display(is);
115329f1 1090
01310af2
FB
1091 /* update queue size and signal for next picture */
1092 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1093 is->pictq_rindex = 0;
115329f1 1094
01310af2
FB
1095 SDL_LockMutex(is->pictq_mutex);
1096 is->pictq_size--;
1097 SDL_CondSignal(is->pictq_cond);
1098 SDL_UnlockMutex(is->pictq_mutex);
1099 }
1100 } else if (is->audio_st) {
1101 /* draw the next audio frame */
1102
1103 schedule_refresh(is, 40);
1104
1105 /* if only audio stream, then display the audio bars (better
1106 than nothing, just to test the implementation */
115329f1 1107
01310af2
FB
1108 /* display picture */
1109 video_display(is);
1110 } else {
1111 schedule_refresh(is, 100);
1112 }
1113 if (show_status) {
1114 static int64_t last_time;
1115 int64_t cur_time;
72ce053b 1116 int aqsize, vqsize, sqsize;
638c9d91 1117 double av_diff;
115329f1 1118
01310af2
FB
1119 cur_time = av_gettime();
1120 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1121 aqsize = 0;
1122 vqsize = 0;
72ce053b 1123 sqsize = 0;
01310af2
FB
1124 if (is->audio_st)
1125 aqsize = is->audioq.size;
1126 if (is->video_st)
1127 vqsize = is->videoq.size;
72ce053b
IC
1128 if (is->subtitle_st)
1129 sqsize = is->subtitleq.size;
638c9d91
FB
1130 av_diff = 0;
1131 if (is->audio_st && is->video_st)
1132 av_diff = get_audio_clock(is) - get_video_clock(is);
115329f1 1133 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
72ce053b 1134 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
01310af2
FB
1135 fflush(stdout);
1136 last_time = cur_time;
1137 }
1138 }
1139}
1140
1141/* allocate a picture (needs to do that in main thread to avoid
1142 potential locking problems */
1143static void alloc_picture(void *opaque)
1144{
1145 VideoState *is = opaque;
1146 VideoPicture *vp;
01310af2
FB
1147
1148 vp = &is->pictq[is->pictq_windex];
1149
1150 if (vp->bmp)
1151 SDL_FreeYUVOverlay(vp->bmp);
1152
61890b02 1153#if 0
01310af2 1154 /* XXX: use generic function */
61890b02 1155 /* XXX: disable overlay if no hardware acceleration or if RGB format */
01f4895c 1156 switch(is->video_st->codec->pix_fmt) {
01310af2
FB
1157 case PIX_FMT_YUV420P:
1158 case PIX_FMT_YUV422P:
1159 case PIX_FMT_YUV444P:
1160 case PIX_FMT_YUV422:
1161 case PIX_FMT_YUV410P:
1162 case PIX_FMT_YUV411P:
1163 is_yuv = 1;
1164 break;
1165 default:
1166 is_yuv = 0;
1167 break;
1168 }
01310af2 1169#endif
01f4895c
MN
1170 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1171 is->video_st->codec->height,
115329f1 1172 SDL_YV12_OVERLAY,
61890b02 1173 screen);
01f4895c
MN
1174 vp->width = is->video_st->codec->width;
1175 vp->height = is->video_st->codec->height;
01310af2
FB
1176
1177 SDL_LockMutex(is->pictq_mutex);
1178 vp->allocated = 1;
1179 SDL_CondSignal(is->pictq_cond);
1180 SDL_UnlockMutex(is->pictq_mutex);
1181}
1182
267e9dfa
MN
1183/**
1184 *
1185 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1186 */
638c9d91 1187static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01310af2
FB
1188{
1189 VideoPicture *vp;
1190 int dst_pix_fmt;
1191 AVPicture pict;
03ae87a3 1192 static struct SwsContext *img_convert_ctx;
115329f1 1193
01310af2
FB
1194 /* wait until we have space to put a new picture */
1195 SDL_LockMutex(is->pictq_mutex);
1196 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1197 !is->videoq.abort_request) {
1198 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1199 }
1200 SDL_UnlockMutex(is->pictq_mutex);
115329f1 1201
01310af2
FB
1202 if (is->videoq.abort_request)
1203 return -1;
1204
1205 vp = &is->pictq[is->pictq_windex];
1206
1207 /* alloc or resize hardware picture buffer */
115329f1 1208 if (!vp->bmp ||
01f4895c
MN
1209 vp->width != is->video_st->codec->width ||
1210 vp->height != is->video_st->codec->height) {
01310af2
FB
1211 SDL_Event event;
1212
1213 vp->allocated = 0;
1214
1215 /* the allocation must be done in the main thread to avoid
1216 locking problems */
1217 event.type = FF_ALLOC_EVENT;
1218 event.user.data1 = is;
1219 SDL_PushEvent(&event);
115329f1 1220
01310af2
FB
1221 /* wait until the picture is allocated */
1222 SDL_LockMutex(is->pictq_mutex);
1223 while (!vp->allocated && !is->videoq.abort_request) {
1224 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1225 }
1226 SDL_UnlockMutex(is->pictq_mutex);
1227
1228 if (is->videoq.abort_request)
1229 return -1;
1230 }
1231
638c9d91 1232 /* if the frame is not skipped, then display it */
01310af2
FB
1233 if (vp->bmp) {
1234 /* get a pointer on the bitmap */
1235 SDL_LockYUVOverlay (vp->bmp);
1236
1237 dst_pix_fmt = PIX_FMT_YUV420P;
1238 pict.data[0] = vp->bmp->pixels[0];
1239 pict.data[1] = vp->bmp->pixels[2];
1240 pict.data[2] = vp->bmp->pixels[1];
1241
1242 pict.linesize[0] = vp->bmp->pitches[0];
1243 pict.linesize[1] = vp->bmp->pitches[2];
1244 pict.linesize[2] = vp->bmp->pitches[1];
03ae87a3
LA
1245 if (img_convert_ctx == NULL) {
1246 img_convert_ctx = sws_getContext(is->video_st->codec->width,
1247 is->video_st->codec->height, is->video_st->codec->pix_fmt,
1248 is->video_st->codec->width, is->video_st->codec->height,
1249 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1250 if (img_convert_ctx == NULL) {
1251 fprintf(stderr, "Cannot initialize the conversion context\n");
1252 exit(1);
1253 }
1254 }
1255 sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
1256 0, is->video_st->codec->height, pict.data, pict.linesize);
01310af2
FB
1257 /* update the bitmap content */
1258 SDL_UnlockYUVOverlay(vp->bmp);
1259
638c9d91 1260 vp->pts = pts;
01310af2
FB
1261
1262 /* now we can update the picture count */
1263 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1264 is->pictq_windex = 0;
1265 SDL_LockMutex(is->pictq_mutex);
1266 is->pictq_size++;
1267 SDL_UnlockMutex(is->pictq_mutex);
1268 }
638c9d91
FB
1269 return 0;
1270}
1271
115329f1
DB
1272/**
1273 * compute the exact PTS for the picture if it is omitted in the stream
267e9dfa
MN
1274 * @param pts1 the dts of the pkt / pts of the frame
1275 */
638c9d91
FB
1276static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1277{
1278 double frame_delay, pts;
115329f1 1279
638c9d91
FB
1280 pts = pts1;
1281
01310af2 1282 if (pts != 0) {
638c9d91 1283 /* update video clock with pts, if present */
01310af2
FB
1284 is->video_clock = pts;
1285 } else {
72ea344b
FB
1286 pts = is->video_clock;
1287 }
1288 /* update video clock for next frame */
01f4895c 1289 frame_delay = av_q2d(is->video_st->codec->time_base);
72ea344b
FB
1290 /* for MPEG2, the frame can be repeated, so we update the
1291 clock accordingly */
267e9dfa 1292 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
72ea344b 1293 is->video_clock += frame_delay;
638c9d91
FB
1294
1295#if defined(DEBUG_SYNC) && 0
1296 {
1297 int ftype;
1298 if (src_frame->pict_type == FF_B_TYPE)
1299 ftype = 'B';
1300 else if (src_frame->pict_type == FF_I_TYPE)
1301 ftype = 'I';
1302 else
1303 ftype = 'P';
115329f1 1304 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
72ea344b 1305 ftype, pts, pts1);
638c9d91
FB
1306 }
1307#endif
72ea344b 1308 return queue_picture(is, src_frame, pts);
01310af2
FB
1309}
1310
1311static int video_thread(void *arg)
1312{
1313 VideoState *is = arg;
1314 AVPacket pkt1, *pkt = &pkt1;
72ea344b 1315 int len1, got_picture;
c6b1edc9 1316 AVFrame *frame= avcodec_alloc_frame();
01310af2
FB
1317 double pts;
1318
1319 for(;;) {
1320 while (is->paused && !is->videoq.abort_request) {
1321 SDL_Delay(10);
1322 }
1323 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1324 break;
39c6a118
MN
1325
1326 if(pkt->data == flush_pkt.data){
1327 avcodec_flush_buffers(is->video_st->codec);
1328 continue;
1329 }
1330
638c9d91
FB
1331 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1332 this packet, if any */
72ea344b 1333 pts = 0;
61c1d8e2 1334 if (pkt->dts != AV_NOPTS_VALUE)
c0df9d75 1335 pts = av_q2d(is->video_st->time_base)*pkt->dts;
72ea344b 1336
115329f1
DB
1337 len1 = avcodec_decode_video(is->video_st->codec,
1338 frame, &got_picture,
72ea344b 1339 pkt->data, pkt->size);
fb966f99
MN
1340// if (len1 < 0)
1341// break;
72ea344b
FB
1342 if (got_picture) {
1343 if (output_picture2(is, frame, pts) < 0)
1344 goto the_end;
01310af2 1345 }
01310af2 1346 av_free_packet(pkt);
115329f1 1347 if (step)
bba04f1e
WH
1348 if (cur_stream)
1349 stream_pause(cur_stream);
01310af2
FB
1350 }
1351 the_end:
c6b1edc9 1352 av_free(frame);
01310af2
FB
1353 return 0;
1354}
1355
72ce053b
IC
1356static int subtitle_thread(void *arg)
1357{
1358 VideoState *is = arg;
1359 SubPicture *sp;
1360 AVPacket pkt1, *pkt = &pkt1;
1361 int len1, got_subtitle;
1362 double pts;
1363 int i, j;
1364 int r, g, b, y, u, v, a;
1365
1366 for(;;) {
1367 while (is->paused && !is->subtitleq.abort_request) {
1368 SDL_Delay(10);
1369 }
1370 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1371 break;
115329f1 1372
39c6a118
MN
1373 if(pkt->data == flush_pkt.data){
1374 avcodec_flush_buffers(is->subtitle_st->codec);
1375 continue;
1376 }
72ce053b
IC
1377 SDL_LockMutex(is->subpq_mutex);
1378 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1379 !is->subtitleq.abort_request) {
1380 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1381 }
1382 SDL_UnlockMutex(is->subpq_mutex);
115329f1 1383
72ce053b
IC
1384 if (is->subtitleq.abort_request)
1385 goto the_end;
115329f1 1386
72ce053b
IC
1387 sp = &is->subpq[is->subpq_windex];
1388
1389 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1390 this packet, if any */
1391 pts = 0;
1392 if (pkt->pts != AV_NOPTS_VALUE)
1393 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1394
115329f1
DB
1395 len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
1396 &sp->sub, &got_subtitle,
72ce053b 1397 pkt->data, pkt->size);
72ce053b
IC
1398// if (len1 < 0)
1399// break;
1400 if (got_subtitle && sp->sub.format == 0) {
1401 sp->pts = pts;
115329f1 1402
72ce053b
IC
1403 for (i = 0; i < sp->sub.num_rects; i++)
1404 {
1405 for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
1406 {
1407 RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
1408 y = RGB_TO_Y_CCIR(r, g, b);
1409 u = RGB_TO_U_CCIR(r, g, b, 0);
1410 v = RGB_TO_V_CCIR(r, g, b, 0);
1411 YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
1412 }
1413 }
1414
1415 /* now we can update the picture count */
1416 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1417 is->subpq_windex = 0;
1418 SDL_LockMutex(is->subpq_mutex);
1419 is->subpq_size++;
1420 SDL_UnlockMutex(is->subpq_mutex);
1421 }
1422 av_free_packet(pkt);
115329f1 1423// if (step)
72ce053b
IC
1424// if (cur_stream)
1425// stream_pause(cur_stream);
1426 }
1427 the_end:
1428 return 0;
1429}
1430
01310af2
FB
1431/* copy samples for viewing in editor window */
1432static void update_sample_display(VideoState *is, short *samples, int samples_size)
1433{
1434 int size, len, channels;
1435
01f4895c 1436 channels = is->audio_st->codec->channels;
01310af2
FB
1437
1438 size = samples_size / sizeof(short);
1439 while (size > 0) {
1440 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1441 if (len > size)
1442 len = size;
1443 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1444 samples += len;
1445 is->sample_array_index += len;
1446 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1447 is->sample_array_index = 0;
1448 size -= len;
1449 }
1450}
1451
01310af2
FB
1452/* return the new audio buffer size (samples can be added or deleted
1453 to get better sync if video or external master clock) */
115329f1 1454static int synchronize_audio(VideoState *is, short *samples,
638c9d91 1455 int samples_size1, double pts)
01310af2 1456{
638c9d91 1457 int n, samples_size;
01310af2 1458 double ref_clock;
115329f1 1459
01f4895c 1460 n = 2 * is->audio_st->codec->channels;
638c9d91 1461 samples_size = samples_size1;
01310af2 1462
01310af2 1463 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 1464 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
1465 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1466 double diff, avg_diff;
01310af2 1467 int wanted_size, min_size, max_size, nb_samples;
115329f1 1468
638c9d91
FB
1469 ref_clock = get_master_clock(is);
1470 diff = get_audio_clock(is) - ref_clock;
115329f1 1471
638c9d91
FB
1472 if (diff < AV_NOSYNC_THRESHOLD) {
1473 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1474 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1475 /* not enough measures to have a correct estimate */
1476 is->audio_diff_avg_count++;
1477 } else {
1478 /* estimate the A-V difference */
1479 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1480
1481 if (fabs(avg_diff) >= is->audio_diff_threshold) {
01f4895c 1482 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
638c9d91 1483 nb_samples = samples_size / n;
115329f1 1484
638c9d91
FB
1485 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1486 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1487 if (wanted_size < min_size)
1488 wanted_size = min_size;
1489 else if (wanted_size > max_size)
1490 wanted_size = max_size;
115329f1 1491
638c9d91
FB
1492 /* add or remove samples to correction the synchro */
1493 if (wanted_size < samples_size) {
1494 /* remove samples */
1495 samples_size = wanted_size;
1496 } else if (wanted_size > samples_size) {
1497 uint8_t *samples_end, *q;
1498 int nb;
115329f1 1499
638c9d91
FB
1500 /* add samples */
1501 nb = (samples_size - wanted_size);
1502 samples_end = (uint8_t *)samples + samples_size - n;
1503 q = samples_end + n;
1504 while (nb > 0) {
1505 memcpy(q, samples_end, n);
1506 q += n;
1507 nb -= n;
1508 }
1509 samples_size = wanted_size;
1510 }
1511 }
1512#if 0
115329f1
DB
1513 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1514 diff, avg_diff, samples_size - samples_size1,
638c9d91
FB
1515 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1516#endif
01310af2 1517 }
638c9d91
FB
1518 } else {
1519 /* too big difference : may be initial PTS errors, so
1520 reset A-V filter */
1521 is->audio_diff_avg_count = 0;
1522 is->audio_diff_cum = 0;
01310af2
FB
1523 }
1524 }
1525
01310af2
FB
1526 return samples_size;
1527}
1528
1529/* decode one audio frame and returns its uncompressed size */
1530static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1531{
1532 AVPacket *pkt = &is->audio_pkt;
72ea344b 1533 int n, len1, data_size;
01310af2
FB
1534 double pts;
1535
1536 for(;;) {
72ea344b 1537 /* NOTE: the audio packet can contain several frames */
01310af2 1538 while (is->audio_pkt_size > 0) {
115329f1
DB
1539 len1 = avcodec_decode_audio(is->audio_st->codec,
1540 (int16_t *)audio_buf, &data_size,
01310af2 1541 is->audio_pkt_data, is->audio_pkt_size);
72ea344b
FB
1542 if (len1 < 0) {
1543 /* if error, we skip the frame */
1544 is->audio_pkt_size = 0;
01310af2 1545 break;
72ea344b 1546 }
115329f1 1547
01310af2
FB
1548 is->audio_pkt_data += len1;
1549 is->audio_pkt_size -= len1;
72ea344b
FB
1550 if (data_size <= 0)
1551 continue;
1552 /* if no pts, then compute it */
1553 pts = is->audio_clock;
1554 *pts_ptr = pts;
01f4895c 1555 n = 2 * is->audio_st->codec->channels;
115329f1 1556 is->audio_clock += (double)data_size /
01f4895c 1557 (double)(n * is->audio_st->codec->sample_rate);
638c9d91 1558#if defined(DEBUG_SYNC)
72ea344b
FB
1559 {
1560 static double last_clock;
1561 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1562 is->audio_clock - last_clock,
1563 is->audio_clock, pts);
1564 last_clock = is->audio_clock;
01310af2 1565 }
72ea344b
FB
1566#endif
1567 return data_size;
01310af2
FB
1568 }
1569
72ea344b
FB
1570 /* free the current packet */
1571 if (pkt->data)
01310af2 1572 av_free_packet(pkt);
115329f1 1573
72ea344b
FB
1574 if (is->paused || is->audioq.abort_request) {
1575 return -1;
1576 }
115329f1 1577
01310af2
FB
1578 /* read next packet */
1579 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1580 return -1;
39c6a118
MN
1581 if(pkt->data == flush_pkt.data){
1582 avcodec_flush_buffers(is->audio_st->codec);
1583 continue;
1584 }
1585
01310af2
FB
1586 is->audio_pkt_data = pkt->data;
1587 is->audio_pkt_size = pkt->size;
115329f1 1588
72ea344b
FB
1589 /* if update the audio clock with the pts */
1590 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1591 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1592 }
01310af2
FB
1593 }
1594}
1595
638c9d91
FB
1596/* get the current audio output buffer size, in samples. With SDL, we
1597 cannot have a precise information */
1598static int audio_write_get_buf_size(VideoState *is)
01310af2 1599{
638c9d91 1600 return is->audio_hw_buf_size - is->audio_buf_index;
01310af2
FB
1601}
1602
1603
1604/* prepare a new audio buffer */
1605void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1606{
1607 VideoState *is = opaque;
1608 int audio_size, len1;
1609 double pts;
1610
1611 audio_callback_time = av_gettime();
115329f1 1612
01310af2
FB
1613 while (len > 0) {
1614 if (is->audio_buf_index >= is->audio_buf_size) {
1615 audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1616 if (audio_size < 0) {
1617 /* if error, just output silence */
1618 is->audio_buf_size = 1024;
1619 memset(is->audio_buf, 0, is->audio_buf_size);
1620 } else {
1621 if (is->show_audio)
1622 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
115329f1 1623 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
01310af2
FB
1624 pts);
1625 is->audio_buf_size = audio_size;
1626 }
1627 is->audio_buf_index = 0;
1628 }
1629 len1 = is->audio_buf_size - is->audio_buf_index;
1630 if (len1 > len)
1631 len1 = len;
1632 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1633 len -= len1;
1634 stream += len1;
1635 is->audio_buf_index += len1;
1636 }
1637}
1638
01310af2
FB
1639/* open a given stream. Return 0 if OK */
1640static int stream_component_open(VideoState *is, int stream_index)
1641{
1642 AVFormatContext *ic = is->ic;
1643 AVCodecContext *enc;
1644 AVCodec *codec;
1645 SDL_AudioSpec wanted_spec, spec;
1646
1647 if (stream_index < 0 || stream_index >= ic->nb_streams)
1648 return -1;
01f4895c 1649 enc = ic->streams[stream_index]->codec;
115329f1 1650
01310af2
FB
1651 /* prepare audio output */
1652 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1653 wanted_spec.freq = enc->sample_rate;
1654 wanted_spec.format = AUDIO_S16SYS;
638c9d91
FB
1655 /* hack for AC3. XXX: suppress that */
1656 if (enc->channels > 2)
1657 enc->channels = 2;
01310af2
FB
1658 wanted_spec.channels = enc->channels;
1659 wanted_spec.silence = 0;
638c9d91 1660 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
01310af2
FB
1661 wanted_spec.callback = sdl_audio_callback;
1662 wanted_spec.userdata = is;
638c9d91
FB
1663 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1664 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
01310af2 1665 return -1;
638c9d91 1666 }
01310af2
FB
1667 is->audio_hw_buf_size = spec.size;
1668 }
1669
1670 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1671 enc->debug_mv = debug_mv;
1672 enc->debug = debug;
6387c3e6 1673 enc->workaround_bugs = workaround_bugs;
178fcca8 1674 enc->lowres = lowres;
61846e9a 1675 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1676 enc->idct_algo= idct;
6fc5b059 1677 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
8c3eba7c
MN
1678 enc->skip_frame= skip_frame;
1679 enc->skip_idct= skip_idct;
1680 enc->skip_loop_filter= skip_loop_filter;
1b51e051
MN
1681 enc->error_resilience= error_resilience;
1682 enc->error_concealment= error_concealment;
01310af2
FB
1683 if (!codec ||
1684 avcodec_open(enc, codec) < 0)
1685 return -1;
2450cff2 1686#if defined(HAVE_THREADS)
c62c07d3
MN
1687 if(thread_count>1)
1688 avcodec_thread_init(enc, thread_count);
1689#endif
1690 enc->thread_count= thread_count;
638c9d91 1691 switch(enc->codec_type) {
01310af2
FB
1692 case CODEC_TYPE_AUDIO:
1693 is->audio_stream = stream_index;
1694 is->audio_st = ic->streams[stream_index];
1695 is->audio_buf_size = 0;
1696 is->audio_buf_index = 0;
638c9d91
FB
1697
1698 /* init averaging filter */
1699 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1700 is->audio_diff_avg_count = 0;
1701 /* since we do not have a precise anough audio fifo fullness,
1702 we correct audio sync only if larger than this threshold */
1703 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1704
01310af2
FB
1705 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1706 packet_queue_init(&is->audioq);
bb270c08 1707 SDL_PauseAudio(0);
01310af2
FB
1708 break;
1709 case CODEC_TYPE_VIDEO:
1710 is->video_stream = stream_index;
1711 is->video_st = ic->streams[stream_index];
1712
638c9d91
FB
1713 is->frame_last_delay = 40e-3;
1714 is->frame_timer = (double)av_gettime() / 1000000.0;
638c9d91
FB
1715 is->video_current_pts_time = av_gettime();
1716
01310af2
FB
1717 packet_queue_init(&is->videoq);
1718 is->video_tid = SDL_CreateThread(video_thread, is);
1719 break;
72ce053b
IC
1720 case CODEC_TYPE_SUBTITLE:
1721 is->subtitle_stream = stream_index;
1722 is->subtitle_st = ic->streams[stream_index];
1723 packet_queue_init(&is->subtitleq);
115329f1 1724
72ce053b
IC
1725 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1726 break;
01310af2
FB
1727 default:
1728 break;
1729 }
1730 return 0;
1731}
1732
1733static void stream_component_close(VideoState *is, int stream_index)
1734{
1735 AVFormatContext *ic = is->ic;
1736 AVCodecContext *enc;
115329f1 1737
72ce053b
IC
1738 if (stream_index < 0 || stream_index >= ic->nb_streams)
1739 return;
01f4895c 1740 enc = ic->streams[stream_index]->codec;
01310af2
FB
1741
1742 switch(enc->codec_type) {
1743 case CODEC_TYPE_AUDIO:
1744 packet_queue_abort(&is->audioq);
1745
1746 SDL_CloseAudio();
1747
1748 packet_queue_end(&is->audioq);
1749 break;
1750 case CODEC_TYPE_VIDEO:
1751 packet_queue_abort(&is->videoq);
1752
1753 /* note: we also signal this mutex to make sure we deblock the
1754 video thread in all cases */
1755 SDL_LockMutex(is->pictq_mutex);
1756 SDL_CondSignal(is->pictq_cond);
1757 SDL_UnlockMutex(is->pictq_mutex);
1758
1759 SDL_WaitThread(is->video_tid, NULL);
1760
1761 packet_queue_end(&is->videoq);
1762 break;
72ce053b
IC
1763 case CODEC_TYPE_SUBTITLE:
1764 packet_queue_abort(&is->subtitleq);
115329f1 1765
72ce053b
IC
1766 /* note: we also signal this mutex to make sure we deblock the
1767 video thread in all cases */
1768 SDL_LockMutex(is->subpq_mutex);
1769 is->subtitle_stream_changed = 1;
115329f1 1770
72ce053b
IC
1771 SDL_CondSignal(is->subpq_cond);
1772 SDL_UnlockMutex(is->subpq_mutex);
1773
1774 SDL_WaitThread(is->subtitle_tid, NULL);
1775
1776 packet_queue_end(&is->subtitleq);
1777 break;
01310af2
FB
1778 default:
1779 break;
1780 }
1781
1782 avcodec_close(enc);
1783 switch(enc->codec_type) {
1784 case CODEC_TYPE_AUDIO:
1785 is->audio_st = NULL;
1786 is->audio_stream = -1;
1787 break;
1788 case CODEC_TYPE_VIDEO:
1789 is->video_st = NULL;
1790 is->video_stream = -1;
1791 break;
72ce053b
IC
1792 case CODEC_TYPE_SUBTITLE:
1793 is->subtitle_st = NULL;
1794 is->subtitle_stream = -1;
1795 break;
01310af2
FB
1796 default:
1797 break;
1798 }
1799}
1800
7b49ce2e 1801static void dump_stream_info(const AVFormatContext *s)
d0526ecf
FB
1802{
1803 if (s->track != 0)
1804 fprintf(stderr, "Track: %d\n", s->track);
1805 if (s->title[0] != '\0')
1806 fprintf(stderr, "Title: %s\n", s->title);
1807 if (s->author[0] != '\0')
1808 fprintf(stderr, "Author: %s\n", s->author);
f0861f46
PI
1809 if (s->copyright[0] != '\0')
1810 fprintf(stderr, "Copyright: %s\n", s->copyright);
1811 if (s->comment[0] != '\0')
1812 fprintf(stderr, "Comment: %s\n", s->comment);
d0526ecf
FB
1813 if (s->album[0] != '\0')
1814 fprintf(stderr, "Album: %s\n", s->album);
1815 if (s->year != 0)
1816 fprintf(stderr, "Year: %d\n", s->year);
1817 if (s->genre[0] != '\0')
1818 fprintf(stderr, "Genre: %s\n", s->genre);
1819}
1820
416e3508
FB
1821/* since we have only one decoding thread, we can use a global
1822 variable instead of a thread local variable */
1823static VideoState *global_video_state;
1824
1825static int decode_interrupt_cb(void)
1826{
1827 return (global_video_state && global_video_state->abort_request);
1828}
01310af2
FB
1829
1830/* this thread gets the stream from the disk or the network */
1831static int decode_thread(void *arg)
1832{
1833 VideoState *is = arg;
1834 AVFormatContext *ic;
72ea344b 1835 int err, i, ret, video_index, audio_index, use_play;
01310af2 1836 AVPacket pkt1, *pkt = &pkt1;
61890b02 1837 AVFormatParameters params, *ap = &params;
01310af2
FB
1838
1839 video_index = -1;
1840 audio_index = -1;
1841 is->video_stream = -1;
1842 is->audio_stream = -1;
72ce053b 1843 is->subtitle_stream = -1;
01310af2 1844
416e3508
FB
1845 global_video_state = is;
1846 url_set_interrupt_cb(decode_interrupt_cb);
1847
61890b02 1848 memset(ap, 0, sizeof(*ap));
72ea344b
FB
1849 ap->initial_pause = 1; /* we force a pause when starting an RTSP
1850 stream */
115329f1 1851
61890b02 1852 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1853 if (err < 0) {
1854 print_error(is->filename, err);
1855 ret = -1;
1856 goto fail;
1857 }
01310af2 1858 is->ic = ic;
72ea344b 1859#ifdef CONFIG_NETWORK
d2a067d1 1860 use_play = (ic->iformat == &rtsp_demuxer);
72ea344b
FB
1861#else
1862 use_play = 0;
1863#endif
30bc6613
MN
1864
1865 if(genpts)
1866 ic->flags |= AVFMT_FLAG_GENPTS;
1867
72ea344b
FB
1868 if (!use_play) {
1869 err = av_find_stream_info(ic);
1870 if (err < 0) {
1871 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1872 ret = -1;
1873 goto fail;
1874 }
2536c5fd 1875 ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
638c9d91 1876 }
72ea344b
FB
1877
1878 /* if seeking requested, we execute it */
1879 if (start_time != AV_NOPTS_VALUE) {
1880 int64_t timestamp;
1881
1882 timestamp = start_time;
1883 /* add the stream start time */
1884 if (ic->start_time != AV_NOPTS_VALUE)
1885 timestamp += ic->start_time;
3ba1438d 1886 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
72ea344b 1887 if (ret < 0) {
115329f1 1888 fprintf(stderr, "%s: could not seek to position %0.3f\n",
72ea344b
FB
1889 is->filename, (double)timestamp / AV_TIME_BASE);
1890 }
1891 }
1892
1893 /* now we can begin to play (RTSP stream only) */
1894 av_read_play(ic);
1895
1896 if (use_play) {
1897 err = av_find_stream_info(ic);
1898 if (err < 0) {
1899 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1900 ret = -1;
1901 goto fail;
1902 }
1903 }
1904
01310af2 1905 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1906 AVCodecContext *enc = ic->streams[i]->codec;
01310af2
FB
1907 switch(enc->codec_type) {
1908 case CODEC_TYPE_AUDIO:
1909 if (audio_index < 0 && !audio_disable)
1910 audio_index = i;
1911 break;
1912 case CODEC_TYPE_VIDEO:
1913 if (video_index < 0 && !video_disable)
1914 video_index = i;
1915 break;
1916 default:
1917 break;
1918 }
1919 }
1920 if (show_status) {
1921 dump_format(ic, 0, is->filename, 0);
d0526ecf 1922 dump_stream_info(ic);
01310af2
FB
1923 }
1924
1925 /* open the streams */
1926 if (audio_index >= 0) {
1927 stream_component_open(is, audio_index);
1928 }
1929
1930 if (video_index >= 0) {
1931 stream_component_open(is, video_index);
1932 } else {
1933 if (!display_disable)
1934 is->show_audio = 1;
1935 }
1936
1937 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1938 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1939 ret = -1;
01310af2
FB
1940 goto fail;
1941 }
1942
1943 for(;;) {
1944 if (is->abort_request)
1945 break;
400738b1 1946#ifdef CONFIG_NETWORK
416e3508
FB
1947 if (is->paused != is->last_paused) {
1948 is->last_paused = is->paused;
72ea344b
FB
1949 if (is->paused)
1950 av_read_pause(ic);
1951 else
1952 av_read_play(ic);
416e3508 1953 }
d2a067d1 1954 if (is->paused && ic->iformat == &rtsp_demuxer) {
416e3508
FB
1955 /* wait 10 ms to avoid trying to get another packet */
1956 /* XXX: horrible */
1957 SDL_Delay(10);
1958 continue;
1959 }
400738b1 1960#endif
72ea344b 1961 if (is->seek_req) {
3ba1438d 1962 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
72ea344b
FB
1963 if (ret < 0) {
1964 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
1965 }else{
1966 if (is->audio_stream >= 0) {
1967 packet_queue_flush(&is->audioq);
39c6a118 1968 packet_queue_put(&is->audioq, &flush_pkt);
e6c0297f 1969 }
72ce053b
IC
1970 if (is->subtitle_stream >= 0) {
1971 packet_queue_flush(&is->subtitleq);
39c6a118 1972 packet_queue_put(&is->subtitleq, &flush_pkt);
72ce053b 1973 }
e6c0297f
MN
1974 if (is->video_stream >= 0) {
1975 packet_queue_flush(&is->videoq);
39c6a118 1976 packet_queue_put(&is->videoq, &flush_pkt);
e6c0297f 1977 }
72ea344b
FB
1978 }
1979 is->seek_req = 0;
1980 }
416e3508 1981
01310af2
FB
1982 /* if the queue are full, no need to read more */
1983 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
115329f1
DB
1984 is->videoq.size > MAX_VIDEOQ_SIZE ||
1985 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
0c904df2 1986 url_feof(&ic->pb)) {
01310af2
FB
1987 /* wait 10 ms */
1988 SDL_Delay(10);
1989 continue;
1990 }
72ea344b 1991 ret = av_read_frame(ic, pkt);
01310af2 1992 if (ret < 0) {
bb270c08 1993 if (url_ferror(&ic->pb) == 0) {
6e1f8725 1994 SDL_Delay(100); /* wait for user event */
bb270c08
DB
1995 continue;
1996 } else
1997 break;
01310af2
FB
1998 }
1999 if (pkt->stream_index == is->audio_stream) {
2000 packet_queue_put(&is->audioq, pkt);
2001 } else if (pkt->stream_index == is->video_stream) {
2002 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
2003 } else if (pkt->stream_index == is->subtitle_stream) {
2004 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
2005 } else {
2006 av_free_packet(pkt);
2007 }
2008 }
2009 /* wait until the end */
2010 while (!is->abort_request) {
2011 SDL_Delay(100);
2012 }
2013
638c9d91 2014 ret = 0;
01310af2 2015 fail:
416e3508
FB
2016 /* disable interrupting */
2017 global_video_state = NULL;
2018
01310af2
FB
2019 /* close each stream */
2020 if (is->audio_stream >= 0)
2021 stream_component_close(is, is->audio_stream);
2022 if (is->video_stream >= 0)
2023 stream_component_close(is, is->video_stream);
72ce053b
IC
2024 if (is->subtitle_stream >= 0)
2025 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
2026 if (is->ic) {
2027 av_close_input_file(is->ic);
2028 is->ic = NULL; /* safety */
2029 }
416e3508
FB
2030 url_set_interrupt_cb(NULL);
2031
638c9d91
FB
2032 if (ret != 0) {
2033 SDL_Event event;
115329f1 2034
638c9d91
FB
2035 event.type = FF_QUIT_EVENT;
2036 event.user.data1 = is;
2037 SDL_PushEvent(&event);
2038 }
01310af2
FB
2039 return 0;
2040}
2041
638c9d91 2042static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
2043{
2044 VideoState *is;
2045
2046 is = av_mallocz(sizeof(VideoState));
2047 if (!is)
2048 return NULL;
2049 pstrcpy(is->filename, sizeof(is->filename), filename);
638c9d91 2050 is->iformat = iformat;
01310af2
FB
2051 is->ytop = 0;
2052 is->xleft = 0;
2053
2054 /* start video display */
2055 is->pictq_mutex = SDL_CreateMutex();
2056 is->pictq_cond = SDL_CreateCond();
115329f1 2057
72ce053b
IC
2058 is->subpq_mutex = SDL_CreateMutex();
2059 is->subpq_cond = SDL_CreateCond();
115329f1 2060
01310af2
FB
2061 /* add the refresh timer to draw the picture */
2062 schedule_refresh(is, 40);
2063
638c9d91 2064 is->av_sync_type = av_sync_type;
01310af2
FB
2065 is->parse_tid = SDL_CreateThread(decode_thread, is);
2066 if (!is->parse_tid) {
2067 av_free(is);
2068 return NULL;
2069 }
2070 return is;
2071}
2072
2073static void stream_close(VideoState *is)
2074{
2075 VideoPicture *vp;
2076 int i;
2077 /* XXX: use a special url_shutdown call to abort parse cleanly */
2078 is->abort_request = 1;
2079 SDL_WaitThread(is->parse_tid, NULL);
2080
2081 /* free all pictures */
2082 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2083 vp = &is->pictq[i];
2084 if (vp->bmp) {
2085 SDL_FreeYUVOverlay(vp->bmp);
2086 vp->bmp = NULL;
2087 }
2088 }
2089 SDL_DestroyMutex(is->pictq_mutex);
2090 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2091 SDL_DestroyMutex(is->subpq_mutex);
2092 SDL_DestroyCond(is->subpq_cond);
01310af2
FB
2093}
2094
7b49ce2e 2095static void stream_cycle_channel(VideoState *is, int codec_type)
638c9d91
FB
2096{
2097 AVFormatContext *ic = is->ic;
2098 int start_index, stream_index;
2099 AVStream *st;
2100
2101 if (codec_type == CODEC_TYPE_VIDEO)
2102 start_index = is->video_stream;
72ce053b 2103 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2104 start_index = is->audio_stream;
72ce053b
IC
2105 else
2106 start_index = is->subtitle_stream;
2107 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2108 return;
2109 stream_index = start_index;
2110 for(;;) {
2111 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2112 {
2113 if (codec_type == CODEC_TYPE_SUBTITLE)
2114 {
2115 stream_index = -1;
2116 goto the_end;
2117 } else
2118 stream_index = 0;
2119 }
638c9d91
FB
2120 if (stream_index == start_index)
2121 return;
2122 st = ic->streams[stream_index];
01f4895c 2123 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2124 /* check that parameters are OK */
2125 switch(codec_type) {
2126 case CODEC_TYPE_AUDIO:
01f4895c
MN
2127 if (st->codec->sample_rate != 0 &&
2128 st->codec->channels != 0)
638c9d91
FB
2129 goto the_end;
2130 break;
2131 case CODEC_TYPE_VIDEO:
72ce053b 2132 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2133 goto the_end;
2134 default:
2135 break;
2136 }
2137 }
2138 }
2139 the_end:
2140 stream_component_close(is, start_index);
2141 stream_component_open(is, stream_index);
2142}
2143
2144
7b49ce2e 2145static void toggle_full_screen(void)
01310af2 2146{
01310af2 2147 is_full_screen = !is_full_screen;
29f3b38a
MR
2148 if (!fs_screen_width) {
2149 /* use default SDL method */
2150 SDL_WM_ToggleFullScreen(screen);
01310af2 2151 } else {
29f3b38a 2152 /* use the recorded resolution */
c03312cc 2153 video_open(cur_stream);
01310af2
FB
2154 }
2155}
2156
7b49ce2e 2157static void toggle_pause(void)
01310af2
FB
2158{
2159 if (cur_stream)
2160 stream_pause(cur_stream);
bba04f1e
WH
2161 step = 0;
2162}
2163
7b49ce2e 2164static void step_to_next_frame(void)
bba04f1e
WH
2165{
2166 if (cur_stream) {
2167 if (cur_stream->paused)
2168 cur_stream->paused=0;
2169 cur_stream->video_current_pts = get_video_clock(cur_stream);
2170 }
2171 step = 1;
01310af2
FB
2172}
2173
7b49ce2e 2174static void do_exit(void)
01310af2
FB
2175{
2176 if (cur_stream) {
2177 stream_close(cur_stream);
2178 cur_stream = NULL;
2179 }
2180 if (show_status)
2181 printf("\n");
2182 SDL_Quit();
2183 exit(0);
2184}
2185
7b49ce2e 2186static void toggle_audio_display(void)
01310af2
FB
2187{
2188 if (cur_stream) {
2189 cur_stream->show_audio = !cur_stream->show_audio;
2190 }
2191}
2192
2193/* handle an event sent by the GUI */
7b49ce2e 2194static void event_loop(void)
01310af2
FB
2195{
2196 SDL_Event event;
a11d11aa 2197 double incr, pos, frac;
01310af2
FB
2198
2199 for(;;) {
2200 SDL_WaitEvent(&event);
2201 switch(event.type) {
2202 case SDL_KEYDOWN:
2203 switch(event.key.keysym.sym) {
2204 case SDLK_ESCAPE:
2205 case SDLK_q:
2206 do_exit();
2207 break;
2208 case SDLK_f:
2209 toggle_full_screen();
2210 break;
2211 case SDLK_p:
2212 case SDLK_SPACE:
2213 toggle_pause();
2214 break;
bba04f1e
WH
2215 case SDLK_s: //S: Step to next frame
2216 step_to_next_frame();
2217 break;
01310af2 2218 case SDLK_a:
115329f1 2219 if (cur_stream)
638c9d91
FB
2220 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2221 break;
2222 case SDLK_v:
115329f1 2223 if (cur_stream)
638c9d91
FB
2224 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2225 break;
72ce053b 2226 case SDLK_t:
115329f1 2227 if (cur_stream)
72ce053b
IC
2228 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2229 break;
638c9d91 2230 case SDLK_w:
01310af2
FB
2231 toggle_audio_display();
2232 break;
72ea344b
FB
2233 case SDLK_LEFT:
2234 incr = -10.0;
2235 goto do_seek;
2236 case SDLK_RIGHT:
2237 incr = 10.0;
2238 goto do_seek;
2239 case SDLK_UP:
2240 incr = 60.0;
2241 goto do_seek;
2242 case SDLK_DOWN:
2243 incr = -60.0;
2244 do_seek:
2245 if (cur_stream) {
94b594c6
SH
2246 if (seek_by_bytes) {
2247 pos = url_ftell(&cur_stream->ic->pb);
2248 if (cur_stream->ic->bit_rate)
2249 incr *= cur_stream->ic->bit_rate / 60.0;
2250 else
2251 incr *= 180000.0;
2252 pos += incr;
2253 stream_seek(cur_stream, pos, incr);
2254 } else {
2255 pos = get_master_clock(cur_stream);
2256 pos += incr;
2257 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
2258 }
72ea344b
FB
2259 }
2260 break;
01310af2
FB
2261 default:
2262 break;
2263 }
2264 break;
a11d11aa 2265 case SDL_MOUSEBUTTONDOWN:
bb270c08
DB
2266 if (cur_stream) {
2267 int ns, hh, mm, ss;
2268 int tns, thh, tmm, tss;
2269 tns = cur_stream->ic->duration/1000000LL;
2270 thh = tns/3600;
2271 tmm = (tns%3600)/60;
2272 tss = (tns%60);
2273 frac = (double)event.button.x/(double)cur_stream->width;
2274 ns = frac*tns;
2275 hh = ns/3600;
2276 mm = (ns%3600)/60;
2277 ss = (ns%60);
2278 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2279 hh, mm, ss, thh, tmm, tss);
2280 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2281 }
2282 break;
01310af2
FB
2283 case SDL_VIDEORESIZE:
2284 if (cur_stream) {
115329f1 2285 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2
FB
2286 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2287 cur_stream->width = event.resize.w;
2288 cur_stream->height = event.resize.h;
2289 }
2290 break;
2291 case SDL_QUIT:
638c9d91 2292 case FF_QUIT_EVENT:
01310af2
FB
2293 do_exit();
2294 break;
2295 case FF_ALLOC_EVENT:
fccb19e3 2296 video_open(event.user.data1);
01310af2
FB
2297 alloc_picture(event.user.data1);
2298 break;
2299 case FF_REFRESH_EVENT:
2300 video_refresh_timer(event.user.data1);
2301 break;
2302 default:
2303 break;
2304 }
2305 }
2306}
2307
2308void opt_width(const char *arg)
2309{
2310 screen_width = atoi(arg);
cfe9cfed
MN
2311 if(screen_width<=0){
2312 fprintf(stderr, "invalid width\n");
2313 exit(1);
2314 }
01310af2
FB
2315}
2316
2317void opt_height(const char *arg)
2318{
2319 screen_height = atoi(arg);
cfe9cfed
MN
2320 if(screen_height<=0){
2321 fprintf(stderr, "invalid height\n");
2322 exit(1);
2323 }
01310af2
FB
2324}
2325
2326static void opt_format(const char *arg)
2327{
2328 file_iformat = av_find_input_format(arg);
2329 if (!file_iformat) {
2330 fprintf(stderr, "Unknown input format: %s\n", arg);
2331 exit(1);
2332 }
2333}
61890b02 2334
400738b1 2335#ifdef CONFIG_NETWORK
416e3508
FB
2336void opt_rtp_tcp(void)
2337{
2338 /* only tcp protocol */
2339 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
2340}
400738b1 2341#endif
416e3508 2342
638c9d91
FB
2343void opt_sync(const char *arg)
2344{
2345 if (!strcmp(arg, "audio"))
2346 av_sync_type = AV_SYNC_AUDIO_MASTER;
2347 else if (!strcmp(arg, "video"))
2348 av_sync_type = AV_SYNC_VIDEO_MASTER;
2349 else if (!strcmp(arg, "ext"))
2350 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2351 else
2352 show_help();
2353}
2354
72ea344b
FB
2355void opt_seek(const char *arg)
2356{
2357 start_time = parse_date(arg, 1);
2358}
2359
e26a8335
WH
2360static void opt_debug(const char *arg)
2361{
0540cad3 2362 av_log_set_level(99);
e26a8335
WH
2363 debug = atoi(arg);
2364}
115329f1 2365
0c9bbaec
WH
2366static void opt_vismv(const char *arg)
2367{
2368 debug_mv = atoi(arg);
2369}
c62c07d3
MN
2370
2371static void opt_thread_count(const char *arg)
2372{
2373 thread_count= atoi(arg);
2450cff2 2374#if !defined(HAVE_THREADS)
c62c07d3
MN
2375 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2376#endif
2377}
115329f1 2378
01310af2 2379const OptionDef options[] = {
115329f1 2380 { "h", 0, {(void*)show_help}, "show help" },
01310af2
FB
2381 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
2382 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
638c9d91 2383 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2384 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2385 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
72ea344b 2386 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
94b594c6 2387 { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
01310af2
FB
2388 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2389 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
2390 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
e26a8335 2391 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2392 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
0c9bbaec 2393 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2394 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2395 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
178fcca8 2396 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2397 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2398 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2399 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2400 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
1b51e051
MN
2401 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
2402 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
400738b1 2403#ifdef CONFIG_NETWORK
416e3508 2404 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
400738b1 2405#endif
c62c07d3
MN
2406 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2407 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
01310af2
FB
2408 { NULL, },
2409};
2410
2411void show_help(void)
2412{
3e66a740 2413 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard, et al.\n"
02d504a7 2414 "usage: ffplay [options] input_file\n"
01310af2
FB
2415 "Simple media player\n");
2416 printf("\n");
02d504a7
FB
2417 show_help_options(options, "Main options:\n",
2418 OPT_EXPERT, 0);
2419 show_help_options(options, "\nAdvanced options:\n",
2420 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2421 printf("\nWhile playing:\n"
2422 "q, ESC quit\n"
2423 "f toggle full screen\n"
2424 "p, SPC pause\n"
638c9d91
FB
2425 "a cycle audio channel\n"
2426 "v cycle video channel\n"
72ce053b 2427 "t cycle subtitle channel\n"
638c9d91 2428 "w show audio waves\n"
72ea344b
FB
2429 "left/right seek backward/forward 10 seconds\n"
2430 "down/up seek backward/forward 1 minute\n"
a11d11aa 2431 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2
FB
2432 );
2433 exit(1);
2434}
2435
2436void parse_arg_file(const char *filename)
2437{
e8d83e1c
MN
2438 if (!strcmp(filename, "-"))
2439 filename = "pipe:";
01310af2
FB
2440 input_filename = filename;
2441}
2442
2443/* Called from the main */
2444int main(int argc, char **argv)
2445{
fccb19e3 2446 int flags;
115329f1 2447
01310af2
FB
2448 /* register all codecs, demux and protocols */
2449 av_register_all();
2450
3ca4b654
MN
2451 #ifdef CONFIG_OS2
2452 MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
115329f1 2453
3ca4b654
MN
2454 // Make stdout and stderr unbuffered
2455 setbuf( stdout, NULL );
2456 setbuf( stderr, NULL );
2457 #endif
2458
01310af2
FB
2459 parse_options(argc, argv, options);
2460
2461 if (!input_filename)
2462 show_help();
2463
2464 if (display_disable) {
2465 video_disable = 1;
2466 }
31319a8c 2467 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2f30a81d 2468#if !defined(__MINGW32__) && !defined(CONFIG_DARWIN)
4b0e85d4 2469 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 or darwin */
31319a8c 2470#endif
01310af2 2471 if (SDL_Init (flags)) {
05ab0b76 2472 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2473 exit(1);
2474 }
2475
2476 if (!display_disable) {
29f3b38a 2477#ifdef HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2478 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2479 fs_screen_width = vi->current_w;
2480 fs_screen_height = vi->current_h;
29f3b38a 2481#endif
01310af2
FB
2482 }
2483
2484 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2485 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2486 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2487 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2488
39c6a118
MN
2489 av_init_packet(&flush_pkt);
2490 flush_pkt.data= "FLUSH";
2491
638c9d91 2492 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2493
2494 event_loop();
2495
2496 /* never returns */
2497
2498 return 0;
2499}