Dont try generic seek if seek request before first index entry and backward.
[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 */
f04c6e35 1029 diff = get_video_clock(is) - get_master_clock(is);
49410784
TB
1030
1031 /* skip or repeat frame. We take into account the
1032 delay to compute the threshold. I still don't know
1033 if it is the best guess */
1034 sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1035 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1036 if (diff <= -sync_threshold)
1037 delay = 0;
1038 else if (diff >= sync_threshold)
1039 delay = 2 * delay;
1040 }
1041 }
1042
1043 is->frame_timer += delay;
1044 /* compute the REAL delay (we need to do that to avoid
1045 long term errors */
1046 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
1047 if (actual_delay < 0.010) {
1048 /* XXX: should skip picture */
1049 actual_delay = 0.010;
1050 }
1051
eecc17a7
TB
1052#if defined(DEBUG_SYNC)
1053 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1054 delay, actual_delay, frame_current_pts, -diff);
1055#endif
1056
49410784
TB
1057 return actual_delay;
1058}
1059
01310af2
FB
1060/* called to display each frame */
1061static void video_refresh_timer(void *opaque)
1062{
1063 VideoState *is = opaque;
1064 VideoPicture *vp;
638c9d91 1065
72ce053b 1066 SubPicture *sp, *sp2;
01310af2
FB
1067
1068 if (is->video_st) {
1069 if (is->pictq_size == 0) {
48ff3f7c 1070 fprintf(stderr, "Internal error detected in the SDL timer\n");
01310af2 1071 } else {
638c9d91 1072 /* dequeue the picture */
01310af2 1073 vp = &is->pictq[is->pictq_rindex];
638c9d91
FB
1074
1075 /* update current video pts */
1076 is->video_current_pts = vp->pts;
68aefbe8 1077 is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
a3cc2160 1078 is->video_current_pos = vp->pos;
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;
b25453bd 1372 is->frame_timer = (double)av_gettime() / 1000000.0;
967030eb 1373
39c6a118
MN
1374 continue;
1375 }
1376
638c9d91
FB
1377 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1378 this packet, if any */
7fb262b5 1379 is->video_st->codec->reordered_opaque= pkt->pts;
bea18375 1380 len1 = avcodec_decode_video2(is->video_st->codec,
620e8baf 1381 frame, &got_picture,
bea18375 1382 pkt);
620e8baf 1383
99e0b12b 1384 if (got_picture) {
df7d6e48
SS
1385 if(pkt->dts != AV_NOPTS_VALUE){
1386 is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection;
1387 is->last_dts_for_fault_detection= pkt->dts;
1388 }
1389 if(frame->reordered_opaque != AV_NOPTS_VALUE){
1390 is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection;
1391 is->last_pts_for_fault_detection= frame->reordered_opaque;
1392 }
99e0b12b 1393 }
41db429d
MN
1394
1395 if( ( decoder_reorder_pts==1
ecbed31c 1396 || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
41db429d 1397 || pkt->dts == AV_NOPTS_VALUE)
7fb262b5
MN
1398 && frame->reordered_opaque != AV_NOPTS_VALUE)
1399 pts= frame->reordered_opaque;
620e8baf
MN
1400 else if(pkt->dts != AV_NOPTS_VALUE)
1401 pts= pkt->dts;
1402 else
1403 pts= 0;
1404 pts *= av_q2d(is->video_st->time_base);
5039185a 1405
fb966f99
MN
1406// if (len1 < 0)
1407// break;
620e8baf 1408 if (got_picture) {
1a620dd7 1409 if (output_picture2(is, frame, pts, pkt->pos) < 0)
620e8baf
MN
1410 goto the_end;
1411 }
01310af2 1412 av_free_packet(pkt);
115329f1 1413 if (step)
bba04f1e
WH
1414 if (cur_stream)
1415 stream_pause(cur_stream);
01310af2
FB
1416 }
1417 the_end:
c6b1edc9 1418 av_free(frame);
01310af2
FB
1419 return 0;
1420}
1421
72ce053b
IC
1422static int subtitle_thread(void *arg)
1423{
1424 VideoState *is = arg;
1425 SubPicture *sp;
1426 AVPacket pkt1, *pkt = &pkt1;
1427 int len1, got_subtitle;
1428 double pts;
1429 int i, j;
1430 int r, g, b, y, u, v, a;
1431
1432 for(;;) {
1433 while (is->paused && !is->subtitleq.abort_request) {
1434 SDL_Delay(10);
1435 }
1436 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1437 break;
115329f1 1438
39c6a118
MN
1439 if(pkt->data == flush_pkt.data){
1440 avcodec_flush_buffers(is->subtitle_st->codec);
1441 continue;
1442 }
72ce053b
IC
1443 SDL_LockMutex(is->subpq_mutex);
1444 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1445 !is->subtitleq.abort_request) {
1446 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1447 }
1448 SDL_UnlockMutex(is->subpq_mutex);
115329f1 1449
72ce053b
IC
1450 if (is->subtitleq.abort_request)
1451 goto the_end;
115329f1 1452
72ce053b
IC
1453 sp = &is->subpq[is->subpq_windex];
1454
1455 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1456 this packet, if any */
1457 pts = 0;
1458 if (pkt->pts != AV_NOPTS_VALUE)
1459 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1460
bea18375 1461 len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
115329f1 1462 &sp->sub, &got_subtitle,
bea18375 1463 pkt);
72ce053b
IC
1464// if (len1 < 0)
1465// break;
1466 if (got_subtitle && sp->sub.format == 0) {
1467 sp->pts = pts;
115329f1 1468
72ce053b
IC
1469 for (i = 0; i < sp->sub.num_rects; i++)
1470 {
db4fac64 1471 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
72ce053b 1472 {
25b4c651 1473 RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
72ce053b
IC
1474 y = RGB_TO_Y_CCIR(r, g, b);
1475 u = RGB_TO_U_CCIR(r, g, b, 0);
1476 v = RGB_TO_V_CCIR(r, g, b, 0);
25b4c651 1477 YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
72ce053b
IC
1478 }
1479 }
1480
1481 /* now we can update the picture count */
1482 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1483 is->subpq_windex = 0;
1484 SDL_LockMutex(is->subpq_mutex);
1485 is->subpq_size++;
1486 SDL_UnlockMutex(is->subpq_mutex);
1487 }
1488 av_free_packet(pkt);
115329f1 1489// if (step)
72ce053b
IC
1490// if (cur_stream)
1491// stream_pause(cur_stream);
1492 }
1493 the_end:
1494 return 0;
1495}
1496
01310af2
FB
1497/* copy samples for viewing in editor window */
1498static void update_sample_display(VideoState *is, short *samples, int samples_size)
1499{
1500 int size, len, channels;
1501
01f4895c 1502 channels = is->audio_st->codec->channels;
01310af2
FB
1503
1504 size = samples_size / sizeof(short);
1505 while (size > 0) {
1506 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1507 if (len > size)
1508 len = size;
1509 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1510 samples += len;
1511 is->sample_array_index += len;
1512 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1513 is->sample_array_index = 0;
1514 size -= len;
1515 }
1516}
1517
01310af2
FB
1518/* return the new audio buffer size (samples can be added or deleted
1519 to get better sync if video or external master clock) */
115329f1 1520static int synchronize_audio(VideoState *is, short *samples,
638c9d91 1521 int samples_size1, double pts)
01310af2 1522{
638c9d91 1523 int n, samples_size;
01310af2 1524 double ref_clock;
115329f1 1525
01f4895c 1526 n = 2 * is->audio_st->codec->channels;
638c9d91 1527 samples_size = samples_size1;
01310af2 1528
01310af2 1529 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 1530 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
1531 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1532 double diff, avg_diff;
01310af2 1533 int wanted_size, min_size, max_size, nb_samples;
115329f1 1534
638c9d91
FB
1535 ref_clock = get_master_clock(is);
1536 diff = get_audio_clock(is) - ref_clock;
115329f1 1537
638c9d91
FB
1538 if (diff < AV_NOSYNC_THRESHOLD) {
1539 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1540 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1541 /* not enough measures to have a correct estimate */
1542 is->audio_diff_avg_count++;
1543 } else {
1544 /* estimate the A-V difference */
1545 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1546
1547 if (fabs(avg_diff) >= is->audio_diff_threshold) {
01f4895c 1548 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
638c9d91 1549 nb_samples = samples_size / n;
115329f1 1550
638c9d91
FB
1551 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1552 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1553 if (wanted_size < min_size)
1554 wanted_size = min_size;
1555 else if (wanted_size > max_size)
1556 wanted_size = max_size;
115329f1 1557
638c9d91
FB
1558 /* add or remove samples to correction the synchro */
1559 if (wanted_size < samples_size) {
1560 /* remove samples */
1561 samples_size = wanted_size;
1562 } else if (wanted_size > samples_size) {
1563 uint8_t *samples_end, *q;
1564 int nb;
115329f1 1565
638c9d91
FB
1566 /* add samples */
1567 nb = (samples_size - wanted_size);
1568 samples_end = (uint8_t *)samples + samples_size - n;
1569 q = samples_end + n;
1570 while (nb > 0) {
1571 memcpy(q, samples_end, n);
1572 q += n;
1573 nb -= n;
1574 }
1575 samples_size = wanted_size;
1576 }
1577 }
1578#if 0
115329f1
DB
1579 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1580 diff, avg_diff, samples_size - samples_size1,
638c9d91
FB
1581 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1582#endif
01310af2 1583 }
638c9d91
FB
1584 } else {
1585 /* too big difference : may be initial PTS errors, so
1586 reset A-V filter */
1587 is->audio_diff_avg_count = 0;
1588 is->audio_diff_cum = 0;
01310af2
FB
1589 }
1590 }
1591
01310af2
FB
1592 return samples_size;
1593}
1594
1595/* decode one audio frame and returns its uncompressed size */
5a4476e2 1596static int audio_decode_frame(VideoState *is, double *pts_ptr)
01310af2 1597{
bea18375 1598 AVPacket *pkt_temp = &is->audio_pkt_temp;
01310af2 1599 AVPacket *pkt = &is->audio_pkt;
abdff646 1600 AVCodecContext *dec= is->audio_st->codec;
72ea344b 1601 int n, len1, data_size;
01310af2
FB
1602 double pts;
1603
1604 for(;;) {
72ea344b 1605 /* NOTE: the audio packet can contain several frames */
bea18375 1606 while (pkt_temp->size > 0) {
5a4476e2 1607 data_size = sizeof(is->audio_buf1);
bea18375 1608 len1 = avcodec_decode_audio3(dec,
5a4476e2 1609 (int16_t *)is->audio_buf1, &data_size,
bea18375 1610 pkt_temp);
72ea344b
FB
1611 if (len1 < 0) {
1612 /* if error, we skip the frame */
bea18375 1613 pkt_temp->size = 0;
01310af2 1614 break;
72ea344b 1615 }
115329f1 1616
bea18375
TB
1617 pkt_temp->data += len1;
1618 pkt_temp->size -= len1;
72ea344b
FB
1619 if (data_size <= 0)
1620 continue;
5a4476e2
PR
1621
1622 if (dec->sample_fmt != is->audio_src_fmt) {
1623 if (is->reformat_ctx)
1624 av_audio_convert_free(is->reformat_ctx);
1625 is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
1626 dec->sample_fmt, 1, NULL, 0);
1627 if (!is->reformat_ctx) {
1628 fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
1629 avcodec_get_sample_fmt_name(dec->sample_fmt),
1630 avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
1631 break;
1632 }
1633 is->audio_src_fmt= dec->sample_fmt;
1634 }
1635
1636 if (is->reformat_ctx) {
1637 const void *ibuf[6]= {is->audio_buf1};
1638 void *obuf[6]= {is->audio_buf2};
1639 int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
1640 int ostride[6]= {2};
1641 int len= data_size/istride[0];
1642 if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
1643 printf("av_audio_convert() failed\n");
1644 break;
1645 }
1646 is->audio_buf= is->audio_buf2;
1647 /* FIXME: existing code assume that data_size equals framesize*channels*2
1648 remove this legacy cruft */
1649 data_size= len*2;
1650 }else{
1651 is->audio_buf= is->audio_buf1;
1652 }
1653
72ea344b
FB
1654 /* if no pts, then compute it */
1655 pts = is->audio_clock;
1656 *pts_ptr = pts;
abdff646 1657 n = 2 * dec->channels;
115329f1 1658 is->audio_clock += (double)data_size /
abdff646 1659 (double)(n * dec->sample_rate);
638c9d91 1660#if defined(DEBUG_SYNC)
72ea344b
FB
1661 {
1662 static double last_clock;
1663 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1664 is->audio_clock - last_clock,
1665 is->audio_clock, pts);
1666 last_clock = is->audio_clock;
01310af2 1667 }
72ea344b
FB
1668#endif
1669 return data_size;
01310af2
FB
1670 }
1671
72ea344b
FB
1672 /* free the current packet */
1673 if (pkt->data)
01310af2 1674 av_free_packet(pkt);
115329f1 1675
72ea344b
FB
1676 if (is->paused || is->audioq.abort_request) {
1677 return -1;
1678 }
115329f1 1679
01310af2
FB
1680 /* read next packet */
1681 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1682 return -1;
39c6a118 1683 if(pkt->data == flush_pkt.data){
abdff646 1684 avcodec_flush_buffers(dec);
39c6a118
MN
1685 continue;
1686 }
1687
bea18375
TB
1688 pkt_temp->data = pkt->data;
1689 pkt_temp->size = pkt->size;
115329f1 1690
72ea344b
FB
1691 /* if update the audio clock with the pts */
1692 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1693 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1694 }
01310af2
FB
1695 }
1696}
1697
638c9d91
FB
1698/* get the current audio output buffer size, in samples. With SDL, we
1699 cannot have a precise information */
1700static int audio_write_get_buf_size(VideoState *is)
01310af2 1701{
b09b580b 1702 return is->audio_buf_size - is->audio_buf_index;
01310af2
FB
1703}
1704
1705
1706/* prepare a new audio buffer */
358061f6 1707static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
01310af2
FB
1708{
1709 VideoState *is = opaque;
1710 int audio_size, len1;
1711 double pts;
1712
1713 audio_callback_time = av_gettime();
115329f1 1714
01310af2
FB
1715 while (len > 0) {
1716 if (is->audio_buf_index >= is->audio_buf_size) {
5a4476e2 1717 audio_size = audio_decode_frame(is, &pts);
01310af2
FB
1718 if (audio_size < 0) {
1719 /* if error, just output silence */
1a1078fa 1720 is->audio_buf = is->audio_buf1;
01310af2
FB
1721 is->audio_buf_size = 1024;
1722 memset(is->audio_buf, 0, is->audio_buf_size);
1723 } else {
1724 if (is->show_audio)
1725 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
115329f1 1726 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
01310af2
FB
1727 pts);
1728 is->audio_buf_size = audio_size;
1729 }
1730 is->audio_buf_index = 0;
1731 }
1732 len1 = is->audio_buf_size - is->audio_buf_index;
1733 if (len1 > len)
1734 len1 = len;
1735 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1736 len -= len1;
1737 stream += len1;
1738 is->audio_buf_index += len1;
1739 }
1740}
1741
01310af2
FB
1742/* open a given stream. Return 0 if OK */
1743static int stream_component_open(VideoState *is, int stream_index)
1744{
1745 AVFormatContext *ic = is->ic;
1746 AVCodecContext *enc;
1747 AVCodec *codec;
1748 SDL_AudioSpec wanted_spec, spec;
1749
1750 if (stream_index < 0 || stream_index >= ic->nb_streams)
1751 return -1;
01f4895c 1752 enc = ic->streams[stream_index]->codec;
115329f1 1753
01310af2
FB
1754 /* prepare audio output */
1755 if (enc->codec_type == CODEC_TYPE_AUDIO) {
51b73087
JR
1756 if (enc->channels > 0) {
1757 enc->request_channels = FFMIN(2, enc->channels);
94eadc8b 1758 } else {
51b73087 1759 enc->request_channels = 2;
638c9d91 1760 }
01310af2
FB
1761 }
1762
1763 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1764 enc->debug_mv = debug_mv;
1765 enc->debug = debug;
6387c3e6 1766 enc->workaround_bugs = workaround_bugs;
178fcca8 1767 enc->lowres = lowres;
61846e9a 1768 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1769 enc->idct_algo= idct;
6fc5b059 1770 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
8c3eba7c
MN
1771 enc->skip_frame= skip_frame;
1772 enc->skip_idct= skip_idct;
1773 enc->skip_loop_filter= skip_loop_filter;
047599a4 1774 enc->error_recognition= error_recognition;
1b51e051 1775 enc->error_concealment= error_concealment;
40ccc754 1776 avcodec_thread_init(enc, thread_count);
e43d7a18 1777
636f1c4c 1778 set_context_opts(enc, avcodec_opts[enc->codec_type], 0);
e43d7a18 1779
01310af2
FB
1780 if (!codec ||
1781 avcodec_open(enc, codec) < 0)
1782 return -1;
51b73087
JR
1783
1784 /* prepare audio output */
1785 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1786 wanted_spec.freq = enc->sample_rate;
1787 wanted_spec.format = AUDIO_S16SYS;
1788 wanted_spec.channels = enc->channels;
1789 wanted_spec.silence = 0;
1790 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1791 wanted_spec.callback = sdl_audio_callback;
1792 wanted_spec.userdata = is;
1793 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1794 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1795 return -1;
1796 }
1797 is->audio_hw_buf_size = spec.size;
5a4476e2 1798 is->audio_src_fmt= SAMPLE_FMT_S16;
51b73087
JR
1799 }
1800
3f3fe38d 1801 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
638c9d91 1802 switch(enc->codec_type) {
01310af2
FB
1803 case CODEC_TYPE_AUDIO:
1804 is->audio_stream = stream_index;
1805 is->audio_st = ic->streams[stream_index];
1806 is->audio_buf_size = 0;
1807 is->audio_buf_index = 0;
638c9d91
FB
1808
1809 /* init averaging filter */
1810 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1811 is->audio_diff_avg_count = 0;
1812 /* since we do not have a precise anough audio fifo fullness,
1813 we correct audio sync only if larger than this threshold */
1814 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1815
01310af2
FB
1816 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1817 packet_queue_init(&is->audioq);
bb270c08 1818 SDL_PauseAudio(0);
01310af2
FB
1819 break;
1820 case CODEC_TYPE_VIDEO:
1821 is->video_stream = stream_index;
1822 is->video_st = ic->streams[stream_index];
1823
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 {
48ff3f7c
MN
2024 /* add the refresh timer to draw the picture */
2025 schedule_refresh(is, 40);
2026
01310af2
FB
2027 if (!display_disable)
2028 is->show_audio = 1;
2029 }
2030
16a59a7b
BA
2031 if (subtitle_index >= 0) {
2032 stream_component_open(is, subtitle_index);
2033 }
2034
01310af2 2035 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
2036 fprintf(stderr, "%s: could not open codecs\n", is->filename);
2037 ret = -1;
01310af2
FB
2038 goto fail;
2039 }
2040
2041 for(;;) {
2042 if (is->abort_request)
2043 break;
416e3508
FB
2044 if (is->paused != is->last_paused) {
2045 is->last_paused = is->paused;
72ea344b 2046 if (is->paused)
f5668147 2047 is->read_pause_return= av_read_pause(ic);
72ea344b
FB
2048 else
2049 av_read_play(ic);
416e3508 2050 }
2f642393
AJ
2051#if CONFIG_RTSP_DEMUXER
2052 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
416e3508
FB
2053 /* wait 10 ms to avoid trying to get another packet */
2054 /* XXX: horrible */
2055 SDL_Delay(10);
2056 continue;
2057 }
400738b1 2058#endif
72ea344b 2059 if (is->seek_req) {
8e606cc8 2060 int64_t seek_target= is->seek_pos;
4ed29207
MN
2061 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2062 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2063//FIXME the +-2 is due to rounding being not done in the correct direction in generation
2064// of the seek_pos/seek_rel variables
8e606cc8 2065
4ed29207 2066 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
72ea344b
FB
2067 if (ret < 0) {
2068 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
2069 }else{
2070 if (is->audio_stream >= 0) {
2071 packet_queue_flush(&is->audioq);
39c6a118 2072 packet_queue_put(&is->audioq, &flush_pkt);
e6c0297f 2073 }
72ce053b
IC
2074 if (is->subtitle_stream >= 0) {
2075 packet_queue_flush(&is->subtitleq);
39c6a118 2076 packet_queue_put(&is->subtitleq, &flush_pkt);
72ce053b 2077 }
e6c0297f
MN
2078 if (is->video_stream >= 0) {
2079 packet_queue_flush(&is->videoq);
39c6a118 2080 packet_queue_put(&is->videoq, &flush_pkt);
e6c0297f 2081 }
72ea344b
FB
2082 }
2083 is->seek_req = 0;
e45aeb38 2084 eof= 0;
72ea344b 2085 }
416e3508 2086
01310af2 2087 /* if the queue are full, no need to read more */
79ee4683
MN
2088 if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2089 || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream<0)
2090 && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream<0)
2091 && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream<0))) {
01310af2
FB
2092 /* wait 10 ms */
2093 SDL_Delay(10);
2094 continue;
2095 }
75bb7b0a 2096 if(url_feof(ic->pb) || eof) {
9dc41767 2097 if(is->video_stream >= 0){
26534fe8
MN
2098 av_init_packet(pkt);
2099 pkt->data=NULL;
2100 pkt->size=0;
2101 pkt->stream_index= is->video_stream;
2102 packet_queue_put(&is->videoq, pkt);
9dc41767 2103 }
b4083171 2104 SDL_Delay(10);
600a331c
MN
2105 continue;
2106 }
72ea344b 2107 ret = av_read_frame(ic, pkt);
01310af2 2108 if (ret < 0) {
75bb7b0a
MN
2109 if (ret == AVERROR_EOF)
2110 eof=1;
2111 if (url_ferror(ic->pb))
bb270c08 2112 break;
75bb7b0a
MN
2113 SDL_Delay(100); /* wait for user event */
2114 continue;
01310af2
FB
2115 }
2116 if (pkt->stream_index == is->audio_stream) {
2117 packet_queue_put(&is->audioq, pkt);
2118 } else if (pkt->stream_index == is->video_stream) {
2119 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
2120 } else if (pkt->stream_index == is->subtitle_stream) {
2121 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
2122 } else {
2123 av_free_packet(pkt);
2124 }
2125 }
2126 /* wait until the end */
2127 while (!is->abort_request) {
2128 SDL_Delay(100);
2129 }
2130
638c9d91 2131 ret = 0;
01310af2 2132 fail:
416e3508
FB
2133 /* disable interrupting */
2134 global_video_state = NULL;
2135
01310af2
FB
2136 /* close each stream */
2137 if (is->audio_stream >= 0)
2138 stream_component_close(is, is->audio_stream);
2139 if (is->video_stream >= 0)
2140 stream_component_close(is, is->video_stream);
72ce053b
IC
2141 if (is->subtitle_stream >= 0)
2142 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
2143 if (is->ic) {
2144 av_close_input_file(is->ic);
2145 is->ic = NULL; /* safety */
2146 }
416e3508
FB
2147 url_set_interrupt_cb(NULL);
2148
638c9d91
FB
2149 if (ret != 0) {
2150 SDL_Event event;
115329f1 2151
638c9d91
FB
2152 event.type = FF_QUIT_EVENT;
2153 event.user.data1 = is;
2154 SDL_PushEvent(&event);
2155 }
01310af2
FB
2156 return 0;
2157}
2158
638c9d91 2159static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
2160{
2161 VideoState *is;
2162
2163 is = av_mallocz(sizeof(VideoState));
2164 if (!is)
2165 return NULL;
f7d78f36 2166 av_strlcpy(is->filename, filename, sizeof(is->filename));
638c9d91 2167 is->iformat = iformat;
01310af2
FB
2168 is->ytop = 0;
2169 is->xleft = 0;
2170
2171 /* start video display */
2172 is->pictq_mutex = SDL_CreateMutex();
2173 is->pictq_cond = SDL_CreateCond();
115329f1 2174
72ce053b
IC
2175 is->subpq_mutex = SDL_CreateMutex();
2176 is->subpq_cond = SDL_CreateCond();
115329f1 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) {
f5968788 2309 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
01310af2 2310 cur_stream->show_audio = !cur_stream->show_audio;
f5968788
MN
2311 fill_rectangle(screen,
2312 cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height,
2313 bgcolor);
2314 SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height);
01310af2
FB
2315 }
2316}
2317
2318/* handle an event sent by the GUI */
7b49ce2e 2319static void event_loop(void)
01310af2
FB
2320{
2321 SDL_Event event;
a11d11aa 2322 double incr, pos, frac;
01310af2
FB
2323
2324 for(;;) {
2325 SDL_WaitEvent(&event);
2326 switch(event.type) {
2327 case SDL_KEYDOWN:
2328 switch(event.key.keysym.sym) {
2329 case SDLK_ESCAPE:
2330 case SDLK_q:
2331 do_exit();
2332 break;
2333 case SDLK_f:
2334 toggle_full_screen();
2335 break;
2336 case SDLK_p:
2337 case SDLK_SPACE:
2338 toggle_pause();
2339 break;
bba04f1e
WH
2340 case SDLK_s: //S: Step to next frame
2341 step_to_next_frame();
2342 break;
01310af2 2343 case SDLK_a:
115329f1 2344 if (cur_stream)
638c9d91
FB
2345 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2346 break;
2347 case SDLK_v:
115329f1 2348 if (cur_stream)
638c9d91
FB
2349 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2350 break;
72ce053b 2351 case SDLK_t:
115329f1 2352 if (cur_stream)
72ce053b
IC
2353 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2354 break;
638c9d91 2355 case SDLK_w:
01310af2
FB
2356 toggle_audio_display();
2357 break;
72ea344b
FB
2358 case SDLK_LEFT:
2359 incr = -10.0;
2360 goto do_seek;
2361 case SDLK_RIGHT:
2362 incr = 10.0;
2363 goto do_seek;
2364 case SDLK_UP:
2365 incr = 60.0;
2366 goto do_seek;
2367 case SDLK_DOWN:
2368 incr = -60.0;
2369 do_seek:
2370 if (cur_stream) {
94b594c6 2371 if (seek_by_bytes) {
1a620dd7
MN
2372 if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos>=0){
2373 pos= cur_stream->video_current_pos;
2374 }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){
2375 pos= cur_stream->audio_pkt.pos;
2376 }else
2377 pos = url_ftell(cur_stream->ic->pb);
94b594c6 2378 if (cur_stream->ic->bit_rate)
566cd2cb 2379 incr *= cur_stream->ic->bit_rate / 8.0;
94b594c6
SH
2380 else
2381 incr *= 180000.0;
2382 pos += incr;
2ef46053 2383 stream_seek(cur_stream, pos, incr, 1);
94b594c6
SH
2384 } else {
2385 pos = get_master_clock(cur_stream);
2386 pos += incr;
2ef46053 2387 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
94b594c6 2388 }
72ea344b
FB
2389 }
2390 break;
01310af2
FB
2391 default:
2392 break;
2393 }
2394 break;
a11d11aa 2395 case SDL_MOUSEBUTTONDOWN:
bb270c08 2396 if (cur_stream) {
2ef46053
MN
2397 if(seek_by_bytes || cur_stream->ic->duration<=0){
2398 uint64_t size= url_fsize(cur_stream->ic->pb);
2399 stream_seek(cur_stream, size*(double)event.button.x/(double)cur_stream->width, 0, 1);
2400 }else{
6371c81a
MN
2401 int64_t ts;
2402 int ns, hh, mm, ss;
2403 int tns, thh, tmm, tss;
2404 tns = cur_stream->ic->duration/1000000LL;
2405 thh = tns/3600;
2406 tmm = (tns%3600)/60;
2407 tss = (tns%60);
2408 frac = (double)event.button.x/(double)cur_stream->width;
2409 ns = frac*tns;
2410 hh = ns/3600;
2411 mm = (ns%3600)/60;
2412 ss = (ns%60);
2413 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2414 hh, mm, ss, thh, tmm, tss);
2415 ts = frac*cur_stream->ic->duration;
2416 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2417 ts += cur_stream->ic->start_time;
2418 stream_seek(cur_stream, ts, 0, 0);
2ef46053 2419 }
bb270c08
DB
2420 }
2421 break;
01310af2
FB
2422 case SDL_VIDEORESIZE:
2423 if (cur_stream) {
115329f1 2424 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2 2425 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
c57d3469
MN
2426 screen_width = cur_stream->width = event.resize.w;
2427 screen_height= cur_stream->height= event.resize.h;
01310af2
FB
2428 }
2429 break;
2430 case SDL_QUIT:
638c9d91 2431 case FF_QUIT_EVENT:
01310af2
FB
2432 do_exit();
2433 break;
2434 case FF_ALLOC_EVENT:
fccb19e3 2435 video_open(event.user.data1);
01310af2
FB
2436 alloc_picture(event.user.data1);
2437 break;
2438 case FF_REFRESH_EVENT:
2439 video_refresh_timer(event.user.data1);
2440 break;
2441 default:
2442 break;
2443 }
2444 }
2445}
2446
e4b89522
LW
2447static void opt_frame_size(const char *arg)
2448{
b33ece16 2449 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
e4b89522
LW
2450 fprintf(stderr, "Incorrect frame size\n");
2451 exit(1);
2452 }
2453 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2454 fprintf(stderr, "Frame size must be a multiple of 2\n");
2455 exit(1);
2456 }
2457}
2458
a5b3b5f6 2459static int opt_width(const char *opt, const char *arg)
01310af2 2460{
a5b3b5f6
SS
2461 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2462 return 0;
01310af2
FB
2463}
2464
a5b3b5f6 2465static int opt_height(const char *opt, const char *arg)
01310af2 2466{
a5b3b5f6
SS
2467 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2468 return 0;
01310af2
FB
2469}
2470
2471static void opt_format(const char *arg)
2472{
2473 file_iformat = av_find_input_format(arg);
2474 if (!file_iformat) {
2475 fprintf(stderr, "Unknown input format: %s\n", arg);
2476 exit(1);
2477 }
2478}
61890b02 2479
e4b89522
LW
2480static void opt_frame_pix_fmt(const char *arg)
2481{
718c7b18 2482 frame_pix_fmt = av_get_pix_fmt(arg);
e4b89522
LW
2483}
2484
b81d6235 2485static int opt_sync(const char *opt, const char *arg)
638c9d91
FB
2486{
2487 if (!strcmp(arg, "audio"))
2488 av_sync_type = AV_SYNC_AUDIO_MASTER;
2489 else if (!strcmp(arg, "video"))
2490 av_sync_type = AV_SYNC_VIDEO_MASTER;
2491 else if (!strcmp(arg, "ext"))
2492 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
aab1b7e5 2493 else {
b81d6235 2494 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
aab1b7e5
SS
2495 exit(1);
2496 }
b81d6235 2497 return 0;
638c9d91
FB
2498}
2499
e11bc2c6 2500static int opt_seek(const char *opt, const char *arg)
72ea344b 2501{
e11bc2c6
SS
2502 start_time = parse_time_or_die(opt, arg, 1);
2503 return 0;
72ea344b
FB
2504}
2505
a5b3b5f6 2506static int opt_debug(const char *opt, const char *arg)
e26a8335 2507{
a309073b 2508 av_log_set_level(99);
a5b3b5f6
SS
2509 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2510 return 0;
e26a8335 2511}
115329f1 2512
a5b3b5f6 2513static int opt_vismv(const char *opt, const char *arg)
0c9bbaec 2514{
a5b3b5f6
SS
2515 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2516 return 0;
0c9bbaec 2517}
c62c07d3 2518
a5b3b5f6 2519static int opt_thread_count(const char *opt, const char *arg)
c62c07d3 2520{
a5b3b5f6 2521 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
b250f9c6 2522#if !HAVE_THREADS
c62c07d3
MN
2523 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2524#endif
a5b3b5f6 2525 return 0;
c62c07d3 2526}
115329f1 2527
358061f6 2528static const OptionDef options[] = {
992f8eae 2529#include "cmdutils_common_opts.h"
a5b3b5f6
SS
2530 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2531 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
e4b89522 2532 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
638c9d91 2533 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2534 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2535 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
4b037567
SS
2536 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "select desired audio stream", "stream_number" },
2537 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "select desired video stream", "stream_number" },
2538 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "select desired subtitle stream", "stream_number" },
e11bc2c6 2539 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
70a4764d 2540 { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto" },
01310af2
FB
2541 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2542 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
e4b89522 2543 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
98ae6acf 2544 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
a5b3b5f6 2545 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2546 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
a5b3b5f6 2547 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2548 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2549 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
59055363 2550 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts 0=off 1=on -1=auto", ""},
178fcca8 2551 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2552 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2553 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2554 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2555 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
047599a4 2556 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
1b51e051 2557 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
b81d6235 2558 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
a5b3b5f6 2559 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
e43d7a18 2560 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
01310af2
FB
2561 { NULL, },
2562};
2563
0c2a18cb 2564static void show_usage(void)
01310af2 2565{
27daa420
RP
2566 printf("Simple media player\n");
2567 printf("usage: ffplay [options] input_file\n");
01310af2 2568 printf("\n");
0c2a18cb
RP
2569}
2570
2571static void show_help(void)
2572{
2573 show_usage();
02d504a7
FB
2574 show_help_options(options, "Main options:\n",
2575 OPT_EXPERT, 0);
2576 show_help_options(options, "\nAdvanced options:\n",
2577 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2578 printf("\nWhile playing:\n"
2579 "q, ESC quit\n"
2580 "f toggle full screen\n"
2581 "p, SPC pause\n"
638c9d91
FB
2582 "a cycle audio channel\n"
2583 "v cycle video channel\n"
72ce053b 2584 "t cycle subtitle channel\n"
638c9d91 2585 "w show audio waves\n"
72ea344b
FB
2586 "left/right seek backward/forward 10 seconds\n"
2587 "down/up seek backward/forward 1 minute\n"
a11d11aa 2588 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2 2589 );
01310af2
FB
2590}
2591
358061f6 2592static void opt_input_file(const char *filename)
01310af2 2593{
e8d83e1c 2594 if (!strcmp(filename, "-"))
9fcfc0b7 2595 filename = "pipe:";
01310af2
FB
2596 input_filename = filename;
2597}
2598
2599/* Called from the main */
2600int main(int argc, char **argv)
2601{
e43d7a18 2602 int flags, i;
115329f1 2603
01310af2 2604 /* register all codecs, demux and protocols */
c721d803
LA
2605 avcodec_register_all();
2606 avdevice_register_all();
01310af2
FB
2607 av_register_all();
2608
e43d7a18 2609 for(i=0; i<CODEC_TYPE_NB; i++){
636f1c4c 2610 avcodec_opts[i]= avcodec_alloc_context2(i);
e43d7a18 2611 }
8e2fd8e1 2612 avformat_opts = avformat_alloc_context();
e43d7a18
MN
2613 sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
2614
ea9c581f 2615 show_banner();
4cfac5bc 2616
f5da5c93 2617 parse_options(argc, argv, options, opt_input_file);
01310af2 2618
aab1b7e5 2619 if (!input_filename) {
7f11e745 2620 show_usage();
7a7da6b4 2621 fprintf(stderr, "An input file must be specified\n");
7f11e745 2622 fprintf(stderr, "Use -h to get full help or, even better, run 'man ffplay'\n");
aab1b7e5
SS
2623 exit(1);
2624 }
01310af2
FB
2625
2626 if (display_disable) {
2627 video_disable = 1;
2628 }
31319a8c 2629 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
c97f5402
DB
2630#if !defined(__MINGW32__) && !defined(__APPLE__)
2631 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
31319a8c 2632#endif
01310af2 2633 if (SDL_Init (flags)) {
05ab0b76 2634 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2635 exit(1);
2636 }
2637
2638 if (!display_disable) {
b250f9c6 2639#if HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2640 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2641 fs_screen_width = vi->current_w;
2642 fs_screen_height = vi->current_h;
29f3b38a 2643#endif
01310af2
FB
2644 }
2645
2646 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2647 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2648 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2649 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2650
39c6a118
MN
2651 av_init_packet(&flush_pkt);
2652 flush_pkt.data= "FLUSH";
2653
638c9d91 2654 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2655
2656 event_loop();
2657
2658 /* never returns */
2659
2660 return 0;
2661}