Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ 122dcdcb

History | View | Annotate | Download (93.3 KB)

1
/*
2
 * FFplay : Simple Media Player based on the FFmpeg libraries
3
 * Copyright (c) 2003 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

    
22
#include "config.h"
23
#include <math.h>
24
#include <limits.h>
25
#include "libavutil/avstring.h"
26
#include "libavutil/pixdesc.h"
27
#include "libavformat/avformat.h"
28
#include "libavdevice/avdevice.h"
29
#include "libswscale/swscale.h"
30
#include "libavcodec/audioconvert.h"
31
#include "libavcodec/colorspace.h"
32
#include "libavcodec/opt.h"
33
#include "libavcodec/avfft.h"
34

    
35
#if CONFIG_AVFILTER
36
# include "libavfilter/avfilter.h"
37
# include "libavfilter/avfiltergraph.h"
38
# include "libavfilter/graphparser.h"
39
#endif
40

    
41
#include "cmdutils.h"
42

    
43
#include <SDL.h>
44
#include <SDL_thread.h>
45

    
46
#ifdef __MINGW32__
47
#undef main /* We don't want SDL to override our main() */
48
#endif
49

    
50
const char program_name[] = "FFplay";
51
const int program_birth_year = 2003;
52

    
53
//#define DEBUG_SYNC
54

    
55
#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
56
#define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
57
#define MIN_FRAMES 5
58

    
59
/* SDL audio buffer size, in samples. Should be small to have precise
60
   A/V sync as SDL does not have hardware buffer fullness info. */
61
#define SDL_AUDIO_BUFFER_SIZE 1024
62

    
63
/* no AV sync correction is done if below the AV sync threshold */
64
#define AV_SYNC_THRESHOLD 0.01
65
/* no AV correction is done if too big error */
66
#define AV_NOSYNC_THRESHOLD 10.0
67

    
68
/* maximum audio speed change to get correct sync */
69
#define SAMPLE_CORRECTION_PERCENT_MAX 10
70

    
71
/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
72
#define AUDIO_DIFF_AVG_NB   20
73

    
74
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
75
#define SAMPLE_ARRAY_SIZE (2*65536)
76

    
77
#if !CONFIG_AVFILTER
78
static int sws_flags = SWS_BICUBIC;
79
#endif
80

    
81
typedef struct PacketQueue {
82
    AVPacketList *first_pkt, *last_pkt;
83
    int nb_packets;
84
    int size;
85
    int abort_request;
86
    SDL_mutex *mutex;
87
    SDL_cond *cond;
88
} PacketQueue;
89

    
90
#define VIDEO_PICTURE_QUEUE_SIZE 2
91
#define SUBPICTURE_QUEUE_SIZE 4
92

    
93
typedef struct VideoPicture {
94
    double pts;                                  ///<presentation time stamp for this picture
95
    int64_t pos;                                 ///<byte position in file
96
    SDL_Overlay *bmp;
97
    int width, height; /* source height & width */
98
    int allocated;
99
    SDL_TimerID timer_id;
100
    enum PixelFormat pix_fmt;
101

    
102
#if CONFIG_AVFILTER
103
    AVFilterPicRef *picref;
104
#endif
105
} VideoPicture;
106

    
107
typedef struct SubPicture {
108
    double pts; /* presentation time stamp for this picture */
109
    AVSubtitle sub;
110
} SubPicture;
111

    
112
enum {
113
    AV_SYNC_AUDIO_MASTER, /* default choice */
114
    AV_SYNC_VIDEO_MASTER,
115
    AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
116
};
117

    
118
typedef struct VideoState {
119
    SDL_Thread *parse_tid;
120
    SDL_Thread *video_tid;
121
    AVInputFormat *iformat;
122
    int no_background;
123
    int abort_request;
124
    int paused;
125
    int last_paused;
126
    int seek_req;
127
    int seek_flags;
128
    int64_t seek_pos;
129
    int64_t seek_rel;
130
    int read_pause_return;
131
    AVFormatContext *ic;
132
    int dtg_active_format;
133

    
134
    int audio_stream;
135

    
136
    int av_sync_type;
137
    double external_clock; /* external clock base */
138
    int64_t external_clock_time;
139

    
140
    double audio_clock;
141
    double audio_diff_cum; /* used for AV difference average computation */
142
    double audio_diff_avg_coef;
143
    double audio_diff_threshold;
144
    int audio_diff_avg_count;
145
    AVStream *audio_st;
146
    PacketQueue audioq;
147
    int audio_hw_buf_size;
148
    /* samples output by the codec. we reserve more space for avsync
149
       compensation */
150
    DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
151
    DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
152
    uint8_t *audio_buf;
153
    unsigned int audio_buf_size; /* in bytes */
154
    int audio_buf_index; /* in bytes */
155
    AVPacket audio_pkt_temp;
156
    AVPacket audio_pkt;
157
    enum SampleFormat audio_src_fmt;
158
    AVAudioConvert *reformat_ctx;
159

    
160
    int show_audio; /* if true, display audio samples */
161
    int16_t sample_array[SAMPLE_ARRAY_SIZE];
162
    int sample_array_index;
163
    int last_i_start;
164
    RDFTContext *rdft;
165
    int rdft_bits;
166
    int xpos;
167

    
168
    SDL_Thread *subtitle_tid;
169
    int subtitle_stream;
170
    int subtitle_stream_changed;
171
    AVStream *subtitle_st;
172
    PacketQueue subtitleq;
173
    SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
174
    int subpq_size, subpq_rindex, subpq_windex;
175
    SDL_mutex *subpq_mutex;
176
    SDL_cond *subpq_cond;
177

    
178
    double frame_timer;
179
    double frame_last_pts;
180
    double frame_last_delay;
181
    double video_clock;                          ///<pts of last decoded frame / predicted pts of next decoded frame
182
    int video_stream;
183
    AVStream *video_st;
184
    PacketQueue videoq;
185
    double video_current_pts;                    ///<current displayed pts (different from video_clock if frame fifos are used)
186
    double video_current_pts_drift;              ///<video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
187
    int64_t video_current_pos;                   ///<current displayed file pos
188
    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
189
    int pictq_size, pictq_rindex, pictq_windex;
190
    SDL_mutex *pictq_mutex;
191
    SDL_cond *pictq_cond;
192
#if !CONFIG_AVFILTER
193
    struct SwsContext *img_convert_ctx;
194
#endif
195

    
196
    //    QETimer *video_timer;
197
    char filename[1024];
198
    int width, height, xleft, ytop;
199

    
200
    int64_t faulty_pts;
201
    int64_t faulty_dts;
202
    int64_t last_dts_for_fault_detection;
203
    int64_t last_pts_for_fault_detection;
204

    
205
#if CONFIG_AVFILTER
206
    AVFilterContext *out_video_filter;          ///<the last filter in the video chain
207
#endif
208
} VideoState;
209

    
210
static void show_help(void);
211
static int audio_write_get_buf_size(VideoState *is);
212

    
213
/* options specified by the user */
214
static AVInputFormat *file_iformat;
215
static const char *input_filename;
216
static int fs_screen_width;
217
static int fs_screen_height;
218
static int screen_width = 0;
219
static int screen_height = 0;
220
static int frame_width = 0;
221
static int frame_height = 0;
222
static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
223
static int audio_disable;
224
static int video_disable;
225
static int wanted_stream[CODEC_TYPE_NB]={
226
    [CODEC_TYPE_AUDIO]=-1,
227
    [CODEC_TYPE_VIDEO]=-1,
228
    [CODEC_TYPE_SUBTITLE]=-1,
229
};
230
static int seek_by_bytes=-1;
231
static int display_disable;
232
static int show_status = 1;
233
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
234
static int64_t start_time = AV_NOPTS_VALUE;
235
static int debug = 0;
236
static int debug_mv = 0;
237
static int step = 0;
238
static int thread_count = 1;
239
static int workaround_bugs = 1;
240
static int fast = 0;
241
static int genpts = 0;
242
static int lowres = 0;
243
static int idct = FF_IDCT_AUTO;
244
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
245
static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
246
static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
247
static int error_recognition = FF_ER_CAREFUL;
248
static int error_concealment = 3;
249
static int decoder_reorder_pts= -1;
250
static int autoexit;
251
#if CONFIG_AVFILTER
252
static char *vfilters = NULL;
253
#endif
254

    
255
/* current context */
256
static int is_full_screen;
257
static VideoState *cur_stream;
258
static int64_t audio_callback_time;
259

    
260
static AVPacket flush_pkt;
261

    
262
#define FF_ALLOC_EVENT   (SDL_USEREVENT)
263
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
264
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
265

    
266
static SDL_Surface *screen;
267

    
268
static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
269

    
270
/* packet queue handling */
271
static void packet_queue_init(PacketQueue *q)
272
{
273
    memset(q, 0, sizeof(PacketQueue));
274
    q->mutex = SDL_CreateMutex();
275
    q->cond = SDL_CreateCond();
276
    packet_queue_put(q, &flush_pkt);
277
}
278

    
279
static void packet_queue_flush(PacketQueue *q)
280
{
281
    AVPacketList *pkt, *pkt1;
282

    
283
    SDL_LockMutex(q->mutex);
284
    for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
285
        pkt1 = pkt->next;
286
        av_free_packet(&pkt->pkt);
287
        av_freep(&pkt);
288
    }
289
    q->last_pkt = NULL;
290
    q->first_pkt = NULL;
291
    q->nb_packets = 0;
292
    q->size = 0;
293
    SDL_UnlockMutex(q->mutex);
294
}
295

    
296
static void packet_queue_end(PacketQueue *q)
297
{
298
    packet_queue_flush(q);
299
    SDL_DestroyMutex(q->mutex);
300
    SDL_DestroyCond(q->cond);
301
}
302

    
303
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
304
{
305
    AVPacketList *pkt1;
306

    
307
    /* duplicate the packet */
308
    if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
309
        return -1;
310

    
311
    pkt1 = av_malloc(sizeof(AVPacketList));
312
    if (!pkt1)
313
        return -1;
314
    pkt1->pkt = *pkt;
315
    pkt1->next = NULL;
316

    
317

    
318
    SDL_LockMutex(q->mutex);
319

    
320
    if (!q->last_pkt)
321

    
322
        q->first_pkt = pkt1;
323
    else
324
        q->last_pkt->next = pkt1;
325
    q->last_pkt = pkt1;
326
    q->nb_packets++;
327
    q->size += pkt1->pkt.size + sizeof(*pkt1);
328
    /* XXX: should duplicate packet data in DV case */
329
    SDL_CondSignal(q->cond);
330

    
331
    SDL_UnlockMutex(q->mutex);
332
    return 0;
333
}
334

    
335
static void packet_queue_abort(PacketQueue *q)
336
{
337
    SDL_LockMutex(q->mutex);
338

    
339
    q->abort_request = 1;
340

    
341
    SDL_CondSignal(q->cond);
342

    
343
    SDL_UnlockMutex(q->mutex);
344
}
345

    
346
/* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
347
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
348
{
349
    AVPacketList *pkt1;
350
    int ret;
351

    
352
    SDL_LockMutex(q->mutex);
353

    
354
    for(;;) {
355
        if (q->abort_request) {
356
            ret = -1;
357
            break;
358
        }
359

    
360
        pkt1 = q->first_pkt;
361
        if (pkt1) {
362
            q->first_pkt = pkt1->next;
363
            if (!q->first_pkt)
364
                q->last_pkt = NULL;
365
            q->nb_packets--;
366
            q->size -= pkt1->pkt.size + sizeof(*pkt1);
367
            *pkt = pkt1->pkt;
368
            av_free(pkt1);
369
            ret = 1;
370
            break;
371
        } else if (!block) {
372
            ret = 0;
373
            break;
374
        } else {
375
            SDL_CondWait(q->cond, q->mutex);
376
        }
377
    }
378
    SDL_UnlockMutex(q->mutex);
379
    return ret;
380
}
381

    
382
static inline void fill_rectangle(SDL_Surface *screen,
383
                                  int x, int y, int w, int h, int color)
384
{
385
    SDL_Rect rect;
386
    rect.x = x;
387
    rect.y = y;
388
    rect.w = w;
389
    rect.h = h;
390
    SDL_FillRect(screen, &rect, color);
391
}
392

    
393
#if 0
394
/* draw only the border of a rectangle */
395
void fill_border(VideoState *s, int x, int y, int w, int h, int color)
396
{
397
    int w1, w2, h1, h2;
398

399
    /* fill the background */
400
    w1 = x;
401
    if (w1 < 0)
402
        w1 = 0;
403
    w2 = s->width - (x + w);
404
    if (w2 < 0)
405
        w2 = 0;
406
    h1 = y;
407
    if (h1 < 0)
408
        h1 = 0;
409
    h2 = s->height - (y + h);
410
    if (h2 < 0)
411
        h2 = 0;
412
    fill_rectangle(screen,
413
                   s->xleft, s->ytop,
414
                   w1, s->height,
415
                   color);
416
    fill_rectangle(screen,
417
                   s->xleft + s->width - w2, s->ytop,
418
                   w2, s->height,
419
                   color);
420
    fill_rectangle(screen,
421
                   s->xleft + w1, s->ytop,
422
                   s->width - w1 - w2, h1,
423
                   color);
424
    fill_rectangle(screen,
425
                   s->xleft + w1, s->ytop + s->height - h2,
426
                   s->width - w1 - w2, h2,
427
                   color);
428
}
429
#endif
430

    
431
#define ALPHA_BLEND(a, oldp, newp, s)\
432
((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
433

    
434
#define RGBA_IN(r, g, b, a, s)\
435
{\
436
    unsigned int v = ((const uint32_t *)(s))[0];\
437
    a = (v >> 24) & 0xff;\
438
    r = (v >> 16) & 0xff;\
439
    g = (v >> 8) & 0xff;\
440
    b = v & 0xff;\
441
}
442

    
443
#define YUVA_IN(y, u, v, a, s, pal)\
444
{\
445
    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
446
    a = (val >> 24) & 0xff;\
447
    y = (val >> 16) & 0xff;\
448
    u = (val >> 8) & 0xff;\
449
    v = val & 0xff;\
450
}
451

    
452
#define YUVA_OUT(d, y, u, v, a)\
453
{\
454
    ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
455
}
456

    
457

    
458
#define BPP 1
459

    
460
static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
461
{
462
    int wrap, wrap3, width2, skip2;
463
    int y, u, v, a, u1, v1, a1, w, h;
464
    uint8_t *lum, *cb, *cr;
465
    const uint8_t *p;
466
    const uint32_t *pal;
467
    int dstx, dsty, dstw, dsth;
468

    
469
    dstw = av_clip(rect->w, 0, imgw);
470
    dsth = av_clip(rect->h, 0, imgh);
471
    dstx = av_clip(rect->x, 0, imgw - dstw);
472
    dsty = av_clip(rect->y, 0, imgh - dsth);
473
    lum = dst->data[0] + dsty * dst->linesize[0];
474
    cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
475
    cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
476

    
477
    width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
478
    skip2 = dstx >> 1;
479
    wrap = dst->linesize[0];
480
    wrap3 = rect->pict.linesize[0];
481
    p = rect->pict.data[0];
482
    pal = (const uint32_t *)rect->pict.data[1];  /* Now in YCrCb! */
483

    
484
    if (dsty & 1) {
485
        lum += dstx;
486
        cb += skip2;
487
        cr += skip2;
488

    
489
        if (dstx & 1) {
490
            YUVA_IN(y, u, v, a, p, pal);
491
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
492
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
493
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
494
            cb++;
495
            cr++;
496
            lum++;
497
            p += BPP;
498
        }
499
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
500
            YUVA_IN(y, u, v, a, p, pal);
501
            u1 = u;
502
            v1 = v;
503
            a1 = a;
504
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
505

    
506
            YUVA_IN(y, u, v, a, p + BPP, pal);
507
            u1 += u;
508
            v1 += v;
509
            a1 += a;
510
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
511
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
512
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
513
            cb++;
514
            cr++;
515
            p += 2 * BPP;
516
            lum += 2;
517
        }
518
        if (w) {
519
            YUVA_IN(y, u, v, a, p, pal);
520
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
521
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
522
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
523
            p++;
524
            lum++;
525
        }
526
        p += wrap3 - dstw * BPP;
527
        lum += wrap - dstw - dstx;
528
        cb += dst->linesize[1] - width2 - skip2;
529
        cr += dst->linesize[2] - width2 - skip2;
530
    }
531
    for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
532
        lum += dstx;
533
        cb += skip2;
534
        cr += skip2;
535

    
536
        if (dstx & 1) {
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
            p += wrap3;
543
            lum += wrap;
544
            YUVA_IN(y, u, v, a, p, pal);
545
            u1 += u;
546
            v1 += v;
547
            a1 += a;
548
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
549
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
550
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
551
            cb++;
552
            cr++;
553
            p += -wrap3 + BPP;
554
            lum += -wrap + 1;
555
        }
556
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
557
            YUVA_IN(y, u, v, a, p, pal);
558
            u1 = u;
559
            v1 = v;
560
            a1 = a;
561
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
562

    
563
            YUVA_IN(y, u, v, a, p + BPP, pal);
564
            u1 += u;
565
            v1 += v;
566
            a1 += a;
567
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
568
            p += wrap3;
569
            lum += wrap;
570

    
571
            YUVA_IN(y, u, v, a, p, pal);
572
            u1 += u;
573
            v1 += v;
574
            a1 += a;
575
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
576

    
577
            YUVA_IN(y, u, v, a, p + BPP, pal);
578
            u1 += u;
579
            v1 += v;
580
            a1 += a;
581
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
582

    
583
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
584
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
585

    
586
            cb++;
587
            cr++;
588
            p += -wrap3 + 2 * BPP;
589
            lum += -wrap + 2;
590
        }
591
        if (w) {
592
            YUVA_IN(y, u, v, a, p, pal);
593
            u1 = u;
594
            v1 = v;
595
            a1 = a;
596
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
597
            p += wrap3;
598
            lum += wrap;
599
            YUVA_IN(y, u, v, a, p, pal);
600
            u1 += u;
601
            v1 += v;
602
            a1 += a;
603
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
604
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
605
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
606
            cb++;
607
            cr++;
608
            p += -wrap3 + BPP;
609
            lum += -wrap + 1;
610
        }
611
        p += wrap3 + (wrap3 - dstw * BPP);
612
        lum += wrap + (wrap - dstw - dstx);
613
        cb += dst->linesize[1] - width2 - skip2;
614
        cr += dst->linesize[2] - width2 - skip2;
615
    }
616
    /* handle odd height */
617
    if (h) {
618
        lum += dstx;
619
        cb += skip2;
620
        cr += skip2;
621

    
622
        if (dstx & 1) {
623
            YUVA_IN(y, u, v, a, p, pal);
624
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
625
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
626
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
627
            cb++;
628
            cr++;
629
            lum++;
630
            p += BPP;
631
        }
632
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
633
            YUVA_IN(y, u, v, a, p, pal);
634
            u1 = u;
635
            v1 = v;
636
            a1 = a;
637
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
638

    
639
            YUVA_IN(y, u, v, a, p + BPP, pal);
640
            u1 += u;
641
            v1 += v;
642
            a1 += a;
643
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
644
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
645
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
646
            cb++;
647
            cr++;
648
            p += 2 * BPP;
649
            lum += 2;
650
        }
651
        if (w) {
652
            YUVA_IN(y, u, v, a, p, pal);
653
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
654
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
655
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
656
        }
657
    }
658
}
659

    
660
static void free_subpicture(SubPicture *sp)
661
{
662
    int i;
663

    
664
    for (i = 0; i < sp->sub.num_rects; i++)
665
    {
666
        av_freep(&sp->sub.rects[i]->pict.data[0]);
667
        av_freep(&sp->sub.rects[i]->pict.data[1]);
668
        av_freep(&sp->sub.rects[i]);
669
    }
670

    
671
    av_free(sp->sub.rects);
672

    
673
    memset(&sp->sub, 0, sizeof(AVSubtitle));
674
}
675

    
676
static void video_image_display(VideoState *is)
677
{
678
    VideoPicture *vp;
679
    SubPicture *sp;
680
    AVPicture pict;
681
    float aspect_ratio;
682
    int width, height, x, y;
683
    SDL_Rect rect;
684
    int i;
685

    
686
    vp = &is->pictq[is->pictq_rindex];
687
    if (vp->bmp) {
688
#if CONFIG_AVFILTER
689
         if (vp->picref->pixel_aspect.num == 0)
690
             aspect_ratio = 0;
691
         else
692
             aspect_ratio = av_q2d(vp->picref->pixel_aspect);
693
#else
694

    
695
        /* XXX: use variable in the frame */
696
        if (is->video_st->sample_aspect_ratio.num)
697
            aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
698
        else if (is->video_st->codec->sample_aspect_ratio.num)
699
            aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
700
        else
701
            aspect_ratio = 0;
702
#endif
703
        if (aspect_ratio <= 0.0)
704
            aspect_ratio = 1.0;
705
        aspect_ratio *= (float)vp->width / (float)vp->height;
706
        /* if an active format is indicated, then it overrides the
707
           mpeg format */
708
#if 0
709
        if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
710
            is->dtg_active_format = is->video_st->codec->dtg_active_format;
711
            printf("dtg_active_format=%d\n", is->dtg_active_format);
712
        }
713
#endif
714
#if 0
715
        switch(is->video_st->codec->dtg_active_format) {
716
        case FF_DTG_AFD_SAME:
717
        default:
718
            /* nothing to do */
719
            break;
720
        case FF_DTG_AFD_4_3:
721
            aspect_ratio = 4.0 / 3.0;
722
            break;
723
        case FF_DTG_AFD_16_9:
724
            aspect_ratio = 16.0 / 9.0;
725
            break;
726
        case FF_DTG_AFD_14_9:
727
            aspect_ratio = 14.0 / 9.0;
728
            break;
729
        case FF_DTG_AFD_4_3_SP_14_9:
730
            aspect_ratio = 14.0 / 9.0;
731
            break;
732
        case FF_DTG_AFD_16_9_SP_14_9:
733
            aspect_ratio = 14.0 / 9.0;
734
            break;
735
        case FF_DTG_AFD_SP_4_3:
736
            aspect_ratio = 4.0 / 3.0;
737
            break;
738
        }
739
#endif
740

    
741
        if (is->subtitle_st)
742
        {
743
            if (is->subpq_size > 0)
744
            {
745
                sp = &is->subpq[is->subpq_rindex];
746

    
747
                if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
748
                {
749
                    SDL_LockYUVOverlay (vp->bmp);
750

    
751
                    pict.data[0] = vp->bmp->pixels[0];
752
                    pict.data[1] = vp->bmp->pixels[2];
753
                    pict.data[2] = vp->bmp->pixels[1];
754

    
755
                    pict.linesize[0] = vp->bmp->pitches[0];
756
                    pict.linesize[1] = vp->bmp->pitches[2];
757
                    pict.linesize[2] = vp->bmp->pitches[1];
758

    
759
                    for (i = 0; i < sp->sub.num_rects; i++)
760
                        blend_subrect(&pict, sp->sub.rects[i],
761
                                      vp->bmp->w, vp->bmp->h);
762

    
763
                    SDL_UnlockYUVOverlay (vp->bmp);
764
                }
765
            }
766
        }
767

    
768

    
769
        /* XXX: we suppose the screen has a 1.0 pixel ratio */
770
        height = is->height;
771
        width = ((int)rint(height * aspect_ratio)) & ~1;
772
        if (width > is->width) {
773
            width = is->width;
774
            height = ((int)rint(width / aspect_ratio)) & ~1;
775
        }
776
        x = (is->width - width) / 2;
777
        y = (is->height - height) / 2;
778
        if (!is->no_background) {
779
            /* fill the background */
780
            //            fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
781
        } else {
782
            is->no_background = 0;
783
        }
784
        rect.x = is->xleft + x;
785
        rect.y = is->ytop  + y;
786
        rect.w = width;
787
        rect.h = height;
788
        SDL_DisplayYUVOverlay(vp->bmp, &rect);
789
    } else {
790
#if 0
791
        fill_rectangle(screen,
792
                       is->xleft, is->ytop, is->width, is->height,
793
                       QERGB(0x00, 0x00, 0x00));
794
#endif
795
    }
796
}
797

    
798
static inline int compute_mod(int a, int b)
799
{
800
    a = a % b;
801
    if (a >= 0)
802
        return a;
803
    else
804
        return a + b;
805
}
806

    
807
static void video_audio_display(VideoState *s)
808
{
809
    int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
810
    int ch, channels, h, h2, bgcolor, fgcolor;
811
    int16_t time_diff;
812
    int rdft_bits, nb_freq;
813

    
814
    for(rdft_bits=1; (1<<rdft_bits)<2*s->height; rdft_bits++)
815
        ;
816
    nb_freq= 1<<(rdft_bits-1);
817

    
818
    /* compute display index : center on currently output samples */
819
    channels = s->audio_st->codec->channels;
820
    nb_display_channels = channels;
821
    if (!s->paused) {
822
        int data_used= s->show_audio==1 ? s->width : (2*nb_freq);
823
        n = 2 * channels;
824
        delay = audio_write_get_buf_size(s);
825
        delay /= n;
826

    
827
        /* to be more precise, we take into account the time spent since
828
           the last buffer computation */
829
        if (audio_callback_time) {
830
            time_diff = av_gettime() - audio_callback_time;
831
            delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
832
        }
833

    
834
        delay += 2*data_used;
835
        if (delay < data_used)
836
            delay = data_used;
837

    
838
        i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
839
        if(s->show_audio==1){
840
            h= INT_MIN;
841
            for(i=0; i<1000; i+=channels){
842
                int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
843
                int a= s->sample_array[idx];
844
                int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
845
                int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
846
                int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
847
                int score= a-d;
848
                if(h<score && (b^c)<0){
849
                    h= score;
850
                    i_start= idx;
851
                }
852
            }
853
        }
854

    
855
        s->last_i_start = i_start;
856
    } else {
857
        i_start = s->last_i_start;
858
    }
859

    
860
    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
861
    if(s->show_audio==1){
862
        fill_rectangle(screen,
863
                       s->xleft, s->ytop, s->width, s->height,
864
                       bgcolor);
865

    
866
        fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
867

    
868
        /* total height for one channel */
869
        h = s->height / nb_display_channels;
870
        /* graph height / 2 */
871
        h2 = (h * 9) / 20;
872
        for(ch = 0;ch < nb_display_channels; ch++) {
873
            i = i_start + ch;
874
            y1 = s->ytop + ch * h + (h / 2); /* position of center line */
875
            for(x = 0; x < s->width; x++) {
876
                y = (s->sample_array[i] * h2) >> 15;
877
                if (y < 0) {
878
                    y = -y;
879
                    ys = y1 - y;
880
                } else {
881
                    ys = y1;
882
                }
883
                fill_rectangle(screen,
884
                               s->xleft + x, ys, 1, y,
885
                               fgcolor);
886
                i += channels;
887
                if (i >= SAMPLE_ARRAY_SIZE)
888
                    i -= SAMPLE_ARRAY_SIZE;
889
            }
890
        }
891

    
892
        fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
893

    
894
        for(ch = 1;ch < nb_display_channels; ch++) {
895
            y = s->ytop + ch * h;
896
            fill_rectangle(screen,
897
                           s->xleft, y, s->width, 1,
898
                           fgcolor);
899
        }
900
        SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
901
    }else{
902
        nb_display_channels= FFMIN(nb_display_channels, 2);
903
        if(rdft_bits != s->rdft_bits){
904
            av_rdft_end(s->rdft);
905
            s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
906
            s->rdft_bits= rdft_bits;
907
        }
908
        {
909
            FFTSample data[2][2*nb_freq];
910
            for(ch = 0;ch < nb_display_channels; ch++) {
911
                i = i_start + ch;
912
                for(x = 0; x < 2*nb_freq; x++) {
913
                    double w= (x-nb_freq)*(1.0/nb_freq);
914
                    data[ch][x]= s->sample_array[i]*(1.0-w*w);
915
                    i += channels;
916
                    if (i >= SAMPLE_ARRAY_SIZE)
917
                        i -= SAMPLE_ARRAY_SIZE;
918
                }
919
                av_rdft_calc(s->rdft, data[ch]);
920
            }
921
            //least efficient way to do this, we should of course directly access it but its more than fast enough
922
            for(y=0; y<s->height; y++){
923
                double w= 1/sqrt(nb_freq);
924
                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]));
925
                int b= sqrt(w*sqrt(data[1][2*y+0]*data[1][2*y+0] + data[1][2*y+1]*data[1][2*y+1]));
926
                a= FFMIN(a,255);
927
                b= FFMIN(b,255);
928
                fgcolor = SDL_MapRGB(screen->format, a, b, (a+b)/2);
929

    
930
                fill_rectangle(screen,
931
                            s->xpos, s->height-y, 1, 1,
932
                            fgcolor);
933
            }
934
        }
935
        SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
936
        s->xpos++;
937
        if(s->xpos >= s->width)
938
            s->xpos= s->xleft;
939
    }
940
}
941

    
942
static int video_open(VideoState *is){
943
    int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
944
    int w,h;
945

    
946
    if(is_full_screen) flags |= SDL_FULLSCREEN;
947
    else               flags |= SDL_RESIZABLE;
948

    
949
    if (is_full_screen && fs_screen_width) {
950
        w = fs_screen_width;
951
        h = fs_screen_height;
952
    } else if(!is_full_screen && screen_width){
953
        w = screen_width;
954
        h = screen_height;
955
#if CONFIG_AVFILTER
956
    }else if (is->out_video_filter && is->out_video_filter->inputs[0]){
957
        w = is->out_video_filter->inputs[0]->w;
958
        h = is->out_video_filter->inputs[0]->h;
959
#else
960
    }else if (is->video_st && is->video_st->codec->width){
961
        w = is->video_st->codec->width;
962
        h = is->video_st->codec->height;
963
#endif
964
    } else {
965
        w = 640;
966
        h = 480;
967
    }
968
    if(screen && is->width == screen->w && screen->w == w
969
       && is->height== screen->h && screen->h == h)
970
        return 0;
971

    
972
#ifndef __APPLE__
973
    screen = SDL_SetVideoMode(w, h, 0, flags);
974
#else
975
    /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
976
    screen = SDL_SetVideoMode(w, h, 24, flags);
977
#endif
978
    if (!screen) {
979
        fprintf(stderr, "SDL: could not set video mode - exiting\n");
980
        return -1;
981
    }
982
    SDL_WM_SetCaption("FFplay", "FFplay");
983

    
984
    is->width = screen->w;
985
    is->height = screen->h;
986

    
987
    return 0;
988
}
989

    
990
/* display the current picture, if any */
991
static void video_display(VideoState *is)
992
{
993
    if(!screen)
994
        video_open(cur_stream);
995
    if (is->audio_st && is->show_audio)
996
        video_audio_display(is);
997
    else if (is->video_st)
998
        video_image_display(is);
999
}
1000

    
1001
static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
1002
{
1003
    SDL_Event event;
1004
    event.type = FF_REFRESH_EVENT;
1005
    event.user.data1 = opaque;
1006
    SDL_PushEvent(&event);
1007
    return 0; /* 0 means stop timer */
1008
}
1009

    
1010
/* schedule a video refresh in 'delay' ms */
1011
static SDL_TimerID schedule_refresh(VideoState *is, int delay)
1012
{
1013
    if(!delay) delay=1; //SDL seems to be buggy when the delay is 0
1014
    return SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
1015
}
1016

    
1017
/* get the current audio clock value */
1018
static double get_audio_clock(VideoState *is)
1019
{
1020
    double pts;
1021
    int hw_buf_size, bytes_per_sec;
1022
    pts = is->audio_clock;
1023
    hw_buf_size = audio_write_get_buf_size(is);
1024
    bytes_per_sec = 0;
1025
    if (is->audio_st) {
1026
        bytes_per_sec = is->audio_st->codec->sample_rate *
1027
            2 * is->audio_st->codec->channels;
1028
    }
1029
    if (bytes_per_sec)
1030
        pts -= (double)hw_buf_size / bytes_per_sec;
1031
    return pts;
1032
}
1033

    
1034
/* get the current video clock value */
1035
static double get_video_clock(VideoState *is)
1036
{
1037
    if (is->paused) {
1038
        return is->video_current_pts;
1039
    } else {
1040
        return is->video_current_pts_drift + av_gettime() / 1000000.0;
1041
    }
1042
}
1043

    
1044
/* get the current external clock value */
1045
static double get_external_clock(VideoState *is)
1046
{
1047
    int64_t ti;
1048
    ti = av_gettime();
1049
    return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
1050
}
1051

    
1052
/* get the current master clock value */
1053
static double get_master_clock(VideoState *is)
1054
{
1055
    double val;
1056

    
1057
    if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1058
        if (is->video_st)
1059
            val = get_video_clock(is);
1060
        else
1061
            val = get_audio_clock(is);
1062
    } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1063
        if (is->audio_st)
1064
            val = get_audio_clock(is);
1065
        else
1066
            val = get_video_clock(is);
1067
    } else {
1068
        val = get_external_clock(is);
1069
    }
1070
    return val;
1071
}
1072

    
1073
/* seek in the stream */
1074
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
1075
{
1076
    if (!is->seek_req) {
1077
        is->seek_pos = pos;
1078
        is->seek_rel = rel;
1079
        is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1080
        if (seek_by_bytes)
1081
            is->seek_flags |= AVSEEK_FLAG_BYTE;
1082
        is->seek_req = 1;
1083
    }
1084
}
1085

    
1086
/* pause or resume the video */
1087
static void stream_pause(VideoState *is)
1088
{
1089
    if (is->paused) {
1090
        is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
1091
        if(is->read_pause_return != AVERROR(ENOSYS)){
1092
            is->video_current_pts = is->video_current_pts_drift + av_gettime() / 1000000.0;
1093
        }
1094
        is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
1095
    }
1096
    is->paused = !is->paused;
1097
}
1098

    
1099
static double compute_frame_delay(double frame_current_pts, VideoState *is)
1100
{
1101
    double actual_delay, delay, sync_threshold, diff;
1102

    
1103
    /* compute nominal delay */
1104
    delay = frame_current_pts - is->frame_last_pts;
1105
    if (delay <= 0 || delay >= 10.0) {
1106
        /* if incorrect delay, use previous one */
1107
        delay = is->frame_last_delay;
1108
    } else {
1109
        is->frame_last_delay = delay;
1110
    }
1111
    is->frame_last_pts = frame_current_pts;
1112

    
1113
    /* update delay to follow master synchronisation source */
1114
    if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1115
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1116
        /* if video is slave, we try to correct big delays by
1117
           duplicating or deleting a frame */
1118
        diff = get_video_clock(is) - get_master_clock(is);
1119

    
1120
        /* skip or repeat frame. We take into account the
1121
           delay to compute the threshold. I still don't know
1122
           if it is the best guess */
1123
        sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1124
        if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1125
            if (diff <= -sync_threshold)
1126
                delay = 0;
1127
            else if (diff >= sync_threshold)
1128
                delay = 2 * delay;
1129
        }
1130
    }
1131

    
1132
    is->frame_timer += delay;
1133
    /* compute the REAL delay (we need to do that to avoid
1134
       long term errors */
1135
    actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
1136
    if (actual_delay < 0.010) {
1137
        /* XXX: should skip picture */
1138
        actual_delay = 0.010;
1139
    }
1140

    
1141
#if defined(DEBUG_SYNC)
1142
    printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1143
            delay, actual_delay, frame_current_pts, -diff);
1144
#endif
1145

    
1146
    return actual_delay;
1147
}
1148

    
1149
/* called to display each frame */
1150
static void video_refresh_timer(void *opaque)
1151
{
1152
    VideoState *is = opaque;
1153
    VideoPicture *vp;
1154

    
1155
    SubPicture *sp, *sp2;
1156

    
1157
    if (is->video_st) {
1158
        if (is->pictq_size == 0) {
1159
            fprintf(stderr, "Internal error detected in the SDL timer\n");
1160
        } else {
1161
            /* dequeue the picture */
1162
            vp = &is->pictq[is->pictq_rindex];
1163

    
1164
            /* update current video pts */
1165
            is->video_current_pts = vp->pts;
1166
            is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
1167
            is->video_current_pos = vp->pos;
1168

    
1169
            if(is->subtitle_st) {
1170
                if (is->subtitle_stream_changed) {
1171
                    SDL_LockMutex(is->subpq_mutex);
1172

    
1173
                    while (is->subpq_size) {
1174
                        free_subpicture(&is->subpq[is->subpq_rindex]);
1175

    
1176
                        /* update queue size and signal for next picture */
1177
                        if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1178
                            is->subpq_rindex = 0;
1179

    
1180
                        is->subpq_size--;
1181
                    }
1182
                    is->subtitle_stream_changed = 0;
1183

    
1184
                    SDL_CondSignal(is->subpq_cond);
1185
                    SDL_UnlockMutex(is->subpq_mutex);
1186
                } else {
1187
                    if (is->subpq_size > 0) {
1188
                        sp = &is->subpq[is->subpq_rindex];
1189

    
1190
                        if (is->subpq_size > 1)
1191
                            sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1192
                        else
1193
                            sp2 = NULL;
1194

    
1195
                        if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1196
                                || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1197
                        {
1198
                            free_subpicture(sp);
1199

    
1200
                            /* update queue size and signal for next picture */
1201
                            if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1202
                                is->subpq_rindex = 0;
1203

    
1204
                            SDL_LockMutex(is->subpq_mutex);
1205
                            is->subpq_size--;
1206
                            SDL_CondSignal(is->subpq_cond);
1207
                            SDL_UnlockMutex(is->subpq_mutex);
1208
                        }
1209
                    }
1210
                }
1211
            }
1212

    
1213
            /* display picture */
1214
            video_display(is);
1215

    
1216
            /* update queue size and signal for next picture */
1217
            if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1218
                is->pictq_rindex = 0;
1219

    
1220
            SDL_LockMutex(is->pictq_mutex);
1221
            vp->timer_id= 0;
1222
            is->pictq_size--;
1223
            SDL_CondSignal(is->pictq_cond);
1224
            SDL_UnlockMutex(is->pictq_mutex);
1225
        }
1226
    } else if (is->audio_st) {
1227
        /* draw the next audio frame */
1228

    
1229
        schedule_refresh(is, 40);
1230

    
1231
        /* if only audio stream, then display the audio bars (better
1232
           than nothing, just to test the implementation */
1233

    
1234
        /* display picture */
1235
        video_display(is);
1236
    } else {
1237
        schedule_refresh(is, 100);
1238
    }
1239
    if (show_status) {
1240
        static int64_t last_time;
1241
        int64_t cur_time;
1242
        int aqsize, vqsize, sqsize;
1243
        double av_diff;
1244

    
1245
        cur_time = av_gettime();
1246
        if (!last_time || (cur_time - last_time) >= 30000) {
1247
            aqsize = 0;
1248
            vqsize = 0;
1249
            sqsize = 0;
1250
            if (is->audio_st)
1251
                aqsize = is->audioq.size;
1252
            if (is->video_st)
1253
                vqsize = is->videoq.size;
1254
            if (is->subtitle_st)
1255
                sqsize = is->subtitleq.size;
1256
            av_diff = 0;
1257
            if (is->audio_st && is->video_st)
1258
                av_diff = get_audio_clock(is) - get_video_clock(is);
1259
            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB f=%Ld/%Ld   \r",
1260
                   get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize, is->faulty_dts, is->faulty_pts);
1261
            fflush(stdout);
1262
            last_time = cur_time;
1263
        }
1264
    }
1265
}
1266

    
1267
/* allocate a picture (needs to do that in main thread to avoid
1268
   potential locking problems */
1269
static void alloc_picture(void *opaque)
1270
{
1271
    VideoState *is = opaque;
1272
    VideoPicture *vp;
1273

    
1274
    vp = &is->pictq[is->pictq_windex];
1275

    
1276
    if (vp->bmp)
1277
        SDL_FreeYUVOverlay(vp->bmp);
1278

    
1279
#if CONFIG_AVFILTER
1280
    if (vp->picref)
1281
        avfilter_unref_pic(vp->picref);
1282
    vp->picref = NULL;
1283

    
1284
    vp->width   = is->out_video_filter->inputs[0]->w;
1285
    vp->height  = is->out_video_filter->inputs[0]->h;
1286
    vp->pix_fmt = is->out_video_filter->inputs[0]->format;
1287
#else
1288
    vp->width   = is->video_st->codec->width;
1289
    vp->height  = is->video_st->codec->height;
1290
    vp->pix_fmt = is->video_st->codec->pix_fmt;
1291
#endif
1292

    
1293
    vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
1294
                                   SDL_YV12_OVERLAY,
1295
                                   screen);
1296

    
1297
    SDL_LockMutex(is->pictq_mutex);
1298
    vp->allocated = 1;
1299
    SDL_CondSignal(is->pictq_cond);
1300
    SDL_UnlockMutex(is->pictq_mutex);
1301
}
1302

    
1303
/**
1304
 *
1305
 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1306
 */
1307
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
1308
{
1309
    VideoPicture *vp;
1310
    int dst_pix_fmt;
1311
#if CONFIG_AVFILTER
1312
    AVPicture pict_src;
1313
#endif
1314
    /* wait until we have space to put a new picture */
1315
    SDL_LockMutex(is->pictq_mutex);
1316
    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1317
           !is->videoq.abort_request) {
1318
        SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1319
    }
1320
    SDL_UnlockMutex(is->pictq_mutex);
1321

    
1322
    if (is->videoq.abort_request)
1323
        return -1;
1324

    
1325
    vp = &is->pictq[is->pictq_windex];
1326

    
1327
    /* alloc or resize hardware picture buffer */
1328
    if (!vp->bmp ||
1329
#if CONFIG_AVFILTER
1330
        vp->width  != is->out_video_filter->inputs[0]->w ||
1331
        vp->height != is->out_video_filter->inputs[0]->h) {
1332
#else
1333
        vp->width != is->video_st->codec->width ||
1334
        vp->height != is->video_st->codec->height) {
1335
#endif
1336
        SDL_Event event;
1337

    
1338
        vp->allocated = 0;
1339

    
1340
        /* the allocation must be done in the main thread to avoid
1341
           locking problems */
1342
        event.type = FF_ALLOC_EVENT;
1343
        event.user.data1 = is;
1344
        SDL_PushEvent(&event);
1345

    
1346
        /* wait until the picture is allocated */
1347
        SDL_LockMutex(is->pictq_mutex);
1348
        while (!vp->allocated && !is->videoq.abort_request) {
1349
            SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1350
        }
1351
        SDL_UnlockMutex(is->pictq_mutex);
1352

    
1353
        if (is->videoq.abort_request)
1354
            return -1;
1355
    }
1356

    
1357
    /* if the frame is not skipped, then display it */
1358
    if (vp->bmp) {
1359
        AVPicture pict;
1360
#if CONFIG_AVFILTER
1361
        if(vp->picref)
1362
            avfilter_unref_pic(vp->picref);
1363
        vp->picref = src_frame->opaque;
1364
#endif
1365

    
1366
        /* get a pointer on the bitmap */
1367
        SDL_LockYUVOverlay (vp->bmp);
1368

    
1369
        dst_pix_fmt = PIX_FMT_YUV420P;
1370
        memset(&pict,0,sizeof(AVPicture));
1371
        pict.data[0] = vp->bmp->pixels[0];
1372
        pict.data[1] = vp->bmp->pixels[2];
1373
        pict.data[2] = vp->bmp->pixels[1];
1374

    
1375
        pict.linesize[0] = vp->bmp->pitches[0];
1376
        pict.linesize[1] = vp->bmp->pitches[2];
1377
        pict.linesize[2] = vp->bmp->pitches[1];
1378

    
1379
#if CONFIG_AVFILTER
1380
        pict_src.data[0] = src_frame->data[0];
1381
        pict_src.data[1] = src_frame->data[1];
1382
        pict_src.data[2] = src_frame->data[2];
1383

    
1384
        pict_src.linesize[0] = src_frame->linesize[0];
1385
        pict_src.linesize[1] = src_frame->linesize[1];
1386
        pict_src.linesize[2] = src_frame->linesize[2];
1387

    
1388
        //FIXME use direct rendering
1389
        av_picture_copy(&pict, &pict_src,
1390
                        vp->pix_fmt, vp->width, vp->height);
1391
#else
1392
        sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
1393
        is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
1394
            vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,
1395
            dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1396
        if (is->img_convert_ctx == NULL) {
1397
            fprintf(stderr, "Cannot initialize the conversion context\n");
1398
            exit(1);
1399
        }
1400
        sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
1401
                  0, vp->height, pict.data, pict.linesize);
1402
#endif
1403
        /* update the bitmap content */
1404
        SDL_UnlockYUVOverlay(vp->bmp);
1405

    
1406
        vp->pts = pts;
1407
        vp->pos = pos;
1408

    
1409
        /* now we can update the picture count */
1410
        if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1411
            is->pictq_windex = 0;
1412
        SDL_LockMutex(is->pictq_mutex);
1413
        is->pictq_size++;
1414
        //We must schedule in a mutex as we must store the timer id before the timer dies or might end up freeing a alraedy freed id
1415
        vp->timer_id= schedule_refresh(is, (int)(compute_frame_delay(vp->pts, is) * 1000 + 0.5));
1416
        SDL_UnlockMutex(is->pictq_mutex);
1417
    }
1418
    return 0;
1419
}
1420

    
1421
/**
1422
 * compute the exact PTS for the picture if it is omitted in the stream
1423
 * @param pts1 the dts of the pkt / pts of the frame
1424
 */
1425
static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
1426
{
1427
    double frame_delay, pts;
1428

    
1429
    pts = pts1;
1430

    
1431
    if (pts != 0) {
1432
        /* update video clock with pts, if present */
1433
        is->video_clock = pts;
1434
    } else {
1435
        pts = is->video_clock;
1436
    }
1437
    /* update video clock for next frame */
1438
    frame_delay = av_q2d(is->video_st->codec->time_base);
1439
    /* for MPEG2, the frame can be repeated, so we update the
1440
       clock accordingly */
1441
    frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1442
    is->video_clock += frame_delay;
1443

    
1444
#if defined(DEBUG_SYNC) && 0
1445
    printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
1446
           av_get_pict_type_char(src_frame->pict_type), pts, pts1);
1447
#endif
1448
    return queue_picture(is, src_frame, pts, pos);
1449
}
1450

    
1451
static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
1452
{
1453
    int len1, got_picture, i;
1454

    
1455
        if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1456
            return -1;
1457

    
1458
        if(pkt->data == flush_pkt.data){
1459
            avcodec_flush_buffers(is->video_st->codec);
1460

    
1461
            SDL_LockMutex(is->pictq_mutex);
1462
            //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
1463
            for(i=0; i<VIDEO_PICTURE_QUEUE_SIZE; i++){
1464
                if(is->pictq[i].timer_id){
1465
                    if(SDL_RemoveTimer(is->pictq[i].timer_id)){
1466
                    is->pictq[i].timer_id=0;
1467
                    schedule_refresh(is, 1);
1468
                    }
1469
                }
1470
            }
1471
            while (is->pictq_size && !is->videoq.abort_request) {
1472
                SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1473
            }
1474
            is->video_current_pos= -1;
1475
            SDL_UnlockMutex(is->pictq_mutex);
1476

    
1477
            is->last_dts_for_fault_detection=
1478
            is->last_pts_for_fault_detection= INT64_MIN;
1479
            is->frame_last_pts= AV_NOPTS_VALUE;
1480
            is->frame_last_delay = 0;
1481
            is->frame_timer = (double)av_gettime() / 1000000.0;
1482

    
1483
            return 0;
1484
        }
1485

    
1486
        /* NOTE: ipts is the PTS of the _first_ picture beginning in
1487
           this packet, if any */
1488
        is->video_st->codec->reordered_opaque= pkt->pts;
1489
        len1 = avcodec_decode_video2(is->video_st->codec,
1490
                                    frame, &got_picture,
1491
                                    pkt);
1492

    
1493
        if (got_picture) {
1494
            if(pkt->dts != AV_NOPTS_VALUE){
1495
                is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection;
1496
                is->last_dts_for_fault_detection= pkt->dts;
1497
            }
1498
            if(frame->reordered_opaque != AV_NOPTS_VALUE){
1499
                is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection;
1500
                is->last_pts_for_fault_detection= frame->reordered_opaque;
1501
            }
1502
        }
1503

    
1504
        if(   (   decoder_reorder_pts==1
1505
               || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
1506
               || pkt->dts == AV_NOPTS_VALUE)
1507
           && frame->reordered_opaque != AV_NOPTS_VALUE)
1508
            *pts= frame->reordered_opaque;
1509
        else if(pkt->dts != AV_NOPTS_VALUE)
1510
            *pts= pkt->dts;
1511
        else
1512
            *pts= 0;
1513

    
1514
//            if (len1 < 0)
1515
//                break;
1516
    if (got_picture)
1517
        return 1;
1518
    return 0;
1519
}
1520

    
1521
#if CONFIG_AVFILTER
1522
typedef struct {
1523
    VideoState *is;
1524
    AVFrame *frame;
1525
} FilterPriv;
1526

    
1527
static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
1528
{
1529
    FilterPriv *priv = ctx->priv;
1530
    if(!opaque) return -1;
1531

    
1532
    priv->is = opaque;
1533
    priv->frame = avcodec_alloc_frame();
1534

    
1535
    return 0;
1536
}
1537

    
1538
static void input_uninit(AVFilterContext *ctx)
1539
{
1540
    FilterPriv *priv = ctx->priv;
1541
    av_free(priv->frame);
1542
}
1543

    
1544
static int input_request_frame(AVFilterLink *link)
1545
{
1546
    FilterPriv *priv = link->src->priv;
1547
    AVFilterPicRef *picref;
1548
    int64_t pts = 0;
1549
    AVPacket pkt;
1550
    int ret;
1551

    
1552
    while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))
1553
        av_free_packet(&pkt);
1554
    if (ret < 0)
1555
        return -1;
1556

    
1557
    /* FIXME: until I figure out how to hook everything up to the codec
1558
     * right, we're just copying the entire frame. */
1559
    picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
1560
    av_picture_copy((AVPicture *)&picref->data, (AVPicture *)priv->frame,
1561
                    picref->pic->format, link->w, link->h);
1562
    av_free_packet(&pkt);
1563

    
1564
    picref->pts = pts;
1565
    picref->pixel_aspect = priv->is->video_st->codec->sample_aspect_ratio;
1566
    avfilter_start_frame(link, avfilter_ref_pic(picref, ~0));
1567
    avfilter_draw_slice(link, 0, link->h, 1);
1568
    avfilter_end_frame(link);
1569
    avfilter_unref_pic(picref);
1570

    
1571
    return 0;
1572
}
1573

    
1574
static int input_query_formats(AVFilterContext *ctx)
1575
{
1576
    FilterPriv *priv = ctx->priv;
1577
    enum PixelFormat pix_fmts[] = {
1578
        priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE
1579
    };
1580

    
1581
    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1582
    return 0;
1583
}
1584

    
1585
static int input_config_props(AVFilterLink *link)
1586
{
1587
    FilterPriv *priv  = link->src->priv;
1588
    AVCodecContext *c = priv->is->video_st->codec;
1589

    
1590
    link->w = c->width;
1591
    link->h = c->height;
1592

    
1593
    return 0;
1594
}
1595

    
1596
static AVFilter input_filter =
1597
{
1598
    .name      = "ffplay_input",
1599

    
1600
    .priv_size = sizeof(FilterPriv),
1601

    
1602
    .init      = input_init,
1603
    .uninit    = input_uninit,
1604

    
1605
    .query_formats = input_query_formats,
1606

    
1607
    .inputs    = (AVFilterPad[]) {{ .name = NULL }},
1608
    .outputs   = (AVFilterPad[]) {{ .name = "default",
1609
                                    .type = CODEC_TYPE_VIDEO,
1610
                                    .request_frame = input_request_frame,
1611
                                    .config_props  = input_config_props, },
1612
                                  { .name = NULL }},
1613
};
1614

    
1615
static void output_end_frame(AVFilterLink *link)
1616
{
1617
}
1618

    
1619
static int output_query_formats(AVFilterContext *ctx)
1620
{
1621
    enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
1622

    
1623
    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1624
    return 0;
1625
}
1626

    
1627
static int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
1628
                                    int64_t *pts)
1629
{
1630
    AVFilterPicRef *pic;
1631

    
1632
    if(avfilter_request_frame(ctx->inputs[0]))
1633
        return -1;
1634
    if(!(pic = ctx->inputs[0]->cur_pic))
1635
        return -1;
1636
    ctx->inputs[0]->cur_pic = NULL;
1637

    
1638
    frame->opaque = pic;
1639
    *pts          = pic->pts;
1640

    
1641
    memcpy(frame->data,     pic->data,     sizeof(frame->data));
1642
    memcpy(frame->linesize, pic->linesize, sizeof(frame->linesize));
1643

    
1644
    return 1;
1645
}
1646

    
1647
static AVFilter output_filter =
1648
{
1649
    .name      = "ffplay_output",
1650

    
1651
    .query_formats = output_query_formats,
1652

    
1653
    .inputs    = (AVFilterPad[]) {{ .name          = "default",
1654
                                    .type          = CODEC_TYPE_VIDEO,
1655
                                    .end_frame     = output_end_frame,
1656
                                    .min_perms     = AV_PERM_READ, },
1657
                                  { .name = NULL }},
1658
    .outputs   = (AVFilterPad[]) {{ .name = NULL }},
1659
};
1660
#endif  /* CONFIG_AVFILTER */
1661

    
1662
static int video_thread(void *arg)
1663
{
1664
    VideoState *is = arg;
1665
    AVFrame *frame= avcodec_alloc_frame();
1666
    int64_t pts_int;
1667
    double pts;
1668
    int ret;
1669

    
1670
#if CONFIG_AVFILTER
1671
    AVFilterContext *filt_src = NULL, *filt_out = NULL;
1672
    AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph));
1673
    graph->scale_sws_opts = av_strdup("sws_flags=bilinear");
1674

    
1675
    if(!(filt_src = avfilter_open(&input_filter,  "src")))   goto the_end;
1676
    if(!(filt_out = avfilter_open(&output_filter, "out")))   goto the_end;
1677

    
1678
    if(avfilter_init_filter(filt_src, NULL, is))             goto the_end;
1679
    if(avfilter_init_filter(filt_out, NULL, frame))          goto the_end;
1680

    
1681

    
1682
    if(vfilters) {
1683
        AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
1684
        AVFilterInOut *inputs  = av_malloc(sizeof(AVFilterInOut));
1685

    
1686
        outputs->name    = av_strdup("in");
1687
        outputs->filter  = filt_src;
1688
        outputs->pad_idx = 0;
1689
        outputs->next    = NULL;
1690

    
1691
        inputs->name    = av_strdup("out");
1692
        inputs->filter  = filt_out;
1693
        inputs->pad_idx = 0;
1694
        inputs->next    = NULL;
1695

    
1696
        if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
1697
            goto the_end;
1698
        av_freep(&vfilters);
1699
    } else {
1700
        if(avfilter_link(filt_src, 0, filt_out, 0) < 0)          goto the_end;
1701
    }
1702
    avfilter_graph_add_filter(graph, filt_src);
1703
    avfilter_graph_add_filter(graph, filt_out);
1704

    
1705
    if(avfilter_graph_check_validity(graph, NULL))           goto the_end;
1706
    if(avfilter_graph_config_formats(graph, NULL))           goto the_end;
1707
    if(avfilter_graph_config_links(graph, NULL))             goto the_end;
1708

    
1709
    is->out_video_filter = filt_out;
1710
#endif
1711

    
1712
    for(;;) {
1713
#if !CONFIG_AVFILTER
1714
        AVPacket pkt;
1715
#endif
1716
        while (is->paused && !is->videoq.abort_request)
1717
            SDL_Delay(10);
1718
#if CONFIG_AVFILTER
1719
        ret = get_filtered_video_frame(filt_out, frame, &pts_int);
1720
#else
1721
        ret = get_video_frame(is, frame, &pts_int, &pkt);
1722
#endif
1723

    
1724
        if (ret < 0) goto the_end;
1725

    
1726
        if (!ret)
1727
            continue;
1728

    
1729
        pts = pts_int*av_q2d(is->video_st->time_base);
1730

    
1731
#if CONFIG_AVFILTER
1732
        ret = output_picture2(is, frame, pts,  -1); /* fixme: unknown pos */
1733
#else
1734
        ret = output_picture2(is, frame, pts,  pkt.pos);
1735
        av_free_packet(&pkt);
1736
#endif
1737
        if (ret < 0)
1738
            goto the_end;
1739

    
1740
        if (step)
1741
            if (cur_stream)
1742
                stream_pause(cur_stream);
1743
    }
1744
 the_end:
1745
#if CONFIG_AVFILTER
1746
    avfilter_graph_destroy(graph);
1747
    av_freep(&graph);
1748
#endif
1749
    av_free(frame);
1750
    return 0;
1751
}
1752

    
1753
static int subtitle_thread(void *arg)
1754
{
1755
    VideoState *is = arg;
1756
    SubPicture *sp;
1757
    AVPacket pkt1, *pkt = &pkt1;
1758
    int len1, got_subtitle;
1759
    double pts;
1760
    int i, j;
1761
    int r, g, b, y, u, v, a;
1762

    
1763
    for(;;) {
1764
        while (is->paused && !is->subtitleq.abort_request) {
1765
            SDL_Delay(10);
1766
        }
1767
        if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1768
            break;
1769

    
1770
        if(pkt->data == flush_pkt.data){
1771
            avcodec_flush_buffers(is->subtitle_st->codec);
1772
            continue;
1773
        }
1774
        SDL_LockMutex(is->subpq_mutex);
1775
        while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1776
               !is->subtitleq.abort_request) {
1777
            SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1778
        }
1779
        SDL_UnlockMutex(is->subpq_mutex);
1780

    
1781
        if (is->subtitleq.abort_request)
1782
            goto the_end;
1783

    
1784
        sp = &is->subpq[is->subpq_windex];
1785

    
1786
       /* NOTE: ipts is the PTS of the _first_ picture beginning in
1787
           this packet, if any */
1788
        pts = 0;
1789
        if (pkt->pts != AV_NOPTS_VALUE)
1790
            pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1791

    
1792
        len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
1793
                                    &sp->sub, &got_subtitle,
1794
                                    pkt);
1795
//            if (len1 < 0)
1796
//                break;
1797
        if (got_subtitle && sp->sub.format == 0) {
1798
            sp->pts = pts;
1799

    
1800
            for (i = 0; i < sp->sub.num_rects; i++)
1801
            {
1802
                for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
1803
                {
1804
                    RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
1805
                    y = RGB_TO_Y_CCIR(r, g, b);
1806
                    u = RGB_TO_U_CCIR(r, g, b, 0);
1807
                    v = RGB_TO_V_CCIR(r, g, b, 0);
1808
                    YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
1809
                }
1810
            }
1811

    
1812
            /* now we can update the picture count */
1813
            if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1814
                is->subpq_windex = 0;
1815
            SDL_LockMutex(is->subpq_mutex);
1816
            is->subpq_size++;
1817
            SDL_UnlockMutex(is->subpq_mutex);
1818
        }
1819
        av_free_packet(pkt);
1820
//        if (step)
1821
//            if (cur_stream)
1822
//                stream_pause(cur_stream);
1823
    }
1824
 the_end:
1825
    return 0;
1826
}
1827

    
1828
/* copy samples for viewing in editor window */
1829
static void update_sample_display(VideoState *is, short *samples, int samples_size)
1830
{
1831
    int size, len, channels;
1832

    
1833
    channels = is->audio_st->codec->channels;
1834

    
1835
    size = samples_size / sizeof(short);
1836
    while (size > 0) {
1837
        len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1838
        if (len > size)
1839
            len = size;
1840
        memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1841
        samples += len;
1842
        is->sample_array_index += len;
1843
        if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1844
            is->sample_array_index = 0;
1845
        size -= len;
1846
    }
1847
}
1848

    
1849
/* return the new audio buffer size (samples can be added or deleted
1850
   to get better sync if video or external master clock) */
1851
static int synchronize_audio(VideoState *is, short *samples,
1852
                             int samples_size1, double pts)
1853
{
1854
    int n, samples_size;
1855
    double ref_clock;
1856

    
1857
    n = 2 * is->audio_st->codec->channels;
1858
    samples_size = samples_size1;
1859

    
1860
    /* if not master, then we try to remove or add samples to correct the clock */
1861
    if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1862
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1863
        double diff, avg_diff;
1864
        int wanted_size, min_size, max_size, nb_samples;
1865

    
1866
        ref_clock = get_master_clock(is);
1867
        diff = get_audio_clock(is) - ref_clock;
1868

    
1869
        if (diff < AV_NOSYNC_THRESHOLD) {
1870
            is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1871
            if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1872
                /* not enough measures to have a correct estimate */
1873
                is->audio_diff_avg_count++;
1874
            } else {
1875
                /* estimate the A-V difference */
1876
                avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1877

    
1878
                if (fabs(avg_diff) >= is->audio_diff_threshold) {
1879
                    wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
1880
                    nb_samples = samples_size / n;
1881

    
1882
                    min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1883
                    max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1884
                    if (wanted_size < min_size)
1885
                        wanted_size = min_size;
1886
                    else if (wanted_size > max_size)
1887
                        wanted_size = max_size;
1888

    
1889
                    /* add or remove samples to correction the synchro */
1890
                    if (wanted_size < samples_size) {
1891
                        /* remove samples */
1892
                        samples_size = wanted_size;
1893
                    } else if (wanted_size > samples_size) {
1894
                        uint8_t *samples_end, *q;
1895
                        int nb;
1896

    
1897
                        /* add samples */
1898
                        nb = (samples_size - wanted_size);
1899
                        samples_end = (uint8_t *)samples + samples_size - n;
1900
                        q = samples_end + n;
1901
                        while (nb > 0) {
1902
                            memcpy(q, samples_end, n);
1903
                            q += n;
1904
                            nb -= n;
1905
                        }
1906
                        samples_size = wanted_size;
1907
                    }
1908
                }
1909
#if 0
1910
                printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1911
                       diff, avg_diff, samples_size - samples_size1,
1912
                       is->audio_clock, is->video_clock, is->audio_diff_threshold);
1913
#endif
1914
            }
1915
        } else {
1916
            /* too big difference : may be initial PTS errors, so
1917
               reset A-V filter */
1918
            is->audio_diff_avg_count = 0;
1919
            is->audio_diff_cum = 0;
1920
        }
1921
    }
1922

    
1923
    return samples_size;
1924
}
1925

    
1926
/* decode one audio frame and returns its uncompressed size */
1927
static int audio_decode_frame(VideoState *is, double *pts_ptr)
1928
{
1929
    AVPacket *pkt_temp = &is->audio_pkt_temp;
1930
    AVPacket *pkt = &is->audio_pkt;
1931
    AVCodecContext *dec= is->audio_st->codec;
1932
    int n, len1, data_size;
1933
    double pts;
1934

    
1935
    for(;;) {
1936
        /* NOTE: the audio packet can contain several frames */
1937
        while (pkt_temp->size > 0) {
1938
            data_size = sizeof(is->audio_buf1);
1939
            len1 = avcodec_decode_audio3(dec,
1940
                                        (int16_t *)is->audio_buf1, &data_size,
1941
                                        pkt_temp);
1942
            if (len1 < 0) {
1943
                /* if error, we skip the frame */
1944
                pkt_temp->size = 0;
1945
                break;
1946
            }
1947

    
1948
            pkt_temp->data += len1;
1949
            pkt_temp->size -= len1;
1950
            if (data_size <= 0)
1951
                continue;
1952

    
1953
            if (dec->sample_fmt != is->audio_src_fmt) {
1954
                if (is->reformat_ctx)
1955
                    av_audio_convert_free(is->reformat_ctx);
1956
                is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
1957
                                                         dec->sample_fmt, 1, NULL, 0);
1958
                if (!is->reformat_ctx) {
1959
                    fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
1960
                        avcodec_get_sample_fmt_name(dec->sample_fmt),
1961
                        avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
1962
                        break;
1963
                }
1964
                is->audio_src_fmt= dec->sample_fmt;
1965
            }
1966

    
1967
            if (is->reformat_ctx) {
1968
                const void *ibuf[6]= {is->audio_buf1};
1969
                void *obuf[6]= {is->audio_buf2};
1970
                int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
1971
                int ostride[6]= {2};
1972
                int len= data_size/istride[0];
1973
                if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
1974
                    printf("av_audio_convert() failed\n");
1975
                    break;
1976
                }
1977
                is->audio_buf= is->audio_buf2;
1978
                /* FIXME: existing code assume that data_size equals framesize*channels*2
1979
                          remove this legacy cruft */
1980
                data_size= len*2;
1981
            }else{
1982
                is->audio_buf= is->audio_buf1;
1983
            }
1984

    
1985
            /* if no pts, then compute it */
1986
            pts = is->audio_clock;
1987
            *pts_ptr = pts;
1988
            n = 2 * dec->channels;
1989
            is->audio_clock += (double)data_size /
1990
                (double)(n * dec->sample_rate);
1991
#if defined(DEBUG_SYNC)
1992
            {
1993
                static double last_clock;
1994
                printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1995
                       is->audio_clock - last_clock,
1996
                       is->audio_clock, pts);
1997
                last_clock = is->audio_clock;
1998
            }
1999
#endif
2000
            return data_size;
2001
        }
2002

    
2003
        /* free the current packet */
2004
        if (pkt->data)
2005
            av_free_packet(pkt);
2006

    
2007
        if (is->paused || is->audioq.abort_request) {
2008
            return -1;
2009
        }
2010

    
2011
        /* read next packet */
2012
        if (packet_queue_get(&is->audioq, pkt, 1) < 0)
2013
            return -1;
2014
        if(pkt->data == flush_pkt.data){
2015
            avcodec_flush_buffers(dec);
2016
            continue;
2017
        }
2018

    
2019
        pkt_temp->data = pkt->data;
2020
        pkt_temp->size = pkt->size;
2021

    
2022
        /* if update the audio clock with the pts */
2023
        if (pkt->pts != AV_NOPTS_VALUE) {
2024
            is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
2025
        }
2026
    }
2027
}
2028

    
2029
/* get the current audio output buffer size, in samples. With SDL, we
2030
   cannot have a precise information */
2031
static int audio_write_get_buf_size(VideoState *is)
2032
{
2033
    return is->audio_buf_size - is->audio_buf_index;
2034
}
2035

    
2036

    
2037
/* prepare a new audio buffer */
2038
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2039
{
2040
    VideoState *is = opaque;
2041
    int audio_size, len1;
2042
    double pts;
2043

    
2044
    audio_callback_time = av_gettime();
2045

    
2046
    while (len > 0) {
2047
        if (is->audio_buf_index >= is->audio_buf_size) {
2048
           audio_size = audio_decode_frame(is, &pts);
2049
           if (audio_size < 0) {
2050
                /* if error, just output silence */
2051
               is->audio_buf = is->audio_buf1;
2052
               is->audio_buf_size = 1024;
2053
               memset(is->audio_buf, 0, is->audio_buf_size);
2054
           } else {
2055
               if (is->show_audio)
2056
                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2057
               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
2058
                                              pts);
2059
               is->audio_buf_size = audio_size;
2060
           }
2061
           is->audio_buf_index = 0;
2062
        }
2063
        len1 = is->audio_buf_size - is->audio_buf_index;
2064
        if (len1 > len)
2065
            len1 = len;
2066
        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2067
        len -= len1;
2068
        stream += len1;
2069
        is->audio_buf_index += len1;
2070
    }
2071
}
2072

    
2073
/* open a given stream. Return 0 if OK */
2074
static int stream_component_open(VideoState *is, int stream_index)
2075
{
2076
    AVFormatContext *ic = is->ic;
2077
    AVCodecContext *avctx;
2078
    AVCodec *codec;
2079
    SDL_AudioSpec wanted_spec, spec;
2080

    
2081
    if (stream_index < 0 || stream_index >= ic->nb_streams)
2082
        return -1;
2083
    avctx = ic->streams[stream_index]->codec;
2084

    
2085
    /* prepare audio output */
2086
    if (avctx->codec_type == CODEC_TYPE_AUDIO) {
2087
        if (avctx->channels > 0) {
2088
            avctx->request_channels = FFMIN(2, avctx->channels);
2089
        } else {
2090
            avctx->request_channels = 2;
2091
        }
2092
    }
2093

    
2094
    codec = avcodec_find_decoder(avctx->codec_id);
2095
    avctx->debug_mv = debug_mv;
2096
    avctx->debug = debug;
2097
    avctx->workaround_bugs = workaround_bugs;
2098
    avctx->lowres = lowres;
2099
    if(lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
2100
    avctx->idct_algo= idct;
2101
    if(fast) avctx->flags2 |= CODEC_FLAG2_FAST;
2102
    avctx->skip_frame= skip_frame;
2103
    avctx->skip_idct= skip_idct;
2104
    avctx->skip_loop_filter= skip_loop_filter;
2105
    avctx->error_recognition= error_recognition;
2106
    avctx->error_concealment= error_concealment;
2107
    avcodec_thread_init(avctx, thread_count);
2108

    
2109
    set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0);
2110

    
2111
    if (!codec ||
2112
        avcodec_open(avctx, codec) < 0)
2113
        return -1;
2114

    
2115
    /* prepare audio output */
2116
    if (avctx->codec_type == CODEC_TYPE_AUDIO) {
2117
        wanted_spec.freq = avctx->sample_rate;
2118
        wanted_spec.format = AUDIO_S16SYS;
2119
        wanted_spec.channels = avctx->channels;
2120
        wanted_spec.silence = 0;
2121
        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
2122
        wanted_spec.callback = sdl_audio_callback;
2123
        wanted_spec.userdata = is;
2124
        if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
2125
            fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
2126
            return -1;
2127
        }
2128
        is->audio_hw_buf_size = spec.size;
2129
        is->audio_src_fmt= SAMPLE_FMT_S16;
2130
    }
2131

    
2132
    ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2133
    switch(avctx->codec_type) {
2134
    case CODEC_TYPE_AUDIO:
2135
        is->audio_stream = stream_index;
2136
        is->audio_st = ic->streams[stream_index];
2137
        is->audio_buf_size = 0;
2138
        is->audio_buf_index = 0;
2139

    
2140
        /* init averaging filter */
2141
        is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2142
        is->audio_diff_avg_count = 0;
2143
        /* since we do not have a precise anough audio fifo fullness,
2144
           we correct audio sync only if larger than this threshold */
2145
        is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
2146

    
2147
        memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
2148
        packet_queue_init(&is->audioq);
2149
        SDL_PauseAudio(0);
2150
        break;
2151
    case CODEC_TYPE_VIDEO:
2152
        is->video_stream = stream_index;
2153
        is->video_st = ic->streams[stream_index];
2154

    
2155
//        is->video_current_pts_time = av_gettime();
2156

    
2157
        packet_queue_init(&is->videoq);
2158
        is->video_tid = SDL_CreateThread(video_thread, is);
2159
        break;
2160
    case CODEC_TYPE_SUBTITLE:
2161
        is->subtitle_stream = stream_index;
2162
        is->subtitle_st = ic->streams[stream_index];
2163
        packet_queue_init(&is->subtitleq);
2164

    
2165
        is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
2166
        break;
2167
    default:
2168
        break;
2169
    }
2170
    return 0;
2171
}
2172

    
2173
static void stream_component_close(VideoState *is, int stream_index)
2174
{
2175
    AVFormatContext *ic = is->ic;
2176
    AVCodecContext *avctx;
2177

    
2178
    if (stream_index < 0 || stream_index >= ic->nb_streams)
2179
        return;
2180
    avctx = ic->streams[stream_index]->codec;
2181

    
2182
    switch(avctx->codec_type) {
2183
    case CODEC_TYPE_AUDIO:
2184
        packet_queue_abort(&is->audioq);
2185

    
2186
        SDL_CloseAudio();
2187

    
2188
        packet_queue_end(&is->audioq);
2189
        if (is->reformat_ctx)
2190
            av_audio_convert_free(is->reformat_ctx);
2191
        is->reformat_ctx = NULL;
2192
        break;
2193
    case CODEC_TYPE_VIDEO:
2194
        packet_queue_abort(&is->videoq);
2195

    
2196
        /* note: we also signal this mutex to make sure we deblock the
2197
           video thread in all cases */
2198
        SDL_LockMutex(is->pictq_mutex);
2199
        SDL_CondSignal(is->pictq_cond);
2200
        SDL_UnlockMutex(is->pictq_mutex);
2201

    
2202
        SDL_WaitThread(is->video_tid, NULL);
2203

    
2204
        packet_queue_end(&is->videoq);
2205
        break;
2206
    case CODEC_TYPE_SUBTITLE:
2207
        packet_queue_abort(&is->subtitleq);
2208

    
2209
        /* note: we also signal this mutex to make sure we deblock the
2210
           video thread in all cases */
2211
        SDL_LockMutex(is->subpq_mutex);
2212
        is->subtitle_stream_changed = 1;
2213

    
2214
        SDL_CondSignal(is->subpq_cond);
2215
        SDL_UnlockMutex(is->subpq_mutex);
2216

    
2217
        SDL_WaitThread(is->subtitle_tid, NULL);
2218

    
2219
        packet_queue_end(&is->subtitleq);
2220
        break;
2221
    default:
2222
        break;
2223
    }
2224

    
2225
    ic->streams[stream_index]->discard = AVDISCARD_ALL;
2226
    avcodec_close(avctx);
2227
    switch(avctx->codec_type) {
2228
    case CODEC_TYPE_AUDIO:
2229
        is->audio_st = NULL;
2230
        is->audio_stream = -1;
2231
        break;
2232
    case CODEC_TYPE_VIDEO:
2233
        is->video_st = NULL;
2234
        is->video_stream = -1;
2235
        break;
2236
    case CODEC_TYPE_SUBTITLE:
2237
        is->subtitle_st = NULL;
2238
        is->subtitle_stream = -1;
2239
        break;
2240
    default:
2241
        break;
2242
    }
2243
}
2244

    
2245
/* since we have only one decoding thread, we can use a global
2246
   variable instead of a thread local variable */
2247
static VideoState *global_video_state;
2248

    
2249
static int decode_interrupt_cb(void)
2250
{
2251
    return (global_video_state && global_video_state->abort_request);
2252
}
2253

    
2254
/* this thread gets the stream from the disk or the network */
2255
static int decode_thread(void *arg)
2256
{
2257
    VideoState *is = arg;
2258
    AVFormatContext *ic;
2259
    int err, i, ret;
2260
    int st_index[CODEC_TYPE_NB];
2261
    int st_count[CODEC_TYPE_NB]={0};
2262
    int st_best_packet_count[CODEC_TYPE_NB];
2263
    AVPacket pkt1, *pkt = &pkt1;
2264
    AVFormatParameters params, *ap = &params;
2265
    int eof=0;
2266

    
2267
    ic = avformat_alloc_context();
2268

    
2269
    memset(st_index, -1, sizeof(st_index));
2270
    memset(st_best_packet_count, -1, sizeof(st_best_packet_count));
2271
    is->video_stream = -1;
2272
    is->audio_stream = -1;
2273
    is->subtitle_stream = -1;
2274

    
2275
    global_video_state = is;
2276
    url_set_interrupt_cb(decode_interrupt_cb);
2277

    
2278
    memset(ap, 0, sizeof(*ap));
2279

    
2280
    ap->prealloced_context = 1;
2281
    ap->width = frame_width;
2282
    ap->height= frame_height;
2283
    ap->time_base= (AVRational){1, 25};
2284
    ap->pix_fmt = frame_pix_fmt;
2285

    
2286
    set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM);
2287

    
2288
    err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
2289
    if (err < 0) {
2290
        print_error(is->filename, err);
2291
        ret = -1;
2292
        goto fail;
2293
    }
2294
    is->ic = ic;
2295

    
2296
    if(genpts)
2297
        ic->flags |= AVFMT_FLAG_GENPTS;
2298

    
2299
    err = av_find_stream_info(ic);
2300
    if (err < 0) {
2301
        fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
2302
        ret = -1;
2303
        goto fail;
2304
    }
2305
    if(ic->pb)
2306
        ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
2307

    
2308
    if(seek_by_bytes<0)
2309
        seek_by_bytes= !!(ic->iformat->flags & AVFMT_TS_DISCONT);
2310

    
2311
    /* if seeking requested, we execute it */
2312
    if (start_time != AV_NOPTS_VALUE) {
2313
        int64_t timestamp;
2314

    
2315
        timestamp = start_time;
2316
        /* add the stream start time */
2317
        if (ic->start_time != AV_NOPTS_VALUE)
2318
            timestamp += ic->start_time;
2319
        ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2320
        if (ret < 0) {
2321
            fprintf(stderr, "%s: could not seek to position %0.3f\n",
2322
                    is->filename, (double)timestamp / AV_TIME_BASE);
2323
        }
2324
    }
2325

    
2326
    for(i = 0; i < ic->nb_streams; i++) {
2327
        AVStream *st= ic->streams[i];
2328
        AVCodecContext *avctx = st->codec;
2329
        ic->streams[i]->discard = AVDISCARD_ALL;
2330
        if(avctx->codec_type >= (unsigned)CODEC_TYPE_NB)
2331
            continue;
2332
        if(st_count[avctx->codec_type]++ != wanted_stream[avctx->codec_type] && wanted_stream[avctx->codec_type] >= 0)
2333
            continue;
2334

    
2335
        if(st_best_packet_count[avctx->codec_type] >= st->codec_info_nb_frames)
2336
            continue;
2337
        st_best_packet_count[avctx->codec_type]= st->codec_info_nb_frames;
2338

    
2339
        switch(avctx->codec_type) {
2340
        case CODEC_TYPE_AUDIO:
2341
            if (!audio_disable)
2342
                st_index[CODEC_TYPE_AUDIO] = i;
2343
            break;
2344
        case CODEC_TYPE_VIDEO:
2345
        case CODEC_TYPE_SUBTITLE:
2346
            if (!video_disable)
2347
                st_index[avctx->codec_type] = i;
2348
            break;
2349
        default:
2350
            break;
2351
        }
2352
    }
2353
    if (show_status) {
2354
        dump_format(ic, 0, is->filename, 0);
2355
    }
2356

    
2357
    /* open the streams */
2358
    if (st_index[CODEC_TYPE_AUDIO] >= 0) {
2359
        stream_component_open(is, st_index[CODEC_TYPE_AUDIO]);
2360
    }
2361

    
2362
    ret=-1;
2363
    if (st_index[CODEC_TYPE_VIDEO] >= 0) {
2364
        ret= stream_component_open(is, st_index[CODEC_TYPE_VIDEO]);
2365
    }
2366
    if(ret<0) {
2367
        /* add the refresh timer to draw the picture */
2368
        schedule_refresh(is, 40);
2369

    
2370
        if (!display_disable)
2371
            is->show_audio = 2;
2372
    }
2373

    
2374
    if (st_index[CODEC_TYPE_SUBTITLE] >= 0) {
2375
        stream_component_open(is, st_index[CODEC_TYPE_SUBTITLE]);
2376
    }
2377

    
2378
    if (is->video_stream < 0 && is->audio_stream < 0) {
2379
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
2380
        ret = -1;
2381
        goto fail;
2382
    }
2383

    
2384
    for(;;) {
2385
        if (is->abort_request)
2386
            break;
2387
        if (is->paused != is->last_paused) {
2388
            is->last_paused = is->paused;
2389
            if (is->paused)
2390
                is->read_pause_return= av_read_pause(ic);
2391
            else
2392
                av_read_play(ic);
2393
        }
2394
#if CONFIG_RTSP_DEMUXER
2395
        if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
2396
            /* wait 10 ms to avoid trying to get another packet */
2397
            /* XXX: horrible */
2398
            SDL_Delay(10);
2399
            continue;
2400
        }
2401
#endif
2402
        if (is->seek_req) {
2403
            int64_t seek_target= is->seek_pos;
2404
            int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2405
            int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2406
//FIXME the +-2 is due to rounding being not done in the correct direction in generation
2407
//      of the seek_pos/seek_rel variables
2408

    
2409
            ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2410
            if (ret < 0) {
2411
                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2412
            }else{
2413
                if (is->audio_stream >= 0) {
2414
                    packet_queue_flush(&is->audioq);
2415
                    packet_queue_put(&is->audioq, &flush_pkt);
2416
                }
2417
                if (is->subtitle_stream >= 0) {
2418
                    packet_queue_flush(&is->subtitleq);
2419
                    packet_queue_put(&is->subtitleq, &flush_pkt);
2420
                }
2421
                if (is->video_stream >= 0) {
2422
                    packet_queue_flush(&is->videoq);
2423
                    packet_queue_put(&is->videoq, &flush_pkt);
2424
                }
2425
            }
2426
            is->seek_req = 0;
2427
            eof= 0;
2428
        }
2429

    
2430
        /* if the queue are full, no need to read more */
2431
        if (   is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2432
            || (   (is->audioq   .size  > MIN_AUDIOQ_SIZE || is->audio_stream<0)
2433
                && (is->videoq   .nb_packets > MIN_FRAMES || is->video_stream<0)
2434
                && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream<0))) {
2435
            /* wait 10 ms */
2436
            SDL_Delay(10);
2437
            continue;
2438
        }
2439
        if(url_feof(ic->pb) || eof) {
2440
            if(is->video_stream >= 0){
2441
                av_init_packet(pkt);
2442
                pkt->data=NULL;
2443
                pkt->size=0;
2444
                pkt->stream_index= is->video_stream;
2445
                packet_queue_put(&is->videoq, pkt);
2446
            }
2447
            SDL_Delay(10);
2448
            if(autoexit && is->audioq.size + is->videoq.size + is->subtitleq.size ==0){
2449
                ret=AVERROR_EOF;
2450
                goto fail;
2451
            }
2452
            continue;
2453
        }
2454
        ret = av_read_frame(ic, pkt);
2455
        if (ret < 0) {
2456
            if (ret == AVERROR_EOF)
2457
                eof=1;
2458
            if (url_ferror(ic->pb))
2459
                break;
2460
            SDL_Delay(100); /* wait for user event */
2461
            continue;
2462
        }
2463
        if (pkt->stream_index == is->audio_stream) {
2464
            packet_queue_put(&is->audioq, pkt);
2465
        } else if (pkt->stream_index == is->video_stream) {
2466
            packet_queue_put(&is->videoq, pkt);
2467
        } else if (pkt->stream_index == is->subtitle_stream) {
2468
            packet_queue_put(&is->subtitleq, pkt);
2469
        } else {
2470
            av_free_packet(pkt);
2471
        }
2472
    }
2473
    /* wait until the end */
2474
    while (!is->abort_request) {
2475
        SDL_Delay(100);
2476
    }
2477

    
2478
    ret = 0;
2479
 fail:
2480
    /* disable interrupting */
2481
    global_video_state = NULL;
2482

    
2483
    /* close each stream */
2484
    if (is->audio_stream >= 0)
2485
        stream_component_close(is, is->audio_stream);
2486
    if (is->video_stream >= 0)
2487
        stream_component_close(is, is->video_stream);
2488
    if (is->subtitle_stream >= 0)
2489
        stream_component_close(is, is->subtitle_stream);
2490
    if (is->ic) {
2491
        av_close_input_file(is->ic);
2492
        is->ic = NULL; /* safety */
2493
    }
2494
    url_set_interrupt_cb(NULL);
2495

    
2496
    if (ret != 0) {
2497
        SDL_Event event;
2498

    
2499
        event.type = FF_QUIT_EVENT;
2500
        event.user.data1 = is;
2501
        SDL_PushEvent(&event);
2502
    }
2503
    return 0;
2504
}
2505

    
2506
static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2507
{
2508
    VideoState *is;
2509

    
2510
    is = av_mallocz(sizeof(VideoState));
2511
    if (!is)
2512
        return NULL;
2513
    av_strlcpy(is->filename, filename, sizeof(is->filename));
2514
    is->iformat = iformat;
2515
    is->ytop = 0;
2516
    is->xleft = 0;
2517

    
2518
    /* start video display */
2519
    is->pictq_mutex = SDL_CreateMutex();
2520
    is->pictq_cond = SDL_CreateCond();
2521

    
2522
    is->subpq_mutex = SDL_CreateMutex();
2523
    is->subpq_cond = SDL_CreateCond();
2524

    
2525
    is->av_sync_type = av_sync_type;
2526
    is->parse_tid = SDL_CreateThread(decode_thread, is);
2527
    if (!is->parse_tid) {
2528
        av_free(is);
2529
        return NULL;
2530
    }
2531
    return is;
2532
}
2533

    
2534
static void stream_close(VideoState *is)
2535
{
2536
    VideoPicture *vp;
2537
    int i;
2538
    /* XXX: use a special url_shutdown call to abort parse cleanly */
2539
    is->abort_request = 1;
2540
    SDL_WaitThread(is->parse_tid, NULL);
2541

    
2542
    /* free all pictures */
2543
    for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2544
        vp = &is->pictq[i];
2545
#if CONFIG_AVFILTER
2546
        if (vp->picref) {
2547
            avfilter_unref_pic(vp->picref);
2548
            vp->picref = NULL;
2549
        }
2550
#endif
2551
        if (vp->bmp) {
2552
            SDL_FreeYUVOverlay(vp->bmp);
2553
            vp->bmp = NULL;
2554
        }
2555
    }
2556
    SDL_DestroyMutex(is->pictq_mutex);
2557
    SDL_DestroyCond(is->pictq_cond);
2558
    SDL_DestroyMutex(is->subpq_mutex);
2559
    SDL_DestroyCond(is->subpq_cond);
2560
#if !CONFIG_AVFILTER
2561
    if (is->img_convert_ctx)
2562
        sws_freeContext(is->img_convert_ctx);
2563
#endif
2564
    av_free(is);
2565
}
2566

    
2567
static void stream_cycle_channel(VideoState *is, int codec_type)
2568
{
2569
    AVFormatContext *ic = is->ic;
2570
    int start_index, stream_index;
2571
    AVStream *st;
2572

    
2573
    if (codec_type == CODEC_TYPE_VIDEO)
2574
        start_index = is->video_stream;
2575
    else if (codec_type == CODEC_TYPE_AUDIO)
2576
        start_index = is->audio_stream;
2577
    else
2578
        start_index = is->subtitle_stream;
2579
    if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
2580
        return;
2581
    stream_index = start_index;
2582
    for(;;) {
2583
        if (++stream_index >= is->ic->nb_streams)
2584
        {
2585
            if (codec_type == CODEC_TYPE_SUBTITLE)
2586
            {
2587
                stream_index = -1;
2588
                goto the_end;
2589
            } else
2590
                stream_index = 0;
2591
        }
2592
        if (stream_index == start_index)
2593
            return;
2594
        st = ic->streams[stream_index];
2595
        if (st->codec->codec_type == codec_type) {
2596
            /* check that parameters are OK */
2597
            switch(codec_type) {
2598
            case CODEC_TYPE_AUDIO:
2599
                if (st->codec->sample_rate != 0 &&
2600
                    st->codec->channels != 0)
2601
                    goto the_end;
2602
                break;
2603
            case CODEC_TYPE_VIDEO:
2604
            case CODEC_TYPE_SUBTITLE:
2605
                goto the_end;
2606
            default:
2607
                break;
2608
            }
2609
        }
2610
    }
2611
 the_end:
2612
    stream_component_close(is, start_index);
2613
    stream_component_open(is, stream_index);
2614
}
2615

    
2616

    
2617
static void toggle_full_screen(void)
2618
{
2619
    is_full_screen = !is_full_screen;
2620
    if (!fs_screen_width) {
2621
        /* use default SDL method */
2622
//        SDL_WM_ToggleFullScreen(screen);
2623
    }
2624
    video_open(cur_stream);
2625
}
2626

    
2627
static void toggle_pause(void)
2628
{
2629
    if (cur_stream)
2630
        stream_pause(cur_stream);
2631
    step = 0;
2632
}
2633

    
2634
static void step_to_next_frame(void)
2635
{
2636
    if (cur_stream) {
2637
        /* if the stream is paused unpause it, then step */
2638
        if (cur_stream->paused)
2639
            stream_pause(cur_stream);
2640
    }
2641
    step = 1;
2642
}
2643

    
2644
static void do_exit(void)
2645
{
2646
    int i;
2647
    if (cur_stream) {
2648
        stream_close(cur_stream);
2649
        cur_stream = NULL;
2650
    }
2651
    for (i = 0; i < CODEC_TYPE_NB; i++)
2652
        av_free(avcodec_opts[i]);
2653
    av_free(avformat_opts);
2654
    av_free(sws_opts);
2655
#if CONFIG_AVFILTER
2656
    avfilter_uninit();
2657
#endif
2658
    if (show_status)
2659
        printf("\n");
2660
    SDL_Quit();
2661
    exit(0);
2662
}
2663

    
2664
static void toggle_audio_display(void)
2665
{
2666
    if (cur_stream) {
2667
        int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
2668
        cur_stream->show_audio = (cur_stream->show_audio + 1) % 3;
2669
        fill_rectangle(screen,
2670
                    cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height,
2671
                    bgcolor);
2672
        SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height);
2673
    }
2674
}
2675

    
2676
/* handle an event sent by the GUI */
2677
static void event_loop(void)
2678
{
2679
    SDL_Event event;
2680
    double incr, pos, frac;
2681

    
2682
    for(;;) {
2683
        double x;
2684
        SDL_WaitEvent(&event);
2685
        switch(event.type) {
2686
        case SDL_KEYDOWN:
2687
            switch(event.key.keysym.sym) {
2688
            case SDLK_ESCAPE:
2689
            case SDLK_q:
2690
                do_exit();
2691
                break;
2692
            case SDLK_f:
2693
                toggle_full_screen();
2694
                break;
2695
            case SDLK_p:
2696
            case SDLK_SPACE:
2697
                toggle_pause();
2698
                break;
2699
            case SDLK_s: //S: Step to next frame
2700
                step_to_next_frame();
2701
                break;
2702
            case SDLK_a:
2703
                if (cur_stream)
2704
                    stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2705
                break;
2706
            case SDLK_v:
2707
                if (cur_stream)
2708
                    stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2709
                break;
2710
            case SDLK_t:
2711
                if (cur_stream)
2712
                    stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2713
                break;
2714
            case SDLK_w:
2715
                toggle_audio_display();
2716
                break;
2717
            case SDLK_LEFT:
2718
                incr = -10.0;
2719
                goto do_seek;
2720
            case SDLK_RIGHT:
2721
                incr = 10.0;
2722
                goto do_seek;
2723
            case SDLK_UP:
2724
                incr = 60.0;
2725
                goto do_seek;
2726
            case SDLK_DOWN:
2727
                incr = -60.0;
2728
            do_seek:
2729
                if (cur_stream) {
2730
                    if (seek_by_bytes) {
2731
                        if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos>=0){
2732
                            pos= cur_stream->video_current_pos;
2733
                        }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){
2734
                            pos= cur_stream->audio_pkt.pos;
2735
                        }else
2736
                            pos = url_ftell(cur_stream->ic->pb);
2737
                        if (cur_stream->ic->bit_rate)
2738
                            incr *= cur_stream->ic->bit_rate / 8.0;
2739
                        else
2740
                            incr *= 180000.0;
2741
                        pos += incr;
2742
                        stream_seek(cur_stream, pos, incr, 1);
2743
                    } else {
2744
                        pos = get_master_clock(cur_stream);
2745
                        pos += incr;
2746
                        stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
2747
                    }
2748
                }
2749
                break;
2750
            default:
2751
                break;
2752
            }
2753
            break;
2754
        case SDL_MOUSEBUTTONDOWN:
2755
        case SDL_MOUSEMOTION:
2756
            if(event.type ==SDL_MOUSEBUTTONDOWN){
2757
                x= event.button.x;
2758
            }else{
2759
                if(event.motion.state != SDL_PRESSED)
2760
                    break;
2761
                x= event.motion.x;
2762
            }
2763
            if (cur_stream) {
2764
                if(seek_by_bytes || cur_stream->ic->duration<=0){
2765
                    uint64_t size=  url_fsize(cur_stream->ic->pb);
2766
                    stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
2767
                }else{
2768
                    int64_t ts;
2769
                    int ns, hh, mm, ss;
2770
                    int tns, thh, tmm, tss;
2771
                    tns = cur_stream->ic->duration/1000000LL;
2772
                    thh = tns/3600;
2773
                    tmm = (tns%3600)/60;
2774
                    tss = (tns%60);
2775
                    frac = x/cur_stream->width;
2776
                    ns = frac*tns;
2777
                    hh = ns/3600;
2778
                    mm = (ns%3600)/60;
2779
                    ss = (ns%60);
2780
                    fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
2781
                            hh, mm, ss, thh, tmm, tss);
2782
                    ts = frac*cur_stream->ic->duration;
2783
                    if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2784
                        ts += cur_stream->ic->start_time;
2785
                    stream_seek(cur_stream, ts, 0, 0);
2786
                }
2787
            }
2788
            break;
2789
        case SDL_VIDEORESIZE:
2790
            if (cur_stream) {
2791
                screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2792
                                          SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2793
                screen_width = cur_stream->width = event.resize.w;
2794
                screen_height= cur_stream->height= event.resize.h;
2795
            }
2796
            break;
2797
        case SDL_QUIT:
2798
        case FF_QUIT_EVENT:
2799
            do_exit();
2800
            break;
2801
        case FF_ALLOC_EVENT:
2802
            video_open(event.user.data1);
2803
            alloc_picture(event.user.data1);
2804
            break;
2805
        case FF_REFRESH_EVENT:
2806
            video_refresh_timer(event.user.data1);
2807
            break;
2808
        default:
2809
            break;
2810
        }
2811
    }
2812
}
2813

    
2814
static void opt_frame_size(const char *arg)
2815
{
2816
    if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
2817
        fprintf(stderr, "Incorrect frame size\n");
2818
        exit(1);
2819
    }
2820
    if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2821
        fprintf(stderr, "Frame size must be a multiple of 2\n");
2822
        exit(1);
2823
    }
2824
}
2825

    
2826
static int opt_width(const char *opt, const char *arg)
2827
{
2828
    screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2829
    return 0;
2830
}
2831

    
2832
static int opt_height(const char *opt, const char *arg)
2833
{
2834
    screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2835
    return 0;
2836
}
2837

    
2838
static void opt_format(const char *arg)
2839
{
2840
    file_iformat = av_find_input_format(arg);
2841
    if (!file_iformat) {
2842
        fprintf(stderr, "Unknown input format: %s\n", arg);
2843
        exit(1);
2844
    }
2845
}
2846

    
2847
static void opt_frame_pix_fmt(const char *arg)
2848
{
2849
    frame_pix_fmt = av_get_pix_fmt(arg);
2850
}
2851

    
2852
static int opt_sync(const char *opt, const char *arg)
2853
{
2854
    if (!strcmp(arg, "audio"))
2855
        av_sync_type = AV_SYNC_AUDIO_MASTER;
2856
    else if (!strcmp(arg, "video"))
2857
        av_sync_type = AV_SYNC_VIDEO_MASTER;
2858
    else if (!strcmp(arg, "ext"))
2859
        av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2860
    else {
2861
        fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
2862
        exit(1);
2863
    }
2864
    return 0;
2865
}
2866

    
2867
static int opt_seek(const char *opt, const char *arg)
2868
{
2869
    start_time = parse_time_or_die(opt, arg, 1);
2870
    return 0;
2871
}
2872

    
2873
static int opt_debug(const char *opt, const char *arg)
2874
{
2875
    av_log_set_level(99);
2876
    debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2877
    return 0;
2878
}
2879

    
2880
static int opt_vismv(const char *opt, const char *arg)
2881
{
2882
    debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2883
    return 0;
2884
}
2885

    
2886
static int opt_thread_count(const char *opt, const char *arg)
2887
{
2888
    thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2889
#if !HAVE_THREADS
2890
    fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2891
#endif
2892
    return 0;
2893
}
2894

    
2895
static const OptionDef options[] = {
2896
#include "cmdutils_common_opts.h"
2897
    { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2898
    { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
2899
    { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
2900
    { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
2901
    { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2902
    { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
2903
    { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[CODEC_TYPE_AUDIO]}, "select desired audio stream", "stream_number" },
2904
    { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[CODEC_TYPE_VIDEO]}, "select desired video stream", "stream_number" },
2905
    { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[CODEC_TYPE_SUBTITLE]}, "select desired subtitle stream", "stream_number" },
2906
    { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
2907
    { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto", "val" },
2908
    { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2909
    { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
2910
    { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
2911
    { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
2912
    { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
2913
    { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
2914
    { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
2915
    { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
2916
    { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
2917
    { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts 0=off 1=on -1=auto", ""},
2918
    { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
2919
    { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2920
    { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2921
    { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
2922
    { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo",  "algo" },
2923
    { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)",  "threshold" },
2924
    { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options",  "bit_mask" },
2925
    { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2926
    { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
2927
    { "autoexit", OPT_BOOL | OPT_EXPERT, {(void*)&autoexit}, "exit at the end", "" },
2928
#if CONFIG_AVFILTER
2929
    { "vfilters", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
2930
#endif
2931
    { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
2932
    { NULL, },
2933
};
2934

    
2935
static void show_usage(void)
2936
{
2937
    printf("Simple media player\n");
2938
    printf("usage: ffplay [options] input_file\n");
2939
    printf("\n");
2940
}
2941

    
2942
static void show_help(void)
2943
{
2944
    show_usage();
2945
    show_help_options(options, "Main options:\n",
2946
                      OPT_EXPERT, 0);
2947
    show_help_options(options, "\nAdvanced options:\n",
2948
                      OPT_EXPERT, OPT_EXPERT);
2949
    printf("\nWhile playing:\n"
2950
           "q, ESC              quit\n"
2951
           "f                   toggle full screen\n"
2952
           "p, SPC              pause\n"
2953
           "a                   cycle audio channel\n"
2954
           "v                   cycle video channel\n"
2955
           "t                   cycle subtitle channel\n"
2956
           "w                   show audio waves\n"
2957
           "left/right          seek backward/forward 10 seconds\n"
2958
           "down/up             seek backward/forward 1 minute\n"
2959
           "mouse click         seek to percentage in file corresponding to fraction of width\n"
2960
           );
2961
}
2962

    
2963
static void opt_input_file(const char *filename)
2964
{
2965
    if (input_filename) {
2966
        fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
2967
                filename, input_filename);
2968
        exit(1);
2969
    }
2970
    if (!strcmp(filename, "-"))
2971
        filename = "pipe:";
2972
    input_filename = filename;
2973
}
2974

    
2975
/* Called from the main */
2976
int main(int argc, char **argv)
2977
{
2978
    int flags, i;
2979

    
2980
    /* register all codecs, demux and protocols */
2981
    avcodec_register_all();
2982
    avdevice_register_all();
2983
#if CONFIG_AVFILTER
2984
    avfilter_register_all();
2985
#endif
2986
    av_register_all();
2987

    
2988
    for(i=0; i<CODEC_TYPE_NB; i++){
2989
        avcodec_opts[i]= avcodec_alloc_context2(i);
2990
    }
2991
    avformat_opts = avformat_alloc_context();
2992
#if !CONFIG_AVFILTER
2993
    sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
2994
#endif
2995

    
2996
    show_banner();
2997

    
2998
    parse_options(argc, argv, options, opt_input_file);
2999

    
3000
    if (!input_filename) {
3001
        show_usage();
3002
        fprintf(stderr, "An input file must be specified\n");
3003
        fprintf(stderr, "Use -h to get full help or, even better, run 'man ffplay'\n");
3004
        exit(1);
3005
    }
3006

    
3007
    if (display_disable) {
3008
        video_disable = 1;
3009
    }
3010
    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3011
#if !defined(__MINGW32__) && !defined(__APPLE__)
3012
    flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
3013
#endif
3014
    if (SDL_Init (flags)) {
3015
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
3016
        exit(1);
3017
    }
3018

    
3019
    if (!display_disable) {
3020
#if HAVE_SDL_VIDEO_SIZE
3021
        const SDL_VideoInfo *vi = SDL_GetVideoInfo();
3022
        fs_screen_width = vi->current_w;
3023
        fs_screen_height = vi->current_h;
3024
#endif
3025
    }
3026

    
3027
    SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
3028
    SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3029
    SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3030

    
3031
    av_init_packet(&flush_pkt);
3032
    flush_pkt.data= "FLUSH";
3033

    
3034
    cur_stream = stream_open(input_filename, file_iformat);
3035

    
3036
    event_loop();
3037

    
3038
    /* never returns */
3039

    
3040
    return 0;
3041
}