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