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