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