OSDN Git Service

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