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