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