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