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