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