Move img_convert_ctx to VideoState and free it in stream_close().
[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
0f4e8165
RB
22#include <math.h>
23#include <limits.h>
245976da
DB
24#include "libavutil/avstring.h"
25#include "libavformat/avformat.h"
26#include "libavformat/rtsp.h"
27#include "libavdevice/avdevice.h"
28#include "libswscale/swscale.h"
5a4476e2 29#include "libavcodec/audioconvert.h"
e43d7a18 30#include "libavcodec/opt.h"
01310af2
FB
31
32#include "cmdutils.h"
33
34#include <SDL.h>
35#include <SDL_thread.h>
36
2f30a81d 37#ifdef __MINGW32__
31319a8c
FB
38#undef main /* We don't want SDL to override our main() */
39#endif
40
c367d067
MN
41#undef exit
42
64555bd9 43const char program_name[] = "FFplay";
ea9c581f 44const int program_birth_year = 2003;
4cfac5bc 45
638c9d91
FB
46//#define DEBUG_SYNC
47
01310af2
FB
48#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
49#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
72ce053b 50#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
01310af2 51
638c9d91
FB
52/* SDL audio buffer size, in samples. Should be small to have precise
53 A/V sync as SDL does not have hardware buffer fullness info. */
54#define SDL_AUDIO_BUFFER_SIZE 1024
55
56/* no AV sync correction is done if below the AV sync threshold */
7e0140cb 57#define AV_SYNC_THRESHOLD 0.01
638c9d91
FB
58/* no AV correction is done if too big error */
59#define AV_NOSYNC_THRESHOLD 10.0
60
61/* maximum audio speed change to get correct sync */
62#define SAMPLE_CORRECTION_PERCENT_MAX 10
63
64/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
65#define AUDIO_DIFF_AVG_NB 20
66
01310af2
FB
67/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
68#define SAMPLE_ARRAY_SIZE (2*65536)
69
03ae87a3
LA
70static int sws_flags = SWS_BICUBIC;
71
01310af2
FB
72typedef struct PacketQueue {
73 AVPacketList *first_pkt, *last_pkt;
74 int nb_packets;
75 int size;
76 int abort_request;
77 SDL_mutex *mutex;
78 SDL_cond *cond;
79} PacketQueue;
80
81#define VIDEO_PICTURE_QUEUE_SIZE 1
72ce053b 82#define SUBPICTURE_QUEUE_SIZE 4
01310af2
FB
83
84typedef struct VideoPicture {
267e9dfa 85 double pts; ///<presentation time stamp for this picture
01310af2
FB
86 SDL_Overlay *bmp;
87 int width, height; /* source height & width */
88 int allocated;
89} VideoPicture;
90
72ce053b
IC
91typedef struct SubPicture {
92 double pts; /* presentation time stamp for this picture */
93 AVSubtitle sub;
94} SubPicture;
95
01310af2
FB
96enum {
97 AV_SYNC_AUDIO_MASTER, /* default choice */
98 AV_SYNC_VIDEO_MASTER,
638c9d91 99 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
01310af2
FB
100};
101
102typedef struct VideoState {
103 SDL_Thread *parse_tid;
104 SDL_Thread *video_tid;
638c9d91 105 AVInputFormat *iformat;
01310af2
FB
106 int no_background;
107 int abort_request;
108 int paused;
416e3508 109 int last_paused;
72ea344b 110 int seek_req;
3ba1438d 111 int seek_flags;
72ea344b 112 int64_t seek_pos;
4ed29207 113 int64_t seek_rel;
01310af2
FB
114 AVFormatContext *ic;
115 int dtg_active_format;
116
117 int audio_stream;
115329f1 118
01310af2 119 int av_sync_type;
638c9d91
FB
120 double external_clock; /* external clock base */
121 int64_t external_clock_time;
115329f1 122
638c9d91
FB
123 double audio_clock;
124 double audio_diff_cum; /* used for AV difference average computation */
125 double audio_diff_avg_coef;
126 double audio_diff_threshold;
127 int audio_diff_avg_count;
01310af2
FB
128 AVStream *audio_st;
129 PacketQueue audioq;
130 int audio_hw_buf_size;
131 /* samples output by the codec. we reserve more space for avsync
132 compensation */
5a4476e2
PR
133 DECLARE_ALIGNED(16,uint8_t,audio_buf1[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
134 DECLARE_ALIGNED(16,uint8_t,audio_buf2[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
135 uint8_t *audio_buf;
7fea94ce 136 unsigned int audio_buf_size; /* in bytes */
01310af2 137 int audio_buf_index; /* in bytes */
bea18375 138 AVPacket audio_pkt_temp;
01310af2 139 AVPacket audio_pkt;
5a4476e2
PR
140 enum SampleFormat audio_src_fmt;
141 AVAudioConvert *reformat_ctx;
115329f1 142
01310af2
FB
143 int show_audio; /* if true, display audio samples */
144 int16_t sample_array[SAMPLE_ARRAY_SIZE];
145 int sample_array_index;
5e0257e3 146 int last_i_start;
115329f1 147
72ce053b
IC
148 SDL_Thread *subtitle_tid;
149 int subtitle_stream;
150 int subtitle_stream_changed;
151 AVStream *subtitle_st;
152 PacketQueue subtitleq;
153 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
154 int subpq_size, subpq_rindex, subpq_windex;
155 SDL_mutex *subpq_mutex;
156 SDL_cond *subpq_cond;
115329f1 157
638c9d91
FB
158 double frame_timer;
159 double frame_last_pts;
160 double frame_last_delay;
115329f1 161 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
01310af2
FB
162 int video_stream;
163 AVStream *video_st;
164 PacketQueue videoq;
267e9dfa
MN
165 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
166 int64_t video_current_pts_time; ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
01310af2
FB
167 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
168 int pictq_size, pictq_rindex, pictq_windex;
169 SDL_mutex *pictq_mutex;
170 SDL_cond *pictq_cond;
3ac56e28 171 struct SwsContext *img_convert_ctx;
115329f1 172
01310af2
FB
173 // QETimer *video_timer;
174 char filename[1024];
175 int width, height, xleft, ytop;
176} VideoState;
177
358061f6 178static void show_help(void);
638c9d91 179static int audio_write_get_buf_size(VideoState *is);
01310af2
FB
180
181/* options specified by the user */
182static AVInputFormat *file_iformat;
183static const char *input_filename;
184static int fs_screen_width;
185static int fs_screen_height;
fccb19e3
MN
186static int screen_width = 0;
187static int screen_height = 0;
e4b89522
LW
188static int frame_width = 0;
189static int frame_height = 0;
190static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
01310af2
FB
191static int audio_disable;
192static int video_disable;
a8062103 193static int wanted_audio_stream= 0;
4d8243d3 194static int wanted_video_stream= 0;
16a59a7b 195static int wanted_subtitle_stream= -1;
94b594c6 196static int seek_by_bytes;
01310af2
FB
197static int display_disable;
198static int show_status;
638c9d91 199static int av_sync_type = AV_SYNC_AUDIO_MASTER;
72ea344b 200static int64_t start_time = AV_NOPTS_VALUE;
e26a8335 201static int debug = 0;
0c9bbaec 202static int debug_mv = 0;
bba04f1e 203static int step = 0;
c62c07d3 204static int thread_count = 1;
6387c3e6 205static int workaround_bugs = 1;
6fc5b059 206static int fast = 0;
30bc6613 207static int genpts = 0;
178fcca8
MN
208static int lowres = 0;
209static int idct = FF_IDCT_AUTO;
8c3eba7c
MN
210static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
211static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
212static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
047599a4 213static int error_recognition = FF_ER_CAREFUL;
1b51e051 214static int error_concealment = 3;
5039185a 215static int decoder_reorder_pts= 0;
01310af2
FB
216
217/* current context */
218static int is_full_screen;
219static VideoState *cur_stream;
5e0257e3 220static int64_t audio_callback_time;
01310af2 221
2c676c33 222static AVPacket flush_pkt;
39c6a118 223
01310af2
FB
224#define FF_ALLOC_EVENT (SDL_USEREVENT)
225#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
638c9d91 226#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
01310af2 227
2c676c33 228static SDL_Surface *screen;
01310af2
FB
229
230/* packet queue handling */
231static void packet_queue_init(PacketQueue *q)
232{
233 memset(q, 0, sizeof(PacketQueue));
234 q->mutex = SDL_CreateMutex();
235 q->cond = SDL_CreateCond();
236}
237
72ea344b 238static void packet_queue_flush(PacketQueue *q)
01310af2
FB
239{
240 AVPacketList *pkt, *pkt1;
241
687fae2b 242 SDL_LockMutex(q->mutex);
01310af2
FB
243 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
244 pkt1 = pkt->next;
245 av_free_packet(&pkt->pkt);
da6c4573 246 av_freep(&pkt);
01310af2 247 }
72ea344b
FB
248 q->last_pkt = NULL;
249 q->first_pkt = NULL;
250 q->nb_packets = 0;
251 q->size = 0;
687fae2b 252 SDL_UnlockMutex(q->mutex);
72ea344b
FB
253}
254
255static void packet_queue_end(PacketQueue *q)
256{
257 packet_queue_flush(q);
01310af2
FB
258 SDL_DestroyMutex(q->mutex);
259 SDL_DestroyCond(q->cond);
260}
261
262static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
263{
264 AVPacketList *pkt1;
265
72ea344b 266 /* duplicate the packet */
39c6a118 267 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
72ea344b 268 return -1;
115329f1 269
01310af2
FB
270 pkt1 = av_malloc(sizeof(AVPacketList));
271 if (!pkt1)
272 return -1;
273 pkt1->pkt = *pkt;
274 pkt1->next = NULL;
275
72ea344b 276
01310af2
FB
277 SDL_LockMutex(q->mutex);
278
279 if (!q->last_pkt)
280
281 q->first_pkt = pkt1;
282 else
283 q->last_pkt->next = pkt1;
284 q->last_pkt = pkt1;
285 q->nb_packets++;
7b776589 286 q->size += pkt1->pkt.size + sizeof(*pkt1);
01310af2
FB
287 /* XXX: should duplicate packet data in DV case */
288 SDL_CondSignal(q->cond);
289
290 SDL_UnlockMutex(q->mutex);
291 return 0;
292}
293
294static void packet_queue_abort(PacketQueue *q)
295{
296 SDL_LockMutex(q->mutex);
297
298 q->abort_request = 1;
115329f1 299
01310af2
FB
300 SDL_CondSignal(q->cond);
301
302 SDL_UnlockMutex(q->mutex);
303}
304
305/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
306static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
307{
308 AVPacketList *pkt1;
309 int ret;
310
311 SDL_LockMutex(q->mutex);
312
313 for(;;) {
314 if (q->abort_request) {
315 ret = -1;
316 break;
317 }
115329f1 318
01310af2
FB
319 pkt1 = q->first_pkt;
320 if (pkt1) {
321 q->first_pkt = pkt1->next;
322 if (!q->first_pkt)
323 q->last_pkt = NULL;
324 q->nb_packets--;
7b776589 325 q->size -= pkt1->pkt.size + sizeof(*pkt1);
01310af2
FB
326 *pkt = pkt1->pkt;
327 av_free(pkt1);
328 ret = 1;
329 break;
330 } else if (!block) {
331 ret = 0;
332 break;
333 } else {
334 SDL_CondWait(q->cond, q->mutex);
335 }
336 }
337 SDL_UnlockMutex(q->mutex);
338 return ret;
339}
340
115329f1 341static inline void fill_rectangle(SDL_Surface *screen,
01310af2
FB
342 int x, int y, int w, int h, int color)
343{
344 SDL_Rect rect;
345 rect.x = x;
346 rect.y = y;
347 rect.w = w;
348 rect.h = h;
349 SDL_FillRect(screen, &rect, color);
350}
351
352#if 0
353/* draw only the border of a rectangle */
354void fill_border(VideoState *s, int x, int y, int w, int h, int color)
355{
356 int w1, w2, h1, h2;
357
358 /* fill the background */
359 w1 = x;
360 if (w1 < 0)
361 w1 = 0;
362 w2 = s->width - (x + w);
363 if (w2 < 0)
364 w2 = 0;
365 h1 = y;
366 if (h1 < 0)
367 h1 = 0;
368 h2 = s->height - (y + h);
369 if (h2 < 0)
370 h2 = 0;
115329f1
DB
371 fill_rectangle(screen,
372 s->xleft, s->ytop,
373 w1, s->height,
01310af2 374 color);
115329f1
DB
375 fill_rectangle(screen,
376 s->xleft + s->width - w2, s->ytop,
377 w2, s->height,
01310af2 378 color);
115329f1
DB
379 fill_rectangle(screen,
380 s->xleft + w1, s->ytop,
381 s->width - w1 - w2, h1,
01310af2 382 color);
115329f1 383 fill_rectangle(screen,
01310af2
FB
384 s->xleft + w1, s->ytop + s->height - h2,
385 s->width - w1 - w2, h2,
386 color);
387}
388#endif
389
72ce053b
IC
390
391
392#define SCALEBITS 10
393#define ONE_HALF (1 << (SCALEBITS - 1))
394#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
395
396#define RGB_TO_Y_CCIR(r, g, b) \
397((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
398 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
399
400#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
401(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
402 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
403
404#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
405(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
406 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
407
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 */
923static void schedule_refresh(VideoState *is, int delay)
924{
cc1f91d7 925 if(!delay) delay=1; //SDL seems to be buggy when the delay is 0
01310af2
FB
926 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
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{
949 double delta;
04108619 950 if (is->paused) {
72ea344b
FB
951 delta = 0;
952 } else {
953 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
954 }
638c9d91
FB
955 return is->video_current_pts + delta;
956}
957
958/* get the current external clock value */
959static double get_external_clock(VideoState *is)
960{
961 int64_t ti;
962 ti = av_gettime();
963 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
964}
965
966/* get the current master clock value */
967static double get_master_clock(VideoState *is)
968{
969 double val;
970
72ea344b
FB
971 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
972 if (is->video_st)
973 val = get_video_clock(is);
974 else
975 val = get_audio_clock(is);
976 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
977 if (is->audio_st)
978 val = get_audio_clock(is);
979 else
980 val = get_video_clock(is);
981 } else {
638c9d91 982 val = get_external_clock(is);
72ea344b 983 }
638c9d91
FB
984 return val;
985}
986
72ea344b 987/* seek in the stream */
4ed29207 988static void stream_seek(VideoState *is, int64_t pos, int64_t rel)
72ea344b 989{
687fae2b
IW
990 if (!is->seek_req) {
991 is->seek_pos = pos;
4ed29207 992 is->seek_rel = rel;
94b594c6
SH
993 if (seek_by_bytes)
994 is->seek_flags |= AVSEEK_FLAG_BYTE;
687fae2b
IW
995 is->seek_req = 1;
996 }
72ea344b
FB
997}
998
999/* pause or resume the video */
1000static void stream_pause(VideoState *is)
1001{
1002 is->paused = !is->paused;
917fa192 1003 if (!is->paused) {
72ea344b 1004 is->video_current_pts = get_video_clock(is);
917fa192 1005 is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
72ea344b
FB
1006 }
1007}
1008
49410784
TB
1009static double compute_frame_delay(double frame_current_pts, VideoState *is)
1010{
1011 double actual_delay, delay, sync_threshold, ref_clock, diff;
1012
1013 /* compute nominal delay */
1014 delay = frame_current_pts - is->frame_last_pts;
1015 if (delay <= 0 || delay >= 10.0) {
1016 /* if incorrect delay, use previous one */
1017 delay = is->frame_last_delay;
443658fd 1018 } else {
712de377 1019 is->frame_last_delay = delay;
443658fd 1020 }
49410784
TB
1021 is->frame_last_pts = frame_current_pts;
1022
1023 /* update delay to follow master synchronisation source */
1024 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1025 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1026 /* if video is slave, we try to correct big delays by
1027 duplicating or deleting a frame */
1028 ref_clock = get_master_clock(is);
1029 diff = frame_current_pts - ref_clock;
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) {
1070 /* if no picture, need to wait */
7e0140cb 1071 schedule_refresh(is, 1);
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;
1078 is->video_current_pts_time = av_gettime();
1079
01310af2 1080 /* launch timer for next picture */
49410784 1081 schedule_refresh(is, (int)(compute_frame_delay(vp->pts, is) * 1000 + 0.5));
638c9d91 1082
72ce053b
IC
1083 if(is->subtitle_st) {
1084 if (is->subtitle_stream_changed) {
1085 SDL_LockMutex(is->subpq_mutex);
115329f1 1086
72ce053b
IC
1087 while (is->subpq_size) {
1088 free_subpicture(&is->subpq[is->subpq_rindex]);
115329f1 1089
72ce053b
IC
1090 /* update queue size and signal for next picture */
1091 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1092 is->subpq_rindex = 0;
115329f1 1093
72ce053b
IC
1094 is->subpq_size--;
1095 }
1096 is->subtitle_stream_changed = 0;
1097
1098 SDL_CondSignal(is->subpq_cond);
1099 SDL_UnlockMutex(is->subpq_mutex);
1100 } else {
1101 if (is->subpq_size > 0) {
1102 sp = &is->subpq[is->subpq_rindex];
1103
1104 if (is->subpq_size > 1)
1105 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1106 else
1107 sp2 = NULL;
1108
1109 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1110 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1111 {
1112 free_subpicture(sp);
1113
1114 /* update queue size and signal for next picture */
1115 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1116 is->subpq_rindex = 0;
1117
1118 SDL_LockMutex(is->subpq_mutex);
1119 is->subpq_size--;
1120 SDL_CondSignal(is->subpq_cond);
1121 SDL_UnlockMutex(is->subpq_mutex);
1122 }
1123 }
1124 }
1125 }
1126
01310af2
FB
1127 /* display picture */
1128 video_display(is);
115329f1 1129
01310af2
FB
1130 /* update queue size and signal for next picture */
1131 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1132 is->pictq_rindex = 0;
115329f1 1133
01310af2
FB
1134 SDL_LockMutex(is->pictq_mutex);
1135 is->pictq_size--;
1136 SDL_CondSignal(is->pictq_cond);
1137 SDL_UnlockMutex(is->pictq_mutex);
1138 }
1139 } else if (is->audio_st) {
1140 /* draw the next audio frame */
1141
1142 schedule_refresh(is, 40);
1143
1144 /* if only audio stream, then display the audio bars (better
1145 than nothing, just to test the implementation */
115329f1 1146
01310af2
FB
1147 /* display picture */
1148 video_display(is);
1149 } else {
1150 schedule_refresh(is, 100);
1151 }
1152 if (show_status) {
1153 static int64_t last_time;
1154 int64_t cur_time;
72ce053b 1155 int aqsize, vqsize, sqsize;
638c9d91 1156 double av_diff;
115329f1 1157
01310af2
FB
1158 cur_time = av_gettime();
1159 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1160 aqsize = 0;
1161 vqsize = 0;
72ce053b 1162 sqsize = 0;
01310af2
FB
1163 if (is->audio_st)
1164 aqsize = is->audioq.size;
1165 if (is->video_st)
1166 vqsize = is->videoq.size;
72ce053b
IC
1167 if (is->subtitle_st)
1168 sqsize = is->subtitleq.size;
638c9d91
FB
1169 av_diff = 0;
1170 if (is->audio_st && is->video_st)
1171 av_diff = get_audio_clock(is) - get_video_clock(is);
115329f1 1172 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
72ce053b 1173 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
01310af2
FB
1174 fflush(stdout);
1175 last_time = cur_time;
1176 }
1177 }
1178}
1179
1180/* allocate a picture (needs to do that in main thread to avoid
1181 potential locking problems */
1182static void alloc_picture(void *opaque)
1183{
1184 VideoState *is = opaque;
1185 VideoPicture *vp;
01310af2
FB
1186
1187 vp = &is->pictq[is->pictq_windex];
1188
1189 if (vp->bmp)
1190 SDL_FreeYUVOverlay(vp->bmp);
1191
61890b02 1192#if 0
01310af2 1193 /* XXX: use generic function */
61890b02 1194 /* XXX: disable overlay if no hardware acceleration or if RGB format */
01f4895c 1195 switch(is->video_st->codec->pix_fmt) {
01310af2
FB
1196 case PIX_FMT_YUV420P:
1197 case PIX_FMT_YUV422P:
1198 case PIX_FMT_YUV444P:
71e445fc 1199 case PIX_FMT_YUYV422:
01310af2
FB
1200 case PIX_FMT_YUV410P:
1201 case PIX_FMT_YUV411P:
1202 is_yuv = 1;
1203 break;
1204 default:
1205 is_yuv = 0;
1206 break;
1207 }
01310af2 1208#endif
01f4895c
MN
1209 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1210 is->video_st->codec->height,
115329f1 1211 SDL_YV12_OVERLAY,
61890b02 1212 screen);
01f4895c
MN
1213 vp->width = is->video_st->codec->width;
1214 vp->height = is->video_st->codec->height;
01310af2
FB
1215
1216 SDL_LockMutex(is->pictq_mutex);
1217 vp->allocated = 1;
1218 SDL_CondSignal(is->pictq_cond);
1219 SDL_UnlockMutex(is->pictq_mutex);
1220}
1221
267e9dfa
MN
1222/**
1223 *
1224 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1225 */
638c9d91 1226static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01310af2
FB
1227{
1228 VideoPicture *vp;
1229 int dst_pix_fmt;
115329f1 1230
01310af2
FB
1231 /* wait until we have space to put a new picture */
1232 SDL_LockMutex(is->pictq_mutex);
1233 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1234 !is->videoq.abort_request) {
1235 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1236 }
1237 SDL_UnlockMutex(is->pictq_mutex);
115329f1 1238
01310af2
FB
1239 if (is->videoq.abort_request)
1240 return -1;
1241
1242 vp = &is->pictq[is->pictq_windex];
1243
1244 /* alloc or resize hardware picture buffer */
115329f1 1245 if (!vp->bmp ||
01f4895c
MN
1246 vp->width != is->video_st->codec->width ||
1247 vp->height != is->video_st->codec->height) {
01310af2
FB
1248 SDL_Event event;
1249
1250 vp->allocated = 0;
1251
1252 /* the allocation must be done in the main thread to avoid
1253 locking problems */
1254 event.type = FF_ALLOC_EVENT;
1255 event.user.data1 = is;
1256 SDL_PushEvent(&event);
115329f1 1257
01310af2
FB
1258 /* wait until the picture is allocated */
1259 SDL_LockMutex(is->pictq_mutex);
1260 while (!vp->allocated && !is->videoq.abort_request) {
1261 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1262 }
1263 SDL_UnlockMutex(is->pictq_mutex);
1264
1265 if (is->videoq.abort_request)
1266 return -1;
1267 }
1268
638c9d91 1269 /* if the frame is not skipped, then display it */
01310af2 1270 if (vp->bmp) {
fbf1b885 1271 AVPicture pict;
1272
01310af2
FB
1273 /* get a pointer on the bitmap */
1274 SDL_LockYUVOverlay (vp->bmp);
1275
1276 dst_pix_fmt = PIX_FMT_YUV420P;
fbf1b885 1277 memset(&pict,0,sizeof(AVPicture));
01310af2
FB
1278 pict.data[0] = vp->bmp->pixels[0];
1279 pict.data[1] = vp->bmp->pixels[2];
1280 pict.data[2] = vp->bmp->pixels[1];
1281
1282 pict.linesize[0] = vp->bmp->pitches[0];
1283 pict.linesize[1] = vp->bmp->pitches[2];
1284 pict.linesize[2] = vp->bmp->pitches[1];
e43d7a18 1285 sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
3ac56e28 1286 is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
feb7bc67
AB
1287 is->video_st->codec->width, is->video_st->codec->height,
1288 is->video_st->codec->pix_fmt,
1289 is->video_st->codec->width, is->video_st->codec->height,
1290 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
3ac56e28 1291 if (is->img_convert_ctx == NULL) {
26ba8235
AB
1292 fprintf(stderr, "Cannot initialize the conversion context\n");
1293 exit(1);
1294 }
3ac56e28 1295 sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
03ae87a3 1296 0, is->video_st->codec->height, pict.data, pict.linesize);
01310af2
FB
1297 /* update the bitmap content */
1298 SDL_UnlockYUVOverlay(vp->bmp);
1299
638c9d91 1300 vp->pts = pts;
01310af2
FB
1301
1302 /* now we can update the picture count */
1303 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1304 is->pictq_windex = 0;
1305 SDL_LockMutex(is->pictq_mutex);
1306 is->pictq_size++;
1307 SDL_UnlockMutex(is->pictq_mutex);
1308 }
638c9d91
FB
1309 return 0;
1310}
1311
115329f1
DB
1312/**
1313 * compute the exact PTS for the picture if it is omitted in the stream
267e9dfa
MN
1314 * @param pts1 the dts of the pkt / pts of the frame
1315 */
638c9d91
FB
1316static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1317{
1318 double frame_delay, pts;
115329f1 1319
638c9d91
FB
1320 pts = pts1;
1321
01310af2 1322 if (pts != 0) {
638c9d91 1323 /* update video clock with pts, if present */
01310af2
FB
1324 is->video_clock = pts;
1325 } else {
72ea344b
FB
1326 pts = is->video_clock;
1327 }
1328 /* update video clock for next frame */
01f4895c 1329 frame_delay = av_q2d(is->video_st->codec->time_base);
72ea344b
FB
1330 /* for MPEG2, the frame can be repeated, so we update the
1331 clock accordingly */
267e9dfa 1332 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
72ea344b 1333 is->video_clock += frame_delay;
638c9d91
FB
1334
1335#if defined(DEBUG_SYNC) && 0
1336 {
1337 int ftype;
1338 if (src_frame->pict_type == FF_B_TYPE)
1339 ftype = 'B';
1340 else if (src_frame->pict_type == FF_I_TYPE)
1341 ftype = 'I';
1342 else
1343 ftype = 'P';
115329f1 1344 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
72ea344b 1345 ftype, pts, pts1);
638c9d91
FB
1346 }
1347#endif
72ea344b 1348 return queue_picture(is, src_frame, pts);
01310af2
FB
1349}
1350
1351static int video_thread(void *arg)
1352{
1353 VideoState *is = arg;
1354 AVPacket pkt1, *pkt = &pkt1;
72ea344b 1355 int len1, got_picture;
c6b1edc9 1356 AVFrame *frame= avcodec_alloc_frame();
01310af2
FB
1357 double pts;
1358
1359 for(;;) {
1360 while (is->paused && !is->videoq.abort_request) {
1361 SDL_Delay(10);
1362 }
1363 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1364 break;
39c6a118
MN
1365
1366 if(pkt->data == flush_pkt.data){
1367 avcodec_flush_buffers(is->video_st->codec);
1368 continue;
1369 }
1370
638c9d91
FB
1371 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1372 this packet, if any */
7fb262b5 1373 is->video_st->codec->reordered_opaque= pkt->pts;
bea18375 1374 len1 = avcodec_decode_video2(is->video_st->codec,
620e8baf 1375 frame, &got_picture,
bea18375 1376 pkt);
620e8baf
MN
1377
1378 if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
7fb262b5
MN
1379 && frame->reordered_opaque != AV_NOPTS_VALUE)
1380 pts= frame->reordered_opaque;
620e8baf
MN
1381 else if(pkt->dts != AV_NOPTS_VALUE)
1382 pts= pkt->dts;
1383 else
1384 pts= 0;
1385 pts *= av_q2d(is->video_st->time_base);
5039185a 1386
fb966f99
MN
1387// if (len1 < 0)
1388// break;
620e8baf
MN
1389 if (got_picture) {
1390 if (output_picture2(is, frame, pts) < 0)
1391 goto the_end;
1392 }
01310af2 1393 av_free_packet(pkt);
115329f1 1394 if (step)
bba04f1e
WH
1395 if (cur_stream)
1396 stream_pause(cur_stream);
01310af2
FB
1397 }
1398 the_end:
c6b1edc9 1399 av_free(frame);
01310af2
FB
1400 return 0;
1401}
1402
72ce053b
IC
1403static int subtitle_thread(void *arg)
1404{
1405 VideoState *is = arg;
1406 SubPicture *sp;
1407 AVPacket pkt1, *pkt = &pkt1;
1408 int len1, got_subtitle;
1409 double pts;
1410 int i, j;
1411 int r, g, b, y, u, v, a;
1412
1413 for(;;) {
1414 while (is->paused && !is->subtitleq.abort_request) {
1415 SDL_Delay(10);
1416 }
1417 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1418 break;
115329f1 1419
39c6a118
MN
1420 if(pkt->data == flush_pkt.data){
1421 avcodec_flush_buffers(is->subtitle_st->codec);
1422 continue;
1423 }
72ce053b
IC
1424 SDL_LockMutex(is->subpq_mutex);
1425 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1426 !is->subtitleq.abort_request) {
1427 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1428 }
1429 SDL_UnlockMutex(is->subpq_mutex);
115329f1 1430
72ce053b
IC
1431 if (is->subtitleq.abort_request)
1432 goto the_end;
115329f1 1433
72ce053b
IC
1434 sp = &is->subpq[is->subpq_windex];
1435
1436 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1437 this packet, if any */
1438 pts = 0;
1439 if (pkt->pts != AV_NOPTS_VALUE)
1440 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1441
bea18375 1442 len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
115329f1 1443 &sp->sub, &got_subtitle,
bea18375 1444 pkt);
72ce053b
IC
1445// if (len1 < 0)
1446// break;
1447 if (got_subtitle && sp->sub.format == 0) {
1448 sp->pts = pts;
115329f1 1449
72ce053b
IC
1450 for (i = 0; i < sp->sub.num_rects; i++)
1451 {
db4fac64 1452 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
72ce053b 1453 {
25b4c651 1454 RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
72ce053b
IC
1455 y = RGB_TO_Y_CCIR(r, g, b);
1456 u = RGB_TO_U_CCIR(r, g, b, 0);
1457 v = RGB_TO_V_CCIR(r, g, b, 0);
25b4c651 1458 YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
72ce053b
IC
1459 }
1460 }
1461
1462 /* now we can update the picture count */
1463 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1464 is->subpq_windex = 0;
1465 SDL_LockMutex(is->subpq_mutex);
1466 is->subpq_size++;
1467 SDL_UnlockMutex(is->subpq_mutex);
1468 }
1469 av_free_packet(pkt);
115329f1 1470// if (step)
72ce053b
IC
1471// if (cur_stream)
1472// stream_pause(cur_stream);
1473 }
1474 the_end:
1475 return 0;
1476}
1477
01310af2
FB
1478/* copy samples for viewing in editor window */
1479static void update_sample_display(VideoState *is, short *samples, int samples_size)
1480{
1481 int size, len, channels;
1482
01f4895c 1483 channels = is->audio_st->codec->channels;
01310af2
FB
1484
1485 size = samples_size / sizeof(short);
1486 while (size > 0) {
1487 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1488 if (len > size)
1489 len = size;
1490 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1491 samples += len;
1492 is->sample_array_index += len;
1493 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1494 is->sample_array_index = 0;
1495 size -= len;
1496 }
1497}
1498
01310af2
FB
1499/* return the new audio buffer size (samples can be added or deleted
1500 to get better sync if video or external master clock) */
115329f1 1501static int synchronize_audio(VideoState *is, short *samples,
638c9d91 1502 int samples_size1, double pts)
01310af2 1503{
638c9d91 1504 int n, samples_size;
01310af2 1505 double ref_clock;
115329f1 1506
01f4895c 1507 n = 2 * is->audio_st->codec->channels;
638c9d91 1508 samples_size = samples_size1;
01310af2 1509
01310af2 1510 /* if not master, then we try to remove or add samples to correct the clock */
01310af2 1511 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
638c9d91
FB
1512 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1513 double diff, avg_diff;
01310af2 1514 int wanted_size, min_size, max_size, nb_samples;
115329f1 1515
638c9d91
FB
1516 ref_clock = get_master_clock(is);
1517 diff = get_audio_clock(is) - ref_clock;
115329f1 1518
638c9d91
FB
1519 if (diff < AV_NOSYNC_THRESHOLD) {
1520 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1521 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1522 /* not enough measures to have a correct estimate */
1523 is->audio_diff_avg_count++;
1524 } else {
1525 /* estimate the A-V difference */
1526 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1527
1528 if (fabs(avg_diff) >= is->audio_diff_threshold) {
01f4895c 1529 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
638c9d91 1530 nb_samples = samples_size / n;
115329f1 1531
638c9d91
FB
1532 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1533 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1534 if (wanted_size < min_size)
1535 wanted_size = min_size;
1536 else if (wanted_size > max_size)
1537 wanted_size = max_size;
115329f1 1538
638c9d91
FB
1539 /* add or remove samples to correction the synchro */
1540 if (wanted_size < samples_size) {
1541 /* remove samples */
1542 samples_size = wanted_size;
1543 } else if (wanted_size > samples_size) {
1544 uint8_t *samples_end, *q;
1545 int nb;
115329f1 1546
638c9d91
FB
1547 /* add samples */
1548 nb = (samples_size - wanted_size);
1549 samples_end = (uint8_t *)samples + samples_size - n;
1550 q = samples_end + n;
1551 while (nb > 0) {
1552 memcpy(q, samples_end, n);
1553 q += n;
1554 nb -= n;
1555 }
1556 samples_size = wanted_size;
1557 }
1558 }
1559#if 0
115329f1
DB
1560 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1561 diff, avg_diff, samples_size - samples_size1,
638c9d91
FB
1562 is->audio_clock, is->video_clock, is->audio_diff_threshold);
1563#endif
01310af2 1564 }
638c9d91
FB
1565 } else {
1566 /* too big difference : may be initial PTS errors, so
1567 reset A-V filter */
1568 is->audio_diff_avg_count = 0;
1569 is->audio_diff_cum = 0;
01310af2
FB
1570 }
1571 }
1572
01310af2
FB
1573 return samples_size;
1574}
1575
1576/* decode one audio frame and returns its uncompressed size */
5a4476e2 1577static int audio_decode_frame(VideoState *is, double *pts_ptr)
01310af2 1578{
bea18375 1579 AVPacket *pkt_temp = &is->audio_pkt_temp;
01310af2 1580 AVPacket *pkt = &is->audio_pkt;
abdff646 1581 AVCodecContext *dec= is->audio_st->codec;
72ea344b 1582 int n, len1, data_size;
01310af2
FB
1583 double pts;
1584
1585 for(;;) {
72ea344b 1586 /* NOTE: the audio packet can contain several frames */
bea18375 1587 while (pkt_temp->size > 0) {
5a4476e2 1588 data_size = sizeof(is->audio_buf1);
bea18375 1589 len1 = avcodec_decode_audio3(dec,
5a4476e2 1590 (int16_t *)is->audio_buf1, &data_size,
bea18375 1591 pkt_temp);
72ea344b
FB
1592 if (len1 < 0) {
1593 /* if error, we skip the frame */
bea18375 1594 pkt_temp->size = 0;
01310af2 1595 break;
72ea344b 1596 }
115329f1 1597
bea18375
TB
1598 pkt_temp->data += len1;
1599 pkt_temp->size -= len1;
72ea344b
FB
1600 if (data_size <= 0)
1601 continue;
5a4476e2
PR
1602
1603 if (dec->sample_fmt != is->audio_src_fmt) {
1604 if (is->reformat_ctx)
1605 av_audio_convert_free(is->reformat_ctx);
1606 is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
1607 dec->sample_fmt, 1, NULL, 0);
1608 if (!is->reformat_ctx) {
1609 fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
1610 avcodec_get_sample_fmt_name(dec->sample_fmt),
1611 avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
1612 break;
1613 }
1614 is->audio_src_fmt= dec->sample_fmt;
1615 }
1616
1617 if (is->reformat_ctx) {
1618 const void *ibuf[6]= {is->audio_buf1};
1619 void *obuf[6]= {is->audio_buf2};
1620 int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
1621 int ostride[6]= {2};
1622 int len= data_size/istride[0];
1623 if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
1624 printf("av_audio_convert() failed\n");
1625 break;
1626 }
1627 is->audio_buf= is->audio_buf2;
1628 /* FIXME: existing code assume that data_size equals framesize*channels*2
1629 remove this legacy cruft */
1630 data_size= len*2;
1631 }else{
1632 is->audio_buf= is->audio_buf1;
1633 }
1634
72ea344b
FB
1635 /* if no pts, then compute it */
1636 pts = is->audio_clock;
1637 *pts_ptr = pts;
abdff646 1638 n = 2 * dec->channels;
115329f1 1639 is->audio_clock += (double)data_size /
abdff646 1640 (double)(n * dec->sample_rate);
638c9d91 1641#if defined(DEBUG_SYNC)
72ea344b
FB
1642 {
1643 static double last_clock;
1644 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1645 is->audio_clock - last_clock,
1646 is->audio_clock, pts);
1647 last_clock = is->audio_clock;
01310af2 1648 }
72ea344b
FB
1649#endif
1650 return data_size;
01310af2
FB
1651 }
1652
72ea344b
FB
1653 /* free the current packet */
1654 if (pkt->data)
01310af2 1655 av_free_packet(pkt);
115329f1 1656
72ea344b
FB
1657 if (is->paused || is->audioq.abort_request) {
1658 return -1;
1659 }
115329f1 1660
01310af2
FB
1661 /* read next packet */
1662 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1663 return -1;
39c6a118 1664 if(pkt->data == flush_pkt.data){
abdff646 1665 avcodec_flush_buffers(dec);
39c6a118
MN
1666 continue;
1667 }
1668
bea18375
TB
1669 pkt_temp->data = pkt->data;
1670 pkt_temp->size = pkt->size;
115329f1 1671
72ea344b
FB
1672 /* if update the audio clock with the pts */
1673 if (pkt->pts != AV_NOPTS_VALUE) {
c0df9d75 1674 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
72ea344b 1675 }
01310af2
FB
1676 }
1677}
1678
638c9d91
FB
1679/* get the current audio output buffer size, in samples. With SDL, we
1680 cannot have a precise information */
1681static int audio_write_get_buf_size(VideoState *is)
01310af2 1682{
b09b580b 1683 return is->audio_buf_size - is->audio_buf_index;
01310af2
FB
1684}
1685
1686
1687/* prepare a new audio buffer */
358061f6 1688static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
01310af2
FB
1689{
1690 VideoState *is = opaque;
1691 int audio_size, len1;
1692 double pts;
1693
1694 audio_callback_time = av_gettime();
115329f1 1695
01310af2
FB
1696 while (len > 0) {
1697 if (is->audio_buf_index >= is->audio_buf_size) {
5a4476e2 1698 audio_size = audio_decode_frame(is, &pts);
01310af2
FB
1699 if (audio_size < 0) {
1700 /* if error, just output silence */
1a1078fa 1701 is->audio_buf = is->audio_buf1;
01310af2
FB
1702 is->audio_buf_size = 1024;
1703 memset(is->audio_buf, 0, is->audio_buf_size);
1704 } else {
1705 if (is->show_audio)
1706 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
115329f1 1707 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
01310af2
FB
1708 pts);
1709 is->audio_buf_size = audio_size;
1710 }
1711 is->audio_buf_index = 0;
1712 }
1713 len1 = is->audio_buf_size - is->audio_buf_index;
1714 if (len1 > len)
1715 len1 = len;
1716 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1717 len -= len1;
1718 stream += len1;
1719 is->audio_buf_index += len1;
1720 }
1721}
1722
01310af2
FB
1723/* open a given stream. Return 0 if OK */
1724static int stream_component_open(VideoState *is, int stream_index)
1725{
1726 AVFormatContext *ic = is->ic;
1727 AVCodecContext *enc;
1728 AVCodec *codec;
1729 SDL_AudioSpec wanted_spec, spec;
1730
1731 if (stream_index < 0 || stream_index >= ic->nb_streams)
1732 return -1;
01f4895c 1733 enc = ic->streams[stream_index]->codec;
115329f1 1734
01310af2
FB
1735 /* prepare audio output */
1736 if (enc->codec_type == CODEC_TYPE_AUDIO) {
51b73087
JR
1737 if (enc->channels > 0) {
1738 enc->request_channels = FFMIN(2, enc->channels);
94eadc8b 1739 } else {
51b73087 1740 enc->request_channels = 2;
638c9d91 1741 }
01310af2
FB
1742 }
1743
1744 codec = avcodec_find_decoder(enc->codec_id);
13d1512c
MN
1745 enc->debug_mv = debug_mv;
1746 enc->debug = debug;
6387c3e6 1747 enc->workaround_bugs = workaround_bugs;
178fcca8 1748 enc->lowres = lowres;
61846e9a 1749 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
178fcca8 1750 enc->idct_algo= idct;
6fc5b059 1751 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
8c3eba7c
MN
1752 enc->skip_frame= skip_frame;
1753 enc->skip_idct= skip_idct;
1754 enc->skip_loop_filter= skip_loop_filter;
047599a4 1755 enc->error_recognition= error_recognition;
1b51e051 1756 enc->error_concealment= error_concealment;
e43d7a18 1757
636f1c4c 1758 set_context_opts(enc, avcodec_opts[enc->codec_type], 0);
e43d7a18 1759
01310af2
FB
1760 if (!codec ||
1761 avcodec_open(enc, codec) < 0)
1762 return -1;
51b73087
JR
1763
1764 /* prepare audio output */
1765 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1766 wanted_spec.freq = enc->sample_rate;
1767 wanted_spec.format = AUDIO_S16SYS;
1768 wanted_spec.channels = enc->channels;
1769 wanted_spec.silence = 0;
1770 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1771 wanted_spec.callback = sdl_audio_callback;
1772 wanted_spec.userdata = is;
1773 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1774 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1775 return -1;
1776 }
1777 is->audio_hw_buf_size = spec.size;
5a4476e2 1778 is->audio_src_fmt= SAMPLE_FMT_S16;
51b73087
JR
1779 }
1780
c62c07d3
MN
1781 if(thread_count>1)
1782 avcodec_thread_init(enc, thread_count);
c62c07d3 1783 enc->thread_count= thread_count;
3f3fe38d 1784 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
638c9d91 1785 switch(enc->codec_type) {
01310af2
FB
1786 case CODEC_TYPE_AUDIO:
1787 is->audio_stream = stream_index;
1788 is->audio_st = ic->streams[stream_index];
1789 is->audio_buf_size = 0;
1790 is->audio_buf_index = 0;
638c9d91
FB
1791
1792 /* init averaging filter */
1793 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1794 is->audio_diff_avg_count = 0;
1795 /* since we do not have a precise anough audio fifo fullness,
1796 we correct audio sync only if larger than this threshold */
1797 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1798
01310af2
FB
1799 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1800 packet_queue_init(&is->audioq);
bb270c08 1801 SDL_PauseAudio(0);
01310af2
FB
1802 break;
1803 case CODEC_TYPE_VIDEO:
1804 is->video_stream = stream_index;
1805 is->video_st = ic->streams[stream_index];
1806
638c9d91
FB
1807 is->frame_last_delay = 40e-3;
1808 is->frame_timer = (double)av_gettime() / 1000000.0;
638c9d91
FB
1809 is->video_current_pts_time = av_gettime();
1810
01310af2
FB
1811 packet_queue_init(&is->videoq);
1812 is->video_tid = SDL_CreateThread(video_thread, is);
1813 break;
72ce053b
IC
1814 case CODEC_TYPE_SUBTITLE:
1815 is->subtitle_stream = stream_index;
1816 is->subtitle_st = ic->streams[stream_index];
1817 packet_queue_init(&is->subtitleq);
115329f1 1818
72ce053b
IC
1819 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1820 break;
01310af2
FB
1821 default:
1822 break;
1823 }
1824 return 0;
1825}
1826
1827static void stream_component_close(VideoState *is, int stream_index)
1828{
1829 AVFormatContext *ic = is->ic;
1830 AVCodecContext *enc;
115329f1 1831
72ce053b
IC
1832 if (stream_index < 0 || stream_index >= ic->nb_streams)
1833 return;
01f4895c 1834 enc = ic->streams[stream_index]->codec;
01310af2
FB
1835
1836 switch(enc->codec_type) {
1837 case CODEC_TYPE_AUDIO:
1838 packet_queue_abort(&is->audioq);
1839
1840 SDL_CloseAudio();
1841
1842 packet_queue_end(&is->audioq);
5a4476e2
PR
1843 if (is->reformat_ctx)
1844 av_audio_convert_free(is->reformat_ctx);
01310af2
FB
1845 break;
1846 case CODEC_TYPE_VIDEO:
1847 packet_queue_abort(&is->videoq);
1848
1849 /* note: we also signal this mutex to make sure we deblock the
1850 video thread in all cases */
1851 SDL_LockMutex(is->pictq_mutex);
1852 SDL_CondSignal(is->pictq_cond);
1853 SDL_UnlockMutex(is->pictq_mutex);
1854
1855 SDL_WaitThread(is->video_tid, NULL);
1856
1857 packet_queue_end(&is->videoq);
1858 break;
72ce053b
IC
1859 case CODEC_TYPE_SUBTITLE:
1860 packet_queue_abort(&is->subtitleq);
115329f1 1861
72ce053b
IC
1862 /* note: we also signal this mutex to make sure we deblock the
1863 video thread in all cases */
1864 SDL_LockMutex(is->subpq_mutex);
1865 is->subtitle_stream_changed = 1;
115329f1 1866
72ce053b
IC
1867 SDL_CondSignal(is->subpq_cond);
1868 SDL_UnlockMutex(is->subpq_mutex);
1869
1870 SDL_WaitThread(is->subtitle_tid, NULL);
1871
1872 packet_queue_end(&is->subtitleq);
1873 break;
01310af2
FB
1874 default:
1875 break;
1876 }
1877
3f3fe38d 1878 ic->streams[stream_index]->discard = AVDISCARD_ALL;
01310af2
FB
1879 avcodec_close(enc);
1880 switch(enc->codec_type) {
1881 case CODEC_TYPE_AUDIO:
1882 is->audio_st = NULL;
1883 is->audio_stream = -1;
1884 break;
1885 case CODEC_TYPE_VIDEO:
1886 is->video_st = NULL;
1887 is->video_stream = -1;
1888 break;
72ce053b
IC
1889 case CODEC_TYPE_SUBTITLE:
1890 is->subtitle_st = NULL;
1891 is->subtitle_stream = -1;
1892 break;
01310af2
FB
1893 default:
1894 break;
1895 }
1896}
1897
7b49ce2e 1898static void dump_stream_info(const AVFormatContext *s)
d0526ecf 1899{
f7554a99
AJ
1900 AVMetadataTag *tag = NULL;
1901 while ((tag=av_metadata_get(s->metadata,"",tag,AV_METADATA_IGNORE_SUFFIX)))
1902 fprintf(stderr, "%s: %s\n", tag->key, tag->value);
d0526ecf
FB
1903}
1904
416e3508
FB
1905/* since we have only one decoding thread, we can use a global
1906 variable instead of a thread local variable */
1907static VideoState *global_video_state;
1908
1909static int decode_interrupt_cb(void)
1910{
1911 return (global_video_state && global_video_state->abort_request);
1912}
01310af2
FB
1913
1914/* this thread gets the stream from the disk or the network */
1915static int decode_thread(void *arg)
1916{
1917 VideoState *is = arg;
1918 AVFormatContext *ic;
16a59a7b 1919 int err, i, ret, video_index, audio_index, subtitle_index;
01310af2 1920 AVPacket pkt1, *pkt = &pkt1;
61890b02 1921 AVFormatParameters params, *ap = &params;
75bb7b0a 1922 int eof=0;
01310af2
FB
1923
1924 video_index = -1;
1925 audio_index = -1;
16a59a7b 1926 subtitle_index = -1;
01310af2
FB
1927 is->video_stream = -1;
1928 is->audio_stream = -1;
72ce053b 1929 is->subtitle_stream = -1;
01310af2 1930
416e3508
FB
1931 global_video_state = is;
1932 url_set_interrupt_cb(decode_interrupt_cb);
1933
61890b02 1934 memset(ap, 0, sizeof(*ap));
115329f1 1935
e4b89522
LW
1936 ap->width = frame_width;
1937 ap->height= frame_height;
7e042912 1938 ap->time_base= (AVRational){1, 25};
e4b89522 1939 ap->pix_fmt = frame_pix_fmt;
7e042912 1940
61890b02 1941 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
638c9d91
FB
1942 if (err < 0) {
1943 print_error(is->filename, err);
1944 ret = -1;
1945 goto fail;
1946 }
01310af2 1947 is->ic = ic;
30bc6613
MN
1948
1949 if(genpts)
1950 ic->flags |= AVFMT_FLAG_GENPTS;
1951
24c07998
LA
1952 err = av_find_stream_info(ic);
1953 if (err < 0) {
1954 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1955 ret = -1;
1956 goto fail;
1957 }
899681cd
BA
1958 if(ic->pb)
1959 ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
72ea344b
FB
1960
1961 /* if seeking requested, we execute it */
1962 if (start_time != AV_NOPTS_VALUE) {
1963 int64_t timestamp;
1964
1965 timestamp = start_time;
1966 /* add the stream start time */
1967 if (ic->start_time != AV_NOPTS_VALUE)
1968 timestamp += ic->start_time;
4ed29207 1969 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
72ea344b 1970 if (ret < 0) {
115329f1 1971 fprintf(stderr, "%s: could not seek to position %0.3f\n",
72ea344b
FB
1972 is->filename, (double)timestamp / AV_TIME_BASE);
1973 }
1974 }
72ea344b 1975
01310af2 1976 for(i = 0; i < ic->nb_streams; i++) {
01f4895c 1977 AVCodecContext *enc = ic->streams[i]->codec;
3f3fe38d 1978 ic->streams[i]->discard = AVDISCARD_ALL;
01310af2
FB
1979 switch(enc->codec_type) {
1980 case CODEC_TYPE_AUDIO:
5dbb63fe 1981 if (wanted_audio_stream-- >= 0 && !audio_disable)
01310af2
FB
1982 audio_index = i;
1983 break;
1984 case CODEC_TYPE_VIDEO:
5dbb63fe 1985 if (wanted_video_stream-- >= 0 && !video_disable)
01310af2
FB
1986 video_index = i;
1987 break;
16a59a7b 1988 case CODEC_TYPE_SUBTITLE:
5ad4f0d4 1989 if (wanted_subtitle_stream-- >= 0 && !video_disable)
16a59a7b
BA
1990 subtitle_index = i;
1991 break;
01310af2
FB
1992 default:
1993 break;
1994 }
1995 }
1996 if (show_status) {
1997 dump_format(ic, 0, is->filename, 0);
d0526ecf 1998 dump_stream_info(ic);
01310af2
FB
1999 }
2000
2001 /* open the streams */
2002 if (audio_index >= 0) {
2003 stream_component_open(is, audio_index);
2004 }
2005
2006 if (video_index >= 0) {
2007 stream_component_open(is, video_index);
2008 } else {
2009 if (!display_disable)
2010 is->show_audio = 1;
2011 }
2012
16a59a7b
BA
2013 if (subtitle_index >= 0) {
2014 stream_component_open(is, subtitle_index);
2015 }
2016
01310af2 2017 if (is->video_stream < 0 && is->audio_stream < 0) {
638c9d91
FB
2018 fprintf(stderr, "%s: could not open codecs\n", is->filename);
2019 ret = -1;
01310af2
FB
2020 goto fail;
2021 }
2022
2023 for(;;) {
2024 if (is->abort_request)
2025 break;
416e3508
FB
2026 if (is->paused != is->last_paused) {
2027 is->last_paused = is->paused;
72ea344b
FB
2028 if (is->paused)
2029 av_read_pause(ic);
2030 else
2031 av_read_play(ic);
416e3508 2032 }
2f642393
AJ
2033#if CONFIG_RTSP_DEMUXER
2034 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
416e3508
FB
2035 /* wait 10 ms to avoid trying to get another packet */
2036 /* XXX: horrible */
2037 SDL_Delay(10);
2038 continue;
2039 }
400738b1 2040#endif
72ea344b 2041 if (is->seek_req) {
8e606cc8 2042 int64_t seek_target= is->seek_pos;
4ed29207
MN
2043 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2044 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2045//FIXME the +-2 is due to rounding being not done in the correct direction in generation
2046// of the seek_pos/seek_rel variables
8e606cc8 2047
4ed29207 2048 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
72ea344b
FB
2049 if (ret < 0) {
2050 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
e6c0297f
MN
2051 }else{
2052 if (is->audio_stream >= 0) {
2053 packet_queue_flush(&is->audioq);
39c6a118 2054 packet_queue_put(&is->audioq, &flush_pkt);
e6c0297f 2055 }
72ce053b
IC
2056 if (is->subtitle_stream >= 0) {
2057 packet_queue_flush(&is->subtitleq);
39c6a118 2058 packet_queue_put(&is->subtitleq, &flush_pkt);
72ce053b 2059 }
e6c0297f
MN
2060 if (is->video_stream >= 0) {
2061 packet_queue_flush(&is->videoq);
39c6a118 2062 packet_queue_put(&is->videoq, &flush_pkt);
e6c0297f 2063 }
72ea344b
FB
2064 }
2065 is->seek_req = 0;
e45aeb38 2066 eof= 0;
72ea344b 2067 }
416e3508 2068
01310af2
FB
2069 /* if the queue are full, no need to read more */
2070 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
115329f1 2071 is->videoq.size > MAX_VIDEOQ_SIZE ||
600a331c 2072 is->subtitleq.size > MAX_SUBTITLEQ_SIZE) {
01310af2
FB
2073 /* wait 10 ms */
2074 SDL_Delay(10);
2075 continue;
2076 }
75bb7b0a 2077 if(url_feof(ic->pb) || eof) {
9dc41767 2078 if(is->video_stream >= 0){
26534fe8
MN
2079 av_init_packet(pkt);
2080 pkt->data=NULL;
2081 pkt->size=0;
2082 pkt->stream_index= is->video_stream;
2083 packet_queue_put(&is->videoq, pkt);
9dc41767 2084 }
b4083171 2085 SDL_Delay(10);
600a331c
MN
2086 continue;
2087 }
72ea344b 2088 ret = av_read_frame(ic, pkt);
01310af2 2089 if (ret < 0) {
75bb7b0a
MN
2090 if (ret == AVERROR_EOF)
2091 eof=1;
2092 if (url_ferror(ic->pb))
bb270c08 2093 break;
75bb7b0a
MN
2094 SDL_Delay(100); /* wait for user event */
2095 continue;
01310af2
FB
2096 }
2097 if (pkt->stream_index == is->audio_stream) {
2098 packet_queue_put(&is->audioq, pkt);
2099 } else if (pkt->stream_index == is->video_stream) {
2100 packet_queue_put(&is->videoq, pkt);
72ce053b
IC
2101 } else if (pkt->stream_index == is->subtitle_stream) {
2102 packet_queue_put(&is->subtitleq, pkt);
01310af2
FB
2103 } else {
2104 av_free_packet(pkt);
2105 }
2106 }
2107 /* wait until the end */
2108 while (!is->abort_request) {
2109 SDL_Delay(100);
2110 }
2111
638c9d91 2112 ret = 0;
01310af2 2113 fail:
416e3508
FB
2114 /* disable interrupting */
2115 global_video_state = NULL;
2116
01310af2
FB
2117 /* close each stream */
2118 if (is->audio_stream >= 0)
2119 stream_component_close(is, is->audio_stream);
2120 if (is->video_stream >= 0)
2121 stream_component_close(is, is->video_stream);
72ce053b
IC
2122 if (is->subtitle_stream >= 0)
2123 stream_component_close(is, is->subtitle_stream);
638c9d91
FB
2124 if (is->ic) {
2125 av_close_input_file(is->ic);
2126 is->ic = NULL; /* safety */
2127 }
416e3508
FB
2128 url_set_interrupt_cb(NULL);
2129
638c9d91
FB
2130 if (ret != 0) {
2131 SDL_Event event;
115329f1 2132
638c9d91
FB
2133 event.type = FF_QUIT_EVENT;
2134 event.user.data1 = is;
2135 SDL_PushEvent(&event);
2136 }
01310af2
FB
2137 return 0;
2138}
2139
638c9d91 2140static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
01310af2
FB
2141{
2142 VideoState *is;
2143
2144 is = av_mallocz(sizeof(VideoState));
2145 if (!is)
2146 return NULL;
f7d78f36 2147 av_strlcpy(is->filename, filename, sizeof(is->filename));
638c9d91 2148 is->iformat = iformat;
01310af2
FB
2149 is->ytop = 0;
2150 is->xleft = 0;
2151
2152 /* start video display */
2153 is->pictq_mutex = SDL_CreateMutex();
2154 is->pictq_cond = SDL_CreateCond();
115329f1 2155
72ce053b
IC
2156 is->subpq_mutex = SDL_CreateMutex();
2157 is->subpq_cond = SDL_CreateCond();
115329f1 2158
01310af2
FB
2159 /* add the refresh timer to draw the picture */
2160 schedule_refresh(is, 40);
2161
638c9d91 2162 is->av_sync_type = av_sync_type;
01310af2
FB
2163 is->parse_tid = SDL_CreateThread(decode_thread, is);
2164 if (!is->parse_tid) {
2165 av_free(is);
2166 return NULL;
2167 }
2168 return is;
2169}
2170
2171static void stream_close(VideoState *is)
2172{
2173 VideoPicture *vp;
2174 int i;
2175 /* XXX: use a special url_shutdown call to abort parse cleanly */
2176 is->abort_request = 1;
2177 SDL_WaitThread(is->parse_tid, NULL);
2178
2179 /* free all pictures */
2180 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2181 vp = &is->pictq[i];
2182 if (vp->bmp) {
2183 SDL_FreeYUVOverlay(vp->bmp);
2184 vp->bmp = NULL;
2185 }
2186 }
2187 SDL_DestroyMutex(is->pictq_mutex);
2188 SDL_DestroyCond(is->pictq_cond);
72ce053b
IC
2189 SDL_DestroyMutex(is->subpq_mutex);
2190 SDL_DestroyCond(is->subpq_cond);
3ac56e28
MS
2191 if (is->img_convert_ctx)
2192 sws_freeContext(is->img_convert_ctx);
7c5ab145 2193 av_free(is);
01310af2
FB
2194}
2195
7b49ce2e 2196static void stream_cycle_channel(VideoState *is, int codec_type)
638c9d91
FB
2197{
2198 AVFormatContext *ic = is->ic;
2199 int start_index, stream_index;
2200 AVStream *st;
2201
2202 if (codec_type == CODEC_TYPE_VIDEO)
2203 start_index = is->video_stream;
72ce053b 2204 else if (codec_type == CODEC_TYPE_AUDIO)
638c9d91 2205 start_index = is->audio_stream;
72ce053b
IC
2206 else
2207 start_index = is->subtitle_stream;
2208 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
638c9d91
FB
2209 return;
2210 stream_index = start_index;
2211 for(;;) {
2212 if (++stream_index >= is->ic->nb_streams)
72ce053b
IC
2213 {
2214 if (codec_type == CODEC_TYPE_SUBTITLE)
2215 {
2216 stream_index = -1;
2217 goto the_end;
2218 } else
2219 stream_index = 0;
2220 }
638c9d91
FB
2221 if (stream_index == start_index)
2222 return;
2223 st = ic->streams[stream_index];
01f4895c 2224 if (st->codec->codec_type == codec_type) {
638c9d91
FB
2225 /* check that parameters are OK */
2226 switch(codec_type) {
2227 case CODEC_TYPE_AUDIO:
01f4895c
MN
2228 if (st->codec->sample_rate != 0 &&
2229 st->codec->channels != 0)
638c9d91
FB
2230 goto the_end;
2231 break;
2232 case CODEC_TYPE_VIDEO:
72ce053b 2233 case CODEC_TYPE_SUBTITLE:
638c9d91
FB
2234 goto the_end;
2235 default:
2236 break;
2237 }
2238 }
2239 }
2240 the_end:
2241 stream_component_close(is, start_index);
2242 stream_component_open(is, stream_index);
2243}
2244
2245
7b49ce2e 2246static void toggle_full_screen(void)
01310af2 2247{
01310af2 2248 is_full_screen = !is_full_screen;
29f3b38a
MR
2249 if (!fs_screen_width) {
2250 /* use default SDL method */
fb84155b 2251// SDL_WM_ToggleFullScreen(screen);
01310af2 2252 }
fb84155b 2253 video_open(cur_stream);
01310af2
FB
2254}
2255
7b49ce2e 2256static void toggle_pause(void)
01310af2
FB
2257{
2258 if (cur_stream)
2259 stream_pause(cur_stream);
bba04f1e
WH
2260 step = 0;
2261}
2262
7b49ce2e 2263static void step_to_next_frame(void)
bba04f1e
WH
2264{
2265 if (cur_stream) {
19cc524a 2266 /* if the stream is paused unpause it, then step */
bba04f1e 2267 if (cur_stream->paused)
19cc524a 2268 stream_pause(cur_stream);
bba04f1e
WH
2269 }
2270 step = 1;
01310af2
FB
2271}
2272
7b49ce2e 2273static void do_exit(void)
01310af2 2274{
7c5ab145 2275 int i;
01310af2
FB
2276 if (cur_stream) {
2277 stream_close(cur_stream);
2278 cur_stream = NULL;
2279 }
7c5ab145
MS
2280 for (i = 0; i < CODEC_TYPE_NB; i++)
2281 av_free(avcodec_opts[i]);
2282 av_free(avformat_opts);
2283 av_free(sws_opts);
01310af2
FB
2284 if (show_status)
2285 printf("\n");
2286 SDL_Quit();
2287 exit(0);
2288}
2289
7b49ce2e 2290static void toggle_audio_display(void)
01310af2
FB
2291{
2292 if (cur_stream) {
2293 cur_stream->show_audio = !cur_stream->show_audio;
2294 }
2295}
2296
2297/* handle an event sent by the GUI */
7b49ce2e 2298static void event_loop(void)
01310af2
FB
2299{
2300 SDL_Event event;
a11d11aa 2301 double incr, pos, frac;
01310af2
FB
2302
2303 for(;;) {
2304 SDL_WaitEvent(&event);
2305 switch(event.type) {
2306 case SDL_KEYDOWN:
2307 switch(event.key.keysym.sym) {
2308 case SDLK_ESCAPE:
2309 case SDLK_q:
2310 do_exit();
2311 break;
2312 case SDLK_f:
2313 toggle_full_screen();
2314 break;
2315 case SDLK_p:
2316 case SDLK_SPACE:
2317 toggle_pause();
2318 break;
bba04f1e
WH
2319 case SDLK_s: //S: Step to next frame
2320 step_to_next_frame();
2321 break;
01310af2 2322 case SDLK_a:
115329f1 2323 if (cur_stream)
638c9d91
FB
2324 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2325 break;
2326 case SDLK_v:
115329f1 2327 if (cur_stream)
638c9d91
FB
2328 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2329 break;
72ce053b 2330 case SDLK_t:
115329f1 2331 if (cur_stream)
72ce053b
IC
2332 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2333 break;
638c9d91 2334 case SDLK_w:
01310af2
FB
2335 toggle_audio_display();
2336 break;
72ea344b
FB
2337 case SDLK_LEFT:
2338 incr = -10.0;
2339 goto do_seek;
2340 case SDLK_RIGHT:
2341 incr = 10.0;
2342 goto do_seek;
2343 case SDLK_UP:
2344 incr = 60.0;
2345 goto do_seek;
2346 case SDLK_DOWN:
2347 incr = -60.0;
2348 do_seek:
2349 if (cur_stream) {
94b594c6 2350 if (seek_by_bytes) {
899681cd 2351 pos = url_ftell(cur_stream->ic->pb);
94b594c6
SH
2352 if (cur_stream->ic->bit_rate)
2353 incr *= cur_stream->ic->bit_rate / 60.0;
2354 else
2355 incr *= 180000.0;
2356 pos += incr;
2357 stream_seek(cur_stream, pos, incr);
2358 } else {
2359 pos = get_master_clock(cur_stream);
2360 pos += incr;
4ed29207 2361 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE));
94b594c6 2362 }
72ea344b
FB
2363 }
2364 break;
01310af2
FB
2365 default:
2366 break;
2367 }
2368 break;
a11d11aa 2369 case SDL_MOUSEBUTTONDOWN:
bb270c08
DB
2370 if (cur_stream) {
2371 int ns, hh, mm, ss;
2372 int tns, thh, tmm, tss;
2373 tns = cur_stream->ic->duration/1000000LL;
2374 thh = tns/3600;
2375 tmm = (tns%3600)/60;
2376 tss = (tns%60);
2377 frac = (double)event.button.x/(double)cur_stream->width;
2378 ns = frac*tns;
2379 hh = ns/3600;
2380 mm = (ns%3600)/60;
2381 ss = (ns%60);
2382 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2383 hh, mm, ss, thh, tmm, tss);
2384 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
2385 }
2386 break;
01310af2
FB
2387 case SDL_VIDEORESIZE:
2388 if (cur_stream) {
115329f1 2389 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
01310af2 2390 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
c57d3469
MN
2391 screen_width = cur_stream->width = event.resize.w;
2392 screen_height= cur_stream->height= event.resize.h;
01310af2
FB
2393 }
2394 break;
2395 case SDL_QUIT:
638c9d91 2396 case FF_QUIT_EVENT:
01310af2
FB
2397 do_exit();
2398 break;
2399 case FF_ALLOC_EVENT:
fccb19e3 2400 video_open(event.user.data1);
01310af2
FB
2401 alloc_picture(event.user.data1);
2402 break;
2403 case FF_REFRESH_EVENT:
2404 video_refresh_timer(event.user.data1);
2405 break;
2406 default:
2407 break;
2408 }
2409 }
2410}
2411
e4b89522
LW
2412static void opt_frame_size(const char *arg)
2413{
b33ece16 2414 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
e4b89522
LW
2415 fprintf(stderr, "Incorrect frame size\n");
2416 exit(1);
2417 }
2418 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2419 fprintf(stderr, "Frame size must be a multiple of 2\n");
2420 exit(1);
2421 }
2422}
2423
a5b3b5f6 2424static int opt_width(const char *opt, const char *arg)
01310af2 2425{
a5b3b5f6
SS
2426 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2427 return 0;
01310af2
FB
2428}
2429
a5b3b5f6 2430static int opt_height(const char *opt, const char *arg)
01310af2 2431{
a5b3b5f6
SS
2432 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2433 return 0;
01310af2
FB
2434}
2435
2436static void opt_format(const char *arg)
2437{
2438 file_iformat = av_find_input_format(arg);
2439 if (!file_iformat) {
2440 fprintf(stderr, "Unknown input format: %s\n", arg);
2441 exit(1);
2442 }
2443}
61890b02 2444
e4b89522
LW
2445static void opt_frame_pix_fmt(const char *arg)
2446{
2447 frame_pix_fmt = avcodec_get_pix_fmt(arg);
2448}
2449
b81d6235 2450static int opt_sync(const char *opt, const char *arg)
638c9d91
FB
2451{
2452 if (!strcmp(arg, "audio"))
2453 av_sync_type = AV_SYNC_AUDIO_MASTER;
2454 else if (!strcmp(arg, "video"))
2455 av_sync_type = AV_SYNC_VIDEO_MASTER;
2456 else if (!strcmp(arg, "ext"))
2457 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
aab1b7e5 2458 else {
b81d6235 2459 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
aab1b7e5
SS
2460 exit(1);
2461 }
b81d6235 2462 return 0;
638c9d91
FB
2463}
2464
e11bc2c6 2465static int opt_seek(const char *opt, const char *arg)
72ea344b 2466{
e11bc2c6
SS
2467 start_time = parse_time_or_die(opt, arg, 1);
2468 return 0;
72ea344b
FB
2469}
2470
a5b3b5f6 2471static int opt_debug(const char *opt, const char *arg)
e26a8335 2472{
a309073b 2473 av_log_set_level(99);
a5b3b5f6
SS
2474 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2475 return 0;
e26a8335 2476}
115329f1 2477
a5b3b5f6 2478static int opt_vismv(const char *opt, const char *arg)
0c9bbaec 2479{
a5b3b5f6
SS
2480 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2481 return 0;
0c9bbaec 2482}
c62c07d3 2483
a5b3b5f6 2484static int opt_thread_count(const char *opt, const char *arg)
c62c07d3 2485{
a5b3b5f6 2486 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
b250f9c6 2487#if !HAVE_THREADS
c62c07d3
MN
2488 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2489#endif
a5b3b5f6 2490 return 0;
c62c07d3 2491}
115329f1 2492
358061f6 2493static const OptionDef options[] = {
20176cbc
MN
2494 { "h", OPT_EXIT, {(void*)show_help}, "show help" },
2495 { "version", OPT_EXIT, {(void*)show_version}, "show version" },
8fdea204 2496 { "L", OPT_EXIT, {(void*)show_license}, "show license" },
a28b7ed4 2497 { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
a5b3b5f6
SS
2498 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2499 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
e4b89522 2500 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
638c9d91 2501 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
01310af2
FB
2502 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2503 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
4b037567
SS
2504 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "select desired audio stream", "stream_number" },
2505 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "select desired video stream", "stream_number" },
2506 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "select desired subtitle stream", "stream_number" },
e11bc2c6 2507 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
94b594c6 2508 { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
01310af2
FB
2509 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2510 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
e4b89522 2511 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
01310af2 2512 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
a5b3b5f6 2513 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
6387c3e6 2514 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
a5b3b5f6 2515 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
6fc5b059 2516 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
30bc6613 2517 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
5039185a 2518 { "drp", OPT_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
178fcca8 2519 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
8c3eba7c
MN
2520 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2521 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2522 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
178fcca8 2523 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
047599a4 2524 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
1b51e051 2525 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
b81d6235 2526 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
a5b3b5f6 2527 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
e43d7a18 2528 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
01310af2
FB
2529 { NULL, },
2530};
2531
358061f6 2532static void show_help(void)
01310af2 2533{
9c5755ee 2534 printf("usage: ffplay [options] input_file\n"
01310af2
FB
2535 "Simple media player\n");
2536 printf("\n");
02d504a7
FB
2537 show_help_options(options, "Main options:\n",
2538 OPT_EXPERT, 0);
2539 show_help_options(options, "\nAdvanced options:\n",
2540 OPT_EXPERT, OPT_EXPERT);
01310af2
FB
2541 printf("\nWhile playing:\n"
2542 "q, ESC quit\n"
2543 "f toggle full screen\n"
2544 "p, SPC pause\n"
638c9d91
FB
2545 "a cycle audio channel\n"
2546 "v cycle video channel\n"
72ce053b 2547 "t cycle subtitle channel\n"
638c9d91 2548 "w show audio waves\n"
72ea344b
FB
2549 "left/right seek backward/forward 10 seconds\n"
2550 "down/up seek backward/forward 1 minute\n"
a11d11aa 2551 "mouse click seek to percentage in file corresponding to fraction of width\n"
01310af2 2552 );
01310af2
FB
2553}
2554
358061f6 2555static void opt_input_file(const char *filename)
01310af2 2556{
e8d83e1c 2557 if (!strcmp(filename, "-"))
9fcfc0b7 2558 filename = "pipe:";
01310af2
FB
2559 input_filename = filename;
2560}
2561
2562/* Called from the main */
2563int main(int argc, char **argv)
2564{
e43d7a18 2565 int flags, i;
115329f1 2566
01310af2 2567 /* register all codecs, demux and protocols */
c721d803
LA
2568 avcodec_register_all();
2569 avdevice_register_all();
01310af2
FB
2570 av_register_all();
2571
e43d7a18 2572 for(i=0; i<CODEC_TYPE_NB; i++){
636f1c4c 2573 avcodec_opts[i]= avcodec_alloc_context2(i);
e43d7a18 2574 }
8e2fd8e1 2575 avformat_opts = avformat_alloc_context();
e43d7a18
MN
2576 sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
2577
ea9c581f 2578 show_banner();
4cfac5bc 2579
f5da5c93 2580 parse_options(argc, argv, options, opt_input_file);
01310af2 2581
aab1b7e5 2582 if (!input_filename) {
7a7da6b4 2583 fprintf(stderr, "An input file must be specified\n");
aab1b7e5
SS
2584 exit(1);
2585 }
01310af2
FB
2586
2587 if (display_disable) {
2588 video_disable = 1;
2589 }
31319a8c 2590 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
c97f5402
DB
2591#if !defined(__MINGW32__) && !defined(__APPLE__)
2592 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
31319a8c 2593#endif
01310af2 2594 if (SDL_Init (flags)) {
05ab0b76 2595 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
01310af2
FB
2596 exit(1);
2597 }
2598
2599 if (!display_disable) {
b250f9c6 2600#if HAVE_SDL_VIDEO_SIZE
3ef17d62
MR
2601 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2602 fs_screen_width = vi->current_w;
2603 fs_screen_height = vi->current_h;
29f3b38a 2604#endif
01310af2
FB
2605 }
2606
2607 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2608 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2609 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2610 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2611
39c6a118
MN
2612 av_init_packet(&flush_pkt);
2613 flush_pkt.data= "FLUSH";
2614
638c9d91 2615 cur_stream = stream_open(input_filename, file_iformat);
01310af2
FB
2616
2617 event_loop();
2618
2619 /* never returns */
2620
2621 return 0;
2622}