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