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