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