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