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