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