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