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