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