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