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

22
#include "config.h"
23
#include <inttypes.h>
24 25
#include <math.h>
#include <limits.h>
26 27
#include <stdint.h>

28
#include "libavutil/avstring.h"
29
#include "libavutil/colorspace.h"
30
#include "libavutil/mathematics.h"
31
#include "libavutil/pixdesc.h"
32
#include "libavutil/imgutils.h"
33
#include "libavutil/dict.h"
34 35
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
36
#include "libavutil/time.h"
37 38 39
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
40
#include "libavresample/avresample.h"
41
#include "libavutil/opt.h"
42
#include "libavcodec/avfft.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
43

44 45
#if CONFIG_AVFILTER
# include "libavfilter/avfilter.h"
46
# include "libavfilter/buffersink.h"
47
# include "libavfilter/buffersrc.h"
48 49
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
50 51 52 53 54
#include "cmdutils.h"

#include <SDL.h>
#include <SDL_thread.h>

55
#ifdef __MINGW32__
56 57 58
#undef main /* We don't want SDL to override our main() */
#endif

Michael Niedermayer's avatar
Michael Niedermayer committed
59 60
#include <assert.h>

Anton Khirnov's avatar
Anton Khirnov committed
61
const char program_name[] = "avplay";
62
const int program_birth_year = 2003;
63

64 65 66
#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
#define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
#define MIN_FRAMES 5
Fabrice Bellard's avatar
Fabrice Bellard committed
67

68 69 70 71 72
/* SDL audio buffer size, in samples. Should be small to have precise
   A/V sync as SDL does not have hardware buffer fullness info. */
#define SDL_AUDIO_BUFFER_SIZE 1024

/* no AV sync correction is done if below the AV sync threshold */
73
#define AV_SYNC_THRESHOLD 0.01
74 75 76
/* no AV correction is done if too big error */
#define AV_NOSYNC_THRESHOLD 10.0

Michael Niedermayer's avatar
Michael Niedermayer committed
77 78
#define FRAME_SKIP_FACTOR 0.05

79 80 81 82 83 84
/* maximum audio speed change to get correct sync */
#define SAMPLE_CORRECTION_PERCENT_MAX 10

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

Fabrice Bellard's avatar
Fabrice Bellard committed
85
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
Aneesh Dogra's avatar
Aneesh Dogra committed
86
#define SAMPLE_ARRAY_SIZE (2 * 65536)
Fabrice Bellard's avatar
Fabrice Bellard committed
87

88
static int64_t sws_flags = SWS_BICUBIC;
89

Fabrice Bellard's avatar
Fabrice Bellard committed
90 91 92 93 94 95 96 97 98
typedef struct PacketQueue {
    AVPacketList *first_pkt, *last_pkt;
    int nb_packets;
    int size;
    int abort_request;
    SDL_mutex *mutex;
    SDL_cond *cond;
} PacketQueue;

99
#define VIDEO_PICTURE_QUEUE_SIZE 2
100
#define SUBPICTURE_QUEUE_SIZE 4
Fabrice Bellard's avatar
Fabrice Bellard committed
101 102

typedef struct VideoPicture {
103
    double pts;             // presentation timestamp for this picture
104
    double target_clock;    // av_gettime_relative() time at which this should be displayed ideally
105
    int64_t pos;            // byte position in file
Fabrice Bellard's avatar
Fabrice Bellard committed
106 107 108
    SDL_Overlay *bmp;
    int width, height; /* source height & width */
    int allocated;
109
    int reallocate;
110
    enum AVPixelFormat pix_fmt;
111

112
    AVRational sar;
Fabrice Bellard's avatar
Fabrice Bellard committed
113 114
} VideoPicture;

115 116 117 118 119
typedef struct SubPicture {
    double pts; /* presentation time stamp for this picture */
    AVSubtitle sub;
} SubPicture;

Fabrice Bellard's avatar
Fabrice Bellard committed
120 121 122
enum {
    AV_SYNC_AUDIO_MASTER, /* default choice */
    AV_SYNC_VIDEO_MASTER,
123
    AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
Fabrice Bellard's avatar
Fabrice Bellard committed
124 125 126 127 128
};

typedef struct VideoState {
    SDL_Thread *parse_tid;
    SDL_Thread *video_tid;
Michael Niedermayer's avatar
Michael Niedermayer committed
129
    SDL_Thread *refresh_tid;
130
    AVInputFormat *iformat;
Fabrice Bellard's avatar
Fabrice Bellard committed
131 132 133
    int no_background;
    int abort_request;
    int paused;
134
    int last_paused;
Fabrice Bellard's avatar
Fabrice Bellard committed
135
    int seek_req;
136
    int seek_flags;
Fabrice Bellard's avatar
Fabrice Bellard committed
137
    int64_t seek_pos;
138
    int64_t seek_rel;
139
    int read_pause_return;
Fabrice Bellard's avatar
Fabrice Bellard committed
140 141 142
    AVFormatContext *ic;

    int audio_stream;
143

Fabrice Bellard's avatar
Fabrice Bellard committed
144
    int av_sync_type;
145 146
    double external_clock; /* external clock base */
    int64_t external_clock_time;
147

148 149 150 151 152
    double audio_clock;
    double audio_diff_cum; /* used for AV difference average computation */
    double audio_diff_avg_coef;
    double audio_diff_threshold;
    int audio_diff_avg_count;
Fabrice Bellard's avatar
Fabrice Bellard committed
153 154 155
    AVStream *audio_st;
    PacketQueue audioq;
    int audio_hw_buf_size;
156
    uint8_t silence_buf[SDL_AUDIO_BUFFER_SIZE];
157
    uint8_t *audio_buf;
158
    uint8_t *audio_buf1;
159
    unsigned int audio_buf_size; /* in bytes */
Fabrice Bellard's avatar
Fabrice Bellard committed
160
    int audio_buf_index; /* in bytes */
161
    AVPacket audio_pkt_temp;
Fabrice Bellard's avatar
Fabrice Bellard committed
162
    AVPacket audio_pkt;
163 164 165
    enum AVSampleFormat sdl_sample_fmt;
    uint64_t sdl_channel_layout;
    int sdl_channels;
166
    int sdl_sample_rate;
167 168
    enum AVSampleFormat resample_sample_fmt;
    uint64_t resample_channel_layout;
169
    int resample_sample_rate;
170
    AVAudioResampleContext *avr;
171
    AVFrame *frame;
172

Fabrice Bellard's avatar
Fabrice Bellard committed
173 174 175
    int show_audio; /* if true, display audio samples */
    int16_t sample_array[SAMPLE_ARRAY_SIZE];
    int sample_array_index;
176
    int last_i_start;
177
    RDFTContext *rdft;
178
    int rdft_bits;
Måns Rullgård's avatar
Måns Rullgård committed
179
    FFTSample *rdft_data;
180
    int xpos;
181

182 183 184 185 186 187 188 189 190
    SDL_Thread *subtitle_tid;
    int subtitle_stream;
    int subtitle_stream_changed;
    AVStream *subtitle_st;
    PacketQueue subtitleq;
    SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
    int subpq_size, subpq_rindex, subpq_windex;
    SDL_mutex *subpq_mutex;
    SDL_cond *subpq_cond;
191

192 193 194
    double frame_timer;
    double frame_last_pts;
    double frame_last_delay;
195
    double video_clock;             // pts of last decoded frame / predicted pts of next decoded frame
Fabrice Bellard's avatar
Fabrice Bellard committed
196 197 198
    int video_stream;
    AVStream *video_st;
    PacketQueue videoq;
199
    double video_current_pts;       // current displayed pts (different from video_clock if frame fifos are used)
200
    double video_current_pts_drift; // video_current_pts - time (av_gettime_relative) at which we updated video_current_pts - used to have running video pts
201
    int64_t video_current_pos;      // current displayed file pos
Fabrice Bellard's avatar
Fabrice Bellard committed
202 203 204 205
    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
    int pictq_size, pictq_rindex, pictq_windex;
    SDL_mutex *pictq_mutex;
    SDL_cond *pictq_cond;
206
#if !CONFIG_AVFILTER
207
    struct SwsContext *img_convert_ctx;
208
#endif
209

Fabrice Bellard's avatar
Fabrice Bellard committed
210 211 212
    //    QETimer *video_timer;
    char filename[1024];
    int width, height, xleft, ytop;
213

214
    PtsCorrectionContext pts_ctx;
215

216
#if CONFIG_AVFILTER
217 218
    AVFilterContext *in_video_filter;   // the first filter in the video chain
    AVFilterContext *out_video_filter;  // the last filter in the video chain
219
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
220 221 222 223

    float skip_frames;
    float skip_frames_index;
    int refresh;
Fabrice Bellard's avatar
Fabrice Bellard committed
224 225 226 227 228
} VideoState;

/* options specified by the user */
static AVInputFormat *file_iformat;
static const char *input_filename;
229
static const char *window_title;
Fabrice Bellard's avatar
Fabrice Bellard committed
230 231
static int fs_screen_width;
static int fs_screen_height;
Aneesh Dogra's avatar
Aneesh Dogra committed
232
static int screen_width  = 0;
233
static int screen_height = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
234 235
static int audio_disable;
static int video_disable;
Aneesh Dogra's avatar
Aneesh Dogra committed
236 237 238 239
static int wanted_stream[AVMEDIA_TYPE_NB] = {
    [AVMEDIA_TYPE_AUDIO]    = -1,
    [AVMEDIA_TYPE_VIDEO]    = -1,
    [AVMEDIA_TYPE_SUBTITLE] = -1,
240
};
Aneesh Dogra's avatar
Aneesh Dogra committed
241
static int seek_by_bytes = -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
242
static int display_disable;
243
static int show_status = 1;
244
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
Fabrice Bellard's avatar
Fabrice Bellard committed
245
static int64_t start_time = AV_NOPTS_VALUE;
Robert Krüger's avatar
Robert Krüger committed
246
static int64_t duration = AV_NOPTS_VALUE;
247
static int step = 0;
Michael Niedermayer's avatar
-bug  
Michael Niedermayer committed
248
static int workaround_bugs = 1;
249
static int fast = 0;
250
static int genpts = 0;
251
static int idct = FF_IDCT_AUTO;
Aneesh Dogra's avatar
Aneesh Dogra committed
252 253 254
static enum AVDiscard skip_frame       = AVDISCARD_DEFAULT;
static enum AVDiscard skip_idct        = AVDISCARD_DEFAULT;
static enum AVDiscard skip_loop_filter = AVDISCARD_DEFAULT;
255
static int error_concealment = 3;
Aneesh Dogra's avatar
Aneesh Dogra committed
256
static int decoder_reorder_pts = -1;
257
static int noautoexit;
258 259
static int exit_on_keydown;
static int exit_on_mousedown;
Aneesh Dogra's avatar
Aneesh Dogra committed
260 261
static int loop = 1;
static int framedrop = 1;
262
static int infinite_buffer = 0;
263

Aneesh Dogra's avatar
Aneesh Dogra committed
264
static int rdftspeed = 20;
265 266 267
#if CONFIG_AVFILTER
static char *vfilters = NULL;
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
268 269 270 271

/* current context */
static int is_full_screen;
static VideoState *cur_stream;
272
static int64_t audio_callback_time;
Fabrice Bellard's avatar
Fabrice Bellard committed
273

274
static AVPacket flush_pkt;
275

Fabrice Bellard's avatar
Fabrice Bellard committed
276 277
#define FF_ALLOC_EVENT   (SDL_USEREVENT)
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
278
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
Fabrice Bellard's avatar
Fabrice Bellard committed
279

280
static SDL_Surface *screen;
Fabrice Bellard's avatar
Fabrice Bellard committed
281

282 283
static int packet_queue_put(PacketQueue *q, AVPacket *pkt);

Fabrice Bellard's avatar
Fabrice Bellard committed
284 285 286 287 288 289
/* packet queue handling */
static void packet_queue_init(PacketQueue *q)
{
    memset(q, 0, sizeof(PacketQueue));
    q->mutex = SDL_CreateMutex();
    q->cond = SDL_CreateCond();
290
    packet_queue_put(q, &flush_pkt);
Fabrice Bellard's avatar
Fabrice Bellard committed
291 292
}

Fabrice Bellard's avatar
Fabrice Bellard committed
293
static void packet_queue_flush(PacketQueue *q)
Fabrice Bellard's avatar
Fabrice Bellard committed
294 295 296
{
    AVPacketList *pkt, *pkt1;

297
    SDL_LockMutex(q->mutex);
Aneesh Dogra's avatar
Aneesh Dogra committed
298
    for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
Fabrice Bellard's avatar
Fabrice Bellard committed
299 300
        pkt1 = pkt->next;
        av_free_packet(&pkt->pkt);
301
        av_freep(&pkt);
Fabrice Bellard's avatar
Fabrice Bellard committed
302
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
303 304 305 306
    q->last_pkt = NULL;
    q->first_pkt = NULL;
    q->nb_packets = 0;
    q->size = 0;
307
    SDL_UnlockMutex(q->mutex);
Fabrice Bellard's avatar
Fabrice Bellard committed
308 309 310 311 312
}

static void packet_queue_end(PacketQueue *q)
{
    packet_queue_flush(q);
Fabrice Bellard's avatar
Fabrice Bellard committed
313 314 315 316 317 318 319 320
    SDL_DestroyMutex(q->mutex);
    SDL_DestroyCond(q->cond);
}

static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
{
    AVPacketList *pkt1;

Fabrice Bellard's avatar
Fabrice Bellard committed
321
    /* duplicate the packet */
Aneesh Dogra's avatar
Aneesh Dogra committed
322
    if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
323
        return -1;
324

Fabrice Bellard's avatar
Fabrice Bellard committed
325 326 327 328 329 330
    pkt1 = av_malloc(sizeof(AVPacketList));
    if (!pkt1)
        return -1;
    pkt1->pkt = *pkt;
    pkt1->next = NULL;

Fabrice Bellard's avatar
Fabrice Bellard committed
331

Fabrice Bellard's avatar
Fabrice Bellard committed
332 333 334 335 336 337 338 339 340
    SDL_LockMutex(q->mutex);

    if (!q->last_pkt)

        q->first_pkt = pkt1;
    else
        q->last_pkt->next = pkt1;
    q->last_pkt = pkt1;
    q->nb_packets++;
341
    q->size += pkt1->pkt.size + sizeof(*pkt1);
Fabrice Bellard's avatar
Fabrice Bellard committed
342 343 344 345 346 347 348 349 350 351 352 353
    /* XXX: should duplicate packet data in DV case */
    SDL_CondSignal(q->cond);

    SDL_UnlockMutex(q->mutex);
    return 0;
}

static void packet_queue_abort(PacketQueue *q)
{
    SDL_LockMutex(q->mutex);

    q->abort_request = 1;
354

Fabrice Bellard's avatar
Fabrice Bellard committed
355 356 357 358 359 360 361 362 363 364 365 366 367
    SDL_CondSignal(q->cond);

    SDL_UnlockMutex(q->mutex);
}

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

    SDL_LockMutex(q->mutex);

Aneesh Dogra's avatar
Aneesh Dogra committed
368
    for (;;) {
Fabrice Bellard's avatar
Fabrice Bellard committed
369 370 371 372
        if (q->abort_request) {
            ret = -1;
            break;
        }
373

Fabrice Bellard's avatar
Fabrice Bellard committed
374 375 376 377 378 379
        pkt1 = q->first_pkt;
        if (pkt1) {
            q->first_pkt = pkt1->next;
            if (!q->first_pkt)
                q->last_pkt = NULL;
            q->nb_packets--;
380
            q->size -= pkt1->pkt.size + sizeof(*pkt1);
Fabrice Bellard's avatar
Fabrice Bellard committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
            *pkt = pkt1->pkt;
            av_free(pkt1);
            ret = 1;
            break;
        } else if (!block) {
            ret = 0;
            break;
        } else {
            SDL_CondWait(q->cond, q->mutex);
        }
    }
    SDL_UnlockMutex(q->mutex);
    return ret;
}

396
static inline void fill_rectangle(SDL_Surface *screen,
Fabrice Bellard's avatar
Fabrice Bellard committed
397 398 399 400 401 402 403 404 405 406
                                  int x, int y, int w, int h, int color)
{
    SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;
    SDL_FillRect(screen, &rect, color);
}

407 408 409 410 411 412 413 414 415 416 417 418 419 420
#define ALPHA_BLEND(a, oldp, newp, s)\
((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))

#define RGBA_IN(r, g, b, a, s)\
{\
    unsigned int v = ((const uint32_t *)(s))[0];\
    a = (v >> 24) & 0xff;\
    r = (v >> 16) & 0xff;\
    g = (v >> 8) & 0xff;\
    b = v & 0xff;\
}

#define YUVA_IN(y, u, v, a, s, pal)\
{\
421
    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
422 423 424 425 426 427 428 429 430 431 432 433 434 435
    a = (val >> 24) & 0xff;\
    y = (val >> 16) & 0xff;\
    u = (val >> 8) & 0xff;\
    v = val & 0xff;\
}

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


#define BPP 1

436
static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
437 438 439 440 441 442
{
    int wrap, wrap3, width2, skip2;
    int y, u, v, a, u1, v1, a1, w, h;
    uint8_t *lum, *cb, *cr;
    const uint8_t *p;
    const uint32_t *pal;
443 444
    int dstx, dsty, dstw, dsth;

445 446 447 448
    dstw = av_clip(rect->w, 0, imgw);
    dsth = av_clip(rect->h, 0, imgh);
    dstx = av_clip(rect->x, 0, imgw - dstw);
    dsty = av_clip(rect->y, 0, imgh - dsth);
449
    lum = dst->data[0] + dsty * dst->linesize[0];
Aneesh Dogra's avatar
Aneesh Dogra committed
450 451
    cb  = dst->data[1] + (dsty >> 1) * dst->linesize[1];
    cr  = dst->data[2] + (dsty >> 1) * dst->linesize[2];
452

453
    width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
454
    skip2 = dstx >> 1;
455
    wrap = dst->linesize[0];
456 457 458
    wrap3 = rect->pict.linesize[0];
    p = rect->pict.data[0];
    pal = (const uint32_t *)rect->pict.data[1];  /* Now in YCrCb! */
459

460 461
    if (dsty & 1) {
        lum += dstx;
462 463
        cb += skip2;
        cr += skip2;
464

465
        if (dstx & 1) {
466 467 468 469 470 471 472 473 474
            YUVA_IN(y, u, v, a, p, pal);
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
            cb++;
            cr++;
            lum++;
            p += BPP;
        }
Aneesh Dogra's avatar
Aneesh Dogra committed
475
        for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
            YUVA_IN(y, u, v, a, p, pal);
            u1 = u;
            v1 = v;
            a1 = a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);

            YUVA_IN(y, u, v, a, p + BPP, pal);
            u1 += u;
            v1 += v;
            a1 += a;
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
            cb++;
            cr++;
            p += 2 * BPP;
            lum += 2;
        }
        if (w) {
            YUVA_IN(y, u, v, a, p, pal);
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
499 500
            p++;
            lum++;
501
        }
502 503
        p += wrap3 - dstw * BPP;
        lum += wrap - dstw - dstx;
504 505 506
        cb += dst->linesize[1] - width2 - skip2;
        cr += dst->linesize[2] - width2 - skip2;
    }
Aneesh Dogra's avatar
Aneesh Dogra committed
507
    for (h = dsth - (dsty & 1); h >= 2; h -= 2) {
508
        lum += dstx;
509 510
        cb += skip2;
        cr += skip2;
511

512
        if (dstx & 1) {
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
            YUVA_IN(y, u, v, a, p, pal);
            u1 = u;
            v1 = v;
            a1 = a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            p += wrap3;
            lum += wrap;
            YUVA_IN(y, u, v, a, p, pal);
            u1 += u;
            v1 += v;
            a1 += a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
            cb++;
            cr++;
            p += -wrap3 + BPP;
            lum += -wrap + 1;
        }
Aneesh Dogra's avatar
Aneesh Dogra committed
532
        for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
533 534 535 536 537 538
            YUVA_IN(y, u, v, a, p, pal);
            u1 = u;
            v1 = v;
            a1 = a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);

539
            YUVA_IN(y, u, v, a, p + BPP, pal);
540 541 542 543 544 545 546 547 548 549 550 551 552
            u1 += u;
            v1 += v;
            a1 += a;
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
            p += wrap3;
            lum += wrap;

            YUVA_IN(y, u, v, a, p, pal);
            u1 += u;
            v1 += v;
            a1 += a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);

553
            YUVA_IN(y, u, v, a, p + BPP, pal);
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
            u1 += u;
            v1 += v;
            a1 += a;
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);

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

            cb++;
            cr++;
            p += -wrap3 + 2 * BPP;
            lum += -wrap + 2;
        }
        if (w) {
            YUVA_IN(y, u, v, a, p, pal);
            u1 = u;
            v1 = v;
            a1 = a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            p += wrap3;
            lum += wrap;
            YUVA_IN(y, u, v, a, p, pal);
            u1 += u;
            v1 += v;
            a1 += a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
            cb++;
            cr++;
            p += -wrap3 + BPP;
            lum += -wrap + 1;
        }
587 588
        p += wrap3 + (wrap3 - dstw * BPP);
        lum += wrap + (wrap - dstw - dstx);
589 590 591 592 593
        cb += dst->linesize[1] - width2 - skip2;
        cr += dst->linesize[2] - width2 - skip2;
    }
    /* handle odd height */
    if (h) {
594
        lum += dstx;
595 596
        cb += skip2;
        cr += skip2;
597

598
        if (dstx & 1) {
599 600 601 602 603 604 605 606 607
            YUVA_IN(y, u, v, a, p, pal);
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
            cb++;
            cr++;
            lum++;
            p += BPP;
        }
Aneesh Dogra's avatar
Aneesh Dogra committed
608
        for (w = dstw - (dstx & 1); w >= 2; w -= 2) {
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
            YUVA_IN(y, u, v, a, p, pal);
            u1 = u;
            v1 = v;
            a1 = a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);

            YUVA_IN(y, u, v, a, p + BPP, pal);
            u1 += u;
            v1 += v;
            a1 += a;
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
            cb++;
            cr++;
            p += 2 * BPP;
            lum += 2;
        }
        if (w) {
            YUVA_IN(y, u, v, a, p, pal);
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
        }
    }
}

static void free_subpicture(SubPicture *sp)
{
638
    avsubtitle_free(&sp->sub);
639 640
}

Fabrice Bellard's avatar
Fabrice Bellard committed
641 642 643
static void video_image_display(VideoState *is)
{
    VideoPicture *vp;
644 645
    SubPicture *sp;
    AVPicture pict;
Fabrice Bellard's avatar
Fabrice Bellard committed
646 647 648
    float aspect_ratio;
    int width, height, x, y;
    SDL_Rect rect;
649
    int i;
Fabrice Bellard's avatar
Fabrice Bellard committed
650 651 652

    vp = &is->pictq[is->pictq_rindex];
    if (vp->bmp) {
653
#if CONFIG_AVFILTER
654
         if (!vp->sar.num)
655 656
             aspect_ratio = 0;
         else
657
             aspect_ratio = av_q2d(vp->sar);
658 659
#else

Fabrice Bellard's avatar
Fabrice Bellard committed
660
        /* XXX: use variable in the frame */
661 662 663 664
        if (is->video_st->sample_aspect_ratio.num)
            aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
        else if (is->video_st->codec->sample_aspect_ratio.num)
            aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
Fabrice Bellard's avatar
Fabrice Bellard committed
665
        else
666
            aspect_ratio = 0;
667
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
668
        if (aspect_ratio <= 0.0)
669
            aspect_ratio = 1.0;
670
        aspect_ratio *= (float)vp->width / (float)vp->height;
Fabrice Bellard's avatar
Fabrice Bellard committed
671

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
        if (is->subtitle_st)
        {
            if (is->subpq_size > 0)
            {
                sp = &is->subpq[is->subpq_rindex];

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

                    pict.data[0] = vp->bmp->pixels[0];
                    pict.data[1] = vp->bmp->pixels[2];
                    pict.data[2] = vp->bmp->pixels[1];

                    pict.linesize[0] = vp->bmp->pitches[0];
                    pict.linesize[1] = vp->bmp->pitches[2];
                    pict.linesize[2] = vp->bmp->pitches[1];

                    for (i = 0; i < sp->sub.num_rects; i++)
691
                        blend_subrect(&pict, sp->sub.rects[i],
692
                                      vp->bmp->w, vp->bmp->h);
693 694 695 696 697 698 699

                    SDL_UnlockYUVOverlay (vp->bmp);
                }
            }
        }


Fabrice Bellard's avatar
Fabrice Bellard committed
700 701
        /* XXX: we suppose the screen has a 1.0 pixel ratio */
        height = is->height;
702
        width = ((int)rint(height * aspect_ratio)) & ~1;
Fabrice Bellard's avatar
Fabrice Bellard committed
703 704
        if (width > is->width) {
            width = is->width;
705
            height = ((int)rint(width / aspect_ratio)) & ~1;
Fabrice Bellard's avatar
Fabrice Bellard committed
706 707 708
        }
        x = (is->width - width) / 2;
        y = (is->height - height) / 2;
709
        is->no_background = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
710
        rect.x = is->xleft + x;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
711
        rect.y = is->ytop  + y;
Fabrice Bellard's avatar
Fabrice Bellard committed
712 713 714 715 716 717
        rect.w = width;
        rect.h = height;
        SDL_DisplayYUVOverlay(vp->bmp, &rect);
    }
}

718 719 720 721 722 723 724
/* get the current audio output buffer size, in samples. With SDL, we
   cannot have a precise information */
static int audio_write_get_buf_size(VideoState *is)
{
    return is->audio_buf_size - is->audio_buf_index;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
725 726 727
static inline int compute_mod(int a, int b)
{
    a = a % b;
728
    if (a >= 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
729 730 731 732 733 734 735 736 737 738
        return a;
    else
        return a + b;
}

static void video_audio_display(VideoState *s)
{
    int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
    int ch, channels, h, h2, bgcolor, fgcolor;
    int16_t time_diff;
739 740
    int rdft_bits, nb_freq;

Aneesh Dogra's avatar
Aneesh Dogra committed
741
    for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
742
        ;
Aneesh Dogra's avatar
Aneesh Dogra committed
743
    nb_freq = 1 << (rdft_bits - 1);
744

Fabrice Bellard's avatar
Fabrice Bellard committed
745
    /* compute display index : center on currently output samples */
746
    channels = s->sdl_channels;
Fabrice Bellard's avatar
Fabrice Bellard committed
747
    nb_display_channels = channels;
748
    if (!s->paused) {
Aneesh Dogra's avatar
Aneesh Dogra committed
749
        int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq);
750 751 752
        n = 2 * channels;
        delay = audio_write_get_buf_size(s);
        delay /= n;
753

754 755 756
        /* to be more precise, we take into account the time spent since
           the last buffer computation */
        if (audio_callback_time) {
757
            time_diff = av_gettime_relative() - audio_callback_time;
758
            delay -= (time_diff * s->sdl_sample_rate) / 1000000;
759
        }
760

Aneesh Dogra's avatar
Aneesh Dogra committed
761
        delay += 2 * data_used;
762 763
        if (delay < data_used)
            delay = data_used;
764 765

        i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
Aneesh Dogra's avatar
Aneesh Dogra committed
766 767 768 769 770 771 772 773 774 775 776 777
        if (s->show_audio == 1) {
            h = INT_MIN;
            for (i = 0; i < 1000; i += channels) {
                int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
                int a = s->sample_array[idx];
                int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
                int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
                int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
                int score = a - d;
                if (h < score && (b ^ c) < 0) {
                    h = score;
                    i_start = idx;
778
                }
779 780 781
            }
        }

782 783 784
        s->last_i_start = i_start;
    } else {
        i_start = s->last_i_start;
Fabrice Bellard's avatar
Fabrice Bellard committed
785 786 787
    }

    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
Aneesh Dogra's avatar
Aneesh Dogra committed
788
    if (s->show_audio == 1) {
789 790 791 792 793 794 795 796 797 798
        fill_rectangle(screen,
                       s->xleft, s->ytop, s->width, s->height,
                       bgcolor);

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

        /* total height for one channel */
        h = s->height / nb_display_channels;
        /* graph height / 2 */
        h2 = (h * 9) / 20;
Aneesh Dogra's avatar
Aneesh Dogra committed
799
        for (ch = 0; ch < nb_display_channels; ch++) {
800 801
            i = i_start + ch;
            y1 = s->ytop + ch * h + (h / 2); /* position of center line */
Aneesh Dogra's avatar
Aneesh Dogra committed
802
            for (x = 0; x < s->width; x++) {
803 804 805 806 807 808 809 810 811 812 813 814 815
                y = (s->sample_array[i] * h2) >> 15;
                if (y < 0) {
                    y = -y;
                    ys = y1 - y;
                } else {
                    ys = y1;
                }
                fill_rectangle(screen,
                               s->xleft + x, ys, 1, y,
                               fgcolor);
                i += channels;
                if (i >= SAMPLE_ARRAY_SIZE)
                    i -= SAMPLE_ARRAY_SIZE;
Fabrice Bellard's avatar
Fabrice Bellard committed
816 817 818
            }
        }

819
        fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
Fabrice Bellard's avatar
Fabrice Bellard committed
820

Aneesh Dogra's avatar
Aneesh Dogra committed
821
        for (ch = 1; ch < nb_display_channels; ch++) {
822 823 824 825 826 827
            y = s->ytop + ch * h;
            fill_rectangle(screen,
                           s->xleft, y, s->width, 1,
                           fgcolor);
        }
        SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
Aneesh Dogra's avatar
Aneesh Dogra committed
828
    } else {
829
        nb_display_channels= FFMIN(nb_display_channels, 2);
Aneesh Dogra's avatar
Aneesh Dogra committed
830
        if (rdft_bits != s->rdft_bits) {
831
            av_rdft_end(s->rdft);
Måns Rullgård's avatar
Måns Rullgård committed
832
            av_free(s->rdft_data);
833
            s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
Aneesh Dogra's avatar
Aneesh Dogra committed
834 835
            s->rdft_bits = rdft_bits;
            s->rdft_data = av_malloc(4 * nb_freq * sizeof(*s->rdft_data));
836 837
        }
        {
Måns Rullgård's avatar
Måns Rullgård committed
838
            FFTSample *data[2];
Aneesh Dogra's avatar
Aneesh Dogra committed
839 840
            for (ch = 0; ch < nb_display_channels; ch++) {
                data[ch] = s->rdft_data + 2 * nb_freq * ch;
841
                i = i_start + ch;
Aneesh Dogra's avatar
Aneesh Dogra committed
842 843 844
                for (x = 0; x < 2 * nb_freq; x++) {
                    double w = (x-nb_freq) * (1.0 / nb_freq);
                    data[ch][x] = s->sample_array[i] * (1.0 - w * w);
845 846 847 848
                    i += channels;
                    if (i >= SAMPLE_ARRAY_SIZE)
                        i -= SAMPLE_ARRAY_SIZE;
                }
849
                av_rdft_calc(s->rdft, data[ch]);
850
            }
Diego Biurrun's avatar
Diego Biurrun committed
851 852
            /* Least efficient way to do this, we should of course
             * directly access it but it is more than fast enough. */
Aneesh Dogra's avatar
Aneesh Dogra committed
853 854 855 856 857 858 859 860
            for (y = 0; y < s->height; y++) {
                double w = 1 / sqrt(nb_freq);
                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]));
                int b = (nb_display_channels == 2 ) ? sqrt(w * sqrt(data[1][2 * y + 0] * data[1][2 * y + 0]
                       + data[1][2 * y + 1] * data[1][2 * y + 1])) : a;
                a = FFMIN(a, 255);
                b = FFMIN(b, 255);
                fgcolor = SDL_MapRGB(screen->format, a, b, (a + b) / 2);
861 862 863 864 865 866 867 868

                fill_rectangle(screen,
                            s->xpos, s->height-y, 1, 1,
                            fgcolor);
            }
        }
        SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
        s->xpos++;
Aneesh Dogra's avatar
Aneesh Dogra committed
869
        if (s->xpos >= s->width)
870 871
            s->xpos= s->xleft;
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
872 873
}

Aneesh Dogra's avatar
Aneesh Dogra committed
874 875 876
static int video_open(VideoState *is)
{
    int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
877 878
    int w,h;

Aneesh Dogra's avatar
Aneesh Dogra committed
879 880
    if (is_full_screen) flags |= SDL_FULLSCREEN;
    else                flags |= SDL_RESIZABLE;
881

882 883 884
    if (is_full_screen && fs_screen_width) {
        w = fs_screen_width;
        h = fs_screen_height;
Aneesh Dogra's avatar
Aneesh Dogra committed
885
    } else if (!is_full_screen && screen_width) {
886 887
        w = screen_width;
        h = screen_height;
888
#if CONFIG_AVFILTER
Aneesh Dogra's avatar
Aneesh Dogra committed
889
    } else if (is->out_video_filter && is->out_video_filter->inputs[0]) {
890 891 892
        w = is->out_video_filter->inputs[0]->w;
        h = is->out_video_filter->inputs[0]->h;
#else
Aneesh Dogra's avatar
Aneesh Dogra committed
893
    } else if (is->video_st && is->video_st->codec->width) {
894 895
        w = is->video_st->codec->width;
        h = is->video_st->codec->height;
896
#endif
897
    } else {
898 899
        w = 640;
        h = 480;
900
    }
Aneesh Dogra's avatar
Aneesh Dogra committed
901
    if (screen && is->width == screen->w && screen->w == w
902 903 904
       && is->height== screen->h && screen->h == h)
        return 0;

905 906
#if defined(__APPLE__) && !SDL_VERSION_ATLEAST(1, 2, 14)
    /* setting bits_per_pixel = 0 or 32 causes blank video on OS X and older SDL */
907
    screen = SDL_SetVideoMode(w, h, 24, flags);
908 909
#else
    screen = SDL_SetVideoMode(w, h, 0, flags);
910 911 912 913 914
#endif
    if (!screen) {
        fprintf(stderr, "SDL: could not set video mode - exiting\n");
        return -1;
    }
915 916 917
    if (!window_title)
        window_title = input_filename;
    SDL_WM_SetCaption(window_title, window_title);
918

Aneesh Dogra's avatar
Aneesh Dogra committed
919
    is->width  = screen->w;
920 921 922 923
    is->height = screen->h;

    return 0;
}
924

Fabrice Bellard's avatar
Fabrice Bellard committed
925 926 927
/* display the current picture, if any */
static void video_display(VideoState *is)
{
Aneesh Dogra's avatar
Aneesh Dogra committed
928
    if (!screen)
929
        video_open(cur_stream);
930
    if (is->audio_st && is->show_audio)
Fabrice Bellard's avatar
Fabrice Bellard committed
931 932 933 934 935
        video_audio_display(is);
    else if (is->video_st)
        video_image_display(is);
}

Michael Niedermayer's avatar
Michael Niedermayer committed
936
static int refresh_thread(void *opaque)
Fabrice Bellard's avatar
Fabrice Bellard committed
937
{
Michael Niedermayer's avatar
Michael Niedermayer committed
938
    VideoState *is= opaque;
Aneesh Dogra's avatar
Aneesh Dogra committed
939
    while (!is->abort_request) {
940 941 942
        SDL_Event event;
        event.type = FF_REFRESH_EVENT;
        event.user.data1 = opaque;
Aneesh Dogra's avatar
Aneesh Dogra committed
943 944
        if (!is->refresh) {
            is->refresh = 1;
945
            SDL_PushEvent(&event);
Michael Niedermayer's avatar
Michael Niedermayer committed
946
        }
947
        av_usleep(is->audio_st && is->show_audio ? rdftspeed * 1000 : 5000); // FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
Michael Niedermayer's avatar
Michael Niedermayer committed
948 949
    }
    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
950 951
}

952 953 954 955 956 957 958 959 960
/* get the current audio clock value */
static double get_audio_clock(VideoState *is)
{
    double pts;
    int hw_buf_size, bytes_per_sec;
    pts = is->audio_clock;
    hw_buf_size = audio_write_get_buf_size(is);
    bytes_per_sec = 0;
    if (is->audio_st) {
961
        bytes_per_sec = is->sdl_sample_rate * is->sdl_channels *
962
                        av_get_bytes_per_sample(is->sdl_sample_fmt);
963 964 965 966 967 968 969 970 971
    }
    if (bytes_per_sec)
        pts -= (double)hw_buf_size / bytes_per_sec;
    return pts;
}

/* get the current video clock value */
static double get_video_clock(VideoState *is)
{
Michael Niedermayer's avatar
oops  
Michael Niedermayer committed
972
    if (is->paused) {
973
        return is->video_current_pts;
Fabrice Bellard's avatar
Fabrice Bellard committed
974
    } else {
975
        return is->video_current_pts_drift + av_gettime_relative() / 1000000.0;
Fabrice Bellard's avatar
Fabrice Bellard committed
976
    }
977 978 979 980 981 982
}

/* get the current external clock value */
static double get_external_clock(VideoState *is)
{
    int64_t ti;
983
    ti = av_gettime_relative();
984 985 986 987 988 989 990 991
    return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
}

/* get the current master clock value */
static double get_master_clock(VideoState *is)
{
    double val;

Fabrice Bellard's avatar
Fabrice Bellard committed
992 993 994 995 996 997 998 999 1000 1001 1002
    if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
        if (is->video_st)
            val = get_video_clock(is);
        else
            val = get_audio_clock(is);
    } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
        if (is->audio_st)
            val = get_audio_clock(is);
        else
            val = get_video_clock(is);
    } else {
1003
        val = get_external_clock(is);
Fabrice Bellard's avatar
Fabrice Bellard committed
1004
    }
1005 1006 1007
    return val;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
1008
/* seek in the stream */
1009
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
Fabrice Bellard's avatar
Fabrice Bellard committed
1010
{
1011 1012
    if (!is->seek_req) {
        is->seek_pos = pos;
1013
        is->seek_rel = rel;
Michael Niedermayer's avatar
Michael Niedermayer committed
1014
        is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1015 1016
        if (seek_by_bytes)
            is->seek_flags |= AVSEEK_FLAG_BYTE;
1017 1018
        is->seek_req = 1;
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
1019 1020 1021 1022 1023
}

/* pause or resume the video */
static void stream_pause(VideoState *is)
{
1024
    if (is->paused) {
1025
        is->frame_timer += av_gettime_relative() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
Aneesh Dogra's avatar
Aneesh Dogra committed
1026
        if (is->read_pause_return != AVERROR(ENOSYS)) {
1027
            is->video_current_pts = is->video_current_pts_drift + av_gettime_relative() / 1000000.0;
1028
        }
1029
        is->video_current_pts_drift = is->video_current_pts - av_gettime_relative() / 1000000.0;
Fabrice Bellard's avatar
Fabrice Bellard committed
1030
    }
1031
    is->paused = !is->paused;
Fabrice Bellard's avatar
Fabrice Bellard committed
1032 1033
}

Michael Niedermayer's avatar
Michael Niedermayer committed
1034
static double compute_target_time(double frame_current_pts, VideoState *is)
1035
{
Michael Niedermayer's avatar
Michael Niedermayer committed
1036
    double delay, sync_threshold, diff;
1037 1038 1039 1040 1041 1042

    /* compute nominal delay */
    delay = frame_current_pts - is->frame_last_pts;
    if (delay <= 0 || delay >= 10.0) {
        /* if incorrect delay, use previous one */
        delay = is->frame_last_delay;
1043
    } else {
1044
        is->frame_last_delay = delay;
1045
    }
1046 1047 1048 1049 1050 1051 1052
    is->frame_last_pts = frame_current_pts;

    /* update delay to follow master synchronisation source */
    if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
        /* if video is slave, we try to correct big delays by
           duplicating or deleting a frame */
1053
        diff = get_video_clock(is) - get_master_clock(is);
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

        /* skip or repeat frame. We take into account the
           delay to compute the threshold. I still don't know
           if it is the best guess */
        sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
        if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
            if (diff <= -sync_threshold)
                delay = 0;
            else if (diff >= sync_threshold)
                delay = 2 * delay;
        }
    }
    is->frame_timer += delay;
1067 1068 1069

    av_dlog(NULL, "video: delay=%0.3f pts=%0.3f A-V=%f\n",
            delay, frame_current_pts, -diff);
1070

Michael Niedermayer's avatar
Michael Niedermayer committed
1071
    return is->frame_timer;
1072 1073
}

Fabrice Bellard's avatar
Fabrice Bellard committed
1074 1075 1076 1077 1078
/* called to display each frame */
static void video_refresh_timer(void *opaque)
{
    VideoState *is = opaque;
    VideoPicture *vp;
1079

1080
    SubPicture *sp, *sp2;