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