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