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