ffplay.c 97 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
2
 * ffplay : 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
#include "libavutil/avstring.h"
27
#include "libavutil/colorspace.h"
28
#include "libavutil/pixdesc.h"
29 30 31
#include "libavutil/imgutils.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
32 33 34
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
35
#include "libavcodec/audioconvert.h"
36
#include "libavutil/opt.h"
37
#include "libavcodec/avfft.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
38

39 40 41 42 43
#if CONFIG_AVFILTER
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
44 45 46 47 48
#include "cmdutils.h"

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

49
#ifdef __MINGW32__
50 51 52
#undef main /* We don't want SDL to override our main() */
#endif

53 54 55
#include <unistd.h>
#include <assert.h>

56
const char program_name[] = "ffplay";
57
const int program_birth_year = 2003;
58

59
//#define DEBUG
60 61
//#define DEBUG_SYNC

62 63 64
#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
65

66 67 68 69 70
/* 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 */
71
#define AV_SYNC_THRESHOLD 0.01
72 73 74
/* no AV correction is done if too big error */
#define AV_NOSYNC_THRESHOLD 10.0

75 76
#define FRAME_SKIP_FACTOR 0.05

77 78 79 80 81 82
/* 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
83 84 85
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
#define SAMPLE_ARRAY_SIZE (2*65536)

86 87
static int sws_flags = SWS_BICUBIC;

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

97
#define VIDEO_PICTURE_QUEUE_SIZE 2
98
#define SUBPICTURE_QUEUE_SIZE 4
Fabrice Bellard's avatar
Fabrice Bellard committed
99 100

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

#if CONFIG_AVFILTER
110
    AVFilterBufferRef *picref;
111
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
112 113
} VideoPicture;

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

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

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

    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 156 157
    AVStream *audio_st;
    PacketQueue audioq;
    int audio_hw_buf_size;
    /* samples output by the codec. we reserve more space for avsync
       compensation */
158 159
    DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
    DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
160
    uint8_t *audio_buf;
161
    unsigned int audio_buf_size; /* in bytes */
Fabrice Bellard's avatar
Fabrice Bellard committed
162
    int audio_buf_index; /* in bytes */
163
    AVPacket audio_pkt_temp;
Fabrice Bellard's avatar
Fabrice Bellard committed
164
    AVPacket audio_pkt;
165
    enum AVSampleFormat audio_src_fmt;
166
    AVAudioConvert *reformat_ctx;
167

Fabrice Bellard's avatar
Fabrice Bellard committed
168 169 170
    int show_audio; /* if true, display audio samples */
    int16_t sample_array[SAMPLE_ARRAY_SIZE];
    int sample_array_index;
171
    int last_i_start;
172
    RDFTContext *rdft;
173
    int rdft_bits;
Måns Rullgård's avatar
Måns Rullgård committed
174
    FFTSample *rdft_data;
175
    int xpos;
176

177 178 179 180 181 182 183 184 185
    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;
186

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

Fabrice Bellard's avatar
Fabrice Bellard committed
205 206 207
    //    QETimer *video_timer;
    char filename[1024];
    int width, height, xleft, ytop;
208

209
    PtsCorrectionContext pts_ctx;
210

211 212 213
#if CONFIG_AVFILTER
    AVFilterContext *out_video_filter;          ///<the last filter in the video chain
#endif
214 215 216 217

    float skip_frames;
    float skip_frames_index;
    int refresh;
Fabrice Bellard's avatar
Fabrice Bellard committed
218 219
} VideoState;

220
static void show_help(void);
Fabrice Bellard's avatar
Fabrice Bellard committed
221 222 223 224

/* options specified by the user */
static AVInputFormat *file_iformat;
static const char *input_filename;
225
static const char *window_title;
Fabrice Bellard's avatar
Fabrice Bellard committed
226 227
static int fs_screen_width;
static int fs_screen_height;
228 229
static int screen_width = 0;
static int screen_height = 0;
230 231 232
static int frame_width = 0;
static int frame_height = 0;
static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
Fabrice Bellard's avatar
Fabrice Bellard committed
233 234
static int audio_disable;
static int video_disable;
235 236 237 238
static int wanted_stream[AVMEDIA_TYPE_NB]={
    [AVMEDIA_TYPE_AUDIO]=-1,
    [AVMEDIA_TYPE_VIDEO]=-1,
    [AVMEDIA_TYPE_SUBTITLE]=-1,
239
};
240
static int seek_by_bytes=-1;
Fabrice Bellard's avatar
Fabrice Bellard committed
241
static int display_disable;
242
static int show_status = 1;
243
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
Fabrice Bellard's avatar
Fabrice Bellard committed
244
static int64_t start_time = AV_NOPTS_VALUE;
245
static int64_t duration = AV_NOPTS_VALUE;
246
static int debug = 0;
247
static int debug_mv = 0;
248
static int step = 0;
249
static int thread_count = 1;
Michael Niedermayer's avatar
Michael Niedermayer committed
250
static int workaround_bugs = 1;
251
static int fast = 0;
252
static int genpts = 0;
253 254
static int lowres = 0;
static int idct = FF_IDCT_AUTO;
Michael Niedermayer's avatar
Michael Niedermayer committed
255 256 257
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
258
static int error_recognition = FF_ER_CAREFUL;
259
static int error_concealment = 3;
260
static int decoder_reorder_pts= -1;
Michael Niedermayer's avatar
Michael Niedermayer committed
261
static int autoexit;
262 263
static int exit_on_keydown;
static int exit_on_mousedown;
264
static int loop=1;
265
static int framedrop=1;
266 267

static int rdftspeed=20;
268 269 270
#if CONFIG_AVFILTER
static char *vfilters = NULL;
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
271 272 273 274

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

277
static AVPacket flush_pkt;
278

Fabrice Bellard's avatar
Fabrice Bellard committed
279 280
#define FF_ALLOC_EVENT   (SDL_USEREVENT)
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
281
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
Fabrice Bellard's avatar
Fabrice Bellard committed
282

283
static SDL_Surface *screen;
Fabrice Bellard's avatar
Fabrice Bellard committed
284

285 286
static int packet_queue_put(PacketQueue *q, AVPacket *pkt);

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

Fabrice Bellard's avatar
Fabrice Bellard committed
296
static void packet_queue_flush(PacketQueue *q)
Fabrice Bellard's avatar
Fabrice Bellard committed
297 298 299
{
    AVPacketList *pkt, *pkt1;

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

static void packet_queue_end(PacketQueue *q)
{
    packet_queue_flush(q);
Fabrice Bellard's avatar
Fabrice Bellard committed
316 317 318 319 320 321 322 323
    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
324
    /* duplicate the packet */
325
    if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
326
        return -1;
327

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

Fabrice Bellard's avatar
Fabrice Bellard committed
334

Fabrice Bellard's avatar
Fabrice Bellard committed
335 336 337 338 339 340 341 342 343
    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++;
344
    q->size += pkt1->pkt.size + sizeof(*pkt1);
Fabrice Bellard's avatar
Fabrice Bellard committed
345 346 347 348 349 350 351 352 353 354 355 356
    /* 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;
357

Fabrice Bellard's avatar
Fabrice Bellard committed
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
    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);

    for(;;) {
        if (q->abort_request) {
            ret = -1;
            break;
        }
376

Fabrice Bellard's avatar
Fabrice Bellard committed
377 378 379 380 381 382
        pkt1 = q->first_pkt;
        if (pkt1) {
            q->first_pkt = pkt1->next;
            if (!q->first_pkt)
                q->last_pkt = NULL;
            q->nb_packets--;
383
            q->size -= pkt1->pkt.size + sizeof(*pkt1);
Fabrice Bellard's avatar
Fabrice Bellard committed
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
            *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;
}

399
static inline void fill_rectangle(SDL_Surface *screen,
Fabrice Bellard's avatar
Fabrice Bellard committed
400 401 402 403 404 405 406 407 408 409
                                  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);
}

410 411 412 413 414 415 416 417 418 419 420 421 422 423
#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)\
{\
424
    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
425 426 427 428 429 430 431 432 433 434 435 436 437 438
    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

439
static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
440 441 442 443 444 445
{
    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;
446 447
    int dstx, dsty, dstw, dsth;

448 449 450 451
    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);
452 453 454 455
    lum = dst->data[0] + dsty * dst->linesize[0];
    cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
    cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];

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

463 464
    if (dsty & 1) {
        lum += dstx;
465 466
        cb += skip2;
        cr += skip2;
467

468
        if (dstx & 1) {
469 470 471 472 473 474 475 476 477
            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;
        }
478
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
            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);
502 503
            p++;
            lum++;
504
        }
505 506
        p += wrap3 - dstw * BPP;
        lum += wrap - dstw - dstx;
507 508 509
        cb += dst->linesize[1] - width2 - skip2;
        cr += dst->linesize[2] - width2 - skip2;
    }
510 511
    for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
        lum += dstx;
512 513
        cb += skip2;
        cr += skip2;
514

515
        if (dstx & 1) {
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
            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;
        }
535
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
536 537 538 539 540 541
            YUVA_IN(y, u, v, a, p, pal);
            u1 = u;
            v1 = v;
            a1 = a;
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);

542
            YUVA_IN(y, u, v, a, p + BPP, pal);
543 544 545 546 547 548 549 550 551 552 553 554 555
            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);

556
            YUVA_IN(y, u, v, a, p + BPP, pal);
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 587 588 589
            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;
        }
590 591
        p += wrap3 + (wrap3 - dstw * BPP);
        lum += wrap + (wrap - dstw - dstx);
592 593 594 595 596
        cb += dst->linesize[1] - width2 - skip2;
        cr += dst->linesize[2] - width2 - skip2;
    }
    /* handle odd height */
    if (h) {
597
        lum += dstx;
598 599
        cb += skip2;
        cr += skip2;
600

601
        if (dstx & 1) {
602 603 604 605 606 607 608 609 610
            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;
        }
611
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
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 638 639 640
            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)
{
641
    avsubtitle_free(&sp->sub);
642 643
}

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

    vp = &is->pictq[is->pictq_rindex];
    if (vp->bmp) {
656
#if CONFIG_AVFILTER
657
         if (vp->picref->video->pixel_aspect.num == 0)
658 659
             aspect_ratio = 0;
         else
660
             aspect_ratio = av_q2d(vp->picref->video->pixel_aspect);
661 662
#else

Fabrice Bellard's avatar
Fabrice Bellard committed
663
        /* XXX: use variable in the frame */
664 665 666 667
        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
668
        else
669
            aspect_ratio = 0;
670
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
671
        if (aspect_ratio <= 0.0)
672
            aspect_ratio = 1.0;
673
        aspect_ratio *= (float)vp->width / (float)vp->height;
Fabrice Bellard's avatar
Fabrice Bellard committed
674

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
        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++)
694
                        blend_subrect(&pict, sp->sub.rects[i],
695
                                      vp->bmp->w, vp->bmp->h);
696 697 698 699 700 701 702

                    SDL_UnlockYUVOverlay (vp->bmp);
                }
            }
        }


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

721 722 723 724 725 726 727
/* 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
728 729 730
static inline int compute_mod(int a, int b)
{
    a = a % b;
731
    if (a >= 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
732 733 734 735 736 737 738 739 740 741
        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;
742 743 744 745 746
    int rdft_bits, nb_freq;

    for(rdft_bits=1; (1<<rdft_bits)<2*s->height; rdft_bits++)
        ;
    nb_freq= 1<<(rdft_bits-1);
747

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

757 758 759 760
        /* to be more precise, we take into account the time spent since
           the last buffer computation */
        if (audio_callback_time) {
            time_diff = av_gettime() - audio_callback_time;
761
            delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
762
        }
763

764
        delay += 2*data_used;
765 766
        if (delay < data_used)
            delay = data_used;
767 768

        i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
769
        if(s->show_audio==1){
770 771 772 773 774 775 776 777 778 779 780 781
            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;
                }
782 783 784
            }
        }

785 786 787
        s->last_i_start = i_start;
    } else {
        i_start = s->last_i_start;
Fabrice Bellard's avatar
Fabrice Bellard committed
788 789 790
    }

    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
791
    if(s->show_audio==1){
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
        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;
        for(ch = 0;ch < nb_display_channels; ch++) {
            i = i_start + ch;
            y1 = s->ytop + ch * h + (h / 2); /* position of center line */
            for(x = 0; x < s->width; x++) {
                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
819 820 821
            }
        }

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

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

                fill_rectangle(screen,
                            s->xpos, s->height-y, 1, 1,
                            fgcolor);
            }
        }
        SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
        s->xpos++;
        if(s->xpos >= s->width)
            s->xpos= s->xleft;
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
874 875
}

876 877 878 879
static int video_open(VideoState *is){
    int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
    int w,h;

880 881 882
    if(is_full_screen) flags |= SDL_FULLSCREEN;
    else               flags |= SDL_RESIZABLE;

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

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

    is->width = screen->w;
    is->height = screen->h;

    return 0;
}
925

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

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

953 954 955 956 957 958 959 960 961
/* 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) {
962
        bytes_per_sec = is->audio_st->codec->sample_rate *
963
            2 * is->audio_st->codec->channels;
964 965 966 967 968 969 970 971 972
    }
    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
Michael Niedermayer committed
973
    if (is->paused) {
974
        return is->video_current_pts;
Fabrice Bellard's avatar
Fabrice Bellard committed
975
    } else {
976
        return is->video_current_pts_drift + av_gettime() / 1000000.0;
Fabrice Bellard's avatar
Fabrice Bellard committed
977
    }
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
}

/* get the current external clock value */
static double get_external_clock(VideoState *is)
{
    int64_t ti;
    ti = av_gettime();
    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
993 994 995 996 997 998 999 1000 1001 1002 1003
    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 {
1004
        val = get_external_clock(is);
Fabrice Bellard's avatar
Fabrice Bellard committed
1005
    }
1006 1007 1008
    return val;
}

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

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

1035
static double compute_target_time(double frame_current_pts, VideoState *is)
1036
{
1037
    double delay, sync_threshold, diff;
1038 1039 1040 1041 1042 1043

    /* 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;
1044
    } else {
1045
        is->frame_last_delay = delay;
1046
    }
1047 1048 1049 1050 1051 1052 1053
    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 */
1054
        diff = get_video_clock(is) - get_master_clock(is);
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067

        /* 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;
1068 1069 1070 1071 1072
#if defined(DEBUG_SYNC)
    printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
            delay, actual_delay, frame_current_pts, -diff);
#endif

1073
    return is->frame_timer;
1074 1075
}

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

1082
    SubPicture *sp, *sp2;
Fabrice Bellard's avatar
Fabrice Bellard committed
1083 1084

    if (is->video_st) {
1085
retry:
Fabrice Bellard's avatar
Fabrice Bellard committed
1086
        if (is->pictq_size == 0) {
1087
            //nothing to do, no picture to display in the que
Fabrice Bellard's avatar
Fabrice Bellard committed
1088
        } else {
1089 1090
            double time= av_gettime()/1000000.0;
            double next_target;
1091
            /* dequeue the picture */
Fabrice Bellard's avatar
Fabrice Bellard committed
1092
            vp = &is->pictq[is->pictq_rindex];
1093

1094 1095
            if(time < vp->target_clock)
                return;
1096 1097
            /* update current video pts */
            is->video_current_pts = vp->pts;
1098
            is->video_current_pts_drift = is->video_current_pts - time;
1099
            is->video_current_pos = vp->pos;
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
            if(is->pictq_size > 1){
                VideoPicture *nextvp= &is->pictq[(is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE];
                assert(nextvp->target_clock >= vp->target_clock);
                next_target= nextvp->target_clock;
            }else{
                next_target= vp->target_clock + is->video_clock - vp->pts; //FIXME pass durations cleanly
            }
            if(framedrop && time > next_target){
                is->skip_frames *= 1.0 + FRAME_SKIP_FACTOR;
                if(is->pictq_size > 1 || time > next_target + 0.5){
                    /* update queue size and signal for next picture */
                    if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
                        is->pictq_rindex = 0;

                    SDL_LockMutex(is->pictq_mutex);
                    is->pictq_size--;
                    SDL_CondSignal(is->pictq_cond);
                    SDL_UnlockMutex(is->pictq_mutex);
                    goto retry;
                }
            }
1121

1122 1123 1124
            if(is->subtitle_st) {
                if (is->subtitle_stream_changed) {
                    SDL_LockMutex(is->subpq_mutex);
1125

1126 1127
                    while (is->subpq_size) {
                        free_subpicture(&is->subpq[is->subpq_rindex]);
1128

1129 1130 1131
                        /* update queue size and signal for next picture */
                        if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
                            is->subpq_rindex = 0;
1132

1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
                        is->subpq_size--;
                    }
                    is->subtitle_stream_changed = 0;

                    SDL_CondSignal(is->subpq_cond);
                    SDL_UnlockMutex(is->subpq_mutex);
                } else {
                    if (is->subpq_size > 0) {
                        sp = &is->subpq[is->subpq_rindex];

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

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

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

                            SDL_LockMutex(is->subpq_mutex);
                            is->subpq_size--;
                            SDL_CondSignal(is->subpq_cond);
                            SDL_UnlockMutex(is->subpq_mutex);
                        }
                    }
                }
            }

Fabrice Bellard's avatar
Fabrice Bellard committed
1166
            /* display picture */
1167
            if (!display_disable)
1168
                video_display(is);
1169

Fabrice Bellard's avatar
Fabrice Bellard committed
1170 1171 1172
            /* update queue size and signal for next picture */
            if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
                is->pictq_rindex = 0;
1173

Fabrice Bellard's avatar
Fabrice Bellard committed
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
            SDL_LockMutex(is->pictq_mutex);
            is->pictq_size--;
            SDL_CondSignal(is->pictq_cond);
            SDL_UnlockMutex(is->pictq_mutex);
        }
    } else if (is->audio_st) {
        /* draw the next audio frame */

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

Fabrice Bellard's avatar
Fabrice Bellard committed
1185
        /* display picture */
1186
        if (!display_disable)
1187
            video_display(is);
Fabrice Bellard's avatar
Fabrice Bellard committed
1188 1189 1190 1191
    }
    if (show_status) {
        static int64_t last_time;
        int64_t cur_time;
1192
        int aqsize, vqsize, sqsize;
1193
        double av_diff;
1194

Fabrice Bellard's avatar
Fabrice Bellard committed
1195
        cur_time = av_gettime();
1196
        if (!last_time || (cur_time - last_time) >= 30000) {
Fabrice Bellard's avatar
Fabrice Bellard committed
1197 1198
            aqsize = 0;
            vqsize = 0;
1199
            sqsize = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
1200 1201 1202 1203
            if (is->audio_st)
                aqsize = is->audioq.size;
            if (is->video_st)
                vqsize = is->videoq.size;
1204 1205
            if (is->subtitle_st)
                sqsize = is->subtitleq.size;
1206 1207 1208
            av_diff = 0;
            if (is->audio_st && is->video_st)
                av_diff = get_audio_clock(is) - get_video_clock(is);
1209
            printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64"   \r",
1210
                   get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->pts_ctx.num_faulty_dts, is->pts_ctx.num_faulty_pts);
Fabrice Bellard's avatar
Fabrice Bellard committed
1211 1212 1213 1214 1215 1216
            fflush(stdout);
            last_time = cur_time;
        }
    }
}

1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
static void stream_close(VideoState *is)
{
    VideoPicture *vp;
    int i;
    /* XXX: use a special url_shutdown call to abort parse cleanly */
    is->abort_request = 1;
    SDL_WaitThread(is->parse_tid, NULL);
    SDL_WaitThread(is->refresh_tid, NULL);

    /* free all pictures */
    for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
        vp = &is->pictq[i];
#if CONFIG_AVFILTER
        if (vp->picref) {
            avfilter_unref_buffer(vp->picref);
            vp->picref = NULL;
        }
#endif
        if (vp->bmp) {
            SDL_FreeYUVOverlay(vp->bmp);
            vp->bmp = NULL;
        }
    }
    SDL_DestroyMutex(is->pictq_mutex);
    SDL_DestroyCond(is->pictq_cond);
    SDL_DestroyMutex(is->subpq_mutex);
    SDL_DestroyCond(is->subpq_cond);
#if !CONFIG_AVFILTER
    if (is->img_convert_ctx)
        sws_freeContext(is->img_convert_ctx);
#endif
    av_free(is);
}

static void do_exit(void)
{
    if (cur_stream) {
        stream_close(cur_stream);
        cur_stream = NULL;
    }
1257
    uninit_opts();
1258 1259 1260 1261 1262 1263
#if CONFIG_AVFILTER
    avfilter_uninit();
#endif
    if (show_status)
        printf("\n");
    SDL_Quit();
1264
    av_log(NULL, AV_LOG_QUIET, "");
1265 1266 1267
    exit(0);
}

Fabrice Bellard's avatar
Fabrice Bellard committed
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
/* allocate a picture (needs to do that in main thread to avoid
   potential locking problems */
static void alloc_picture(void *opaque)
{
    VideoState *is = opaque;
    VideoPicture *vp;

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

    if (vp->bmp)
        SDL_FreeYUVOverlay(vp->bmp);

1280 1281
#if CONFIG_AVFILTER
    if (vp->picref)
1282
        avfilter_unref_buffer(vp->picref);
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
    vp->picref = NULL;

    vp->width   = is->out_video_filter->inputs[0]->w;
    vp->height  = is->out_video_filter->inputs[0]->h;
    vp->pix_fmt = is->out_video_filter->inputs[0]->format;
#else
    vp->width   = is->video_st->codec->width;
    vp->height  = is->video_st->codec->height;
    vp->pix_fmt = is->video_st->codec->pix_fmt;
#endif

    vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
1295
                                   SDL_YV12_OVERLAY,
1296
                                   screen);
1297 1298 1299 1300
    if (!vp->bmp || vp->bmp->pitches[0] < vp->width) {
        /* SDL allocates a buffer smaller than requested if the video
         * overlay hardware is unable to support the requested size. */
        fprintf(stderr, "Error: the video system does not support an image\n"
1301
                        "size of %dx%d pixels. Try using -lowres or -vf \"scale=w:h\"\n"
1302 1303 1304
                        "to reduce the image size.\n", vp->width, vp->height );
        do_exit();
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
1305 1306 1307 1308 1309 1310 1311

    SDL_LockMutex(is->pictq_mutex);
    vp->allocated = 1;
    SDL_CondSignal(is->pictq_cond);
    SDL_UnlockMutex(is->pictq_mutex);
}

1312 1313 1314 1315
/**
 *
 * @param pts the dts of the pkt / pts of the frame and guessed if not known
 */
1316
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
Fabrice Bellard's avatar
Fabrice Bellard committed
1317 1318 1319
{
    VideoPicture *vp;
    int dst_pix_fmt;
1320 1321 1322
#if CONFIG_AVFILTER
    AVPicture pict_src;
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
1323 1324
    /* wait until we have space to put a new picture */
    SDL_LockMutex(is->pictq_mutex);
1325 1326 1327 1328

    if(is->pictq_size>=VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)
        is->skip_frames= FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0-FRAME_SKIP_FACTOR));

Fabrice Bellard's avatar
Fabrice Bellard committed
1329 1330 1331 1332 1333
    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
           !is->videoq.abort_request) {
        SDL_CondWait(is->pictq_cond, is->pictq_mutex);
    }
    SDL_UnlockMutex(is->pictq_mutex);
1334

Fabrice Bellard's avatar
Fabrice Bellard committed
1335 1336 1337 1338 1339 1340
    if (is->videoq.abort_request)
        return -1;

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

    /* alloc or resize hardware picture buffer */
1341
    if (!vp->bmp ||
1342 1343 1344 1345
#if CONFIG_AVFILTER
        vp->width  != is->out_video_filter->inputs[0]->w ||
        vp->height != is->out_video_filter->inputs[0]->h) {
#else
1346 1347
        vp->width != is->video_st->codec->width ||
        vp->height != is->video_st->codec->height) {
1348
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
1349 1350 1351 1352 1353 1354 1355 1356 1357
        SDL_Event event;

        vp->allocated = 0;

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