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