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