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