Move output_example.c and ffplay.c to the swscale interface
[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 */
115329f1 136 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);
1758 if (s->album[0] != '\0')
1759 fprintf(stderr, "Album: %s\n", s->album);
1760 if (s->year != 0)
1761 fprintf(stderr, "Year: %d\n", s->year);
1762 if (s->genre[0] != '\0')
1763 fprintf(stderr, "Genre: %s\n", s->genre);
1764}
1765
416e3508
FB
1766/* since we have only one decoding thread, we can use a global
1767 variable instead of a thread local variable */
1768static VideoState *global_video_state;
1769
1770static int decode_interrupt_cb(void)
1771{
1772 return (global_video_state && global_video_state->abort_request);
1773}
01310af2
FB
1774
1775/* this thread gets the stream from the disk or the network */
1776static int decode_thread(void *arg)
1777{
1778 VideoState *is = arg;
1779 AVFormatContext *ic;
72ea344b 1780 int err, i, ret, video_index, audio_index, use_play;
01310af2 1781 AVPacket pkt1, *pkt = &pkt1;
61890b02 1782 AVFormatParameters params, *ap = &params;
01310af2
FB
1783
1784 video_index = -1;
1785 audio_index = -1;
1786 is->video_stream = -1;
1787 is->audio_stream = -1;
72ce053b 1788 is->subtitle_stream = -1;
01310af2 1789
416e3508
FB
1790 global_video_state = is;
1791 url_set_interrupt_cb(decode_interrupt_cb);
1792
61890b02
FB
1793 memset(ap, 0, sizeof(*ap));
1794 ap->image_format = image_format;
72ea344b
FB
1795 ap->initial_pause = 1; /* we force a pause when starting an RTSP
1796 stream */
115329f1 1797
61890b02 1798 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1799 if (err < 0) {
1800 print_error(is->filename, err);
1801 ret = -1;
1802 goto fail;
1803 }
01310af2 1804 is->ic = ic;
72ea344b 1805#ifdef CONFIG_NETWORK
d2a067d1 1806 use_play = (ic->iformat == &rtsp_demuxer);
72ea344b
FB
1807#else
1808 use_play = 0;
1809#endif
30bc6613
MN
1810
1811 if(genpts)
1812 ic->flags |= AVFMT_FLAG_GENPTS;
1813
72ea344b
FB
1814 if (!use_play) {
1815 err = av_find_stream_info(ic);
1816 if (err < 0) {
1817 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1818 ret = -1;
1819 goto fail;
1820 }
2536c5fd 1821 ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
638c9d91 1822 }
72ea344b
FB
1823
1824 /* if seeking requested, we execute it */
1825 if (start_time != AV_NOPTS_VALUE) {
1826 int64_t timestamp;
1827
1828 timestamp = start_time;
1829 /* add the stream start time */
1830 if (ic->start_time != AV_NOPTS_VALUE)
1831 timestamp += ic->start_time;
3ba1438d 1832 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
72ea344b 1833 if (ret < 0) {
115329f1 1834 fprintf(stderr, "%s: could not seek to position %0.3f\n",
72ea344b
FB
1835 is->filename, (double)timestamp / AV_TIME_BASE);
1836 }
1837 }
1838
1839 /* now we can begin to play (RTSP stream only) */
1840 av_read_play(ic);
1841
1842 if (use_play) {
1843 err = av_find_stream_info(ic);
1844 if (err < 0) {
1845 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1846 ret = -1;
1847 goto fail;
1848 }
1849 }
1850
01310af2 1851 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1852 AVCodecContext *enc = ic->streams[i]->codec;
01310af2
FB
1853 switch(enc->codec_type) {
1854 case CODEC_TYPE_AUDIO:
1855 if (audio_index < 0 && !audio_disable)
1856 audio_index = i;
1857 break;
1858 case CODEC_TYPE_VIDEO:
1859 if (video_index < 0 && !video_disable)
1860 video_index = i;
1861 break;
1862 default:
1863 break;
1864 }
1865 }
1866 if (show_status) {
1867 dump_format(ic, 0, is->filename, 0);
d0526ecf 1868 dump_stream_info(ic);
01310af2
FB
1869 }
1870
1871 /* open the streams */
1872 if (audio_index >= 0) {
1873 stream_component_open(is, audio_index);
1874 }
1875
1876 if (video_index >= 0) {
1877 stream_component_open(is, video_index);
1878 } else {
1879 if (!display_disable)
1880 is->show_audio = 1;
1881 }
1882
1883 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1884 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1885 ret = -1;
01310af2
FB
1886 goto fail;
1887 }
1888
1889 for(;;) {
1890 if (is->abort_request)
1891 break;
400738b1 1892#ifdef CONFIG_NETWORK
416e3508
FB
1893 if (is->paused != is->last_paused) {
1894 is->last_paused = is->paused;
72ea344b
FB
1895 if (is->paused)
1896 av_read_pause(ic);
1897 else
1898 av_read_play(ic);
416e3508 1899 }
d2a067d1 1900 if (is->paused && ic->iformat == &rtsp_demuxer) {
416e3508
FB
1901 /* wait 10 ms to avoid trying to get another packet */
1902 /* XXX: horrible */
1903 SDL_Delay(10);
1904 continue;
1905 }
400738b1 1906#endif
72ea344b
FB
1907 if (is->seek_req) {
1908 /* XXX: must lock decoder threads */
687fae2b
IW
1909 SDL_LockMutex(is->video_decoder_mutex);
1910 SDL_LockMutex(is->audio_decoder_mutex);
72ce053b 1911 SDL_LockMutex(is->subtitle_decoder_mutex);
3ba1438d 1912 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
72ea344b
FB
1913 if (ret < 0) {
1914 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
1915 }else{
1916 if (is->audio_stream >= 0) {
1917 packet_queue_flush(&is->audioq);
1918 }
72ce053b
IC
1919 if (is->subtitle_stream >= 0) {
1920 packet_queue_flush(&is->subtitleq);
1921 }
e6c0297f
MN
1922 if (is->video_stream >= 0) {
1923 packet_queue_flush(&is->videoq);
01f4895c 1924 avcodec_flush_buffers(ic->streams[video_index]->codec);
e6c0297f 1925 }
72ea344b 1926 }
72ce053b 1927 SDL_UnlockMutex(is->subtitle_decoder_mutex);
687fae2b
IW
1928 SDL_UnlockMutex(is->audio_decoder_mutex);
1929 SDL_UnlockMutex(is->video_decoder_mutex);
72ea344b
FB
1930 is->seek_req = 0;
1931 }
416e3508 1932
01310af2
FB
1933 /* if the queue are full, no need to read more */
1934 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
115329f1
DB
1935 is->videoq.size > MAX_VIDEOQ_SIZE ||
1936 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
0c904df2 1937 url_feof(&ic->pb)) {
01310af2
FB
1938 /* wait 10 ms */
1939 SDL_Delay(10);
1940 continue;
1941 }
72ea344b 1942 ret = av_read_frame(ic, pkt);
01310af2 1943 if (ret < 0) {
bb270c08 1944 if (url_ferror(&ic->pb) == 0) {
6e1f8725 1945 SDL_Delay(100); /* wait for user event */
bb270c08
DB
1946 continue;
1947 } else
1948 break;
01310af2
FB
1949 }
1950 if (pkt->stream_index == is->audio_stream) {
1951 packet_queue_put(&is->audioq, pkt);
1952 } else if (pkt->stream_index == is->video_stream) {
1953 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
1954 } else if (pkt->stream_index == is->subtitle_stream) {
1955 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
1956 } else {
1957 av_free_packet(pkt);
1958 }
1959 }
1960 /* wait until the end */
1961 while (!is->abort_request) {
1962 SDL_Delay(100);
1963 }
1964
638c9d91 1965 ret = 0;
01310af2 1966 fail:
416e3508
FB
1967 /* disable interrupting */
1968 global_video_state = NULL;
1969
01310af2
FB
1970 /* close each stream */
1971 if (is->audio_stream >= 0)
1972 stream_component_close(is, is->audio_stream);
1973 if (is->video_stream >= 0)
1974 stream_component_close(is, is->video_stream);
72ce053b
IC
1975 if (is->subtitle_stream >= 0)
1976 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
1977 if (is->ic) {
1978 av_close_input_file(is->ic);
1979 is->ic = NULL; /* safety */
1980 }
416e3508
FB
1981 url_set_interrupt_cb(NULL);
1982
638c9d91
FB
1983 if (ret != 0) {
1984 SDL_Event event;
115329f1 1985
638c9d91
FB
1986 event.type = FF_QUIT_EVENT;
1987 event.user.data1 = is;
1988 SDL_PushEvent(&event);
1989 }
01310af2
FB
1990 return 0;
1991}
1992
638c9d91 1993static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
1994{
1995 VideoState *is;
1996
1997 is = av_mallocz(sizeof(VideoState));
1998 if (!is)
1999 return NULL;
2000 pstrcpy(is->filename, sizeof(is->filename), filename);
638c9d91 2001 is->iformat = iformat;
01310af2
FB
2002 if (screen) {
2003 is->width = screen->w;
2004 is->height = screen->h;
2005 }
2006 is->ytop = 0;
2007 is->xleft = 0;
2008
2009 /* start video display */
2010 is->pictq_mutex = SDL_CreateMutex();
2011 is->pictq_cond = SDL_CreateCond();
115329f1 2012
72ce053b
IC
2013 is->subpq_mutex = SDL_CreateMutex();
2014 is->subpq_cond = SDL_CreateCond();
115329f1 2015
72ce053b 2016 is->subtitle_decoder_mutex = SDL_CreateMutex();
b514ed3c
MN
2017 is->audio_decoder_mutex = SDL_CreateMutex();
2018 is->video_decoder_mutex = SDL_CreateMutex();
01310af2
FB
2019
2020 /* add the refresh timer to draw the picture */
2021 schedule_refresh(is, 40);
2022
638c9d91 2023 is->av_sync_type = av_sync_type;
01310af2
FB
2024 is->parse_tid = SDL_CreateThread(decode_thread, is);
2025 if (!is->parse_tid) {
2026 av_free(is);
2027 return NULL;
2028 }
2029 return is;
2030}
2031
2032static void stream_close(VideoState *is)
2033{
2034 VideoPicture *vp;
2035 int i;
2036 /* XXX: use a special url_shutdown call to abort parse cleanly */
2037 is->abort_request = 1;
2038 SDL_WaitThread(is->parse_tid, NULL);
2039
2040 /* free all pictures */
2041 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2042 vp = &is->pictq[i];
2043 if (vp->bmp) {
2044 SDL_FreeYUVOverlay(vp->bmp);
2045 vp->bmp = NULL;
2046 }
2047 }
2048 SDL_DestroyMutex(is->pictq_mutex);
2049 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2050 SDL_DestroyMutex(is->subpq_mutex);
2051 SDL_DestroyCond(is->subpq_cond);
2052 SDL_DestroyMutex(is->subtitle_decoder_mutex);
b514ed3c
MN
2053 SDL_DestroyMutex(is->audio_decoder_mutex);
2054 SDL_DestroyMutex(is->video_decoder_mutex);
01310af2
FB
2055}
2056
7b49ce2e 2057static void stream_cycle_channel(VideoState *is, int codec_type)
638c9d91
FB
2058{
2059 AVFormatContext *ic = is->ic;
2060 int start_index, stream_index;
2061 AVStream *st;
2062
2063 if (codec_type == CODEC_TYPE_VIDEO)
2064 start_index = is->video_stream;
72ce053b 2065 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2066 start_index = is->audio_stream;
72ce053b
IC
2067 else
2068 start_index = is->subtitle_stream;
2069 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2070 return;
2071 stream_index = start_index;
2072 for(;;) {
2073 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2074 {
2075 if (codec_type == CODEC_TYPE_SUBTITLE)
2076 {
2077 stream_index = -1;
2078 goto the_end;
2079 } else
2080 stream_index = 0;
2081 }
638c9d91
FB
2082 if (stream_index == start_index)
2083 return;
2084 st = ic->streams[stream_index];
01f4895c 2085 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2086 /* check that parameters are OK */
2087 switch(codec_type) {
2088 case CODEC_TYPE_AUDIO:
01f4895c
MN
2089 if (st->codec->sample_rate != 0 &&
2090 st->codec->channels != 0)
638c9d91
FB
2091 goto the_end;
2092 break;
2093 case CODEC_TYPE_VIDEO:
72ce053b 2094 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2095 goto the_end;
2096 default:
2097 break;
2098 }
2099 }
2100 }
2101 the_end:
2102 stream_component_close(is, start_index);
2103 stream_component_open(is, stream_index);
2104}
2105
2106
7b49ce2e 2107static void toggle_full_screen(void)
01310af2
FB
2108{
2109 int w, h, flags;
2110 is_full_screen = !is_full_screen;
29f3b38a
MR
2111 if (!fs_screen_width) {
2112 /* use default SDL method */
2113 SDL_WM_ToggleFullScreen(screen);
01310af2 2114 } else {
29f3b38a
MR
2115 /* use the recorded resolution */
2116 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2117 if (is_full_screen) {
2118 w = fs_screen_width;
2119 h = fs_screen_height;
2120 flags |= SDL_FULLSCREEN;
2121 } else {
2122 w = screen_width;
2123 h = screen_height;
2124 flags |= SDL_RESIZABLE;
2125 }
2126 screen = SDL_SetVideoMode(w, h, 0, flags);
2127 cur_stream->width = w;
2128 cur_stream->height = h;
01310af2
FB
2129 }
2130}
2131
7b49ce2e 2132static void toggle_pause(void)
01310af2
FB
2133{
2134 if (cur_stream)
2135 stream_pause(cur_stream);
bba04f1e
WH
2136 step = 0;
2137}
2138
7b49ce2e 2139static void step_to_next_frame(void)
bba04f1e
WH
2140{
2141 if (cur_stream) {
2142 if (cur_stream->paused)
2143 cur_stream->paused=0;
2144 cur_stream->video_current_pts = get_video_clock(cur_stream);
2145 }
2146 step = 1;
01310af2
FB
2147}
2148
7b49ce2e 2149static void do_exit(void)
01310af2
FB
2150{
2151 if (cur_stream) {
2152 stream_close(cur_stream);
2153 cur_stream = NULL;
2154 }
2155 if (show_status)
2156 printf("\n");
2157 SDL_Quit();
2158 exit(0);
2159}
2160
7b49ce2e 2161static void toggle_audio_display(void)
01310af2
FB
2162{
2163 if (cur_stream) {
2164 cur_stream->show_audio = !cur_stream->show_audio;
2165 }
2166}
2167
2168/* handle an event sent by the GUI */
7b49ce2e 2169static void event_loop(void)
01310af2
FB
2170{
2171 SDL_Event event;
a11d11aa 2172 double incr, pos, frac;
01310af2
FB
2173
2174 for(;;) {
2175 SDL_WaitEvent(&event);
2176 switch(event.type) {
2177 case SDL_KEYDOWN:
2178 switch(event.key.keysym.sym) {
2179 case SDLK_ESCAPE:
2180 case SDLK_q:
2181 do_exit();
2182 break;
2183 case SDLK_f:
2184 toggle_full_screen();
2185 break;
2186 case SDLK_p:
2187 case SDLK_SPACE:
2188 toggle_pause();
2189 break;
bba04f1e
WH
2190 case SDLK_s: //S: Step to next frame
2191 step_to_next_frame();
2192 break;
01310af2 2193 case SDLK_a:
115329f1 2194 if (cur_stream)
638c9d91
FB
2195 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2196 break;
2197 case SDLK_v:
115329f1 2198 if (cur_stream)
638c9d91
FB
2199 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2200 break;
72ce053b 2201 case SDLK_t:
115329f1 2202 if (cur_stream)
72ce053b
IC
2203 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2204 break;
638c9d91 2205 case SDLK_w:
01310af2
FB
2206 toggle_audio_display();
2207 break;
72ea344b
FB
2208 case SDLK_LEFT:
2209 incr = -10.0;
2210 goto do_seek;
2211 case SDLK_RIGHT:
2212 incr = 10.0;
2213 goto do_seek;
2214 case SDLK_UP:
2215 incr = 60.0;
2216 goto do_seek;
2217 case SDLK_DOWN:
2218 incr = -60.0;
2219 do_seek:
2220 if (cur_stream) {
2221 pos = get_master_clock(cur_stream);
2222 pos += incr;
3ba1438d 2223 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
72ea344b
FB
2224 }
2225 break;
01310af2
FB
2226 default:
2227 break;
2228 }
2229 break;
a11d11aa 2230 case SDL_MOUSEBUTTONDOWN:
bb270c08
DB
2231 if (cur_stream) {
2232 int ns, hh, mm, ss;
2233 int tns, thh, tmm, tss;
2234 tns = cur_stream->ic->duration/1000000LL;
2235 thh = tns/3600;
2236 tmm = (tns%3600)/60;
2237 tss = (tns%60);
2238 frac = (double)event.button.x/(double)cur_stream->width;
2239 ns = frac*tns;
2240 hh = ns/3600;
2241 mm = (ns%3600)/60;
2242 ss = (ns%60);
2243 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2244 hh, mm, ss, thh, tmm, tss);
2245 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2246 }
2247 break;
01310af2
FB
2248 case SDL_VIDEORESIZE:
2249 if (cur_stream) {
115329f1 2250 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2
FB
2251 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2252 cur_stream->width = event.resize.w;
2253 cur_stream->height = event.resize.h;
2254 }
2255 break;
2256 case SDL_QUIT:
638c9d91 2257 case FF_QUIT_EVENT:
01310af2
FB
2258 do_exit();
2259 break;
2260 case FF_ALLOC_EVENT:
2261 alloc_picture(event.user.data1);
2262 break;
2263 case FF_REFRESH_EVENT:
2264 video_refresh_timer(event.user.data1);
2265 break;
2266 default:
2267 break;
2268 }
2269 }
2270}
2271
2272void opt_width(const char *arg)
2273{
2274 screen_width = atoi(arg);
2275}
2276
2277void opt_height(const char *arg)
2278{
2279 screen_height = atoi(arg);
2280}
2281
2282static void opt_format(const char *arg)
2283{
2284 file_iformat = av_find_input_format(arg);
2285 if (!file_iformat) {
2286 fprintf(stderr, "Unknown input format: %s\n", arg);
2287 exit(1);
2288 }
2289}
61890b02
FB
2290
2291static void opt_image_format(const char *arg)
2292{
2293 AVImageFormat *f;
115329f1 2294
61890b02
FB
2295 for(f = first_image_format; f != NULL; f = f->next) {
2296 if (!strcmp(arg, f->name))
2297 break;
2298 }
2299 if (!f) {
2300 fprintf(stderr, "Unknown image format: '%s'\n", arg);
2301 exit(1);
2302 }
2303 image_format = f;
2304}
2305
400738b1 2306#ifdef CONFIG_NETWORK
416e3508
FB
2307void opt_rtp_tcp(void)
2308{
2309 /* only tcp protocol */
2310 rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
2311}
400738b1 2312#endif
416e3508 2313
638c9d91
FB
2314void opt_sync(const char *arg)
2315{
2316 if (!strcmp(arg, "audio"))
2317 av_sync_type = AV_SYNC_AUDIO_MASTER;
2318 else if (!strcmp(arg, "video"))
2319 av_sync_type = AV_SYNC_VIDEO_MASTER;
2320 else if (!strcmp(arg, "ext"))
2321 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2322 else
2323 show_help();
2324}
2325
72ea344b
FB
2326void opt_seek(const char *arg)
2327{
2328 start_time = parse_date(arg, 1);
2329}
2330
e26a8335
WH
2331static void opt_debug(const char *arg)
2332{
0540cad3 2333 av_log_set_level(99);
e26a8335
WH
2334 debug = atoi(arg);
2335}
115329f1 2336
0c9bbaec
WH
2337static void opt_vismv(const char *arg)
2338{
2339 debug_mv = atoi(arg);
2340}
c62c07d3
MN
2341
2342static void opt_thread_count(const char *arg)
2343{
2344 thread_count= atoi(arg);
2450cff2 2345#if !defined(HAVE_THREADS)
c62c07d3
MN
2346 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2347#endif
2348}
115329f1 2349
01310af2 2350const OptionDef options[] = {
115329f1 2351 { "h", 0, {(void*)show_help}, "show help" },
01310af2
FB
2352 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
2353 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
638c9d91 2354 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2355 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2356 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
72ea344b 2357 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
01310af2
FB
2358 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2359 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
61890b02 2360 { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
01310af2 2361 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
e26a8335 2362 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2363 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
0c9bbaec 2364 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2365 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2366 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
178fcca8 2367 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2368 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2369 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2370 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2371 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
1b51e051
MN
2372 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
2373 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
400738b1 2374#ifdef CONFIG_NETWORK
416e3508 2375 { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
400738b1 2376#endif
c62c07d3
MN
2377 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2378 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
01310af2
FB
2379 { NULL, },
2380};
2381
2382void show_help(void)
2383{
02d504a7
FB
2384 printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
2385 "usage: ffplay [options] input_file\n"
01310af2
FB
2386 "Simple media player\n");
2387 printf("\n");
02d504a7
FB
2388 show_help_options(options, "Main options:\n",
2389 OPT_EXPERT, 0);
2390 show_help_options(options, "\nAdvanced options:\n",
2391 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2392 printf("\nWhile playing:\n"
2393 "q, ESC quit\n"
2394 "f toggle full screen\n"
2395 "p, SPC pause\n"
638c9d91
FB
2396 "a cycle audio channel\n"
2397 "v cycle video channel\n"
72ce053b 2398 "t cycle subtitle channel\n"
638c9d91 2399 "w show audio waves\n"
72ea344b
FB
2400 "left/right seek backward/forward 10 seconds\n"
2401 "down/up seek backward/forward 1 minute\n"
a11d11aa 2402 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2
FB
2403 );
2404 exit(1);
2405}
2406
2407void parse_arg_file(const char *filename)
2408{
e8d83e1c
MN
2409 if (!strcmp(filename, "-"))
2410 filename = "pipe:";
01310af2
FB
2411 input_filename = filename;
2412}
2413
2414/* Called from the main */
2415int main(int argc, char **argv)
2416{
638c9d91 2417 int flags, w, h;
115329f1 2418
01310af2
FB
2419 /* register all codecs, demux and protocols */
2420 av_register_all();
2421
3ca4b654
MN
2422 #ifdef CONFIG_OS2
2423 MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
115329f1 2424
3ca4b654
MN
2425 // Make stdout and stderr unbuffered
2426 setbuf( stdout, NULL );
2427 setbuf( stderr, NULL );
2428 #endif
2429
01310af2
FB
2430 parse_options(argc, argv, options);
2431
2432 if (!input_filename)
2433 show_help();
2434
2435 if (display_disable) {
2436 video_disable = 1;
2437 }
31319a8c 2438 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2f30a81d 2439#if !defined(__MINGW32__) && !defined(CONFIG_DARWIN)
4b0e85d4 2440 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 or darwin */
31319a8c 2441#endif
01310af2 2442 if (SDL_Init (flags)) {
05ab0b76 2443 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2444 exit(1);
2445 }
2446
2447 if (!display_disable) {
29f3b38a 2448#ifdef HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2449 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2450 fs_screen_width = vi->current_w;
2451 fs_screen_height = vi->current_h;
29f3b38a 2452#endif
638c9d91
FB
2453 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
2454 if (is_full_screen && fs_screen_width) {
2455 w = fs_screen_width;
2456 h = fs_screen_height;
2457 flags |= SDL_FULLSCREEN;
2458 } else {
2459 w = screen_width;
2460 h = screen_height;
2461 flags |= SDL_RESIZABLE;
2462 }
4b0e85d4 2463#ifndef CONFIG_DARWIN
638c9d91 2464 screen = SDL_SetVideoMode(w, h, 0, flags);
4b0e85d4
EL
2465#else
2466 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
2467 screen = SDL_SetVideoMode(w, h, 24, flags);
2468#endif
638c9d91
FB
2469 if (!screen) {
2470 fprintf(stderr, "SDL: could not set video mode - exiting\n");
2471 exit(1);
2472 }
2473 SDL_WM_SetCaption("FFplay", "FFplay");
01310af2
FB
2474 }
2475
2476 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2477 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2478 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2479 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2480
638c9d91 2481 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2482
2483 event_loop();
2484
2485 /* never returns */
2486
2487 return 0;
2488}