FFplay : Fix segfault when playing monoaural streams.
[libav.git] / ffplay.c
1 /*
2 * FFplay : Simple Media Player based on the FFmpeg libraries
3 * Copyright (c) 2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
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
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "config.h"
23 #include <inttypes.h>
24 #include <math.h>
25 #include <limits.h>
26 #include "libavutil/avstring.h"
27 #include "libavutil/colorspace.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavformat/avformat.h"
30 #include "libavdevice/avdevice.h"
31 #include "libswscale/swscale.h"
32 #include "libavcodec/audioconvert.h"
33 #include "libavcodec/opt.h"
34 #include "libavcodec/avfft.h"
35
36 #if CONFIG_AVFILTER
37 # include "libavfilter/avfilter.h"
38 # include "libavfilter/avfiltergraph.h"
39 # include "libavfilter/graphparser.h"
40 #endif
41
42 #include "cmdutils.h"
43
44 #include <SDL.h>
45 #include <SDL_thread.h>
46
47 #ifdef __MINGW32__
48 #undef main /* We don't want SDL to override our main() */
49 #endif
50
51 #include <unistd.h>
52 #include <assert.h>
53
54 const char program_name[] = "FFplay";
55 const int program_birth_year = 2003;
56
57 //#define DEBUG_SYNC
58
59 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
60 #define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
61 #define MIN_FRAMES 5
62
63 /* SDL audio buffer size, in samples. Should be small to have precise
64 A/V sync as SDL does not have hardware buffer fullness info. */
65 #define SDL_AUDIO_BUFFER_SIZE 1024
66
67 /* no AV sync correction is done if below the AV sync threshold */
68 #define AV_SYNC_THRESHOLD 0.01
69 /* no AV correction is done if too big error */
70 #define AV_NOSYNC_THRESHOLD 10.0
71
72 #define FRAME_SKIP_FACTOR 0.05
73
74 /* maximum audio speed change to get correct sync */
75 #define SAMPLE_CORRECTION_PERCENT_MAX 10
76
77 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
78 #define AUDIO_DIFF_AVG_NB 20
79
80 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
81 #define SAMPLE_ARRAY_SIZE (2*65536)
82
83 static int sws_flags = SWS_BICUBIC;
84
85 typedef struct PacketQueue {
86 AVPacketList *first_pkt, *last_pkt;
87 int nb_packets;
88 int size;
89 int abort_request;
90 SDL_mutex *mutex;
91 SDL_cond *cond;
92 } PacketQueue;
93
94 #define VIDEO_PICTURE_QUEUE_SIZE 2
95 #define SUBPICTURE_QUEUE_SIZE 4
96
97 typedef struct VideoPicture {
98 double pts; ///<presentation time stamp for this picture
99 double target_clock; ///<av_gettime() time at which this should be displayed ideally
100 int64_t pos; ///<byte position in file
101 SDL_Overlay *bmp;
102 int width, height; /* source height & width */
103 int allocated;
104 enum PixelFormat pix_fmt;
105
106 #if CONFIG_AVFILTER
107 AVFilterPicRef *picref;
108 #endif
109 } VideoPicture;
110
111 typedef struct SubPicture {
112 double pts; /* presentation time stamp for this picture */
113 AVSubtitle sub;
114 } SubPicture;
115
116 enum {
117 AV_SYNC_AUDIO_MASTER, /* default choice */
118 AV_SYNC_VIDEO_MASTER,
119 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
120 };
121
122 typedef struct VideoState {
123 SDL_Thread *parse_tid;
124 SDL_Thread *video_tid;
125 SDL_Thread *refresh_tid;
126 AVInputFormat *iformat;
127 int no_background;
128 int abort_request;
129 int paused;
130 int last_paused;
131 int seek_req;
132 int seek_flags;
133 int64_t seek_pos;
134 int64_t seek_rel;
135 int read_pause_return;
136 AVFormatContext *ic;
137 int dtg_active_format;
138
139 int audio_stream;
140
141 int av_sync_type;
142 double external_clock; /* external clock base */
143 int64_t external_clock_time;
144
145 double audio_clock;
146 double audio_diff_cum; /* used for AV difference average computation */
147 double audio_diff_avg_coef;
148 double audio_diff_threshold;
149 int audio_diff_avg_count;
150 AVStream *audio_st;
151 PacketQueue audioq;
152 int audio_hw_buf_size;
153 /* samples output by the codec. we reserve more space for avsync
154 compensation */
155 DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
156 DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
157 uint8_t *audio_buf;
158 unsigned int audio_buf_size; /* in bytes */
159 int audio_buf_index; /* in bytes */
160 AVPacket audio_pkt_temp;
161 AVPacket audio_pkt;
162 enum SampleFormat audio_src_fmt;
163 AVAudioConvert *reformat_ctx;
164
165 int show_audio; /* if true, display audio samples */
166 int16_t sample_array[SAMPLE_ARRAY_SIZE];
167 int sample_array_index;
168 int last_i_start;
169 RDFTContext *rdft;
170 int rdft_bits;
171 FFTSample *rdft_data;
172 int xpos;
173
174 SDL_Thread *subtitle_tid;
175 int subtitle_stream;
176 int subtitle_stream_changed;
177 AVStream *subtitle_st;
178 PacketQueue subtitleq;
179 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
180 int subpq_size, subpq_rindex, subpq_windex;
181 SDL_mutex *subpq_mutex;
182 SDL_cond *subpq_cond;
183
184 double frame_timer;
185 double frame_last_pts;
186 double frame_last_delay;
187 double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
188 int video_stream;
189 AVStream *video_st;
190 PacketQueue videoq;
191 double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
192 double video_current_pts_drift; ///<video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
193 int64_t video_current_pos; ///<current displayed file pos
194 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
195 int pictq_size, pictq_rindex, pictq_windex;
196 SDL_mutex *pictq_mutex;
197 SDL_cond *pictq_cond;
198 #if !CONFIG_AVFILTER
199 struct SwsContext *img_convert_ctx;
200 #endif
201
202 // QETimer *video_timer;
203 char filename[1024];
204 int width, height, xleft, ytop;
205
206 int64_t faulty_pts;
207 int64_t faulty_dts;
208 int64_t last_dts_for_fault_detection;
209 int64_t last_pts_for_fault_detection;
210
211 #if CONFIG_AVFILTER
212 AVFilterContext *out_video_filter; ///<the last filter in the video chain
213 #endif
214
215 float skip_frames;
216 float skip_frames_index;
217 int refresh;
218 } VideoState;
219
220 static void show_help(void);
221 static int audio_write_get_buf_size(VideoState *is);
222
223 /* options specified by the user */
224 static AVInputFormat *file_iformat;
225 static const char *input_filename;
226 static const char *window_title;
227 static int fs_screen_width;
228 static int fs_screen_height;
229 static int screen_width = 0;
230 static int screen_height = 0;
231 static int frame_width = 0;
232 static int frame_height = 0;
233 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
234 static int audio_disable;
235 static int video_disable;
236 static int wanted_stream[AVMEDIA_TYPE_NB]={
237 [AVMEDIA_TYPE_AUDIO]=-1,
238 [AVMEDIA_TYPE_VIDEO]=-1,
239 [AVMEDIA_TYPE_SUBTITLE]=-1,
240 };
241 static int seek_by_bytes=-1;
242 static int display_disable;
243 static int show_status = 1;
244 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
245 static int64_t start_time = AV_NOPTS_VALUE;
246 static int64_t duration = AV_NOPTS_VALUE;
247 static int debug = 0;
248 static int debug_mv = 0;
249 static int step = 0;
250 static int thread_count = 1;
251 static int workaround_bugs = 1;
252 static int fast = 0;
253 static int genpts = 0;
254 static int lowres = 0;
255 static int idct = FF_IDCT_AUTO;
256 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
257 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
258 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
259 static int error_recognition = FF_ER_CAREFUL;
260 static int error_concealment = 3;
261 static int decoder_reorder_pts= -1;
262 static int autoexit;
263 static int exit_on_keydown;
264 static int exit_on_mousedown;
265 static int loop=1;
266 static int framedrop=1;
267
268 static int rdftspeed=20;
269 #if CONFIG_AVFILTER
270 static char *vfilters = NULL;
271 #endif
272
273 /* current context */
274 static int is_full_screen;
275 static VideoState *cur_stream;
276 static int64_t audio_callback_time;
277
278 static AVPacket flush_pkt;
279
280 #define FF_ALLOC_EVENT (SDL_USEREVENT)
281 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
282 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
283
284 static SDL_Surface *screen;
285
286 static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
287
288 /* packet queue handling */
289 static void packet_queue_init(PacketQueue *q)
290 {
291 memset(q, 0, sizeof(PacketQueue));
292 q->mutex = SDL_CreateMutex();
293 q->cond = SDL_CreateCond();
294 packet_queue_put(q, &flush_pkt);
295 }
296
297 static void packet_queue_flush(PacketQueue *q)
298 {
299 AVPacketList *pkt, *pkt1;
300
301 SDL_LockMutex(q->mutex);
302 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
303 pkt1 = pkt->next;
304 av_free_packet(&pkt->pkt);
305 av_freep(&pkt);
306 }
307 q->last_pkt = NULL;
308 q->first_pkt = NULL;
309 q->nb_packets = 0;
310 q->size = 0;
311 SDL_UnlockMutex(q->mutex);
312 }
313
314 static void packet_queue_end(PacketQueue *q)
315 {
316 packet_queue_flush(q);
317 SDL_DestroyMutex(q->mutex);
318 SDL_DestroyCond(q->cond);
319 }
320
321 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
322 {
323 AVPacketList *pkt1;
324
325 /* duplicate the packet */
326 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
327 return -1;
328
329 pkt1 = av_malloc(sizeof(AVPacketList));
330 if (!pkt1)
331 return -1;
332 pkt1->pkt = *pkt;
333 pkt1->next = NULL;
334
335
336 SDL_LockMutex(q->mutex);
337
338 if (!q->last_pkt)
339
340 q->first_pkt = pkt1;
341 else
342 q->last_pkt->next = pkt1;
343 q->last_pkt = pkt1;
344 q->nb_packets++;
345 q->size += pkt1->pkt.size + sizeof(*pkt1);
346 /* XXX: should duplicate packet data in DV case */
347 SDL_CondSignal(q->cond);
348
349 SDL_UnlockMutex(q->mutex);
350 return 0;
351 }
352
353 static void packet_queue_abort(PacketQueue *q)
354 {
355 SDL_LockMutex(q->mutex);
356
357 q->abort_request = 1;
358
359 SDL_CondSignal(q->cond);
360
361 SDL_UnlockMutex(q->mutex);
362 }
363
364 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
365 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
366 {
367 AVPacketList *pkt1;
368 int ret;
369
370 SDL_LockMutex(q->mutex);
371
372 for(;;) {
373 if (q->abort_request) {
374 ret = -1;
375 break;
376 }
377
378 pkt1 = q->first_pkt;
379 if (pkt1) {
380 q->first_pkt = pkt1->next;
381 if (!q->first_pkt)
382 q->last_pkt = NULL;
383 q->nb_packets--;
384 q->size -= pkt1->pkt.size + sizeof(*pkt1);
385 *pkt = pkt1->pkt;
386 av_free(pkt1);
387 ret = 1;
388 break;
389 } else if (!block) {
390 ret = 0;
391 break;
392 } else {
393 SDL_CondWait(q->cond, q->mutex);
394 }
395 }
396 SDL_UnlockMutex(q->mutex);
397 return ret;
398 }
399
400 static inline void fill_rectangle(SDL_Surface *screen,
401 int x, int y, int w, int h, int color)
402 {
403 SDL_Rect rect;
404 rect.x = x;
405 rect.y = y;
406 rect.w = w;
407 rect.h = h;
408 SDL_FillRect(screen, &rect, color);
409 }
410
411 #if 0
412 /* draw only the border of a rectangle */
413 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
414 {
415 int w1, w2, h1, h2;
416
417 /* fill the background */
418 w1 = x;
419 if (w1 < 0)
420 w1 = 0;
421 w2 = s->width - (x + w);
422 if (w2 < 0)
423 w2 = 0;
424 h1 = y;
425 if (h1 < 0)
426 h1 = 0;
427 h2 = s->height - (y + h);
428 if (h2 < 0)
429 h2 = 0;
430 fill_rectangle(screen,
431 s->xleft, s->ytop,
432 w1, s->height,
433 color);
434 fill_rectangle(screen,
435 s->xleft + s->width - w2, s->ytop,
436 w2, s->height,
437 color);
438 fill_rectangle(screen,
439 s->xleft + w1, s->ytop,
440 s->width - w1 - w2, h1,
441 color);
442 fill_rectangle(screen,
443 s->xleft + w1, s->ytop + s->height - h2,
444 s->width - w1 - w2, h2,
445 color);
446 }
447 #endif
448
449 #define ALPHA_BLEND(a, oldp, newp, s)\
450 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
451
452 #define RGBA_IN(r, g, b, a, s)\
453 {\
454 unsigned int v = ((const uint32_t *)(s))[0];\
455 a = (v >> 24) & 0xff;\
456 r = (v >> 16) & 0xff;\
457 g = (v >> 8) & 0xff;\
458 b = v & 0xff;\
459 }
460
461 #define YUVA_IN(y, u, v, a, s, pal)\
462 {\
463 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
464 a = (val >> 24) & 0xff;\
465 y = (val >> 16) & 0xff;\
466 u = (val >> 8) & 0xff;\
467 v = val & 0xff;\
468 }
469
470 #define YUVA_OUT(d, y, u, v, a)\
471 {\
472 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
473 }
474
475
476 #define BPP 1
477
478 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
479 {
480 int wrap, wrap3, width2, skip2;
481 int y, u, v, a, u1, v1, a1, w, h;
482 uint8_t *lum, *cb, *cr;
483 const uint8_t *p;
484 const uint32_t *pal;
485 int dstx, dsty, dstw, dsth;
486
487 dstw = av_clip(rect->w, 0, imgw);
488 dsth = av_clip(rect->h, 0, imgh);
489 dstx = av_clip(rect->x, 0, imgw - dstw);
490 dsty = av_clip(rect->y, 0, imgh - dsth);
491 lum = dst->data[0] + dsty * dst->linesize[0];
492 cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
493 cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
494
495 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
496 skip2 = dstx >> 1;
497 wrap = dst->linesize[0];
498 wrap3 = rect->pict.linesize[0];
499 p = rect->pict.data[0];
500 pal = (const uint32_t *)rect->pict.data[1]; /* Now in YCrCb! */
501
502 if (dsty & 1) {
503 lum += dstx;
504 cb += skip2;
505 cr += skip2;
506
507 if (dstx & 1) {
508 YUVA_IN(y, u, v, a, p, pal);
509 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
510 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
511 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
512 cb++;
513 cr++;
514 lum++;
515 p += BPP;
516 }
517 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
518 YUVA_IN(y, u, v, a, p, pal);
519 u1 = u;
520 v1 = v;
521 a1 = a;
522 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
523
524 YUVA_IN(y, u, v, a, p + BPP, pal);
525 u1 += u;
526 v1 += v;
527 a1 += a;
528 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
529 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
530 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
531 cb++;
532 cr++;
533 p += 2 * BPP;
534 lum += 2;
535 }
536 if (w) {
537 YUVA_IN(y, u, v, a, p, pal);
538 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
539 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
540 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
541 p++;
542 lum++;
543 }
544 p += wrap3 - dstw * BPP;
545 lum += wrap - dstw - dstx;
546 cb += dst->linesize[1] - width2 - skip2;
547 cr += dst->linesize[2] - width2 - skip2;
548 }
549 for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
550 lum += dstx;
551 cb += skip2;
552 cr += skip2;
553
554 if (dstx & 1) {
555 YUVA_IN(y, u, v, a, p, pal);
556 u1 = u;
557 v1 = v;
558 a1 = a;
559 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
560 p += wrap3;
561 lum += wrap;
562 YUVA_IN(y, u, v, a, p, pal);
563 u1 += u;
564 v1 += v;
565 a1 += a;
566 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
567 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
568 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
569 cb++;
570 cr++;
571 p += -wrap3 + BPP;
572 lum += -wrap + 1;
573 }
574 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
575 YUVA_IN(y, u, v, a, p, pal);
576 u1 = u;
577 v1 = v;
578 a1 = a;
579 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
580
581 YUVA_IN(y, u, v, a, p + BPP, pal);
582 u1 += u;
583 v1 += v;
584 a1 += a;
585 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
586 p += wrap3;
587 lum += wrap;
588
589 YUVA_IN(y, u, v, a, p, pal);
590 u1 += u;
591 v1 += v;
592 a1 += a;
593 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
594
595 YUVA_IN(y, u, v, a, p + BPP, pal);
596 u1 += u;
597 v1 += v;
598 a1 += a;
599 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
600
601 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
602 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
603
604 cb++;
605 cr++;
606 p += -wrap3 + 2 * BPP;
607 lum += -wrap + 2;
608 }
609 if (w) {
610 YUVA_IN(y, u, v, a, p, pal);
611 u1 = u;
612 v1 = v;
613 a1 = a;
614 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
615 p += wrap3;
616 lum += wrap;
617 YUVA_IN(y, u, v, a, p, pal);
618 u1 += u;
619 v1 += v;
620 a1 += a;
621 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
622 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
623 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
624 cb++;
625 cr++;
626 p += -wrap3 + BPP;
627 lum += -wrap + 1;
628 }
629 p += wrap3 + (wrap3 - dstw * BPP);
630 lum += wrap + (wrap - dstw - dstx);
631 cb += dst->linesize[1] - width2 - skip2;
632 cr += dst->linesize[2] - width2 - skip2;
633 }
634 /* handle odd height */
635 if (h) {
636 lum += dstx;
637 cb += skip2;
638 cr += skip2;
639
640 if (dstx & 1) {
641 YUVA_IN(y, u, v, a, p, pal);
642 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
643 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
644 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
645 cb++;
646 cr++;
647 lum++;
648 p += BPP;
649 }
650 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
651 YUVA_IN(y, u, v, a, p, pal);
652 u1 = u;
653 v1 = v;
654 a1 = a;
655 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
656
657 YUVA_IN(y, u, v, a, p + BPP, pal);
658 u1 += u;
659 v1 += v;
660 a1 += a;
661 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
662 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
663 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
664 cb++;
665 cr++;
666 p += 2 * BPP;
667 lum += 2;
668 }
669 if (w) {
670 YUVA_IN(y, u, v, a, p, pal);
671 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
672 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
673 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
674 }
675 }
676 }
677
678 static void free_subpicture(SubPicture *sp)
679 {
680 int i;
681
682 for (i = 0; i < sp->sub.num_rects; i++)
683 {
684 av_freep(&sp->sub.rects[i]->pict.data[0]);
685 av_freep(&sp->sub.rects[i]->pict.data[1]);
686 av_freep(&sp->sub.rects[i]);
687 }
688
689 av_free(sp->sub.rects);
690
691 memset(&sp->sub, 0, sizeof(AVSubtitle));
692 }
693
694 static void video_image_display(VideoState *is)
695 {
696 VideoPicture *vp;
697 SubPicture *sp;
698 AVPicture pict;
699 float aspect_ratio;
700 int width, height, x, y;
701 SDL_Rect rect;
702 int i;
703
704 vp = &is->pictq[is->pictq_rindex];
705 if (vp->bmp) {
706 #if CONFIG_AVFILTER
707 if (vp->picref->pixel_aspect.num == 0)
708 aspect_ratio = 0;
709 else
710 aspect_ratio = av_q2d(vp->picref->pixel_aspect);
711 #else
712
713 /* XXX: use variable in the frame */
714 if (is->video_st->sample_aspect_ratio.num)
715 aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
716 else if (is->video_st->codec->sample_aspect_ratio.num)
717 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
718 else
719 aspect_ratio = 0;
720 #endif
721 if (aspect_ratio <= 0.0)
722 aspect_ratio = 1.0;
723 aspect_ratio *= (float)vp->width / (float)vp->height;
724 /* if an active format is indicated, then it overrides the
725 mpeg format */
726 #if 0
727 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
728 is->dtg_active_format = is->video_st->codec->dtg_active_format;
729 printf("dtg_active_format=%d\n", is->dtg_active_format);
730 }
731 #endif
732 #if 0
733 switch(is->video_st->codec->dtg_active_format) {
734 case FF_DTG_AFD_SAME:
735 default:
736 /* nothing to do */
737 break;
738 case FF_DTG_AFD_4_3:
739 aspect_ratio = 4.0 / 3.0;
740 break;
741 case FF_DTG_AFD_16_9:
742 aspect_ratio = 16.0 / 9.0;
743 break;
744 case FF_DTG_AFD_14_9:
745 aspect_ratio = 14.0 / 9.0;
746 break;
747 case FF_DTG_AFD_4_3_SP_14_9:
748 aspect_ratio = 14.0 / 9.0;
749 break;
750 case FF_DTG_AFD_16_9_SP_14_9:
751 aspect_ratio = 14.0 / 9.0;
752 break;
753 case FF_DTG_AFD_SP_4_3:
754 aspect_ratio = 4.0 / 3.0;
755 break;
756 }
757 #endif
758
759 if (is->subtitle_st)
760 {
761 if (is->subpq_size > 0)
762 {
763 sp = &is->subpq[is->subpq_rindex];
764
765 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
766 {
767 SDL_LockYUVOverlay (vp->bmp);
768
769 pict.data[0] = vp->bmp->pixels[0];
770 pict.data[1] = vp->bmp->pixels[2];
771 pict.data[2] = vp->bmp->pixels[1];
772
773 pict.linesize[0] = vp->bmp->pitches[0];
774 pict.linesize[1] = vp->bmp->pitches[2];
775 pict.linesize[2] = vp->bmp->pitches[1];
776
777 for (i = 0; i < sp->sub.num_rects; i++)
778 blend_subrect(&pict, sp->sub.rects[i],
779 vp->bmp->w, vp->bmp->h);
780
781 SDL_UnlockYUVOverlay (vp->bmp);
782 }
783 }
784 }
785
786
787 /* XXX: we suppose the screen has a 1.0 pixel ratio */
788 height = is->height;
789 width = ((int)rint(height * aspect_ratio)) & ~1;
790 if (width > is->width) {
791 width = is->width;
792 height = ((int)rint(width / aspect_ratio)) & ~1;
793 }
794 x = (is->width - width) / 2;
795 y = (is->height - height) / 2;
796 if (!is->no_background) {
797 /* fill the background */
798 // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
799 } else {
800 is->no_background = 0;
801 }
802 rect.x = is->xleft + x;
803 rect.y = is->ytop + y;
804 rect.w = width;
805 rect.h = height;
806 SDL_DisplayYUVOverlay(vp->bmp, &rect);
807 } else {
808 #if 0
809 fill_rectangle(screen,
810 is->xleft, is->ytop, is->width, is->height,
811 QERGB(0x00, 0x00, 0x00));
812 #endif
813 }
814 }
815
816 static inline int compute_mod(int a, int b)
817 {
818 a = a % b;
819 if (a >= 0)
820 return a;
821 else
822 return a + b;
823 }
824
825 static void video_audio_display(VideoState *s)
826 {
827 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
828 int ch, channels, h, h2, bgcolor, fgcolor;
829 int16_t time_diff;
830 int rdft_bits, nb_freq;
831
832 for(rdft_bits=1; (1<<rdft_bits)<2*s->height; rdft_bits++)
833 ;
834 nb_freq= 1<<(rdft_bits-1);
835
836 /* compute display index : center on currently output samples */
837 channels = s->audio_st->codec->channels;
838 nb_display_channels = channels;
839 if (!s->paused) {
840 int data_used= s->show_audio==1 ? s->width : (2*nb_freq);
841 n = 2 * channels;
842 delay = audio_write_get_buf_size(s);
843 delay /= n;
844
845 /* to be more precise, we take into account the time spent since
846 the last buffer computation */
847 if (audio_callback_time) {
848 time_diff = av_gettime() - audio_callback_time;
849 delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
850 }
851
852 delay += 2*data_used;
853 if (delay < data_used)
854 delay = data_used;
855
856 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
857 if(s->show_audio==1){
858 h= INT_MIN;
859 for(i=0; i<1000; i+=channels){
860 int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
861 int a= s->sample_array[idx];
862 int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
863 int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
864 int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
865 int score= a-d;
866 if(h<score && (b^c)<0){
867 h= score;
868 i_start= idx;
869 }
870 }
871 }
872
873 s->last_i_start = i_start;
874 } else {
875 i_start = s->last_i_start;
876 }
877
878 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
879 if(s->show_audio==1){
880 fill_rectangle(screen,
881 s->xleft, s->ytop, s->width, s->height,
882 bgcolor);
883
884 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
885
886 /* total height for one channel */
887 h = s->height / nb_display_channels;
888 /* graph height / 2 */
889 h2 = (h * 9) / 20;
890 for(ch = 0;ch < nb_display_channels; ch++) {
891 i = i_start + ch;
892 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
893 for(x = 0; x < s->width; x++) {
894 y = (s->sample_array[i] * h2) >> 15;
895 if (y < 0) {
896 y = -y;
897 ys = y1 - y;
898 } else {
899 ys = y1;
900 }
901 fill_rectangle(screen,
902 s->xleft + x, ys, 1, y,
903 fgcolor);
904 i += channels;
905 if (i >= SAMPLE_ARRAY_SIZE)
906 i -= SAMPLE_ARRAY_SIZE;
907 }
908 }
909
910 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
911
912 for(ch = 1;ch < nb_display_channels; ch++) {
913 y = s->ytop + ch * h;
914 fill_rectangle(screen,
915 s->xleft, y, s->width, 1,
916 fgcolor);
917 }
918 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
919 }else{
920 nb_display_channels= FFMIN(nb_display_channels, 2);
921 if(rdft_bits != s->rdft_bits){
922 av_rdft_end(s->rdft);
923 av_free(s->rdft_data);
924 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
925 s->rdft_bits= rdft_bits;
926 s->rdft_data= av_malloc(4*nb_freq*sizeof(*s->rdft_data));
927 }
928 {
929 FFTSample *data[2];
930 for(ch = 0;ch < nb_display_channels; ch++) {
931 data[ch] = s->rdft_data + 2*nb_freq*ch;
932 i = i_start + ch;
933 for(x = 0; x < 2*nb_freq; x++) {
934 double w= (x-nb_freq)*(1.0/nb_freq);
935 data[ch][x]= s->sample_array[i]*(1.0-w*w);
936 i += channels;
937 if (i >= SAMPLE_ARRAY_SIZE)
938 i -= SAMPLE_ARRAY_SIZE;
939 }
940 av_rdft_calc(s->rdft, data[ch]);
941 }
942 //least efficient way to do this, we should of course directly access it but its more than fast enough
943 for(y=0; y<s->height; y++){
944 double w= 1/sqrt(nb_freq);
945 int a= sqrt(w*sqrt(data[0][2*y+0]*data[0][2*y+0] + data[0][2*y+1]*data[0][2*y+1]));
946 int b= (nb_display_channels == 2 ) ? sqrt(w*sqrt(data[1][2*y+0]*data[1][2*y+0]
947 + data[1][2*y+1]*data[1][2*y+1])) : a;
948 a= FFMIN(a,255);
949 b= FFMIN(b,255);
950 fgcolor = SDL_MapRGB(screen->format, a, b, (a+b)/2);
951
952 fill_rectangle(screen,
953 s->xpos, s->height-y, 1, 1,
954 fgcolor);
955 }
956 }
957 SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
958 s->xpos++;
959 if(s->xpos >= s->width)
960 s->xpos= s->xleft;
961 }
962 }
963
964 static int video_open(VideoState *is){
965 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
966 int w,h;
967
968 if(is_full_screen) flags |= SDL_FULLSCREEN;
969 else flags |= SDL_RESIZABLE;
970
971 if (is_full_screen && fs_screen_width) {
972 w = fs_screen_width;
973 h = fs_screen_height;
974 } else if(!is_full_screen && screen_width){
975 w = screen_width;
976 h = screen_height;
977 #if CONFIG_AVFILTER
978 }else if (is->out_video_filter && is->out_video_filter->inputs[0]){
979 w = is->out_video_filter->inputs[0]->w;
980 h = is->out_video_filter->inputs[0]->h;
981 #else
982 }else if (is->video_st && is->video_st->codec->width){
983 w = is->video_st->codec->width;
984 h = is->video_st->codec->height;
985 #endif
986 } else {
987 w = 640;
988 h = 480;
989 }
990 if(screen && is->width == screen->w && screen->w == w
991 && is->height== screen->h && screen->h == h)
992 return 0;
993
994 #ifndef __APPLE__
995 screen = SDL_SetVideoMode(w, h, 0, flags);
996 #else
997 /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
998 screen = SDL_SetVideoMode(w, h, 24, flags);
999 #endif
1000 if (!screen) {
1001 fprintf(stderr, "SDL: could not set video mode - exiting\n");
1002 return -1;
1003 }
1004 if (!window_title)
1005 window_title = input_filename;
1006 SDL_WM_SetCaption(window_title, window_title);
1007
1008 is->width = screen->w;
1009 is->height = screen->h;
1010
1011 return 0;
1012 }
1013
1014 /* display the current picture, if any */
1015 static void video_display(VideoState *is)
1016 {
1017 if(!screen)
1018 video_open(cur_stream);
1019 if (is->audio_st && is->show_audio)
1020 video_audio_display(is);
1021 else if (is->video_st)
1022 video_image_display(is);
1023 }
1024
1025 static int refresh_thread(void *opaque)
1026 {
1027 VideoState *is= opaque;
1028 while(!is->abort_request){
1029 SDL_Event event;
1030 event.type = FF_REFRESH_EVENT;
1031 event.user.data1 = opaque;
1032 if(!is->refresh){
1033 is->refresh=1;
1034 SDL_PushEvent(&event);
1035 }
1036 usleep(is->audio_st && is->show_audio ? rdftspeed*1000 : 5000); //FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
1037 }
1038 return 0;
1039 }
1040
1041 /* get the current audio clock value */
1042 static double get_audio_clock(VideoState *is)
1043 {
1044 double pts;
1045 int hw_buf_size, bytes_per_sec;
1046 pts = is->audio_clock;
1047 hw_buf_size = audio_write_get_buf_size(is);
1048 bytes_per_sec = 0;
1049 if (is->audio_st) {
1050 bytes_per_sec = is->audio_st->codec->sample_rate *
1051 2 * is->audio_st->codec->channels;
1052 }
1053 if (bytes_per_sec)
1054 pts -= (double)hw_buf_size / bytes_per_sec;
1055 return pts;
1056 }
1057
1058 /* get the current video clock value */
1059 static double get_video_clock(VideoState *is)
1060 {
1061 if (is->paused) {
1062 return is->video_current_pts;
1063 } else {
1064 return is->video_current_pts_drift + av_gettime() / 1000000.0;
1065 }
1066 }
1067
1068 /* get the current external clock value */
1069 static double get_external_clock(VideoState *is)
1070 {
1071 int64_t ti;
1072 ti = av_gettime();
1073 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
1074 }
1075
1076 /* get the current master clock value */
1077 static double get_master_clock(VideoState *is)
1078 {
1079 double val;
1080
1081 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1082 if (is->video_st)
1083 val = get_video_clock(is);
1084 else
1085 val = get_audio_clock(is);
1086 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1087 if (is->audio_st)
1088 val = get_audio_clock(is);
1089 else
1090 val = get_video_clock(is);
1091 } else {
1092 val = get_external_clock(is);
1093 }
1094 return val;
1095 }
1096
1097 /* seek in the stream */
1098 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
1099 {
1100 if (!is->seek_req) {
1101 is->seek_pos = pos;
1102 is->seek_rel = rel;
1103 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1104 if (seek_by_bytes)
1105 is->seek_flags |= AVSEEK_FLAG_BYTE;
1106 is->seek_req = 1;
1107 }
1108 }
1109
1110 /* pause or resume the video */
1111 static void stream_pause(VideoState *is)
1112 {
1113 if (is->paused) {
1114 is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
1115 if(is->read_pause_return != AVERROR(ENOSYS)){
1116 is->video_current_pts = is->video_current_pts_drift + av_gettime() / 1000000.0;
1117 }
1118 is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
1119 }
1120 is->paused = !is->paused;
1121 }
1122
1123 static double compute_target_time(double frame_current_pts, VideoState *is)
1124 {
1125 double delay, sync_threshold, diff;
1126
1127 /* compute nominal delay */
1128 delay = frame_current_pts - is->frame_last_pts;
1129 if (delay <= 0 || delay >= 10.0) {
1130 /* if incorrect delay, use previous one */
1131 delay = is->frame_last_delay;
1132 } else {
1133 is->frame_last_delay = delay;
1134 }
1135 is->frame_last_pts = frame_current_pts;
1136
1137 /* update delay to follow master synchronisation source */
1138 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1139 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1140 /* if video is slave, we try to correct big delays by
1141 duplicating or deleting a frame */
1142 diff = get_video_clock(is) - get_master_clock(is);
1143
1144 /* skip or repeat frame. We take into account the
1145 delay to compute the threshold. I still don't know
1146 if it is the best guess */
1147 sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1148 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1149 if (diff <= -sync_threshold)
1150 delay = 0;
1151 else if (diff >= sync_threshold)
1152 delay = 2 * delay;
1153 }
1154 }
1155 is->frame_timer += delay;
1156 #if defined(DEBUG_SYNC)
1157 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1158 delay, actual_delay, frame_current_pts, -diff);
1159 #endif
1160
1161 return is->frame_timer;
1162 }
1163
1164 /* called to display each frame */
1165 static void video_refresh_timer(void *opaque)
1166 {
1167 VideoState *is = opaque;
1168 VideoPicture *vp;
1169
1170 SubPicture *sp, *sp2;
1171
1172 if (is->video_st) {
1173 retry:
1174 if (is->pictq_size == 0) {
1175 //nothing to do, no picture to display in the que
1176 } else {
1177 double time= av_gettime()/1000000.0;
1178 double next_target;
1179 /* dequeue the picture */
1180 vp = &is->pictq[is->pictq_rindex];
1181
1182 if(time < vp->target_clock)
1183 return;
1184 /* update current video pts */
1185 is->video_current_pts = vp->pts;
1186 is->video_current_pts_drift = is->video_current_pts - time;
1187 is->video_current_pos = vp->pos;
1188 if(is->pictq_size > 1){
1189 VideoPicture *nextvp= &is->pictq[(is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE];
1190 assert(nextvp->target_clock >= vp->target_clock);
1191 next_target= nextvp->target_clock;
1192 }else{
1193 next_target= vp->target_clock + is->video_clock - vp->pts; //FIXME pass durations cleanly
1194 }
1195 if(framedrop && time > next_target){
1196 is->skip_frames *= 1.0 + FRAME_SKIP_FACTOR;
1197 if(is->pictq_size > 1 || time > next_target + 0.5){
1198 /* update queue size and signal for next picture */
1199 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1200 is->pictq_rindex = 0;
1201
1202 SDL_LockMutex(is->pictq_mutex);
1203 is->pictq_size--;
1204 SDL_CondSignal(is->pictq_cond);
1205 SDL_UnlockMutex(is->pictq_mutex);
1206 goto retry;
1207 }
1208 }
1209
1210 if(is->subtitle_st) {
1211 if (is->subtitle_stream_changed) {
1212 SDL_LockMutex(is->subpq_mutex);
1213
1214 while (is->subpq_size) {
1215 free_subpicture(&is->subpq[is->subpq_rindex]);
1216
1217 /* update queue size and signal for next picture */
1218 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1219 is->subpq_rindex = 0;
1220
1221 is->subpq_size--;
1222 }
1223 is->subtitle_stream_changed = 0;
1224
1225 SDL_CondSignal(is->subpq_cond);
1226 SDL_UnlockMutex(is->subpq_mutex);
1227 } else {
1228 if (is->subpq_size > 0) {
1229 sp = &is->subpq[is->subpq_rindex];
1230
1231 if (is->subpq_size > 1)
1232 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1233 else
1234 sp2 = NULL;
1235
1236 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1237 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1238 {
1239 free_subpicture(sp);
1240
1241 /* update queue size and signal for next picture */
1242 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1243 is->subpq_rindex = 0;
1244
1245 SDL_LockMutex(is->subpq_mutex);
1246 is->subpq_size--;
1247 SDL_CondSignal(is->subpq_cond);
1248 SDL_UnlockMutex(is->subpq_mutex);
1249 }
1250 }
1251 }
1252 }
1253
1254 /* display picture */
1255 video_display(is);
1256
1257 /* update queue size and signal for next picture */
1258 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1259 is->pictq_rindex = 0;
1260
1261 SDL_LockMutex(is->pictq_mutex);
1262 is->pictq_size--;
1263 SDL_CondSignal(is->pictq_cond);
1264 SDL_UnlockMutex(is->pictq_mutex);
1265 }
1266 } else if (is->audio_st) {
1267 /* draw the next audio frame */
1268
1269 /* if only audio stream, then display the audio bars (better
1270 than nothing, just to test the implementation */
1271
1272 /* display picture */
1273 video_display(is);
1274 }
1275 if (show_status) {
1276 static int64_t last_time;
1277 int64_t cur_time;
1278 int aqsize, vqsize, sqsize;
1279 double av_diff;
1280
1281 cur_time = av_gettime();
1282 if (!last_time || (cur_time - last_time) >= 30000) {
1283 aqsize = 0;
1284 vqsize = 0;
1285 sqsize = 0;
1286 if (is->audio_st)
1287 aqsize = is->audioq.size;
1288 if (is->video_st)
1289 vqsize = is->videoq.size;
1290 if (is->subtitle_st)
1291 sqsize = is->subtitleq.size;
1292 av_diff = 0;
1293 if (is->audio_st && is->video_st)
1294 av_diff = get_audio_clock(is) - get_video_clock(is);
1295 printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
1296 get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->faulty_dts, is->faulty_pts);
1297 fflush(stdout);
1298 last_time = cur_time;
1299 }
1300 }
1301 }
1302
1303 /* allocate a picture (needs to do that in main thread to avoid
1304 potential locking problems */
1305 static void alloc_picture(void *opaque)
1306 {
1307 VideoState *is = opaque;
1308 VideoPicture *vp;
1309
1310 vp = &is->pictq[is->pictq_windex];
1311
1312 if (vp->bmp)
1313 SDL_FreeYUVOverlay(vp->bmp);
1314
1315 #if CONFIG_AVFILTER
1316 if (vp->picref)
1317 avfilter_unref_pic(vp->picref);
1318 vp->picref = NULL;
1319
1320 vp->width = is->out_video_filter->inputs[0]->w;
1321 vp->height = is->out_video_filter->inputs[0]->h;
1322 vp->pix_fmt = is->out_video_filter->inputs[0]->format;
1323 #else
1324 vp->width = is->video_st->codec->width;
1325 vp->height = is->video_st->codec->height;
1326 vp->pix_fmt = is->video_st->codec->pix_fmt;
1327 #endif
1328
1329 vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
1330 SDL_YV12_OVERLAY,
1331 screen);
1332
1333 SDL_LockMutex(is->pictq_mutex);
1334 vp->allocated = 1;
1335 SDL_CondSignal(is->pictq_cond);
1336 SDL_UnlockMutex(is->pictq_mutex);
1337 }
1338
1339 /**
1340 *
1341 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1342 */
1343 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
1344 {
1345 VideoPicture *vp;
1346 int dst_pix_fmt;
1347 #if CONFIG_AVFILTER
1348 AVPicture pict_src;
1349 #endif
1350 /* wait until we have space to put a new picture */
1351 SDL_LockMutex(is->pictq_mutex);
1352
1353 if(is->pictq_size>=VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)
1354 is->skip_frames= FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0-FRAME_SKIP_FACTOR));
1355
1356 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1357 !is->videoq.abort_request) {
1358 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1359 }
1360 SDL_UnlockMutex(is->pictq_mutex);
1361
1362 if (is->videoq.abort_request)
1363 return -1;
1364
1365 vp = &is->pictq[is->pictq_windex];
1366
1367 /* alloc or resize hardware picture buffer */
1368 if (!vp->bmp ||
1369 #if CONFIG_AVFILTER
1370 vp->width != is->out_video_filter->inputs[0]->w ||
1371 vp->height != is->out_video_filter->inputs[0]->h) {
1372 #else
1373 vp->width != is->video_st->codec->width ||
1374 vp->height != is->video_st->codec->height) {
1375 #endif
1376 SDL_Event event;
1377
1378 vp->allocated = 0;
1379
1380 /* the allocation must be done in the main thread to avoid
1381 locking problems */
1382 event.type = FF_ALLOC_EVENT;
1383 event.user.data1 = is;
1384 SDL_PushEvent(&event);
1385
1386 /* wait until the picture is allocated */
1387 SDL_LockMutex(is->pictq_mutex);
1388 while (!vp->allocated && !is->videoq.abort_request) {
1389 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1390 }
1391 SDL_UnlockMutex(is->pictq_mutex);
1392
1393 if (is->videoq.abort_request)
1394 return -1;
1395 }
1396
1397 /* if the frame is not skipped, then display it */
1398 if (vp->bmp) {
1399 AVPicture pict;
1400 #if CONFIG_AVFILTER
1401 if(vp->picref)
1402 avfilter_unref_pic(vp->picref);
1403 vp->picref = src_frame->opaque;
1404 #endif
1405
1406 /* get a pointer on the bitmap */
1407 SDL_LockYUVOverlay (vp->bmp);
1408
1409 dst_pix_fmt = PIX_FMT_YUV420P;
1410 memset(&pict,0,sizeof(AVPicture));
1411 pict.data[0] = vp->bmp->pixels[0];
1412 pict.data[1] = vp->bmp->pixels[2];
1413 pict.data[2] = vp->bmp->pixels[1];
1414
1415 pict.linesize[0] = vp->bmp->pitches[0];
1416 pict.linesize[1] = vp->bmp->pitches[2];
1417 pict.linesize[2] = vp->bmp->pitches[1];
1418
1419 #if CONFIG_AVFILTER
1420 pict_src.data[0] = src_frame->data[0];
1421 pict_src.data[1] = src_frame->data[1];
1422 pict_src.data[2] = src_frame->data[2];
1423
1424 pict_src.linesize[0] = src_frame->linesize[0];
1425 pict_src.linesize[1] = src_frame->linesize[1];
1426 pict_src.linesize[2] = src_frame->linesize[2];
1427
1428 //FIXME use direct rendering
1429 av_picture_copy(&pict, &pict_src,
1430 vp->pix_fmt, vp->width, vp->height);
1431 #else
1432 sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
1433 is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
1434 vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,
1435 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1436 if (is->img_convert_ctx == NULL) {
1437 fprintf(stderr, "Cannot initialize the conversion context\n");
1438 exit(1);
1439 }
1440 sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
1441 0, vp->height, pict.data, pict.linesize);
1442 #endif
1443 /* update the bitmap content */
1444 SDL_UnlockYUVOverlay(vp->bmp);
1445
1446 vp->pts = pts;
1447 vp->pos = pos;
1448
1449 /* now we can update the picture count */
1450 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1451 is->pictq_windex = 0;
1452 SDL_LockMutex(is->pictq_mutex);
1453 vp->target_clock= compute_target_time(vp->pts, is);
1454
1455 is->pictq_size++;
1456 SDL_UnlockMutex(is->pictq_mutex);
1457 }
1458 return 0;
1459 }
1460
1461 /**
1462 * compute the exact PTS for the picture if it is omitted in the stream
1463 * @param pts1 the dts of the pkt / pts of the frame
1464 */
1465 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
1466 {
1467 double frame_delay, pts;
1468
1469 pts = pts1;
1470
1471 if (pts != 0) {
1472 /* update video clock with pts, if present */
1473 is->video_clock = pts;
1474 } else {
1475 pts = is->video_clock;
1476 }
1477 /* update video clock for next frame */
1478 frame_delay = av_q2d(is->video_st->codec->time_base);
1479 /* for MPEG2, the frame can be repeated, so we update the
1480 clock accordingly */
1481 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1482 is->video_clock += frame_delay;
1483
1484 #if defined(DEBUG_SYNC) && 0
1485 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
1486 av_get_pict_type_char(src_frame->pict_type), pts, pts1);
1487 #endif
1488 return queue_picture(is, src_frame, pts, pos);
1489 }
1490
1491 static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
1492 {
1493 int len1, got_picture, i;
1494
1495 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1496 return -1;
1497
1498 if(pkt->data == flush_pkt.data){
1499 avcodec_flush_buffers(is->video_st->codec);
1500
1501 SDL_LockMutex(is->pictq_mutex);
1502 //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
1503 for(i=0; i<VIDEO_PICTURE_QUEUE_SIZE; i++){
1504 is->pictq[i].target_clock= 0;
1505 }
1506 while (is->pictq_size && !is->videoq.abort_request) {
1507 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1508 }
1509 is->video_current_pos= -1;
1510 SDL_UnlockMutex(is->pictq_mutex);
1511
1512 is->last_dts_for_fault_detection=
1513 is->last_pts_for_fault_detection= INT64_MIN;
1514 is->frame_last_pts= AV_NOPTS_VALUE;
1515 is->frame_last_delay = 0;
1516 is->frame_timer = (double)av_gettime() / 1000000.0;
1517 is->skip_frames= 1;
1518 is->skip_frames_index= 0;
1519 return 0;
1520 }
1521
1522 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1523 this packet, if any */
1524 is->video_st->codec->reordered_opaque= pkt->pts;
1525 len1 = avcodec_decode_video2(is->video_st->codec,
1526 frame, &got_picture,
1527 pkt);
1528
1529 if (got_picture) {
1530 if(pkt->dts != AV_NOPTS_VALUE){
1531 is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection;
1532 is->last_dts_for_fault_detection= pkt->dts;
1533 }
1534 if(frame->reordered_opaque != AV_NOPTS_VALUE){
1535 is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection;
1536 is->last_pts_for_fault_detection= frame->reordered_opaque;
1537 }
1538 }
1539
1540 if( ( decoder_reorder_pts==1
1541 || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
1542 || pkt->dts == AV_NOPTS_VALUE)
1543 && frame->reordered_opaque != AV_NOPTS_VALUE)
1544 *pts= frame->reordered_opaque;
1545 else if(pkt->dts != AV_NOPTS_VALUE)
1546 *pts= pkt->dts;
1547 else
1548 *pts= 0;
1549
1550 // if (len1 < 0)
1551 // break;
1552 if (got_picture){
1553 is->skip_frames_index += 1;
1554 if(is->skip_frames_index >= is->skip_frames){
1555 is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
1556 return 1;
1557 }
1558
1559 }
1560 return 0;
1561 }
1562
1563 #if CONFIG_AVFILTER
1564 typedef struct {
1565 VideoState *is;
1566 AVFrame *frame;
1567 int use_dr1;
1568 } FilterPriv;
1569
1570 static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
1571 {
1572 AVFilterContext *ctx = codec->opaque;
1573 AVFilterPicRef *ref;
1574 int perms = AV_PERM_WRITE;
1575 int i, w, h, stride[4];
1576 unsigned edge;
1577
1578 if(pic->buffer_hints & FF_BUFFER_HINTS_VALID) {
1579 if(pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ;
1580 if(pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE;
1581 if(pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) perms |= AV_PERM_REUSE2;
1582 }
1583 if(pic->reference) perms |= AV_PERM_READ | AV_PERM_PRESERVE;
1584
1585 w = codec->width;
1586 h = codec->height;
1587 avcodec_align_dimensions2(codec, &w, &h, stride);
1588 edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width();
1589 w += edge << 1;
1590 h += edge << 1;
1591
1592 if(!(ref = avfilter_get_video_buffer(ctx->outputs[0], perms, w, h)))
1593 return -1;
1594
1595 ref->w = codec->width;
1596 ref->h = codec->height;
1597 for(i = 0; i < 4; i ++) {
1598 unsigned hshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->pic->format].log2_chroma_w : 0;
1599 unsigned vshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->pic->format].log2_chroma_h : 0;
1600
1601 if (ref->data[i]) {
1602 ref->data[i] += (edge >> hshift) + ((edge * ref->linesize[i]) >> vshift);
1603 }
1604 pic->data[i] = ref->data[i];
1605 pic->linesize[i] = ref->linesize[i];
1606 }
1607 pic->opaque = ref;
1608 pic->age = INT_MAX;
1609 pic->type = FF_BUFFER_TYPE_USER;
1610 pic->reordered_opaque = codec->reordered_opaque;
1611 return 0;
1612 }
1613
1614 static void input_release_buffer(AVCodecContext *codec, AVFrame *pic)
1615 {
1616 memset(pic->data, 0, sizeof(pic->data));
1617 avfilter_unref_pic(pic->opaque);
1618 }
1619
1620 static int input_reget_buffer(AVCodecContext *codec, AVFrame *pic)
1621 {
1622 AVFilterPicRef *ref = pic->opaque;
1623
1624 if (pic->data[0] == NULL) {
1625 pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
1626 return codec->get_buffer(codec, pic);
1627 }
1628
1629 if ((codec->width != ref->w) || (codec->height != ref->h) ||
1630 (codec->pix_fmt != ref->pic->format)) {
1631 av_log(codec, AV_LOG_ERROR, "Picture properties changed.\n");
1632 return -1;
1633 }
1634
1635 pic->reordered_opaque = codec->reordered_opaque;
1636 return 0;
1637 }
1638
1639 static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
1640 {
1641 FilterPriv *priv = ctx->priv;
1642 AVCodecContext *codec;
1643 if(!opaque) return -1;
1644
1645 priv->is = opaque;
1646 codec = priv->is->video_st->codec;
1647 codec->opaque = ctx;
1648 if(codec->codec->capabilities & CODEC_CAP_DR1) {
1649 priv->use_dr1 = 1;
1650 codec->get_buffer = input_get_buffer;
1651 codec->release_buffer = input_release_buffer;
1652 codec->reget_buffer = input_reget_buffer;
1653 }
1654
1655 priv->frame = avcodec_alloc_frame();
1656
1657 return 0;
1658 }
1659
1660 static void input_uninit(AVFilterContext *ctx)
1661 {
1662 FilterPriv *priv = ctx->priv;
1663 av_free(priv->frame);
1664 }
1665
1666 static int input_request_frame(AVFilterLink *link)
1667 {
1668 FilterPriv *priv = link->src->priv;
1669 AVFilterPicRef *picref;
1670 int64_t pts = 0;
1671 AVPacket pkt;
1672 int ret;
1673
1674 while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))
1675 av_free_packet(&pkt);
1676 if (ret < 0)
1677 return -1;
1678
1679 if(priv->use_dr1) {
1680 picref = avfilter_ref_pic(priv->frame->opaque, ~0);
1681 } else {
1682 picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
1683 av_picture_copy((AVPicture *)&picref->data, (AVPicture *)priv->frame,
1684 picref->pic->format, link->w, link->h);
1685 }
1686 av_free_packet(&pkt);
1687
1688 picref->pts = pts;
1689 picref->pos = pkt.pos;
1690 picref->pixel_aspect = priv->is->video_st->codec->sample_aspect_ratio;
1691 avfilter_start_frame(link, picref);
1692 avfilter_draw_slice(link, 0, link->h, 1);
1693 avfilter_end_frame(link);
1694
1695 return 0;
1696 }
1697
1698 static int input_query_formats(AVFilterContext *ctx)
1699 {
1700 FilterPriv *priv = ctx->priv;
1701 enum PixelFormat pix_fmts[] = {
1702 priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE
1703 };
1704
1705 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1706 return 0;
1707 }
1708
1709 static int input_config_props(AVFilterLink *link)
1710 {
1711 FilterPriv *priv = link->src->priv;
1712 AVCodecContext *c = priv->is->video_st->codec;
1713
1714 link->w = c->width;
1715 link->h = c->height;
1716
1717 return 0;
1718 }
1719
1720 static AVFilter input_filter =
1721 {
1722 .name = "ffplay_input",
1723
1724 .priv_size = sizeof(FilterPriv),
1725
1726 .init = input_init,
1727 .uninit = input_uninit,
1728
1729 .query_formats = input_query_formats,
1730
1731 .inputs = (AVFilterPad[]) {{ .name = NULL }},
1732 .outputs = (AVFilterPad[]) {{ .name = "default",
1733 .type = AVMEDIA_TYPE_VIDEO,
1734 .request_frame = input_request_frame,
1735 .config_props = input_config_props, },
1736 { .name = NULL }},
1737 };
1738
1739 static void output_end_frame(AVFilterLink *link)
1740 {
1741 }
1742
1743 static int output_query_formats(AVFilterContext *ctx)
1744 {
1745 enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
1746
1747 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1748 return 0;
1749 }
1750
1751 static int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
1752 int64_t *pts, int64_t *pos)
1753 {
1754 AVFilterPicRef *pic;
1755
1756 if(avfilter_request_frame(ctx->inputs[0]))
1757 return -1;
1758 if(!(pic = ctx->inputs[0]->cur_pic))
1759 return -1;
1760 ctx->inputs[0]->cur_pic = NULL;
1761
1762 frame->opaque = pic;
1763 *pts = pic->pts;
1764 *pos = pic->pos;
1765
1766 memcpy(frame->data, pic->data, sizeof(frame->data));
1767 memcpy(frame->linesize, pic->linesize, sizeof(frame->linesize));
1768
1769 return 1;
1770 }
1771
1772 static AVFilter output_filter =
1773 {
1774 .name = "ffplay_output",
1775
1776 .query_formats = output_query_formats,
1777
1778 .inputs = (AVFilterPad[]) {{ .name = "default",
1779 .type = AVMEDIA_TYPE_VIDEO,
1780 .end_frame = output_end_frame,
1781 .min_perms = AV_PERM_READ, },
1782 { .name = NULL }},
1783 .outputs = (AVFilterPad[]) {{ .name = NULL }},
1784 };
1785 #endif /* CONFIG_AVFILTER */
1786
1787 static int video_thread(void *arg)
1788 {
1789 VideoState *is = arg;
1790 AVFrame *frame= avcodec_alloc_frame();
1791 int64_t pts_int;
1792 double pts;
1793 int ret;
1794
1795 #if CONFIG_AVFILTER
1796 int64_t pos;
1797 char sws_flags_str[128];
1798 AVFilterContext *filt_src = NULL, *filt_out = NULL;
1799 AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph));
1800 snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
1801 graph->scale_sws_opts = av_strdup(sws_flags_str);
1802
1803 if(!(filt_src = avfilter_open(&input_filter, "src"))) goto the_end;
1804 if(!(filt_out = avfilter_open(&output_filter, "out"))) goto the_end;
1805
1806 if(avfilter_init_filter(filt_src, NULL, is)) goto the_end;
1807 if(avfilter_init_filter(filt_out, NULL, frame)) goto the_end;
1808
1809
1810 if(vfilters) {
1811 AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
1812 AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
1813
1814 outputs->name = av_strdup("in");
1815 outputs->filter = filt_src;
1816 outputs->pad_idx = 0;
1817 outputs->next = NULL;
1818
1819 inputs->name = av_strdup("out");
1820 inputs->filter = filt_out;
1821 inputs->pad_idx = 0;
1822 inputs->next = NULL;
1823
1824 if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
1825 goto the_end;
1826 av_freep(&vfilters);
1827 } else {
1828 if(avfilter_link(filt_src, 0, filt_out, 0) < 0) goto the_end;
1829 }
1830 avfilter_graph_add_filter(graph, filt_src);
1831 avfilter_graph_add_filter(graph, filt_out);
1832
1833 if(avfilter_graph_check_validity(graph, NULL)) goto the_end;
1834 if(avfilter_graph_config_formats(graph, NULL)) goto the_end;
1835 if(avfilter_graph_config_links(graph, NULL)) goto the_end;
1836
1837 is->out_video_filter = filt_out;
1838 #endif
1839
1840 for(;;) {
1841 #if !CONFIG_AVFILTER
1842 AVPacket pkt;
1843 #endif
1844 while (is->paused && !is->videoq.abort_request)
1845 SDL_Delay(10);
1846 #if CONFIG_AVFILTER
1847 ret = get_filtered_video_frame(filt_out, frame, &pts_int, &pos);
1848 #else
1849 ret = get_video_frame(is, frame, &pts_int, &pkt);
1850 #endif
1851
1852 if (ret < 0) goto the_end;
1853
1854 if (!ret)
1855 continue;
1856
1857 pts = pts_int*av_q2d(is->video_st->time_base);
1858
1859 #if CONFIG_AVFILTER
1860 ret = output_picture2(is, frame, pts, pos);
1861 #else
1862 ret = output_picture2(is, frame, pts, pkt.pos);
1863 av_free_packet(&pkt);
1864 #endif
1865 if (ret < 0)
1866 goto the_end;
1867
1868 if (step)
1869 if (cur_stream)
1870 stream_pause(cur_stream);
1871 }
1872 the_end:
1873 #if CONFIG_AVFILTER
1874 avfilter_graph_destroy(graph);
1875 av_freep(&graph);
1876 #endif
1877 av_free(frame);
1878 return 0;
1879 }
1880
1881 static int subtitle_thread(void *arg)
1882 {
1883 VideoState *is = arg;
1884 SubPicture *sp;
1885 AVPacket pkt1, *pkt = &pkt1;
1886 int len1, got_subtitle;
1887 double pts;
1888 int i, j;
1889 int r, g, b, y, u, v, a;
1890
1891 for(;;) {
1892 while (is->paused && !is->subtitleq.abort_request) {
1893 SDL_Delay(10);
1894 }
1895 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1896 break;
1897
1898 if(pkt->data == flush_pkt.data){
1899 avcodec_flush_buffers(is->subtitle_st->codec);
1900 continue;
1901 }
1902 SDL_LockMutex(is->subpq_mutex);
1903 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1904 !is->subtitleq.abort_request) {
1905 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1906 }
1907 SDL_UnlockMutex(is->subpq_mutex);
1908
1909 if (is->subtitleq.abort_request)
1910 goto the_end;
1911
1912 sp = &is->subpq[is->subpq_windex];
1913
1914 /* NOTE: ipts is the PTS of the _first_ picture beginning in
1915 this packet, if any */
1916 pts = 0;
1917 if (pkt->pts != AV_NOPTS_VALUE)
1918 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1919
1920 len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
1921 &sp->sub, &got_subtitle,
1922 pkt);
1923 // if (len1 < 0)
1924 // break;
1925 if (got_subtitle && sp->sub.format == 0) {
1926 sp->pts = pts;
1927
1928 for (i = 0; i < sp->sub.num_rects; i++)
1929 {
1930 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
1931 {
1932 RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
1933 y = RGB_TO_Y_CCIR(r, g, b);
1934 u = RGB_TO_U_CCIR(r, g, b, 0);
1935 v = RGB_TO_V_CCIR(r, g, b, 0);
1936 YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
1937 }
1938 }
1939
1940 /* now we can update the picture count */
1941 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1942 is->subpq_windex = 0;
1943 SDL_LockMutex(is->subpq_mutex);
1944 is->subpq_size++;
1945 SDL_UnlockMutex(is->subpq_mutex);
1946 }
1947 av_free_packet(pkt);
1948 // if (step)
1949 // if (cur_stream)
1950 // stream_pause(cur_stream);
1951 }
1952 the_end:
1953 return 0;
1954 }
1955
1956 /* copy samples for viewing in editor window */
1957 static void update_sample_display(VideoState *is, short *samples, int samples_size)
1958 {
1959 int size, len, channels;
1960
1961 channels = is->audio_st->codec->channels;
1962
1963 size = samples_size / sizeof(short);
1964 while (size > 0) {
1965 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1966 if (len > size)
1967 len = size;
1968 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1969 samples += len;
1970 is->sample_array_index += len;
1971 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1972 is->sample_array_index = 0;
1973 size -= len;
1974 }
1975 }
1976
1977 /* return the new audio buffer size (samples can be added or deleted
1978 to get better sync if video or external master clock) */
1979 static int synchronize_audio(VideoState *is, short *samples,
1980 int samples_size1, double pts)
1981 {
1982 int n, samples_size;
1983 double ref_clock;
1984
1985 n = 2 * is->audio_st->codec->channels;
1986 samples_size = samples_size1;
1987
1988 /* if not master, then we try to remove or add samples to correct the clock */
1989 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1990 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1991 double diff, avg_diff;
1992 int wanted_size, min_size, max_size, nb_samples;
1993
1994 ref_clock = get_master_clock(is);
1995 diff = get_audio_clock(is) - ref_clock;
1996
1997 if (diff < AV_NOSYNC_THRESHOLD) {
1998 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1999 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
2000 /* not enough measures to have a correct estimate */
2001 is->audio_diff_avg_count++;
2002 } else {
2003 /* estimate the A-V difference */
2004 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
2005
2006 if (fabs(avg_diff) >= is->audio_diff_threshold) {
2007 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
2008 nb_samples = samples_size / n;
2009
2010 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
2011 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
2012 if (wanted_size < min_size)
2013 wanted_size = min_size;
2014 else if (wanted_size > max_size)
2015 wanted_size = max_size;
2016
2017 /* add or remove samples to correction the synchro */
2018 if (wanted_size < samples_size) {
2019 /* remove samples */
2020 samples_size = wanted_size;
2021 } else if (wanted_size > samples_size) {
2022 uint8_t *samples_end, *q;
2023 int nb;
2024
2025 /* add samples */
2026 nb = (samples_size - wanted_size);
2027 samples_end = (uint8_t *)samples + samples_size - n;
2028 q = samples_end + n;
2029 while (nb > 0) {
2030 memcpy(q, samples_end, n);
2031 q += n;
2032 nb -= n;
2033 }
2034 samples_size = wanted_size;
2035 }
2036 }
2037 #if 0
2038 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
2039 diff, avg_diff, samples_size - samples_size1,
2040 is->audio_clock, is->video_clock, is->audio_diff_threshold);
2041 #endif
2042 }
2043 } else {
2044 /* too big difference : may be initial PTS errors, so
2045 reset A-V filter */
2046 is->audio_diff_avg_count = 0;
2047 is->audio_diff_cum = 0;
2048 }
2049 }
2050
2051 return samples_size;
2052 }
2053
2054 /* decode one audio frame and returns its uncompressed size */
2055 static int audio_decode_frame(VideoState *is, double *pts_ptr)
2056 {
2057 AVPacket *pkt_temp = &is->audio_pkt_temp;
2058 AVPacket *pkt = &is->audio_pkt;
2059 AVCodecContext *dec= is->audio_st->codec;
2060 int n, len1, data_size;
2061 double pts;
2062
2063 for(;;) {
2064 /* NOTE: the audio packet can contain several frames */
2065 while (pkt_temp->size > 0) {
2066 data_size = sizeof(is->audio_buf1);
2067 len1 = avcodec_decode_audio3(dec,
2068 (int16_t *)is->audio_buf1, &data_size,
2069 pkt_temp);
2070 if (len1 < 0) {
2071 /* if error, we skip the frame */
2072 pkt_temp->size = 0;
2073 break;
2074 }
2075
2076 pkt_temp->data += len1;
2077 pkt_temp->size -= len1;
2078 if (data_size <= 0)
2079 continue;
2080
2081 if (dec->sample_fmt != is->audio_src_fmt) {
2082 if (is->reformat_ctx)
2083 av_audio_convert_free(is->reformat_ctx);
2084 is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
2085 dec->sample_fmt, 1, NULL, 0);
2086 if (!is->reformat_ctx) {
2087 fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
2088 avcodec_get_sample_fmt_name(dec->sample_fmt),
2089 avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
2090 break;
2091 }
2092 is->audio_src_fmt= dec->sample_fmt;
2093 }
2094
2095 if (is->reformat_ctx) {
2096 const void *ibuf[6]= {is->audio_buf1};
2097 void *obuf[6]= {is->audio_buf2};
2098 int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
2099 int ostride[6]= {2};
2100 int len= data_size/istride[0];
2101 if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
2102 printf("av_audio_convert() failed\n");
2103 break;
2104 }
2105 is->audio_buf= is->audio_buf2;
2106 /* FIXME: existing code assume that data_size equals framesize*channels*2
2107 remove this legacy cruft */
2108 data_size= len*2;
2109 }else{
2110 is->audio_buf= is->audio_buf1;
2111 }
2112
2113 /* if no pts, then compute it */
2114 pts = is->audio_clock;
2115 *pts_ptr = pts;
2116 n = 2 * dec->channels;
2117 is->audio_clock += (double)data_size /
2118 (double)(n * dec->sample_rate);
2119 #if defined(DEBUG_SYNC)
2120 {
2121 static double last_clock;
2122 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
2123 is->audio_clock - last_clock,
2124 is->audio_clock, pts);
2125 last_clock = is->audio_clock;
2126 }
2127 #endif
2128 return data_size;
2129 }
2130
2131 /* free the current packet */
2132 if (pkt->data)
2133 av_free_packet(pkt);
2134
2135 if (is->paused || is->audioq.abort_request) {
2136 return -1;
2137 }
2138
2139 /* read next packet */
2140 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
2141 return -1;
2142 if(pkt->data == flush_pkt.data){
2143 avcodec_flush_buffers(dec);
2144 continue;
2145 }
2146
2147 pkt_temp->data = pkt->data;
2148 pkt_temp->size = pkt->size;
2149
2150 /* if update the audio clock with the pts */
2151 if (pkt->pts != AV_NOPTS_VALUE) {
2152 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
2153 }
2154 }
2155 }
2156
2157 /* get the current audio output buffer size, in samples. With SDL, we
2158 cannot have a precise information */
2159 static int audio_write_get_buf_size(VideoState *is)
2160 {
2161 return is->audio_buf_size - is->audio_buf_index;
2162 }
2163
2164
2165 /* prepare a new audio buffer */
2166 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2167 {
2168 VideoState *is = opaque;
2169 int audio_size, len1;
2170 double pts;
2171
2172 audio_callback_time = av_gettime();
2173
2174 while (len > 0) {
2175 if (is->audio_buf_index >= is->audio_buf_size) {
2176 audio_size = audio_decode_frame(is, &pts);
2177 if (audio_size < 0) {
2178 /* if error, just output silence */
2179 is->audio_buf = is->audio_buf1;
2180 is->audio_buf_size = 1024;
2181 memset(is->audio_buf, 0, is->audio_buf_size);
2182 } else {
2183 if (is->show_audio)
2184 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2185 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
2186 pts);
2187 is->audio_buf_size = audio_size;
2188 }
2189 is->audio_buf_index = 0;
2190 }
2191 len1 = is->audio_buf_size - is->audio_buf_index;
2192 if (len1 > len)
2193 len1 = len;
2194 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2195 len -= len1;
2196 stream += len1;
2197 is->audio_buf_index += len1;
2198 }
2199 }
2200
2201 /* open a given stream. Return 0 if OK */
2202 static int stream_component_open(VideoState *is, int stream_index)
2203 {
2204 AVFormatContext *ic = is->ic;
2205 AVCodecContext *avctx;
2206 AVCodec *codec;
2207 SDL_AudioSpec wanted_spec, spec;
2208
2209 if (stream_index < 0 || stream_index >= ic->nb_streams)
2210 return -1;
2211 avctx = ic->streams[stream_index]->codec;
2212
2213 /* prepare audio output */
2214 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
2215 if (avctx->channels > 0) {
2216 avctx->request_channels = FFMIN(2, avctx->channels);
2217 } else {
2218 avctx->request_channels = 2;
2219 }
2220 }
2221
2222 codec = avcodec_find_decoder(avctx->codec_id);
2223 avctx->debug_mv = debug_mv;
2224 avctx->debug = debug;
2225 avctx->workaround_bugs = workaround_bugs;
2226 avctx->lowres = lowres;
2227 if(lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
2228 avctx->idct_algo= idct;
2229 if(fast) avctx->flags2 |= CODEC_FLAG2_FAST;
2230 avctx->skip_frame= skip_frame;
2231 avctx->skip_idct= skip_idct;
2232 avctx->skip_loop_filter= skip_loop_filter;
2233 avctx->error_recognition= error_recognition;
2234 avctx->error_concealment= error_concealment;
2235 avcodec_thread_init(avctx, thread_count);
2236
2237 set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0);
2238
2239 if (!codec ||
2240 avcodec_open(avctx, codec) < 0)
2241 return -1;
2242
2243 /* prepare audio output */
2244 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
2245 wanted_spec.freq = avctx->sample_rate;
2246 wanted_spec.format = AUDIO_S16SYS;
2247 wanted_spec.channels = avctx->channels;
2248 wanted_spec.silence = 0;
2249 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
2250 wanted_spec.callback = sdl_audio_callback;
2251 wanted_spec.userdata = is;
2252 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2253 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
2254 return -1;
2255 }
2256 is->audio_hw_buf_size = spec.size;
2257 is->audio_src_fmt= SAMPLE_FMT_S16;
2258 }
2259
2260 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2261 switch(avctx->codec_type) {
2262 case AVMEDIA_TYPE_AUDIO:
2263 is->audio_stream = stream_index;
2264 is->audio_st = ic->streams[stream_index];
2265 is->audio_buf_size = 0;
2266 is->audio_buf_index = 0;
2267
2268 /* init averaging filter */
2269 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2270 is->audio_diff_avg_count = 0;
2271 /* since we do not have a precise anough audio fifo fullness,
2272 we correct audio sync only if larger than this threshold */
2273 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
2274
2275 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
2276 packet_queue_init(&is->audioq);
2277 SDL_PauseAudio(0);
2278 break;
2279 case AVMEDIA_TYPE_VIDEO:
2280 is->video_stream = stream_index;
2281 is->video_st = ic->streams[stream_index];
2282
2283 // is->video_current_pts_time = av_gettime();
2284
2285 packet_queue_init(&is->videoq);
2286 is->video_tid = SDL_CreateThread(video_thread, is);
2287 break;
2288 case AVMEDIA_TYPE_SUBTITLE:
2289 is->subtitle_stream = stream_index;
2290 is->subtitle_st = ic->streams[stream_index];
2291 packet_queue_init(&is->subtitleq);
2292
2293 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
2294 break;
2295 default:
2296 break;
2297 }
2298 return 0;
2299 }
2300
2301 static void stream_component_close(VideoState *is, int stream_index)
2302 {
2303 AVFormatContext *ic = is->ic;
2304 AVCodecContext *avctx;
2305
2306 if (stream_index < 0 || stream_index >= ic->nb_streams)
2307 return;
2308 avctx = ic->streams[stream_index]->codec;
2309
2310 switch(avctx->codec_type) {
2311 case AVMEDIA_TYPE_AUDIO:
2312 packet_queue_abort(&is->audioq);
2313
2314 SDL_CloseAudio();
2315
2316 packet_queue_end(&is->audioq);
2317 if (is->reformat_ctx)
2318 av_audio_convert_free(is->reformat_ctx);
2319 is->reformat_ctx = NULL;
2320 break;
2321 case AVMEDIA_TYPE_VIDEO:
2322 packet_queue_abort(&is->videoq);
2323
2324 /* note: we also signal this mutex to make sure we deblock the
2325 video thread in all cases */
2326 SDL_LockMutex(is->pictq_mutex);
2327 SDL_CondSignal(is->pictq_cond);
2328 SDL_UnlockMutex(is->pictq_mutex);
2329
2330 SDL_WaitThread(is->video_tid, NULL);
2331
2332 packet_queue_end(&is->videoq);
2333 break;
2334 case AVMEDIA_TYPE_SUBTITLE:
2335 packet_queue_abort(&is->subtitleq);
2336
2337 /* note: we also signal this mutex to make sure we deblock the
2338 video thread in all cases */
2339 SDL_LockMutex(is->subpq_mutex);
2340 is->subtitle_stream_changed = 1;
2341
2342 SDL_CondSignal(is->subpq_cond);
2343 SDL_UnlockMutex(is->subpq_mutex);
2344
2345 SDL_WaitThread(is->subtitle_tid, NULL);
2346
2347 packet_queue_end(&is->subtitleq);
2348 break;
2349 default:
2350 break;
2351 }
2352
2353 ic->streams[stream_index]->discard = AVDISCARD_ALL;
2354 avcodec_close(avctx);
2355 switch(avctx->codec_type) {
2356 case AVMEDIA_TYPE_AUDIO:
2357 is->audio_st = NULL;
2358 is->audio_stream = -1;
2359 break;
2360 case AVMEDIA_TYPE_VIDEO:
2361 is->video_st = NULL;
2362 is->video_stream = -1;
2363 break;
2364 case AVMEDIA_TYPE_SUBTITLE:
2365 is->subtitle_st = NULL;
2366 is->subtitle_stream = -1;
2367 break;
2368 default:
2369 break;
2370 }
2371 }
2372
2373 /* since we have only one decoding thread, we can use a global
2374 variable instead of a thread local variable */
2375 static VideoState *global_video_state;
2376
2377 static int decode_interrupt_cb(void)
2378 {
2379 return (global_video_state && global_video_state->abort_request);
2380 }
2381
2382 /* this thread gets the stream from the disk or the network */
2383 static int decode_thread(void *arg)
2384 {
2385 VideoState *is = arg;
2386 AVFormatContext *ic;
2387 int err, i, ret;
2388 int st_index[AVMEDIA_TYPE_NB];
2389 int st_count[AVMEDIA_TYPE_NB]={0};
2390 int st_best_packet_count[AVMEDIA_TYPE_NB];
2391 AVPacket pkt1, *pkt = &pkt1;
2392 AVFormatParameters params, *ap = &params;
2393 int eof=0;
2394 int pkt_in_play_range = 0;
2395
2396 ic = avformat_alloc_context();
2397
2398 memset(st_index, -1, sizeof(st_index));
2399 memset(st_best_packet_count, -1, sizeof(st_best_packet_count));
2400 is->video_stream = -1;
2401 is->audio_stream = -1;
2402 is->subtitle_stream = -1;
2403
2404 global_video_state = is;
2405 url_set_interrupt_cb(decode_interrupt_cb);
2406
2407 memset(ap, 0, sizeof(*ap));
2408
2409 ap->prealloced_context = 1;
2410 ap->width = frame_width;
2411 ap->height= frame_height;
2412 ap->time_base= (AVRational){1, 25};
2413 ap->pix_fmt = frame_pix_fmt;
2414
2415 set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM);
2416
2417 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
2418 if (err < 0) {
2419 print_error(is->filename, err);
2420 ret = -1;
2421 goto fail;
2422 }
2423 is->ic = ic;
2424
2425 if(genpts)
2426 ic->flags |= AVFMT_FLAG_GENPTS;
2427
2428 err = av_find_stream_info(ic);
2429 if (err < 0) {
2430 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
2431 ret = -1;
2432 goto fail;
2433 }
2434 if(ic->pb)
2435 ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
2436
2437 if(seek_by_bytes<0)
2438 seek_by_bytes= !!(ic->iformat->flags & AVFMT_TS_DISCONT);
2439
2440 /* if seeking requested, we execute it */
2441 if (start_time != AV_NOPTS_VALUE) {
2442 int64_t timestamp;
2443
2444 timestamp = start_time;
2445 /* add the stream start time */
2446 if (ic->start_time != AV_NOPTS_VALUE)
2447 timestamp += ic->start_time;
2448 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2449 if (ret < 0) {
2450 fprintf(stderr, "%s: could not seek to position %0.3f\n",
2451 is->filename, (double)timestamp / AV_TIME_BASE);
2452 }
2453 }
2454
2455 for(i = 0; i < ic->nb_streams; i++) {
2456 AVStream *st= ic->streams[i];
2457 AVCodecContext *avctx = st->codec;
2458 ic->streams[i]->discard = AVDISCARD_ALL;
2459 if(avctx->codec_type >= (unsigned)AVMEDIA_TYPE_NB)
2460 continue;
2461 if(st_count[avctx->codec_type]++ != wanted_stream[avctx->codec_type] && wanted_stream[avctx->codec_type] >= 0)
2462 continue;
2463
2464 if(st_best_packet_count[avctx->codec_type] >= st->codec_info_nb_frames)
2465 continue;
2466 st_best_packet_count[avctx->codec_type]= st->codec_info_nb_frames;
2467
2468 switch(avctx->codec_type) {
2469 case AVMEDIA_TYPE_AUDIO:
2470 if (!audio_disable)
2471 st_index[AVMEDIA_TYPE_AUDIO] = i;
2472 break;
2473 case AVMEDIA_TYPE_VIDEO:
2474 case AVMEDIA_TYPE_SUBTITLE:
2475 if (!video_disable)
2476 st_index[avctx->codec_type] = i;
2477 break;
2478 default:
2479 break;
2480 }
2481 }
2482 if (show_status) {
2483 dump_format(ic, 0, is->filename, 0);
2484 }
2485
2486 /* open the streams */
2487 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2488 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
2489 }
2490
2491 ret=-1;
2492 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2493 ret= stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
2494 }
2495 is->refresh_tid = SDL_CreateThread(refresh_thread, is);
2496 if(ret<0) {
2497 if (!display_disable)
2498 is->show_audio = 2;
2499 }
2500
2501 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2502 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
2503 }
2504
2505 if (is->video_stream < 0 && is->audio_stream < 0) {
2506 fprintf(stderr, "%s: could not open codecs\n", is->filename);
2507 ret = -1;
2508 goto fail;
2509 }
2510
2511 for(;;) {
2512 if (is->abort_request)
2513 break;
2514 if (is->paused != is->last_paused) {
2515 is->last_paused = is->paused;
2516 if (is->paused)
2517 is->read_pause_return= av_read_pause(ic);
2518 else
2519 av_read_play(ic);
2520 }
2521 #if CONFIG_RTSP_DEMUXER
2522 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
2523 /* wait 10 ms to avoid trying to get another packet */
2524 /* XXX: horrible */
2525 SDL_Delay(10);
2526 continue;
2527 }
2528 #endif
2529 if (is->seek_req) {
2530 int64_t seek_target= is->seek_pos;
2531 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2532 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2533 //FIXME the +-2 is due to rounding being not done in the correct direction in generation
2534 // of the seek_pos/seek_rel variables
2535
2536 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2537 if (ret < 0) {
2538 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2539 }else{
2540 if (is->audio_stream >= 0) {
2541 packet_queue_flush(&is->audioq);
2542 packet_queue_put(&is->audioq, &flush_pkt);
2543 }
2544 if (is->subtitle_stream >= 0) {
2545 packet_queue_flush(&is->subtitleq);
2546 packet_queue_put(&is->subtitleq, &flush_pkt);
2547 }
2548 if (is->video_stream >= 0) {
2549 packet_queue_flush(&is->videoq);
2550 packet_queue_put(&is->videoq, &flush_pkt);
2551 }
2552 }
2553 is->seek_req = 0;
2554 eof= 0;
2555 }
2556
2557 /* if the queue are full, no need to read more */
2558 if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2559 || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream<0)
2560 && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream<0)
2561 && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream<0))) {
2562 /* wait 10 ms */
2563 SDL_Delay(10);
2564 continue;
2565 }
2566 if(url_feof(ic->pb) || eof) {
2567 if(is->video_stream >= 0){
2568 av_init_packet(pkt);
2569 pkt->data=NULL;
2570 pkt->size=0;
2571 pkt->stream_index= is->video_stream;
2572 packet_queue_put(&is->videoq, pkt);
2573 }
2574 SDL_Delay(10);
2575 if(is->audioq.size + is->videoq.size + is->subtitleq.size ==0){
2576 if(loop!=1 && (!loop || --loop)){
2577 stream_seek(cur_stream, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
2578 }else if(autoexit){
2579 ret=AVERROR_EOF;
2580 goto fail;
2581 }
2582 }
2583 continue;
2584 }
2585 ret = av_read_frame(ic, pkt);
2586 if (ret < 0) {
2587 if (ret == AVERROR_EOF)
2588 eof=1;
2589 if (url_ferror(ic->pb))
2590 break;
2591 SDL_Delay(100); /* wait for user event */
2592 continue;
2593 }
2594 /* check if packet is in play range specified by user, then queue, otherwise discard */
2595 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
2596 (pkt->pts - ic->streams[pkt->stream_index]->start_time) *
2597 av_q2d(ic->streams[pkt->stream_index]->time_base) -
2598 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0)/1000000
2599 <= ((double)duration/1000000);
2600 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
2601 packet_queue_put(&is->audioq, pkt);
2602 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range) {
2603 packet_queue_put(&is->videoq, pkt);
2604 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
2605 packet_queue_put(&is->subtitleq, pkt);
2606 } else {
2607 av_free_packet(pkt);
2608 }
2609 }
2610 /* wait until the end */
2611 while (!is->abort_request) {
2612 SDL_Delay(100);
2613 }
2614
2615 ret = 0;
2616 fail:
2617 /* disable interrupting */
2618 global_video_state = NULL;
2619
2620 /* close each stream */
2621 if (is->audio_stream >= 0)
2622 stream_component_close(is, is->audio_stream);
2623 if (is->video_stream >= 0)
2624 stream_component_close(is, is->video_stream);
2625 if (is->subtitle_stream >= 0)
2626 stream_component_close(is, is->subtitle_stream);
2627 if (is->ic) {
2628 av_close_input_file(is->ic);
2629 is->ic = NULL; /* safety */
2630 }
2631 url_set_interrupt_cb(NULL);
2632
2633 if (ret != 0) {
2634 SDL_Event event;
2635
2636 event.type = FF_QUIT_EVENT;
2637 event.user.data1 = is;
2638 SDL_PushEvent(&event);
2639 }
2640 return 0;
2641 }
2642
2643 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2644 {
2645 VideoState *is;
2646
2647 is = av_mallocz(sizeof(VideoState));
2648 if (!is)
2649 return NULL;
2650 av_strlcpy(is->filename, filename, sizeof(is->filename));
2651 is->iformat = iformat;
2652 is->ytop = 0;
2653 is->xleft = 0;
2654
2655 /* start video display */
2656 is->pictq_mutex = SDL_CreateMutex();
2657 is->pictq_cond = SDL_CreateCond();
2658
2659 is->subpq_mutex = SDL_CreateMutex();
2660 is->subpq_cond = SDL_CreateCond();
2661
2662 is->av_sync_type = av_sync_type;
2663 is->parse_tid = SDL_CreateThread(decode_thread, is);
2664 if (!is->parse_tid) {
2665 av_free(is);
2666 return NULL;
2667 }
2668 return is;
2669 }
2670
2671 static void stream_close(VideoState *is)
2672 {
2673 VideoPicture *vp;
2674 int i;
2675 /* XXX: use a special url_shutdown call to abort parse cleanly */
2676 is->abort_request = 1;
2677 SDL_WaitThread(is->parse_tid, NULL);
2678 SDL_WaitThread(is->refresh_tid, NULL);
2679
2680 /* free all pictures */
2681 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2682 vp = &is->pictq[i];
2683 #if CONFIG_AVFILTER
2684 if (vp->picref) {
2685 avfilter_unref_pic(vp->picref);
2686 vp->picref = NULL;
2687 }
2688 #endif
2689 if (vp->bmp) {
2690 SDL_FreeYUVOverlay(vp->bmp);
2691 vp->bmp = NULL;
2692 }
2693 }
2694 SDL_DestroyMutex(is->pictq_mutex);
2695 SDL_DestroyCond(is->pictq_cond);
2696 SDL_DestroyMutex(is->subpq_mutex);
2697 SDL_DestroyCond(is->subpq_cond);
2698 #if !CONFIG_AVFILTER
2699 if (is->img_convert_ctx)
2700 sws_freeContext(is->img_convert_ctx);
2701 #endif
2702 av_free(is);
2703 }
2704
2705 static void stream_cycle_channel(VideoState *is, int codec_type)
2706 {
2707 AVFormatContext *ic = is->ic;
2708 int start_index, stream_index;
2709 AVStream *st;
2710
2711 if (codec_type == AVMEDIA_TYPE_VIDEO)
2712 start_index = is->video_stream;
2713 else if (codec_type == AVMEDIA_TYPE_AUDIO)
2714 start_index = is->audio_stream;
2715 else
2716 start_index = is->subtitle_stream;
2717 if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0))
2718 return;
2719 stream_index = start_index;
2720 for(;;) {
2721 if (++stream_index >= is->ic->nb_streams)
2722 {
2723 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
2724 {
2725 stream_index = -1;
2726 goto the_end;
2727 } else
2728 stream_index = 0;
2729 }
2730 if (stream_index == start_index)
2731 return;
2732 st = ic->streams[stream_index];
2733 if (st->codec->codec_type == codec_type) {
2734 /* check that parameters are OK */
2735 switch(codec_type) {
2736 case AVMEDIA_TYPE_AUDIO:
2737 if (st->codec->sample_rate != 0 &&
2738 st->codec->channels != 0)
2739 goto the_end;
2740 break;
2741 case AVMEDIA_TYPE_VIDEO:
2742 case AVMEDIA_TYPE_SUBTITLE:
2743 goto the_end;
2744 default:
2745 break;
2746 }
2747 }
2748 }
2749 the_end:
2750 stream_component_close(is, start_index);
2751 stream_component_open(is, stream_index);
2752 }
2753
2754
2755 static void toggle_full_screen(void)
2756 {
2757 is_full_screen = !is_full_screen;
2758 if (!fs_screen_width) {
2759 /* use default SDL method */
2760 // SDL_WM_ToggleFullScreen(screen);
2761 }
2762 video_open(cur_stream);
2763 }
2764
2765 static void toggle_pause(void)
2766 {
2767 if (cur_stream)
2768 stream_pause(cur_stream);
2769 step = 0;
2770 }
2771
2772 static void step_to_next_frame(void)
2773 {
2774 if (cur_stream) {
2775 /* if the stream is paused unpause it, then step */
2776 if (cur_stream->paused)
2777 stream_pause(cur_stream);
2778 }
2779 step = 1;
2780 }
2781
2782 static void do_exit(void)
2783 {
2784 int i;
2785 if (cur_stream) {
2786 stream_close(cur_stream);
2787 cur_stream = NULL;
2788 }
2789 for (i = 0; i < AVMEDIA_TYPE_NB; i++)
2790 av_free(avcodec_opts[i]);
2791 av_free(avformat_opts);
2792 av_free(sws_opts);
2793 #if CONFIG_AVFILTER
2794 avfilter_uninit();
2795 #endif
2796 if (show_status)
2797 printf("\n");
2798 SDL_Quit();
2799 exit(0);
2800 }
2801
2802 static void toggle_audio_display(void)
2803 {
2804 if (cur_stream) {
2805 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
2806 cur_stream->show_audio = (cur_stream->show_audio + 1) % 3;
2807 fill_rectangle(screen,
2808 cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height,
2809 bgcolor);
2810 SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height);
2811 }
2812 }
2813
2814 /* handle an event sent by the GUI */
2815 static void event_loop(void)
2816 {
2817 SDL_Event event;
2818 double incr, pos, frac;
2819
2820 for(;;) {
2821 double x;
2822 SDL_WaitEvent(&event);
2823 switch(event.type) {
2824 case SDL_KEYDOWN:
2825 if (exit_on_keydown) {
2826 do_exit();
2827 break;
2828 }
2829 switch(event.key.keysym.sym) {
2830 case SDLK_ESCAPE:
2831 case SDLK_q:
2832 do_exit();
2833 break;
2834 case SDLK_f:
2835 toggle_full_screen();
2836 break;
2837 case SDLK_p:
2838 case SDLK_SPACE:
2839 toggle_pause();
2840 break;
2841 case SDLK_s: //S: Step to next frame
2842 step_to_next_frame();
2843 break;
2844 case SDLK_a:
2845 if (cur_stream)
2846 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
2847 break;
2848 case SDLK_v:
2849 if (cur_stream)
2850 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
2851 break;
2852 case SDLK_t:
2853 if (cur_stream)
2854 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
2855 break;
2856 case SDLK_w:
2857 toggle_audio_display();
2858 break;
2859 case SDLK_LEFT:
2860 incr = -10.0;
2861 goto do_seek;
2862 case SDLK_RIGHT:
2863 incr = 10.0;
2864 goto do_seek;
2865 case SDLK_UP:
2866 incr = 60.0;
2867 goto do_seek;
2868 case SDLK_DOWN:
2869 incr = -60.0;
2870 do_seek:
2871 if (cur_stream) {
2872 if (seek_by_bytes) {
2873 if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos>=0){
2874 pos= cur_stream->video_current_pos;
2875 }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){
2876 pos= cur_stream->audio_pkt.pos;
2877 }else
2878 pos = url_ftell(cur_stream->ic->pb);
2879 if (cur_stream->ic->bit_rate)
2880 incr *= cur_stream->ic->bit_rate / 8.0;
2881 else
2882 incr *= 180000.0;
2883 pos += incr;
2884 stream_seek(cur_stream, pos, incr, 1);
2885 } else {
2886 pos = get_master_clock(cur_stream);
2887 pos += incr;
2888 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
2889 }
2890 }
2891 break;
2892 default:
2893 break;
2894 }
2895 break;
2896 case SDL_MOUSEBUTTONDOWN:
2897 if (exit_on_mousedown) {
2898 do_exit();
2899 break;
2900 }
2901 case SDL_MOUSEMOTION:
2902 if(event.type ==SDL_MOUSEBUTTONDOWN){
2903 x= event.button.x;
2904 }else{
2905 if(event.motion.state != SDL_PRESSED)
2906 break;
2907 x= event.motion.x;
2908 }
2909 if (cur_stream) {
2910 if(seek_by_bytes || cur_stream->ic->duration<=0){
2911 uint64_t size= url_fsize(cur_stream->ic->pb);
2912 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
2913 }else{
2914 int64_t ts;
2915 int ns, hh, mm, ss;
2916 int tns, thh, tmm, tss;
2917 tns = cur_stream->ic->duration/1000000LL;
2918 thh = tns/3600;
2919 tmm = (tns%3600)/60;
2920 tss = (tns%60);
2921 frac = x/cur_stream->width;
2922 ns = frac*tns;
2923 hh = ns/3600;
2924 mm = (ns%3600)/60;
2925 ss = (ns%60);
2926 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
2927 hh, mm, ss, thh, tmm, tss);
2928 ts = frac*cur_stream->ic->duration;
2929 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2930 ts += cur_stream->ic->start_time;
2931 stream_seek(cur_stream, ts, 0, 0);
2932 }
2933 }
2934 break;
2935 case SDL_VIDEORESIZE:
2936 if (cur_stream) {
2937 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2938 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2939 screen_width = cur_stream->width = event.resize.w;
2940 screen_height= cur_stream->height= event.resize.h;
2941 }
2942 break;
2943 case SDL_QUIT:
2944 case FF_QUIT_EVENT:
2945 do_exit();
2946 break;
2947 case FF_ALLOC_EVENT:
2948 video_open(event.user.data1);
2949 alloc_picture(event.user.data1);
2950 break;
2951 case FF_REFRESH_EVENT:
2952 video_refresh_timer(event.user.data1);
2953 cur_stream->refresh=0;
2954 break;
2955 default:
2956 break;
2957 }
2958 }
2959 }
2960
2961 static void opt_frame_size(const char *arg)
2962 {
2963 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
2964 fprintf(stderr, "Incorrect frame size\n");
2965 exit(1);
2966 }
2967 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2968 fprintf(stderr, "Frame size must be a multiple of 2\n");
2969 exit(1);
2970 }
2971 }
2972
2973 static int opt_width(const char *opt, const char *arg)
2974 {
2975 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2976 return 0;
2977 }
2978
2979 static int opt_height(const char *opt, const char *arg)
2980 {
2981 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2982 return 0;
2983 }
2984
2985 static void opt_format(const char *arg)
2986 {
2987 file_iformat = av_find_input_format(arg);
2988 if (!file_iformat) {
2989 fprintf(stderr, "Unknown input format: %s\n", arg);
2990 exit(1);
2991 }
2992 }
2993
2994 static void opt_frame_pix_fmt(const char *arg)
2995 {
2996 frame_pix_fmt = av_get_pix_fmt(arg);
2997 }
2998
2999 static int opt_sync(const char *opt, const char *arg)
3000 {
3001 if (!strcmp(arg, "audio"))
3002 av_sync_type = AV_SYNC_AUDIO_MASTER;
3003 else if (!strcmp(arg, "video"))
3004 av_sync_type = AV_SYNC_VIDEO_MASTER;
3005 else if (!strcmp(arg, "ext"))
3006 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
3007 else {
3008 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
3009 exit(1);
3010 }
3011 return 0;
3012 }
3013
3014 static int opt_seek(const char *opt, const char *arg)
3015 {
3016 start_time = parse_time_or_die(opt, arg, 1);
3017 return 0;
3018 }
3019
3020 static int opt_duration(const char *opt, const char *arg)
3021 {
3022 duration = parse_time_or_die(opt, arg, 1);
3023 return 0;
3024 }
3025
3026 static int opt_debug(const char *opt, const char *arg)
3027 {
3028 av_log_set_level(99);
3029 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
3030 return 0;
3031 }
3032
3033 static int opt_vismv(const char *opt, const char *arg)
3034 {
3035 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
3036 return 0;
3037 }
3038
3039 static int opt_thread_count(const char *opt, const char *arg)
3040 {
3041 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
3042 #if !HAVE_THREADS
3043 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
3044 #endif
3045 return 0;
3046 }
3047
3048 static const OptionDef options[] = {
3049 #include "cmdutils_common_opts.h"
3050 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
3051 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
3052 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
3053 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
3054 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
3055 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
3056 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_AUDIO]}, "select desired audio stream", "stream_number" },
3057 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_VIDEO]}, "select desired video stream", "stream_number" },
3058 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE]}, "select desired subtitle stream", "stream_number" },
3059 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
3060 { "t", HAS_ARG | OPT_FUNC2, {(void*)&opt_duration}, "play \"duration\" seconds of audio/video", "duration" },
3061 { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto", "val" },
3062 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
3063 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
3064 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
3065 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
3066 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
3067 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
3068 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
3069 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
3070 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
3071 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts 0=off 1=on -1=auto", ""},
3072 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
3073 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
3074 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
3075 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
3076 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
3077 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
3078 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
3079 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
3080 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
3081 { "autoexit", OPT_BOOL | OPT_EXPERT, {(void*)&autoexit}, "exit at the end", "" },
3082 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, {(void*)&exit_on_keydown}, "exit on key down", "" },
3083 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, {(void*)&exit_on_mousedown}, "exit on mouse down", "" },
3084 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&loop}, "set number of times the playback shall be looped", "loop count" },
3085 { "framedrop", OPT_BOOL | OPT_EXPERT, {(void*)&framedrop}, "drop frames when cpu is too slow", "" },
3086 { "window_title", OPT_STRING | HAS_ARG, {(void*)&window_title}, "set window title", "window title" },
3087 #if CONFIG_AVFILTER
3088 { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
3089 #endif
3090 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, {(void*)&rdftspeed}, "rdft speed", "msecs" },
3091 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
3092 { NULL, },
3093 };
3094
3095 static void show_usage(void)
3096 {
3097 printf("Simple media player\n");
3098 printf("usage: ffplay [options] input_file\n");
3099 printf("\n");
3100 }
3101
3102 static void show_help(void)
3103 {
3104 show_usage();
3105 show_help_options(options, "Main options:\n",
3106 OPT_EXPERT, 0);
3107 show_help_options(options, "\nAdvanced options:\n",
3108 OPT_EXPERT, OPT_EXPERT);
3109 printf("\nWhile playing:\n"
3110 "q, ESC quit\n"
3111 "f toggle full screen\n"
3112 "p, SPC pause\n"
3113 "a cycle audio channel\n"
3114 "v cycle video channel\n"
3115 "t cycle subtitle channel\n"
3116 "w show audio waves\n"
3117 "s activate frame-step mode\n"
3118 "left/right seek backward/forward 10 seconds\n"
3119 "down/up seek backward/forward 1 minute\n"
3120 "mouse click seek to percentage in file corresponding to fraction of width\n"
3121 );
3122 }
3123
3124 static void opt_input_file(const char *filename)
3125 {
3126 if (input_filename) {
3127 fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3128 filename, input_filename);
3129 exit(1);
3130 }
3131 if (!strcmp(filename, "-"))
3132 filename = "pipe:";
3133 input_filename = filename;
3134 }
3135
3136 /* Called from the main */
3137 int main(int argc, char **argv)
3138 {
3139 int flags, i;
3140
3141 /* register all codecs, demux and protocols */
3142 avcodec_register_all();
3143 #if CONFIG_AVDEVICE
3144 avdevice_register_all();
3145 #endif
3146 #if CONFIG_AVFILTER
3147 avfilter_register_all();
3148 #endif
3149 av_register_all();
3150
3151 for(i=0; i<AVMEDIA_TYPE_NB; i++){
3152 avcodec_opts[i]= avcodec_alloc_context2(i);
3153 }
3154 avformat_opts = avformat_alloc_context();
3155 #if !CONFIG_AVFILTER
3156 sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
3157 #endif
3158
3159 show_banner();
3160
3161 parse_options(argc, argv, options, opt_input_file);
3162
3163 if (!input_filename) {
3164 show_usage();
3165 fprintf(stderr, "An input file must be specified\n");
3166 fprintf(stderr, "Use -h to get full help or, even better, run 'man ffplay'\n");
3167 exit(1);
3168 }
3169
3170 if (display_disable) {
3171 video_disable = 1;
3172 }
3173 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3174 #if !defined(__MINGW32__) && !defined(__APPLE__)
3175 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
3176 #endif
3177 if (SDL_Init (flags)) {
3178 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
3179 exit(1);
3180 }
3181
3182 if (!display_disable) {
3183 #if HAVE_SDL_VIDEO_SIZE
3184 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
3185 fs_screen_width = vi->current_w;
3186 fs_screen_height = vi->current_h;
3187 #endif
3188 }
3189
3190 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
3191 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3192 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3193
3194 av_init_packet(&flush_pkt);
3195 flush_pkt.data= "FLUSH";
3196
3197 cur_stream = stream_open(input_filename, file_iformat);
3198
3199 event_loop();
3200
3201 /* never returns */
3202
3203 return 0;
3204 }