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