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