Fix warnings about redefining constants when compiling libpostproc.
[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;
70a4764d 210static int seek_by_bytes=-1;
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 1973
70a4764d
MN
1974 if(seek_by_bytes<0)
1975 seek_by_bytes= !!(ic->iformat->flags & AVFMT_TS_DISCONT);
1976
72ea344b
FB
1977 /* if seeking requested, we execute it */
1978 if (start_time != AV_NOPTS_VALUE) {
1979 int64_t timestamp;
1980
1981 timestamp = start_time;
1982 /* add the stream start time */
1983 if (ic->start_time != AV_NOPTS_VALUE)
1984 timestamp += ic->start_time;
4ed29207 1985 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
72ea344b 1986 if (ret < 0) {
115329f1 1987 fprintf(stderr, "%s: could not seek to position %0.3f\n",
72ea344b
FB
1988 is->filename, (double)timestamp / AV_TIME_BASE);
1989 }
1990 }
72ea344b 1991
01310af2 1992 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1993 AVCodecContext *enc = ic->streams[i]->codec;
3f3fe38d 1994 ic->streams[i]->discard = AVDISCARD_ALL;
01310af2
FB
1995 switch(enc->codec_type) {
1996 case CODEC_TYPE_AUDIO:
5dbb63fe 1997 if (wanted_audio_stream-- >= 0 && !audio_disable)
01310af2
FB
1998 audio_index = i;
1999 break;
2000 case CODEC_TYPE_VIDEO:
5dbb63fe 2001 if (wanted_video_stream-- >= 0 && !video_disable)
01310af2
FB
2002 video_index = i;
2003 break;
16a59a7b 2004 case CODEC_TYPE_SUBTITLE:
5ad4f0d4 2005 if (wanted_subtitle_stream-- >= 0 && !video_disable)
16a59a7b
BA
2006 subtitle_index = i;
2007 break;
01310af2
FB
2008 default:
2009 break;
2010 }
2011 }
2012 if (show_status) {
2013 dump_format(ic, 0, is->filename, 0);
2014 }
2015
2016 /* open the streams */
2017 if (audio_index >= 0) {
2018 stream_component_open(is, audio_index);
2019 }
2020
2021 if (video_index >= 0) {
2022 stream_component_open(is, video_index);
2023 } else {
2024 if (!display_disable)
2025 is->show_audio = 1;
2026 }
2027
16a59a7b
BA
2028 if (subtitle_index >= 0) {
2029 stream_component_open(is, subtitle_index);
2030 }
2031
01310af2 2032 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
2033 fprintf(stderr, "%s: could not open codecs\n", is->filename);
2034 ret = -1;
01310af2
FB
2035 goto fail;
2036 }
2037
2038 for(;;) {
2039 if (is->abort_request)
2040 break;
416e3508
FB
2041 if (is->paused != is->last_paused) {
2042 is->last_paused = is->paused;
72ea344b 2043 if (is->paused)
f5668147 2044 is->read_pause_return= av_read_pause(ic);
72ea344b
FB
2045 else
2046 av_read_play(ic);
416e3508 2047 }
2f642393
AJ
2048#if CONFIG_RTSP_DEMUXER
2049 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
416e3508
FB
2050 /* wait 10 ms to avoid trying to get another packet */
2051 /* XXX: horrible */
2052 SDL_Delay(10);
2053 continue;
2054 }
400738b1 2055#endif
72ea344b 2056 if (is->seek_req) {
8e606cc8 2057 int64_t seek_target= is->seek_pos;
4ed29207
MN
2058 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2059 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2060//FIXME the +-2 is due to rounding being not done in the correct direction in generation
2061// of the seek_pos/seek_rel variables
8e606cc8 2062
4ed29207 2063 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
72ea344b
FB
2064 if (ret < 0) {
2065 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
2066 }else{
2067 if (is->audio_stream >= 0) {
2068 packet_queue_flush(&is->audioq);
39c6a118 2069 packet_queue_put(&is->audioq, &flush_pkt);
e6c0297f 2070 }
72ce053b
IC
2071 if (is->subtitle_stream >= 0) {
2072 packet_queue_flush(&is->subtitleq);
39c6a118 2073 packet_queue_put(&is->subtitleq, &flush_pkt);
72ce053b 2074 }
e6c0297f
MN
2075 if (is->video_stream >= 0) {
2076 packet_queue_flush(&is->videoq);
39c6a118 2077 packet_queue_put(&is->videoq, &flush_pkt);
e6c0297f 2078 }
72ea344b
FB
2079 }
2080 is->seek_req = 0;
e45aeb38 2081 eof= 0;
72ea344b 2082 }
416e3508 2083
01310af2 2084 /* if the queue are full, no need to read more */
79ee4683
MN
2085 if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2086 || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream<0)
2087 && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream<0)
2088 && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream<0))) {
01310af2
FB
2089 /* wait 10 ms */
2090 SDL_Delay(10);
2091 continue;
2092 }
75bb7b0a 2093 if(url_feof(ic->pb) || eof) {
9dc41767 2094 if(is->video_stream >= 0){
26534fe8
MN
2095 av_init_packet(pkt);
2096 pkt->data=NULL;
2097 pkt->size=0;
2098 pkt->stream_index= is->video_stream;
2099 packet_queue_put(&is->videoq, pkt);
9dc41767 2100 }
b4083171 2101 SDL_Delay(10);
600a331c
MN
2102 continue;
2103 }
72ea344b 2104 ret = av_read_frame(ic, pkt);
01310af2 2105 if (ret < 0) {
75bb7b0a
MN
2106 if (ret == AVERROR_EOF)
2107 eof=1;
2108 if (url_ferror(ic->pb))
bb270c08 2109 break;
75bb7b0a
MN
2110 SDL_Delay(100); /* wait for user event */
2111 continue;
01310af2
FB
2112 }
2113 if (pkt->stream_index == is->audio_stream) {
2114 packet_queue_put(&is->audioq, pkt);
2115 } else if (pkt->stream_index == is->video_stream) {
2116 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
2117 } else if (pkt->stream_index == is->subtitle_stream) {
2118 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
2119 } else {
2120 av_free_packet(pkt);
2121 }
2122 }
2123 /* wait until the end */
2124 while (!is->abort_request) {
2125 SDL_Delay(100);
2126 }
2127
638c9d91 2128 ret = 0;
01310af2 2129 fail:
416e3508
FB
2130 /* disable interrupting */
2131 global_video_state = NULL;
2132
01310af2
FB
2133 /* close each stream */
2134 if (is->audio_stream >= 0)
2135 stream_component_close(is, is->audio_stream);
2136 if (is->video_stream >= 0)
2137 stream_component_close(is, is->video_stream);
72ce053b
IC
2138 if (is->subtitle_stream >= 0)
2139 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
2140 if (is->ic) {
2141 av_close_input_file(is->ic);
2142 is->ic = NULL; /* safety */
2143 }
416e3508
FB
2144 url_set_interrupt_cb(NULL);
2145
638c9d91
FB
2146 if (ret != 0) {
2147 SDL_Event event;
115329f1 2148
638c9d91
FB
2149 event.type = FF_QUIT_EVENT;
2150 event.user.data1 = is;
2151 SDL_PushEvent(&event);
2152 }
01310af2
FB
2153 return 0;
2154}
2155
638c9d91 2156static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
2157{
2158 VideoState *is;
2159
2160 is = av_mallocz(sizeof(VideoState));
2161 if (!is)
2162 return NULL;
f7d78f36 2163 av_strlcpy(is->filename, filename, sizeof(is->filename));
638c9d91 2164 is->iformat = iformat;
01310af2
FB
2165 is->ytop = 0;
2166 is->xleft = 0;
2167
2168 /* start video display */
2169 is->pictq_mutex = SDL_CreateMutex();
2170 is->pictq_cond = SDL_CreateCond();
115329f1 2171
72ce053b
IC
2172 is->subpq_mutex = SDL_CreateMutex();
2173 is->subpq_cond = SDL_CreateCond();
115329f1 2174
01310af2
FB
2175 /* add the refresh timer to draw the picture */
2176 schedule_refresh(is, 40);
2177
638c9d91 2178 is->av_sync_type = av_sync_type;
01310af2
FB
2179 is->parse_tid = SDL_CreateThread(decode_thread, is);
2180 if (!is->parse_tid) {
2181 av_free(is);
2182 return NULL;
2183 }
2184 return is;
2185}
2186
2187static void stream_close(VideoState *is)
2188{
2189 VideoPicture *vp;
2190 int i;
2191 /* XXX: use a special url_shutdown call to abort parse cleanly */
2192 is->abort_request = 1;
2193 SDL_WaitThread(is->parse_tid, NULL);
2194
2195 /* free all pictures */
2196 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2197 vp = &is->pictq[i];
2198 if (vp->bmp) {
2199 SDL_FreeYUVOverlay(vp->bmp);
2200 vp->bmp = NULL;
2201 }
2202 }
2203 SDL_DestroyMutex(is->pictq_mutex);
2204 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2205 SDL_DestroyMutex(is->subpq_mutex);
2206 SDL_DestroyCond(is->subpq_cond);
3ac56e28
MS
2207 if (is->img_convert_ctx)
2208 sws_freeContext(is->img_convert_ctx);
7c5ab145 2209 av_free(is);
01310af2
FB
2210}
2211
7b49ce2e 2212static void stream_cycle_channel(VideoState *is, int codec_type)
638c9d91
FB
2213{
2214 AVFormatContext *ic = is->ic;
2215 int start_index, stream_index;
2216 AVStream *st;
2217
2218 if (codec_type == CODEC_TYPE_VIDEO)
2219 start_index = is->video_stream;
72ce053b 2220 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2221 start_index = is->audio_stream;
72ce053b
IC
2222 else
2223 start_index = is->subtitle_stream;
2224 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2225 return;
2226 stream_index = start_index;
2227 for(;;) {
2228 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2229 {
2230 if (codec_type == CODEC_TYPE_SUBTITLE)
2231 {
2232 stream_index = -1;
2233 goto the_end;
2234 } else
2235 stream_index = 0;
2236 }
638c9d91
FB
2237 if (stream_index == start_index)
2238 return;
2239 st = ic->streams[stream_index];
01f4895c 2240 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2241 /* check that parameters are OK */
2242 switch(codec_type) {
2243 case CODEC_TYPE_AUDIO:
01f4895c
MN
2244 if (st->codec->sample_rate != 0 &&
2245 st->codec->channels != 0)
638c9d91
FB
2246 goto the_end;
2247 break;
2248 case CODEC_TYPE_VIDEO:
72ce053b 2249 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2250 goto the_end;
2251 default:
2252 break;
2253 }
2254 }
2255 }
2256 the_end:
2257 stream_component_close(is, start_index);
2258 stream_component_open(is, stream_index);
2259}
2260
2261
7b49ce2e 2262static void toggle_full_screen(void)
01310af2 2263{
01310af2 2264 is_full_screen = !is_full_screen;
29f3b38a
MR
2265 if (!fs_screen_width) {
2266 /* use default SDL method */
fb84155b 2267// SDL_WM_ToggleFullScreen(screen);
01310af2 2268 }
fb84155b 2269 video_open(cur_stream);
01310af2
FB
2270}
2271
7b49ce2e 2272static void toggle_pause(void)
01310af2
FB
2273{
2274 if (cur_stream)
2275 stream_pause(cur_stream);
bba04f1e
WH
2276 step = 0;
2277}
2278
7b49ce2e 2279static void step_to_next_frame(void)
bba04f1e
WH
2280{
2281 if (cur_stream) {
19cc524a 2282 /* if the stream is paused unpause it, then step */
bba04f1e 2283 if (cur_stream->paused)
19cc524a 2284 stream_pause(cur_stream);
bba04f1e
WH
2285 }
2286 step = 1;
01310af2
FB
2287}
2288
7b49ce2e 2289static void do_exit(void)
01310af2 2290{
7c5ab145 2291 int i;
01310af2
FB
2292 if (cur_stream) {
2293 stream_close(cur_stream);
2294 cur_stream = NULL;
2295 }
7c5ab145
MS
2296 for (i = 0; i < CODEC_TYPE_NB; i++)
2297 av_free(avcodec_opts[i]);
2298 av_free(avformat_opts);
2299 av_free(sws_opts);
01310af2
FB
2300 if (show_status)
2301 printf("\n");
2302 SDL_Quit();
2303 exit(0);
2304}
2305
7b49ce2e 2306static void toggle_audio_display(void)
01310af2
FB
2307{
2308 if (cur_stream) {
2309 cur_stream->show_audio = !cur_stream->show_audio;
2310 }
2311}
2312
2313/* handle an event sent by the GUI */
7b49ce2e 2314static void event_loop(void)
01310af2
FB
2315{
2316 SDL_Event event;
a11d11aa 2317 double incr, pos, frac;
01310af2
FB
2318
2319 for(;;) {
2320 SDL_WaitEvent(&event);
2321 switch(event.type) {
2322 case SDL_KEYDOWN:
2323 switch(event.key.keysym.sym) {
2324 case SDLK_ESCAPE:
2325 case SDLK_q:
2326 do_exit();
2327 break;
2328 case SDLK_f:
2329 toggle_full_screen();
2330 break;
2331 case SDLK_p:
2332 case SDLK_SPACE:
2333 toggle_pause();
2334 break;
bba04f1e
WH
2335 case SDLK_s: //S: Step to next frame
2336 step_to_next_frame();
2337 break;
01310af2 2338 case SDLK_a:
115329f1 2339 if (cur_stream)
638c9d91
FB
2340 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2341 break;
2342 case SDLK_v:
115329f1 2343 if (cur_stream)
638c9d91
FB
2344 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2345 break;
72ce053b 2346 case SDLK_t:
115329f1 2347 if (cur_stream)
72ce053b
IC
2348 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2349 break;
638c9d91 2350 case SDLK_w:
01310af2
FB
2351 toggle_audio_display();
2352 break;
72ea344b
FB
2353 case SDLK_LEFT:
2354 incr = -10.0;
2355 goto do_seek;
2356 case SDLK_RIGHT:
2357 incr = 10.0;
2358 goto do_seek;
2359 case SDLK_UP:
2360 incr = 60.0;
2361 goto do_seek;
2362 case SDLK_DOWN:
2363 incr = -60.0;
2364 do_seek:
2365 if (cur_stream) {
94b594c6 2366 if (seek_by_bytes) {
1a620dd7
MN
2367 if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos>=0){
2368 pos= cur_stream->video_current_pos;
2369 }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){
2370 pos= cur_stream->audio_pkt.pos;
2371 }else
2372 pos = url_ftell(cur_stream->ic->pb);
94b594c6
SH
2373 if (cur_stream->ic->bit_rate)
2374 incr *= cur_stream->ic->bit_rate / 60.0;
2375 else
2376 incr *= 180000.0;
2377 pos += incr;
2ef46053 2378 stream_seek(cur_stream, pos, incr, 1);
94b594c6
SH
2379 } else {
2380 pos = get_master_clock(cur_stream);
2381 pos += incr;
2ef46053 2382 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
94b594c6 2383 }
72ea344b
FB
2384 }
2385 break;
01310af2
FB
2386 default:
2387 break;
2388 }
2389 break;
a11d11aa 2390 case SDL_MOUSEBUTTONDOWN:
bb270c08 2391 if (cur_stream) {
2ef46053
MN
2392 if(seek_by_bytes || cur_stream->ic->duration<=0){
2393 uint64_t size= url_fsize(cur_stream->ic->pb);
2394 stream_seek(cur_stream, size*(double)event.button.x/(double)cur_stream->width, 0, 1);
2395 }else{
6371c81a
MN
2396 int64_t ts;
2397 int ns, hh, mm, ss;
2398 int tns, thh, tmm, tss;
2399 tns = cur_stream->ic->duration/1000000LL;
2400 thh = tns/3600;
2401 tmm = (tns%3600)/60;
2402 tss = (tns%60);
2403 frac = (double)event.button.x/(double)cur_stream->width;
2404 ns = frac*tns;
2405 hh = ns/3600;
2406 mm = (ns%3600)/60;
2407 ss = (ns%60);
2408 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2409 hh, mm, ss, thh, tmm, tss);
2410 ts = frac*cur_stream->ic->duration;
2411 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2412 ts += cur_stream->ic->start_time;
2413 stream_seek(cur_stream, ts, 0, 0);
2ef46053 2414 }
bb270c08
DB
2415 }
2416 break;
01310af2
FB
2417 case SDL_VIDEORESIZE:
2418 if (cur_stream) {
115329f1 2419 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2 2420 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
c57d3469
MN
2421 screen_width = cur_stream->width = event.resize.w;
2422 screen_height= cur_stream->height= event.resize.h;
01310af2
FB
2423 }
2424 break;
2425 case SDL_QUIT:
638c9d91 2426 case FF_QUIT_EVENT:
01310af2
FB
2427 do_exit();
2428 break;
2429 case FF_ALLOC_EVENT:
fccb19e3 2430 video_open(event.user.data1);
01310af2
FB
2431 alloc_picture(event.user.data1);
2432 break;
2433 case FF_REFRESH_EVENT:
2434 video_refresh_timer(event.user.data1);
2435 break;
2436 default:
2437 break;
2438 }
2439 }
2440}
2441
e4b89522
LW
2442static void opt_frame_size(const char *arg)
2443{
b33ece16 2444 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
e4b89522
LW
2445 fprintf(stderr, "Incorrect frame size\n");
2446 exit(1);
2447 }
2448 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2449 fprintf(stderr, "Frame size must be a multiple of 2\n");
2450 exit(1);
2451 }
2452}
2453
a5b3b5f6 2454static int opt_width(const char *opt, const char *arg)
01310af2 2455{
a5b3b5f6
SS
2456 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2457 return 0;
01310af2
FB
2458}
2459
a5b3b5f6 2460static int opt_height(const char *opt, const char *arg)
01310af2 2461{
a5b3b5f6
SS
2462 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2463 return 0;
01310af2
FB
2464}
2465
2466static void opt_format(const char *arg)
2467{
2468 file_iformat = av_find_input_format(arg);
2469 if (!file_iformat) {
2470 fprintf(stderr, "Unknown input format: %s\n", arg);
2471 exit(1);
2472 }
2473}
61890b02 2474
e4b89522
LW
2475static void opt_frame_pix_fmt(const char *arg)
2476{
718c7b18 2477 frame_pix_fmt = av_get_pix_fmt(arg);
e4b89522
LW
2478}
2479
b81d6235 2480static int opt_sync(const char *opt, const char *arg)
638c9d91
FB
2481{
2482 if (!strcmp(arg, "audio"))
2483 av_sync_type = AV_SYNC_AUDIO_MASTER;
2484 else if (!strcmp(arg, "video"))
2485 av_sync_type = AV_SYNC_VIDEO_MASTER;
2486 else if (!strcmp(arg, "ext"))
2487 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
aab1b7e5 2488 else {
b81d6235 2489 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
aab1b7e5
SS
2490 exit(1);
2491 }
b81d6235 2492 return 0;
638c9d91
FB
2493}
2494
e11bc2c6 2495static int opt_seek(const char *opt, const char *arg)
72ea344b 2496{
e11bc2c6
SS
2497 start_time = parse_time_or_die(opt, arg, 1);
2498 return 0;
72ea344b
FB
2499}
2500
a5b3b5f6 2501static int opt_debug(const char *opt, const char *arg)
e26a8335 2502{
a309073b 2503 av_log_set_level(99);
a5b3b5f6
SS
2504 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2505 return 0;
e26a8335 2506}
115329f1 2507
a5b3b5f6 2508static int opt_vismv(const char *opt, const char *arg)
0c9bbaec 2509{
a5b3b5f6
SS
2510 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2511 return 0;
0c9bbaec 2512}
c62c07d3 2513
a5b3b5f6 2514static int opt_thread_count(const char *opt, const char *arg)
c62c07d3 2515{
a5b3b5f6 2516 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
b250f9c6 2517#if !HAVE_THREADS
c62c07d3
MN
2518 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2519#endif
a5b3b5f6 2520 return 0;
c62c07d3 2521}
115329f1 2522
358061f6 2523static const OptionDef options[] = {
992f8eae 2524#include "cmdutils_common_opts.h"
a5b3b5f6
SS
2525 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2526 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
e4b89522 2527 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
638c9d91 2528 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2529 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2530 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
4b037567
SS
2531 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "select desired audio stream", "stream_number" },
2532 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "select desired video stream", "stream_number" },
2533 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "select desired subtitle stream", "stream_number" },
e11bc2c6 2534 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
70a4764d 2535 { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto" },
01310af2
FB
2536 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2537 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
e4b89522 2538 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
98ae6acf 2539 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
a5b3b5f6 2540 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2541 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
a5b3b5f6 2542 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2543 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2544 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
59055363 2545 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts 0=off 1=on -1=auto", ""},
178fcca8 2546 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2547 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2548 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2549 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2550 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
047599a4 2551 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
1b51e051 2552 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
b81d6235 2553 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
a5b3b5f6 2554 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
e43d7a18 2555 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
01310af2
FB
2556 { NULL, },
2557};
2558
0c2a18cb 2559static void show_usage(void)
01310af2 2560{
27daa420
RP
2561 printf("Simple media player\n");
2562 printf("usage: ffplay [options] input_file\n");
01310af2 2563 printf("\n");
0c2a18cb
RP
2564}
2565
2566static void show_help(void)
2567{
2568 show_usage();
02d504a7
FB
2569 show_help_options(options, "Main options:\n",
2570 OPT_EXPERT, 0);
2571 show_help_options(options, "\nAdvanced options:\n",
2572 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2573 printf("\nWhile playing:\n"
2574 "q, ESC quit\n"
2575 "f toggle full screen\n"
2576 "p, SPC pause\n"
638c9d91
FB
2577 "a cycle audio channel\n"
2578 "v cycle video channel\n"
72ce053b 2579 "t cycle subtitle channel\n"
638c9d91 2580 "w show audio waves\n"
72ea344b
FB
2581 "left/right seek backward/forward 10 seconds\n"
2582 "down/up seek backward/forward 1 minute\n"
a11d11aa 2583 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2 2584 );
01310af2
FB
2585}
2586
358061f6 2587static void opt_input_file(const char *filename)
01310af2 2588{
e8d83e1c 2589 if (!strcmp(filename, "-"))
9fcfc0b7 2590 filename = "pipe:";
01310af2
FB
2591 input_filename = filename;
2592}
2593
2594/* Called from the main */
2595int main(int argc, char **argv)
2596{
e43d7a18 2597 int flags, i;
115329f1 2598
01310af2 2599 /* register all codecs, demux and protocols */
c721d803
LA
2600 avcodec_register_all();
2601 avdevice_register_all();
01310af2
FB
2602 av_register_all();
2603
e43d7a18 2604 for(i=0; i<CODEC_TYPE_NB; i++){
636f1c4c 2605 avcodec_opts[i]= avcodec_alloc_context2(i);
e43d7a18 2606 }
8e2fd8e1 2607 avformat_opts = avformat_alloc_context();
e43d7a18
MN
2608 sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
2609
ea9c581f 2610 show_banner();
4cfac5bc 2611
f5da5c93 2612 parse_options(argc, argv, options, opt_input_file);
01310af2 2613
aab1b7e5 2614 if (!input_filename) {
7f11e745 2615 show_usage();
7a7da6b4 2616 fprintf(stderr, "An input file must be specified\n");
7f11e745 2617 fprintf(stderr, "Use -h to get full help or, even better, run 'man ffplay'\n");
aab1b7e5
SS
2618 exit(1);
2619 }
01310af2
FB
2620
2621 if (display_disable) {
2622 video_disable = 1;
2623 }
31319a8c 2624 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
c97f5402
DB
2625#if !defined(__MINGW32__) && !defined(__APPLE__)
2626 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
31319a8c 2627#endif
01310af2 2628 if (SDL_Init (flags)) {
05ab0b76 2629 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2630 exit(1);
2631 }
2632
2633 if (!display_disable) {
b250f9c6 2634#if HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2635 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2636 fs_screen_width = vi->current_w;
2637 fs_screen_height = vi->current_h;
29f3b38a 2638#endif
01310af2
FB
2639 }
2640
2641 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2642 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2643 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2644 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2645
39c6a118
MN
2646 av_init_packet(&flush_pkt);
2647 flush_pkt.data= "FLUSH";
2648
638c9d91 2649 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2650
2651 event_loop();
2652
2653 /* never returns */
2654
2655 return 0;
2656}