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