support big endian lpcm with audio stsd v2
[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>
245976da
DB
24#include "libavutil/avstring.h"
25#include "libavformat/avformat.h"
26#include "libavformat/rtsp.h"
27#include "libavdevice/avdevice.h"
28#include "libswscale/swscale.h"
01310af2
FB
29
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
64555bd9 41const char program_name[] = "FFplay";
ea9c581f 42const int program_birth_year = 2003;
4cfac5bc 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
358061f6 171static void 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)
cea96420 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;
abdff646 1574 AVCodecContext *dec= is->audio_st->codec;
72ea344b 1575 int n, len1, data_size;
01310af2
FB
1576 double pts;
1577
1578 for(;;) {
72ea344b 1579 /* NOTE: the audio packet can contain several frames */
01310af2 1580 while (is->audio_pkt_size > 0) {
07cbff39 1581 data_size = buf_size;
abdff646 1582 len1 = avcodec_decode_audio2(dec,
115329f1 1583 (int16_t *)audio_buf, &data_size,
01310af2 1584 is->audio_pkt_data, is->audio_pkt_size);
72ea344b
FB
1585 if (len1 < 0) {
1586 /* if error, we skip the frame */
1587 is->audio_pkt_size = 0;
01310af2 1588 break;
72ea344b 1589 }
115329f1 1590
01310af2
FB
1591 is->audio_pkt_data += len1;
1592 is->audio_pkt_size -= len1;
72ea344b
FB
1593 if (data_size <= 0)
1594 continue;
1595 /* if no pts, then compute it */
1596 pts = is->audio_clock;
1597 *pts_ptr = pts;
abdff646 1598 n = 2 * dec->channels;
115329f1 1599 is->audio_clock += (double)data_size /
abdff646 1600 (double)(n * dec->sample_rate);
638c9d91 1601#if defined(DEBUG_SYNC)
72ea344b
FB
1602 {
1603 static double last_clock;
1604 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1605 is->audio_clock - last_clock,
1606 is->audio_clock, pts);
1607 last_clock = is->audio_clock;
01310af2 1608 }
72ea344b
FB
1609#endif
1610 return data_size;
01310af2
FB
1611 }
1612
72ea344b
FB
1613 /* free the current packet */
1614 if (pkt->data)
01310af2 1615 av_free_packet(pkt);
115329f1 1616
72ea344b
FB
1617 if (is->paused || is->audioq.abort_request) {
1618 return -1;
1619 }
115329f1 1620
01310af2
FB
1621 /* read next packet */
1622 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1623 return -1;
39c6a118 1624 if(pkt->data == flush_pkt.data){
abdff646 1625 avcodec_flush_buffers(dec);
39c6a118
MN
1626 continue;
1627 }
1628
01310af2
FB
1629 is->audio_pkt_data = pkt->data;
1630 is->audio_pkt_size = pkt->size;
115329f1 1631
72ea344b
FB
1632 /* if update the audio clock with the pts */
1633 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1634 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1635 }
01310af2
FB
1636 }
1637}
1638
638c9d91
FB
1639/* get the current audio output buffer size, in samples. With SDL, we
1640 cannot have a precise information */
1641static int audio_write_get_buf_size(VideoState *is)
01310af2 1642{
b09b580b 1643 return is->audio_buf_size - is->audio_buf_index;
01310af2
FB
1644}
1645
1646
1647/* prepare a new audio buffer */
358061f6 1648static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
01310af2
FB
1649{
1650 VideoState *is = opaque;
1651 int audio_size, len1;
1652 double pts;
1653
1654 audio_callback_time = av_gettime();
115329f1 1655
01310af2
FB
1656 while (len > 0) {
1657 if (is->audio_buf_index >= is->audio_buf_size) {
07cbff39 1658 audio_size = audio_decode_frame(is, is->audio_buf, sizeof(is->audio_buf), &pts);
01310af2
FB
1659 if (audio_size < 0) {
1660 /* if error, just output silence */
1661 is->audio_buf_size = 1024;
1662 memset(is->audio_buf, 0, is->audio_buf_size);
1663 } else {
1664 if (is->show_audio)
1665 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
115329f1 1666 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
01310af2
FB
1667 pts);
1668 is->audio_buf_size = audio_size;
1669 }
1670 is->audio_buf_index = 0;
1671 }
1672 len1 = is->audio_buf_size - is->audio_buf_index;
1673 if (len1 > len)
1674 len1 = len;
1675 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1676 len -= len1;
1677 stream += len1;
1678 is->audio_buf_index += len1;
1679 }
1680}
1681
01310af2
FB
1682/* open a given stream. Return 0 if OK */
1683static int stream_component_open(VideoState *is, int stream_index)
1684{
1685 AVFormatContext *ic = is->ic;
1686 AVCodecContext *enc;
1687 AVCodec *codec;
1688 SDL_AudioSpec wanted_spec, spec;
1689
1690 if (stream_index < 0 || stream_index >= ic->nb_streams)
1691 return -1;
01f4895c 1692 enc = ic->streams[stream_index]->codec;
115329f1 1693
01310af2
FB
1694 /* prepare audio output */
1695 if (enc->codec_type == CODEC_TYPE_AUDIO) {
51b73087
JR
1696 if (enc->channels > 0) {
1697 enc->request_channels = FFMIN(2, enc->channels);
94eadc8b 1698 } else {
51b73087 1699 enc->request_channels = 2;
638c9d91 1700 }
01310af2
FB
1701 }
1702
1703 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1704 enc->debug_mv = debug_mv;
1705 enc->debug = debug;
6387c3e6 1706 enc->workaround_bugs = workaround_bugs;
178fcca8 1707 enc->lowres = lowres;
61846e9a 1708 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1709 enc->idct_algo= idct;
6fc5b059 1710 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
8c3eba7c
MN
1711 enc->skip_frame= skip_frame;
1712 enc->skip_idct= skip_idct;
1713 enc->skip_loop_filter= skip_loop_filter;
1b51e051
MN
1714 enc->error_resilience= error_resilience;
1715 enc->error_concealment= error_concealment;
01310af2
FB
1716 if (!codec ||
1717 avcodec_open(enc, codec) < 0)
1718 return -1;
51b73087
JR
1719
1720 /* prepare audio output */
1721 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1722 wanted_spec.freq = enc->sample_rate;
1723 wanted_spec.format = AUDIO_S16SYS;
1724 wanted_spec.channels = enc->channels;
1725 wanted_spec.silence = 0;
1726 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1727 wanted_spec.callback = sdl_audio_callback;
1728 wanted_spec.userdata = is;
1729 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1730 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1731 return -1;
1732 }
1733 is->audio_hw_buf_size = spec.size;
1734 }
1735
c62c07d3
MN
1736 if(thread_count>1)
1737 avcodec_thread_init(enc, thread_count);
c62c07d3 1738 enc->thread_count= thread_count;
638c9d91 1739 switch(enc->codec_type) {
01310af2
FB
1740 case CODEC_TYPE_AUDIO:
1741 is->audio_stream = stream_index;
1742 is->audio_st = ic->streams[stream_index];
1743 is->audio_buf_size = 0;
1744 is->audio_buf_index = 0;
638c9d91
FB
1745
1746 /* init averaging filter */
1747 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1748 is->audio_diff_avg_count = 0;
1749 /* since we do not have a precise anough audio fifo fullness,
1750 we correct audio sync only if larger than this threshold */
1751 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1752
01310af2
FB
1753 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1754 packet_queue_init(&is->audioq);
bb270c08 1755 SDL_PauseAudio(0);
01310af2
FB
1756 break;
1757 case CODEC_TYPE_VIDEO:
1758 is->video_stream = stream_index;
1759 is->video_st = ic->streams[stream_index];
1760
638c9d91
FB
1761 is->frame_last_delay = 40e-3;
1762 is->frame_timer = (double)av_gettime() / 1000000.0;
638c9d91
FB
1763 is->video_current_pts_time = av_gettime();
1764
01310af2
FB
1765 packet_queue_init(&is->videoq);
1766 is->video_tid = SDL_CreateThread(video_thread, is);
5039185a
MN
1767
1768 enc-> get_buffer= my_get_buffer;
1769 enc->release_buffer= my_release_buffer;
01310af2 1770 break;
72ce053b
IC
1771 case CODEC_TYPE_SUBTITLE:
1772 is->subtitle_stream = stream_index;
1773 is->subtitle_st = ic->streams[stream_index];
1774 packet_queue_init(&is->subtitleq);
115329f1 1775
72ce053b
IC
1776 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1777 break;
01310af2
FB
1778 default:
1779 break;
1780 }
1781 return 0;
1782}
1783
1784static void stream_component_close(VideoState *is, int stream_index)
1785{
1786 AVFormatContext *ic = is->ic;
1787 AVCodecContext *enc;
115329f1 1788
72ce053b
IC
1789 if (stream_index < 0 || stream_index >= ic->nb_streams)
1790 return;
01f4895c 1791 enc = ic->streams[stream_index]->codec;
01310af2
FB
1792
1793 switch(enc->codec_type) {
1794 case CODEC_TYPE_AUDIO:
1795 packet_queue_abort(&is->audioq);
1796
1797 SDL_CloseAudio();
1798
1799 packet_queue_end(&is->audioq);
1800 break;
1801 case CODEC_TYPE_VIDEO:
1802 packet_queue_abort(&is->videoq);
1803
1804 /* note: we also signal this mutex to make sure we deblock the
1805 video thread in all cases */
1806 SDL_LockMutex(is->pictq_mutex);
1807 SDL_CondSignal(is->pictq_cond);
1808 SDL_UnlockMutex(is->pictq_mutex);
1809
1810 SDL_WaitThread(is->video_tid, NULL);
1811
1812 packet_queue_end(&is->videoq);
1813 break;
72ce053b
IC
1814 case CODEC_TYPE_SUBTITLE:
1815 packet_queue_abort(&is->subtitleq);
115329f1 1816
72ce053b
IC
1817 /* note: we also signal this mutex to make sure we deblock the
1818 video thread in all cases */
1819 SDL_LockMutex(is->subpq_mutex);
1820 is->subtitle_stream_changed = 1;
115329f1 1821
72ce053b
IC
1822 SDL_CondSignal(is->subpq_cond);
1823 SDL_UnlockMutex(is->subpq_mutex);
1824
1825 SDL_WaitThread(is->subtitle_tid, NULL);
1826
1827 packet_queue_end(&is->subtitleq);
1828 break;
01310af2
FB
1829 default:
1830 break;
1831 }
1832
1833 avcodec_close(enc);
1834 switch(enc->codec_type) {
1835 case CODEC_TYPE_AUDIO:
1836 is->audio_st = NULL;
1837 is->audio_stream = -1;
1838 break;
1839 case CODEC_TYPE_VIDEO:
1840 is->video_st = NULL;
1841 is->video_stream = -1;
1842 break;
72ce053b
IC
1843 case CODEC_TYPE_SUBTITLE:
1844 is->subtitle_st = NULL;
1845 is->subtitle_stream = -1;
1846 break;
01310af2
FB
1847 default:
1848 break;
1849 }
1850}
1851
7b49ce2e 1852static void dump_stream_info(const AVFormatContext *s)
d0526ecf
FB
1853{
1854 if (s->track != 0)
1855 fprintf(stderr, "Track: %d\n", s->track);
1856 if (s->title[0] != '\0')
1857 fprintf(stderr, "Title: %s\n", s->title);
1858 if (s->author[0] != '\0')
1859 fprintf(stderr, "Author: %s\n", s->author);
f0861f46
PI
1860 if (s->copyright[0] != '\0')
1861 fprintf(stderr, "Copyright: %s\n", s->copyright);
1862 if (s->comment[0] != '\0')
1863 fprintf(stderr, "Comment: %s\n", s->comment);
d0526ecf
FB
1864 if (s->album[0] != '\0')
1865 fprintf(stderr, "Album: %s\n", s->album);
1866 if (s->year != 0)
1867 fprintf(stderr, "Year: %d\n", s->year);
1868 if (s->genre[0] != '\0')
1869 fprintf(stderr, "Genre: %s\n", s->genre);
1870}
1871
416e3508
FB
1872/* since we have only one decoding thread, we can use a global
1873 variable instead of a thread local variable */
1874static VideoState *global_video_state;
1875
1876static int decode_interrupt_cb(void)
1877{
1878 return (global_video_state && global_video_state->abort_request);
1879}
01310af2
FB
1880
1881/* this thread gets the stream from the disk or the network */
1882static int decode_thread(void *arg)
1883{
1884 VideoState *is = arg;
1885 AVFormatContext *ic;
b2e6799b 1886 int err, i, ret, video_index, audio_index;
01310af2 1887 AVPacket pkt1, *pkt = &pkt1;
61890b02 1888 AVFormatParameters params, *ap = &params;
01310af2
FB
1889
1890 video_index = -1;
1891 audio_index = -1;
1892 is->video_stream = -1;
1893 is->audio_stream = -1;
72ce053b 1894 is->subtitle_stream = -1;
01310af2 1895
416e3508
FB
1896 global_video_state = is;
1897 url_set_interrupt_cb(decode_interrupt_cb);
1898
61890b02 1899 memset(ap, 0, sizeof(*ap));
115329f1 1900
e4b89522
LW
1901 ap->width = frame_width;
1902 ap->height= frame_height;
7e042912 1903 ap->time_base= (AVRational){1, 25};
e4b89522 1904 ap->pix_fmt = frame_pix_fmt;
7e042912 1905
61890b02 1906 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1907 if (err < 0) {
1908 print_error(is->filename, err);
1909 ret = -1;
1910 goto fail;
1911 }
01310af2 1912 is->ic = ic;
30bc6613
MN
1913
1914 if(genpts)
1915 ic->flags |= AVFMT_FLAG_GENPTS;
1916
24c07998
LA
1917 err = av_find_stream_info(ic);
1918 if (err < 0) {
1919 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1920 ret = -1;
1921 goto fail;
1922 }
899681cd
BA
1923 if(ic->pb)
1924 ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
72ea344b
FB
1925
1926 /* if seeking requested, we execute it */
1927 if (start_time != AV_NOPTS_VALUE) {
1928 int64_t timestamp;
1929
1930 timestamp = start_time;
1931 /* add the stream start time */
1932 if (ic->start_time != AV_NOPTS_VALUE)
1933 timestamp += ic->start_time;
3ba1438d 1934 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
72ea344b 1935 if (ret < 0) {
115329f1 1936 fprintf(stderr, "%s: could not seek to position %0.3f\n",
72ea344b
FB
1937 is->filename, (double)timestamp / AV_TIME_BASE);
1938 }
1939 }
72ea344b 1940
01310af2 1941 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1942 AVCodecContext *enc = ic->streams[i]->codec;
01310af2
FB
1943 switch(enc->codec_type) {
1944 case CODEC_TYPE_AUDIO:
a8062103 1945 if ((audio_index < 0 || wanted_audio_stream-- > 0) && !audio_disable)
01310af2
FB
1946 audio_index = i;
1947 break;
1948 case CODEC_TYPE_VIDEO:
4d8243d3 1949 if ((video_index < 0 || wanted_video_stream-- > 0) && !video_disable)
01310af2
FB
1950 video_index = i;
1951 break;
1952 default:
1953 break;
1954 }
1955 }
1956 if (show_status) {
1957 dump_format(ic, 0, is->filename, 0);
d0526ecf 1958 dump_stream_info(ic);
01310af2
FB
1959 }
1960
1961 /* open the streams */
1962 if (audio_index >= 0) {
1963 stream_component_open(is, audio_index);
1964 }
1965
1966 if (video_index >= 0) {
1967 stream_component_open(is, video_index);
1968 } else {
1969 if (!display_disable)
1970 is->show_audio = 1;
1971 }
1972
1973 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
1974 fprintf(stderr, "%s: could not open codecs\n", is->filename);
1975 ret = -1;
01310af2
FB
1976 goto fail;
1977 }
1978
1979 for(;;) {
1980 if (is->abort_request)
1981 break;
416e3508
FB
1982 if (is->paused != is->last_paused) {
1983 is->last_paused = is->paused;
72ea344b
FB
1984 if (is->paused)
1985 av_read_pause(ic);
1986 else
1987 av_read_play(ic);
416e3508 1988 }
c03af894
BA
1989#if defined(CONFIG_RTSP_DEMUXER) || defined(CONFIG_MMSH_PROTOCOL)
1990 if (is->paused &&
1991 (!strcmp(ic->iformat->name, "rtsp") ||
899681cd 1992 (ic->pb && !strcmp(url_fileno(ic->pb)->prot->name, "mmsh")))) {
416e3508
FB
1993 /* wait 10 ms to avoid trying to get another packet */
1994 /* XXX: horrible */
1995 SDL_Delay(10);
1996 continue;
1997 }
400738b1 1998#endif
72ea344b 1999 if (is->seek_req) {
8e606cc8
MN
2000 int stream_index= -1;
2001 int64_t seek_target= is->seek_pos;
2002
2003 if (is-> video_stream >= 0) stream_index= is-> video_stream;
2004 else if(is-> audio_stream >= 0) stream_index= is-> audio_stream;
2005 else if(is->subtitle_stream >= 0) stream_index= is->subtitle_stream;
2006
2007 if(stream_index>=0){
2008 seek_target= av_rescale_q(seek_target, AV_TIME_BASE_Q, ic->streams[stream_index]->time_base);
2009 }
2010
2011 ret = av_seek_frame(is->ic, stream_index, seek_target, is->seek_flags);
72ea344b
FB
2012 if (ret < 0) {
2013 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
2014 }else{
2015 if (is->audio_stream >= 0) {
2016 packet_queue_flush(&is->audioq);
39c6a118 2017 packet_queue_put(&is->audioq, &flush_pkt);
e6c0297f 2018 }
72ce053b
IC
2019 if (is->subtitle_stream >= 0) {
2020 packet_queue_flush(&is->subtitleq);
39c6a118 2021 packet_queue_put(&is->subtitleq, &flush_pkt);
72ce053b 2022 }
e6c0297f
MN
2023 if (is->video_stream >= 0) {
2024 packet_queue_flush(&is->videoq);
39c6a118 2025 packet_queue_put(&is->videoq, &flush_pkt);
e6c0297f 2026 }
72ea344b
FB
2027 }
2028 is->seek_req = 0;
2029 }
416e3508 2030
01310af2
FB
2031 /* if the queue are full, no need to read more */
2032 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
115329f1
DB
2033 is->videoq.size > MAX_VIDEOQ_SIZE ||
2034 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
899681cd 2035 url_feof(ic->pb)) {
01310af2
FB
2036 /* wait 10 ms */
2037 SDL_Delay(10);
2038 continue;
2039 }
72ea344b 2040 ret = av_read_frame(ic, pkt);
01310af2 2041 if (ret < 0) {
899681cd 2042 if (url_ferror(ic->pb) == 0) {
6e1f8725 2043 SDL_Delay(100); /* wait for user event */
bb270c08
DB
2044 continue;
2045 } else
2046 break;
01310af2
FB
2047 }
2048 if (pkt->stream_index == is->audio_stream) {
2049 packet_queue_put(&is->audioq, pkt);
2050 } else if (pkt->stream_index == is->video_stream) {
2051 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
2052 } else if (pkt->stream_index == is->subtitle_stream) {
2053 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
2054 } else {
2055 av_free_packet(pkt);
2056 }
2057 }
2058 /* wait until the end */
2059 while (!is->abort_request) {
2060 SDL_Delay(100);
2061 }
2062
638c9d91 2063 ret = 0;
01310af2 2064 fail:
416e3508
FB
2065 /* disable interrupting */
2066 global_video_state = NULL;
2067
01310af2
FB
2068 /* close each stream */
2069 if (is->audio_stream >= 0)
2070 stream_component_close(is, is->audio_stream);
2071 if (is->video_stream >= 0)
2072 stream_component_close(is, is->video_stream);
72ce053b
IC
2073 if (is->subtitle_stream >= 0)
2074 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
2075 if (is->ic) {
2076 av_close_input_file(is->ic);
2077 is->ic = NULL; /* safety */
2078 }
416e3508
FB
2079 url_set_interrupt_cb(NULL);
2080
638c9d91
FB
2081 if (ret != 0) {
2082 SDL_Event event;
115329f1 2083
638c9d91
FB
2084 event.type = FF_QUIT_EVENT;
2085 event.user.data1 = is;
2086 SDL_PushEvent(&event);
2087 }
01310af2
FB
2088 return 0;
2089}
2090
638c9d91 2091static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
2092{
2093 VideoState *is;
2094
2095 is = av_mallocz(sizeof(VideoState));
2096 if (!is)
2097 return NULL;
f7d78f36 2098 av_strlcpy(is->filename, filename, sizeof(is->filename));
638c9d91 2099 is->iformat = iformat;
01310af2
FB
2100 is->ytop = 0;
2101 is->xleft = 0;
2102
2103 /* start video display */
2104 is->pictq_mutex = SDL_CreateMutex();
2105 is->pictq_cond = SDL_CreateCond();
115329f1 2106
72ce053b
IC
2107 is->subpq_mutex = SDL_CreateMutex();
2108 is->subpq_cond = SDL_CreateCond();
115329f1 2109
01310af2
FB
2110 /* add the refresh timer to draw the picture */
2111 schedule_refresh(is, 40);
2112
638c9d91 2113 is->av_sync_type = av_sync_type;
01310af2
FB
2114 is->parse_tid = SDL_CreateThread(decode_thread, is);
2115 if (!is->parse_tid) {
2116 av_free(is);
2117 return NULL;
2118 }
2119 return is;
2120}
2121
2122static void stream_close(VideoState *is)
2123{
2124 VideoPicture *vp;
2125 int i;
2126 /* XXX: use a special url_shutdown call to abort parse cleanly */
2127 is->abort_request = 1;
2128 SDL_WaitThread(is->parse_tid, NULL);
2129
2130 /* free all pictures */
2131 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2132 vp = &is->pictq[i];
2133 if (vp->bmp) {
2134 SDL_FreeYUVOverlay(vp->bmp);
2135 vp->bmp = NULL;
2136 }
2137 }
2138 SDL_DestroyMutex(is->pictq_mutex);
2139 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2140 SDL_DestroyMutex(is->subpq_mutex);
2141 SDL_DestroyCond(is->subpq_cond);
01310af2
FB
2142}
2143
7b49ce2e 2144static void stream_cycle_channel(VideoState *is, int codec_type)
638c9d91
FB
2145{
2146 AVFormatContext *ic = is->ic;
2147 int start_index, stream_index;
2148 AVStream *st;
2149
2150 if (codec_type == CODEC_TYPE_VIDEO)
2151 start_index = is->video_stream;
72ce053b 2152 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2153 start_index = is->audio_stream;
72ce053b
IC
2154 else
2155 start_index = is->subtitle_stream;
2156 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2157 return;
2158 stream_index = start_index;
2159 for(;;) {
2160 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2161 {
2162 if (codec_type == CODEC_TYPE_SUBTITLE)
2163 {
2164 stream_index = -1;
2165 goto the_end;
2166 } else
2167 stream_index = 0;
2168 }
638c9d91
FB
2169 if (stream_index == start_index)
2170 return;
2171 st = ic->streams[stream_index];
01f4895c 2172 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2173 /* check that parameters are OK */
2174 switch(codec_type) {
2175 case CODEC_TYPE_AUDIO:
01f4895c
MN
2176 if (st->codec->sample_rate != 0 &&
2177 st->codec->channels != 0)
638c9d91
FB
2178 goto the_end;
2179 break;
2180 case CODEC_TYPE_VIDEO:
72ce053b 2181 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2182 goto the_end;
2183 default:
2184 break;
2185 }
2186 }
2187 }
2188 the_end:
2189 stream_component_close(is, start_index);
2190 stream_component_open(is, stream_index);
2191}
2192
2193
7b49ce2e 2194static void toggle_full_screen(void)
01310af2 2195{
01310af2 2196 is_full_screen = !is_full_screen;
29f3b38a
MR
2197 if (!fs_screen_width) {
2198 /* use default SDL method */
fb84155b 2199// SDL_WM_ToggleFullScreen(screen);
01310af2 2200 }
fb84155b 2201 video_open(cur_stream);
01310af2
FB
2202}
2203
7b49ce2e 2204static void toggle_pause(void)
01310af2
FB
2205{
2206 if (cur_stream)
2207 stream_pause(cur_stream);
bba04f1e
WH
2208 step = 0;
2209}
2210
7b49ce2e 2211static void step_to_next_frame(void)
bba04f1e
WH
2212{
2213 if (cur_stream) {
19cc524a 2214 /* if the stream is paused unpause it, then step */
bba04f1e 2215 if (cur_stream->paused)
19cc524a 2216 stream_pause(cur_stream);
bba04f1e
WH
2217 }
2218 step = 1;
01310af2
FB
2219}
2220
7b49ce2e 2221static void do_exit(void)
01310af2
FB
2222{
2223 if (cur_stream) {
2224 stream_close(cur_stream);
2225 cur_stream = NULL;
2226 }
2227 if (show_status)
2228 printf("\n");
2229 SDL_Quit();
2230 exit(0);
2231}
2232
7b49ce2e 2233static void toggle_audio_display(void)
01310af2
FB
2234{
2235 if (cur_stream) {
2236 cur_stream->show_audio = !cur_stream->show_audio;
2237 }
2238}
2239
2240/* handle an event sent by the GUI */
7b49ce2e 2241static void event_loop(void)
01310af2
FB
2242{
2243 SDL_Event event;
a11d11aa 2244 double incr, pos, frac;
01310af2
FB
2245
2246 for(;;) {
2247 SDL_WaitEvent(&event);
2248 switch(event.type) {
2249 case SDL_KEYDOWN:
2250 switch(event.key.keysym.sym) {
2251 case SDLK_ESCAPE:
2252 case SDLK_q:
2253 do_exit();
2254 break;
2255 case SDLK_f:
2256 toggle_full_screen();
2257 break;
2258 case SDLK_p:
2259 case SDLK_SPACE:
2260 toggle_pause();
2261 break;
bba04f1e
WH
2262 case SDLK_s: //S: Step to next frame
2263 step_to_next_frame();
2264 break;
01310af2 2265 case SDLK_a:
115329f1 2266 if (cur_stream)
638c9d91
FB
2267 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2268 break;
2269 case SDLK_v:
115329f1 2270 if (cur_stream)
638c9d91
FB
2271 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2272 break;
72ce053b 2273 case SDLK_t:
115329f1 2274 if (cur_stream)
72ce053b
IC
2275 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2276 break;
638c9d91 2277 case SDLK_w:
01310af2
FB
2278 toggle_audio_display();
2279 break;
72ea344b
FB
2280 case SDLK_LEFT:
2281 incr = -10.0;
2282 goto do_seek;
2283 case SDLK_RIGHT:
2284 incr = 10.0;
2285 goto do_seek;
2286 case SDLK_UP:
2287 incr = 60.0;
2288 goto do_seek;
2289 case SDLK_DOWN:
2290 incr = -60.0;
2291 do_seek:
2292 if (cur_stream) {
94b594c6 2293 if (seek_by_bytes) {
899681cd 2294 pos = url_ftell(cur_stream->ic->pb);
94b594c6
SH
2295 if (cur_stream->ic->bit_rate)
2296 incr *= cur_stream->ic->bit_rate / 60.0;
2297 else
2298 incr *= 180000.0;
2299 pos += incr;
2300 stream_seek(cur_stream, pos, incr);
2301 } else {
2302 pos = get_master_clock(cur_stream);
2303 pos += incr;
2304 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
2305 }
72ea344b
FB
2306 }
2307 break;
01310af2
FB
2308 default:
2309 break;
2310 }
2311 break;
a11d11aa 2312 case SDL_MOUSEBUTTONDOWN:
bb270c08
DB
2313 if (cur_stream) {
2314 int ns, hh, mm, ss;
2315 int tns, thh, tmm, tss;
2316 tns = cur_stream->ic->duration/1000000LL;
2317 thh = tns/3600;
2318 tmm = (tns%3600)/60;
2319 tss = (tns%60);
2320 frac = (double)event.button.x/(double)cur_stream->width;
2321 ns = frac*tns;
2322 hh = ns/3600;
2323 mm = (ns%3600)/60;
2324 ss = (ns%60);
2325 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2326 hh, mm, ss, thh, tmm, tss);
2327 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2328 }
2329 break;
01310af2
FB
2330 case SDL_VIDEORESIZE:
2331 if (cur_stream) {
115329f1 2332 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2 2333 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
c57d3469
MN
2334 screen_width = cur_stream->width = event.resize.w;
2335 screen_height= cur_stream->height= event.resize.h;
01310af2
FB
2336 }
2337 break;
2338 case SDL_QUIT:
638c9d91 2339 case FF_QUIT_EVENT:
01310af2
FB
2340 do_exit();
2341 break;
2342 case FF_ALLOC_EVENT:
fccb19e3 2343 video_open(event.user.data1);
01310af2
FB
2344 alloc_picture(event.user.data1);
2345 break;
2346 case FF_REFRESH_EVENT:
2347 video_refresh_timer(event.user.data1);
2348 break;
2349 default:
2350 break;
2351 }
2352 }
2353}
2354
e4b89522
LW
2355static void opt_frame_size(const char *arg)
2356{
b33ece16 2357 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
e4b89522
LW
2358 fprintf(stderr, "Incorrect frame size\n");
2359 exit(1);
2360 }
2361 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2362 fprintf(stderr, "Frame size must be a multiple of 2\n");
2363 exit(1);
2364 }
2365}
2366
a5b3b5f6 2367static int opt_width(const char *opt, const char *arg)
01310af2 2368{
a5b3b5f6
SS
2369 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2370 return 0;
01310af2
FB
2371}
2372
a5b3b5f6 2373static int opt_height(const char *opt, const char *arg)
01310af2 2374{
a5b3b5f6
SS
2375 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2376 return 0;
01310af2
FB
2377}
2378
2379static void opt_format(const char *arg)
2380{
2381 file_iformat = av_find_input_format(arg);
2382 if (!file_iformat) {
2383 fprintf(stderr, "Unknown input format: %s\n", arg);
2384 exit(1);
2385 }
2386}
61890b02 2387
e4b89522
LW
2388static void opt_frame_pix_fmt(const char *arg)
2389{
2390 frame_pix_fmt = avcodec_get_pix_fmt(arg);
2391}
2392
b81d6235 2393static int opt_sync(const char *opt, const char *arg)
638c9d91
FB
2394{
2395 if (!strcmp(arg, "audio"))
2396 av_sync_type = AV_SYNC_AUDIO_MASTER;
2397 else if (!strcmp(arg, "video"))
2398 av_sync_type = AV_SYNC_VIDEO_MASTER;
2399 else if (!strcmp(arg, "ext"))
2400 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
aab1b7e5 2401 else {
b81d6235 2402 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
aab1b7e5
SS
2403 exit(1);
2404 }
b81d6235 2405 return 0;
638c9d91
FB
2406}
2407
e11bc2c6 2408static int opt_seek(const char *opt, const char *arg)
72ea344b 2409{
e11bc2c6
SS
2410 start_time = parse_time_or_die(opt, arg, 1);
2411 return 0;
72ea344b
FB
2412}
2413
a5b3b5f6 2414static int opt_debug(const char *opt, const char *arg)
e26a8335 2415{
a309073b 2416 av_log_set_level(99);
a5b3b5f6
SS
2417 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2418 return 0;
e26a8335 2419}
115329f1 2420
a5b3b5f6 2421static int opt_vismv(const char *opt, const char *arg)
0c9bbaec 2422{
a5b3b5f6
SS
2423 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2424 return 0;
0c9bbaec 2425}
c62c07d3 2426
a5b3b5f6 2427static int opt_thread_count(const char *opt, const char *arg)
c62c07d3 2428{
a5b3b5f6 2429 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2450cff2 2430#if !defined(HAVE_THREADS)
c62c07d3
MN
2431 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2432#endif
a5b3b5f6 2433 return 0;
c62c07d3 2434}
115329f1 2435
358061f6 2436static const OptionDef options[] = {
20176cbc
MN
2437 { "h", OPT_EXIT, {(void*)show_help}, "show help" },
2438 { "version", OPT_EXIT, {(void*)show_version}, "show version" },
8fdea204 2439 { "L", OPT_EXIT, {(void*)show_license}, "show license" },
a28b7ed4 2440 { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
a5b3b5f6
SS
2441 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2442 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
e4b89522 2443 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
638c9d91 2444 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2445 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2446 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
a8062103 2447 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "", "" },
4d8243d3 2448 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "", "" },
e11bc2c6 2449 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
94b594c6 2450 { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
01310af2
FB
2451 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2452 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
e4b89522 2453 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
01310af2 2454 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
a5b3b5f6 2455 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2456 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
a5b3b5f6 2457 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2458 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2459 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
5039185a 2460 { "drp", OPT_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
178fcca8 2461 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2462 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2463 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2464 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2465 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
1b51e051
MN
2466 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
2467 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
b81d6235 2468 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
a5b3b5f6 2469 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
01310af2
FB
2470 { NULL, },
2471};
2472
358061f6 2473static void show_help(void)
01310af2 2474{
9c5755ee 2475 printf("usage: ffplay [options] input_file\n"
01310af2
FB
2476 "Simple media player\n");
2477 printf("\n");
02d504a7
FB
2478 show_help_options(options, "Main options:\n",
2479 OPT_EXPERT, 0);
2480 show_help_options(options, "\nAdvanced options:\n",
2481 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2482 printf("\nWhile playing:\n"
2483 "q, ESC quit\n"
2484 "f toggle full screen\n"
2485 "p, SPC pause\n"
638c9d91
FB
2486 "a cycle audio channel\n"
2487 "v cycle video channel\n"
72ce053b 2488 "t cycle subtitle channel\n"
638c9d91 2489 "w show audio waves\n"
72ea344b
FB
2490 "left/right seek backward/forward 10 seconds\n"
2491 "down/up seek backward/forward 1 minute\n"
a11d11aa 2492 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2 2493 );
01310af2
FB
2494}
2495
358061f6 2496static void opt_input_file(const char *filename)
01310af2 2497{
e8d83e1c 2498 if (!strcmp(filename, "-"))
9fcfc0b7 2499 filename = "pipe:";
01310af2
FB
2500 input_filename = filename;
2501}
2502
2503/* Called from the main */
2504int main(int argc, char **argv)
2505{
fccb19e3 2506 int flags;
115329f1 2507
01310af2 2508 /* register all codecs, demux and protocols */
c721d803
LA
2509 avcodec_register_all();
2510 avdevice_register_all();
01310af2
FB
2511 av_register_all();
2512
ea9c581f 2513 show_banner();
4cfac5bc 2514
f5da5c93 2515 parse_options(argc, argv, options, opt_input_file);
01310af2 2516
aab1b7e5 2517 if (!input_filename) {
01310af2 2518 show_help();
aab1b7e5
SS
2519 exit(1);
2520 }
01310af2
FB
2521
2522 if (display_disable) {
2523 video_disable = 1;
2524 }
31319a8c 2525 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
c97f5402
DB
2526#if !defined(__MINGW32__) && !defined(__APPLE__)
2527 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
31319a8c 2528#endif
01310af2 2529 if (SDL_Init (flags)) {
05ab0b76 2530 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2531 exit(1);
2532 }
2533
2534 if (!display_disable) {
29f3b38a 2535#ifdef HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2536 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2537 fs_screen_width = vi->current_w;
2538 fs_screen_height = vi->current_h;
29f3b38a 2539#endif
01310af2
FB
2540 }
2541
2542 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2543 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2544 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2545 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2546
39c6a118
MN
2547 av_init_packet(&flush_pkt);
2548 flush_pkt.data= "FLUSH";
2549
638c9d91 2550 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2551
2552 event_loop();
2553
2554 /* never returns */
2555
2556 return 0;
2557}