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