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