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