ff_ffplay.c 121.5 KB
Newer Older
Z
Zhang Rui 已提交
1 2 3
/*
 * Copyright (c) 2003 Fabrice Bellard
 * Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This file is part of ijkPlayer.
 *
 * ijkPlayer is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * ijkPlayer is distributed in the hope that it will be useful,
 * 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
 * License along with ijkPlayer; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "ff_ffplay.h"
Z
Zhang Rui 已提交
23

Z
Zhang Rui 已提交
24 25 26 27 28 29 30
/**
 * @file
 * simple media player based on the FFmpeg libraries
 */

#include "config.h"
#include <inttypes.h>
Z
Zhang Rui 已提交
31
#include <math.h>
Z
Zhang Rui 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#include <limits.h>
#include <signal.h>
#include <stdint.h>

#include "libavutil/avstring.h"
// FFP_MERGE: #include "libavutil/colorspace.h"
#include "libavutil/eval.h"
#include "libavutil/mathematics.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#include "libavutil/dict.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/avassert.h"
#include "libavutil/time.h"
#include "libavformat/avformat.h"
// FFP_MERGE: #include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavcodec/avfft.h"
#include "libswresample/swresample.h"

#if CONFIG_AVFILTER
# include "libavfilter/avcodec.h"
# include "libavfilter/avfilter.h"
# include "libavfilter/buffersink.h"
# include "libavfilter/buffersrc.h"
#endif

61
#include "ff_cmdutils.h"
Z
Zhang Rui 已提交
62
#include "ff_fferror.h"
Z
Zhang Rui 已提交
63 64
#include "ff_ffpipeline.h"
#include "ff_ffpipenode.h"
Z
Zhang Rui 已提交
65
#include "ff_ffplay_debug.h"
Z
Zhang Rui 已提交
66
#include "ijkmeta.h"
Z
Zhang Rui 已提交
67
#include "ijksdl/ijksdl_log.h"
68

69 70 71 72
#ifndef AV_CODEC_FLAG2_FAST
#define AV_CODEC_FLAG2_FAST CODEC_FLAG2_FAST
#endif

73 74 75 76
#ifndef AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1 CODEC_CAP_DR1
#endif

Z
Zhang Rui 已提交
77
// FIXME: 9 work around NDKr8e or gcc4.7 bug
Z
Zhang Rui 已提交
78
// isnan() may not recognize some double NAN, so we test both double and float
79
#if defined(__ANDROID__)
Z
Zhang Rui 已提交
80 81 82 83
#ifdef isnan
#undef isnan
#endif
#define isnan(x) (isnan((double)(x)) || isnanf((float)(x)))
84
#endif
Z
Zhang Rui 已提交
85

Z
Zhang Rui 已提交
86
#if defined(__ANDROID__)
87
#define printf(...) ALOGD(__VA_ARGS__)
Z
Zhang Rui 已提交
88
#endif
89

90 91
#define FFP_IO_STAT_STEP (50 * 1024)

92 93 94
static int ffp_format_control_message(struct AVFormatContext *s, int type,
                                      void *data, size_t data_size);

95 96 97 98 99 100 101 102
#define OPTION_OFFSET(x) offsetof(FFPlayer, x)
#define OPTION_INT(default__, min__, max__) \
    .type = AV_OPT_TYPE_INT, \
    { .i64 = default__ }, \
    .min = min__, \
    .max = max__, \
    .flags = AV_OPT_FLAG_DECODING_PARAM

Z
Zhang Rui 已提交
103 104 105 106 107 108 109
#define OPTION_CONST(default__) \
    .type = AV_OPT_TYPE_CONST, \
    { .i64 = default__ }, \
    .min = INT_MIN, \
    .max = INT_MAX, \
    .flags = AV_OPT_FLAG_DECODING_PARAM

110 111
static const AVOption ffp_context_options[] = {
    // original options in ffplay.c
Z
Zhang Rui 已提交
112
    { "framedrop",                      "drop frames when cpu is too slow",
113
        OPTION_OFFSET(framedrop),       OPTION_INT(0, -1, 120) },
114 115

    // extended options in ff_ffplay.c
Z
Zhang Rui 已提交
116 117 118 119 120 121 122 123 124 125 126
    { "max-fps",                        "drop frames in video whose fps is greater than max-fps",
        OPTION_OFFSET(max_fps),         OPTION_INT(31, 0, 121) },

    { "overlay-format",                 "fourcc of overlay format",
        OPTION_OFFSET(overlay_format),  OPTION_INT(SDL_FCC_RV32, INT_MIN, INT_MAX),
        .unit = "overlay-format" },
    { "fcc-i420",                       "", 0, OPTION_CONST(SDL_FCC_I420), .unit = "overlay-format" },
    { "fcc-yv12",                       "", 0, OPTION_CONST(SDL_FCC_YV12), .unit = "overlay-format" },
    { "fcc-rv16",                       "", 0, OPTION_CONST(SDL_FCC_RV16), .unit = "overlay-format" },
    { "fcc-rv23",                       "", 0, OPTION_CONST(SDL_FCC_RV24), .unit = "overlay-format" },
    { "fcc-rv32",                       "", 0, OPTION_CONST(SDL_FCC_RV32), .unit = "overlay-format" },
127

Z
Zhang Rui 已提交
128 129 130 131 132 133 134 135
    { "start-on-prepared",                  "automatically start playing on prepared",
        OPTION_OFFSET(start_on_prepared),   OPTION_INT(1, 0, 1) },

    { "video-pictq-size",                   "max picture queue frame count",
        OPTION_OFFSET(pictq_size),          OPTION_INT(VIDEO_PICTURE_QUEUE_SIZE_DEFAULT,
                                                       VIDEO_PICTURE_QUEUE_SIZE_MIN,
                                                       VIDEO_PICTURE_QUEUE_SIZE_MAX) },

Z
Zhang Rui 已提交
136 137 138
    { "max-buffer-size",                    "max buffer size should be pre-read",
        OPTION_OFFSET(max_buffer_size),     OPTION_INT(MAX_QUEUE_SIZE, 0, MAX_QUEUE_SIZE) },

139 140
    { "packet-buffering",                   "pause output until enough packets have been read after stalling",
        OPTION_OFFSET(packet_buffering),    OPTION_INT(1, 0, 1) },
Z
Zhang Rui 已提交
141 142
    { "sync-av-start",                      "synchronise a/v start time",
        OPTION_OFFSET(sync_av_start),       OPTION_INT(1, 0, 1) },
143

144
    // iOS only options
145
    { "videotoolbox",                       "VideoToolbox: enable",
146
        OPTION_OFFSET(videotoolbox),        OPTION_INT(0, 0, 1) },
147
    { "videotoolbox-max-frame-width",       "VideoToolbox: max width of output frame",
148
        OPTION_OFFSET(vtb_max_frame_width), OPTION_INT(0, 0, INT_MAX) },
149 150
    { "videotoolbox-async",                 "VideoToolbox: use kVTDecodeFrame_EnableAsynchronousDecompression()",
        OPTION_OFFSET(vtb_async),           OPTION_INT(0, 0, 1) },
151 152
    { "videotoolbox-wait-async",            "VideoToolbox: call VTDecompressionSessionWaitForAsynchronousFrames()",
        OPTION_OFFSET(vtb_wait_async),      OPTION_INT(1, 0, 1) },
153

154 155 156
    // Android only options
    { "mediacodec",                         "MediaCodec: enable",
        OPTION_OFFSET(mediacodec),          OPTION_INT(0, 0, 1) },
Z
Zhang Rui 已提交
157 158
    { "opensles",                           "OpenSL ES: enable",
        OPTION_OFFSET(opensles),            OPTION_INT(0, 0, 1) },
159

160 161
    { NULL }
};
Z
Zhang Rui 已提交
162
#undef OPTION_CONST
163 164
#undef OPTION_INT
#undef OPTION_OFFSET
165

166 167
#define FFP_BUF_MSG_PERIOD (3)

168 169
static AVPacket flush_pkt;

Z
Zhang Rui 已提交
170 171 172
// FFP_MERGE: cmp_audio_fmts
// FFP_MERGE: get_valid_channel_layout

173
static void free_picture(Frame *vp);
174 175 176 177 178 179

static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
{
    MyAVPacketList *pkt1;

    if (q->abort_request)
Z
Zhang Rui 已提交
180
       return -1;
181

182
#ifdef FFP_MERGE
183
    pkt1 = av_malloc(sizeof(MyAVPacketList));
184 185 186 187 188 189 190 191 192 193 194 195
#else
    pkt1 = q->recycle_pkt;
    if (pkt1) {
        q->recycle_pkt = pkt1->next;
        q->recycle_count++;
    } else {
        q->alloc_count++;
        pkt1 = av_malloc(sizeof(MyAVPacketList));
    }
#ifdef FFP_SHOW_PKT_RECYCLE
    int total_count = q->recycle_count + q->alloc_count;
    if (!(total_count % 50)) {
196
        av_log(ffp, AV_LOG_DEBUG, "pkt-recycle \t%d + \t%d = \t%d\n", q->recycle_count, q->alloc_count, total_count);
197 198 199
    }
#endif
#endif
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
    if (!pkt1)
        return -1;
    pkt1->pkt = *pkt;
    pkt1->next = NULL;
    if (pkt == &flush_pkt)
        q->serial++;
    pkt1->serial = q->serial;

    if (!q->last_pkt)
        q->first_pkt = pkt1;
    else
        q->last_pkt->next = pkt1;
    q->last_pkt = pkt1;
    q->nb_packets++;
    q->size += pkt1->pkt.size + sizeof(*pkt1);
215 216
    if (pkt1->pkt.duration > 0)
        q->duration += pkt1->pkt.duration;
217 218 219 220 221 222 223 224 225 226
    /* XXX: should duplicate packet data in DV case */
    SDL_CondSignal(q->cond);
    return 0;
}

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

    /* duplicate the packet */
B
bbcallen 已提交
227
    if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
228 229 230 231 232 233
        return -1;

    SDL_LockMutex(q->mutex);
    ret = packet_queue_put_private(q, pkt);
    SDL_UnlockMutex(q->mutex);

B
bbcallen 已提交
234
    if (pkt != &flush_pkt && ret < 0)
235 236 237 238 239
        av_free_packet(pkt);

    return ret;
}

240 241 242 243 244 245 246 247 248 249
static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index)
{
    AVPacket pkt1, *pkt = &pkt1;
    av_init_packet(pkt);
    pkt->data = NULL;
    pkt->size = 0;
    pkt->stream_index = stream_index;
    return packet_queue_put(q, pkt);
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263
/* packet queue handling */
static void packet_queue_init(PacketQueue *q)
{
    memset(q, 0, sizeof(PacketQueue));
    q->mutex = SDL_CreateMutex();
    q->cond = SDL_CreateCond();
    q->abort_request = 1;
}

static void packet_queue_flush(PacketQueue *q)
{
    MyAVPacketList *pkt, *pkt1;

    SDL_LockMutex(q->mutex);
Z
Zhang Rui 已提交
264
    for (pkt = q->first_pkt; pkt; pkt = pkt1) {
265 266
        pkt1 = pkt->next;
        av_free_packet(&pkt->pkt);
267
#ifdef FFP_MERGE
268
        av_freep(&pkt);
269 270 271 272
#else
        pkt->next = q->recycle_pkt;
        q->recycle_pkt = pkt;
#endif
273 274 275 276 277
    }
    q->last_pkt = NULL;
    q->first_pkt = NULL;
    q->nb_packets = 0;
    q->size = 0;
278
    q->duration = 0;
279 280 281 282 283
    SDL_UnlockMutex(q->mutex);
}

static void packet_queue_destroy(PacketQueue *q)
{
284 285
    packet_queue_flush(q);

286 287 288 289 290 291 292 293
    SDL_LockMutex(q->mutex);
    while(q->recycle_pkt) {
        MyAVPacketList *pkt = q->recycle_pkt;
        if (pkt)
            q->recycle_pkt = pkt->next;
        av_freep(&pkt);
    }
    SDL_UnlockMutex(q->mutex);
294 295 296

    SDL_DestroyMutex(q->mutex);
    SDL_DestroyCond(q->cond);
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
}

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

    q->abort_request = 1;

    SDL_CondSignal(q->cond);

    SDL_UnlockMutex(q->mutex);
}

static void packet_queue_start(PacketQueue *q)
{
    SDL_LockMutex(q->mutex);
    q->abort_request = 0;
    packet_queue_put_private(q, &flush_pkt);
    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, int *serial)
{
    MyAVPacketList *pkt1;
    int ret;

    SDL_LockMutex(q->mutex);

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

        pkt1 = q->first_pkt;
        if (pkt1) {
            q->first_pkt = pkt1->next;
            if (!q->first_pkt)
                q->last_pkt = NULL;
            q->nb_packets--;
            q->size -= pkt1->pkt.size + sizeof(*pkt1);
339 340
            if (pkt1->pkt.duration > 0)
                q->duration -= pkt1->pkt.duration;
341 342 343
            *pkt = pkt1->pkt;
            if (serial)
                *serial = pkt1->serial;
344
#ifdef FFP_MERGE
345
            av_free(pkt1);
346 347 348 349
#else
            pkt1->next = q->recycle_pkt;
            q->recycle_pkt = pkt1;
#endif
350 351 352 353 354 355 356 357 358 359 360 361 362
            ret = 1;
            break;
        } else if (!block) {
            ret = 0;
            break;
        } else {
            SDL_CondWait(q->cond, q->mutex);
        }
    }
    SDL_UnlockMutex(q->mutex);
    return ret;
}

363
static int packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int *finished)
364
{
365
    assert(finished);
366 367 368
    if (!ffp->packet_buffering)
        return packet_queue_get(q, pkt, 1, serial);

369 370 371 372 373
    while (1) {
        int new_packet = packet_queue_get(q, pkt, 0, serial);
        if (new_packet < 0)
            return -1;
        else if (new_packet == 0) {
374
            if (q->is_buffer_indicator && !*finished)
375 376 377 378 379 380
                ffp_toggle_buffering(ffp, 1);
            new_packet = packet_queue_get(q, pkt, 1, serial);
            if (new_packet < 0)
                return -1;
        }

381
        if (*finished == *serial) {
B
bbcallen 已提交
382
            av_free_packet(pkt);
B
bbcallen 已提交
383
            continue;
B
bbcallen 已提交
384
        }
385 386 387 388 389 390 391
        else
            break;
    }

    return 1;
}

392 393 394 395 396
static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
    memset(d, 0, sizeof(Decoder));
    d->avctx = avctx;
    d->queue = queue;
    d->empty_queue_cond = empty_queue_cond;
397
    d->start_pts = AV_NOPTS_VALUE;
Z
Zhang Rui 已提交
398

Z
Zhang Rui 已提交
399 400 401
    d->first_frame_decoded_time = SDL_GetTickHR();
    d->first_frame_decoded = 0;

Z
Zhang Rui 已提交
402
    SDL_ProfilerReset(&d->decode_profiler, -1);
403 404
}

405
static int decoder_decode_frame(FFPlayer *ffp, Decoder *d, AVFrame *frame, AVSubtitle *sub) {
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
    int got_frame = 0;

    do {
        int ret = -1;

        if (d->queue->abort_request)
            return -1;

        if (!d->packet_pending || d->queue->serial != d->pkt_serial) {
            AVPacket pkt;
            do {
                if (d->queue->nb_packets == 0)
                    SDL_CondSignal(d->empty_queue_cond);
                if (packet_queue_get_or_buffering(ffp, d->queue, &pkt, &d->pkt_serial, &d->finished) < 0)
                    return -1;
                if (pkt.data == flush_pkt.data) {
                    avcodec_flush_buffers(d->avctx);
                    d->finished = 0;
424 425
                    d->next_pts = d->start_pts;
                    d->next_pts_tb = d->start_pts_tb;
426 427 428 429 430 431 432 433
                }
            } while (pkt.data == flush_pkt.data || d->queue->serial != d->pkt_serial);
            av_free_packet(&d->pkt);
            d->pkt_temp = d->pkt = pkt;
            d->packet_pending = 1;
        }

        switch (d->avctx->codec_type) {
434
            case AVMEDIA_TYPE_VIDEO: {
435
#ifdef FFP_SHOW_VDPS
Z
Zhang Rui 已提交
436
                SDL_ProfilerBegin(&d->decode_profiler);
437
#endif
438
                ret = avcodec_decode_video2(d->avctx, frame, &got_frame, &d->pkt_temp);
439
#ifdef FFP_SHOW_VDPS
Z
Zhang Rui 已提交
440 441 442 443 444 445 446 447
                int64_t delta = SDL_ProfilerEnd(&d->decode_profiler);
                if (delta >= 30) {
                    av_log(ffp, AV_LOG_DEBUG,
                           "vdps[%d]: %"PRId64" ms/frame, vdps=%f, +%"PRId64"\n",
                           d->decode_profiler.total_counter,
                           d->decode_profiler.average_elapsed,
                           d->decode_profiler.sample_per_seconds,
                           delta);
448 449
                }
#endif
450 451 452 453 454 455 456 457 458
                if (got_frame) {
                    if (ffp->decoder_reorder_pts == -1) {
                        frame->pts = av_frame_get_best_effort_timestamp(frame);
                    } else if (ffp->decoder_reorder_pts) {
                        frame->pts = frame->pkt_pts;
                    } else {
                        frame->pts = frame->pkt_dts;
                    }
                }
459
                }
460 461
                break;
            case AVMEDIA_TYPE_AUDIO:
462 463 464 465 466 467
                ret = avcodec_decode_audio4(d->avctx, frame, &got_frame, &d->pkt_temp);
                if (got_frame) {
                    AVRational tb = (AVRational){1, frame->sample_rate};
                    if (frame->pts != AV_NOPTS_VALUE)
                        frame->pts = av_rescale_q(frame->pts, d->avctx->time_base, tb);
                    else if (frame->pkt_pts != AV_NOPTS_VALUE)
468
                        frame->pts = av_rescale_q(frame->pkt_pts, av_codec_get_pkt_timebase(d->avctx), tb);
469 470 471 472 473 474 475
                    else if (d->next_pts != AV_NOPTS_VALUE)
                        frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
                    if (frame->pts != AV_NOPTS_VALUE) {
                        d->next_pts = frame->pts + frame->nb_samples;
                        d->next_pts_tb = tb;
                    }
                }
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
                break;
            // FFP_MERGE: case AVMEDIA_TYPE_SUBTITLE:
            default:
                break;
        }

        if (ret < 0) {
            d->packet_pending = 0;
        } else {
            d->pkt_temp.dts =
            d->pkt_temp.pts = AV_NOPTS_VALUE;
            if (d->pkt_temp.data) {
                if (d->avctx->codec_type != AVMEDIA_TYPE_AUDIO)
                    ret = d->pkt_temp.size;
                d->pkt_temp.data += ret;
                d->pkt_temp.size -= ret;
                if (d->pkt_temp.size <= 0)
                    d->packet_pending = 0;
            } else {
                if (!got_frame) {
                    d->packet_pending = 0;
                    d->finished = d->pkt_serial;
                }
            }
        }
    } while (!got_frame && !d->finished);

    return got_frame;
}

static void decoder_destroy(Decoder *d) {
    av_free_packet(&d->pkt);
}

510 511 512
static void frame_queue_unref_item(Frame *vp)
{
    av_frame_unref(vp->frame);
Z
Zhang Rui 已提交
513
    SDL_VoutUnrefYUVOverlay(vp->bmp);
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 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
#ifdef FFP_MERGE
    avsubtitle_free(&vp->sub);
#endif
}

static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
{
    int i;
    memset(f, 0, sizeof(FrameQueue));
    if (!(f->mutex = SDL_CreateMutex()))
        return AVERROR(ENOMEM);
    if (!(f->cond = SDL_CreateCond()))
        return AVERROR(ENOMEM);
    f->pktq = pktq;
    f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
    f->keep_last = !!keep_last;
    for (i = 0; i < f->max_size; i++)
        if (!(f->queue[i].frame = av_frame_alloc()))
            return AVERROR(ENOMEM);
    return 0;
}

static void frame_queue_destory(FrameQueue *f)
{
    int i;
    for (i = 0; i < f->max_size; i++) {
        Frame *vp = &f->queue[i];
        frame_queue_unref_item(vp);
        av_frame_free(&vp->frame);
        free_picture(vp);
    }
    SDL_DestroyMutex(f->mutex);
    SDL_DestroyCond(f->cond);
}

static void frame_queue_signal(FrameQueue *f)
{
    SDL_LockMutex(f->mutex);
    SDL_CondSignal(f->cond);
    SDL_UnlockMutex(f->mutex);
}

static Frame *frame_queue_peek(FrameQueue *f)
{
    return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
}

static Frame *frame_queue_peek_next(FrameQueue *f)
{
    return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
}

static Frame *frame_queue_peek_last(FrameQueue *f)
{
    return &f->queue[f->rindex];
}

static Frame *frame_queue_peek_writable(FrameQueue *f)
{
    /* wait until we have space to put a new frame */
    SDL_LockMutex(f->mutex);
    while (f->size >= f->max_size &&
           !f->pktq->abort_request) {
        SDL_CondWait(f->cond, f->mutex);
    }
    SDL_UnlockMutex(f->mutex);

    if (f->pktq->abort_request)
        return NULL;

    return &f->queue[f->windex];
}

587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
static Frame *frame_queue_peek_readable(FrameQueue *f)
{
    /* wait until we have a readable a new frame */
    SDL_LockMutex(f->mutex);
    while (f->size - f->rindex_shown <= 0 &&
           !f->pktq->abort_request) {
        SDL_CondWait(f->cond, f->mutex);
    }
    SDL_UnlockMutex(f->mutex);

    if (f->pktq->abort_request)
        return NULL;

    return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
}

603 604 605 606 607 608
static void frame_queue_push(FrameQueue *f)
{
    if (++f->windex == f->max_size)
        f->windex = 0;
    SDL_LockMutex(f->mutex);
    f->size++;
609
    SDL_CondSignal(f->cond);
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 638 639 640 641
    SDL_UnlockMutex(f->mutex);
}

static void frame_queue_next(FrameQueue *f)
{
    if (f->keep_last && !f->rindex_shown) {
        f->rindex_shown = 1;
        return;
    }
    frame_queue_unref_item(&f->queue[f->rindex]);
    if (++f->rindex == f->max_size)
        f->rindex = 0;
    SDL_LockMutex(f->mutex);
    f->size--;
    SDL_CondSignal(f->cond);
    SDL_UnlockMutex(f->mutex);
}

/* jump back to the previous frame if available by resetting rindex_shown */
static int frame_queue_prev(FrameQueue *f)
{
    int ret = f->rindex_shown;
    f->rindex_shown = 0;
    return ret;
}

/* return the number of undisplayed frames in the queue */
static int frame_queue_nb_remaining(FrameQueue *f)
{
    return f->size - f->rindex_shown;
}

642
/* return last shown position */
Z
Zhang Rui 已提交
643
#ifdef FFP_MERGE
644 645 646 647 648 649 650 651
static int64_t frame_queue_last_pos(FrameQueue *f)
{
    Frame *fp = &f->queue[f->rindex];
    if (f->rindex_shown && fp->serial == f->pktq->serial)
        return fp->pos;
    else
        return -1;
}
Z
Zhang Rui 已提交
652
#endif
653

654 655 656 657 658 659 660 661 662
static void decoder_abort(Decoder *d, FrameQueue *fq)
{
    packet_queue_abort(d->queue);
    frame_queue_signal(fq);
    SDL_WaitThread(d->decoder_tid, NULL);
    d->decoder_tid = NULL;
    packet_queue_flush(d->queue);
}

Z
Zhang Rui 已提交
663 664 665 666 667 668 669 670
// FFP_MERGE: fill_rectangle
// FFP_MERGE: fill_border
// FFP_MERGE: ALPHA_BLEND
// FFP_MERGE: RGBA_IN
// FFP_MERGE: YUVA_IN
// FFP_MERGE: YUVA_OUT
// FFP_MERGE: BPP
// FFP_MERGE: blend_subrect
671

672
static void free_picture(Frame *vp)
673 674 675 676 677 678 679
{
    if (vp->bmp) {
        SDL_VoutFreeYUVOverlay(vp->bmp);
        vp->bmp = NULL;
    }
}

Z
Zhang Rui 已提交
680 681
// FFP_MERGE: calculate_display_rect
// FFP_MERGE: video_image_display
682

Z
Zhang Rui 已提交
683 684 685 686
#ifdef FFP_SHOW_FPS
static int g_fps_counter = 0;
static int64_t g_fps_total_time = 0;
#endif
Z
Zhang Rui 已提交
687
static void video_image_display2(FFPlayer *ffp)
688
{
689
    VideoState *is = ffp->is;
690
    Frame *vp;
691

692
    vp = frame_queue_peek(&is->pictq);
693
    if (vp->bmp) {
Z
Zhang Rui 已提交
694 695 696
#ifdef FFP_SHOW_FPS
        int64_t start = SDL_GetTickHR();
#endif
697
        SDL_VoutDisplayYUVOverlay(ffp->vout, vp->bmp);
Z
Zhang Rui 已提交
698 699
        if (!ffp->first_video_frame_rendered) {
            ffp->first_video_frame_rendered = 1;
700 701
            ffp_notify_msg1(ffp, FFP_MSG_VIDEO_RENDERING_START);
        }
Z
Zhang Rui 已提交
702 703 704 705
#ifdef FFP_SHOW_FPS
        int64_t dur = SDL_GetTickHR() - start;
        g_fps_total_time += dur;
        g_fps_counter++;
B
bbcallen 已提交
706 707 708 709 710 711
        int64_t avg_frame_time = 0;
        if (g_fps_counter > 0)
            avg_frame_time = g_fps_total_time / g_fps_counter;
        double fps = 0;
        if (avg_frame_time > 0)
            fps = 1.0f / avg_frame_time * 1000;
712
        av_log(ffp, AV_LOG_DEBUG, "fps:  [%f][%d] %"PRId64" ms/frame, fps=%f, +%"PRId64"\n",
Z
Zhang Rui 已提交
713
            vp->pts, g_fps_counter, (int64_t)avg_frame_time, fps, dur);
714 715 716 717
        if (g_fps_total_time >= FFP_XPS_PERIOD) {
            g_fps_total_time -= avg_frame_time;
            g_fps_counter--;
        }
Z
Zhang Rui 已提交
718
#endif
719 720 721
    }
}

Z
Zhang Rui 已提交
722 723
// FFP_MERGE: compute_mod
// FFP_MERGE: video_audio_display
724

725
static void stream_close(VideoState *is)
726 727 728
{
    /* XXX: use a special url_shutdown call to abort parse cleanly */
    is->abort_request = 1;
729 730
    packet_queue_abort(&is->videoq);
    packet_queue_abort(&is->audioq);
731
    av_log(NULL, AV_LOG_DEBUG, "wait for read_tid\n");
732
    SDL_WaitThread(is->read_tid, NULL);
733
    av_log(NULL, AV_LOG_DEBUG, "wait for video_refresh_tid\n");
Z
Zhang Rui 已提交
734 735
    SDL_WaitThread(is->video_refresh_tid, NULL);

736 737
    packet_queue_destroy(&is->videoq);
    packet_queue_destroy(&is->audioq);
Z
Zhang Rui 已提交
738
#ifdef FFP_MERGE
739
    packet_queue_destroy(&is->subtitleq);
Z
Zhang Rui 已提交
740
#endif
741 742

    /* free all pictures */
743
    frame_queue_destory(&is->pictq);
Z
Zhang Rui 已提交
744
    frame_queue_destory(&is->sampq);
Z
Zhang Rui 已提交
745
#ifdef FFP_MERGE
746
    frame_queue_destory(&is->subpq);
Z
Zhang Rui 已提交
747
#endif
748
    SDL_DestroyCond(is->continue_read_thread);
749
    SDL_DestroyMutex(is->play_mutex);
750 751
#if !CONFIG_AVFILTER
    sws_freeContext(is->img_convert_ctx);
752 753 754
#endif
#ifdef FFP_MERGE
    sws_freeContext(is->sub_convert_ctx);
755 756 757 758
#endif
    av_free(is);
}

Z
Zhang Rui 已提交
759 760 761 762
// FFP_MERGE: do_exit
// FFP_MERGE: sigterm_handler
// FFP_MERGE: video_open
// FFP_MERGE: video_display
763 764

/* display the current picture, if any */
Z
Zhang Rui 已提交
765
static void video_display2(FFPlayer *ffp)
766
{
Z
Zhang Rui 已提交
767 768 769
    VideoState *is = ffp->is;
    if (is->video_st)
        video_image_display2(ffp);
770 771
}

Z
Zhang Rui 已提交
772
static double get_clock(Clock *c)
773
{
Z
Zhang Rui 已提交
774
    if (*c->queue_serial != c->serial)
775
        return NAN;
Z
Zhang Rui 已提交
776 777
    if (c->paused) {
        return c->pts;
778
    } else {
Z
Zhang Rui 已提交
779
        double time = av_gettime_relative() / 1000000.0;
Z
Zhang Rui 已提交
780
        return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
781 782 783
    }
}

Z
Zhang Rui 已提交
784
static void set_clock_at(Clock *c, double pts, int serial, double time)
785
{
Z
Zhang Rui 已提交
786 787 788 789
    c->pts = pts;
    c->last_updated = time;
    c->pts_drift = c->pts - time;
    c->serial = serial;
790 791
}

Z
Zhang Rui 已提交
792
static void set_clock(Clock *c, double pts, int serial)
793
{
Z
Zhang Rui 已提交
794
    double time = av_gettime_relative() / 1000000.0;
Z
Zhang Rui 已提交
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
    set_clock_at(c, pts, serial, time);
}

static void set_clock_speed(Clock *c, double speed)
{
    set_clock(c, get_clock(c), c->serial);
    c->speed = speed;
}

static void init_clock(Clock *c, int *queue_serial)
{
    c->speed = 1.0;
    c->paused = 0;
    c->queue_serial = queue_serial;
    set_clock(c, NAN, -1);
}

static void sync_clock_to_slave(Clock *c, Clock *slave)
{
    double clock = get_clock(c);
    double slave_clock = get_clock(slave);
    if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
        set_clock(c, slave_clock, slave->serial);
818 819
}

Z
Zhang Rui 已提交
820
static int get_master_sync_type(VideoState *is) {
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
    if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
        if (is->video_st)
            return AV_SYNC_VIDEO_MASTER;
        else
            return AV_SYNC_AUDIO_MASTER;
    } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
        if (is->audio_st)
            return AV_SYNC_AUDIO_MASTER;
        else
            return AV_SYNC_EXTERNAL_CLOCK;
    } else {
        return AV_SYNC_EXTERNAL_CLOCK;
    }
}

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

    switch (get_master_sync_type(is)) {
Z
Zhang Rui 已提交
842
        case AV_SYNC_VIDEO_MASTER:
Z
Zhang Rui 已提交
843
            val = get_clock(&is->vidclk);
Z
Zhang Rui 已提交
844 845
            break;
        case AV_SYNC_AUDIO_MASTER:
Z
Zhang Rui 已提交
846
            val = get_clock(&is->audclk);
Z
Zhang Rui 已提交
847 848
            break;
        default:
Z
Zhang Rui 已提交
849
            val = get_clock(&is->extclk);
Z
Zhang Rui 已提交
850
            break;
851 852 853 854
    }
    return val;
}

Z
Zhang Rui 已提交
855
static void check_external_clock_speed(VideoState *is) {
856 857
   if ((is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) ||
       (is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES)) {
Z
Zhang Rui 已提交
858
       set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP));
859 860
   } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
              (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
Z
Zhang Rui 已提交
861
       set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP));
Z
Zhang Rui 已提交
862
   } else {
Z
Zhang Rui 已提交
863
       double speed = is->extclk.speed;
Z
Zhang Rui 已提交
864
       if (speed != 1.0)
Z
Zhang Rui 已提交
865
           set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
Z
Zhang Rui 已提交
866
   }
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
}

/* seek in the stream */
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
{
    if (!is->seek_req) {
        is->seek_pos = pos;
        is->seek_rel = rel;
        is->seek_flags &= ~AVSEEK_FLAG_BYTE;
        if (seek_by_bytes)
            is->seek_flags |= AVSEEK_FLAG_BYTE;
        is->seek_req = 1;
        SDL_CondSignal(is->continue_read_thread);
    }
}

/* pause or resume the video */
884
static void stream_toggle_pause_l(FFPlayer *ffp, int pause_on)
885
{
886
    VideoState *is = ffp->is;
Z
Zhang Rui 已提交
887
    if (is->paused && !pause_on) {
888
        is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
Z
Zhang Rui 已提交
889

890
#ifdef FFP_MERGE
891
        if (is->read_pause_return != AVERROR(ENOSYS)) {
Z
Zhang Rui 已提交
892
            is->vidclk.paused = 0;
893
        }
894
#endif
Z
Zhang Rui 已提交
895
        set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
896
    } else {
897
    }
Z
Zhang Rui 已提交
898
    set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
899
    is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = pause_on;
900 901

    SDL_AoutPauseAudio(ffp->aout, pause_on);
902 903
}

904 905 906 907 908 909 910 911 912 913
static void stream_update_pause_l(FFPlayer *ffp)
{
    VideoState *is = ffp->is;
    if (!is->step && (is->pause_req || is->buffering_on)) {
        stream_toggle_pause_l(ffp, 1);
    } else {
        stream_toggle_pause_l(ffp, 0);
    }
}

914
static void toggle_pause_l(FFPlayer *ffp, int pause_on)
915 916
{
    VideoState *is = ffp->is;
917
    is->pause_req = pause_on;
Z
Zhang Rui 已提交
918
    ffp->auto_resume = !pause_on;
919
    stream_update_pause_l(ffp);
920 921
    is->step = 0;
}
922

923 924 925 926 927 928 929
static void toggle_pause(FFPlayer *ffp, int pause_on)
{
    SDL_LockMutex(ffp->is->play_mutex);
    toggle_pause_l(ffp, pause_on);
    SDL_UnlockMutex(ffp->is->play_mutex);
}

930
static void step_to_next_frame_l(FFPlayer *ffp)
931
{
932
    VideoState *is = ffp->is;
933 934
    /* if the stream is paused unpause it, then step */
    if (is->paused)
935
        stream_toggle_pause_l(ffp, 0);
936 937
    is->step = 1;
}
938 939 940

static double compute_target_delay(double delay, VideoState *is)
{
941
    double sync_threshold, diff = 0;
942 943 944 945

    /* update delay to follow master synchronisation source */
    if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) {
        /* if video is slave, we try to correct big delays by
Z
Zhang Rui 已提交
946
           duplicating or deleting a frame */
Z
Zhang Rui 已提交
947
        diff = get_clock(&is->vidclk) - get_master_clock(is);
948 949

        /* skip or repeat frame. We take into account the
Z
Zhang Rui 已提交
950 951
           delay to compute the threshold. I still don't know
           if it is the best guess */
Z
Zhang Rui 已提交
952 953
        sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
        if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
954
            if (diff <= -sync_threshold)
Z
Zhang Rui 已提交
955 956 957
                delay = FFMAX(0, delay + diff);
            else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
                delay = delay + diff;
958 959 960 961 962
            else if (diff >= sync_threshold)
                delay = 2 * delay;
        }
    }

Z
Zhang Rui 已提交
963
#ifdef FFP_SHOW_AUDIO_DELAY
964
    av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
Z
Zhang Rui 已提交
965
            delay, -diff);
Z
Zhang Rui 已提交
966
#endif
967 968 969 970

    return delay;
}

971
static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
Z
Zhang Rui 已提交
972 973 974 975 976 977 978 979 980 981 982
    if (vp->serial == nextvp->serial) {
        double duration = nextvp->pts - vp->pts;
        if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
            return vp->duration;
        else
            return duration;
    } else {
        return 0.0;
    }
}

Z
Zhang Rui 已提交
983
static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) {
984
    /* update current video pts */
Z
Zhang Rui 已提交
985 986
    set_clock(&is->vidclk, pts, serial);
    sync_clock_to_slave(&is->extclk, &is->vidclk);
987 988 989 990 991 992
}

/* called to display each frame */
static void video_refresh(FFPlayer *opaque, double *remaining_time)
{
    FFPlayer *ffp = opaque;
993
    VideoState *is = ffp->is;
994 995
    double time;

Z
Zhang Rui 已提交
996
#ifdef FFP_MERGE
997
    Frame *sp, *sp2;
Z
Zhang Rui 已提交
998
#endif
999 1000 1001 1002 1003

    if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
        check_external_clock_speed(is);

    if (!ffp->display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
Z
Zhang Rui 已提交
1004
        time = av_gettime_relative() / 1000000.0;
1005
        if (is->force_refresh || is->last_vis_time + ffp->rdftspeed < time) {
Z
Zhang Rui 已提交
1006
            video_display2(ffp);
1007 1008 1009 1010 1011 1012 1013 1014
            is->last_vis_time = time;
        }
        *remaining_time = FFMIN(*remaining_time, is->last_vis_time + ffp->rdftspeed - time);
    }

    if (is->video_st) {
        int redisplay = 0;
        if (is->force_refresh)
1015
            redisplay = frame_queue_prev(&is->pictq);
Z
Zhang Rui 已提交
1016
retry:
1017
        if (frame_queue_nb_remaining(&is->pictq) == 0) {
1018 1019 1020
            // nothing to do, no picture to display in the queue
        } else {
            double last_duration, duration, delay;
1021
            Frame *vp, *lastvp;
Z
Zhang Rui 已提交
1022

1023
            /* dequeue the picture */
1024 1025
            lastvp = frame_queue_peek_last(&is->pictq);
            vp = frame_queue_peek(&is->pictq);
1026 1027

            if (vp->serial != is->videoq.serial) {
1028
                frame_queue_next(&is->pictq);
1029 1030 1031 1032
                redisplay = 0;
                goto retry;
            }

Z
Zhang Rui 已提交
1033
            if (lastvp->serial != vp->serial && !redisplay)
Z
Zhang Rui 已提交
1034
                is->frame_timer = av_gettime_relative() / 1000000.0;
Z
Zhang Rui 已提交
1035

1036 1037 1038 1039
            if (is->paused)
                goto display;

            /* compute nominal last_duration */
Z
Zhang Rui 已提交
1040
            last_duration = vp_duration(is, lastvp, vp);
Z
Zhang Rui 已提交
1041 1042 1043
            if (redisplay)
                delay = 0.0;
            else
Z
Zhang Rui 已提交
1044
                delay = compute_target_delay(last_duration, is);
1045

Z
Zhang Rui 已提交
1046
            time= av_gettime_relative()/1000000.0;
Z
Zhang Rui 已提交
1047 1048
            if (isnan(is->frame_timer) || time < is->frame_timer)
                is->frame_timer = time;
Z
Zhang Rui 已提交
1049
            if (time < is->frame_timer + delay && !redisplay) {
1050 1051 1052 1053
                *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
                return;
            }

Z
Zhang Rui 已提交
1054 1055 1056
            is->frame_timer += delay;
            if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
                is->frame_timer = time;
1057

1058
            SDL_LockMutex(is->pictq.mutex);
Z
Zhang Rui 已提交
1059 1060
            if (!redisplay && !isnan(vp->pts))
                update_video_pts(is, vp->pts, vp->pos, vp->serial);
1061
            SDL_UnlockMutex(is->pictq.mutex);
1062

1063 1064
            if (frame_queue_nb_remaining(&is->pictq) > 1) {
                Frame *nextvp = frame_queue_peek_next(&is->pictq);
Z
Zhang Rui 已提交
1065
                duration = vp_duration(is, vp, nextvp);
Z
Zhang Rui 已提交
1066
                if(!is->step && (redisplay || ffp->framedrop > 0 || (ffp->framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration) {
1067 1068
                    if (!redisplay)
                        is->frame_drops_late++;
1069
                    frame_queue_next(&is->pictq);
1070 1071 1072 1073 1074
                    redisplay = 0;
                    goto retry;
                }
            }

Z
Zhang Rui 已提交
1075
            // FFP_MERGE: if (is->subtitle_st) { {...}
1076

Z
Zhang Rui 已提交
1077
display:
1078 1079
            /* display picture */
            if (!ffp->display_disable && is->show_mode == SHOW_MODE_VIDEO)
Z
Zhang Rui 已提交
1080
                video_display2(ffp);
1081

1082
            frame_queue_next(&is->pictq);
1083

1084
            SDL_LockMutex(ffp->is->play_mutex);
1085 1086 1087 1088 1089
            if (is->step) {
                is->step = 0;
                if (!is->paused)
                    stream_update_pause_l(ffp);
            }
1090
            SDL_UnlockMutex(ffp->is->play_mutex);
1091 1092 1093
        }
    }
    is->force_refresh = 0;
Z
Zhang Rui 已提交
1094 1095 1096
    if (ffp->show_status) {
        static int64_t last_time;
        int64_t cur_time;
Z
Zhang Rui 已提交
1097
        int aqsize, vqsize, sqsize __unused;
Z
Zhang Rui 已提交
1098 1099
        double av_diff;

Z
Zhang Rui 已提交
1100
        cur_time = av_gettime_relative();
Z
Zhang Rui 已提交
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
        if (!last_time || (cur_time - last_time) >= 30000) {
            aqsize = 0;
            vqsize = 0;
            sqsize = 0;
            if (is->audio_st)
                aqsize = is->audioq.size;
            if (is->video_st)
                vqsize = is->videoq.size;
#ifdef FFP_MERGE
            if (is->subtitle_st)
                sqsize = is->subtitleq.size;
#else
            sqsize = 0;
#endif
            av_diff = 0;
            if (is->audio_st && is->video_st)
                av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
            else if (is->video_st)
                av_diff = get_master_clock(is) - get_clock(&is->vidclk);
            else if (is->audio_st)
                av_diff = get_master_clock(is) - get_clock(&is->audclk);
            av_log(NULL, AV_LOG_INFO,
                   "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64"   \r",
                   get_master_clock(is),
                   (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : "   ")),
                   av_diff,
                   is->frame_drops_early + is->frame_drops_late,
                   aqsize / 1024,
                   vqsize / 1024,
                   sqsize,
                   is->video_st ? is->video_st->codec->pts_correction_num_faulty_dts : 0,
                   is->video_st ? is->video_st->codec->pts_correction_num_faulty_pts : 0);
            fflush(stdout);
            last_time = cur_time;
        }
    }
1137
}
1138

1139
/* allocate a picture (needs to do that in main thread to avoid
Z
Zhang Rui 已提交
1140
   potential locking problems */
1141 1142
static void alloc_picture(FFPlayer *ffp)
{
1143
    VideoState *is = ffp->is;
1144
    Frame *vp;
B
bbcallen 已提交
1145
#ifdef FFP_MERGE
Z
Zhang Rui 已提交
1146
    int64_t bufferdiff;
B
bbcallen 已提交
1147
#endif
1148

1149
    vp = &is->pictq.queue[is->pictq.windex];
1150

1151
    free_picture(vp);
1152

Z
Zhang Rui 已提交
1153
#ifdef FFP_MERGE
1154
    video_open(ffp, 0, vp);
Z
Zhang Rui 已提交
1155
#endif
1156

1157
    vp->bmp = SDL_Vout_CreateOverlay(vp->width, vp->height,
Z
Zhang Rui 已提交
1158
                                   ffp->overlay_format,
Z
Zhang Rui 已提交
1159
                                   ffp->vout);
1160
#ifdef FFP_MERGE
Z
Zhang Rui 已提交
1161 1162
    bufferdiff = vp->bmp ? FFMAX(vp->bmp->pixels[0], vp->bmp->pixels[1]) - FFMIN(vp->bmp->pixels[0], vp->bmp->pixels[1]) : 0;
    if (!vp->bmp || vp->bmp->pitches[0] < vp->width || bufferdiff < (int64_t)vp->height * vp->bmp->pitches[0]) {
1163 1164
#else
    /* RV16, RV32 contains only one plane */
1165
    if (!vp->bmp || (!vp->bmp->is_private && vp->bmp->pitches[0] < vp->width)) {
1166
#endif
1167 1168
        /* SDL allocates a buffer smaller than requested if the video
         * overlay hardware is unable to support the requested size. */
Z
Zhang Rui 已提交
1169 1170
        av_log(NULL, AV_LOG_FATAL,
               "Error: the video system does not support an image\n"
Z
Zhang Rui 已提交
1171 1172
                        "size of %dx%d pixels. Try using -lowres or -vf \"scale=w:h\"\n"
                        "to reduce the image size.\n", vp->width, vp->height );
1173
        free_picture(vp);
1174 1175
    }

1176
    SDL_LockMutex(is->pictq.mutex);
1177
    vp->allocated = 1;
1178 1179
    SDL_CondSignal(is->pictq.cond);
    SDL_UnlockMutex(is->pictq.mutex);
1180 1181
}

Z
Zhang Rui 已提交
1182
#ifdef FFP_MERGE
Z
Zhang Rui 已提交
1183
static void duplicate_right_border_pixels(SDL_Overlay *bmp) {
1184 1185 1186
    int i, width, height;
    Uint8 *p, *maxp;
    for (i = 0; i < 3; i++) {
Z
Zhang Rui 已提交
1187
        width  = bmp->w;
1188 1189
        height = bmp->h;
        if (i > 0) {
Z
Zhang Rui 已提交
1190
            width  >>= 1;
1191 1192 1193 1194 1195
            height >>= 1;
        }
        if (bmp->pitches[i] > width) {
            maxp = bmp->pixels[i] + bmp->pitches[i] * height - 1;
            for (p = bmp->pixels[i] + width - 1; p < maxp; p += bmp->pitches[i])
Z
Zhang Rui 已提交
1196
                *(p+1) = *p;
1197 1198 1199
        }
    }
}
Z
Zhang Rui 已提交
1200
#endif
1201

Z
Zhang Rui 已提交
1202
static int queue_picture(FFPlayer *ffp, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
1203
{
1204
    VideoState *is = ffp->is;
1205
    Frame *vp;
1206 1207 1208

#if defined(DEBUG_SYNC) && 0
    printf("frame_type=%c pts=%0.3f\n",
Z
Zhang Rui 已提交
1209
           av_get_picture_type_char(src_frame->pict_type), pts);
1210 1211
#endif

1212
    if (!(vp = frame_queue_peek_writable(&is->pictq)))
1213 1214
        return -1;

Z
Zhang Rui 已提交
1215
    vp->sar = src_frame->sample_aspect_ratio;
1216 1217 1218

    /* alloc or resize hardware picture buffer */
    if (!vp->bmp || vp->reallocate || !vp->allocated ||
Z
Zhang Rui 已提交
1219
        vp->width  != src_frame->width ||
Z
Zhang Rui 已提交
1220
        vp->height != src_frame->height) {
Z
Zhang Rui 已提交
1221 1222

        if (vp->width != src_frame->width || vp->height != src_frame->height)
1223
            ffp_notify_msg3(ffp, FFP_MSG_VIDEO_SIZE_CHANGED, src_frame->width, src_frame->height);
Z
Zhang Rui 已提交
1224

Z
Zhang Rui 已提交
1225
        vp->allocated  = 0;
1226 1227 1228 1229 1230
        vp->reallocate = 0;
        vp->width = src_frame->width;
        vp->height = src_frame->height;

        /* the allocation must be done in the main thread to avoid
Z
Zhang Rui 已提交
1231
           locking problems. */
1232
        alloc_picture(ffp);
1233 1234 1235 1236 1237 1238 1239 1240

        if (is->videoq.abort_request)
            return -1;
    }

    /* if the frame is not skipped, then display it */
    if (vp->bmp) {
        /* get a pointer on the bitmap */
Z
Zhang Rui 已提交
1241
        SDL_VoutLockYUVOverlay(vp->bmp);
1242

1243
        if (SDL_VoutFFmpeg_ConvertFrame(vp->bmp, src_frame,
Z
Zhang Rui 已提交
1244
            &is->img_convert_ctx, ffp->sws_flags) < 0) {
Z
Zhang Rui 已提交
1245
            av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
1246 1247 1248
            exit(1);
        }
        /* update the bitmap content */
1249
        SDL_VoutUnlockYUVOverlay(vp->bmp);
1250 1251

        vp->pts = pts;
Z
Zhang Rui 已提交
1252
        vp->duration = duration;
1253 1254 1255
        vp->pos = pos;
        vp->serial = serial;

Z
Zhang Rui 已提交
1256 1257 1258
        vp->bmp->sar_num = vp->sar.num;
        vp->bmp->sar_den = vp->sar.den;

1259
        /* now we can update the picture count */
1260
        frame_queue_push(&is->pictq);
Z
Zhang Rui 已提交
1261
        if (!is->viddec.first_frame_decoded) {
1262
            ALOGD("avcodec/Video: first frame decoded\n");
Z
Zhang Rui 已提交
1263 1264 1265
            is->viddec.first_frame_decoded_time = SDL_GetTickHR();
            is->viddec.first_frame_decoded = 1;
        }
1266 1267 1268 1269
    }
    return 0;
}

1270
static int get_video_frame(FFPlayer *ffp, AVFrame *frame)
1271
{
1272
    VideoState *is = ffp->is;
1273 1274
    int got_picture;

1275
    if ((got_picture = decoder_decode_frame(ffp, &is->viddec, frame, NULL)) < 0)
1276
        return -1;
1277 1278

    if (got_picture) {
Z
Zhang Rui 已提交
1279
        double dpts = NAN;
1280

Z
Zhang Rui 已提交
1281 1282 1283 1284
        if (frame->pts != AV_NOPTS_VALUE)
            dpts = av_q2d(is->video_st->time_base) * frame->pts;

        frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
1285

1286 1287 1288 1289 1290
#ifdef FFP_MERGE
        is->viddec_width  = frame->width;
        is->viddec_height = frame->height;
#endif

B
bbcallen 已提交
1291
        if (ffp->framedrop>0 || (ffp->framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
Z
Zhang Rui 已提交
1292 1293 1294 1295
            if (frame->pts != AV_NOPTS_VALUE) {
                double diff = dpts - get_master_clock(is);
                if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
                    diff - is->frame_last_filter_delay < 0 &&
1296
                    is->viddec.pkt_serial == is->vidclk.serial &&
Z
Zhang Rui 已提交
1297
                    is->videoq.nb_packets) {
B
bbcallen 已提交
1298
                    is->frame_drops_early++;
Z
Zhang Rui 已提交
1299 1300 1301 1302 1303 1304 1305
                    is->continuous_frame_drops_early++;
                    if (is->continuous_frame_drops_early > ffp->framedrop) {
                        is->continuous_frame_drops_early = 0;
                    } else {
                        av_frame_unref(frame);
                        got_picture = 0;
                    }
1306 1307 1308 1309
                }
            }
        }
    }
Z
Zhang Rui 已提交
1310

1311
    return got_picture;
1312 1313
}

1314 1315
#if CONFIG_AVFILTER
static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
Z
Zhang Rui 已提交
1316
                                 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
1317
{
Z
Zhang Rui 已提交
1318 1319
    int ret, i;
    int nb_filters = graph->nb_filters;
1320 1321 1322 1323
    AVFilterInOut *outputs = NULL, *inputs = NULL;

    if (filtergraph) {
        outputs = avfilter_inout_alloc();
Z
Zhang Rui 已提交
1324
        inputs  = avfilter_inout_alloc();
1325 1326 1327 1328 1329
        if (!outputs || !inputs) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }

Z
Zhang Rui 已提交
1330
        outputs->name       = av_strdup("in");
1331
        outputs->filter_ctx = source_ctx;
Z
Zhang Rui 已提交
1332 1333
        outputs->pad_idx    = 0;
        outputs->next       = NULL;
1334

Z
Zhang Rui 已提交
1335 1336 1337 1338
        inputs->name        = av_strdup("out");
        inputs->filter_ctx  = sink_ctx;
        inputs->pad_idx     = 0;
        inputs->next        = NULL;
1339

Z
Zhang Rui 已提交
1340
        if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
Z
Zhang Rui 已提交
1341
            goto fail;
1342 1343
    } else {
        if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
Z
Zhang Rui 已提交
1344
            goto fail;
1345 1346
    }

Z
Zhang Rui 已提交
1347 1348 1349 1350
    /* Reorder the filters to ensure that inputs of the custom filters are merged first */
    for (i = 0; i < graph->nb_filters - nb_filters; i++)
        FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);

1351
    ret = avfilter_graph_config(graph, NULL);
Z
Zhang Rui 已提交
1352
fail:
1353 1354 1355 1356 1357 1358 1359
    avfilter_inout_free(&outputs);
    avfilter_inout_free(&inputs);
    return ret;
}

static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
{
Z
Zhang Rui 已提交
1360
    static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
1361
    char sws_flags_str[512] = "";
1362 1363
    char buffersrc_args[256];
    int ret;
Z
Zhang Rui 已提交
1364
    AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
1365
    AVCodecContext *codec = is->video_st->codec;
Z
Zhang Rui 已提交
1366
    AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
    AVDictionaryEntry *e = NULL;

    while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
        if (!strcmp(e->key, "sws_flags")) {
            av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
        } else
            av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
    }
    if (strlen(sws_flags_str))
        sws_flags_str[strlen(sws_flags_str)-1] = '\0';
1377 1378 1379 1380

    graph->scale_sws_opts = av_strdup(sws_flags_str);

    snprintf(buffersrc_args, sizeof(buffersrc_args),
Z
Zhang Rui 已提交
1381 1382 1383 1384
             "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
             frame->width, frame->height, frame->format,
             is->video_st->time_base.num, is->video_st->time_base.den,
             codec->sample_aspect_ratio.num, FFMAX(codec->sample_aspect_ratio.den, 1));
Z
Zhang Rui 已提交
1385 1386
    if (fr.num && fr.den)
        av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":frame_rate=%d/%d", fr.num, fr.den);
1387 1388

    if ((ret = avfilter_graph_create_filter(&filt_src,
Z
Zhang Rui 已提交
1389 1390 1391 1392
                                            avfilter_get_by_name("buffer"),
                                            "ffplay_buffer", buffersrc_args, NULL,
                                            graph)) < 0)
        goto fail;
1393 1394

    ret = avfilter_graph_create_filter(&filt_out,
Z
Zhang Rui 已提交
1395 1396
                                       avfilter_get_by_name("buffersink"),
                                       "ffplay_buffersink", NULL, NULL, graph);
1397
    if (ret < 0)
Z
Zhang Rui 已提交
1398
        goto fail;
1399

Z
Zhang Rui 已提交
1400 1401 1402
    if ((ret = av_opt_set_int_list(filt_out, "pix_fmts", pix_fmts,  AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
        goto fail;

Z
Zhang Rui 已提交
1403 1404 1405 1406
    last_filter = filt_out;

/* Note: this macro adds a filter before the lastly added filter, so the
 * processing order of the filters is in reverse */
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420
#define INSERT_FILT(name, arg) do {                                          \
    AVFilterContext *filt_ctx;                                               \
                                                                             \
    ret = avfilter_graph_create_filter(&filt_ctx,                            \
                                       avfilter_get_by_name(name),           \
                                       "ffplay_" name, arg, NULL, graph);    \
    if (ret < 0)                                                             \
        goto fail;                                                           \
                                                                             \
    ret = avfilter_link(filt_ctx, 0, last_filter, 0);                        \
    if (ret < 0)                                                             \
        goto fail;                                                           \
                                                                             \
    last_filter = filt_ctx;                                                  \
Z
Zhang Rui 已提交
1421 1422
} while (0)

1423 1424
    /* SDL YUV code is not handling odd width/height for some driver
     * combinations, therefore we crop the picture to an even width/height. */
Z
Zhang Rui 已提交
1425 1426 1427
    INSERT_FILT("crop", "floor(in_w/2)*2:floor(in_h/2)*2");

    if (autorotate) {
1428
        double theta  = get_rotation(is->video_st);
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440

        if (fabs(theta - 90) < 1.0) {
            INSERT_FILT("transpose", "clock");
        } else if (fabs(theta - 180) < 1.0) {
            INSERT_FILT("hflip", NULL);
            INSERT_FILT("vflip", NULL);
        } else if (fabs(theta - 270) < 1.0) {
            INSERT_FILT("transpose", "cclock");
        } else if (fabs(theta) > 1.0) {
            char rotate_buf[64];
            snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
            INSERT_FILT("rotate", rotate_buf);
Z
Zhang Rui 已提交
1441 1442
        }
    }
1443

Z
Zhang Rui 已提交
1444
    if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
Z
Zhang Rui 已提交
1445
        goto fail;
1446

Z
Zhang Rui 已提交
1447
    is->in_video_filter  = filt_src;
1448 1449
    is->out_video_filter = filt_out;

Z
Zhang Rui 已提交
1450
fail:
1451 1452 1453
    return ret;
}

Z
Zhang Rui 已提交
1454 1455 1456 1457 1458 1459 1460
static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
{
    static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
    int sample_rates[2] = { 0, -1 };
    int64_t channel_layouts[2] = { 0, -1 };
    int channels[2] = { 0, -1 };
    AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
1461 1462
    char aresample_swr_opts[512] = "";
    AVDictionaryEntry *e = NULL;
Z
Zhang Rui 已提交
1463 1464 1465 1466 1467 1468 1469
    char asrc_args[256];
    int ret;

    avfilter_graph_free(&is->agraph);
    if (!(is->agraph = avfilter_graph_alloc()))
        return AVERROR(ENOMEM);

1470 1471 1472 1473 1474 1475
    while ((e = av_dict_get(swr_opts, "", e, AV_DICT_IGNORE_SUFFIX)))
        av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
    if (strlen(aresample_swr_opts))
        aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
    av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);

Z
Zhang Rui 已提交
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
    ret = snprintf(asrc_args, sizeof(asrc_args),
                   "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d",
                   is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
                   is->audio_filter_src.channels,
                   1, is->audio_filter_src.freq);
    if (is->audio_filter_src.channel_layout)
        snprintf(asrc_args + ret, sizeof(asrc_args) - ret,
                 ":channel_layout=0x%"PRIx64,  is->audio_filter_src.channel_layout);

    ret = avfilter_graph_create_filter(&filt_asrc,
                                       avfilter_get_by_name("abuffer"), "ffplay_abuffer",
                                       asrc_args, NULL, is->agraph);
    if (ret < 0)
        goto end;


    ret = avfilter_graph_create_filter(&filt_asink,
                                       avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
                                       NULL, NULL, is->agraph);
    if (ret < 0)
        goto end;

    if ((ret = av_opt_set_int_list(filt_asink, "sample_fmts", sample_fmts,  AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
        goto end;
    if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0)
        goto end;

    if (force_output_format) {
        channel_layouts[0] = is->audio_tgt.channel_layout;
        channels       [0] = is->audio_tgt.channels;
        sample_rates   [0] = is->audio_tgt.freq;
        if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0)
            goto end;
        if ((ret = av_opt_set_int_list(filt_asink, "channel_layouts", channel_layouts,  -1, AV_OPT_SEARCH_CHILDREN)) < 0)
            goto end;
        if ((ret = av_opt_set_int_list(filt_asink, "channel_counts" , channels       ,  -1, AV_OPT_SEARCH_CHILDREN)) < 0)
            goto end;
        if ((ret = av_opt_set_int_list(filt_asink, "sample_rates"   , sample_rates   ,  -1, AV_OPT_SEARCH_CHILDREN)) < 0)
            goto end;
    }


    if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
        goto end;

    is->in_audio_filter  = filt_asrc;
    is->out_audio_filter = filt_asink;

end:
    if (ret < 0)
        avfilter_graph_free(&is->agraph);
    return ret;
}
1529 1530
#endif  /* CONFIG_AVFILTER */

1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
static int audio_thread(void *arg)
{
    FFPlayer *ffp = arg;
    VideoState *is = ffp->is;
    AVFrame *frame = av_frame_alloc();
    Frame *af;
#if CONFIG_AVFILTER
    int last_serial = -1;
    int64_t dec_channel_layout;
    int reconfigure;
#endif
    int got_frame = 0;
    AVRational tb;
    int ret = 0;

1546 1547 1548 1549
    if (!frame) {
#if CONFIG_AVFILTER
        avfilter_graph_free(&graph);
#endif
1550
        return AVERROR(ENOMEM);
1551
    }
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566

    do {
        if ((got_frame = decoder_decode_frame(ffp, &is->auddec, frame, NULL)) < 0)
            goto the_end;

        if (got_frame) {
                tb = (AVRational){1, frame->sample_rate};

#if CONFIG_AVFILTER
                dec_channel_layout = get_valid_channel_layout(frame->channel_layout, av_frame_get_channels(frame));

                reconfigure =
                    cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
                                   frame->format, av_frame_get_channels(frame))    ||
                    is->audio_filter_src.channel_layout != dec_channel_layout ||
Z
Zhang Rui 已提交
1567 1568
                    is->audio_filter_src.freq           != frame->sample_rate ||
                    is->auddec.pkt_serial               != last_serial;
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622

                if (reconfigure) {
                    char buf1[1024], buf2[1024];
                    av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
                    av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
                    av_log(NULL, AV_LOG_DEBUG,
                           "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
                           is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
                           frame->sample_rate, av_frame_get_channels(frame), av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);

                    is->audio_filter_src.fmt            = frame->format;
                    is->audio_filter_src.channels       = av_frame_get_channels(frame);
                    is->audio_filter_src.channel_layout = dec_channel_layout;
                    is->audio_filter_src.freq           = frame->sample_rate;
                    last_serial                         = is->auddec.pkt_serial;

                    if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
                        goto the_end;
                }

            if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
                goto the_end;

            while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
                tb = is->out_audio_filter->inputs[0]->time_base;
#endif
                if (!(af = frame_queue_peek_writable(&is->sampq)))
                    goto the_end;

                af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
                af->pos = av_frame_get_pkt_pos(frame);
                af->serial = is->auddec.pkt_serial;
                af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});

                av_frame_move_ref(af->frame, frame);
                frame_queue_push(&is->sampq);

#if CONFIG_AVFILTER
                if (is->audioq.serial != is->auddec.pkt_serial)
                    break;
            }
            if (ret == AVERROR_EOF)
                is->auddec.finished = is->auddec.pkt_serial;
#endif
        }
    } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
 the_end:
#if CONFIG_AVFILTER
    avfilter_graph_free(&is->agraph);
#endif
    av_frame_free(&frame);
    return ret;
}

1623 1624 1625 1626 1627 1628
static void decoder_start(Decoder *d, int (*fn)(void *), void *arg, const char *name)
{
    packet_queue_start(d->queue);
    d->decoder_tid = SDL_CreateThreadEx(&d->_decoder_tid, fn, arg, name);
}

Z
Zhang Rui 已提交
1629
static int ffplay_video_thread(void *arg)
1630 1631
{
    FFPlayer *ffp = arg;
1632
    VideoState *is = ffp->is;
Z
Zhang Rui 已提交
1633
    AVFrame *frame = av_frame_alloc();
1634
    double pts;
Z
Zhang Rui 已提交
1635
    double duration;
1636
    int ret;
Z
Zhang Rui 已提交
1637 1638
    AVRational tb = is->video_st->time_base;
    AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
1639 1640 1641 1642 1643 1644 1645 1646

#if CONFIG_AVFILTER
    AVFilterGraph *graph = avfilter_graph_alloc();
    AVFilterContext *filt_out = NULL, *filt_in = NULL;
    int last_w = 0;
    int last_h = 0;
    enum AVPixelFormat last_format = -2;
    int last_serial = -1;
Z
Zhang Rui 已提交
1647
    int last_vfilter_idx = 0;
1648 1649
    if (!graph) {
        av_frame_free(&frame);
1650
        return AVERROR(ENOMEM);
1651
    }
1652

1653 1654
#endif

1655 1656 1657
    if (!frame)
        return AVERROR(ENOMEM);

1658
    for (;;) {
1659
        ret = get_video_frame(ffp, frame);
1660 1661 1662 1663 1664 1665
        if (ret < 0)
            goto the_end;
        if (!ret)
            continue;

#if CONFIG_AVFILTER
Z
Zhang Rui 已提交
1666
        if (   last_w != frame->width
Z
Zhang Rui 已提交
1667 1668
            || last_h != frame->height
            || last_format != frame->format
1669
            || last_serial != is->viddec.pkt_serial
Z
Zhang Rui 已提交
1670
            || last_vfilter_idx != is->vfilter_idx) {
1671
            av_log(NULL, AV_LOG_DEBUG,
Z
Zhang Rui 已提交
1672 1673 1674 1675
                   "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
                   last_w, last_h,
                   (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
                   frame->width, frame->height,
1676
                   (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
1677 1678
            avfilter_graph_free(&graph);
            graph = avfilter_graph_alloc();
Z
Zhang Rui 已提交
1679
            if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
1680 1681 1682 1683 1684 1685
                SDL_Event event;
                event.type = FF_QUIT_EVENT;
                event.user.data1 = is;
                SDL_PushEvent(&event);
                goto the_end;
            }
Z
Zhang Rui 已提交
1686
            filt_in  = is->in_video_filter;
1687 1688 1689 1690
            filt_out = is->out_video_filter;
            last_w = frame->width;
            last_h = frame->height;
            last_format = frame->format;
1691
            last_serial = is->viddec.pkt_serial;
Z
Zhang Rui 已提交
1692
            last_vfilter_idx = is->vfilter_idx;
Z
Zhang Rui 已提交
1693
            frame_rate = filt_out->inputs[0]->frame_rate;
1694 1695
        }

Z
Zhang Rui 已提交
1696 1697 1698
        ret = av_buffersrc_add_frame(filt_in, frame);
        if (ret < 0)
            goto the_end;
1699 1700

        while (ret >= 0) {
Z
Zhang Rui 已提交
1701
            is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
1702

Z
Zhang Rui 已提交
1703
            ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
1704
            if (ret < 0) {
1705
                if (ret == AVERROR_EOF)
1706
                    is->video_finished = is->viddec.pkt_serial;
1707 1708 1709 1710
                ret = 0;
                break;
            }

Z
Zhang Rui 已提交
1711
            is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
1712
            if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
Z
Zhang Rui 已提交
1713
                is->frame_last_filter_delay = 0;
Z
Zhang Rui 已提交
1714 1715 1716 1717
            tb = filt_out->inputs[0]->time_base;
#endif
            duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
            pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
1718
            ret = queue_picture(ffp, frame, pts, duration, av_frame_get_pkt_pos(frame), is->viddec.pkt_serial);
Z
Zhang Rui 已提交
1719
            av_frame_unref(frame);
Z
Zhang Rui 已提交
1720
#if CONFIG_AVFILTER
1721 1722 1723 1724 1725 1726
        }
#endif

        if (ret < 0)
            goto the_end;
    }
Z
Zhang Rui 已提交
1727
 the_end:
1728 1729 1730
#if CONFIG_AVFILTER
    avfilter_graph_free(&graph);
#endif
Z
Zhang Rui 已提交
1731
    av_frame_free(&frame);
1732 1733 1734
    return 0;
}

Z
Zhang Rui 已提交
1735 1736 1737
static int video_thread(void *arg)
{
    FFPlayer *ffp = (FFPlayer *)arg;
1738
    int       ret = 0;
Z
Zhang Rui 已提交
1739

1740 1741 1742
    if (ffp->node_vdec) {
        ret = ffpipenode_run_sync(ffp->node_vdec);
    }
Z
Zhang Rui 已提交
1743 1744 1745
    return ret;
}

Z
Zhang Rui 已提交
1746
// FFP_MERGE: subtitle_thread
1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777

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

    size = samples_size / sizeof(short);
    while (size > 0) {
        len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
        if (len > size)
            len = size;
        memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
        samples += len;
        is->sample_array_index += len;
        if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
            is->sample_array_index = 0;
        size -= len;
    }
}

/* return the wanted number of samples to get better sync if sync_type is video
 * or external master clock */
static int synchronize_audio(VideoState *is, int nb_samples)
{
    int wanted_nb_samples = nb_samples;

    /* if not master, then we try to remove or add samples to correct the clock */
    if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) {
        double diff, avg_diff;
        int min_nb_samples, max_nb_samples;

Z
Zhang Rui 已提交
1778
        diff = get_clock(&is->audclk) - get_master_clock(is);
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789

        if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
            is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
            if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
                /* not enough measures to have a correct estimate */
                is->audio_diff_avg_count++;
            } else {
                /* estimate the A-V difference */
                avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);

                if (fabs(avg_diff) >= is->audio_diff_threshold) {
Z
Zhang Rui 已提交
1790
                    wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
1791 1792
                    min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
                    max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
1793
                    wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
1794
                }
1795
                av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
Z
Zhang Rui 已提交
1796 1797
                        diff, avg_diff, wanted_nb_samples - nb_samples,
                        is->audio_clock, is->audio_diff_threshold);
1798 1799 1800
            }
        } else {
            /* too big difference : may be initial PTS errors, so
Z
Zhang Rui 已提交
1801
               reset A-V filter */
1802
            is->audio_diff_avg_count = 0;
Z
Zhang Rui 已提交
1803
            is->audio_diff_cum       = 0;
1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816
        }
    }

    return wanted_nb_samples;
}

/**
 * Decode one audio frame and return its uncompressed size.
 *
 * The processed audio frame is decoded, converted if required, and
 * stored in is->audio_buf, with size in bytes given by the return
 * value.
 */
Z
Zhang Rui 已提交
1817
static int audio_decode_frame(FFPlayer *ffp)
1818
{
Z
Zhang Rui 已提交
1819
    VideoState *is = ffp->is;
1820
    int data_size, resampled_data_size;
1821 1822 1823
    int64_t dec_channel_layout;
    av_unused double audio_clock0;
    int wanted_nb_samples;
1824
    Frame *af;
1825

1826
    if (is->paused || is->step)
1827
        return -1;
1828

Z
Zhang Rui 已提交
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843
    if (ffp->sync_av_start &&                       /* sync enabled */
        is->video_st &&                             /* has video stream */
        !is->viddec.first_frame_decoded &&          /* not hot */
        is->viddec.finished != is->videoq.serial) { /* not finished */
        /* waiting for first video frame */
        Uint64 now = SDL_GetTickHR();
        if (now < is->viddec.first_frame_decoded_time ||
            now > is->viddec.first_frame_decoded_time + 2000) {
            is->viddec.first_frame_decoded = 1;
        } else {
            /* video pipeline is not ready yet */
            return -1;
        }
    }

1844
    do {
1845 1846 1847 1848 1849 1850 1851
#if defined(_WIN32)
        while (frame_queue_nb_remaining(&is->sampq) == 0) {
            if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
                return -1;
            av_usleep (1000);
        }
#endif
1852 1853 1854 1855
        if (!(af = frame_queue_peek_readable(&is->sampq)))
            return -1;
        frame_queue_next(&is->sampq);
    } while (af->serial != is->audioq.serial);
Z
Zhang Rui 已提交
1856

Z
Zhang Rui 已提交
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879
    data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(af->frame),
                                           af->frame->nb_samples,
                                           af->frame->format, 1);

    dec_channel_layout =
        (af->frame->channel_layout && av_frame_get_channels(af->frame) == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
        af->frame->channel_layout : av_get_default_channel_layout(av_frame_get_channels(af->frame));
    wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);

    if (af->frame->format        != is->audio_src.fmt            ||
        dec_channel_layout       != is->audio_src.channel_layout ||
        af->frame->sample_rate   != is->audio_src.freq           ||
        (wanted_nb_samples       != af->frame->nb_samples && !is->swr_ctx)) {
        swr_free(&is->swr_ctx);
        is->swr_ctx = swr_alloc_set_opts(NULL,
                                         is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
                                         dec_channel_layout,           af->frame->format, af->frame->sample_rate,
                                         0, NULL);
        if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
            av_log(NULL, AV_LOG_ERROR,
                   "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
                    af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), av_frame_get_channels(af->frame),
                    is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
1880
            swr_free(&is->swr_ctx);
Z
Zhang Rui 已提交
1881
            return -1;
1882
        }
Z
Zhang Rui 已提交
1883 1884 1885 1886 1887
        is->audio_src.channel_layout = dec_channel_layout;
        is->audio_src.channels       = av_frame_get_channels(af->frame);
        is->audio_src.freq = af->frame->sample_rate;
        is->audio_src.fmt = af->frame->format;
    }
1888

Z
Zhang Rui 已提交
1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902
    if (is->swr_ctx) {
        const uint8_t **in = (const uint8_t **)af->frame->extended_data;
        uint8_t **out = &is->audio_buf1;
        int out_count = (int)((int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256);
        int out_size  = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
        int len2;
        if (out_size < 0) {
            av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
            return -1;
        }
        if (wanted_nb_samples != af->frame->nb_samples) {
            if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
                                        wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
                av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
1903 1904 1905
                return -1;
            }
        }
Z
Zhang Rui 已提交
1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924
        av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
        if (!is->audio_buf1)
            return AVERROR(ENOMEM);
        len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
        if (len2 < 0) {
            av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
            return -1;
        }
        if (len2 == out_count) {
            av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
            if (swr_init(is->swr_ctx) < 0)
                swr_free(&is->swr_ctx);
        }
        is->audio_buf = is->audio_buf1;
        resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
    } else {
        is->audio_buf = af->frame->data[0];
        resampled_data_size = data_size;
    }
1925

Z
Zhang Rui 已提交
1926 1927 1928 1929 1930 1931 1932
    audio_clock0 = is->audio_clock;
    /* update the audio clock with the pts */
    if (!isnan(af->pts))
        is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
    else
        is->audio_clock = NAN;
    is->audio_clock_serial = af->serial;
1933
#ifdef FFP_SHOW_AUDIO_DELAY
Z
Zhang Rui 已提交
1934 1935 1936 1937 1938 1939 1940
    {
        static double last_clock;
        printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
               is->audio_clock - last_clock,
               is->audio_clock, audio_clock0);
        last_clock = is->audio_clock;
    }
1941
#endif
1942 1943 1944 1945 1946 1947 1948 1949 1950
    if (!is->auddec.first_frame_decoded) {
        ALOGD("avcodec/Audio: first frame decoded\n");
        is->auddec.first_frame_decoded_time = SDL_GetTickHR();
        is->auddec.first_frame_decoded = 1;
    }
    if (!ffp->first_audio_frame_rendered) {
        ffp->first_audio_frame_rendered = 1;
        ffp_notify_msg1(ffp, FFP_MSG_AUDIO_RENDERING_START);
    }
1951
    return resampled_data_size;
1952 1953 1954 1955 1956 1957
}

/* prepare a new audio buffer */
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
{
    FFPlayer *ffp = opaque;
1958
    VideoState *is = ffp->is;
1959
    int audio_size, len1;
1960 1961 1962 1963
    if (!ffp || !is) {
        memset(stream, 0, len);
        return;
    }
1964

Z
Zhang Rui 已提交
1965
    ffp->audio_callback_time = av_gettime_relative();
1966 1967 1968

    while (len > 0) {
        if (is->audio_buf_index >= is->audio_buf_size) {
Z
Zhang Rui 已提交
1969
           audio_size = audio_decode_frame(ffp);
Z
Zhang Rui 已提交
1970
           if (audio_size < 0) {
1971
                /* if error, just output silence */
Z
Zhang Rui 已提交
1972
               is->audio_buf      = is->silence_buf;
Z
Zhang Rui 已提交
1973
               is->audio_buf_size = sizeof(is->silence_buf) / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
Z
Zhang Rui 已提交
1974 1975 1976 1977 1978 1979
           } else {
               if (is->show_mode != SHOW_MODE_VIDEO)
                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
               is->audio_buf_size = audio_size;
           }
           is->audio_buf_index = 0;
1980
        }
1981
        if (is->auddec.pkt_serial != is->audioq.serial) {
1982 1983
            is->audio_buf_index = is->audio_buf_size;
            memset(stream, 0, len);
Z
Zhang Rui 已提交
1984 1985
            // stream += len;
            // len = 0;
1986 1987 1988
            SDL_AoutFlushAudio(ffp->aout);
            break;
        }
1989 1990 1991
        len1 = is->audio_buf_size - is->audio_buf_index;
        if (len1 > len)
            len1 = len;
Z
Zhang Rui 已提交
1992
        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1993 1994 1995 1996 1997 1998
        len -= len1;
        stream += len1;
        is->audio_buf_index += len1;
    }
    is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
    /* Let's assume the audio driver that is used by SDL has two periods. */
Z
Zhang Rui 已提交
1999
    if (!isnan(is->audio_clock)) {
2000
        set_clock_at(&is->audclk, is->audio_clock - (double)(is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec - SDL_AoutGetLatencySeconds(ffp->aout), is->audio_clock_serial, ffp->audio_callback_time / 1000000.0);
Z
Zhang Rui 已提交
2001 2002
        sync_clock_to_slave(&is->extclk, &is->audclk);
    }
2003 2004
}

2005
static int audio_open(FFPlayer *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params)
2006
{
Z
Zhang Rui 已提交
2007
    FFPlayer *ffp = opaque;
2008
    VideoState *is = ffp->is;
2009 2010
    SDL_AudioSpec wanted_spec, spec;
    const char *env;
2011
    static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
Z
Zhang Rui 已提交
2012 2013 2014
#ifdef FFP_MERGE
    static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
#endif
Z
Zhang Rui 已提交
2015
    static const int next_sample_rates[] = {0, 44100, 48000};
Z
Zhang Rui 已提交
2016
    int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026

    env = SDL_getenv("SDL_AUDIO_CHANNELS");
    if (env) {
        wanted_nb_channels = atoi(env);
        wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
    }
    if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) {
        wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
        wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
    }
Z
Zhang Rui 已提交
2027 2028
    wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
    wanted_spec.channels = wanted_nb_channels;
2029 2030
    wanted_spec.freq = wanted_sample_rate;
    if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
Z
Zhang Rui 已提交
2031
        av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
2032 2033
        return -1;
    }
Z
Zhang Rui 已提交
2034 2035
    while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
        next_sample_rate_idx--;
2036 2037
    wanted_spec.format = AUDIO_S16SYS;
    wanted_spec.silence = 0;
Z
Zhang Rui 已提交
2038
    wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
2039 2040
    wanted_spec.callback = sdl_audio_callback;
    wanted_spec.userdata = opaque;
Z
Zhang Rui 已提交
2041
    while (SDL_AoutOpenAudio(ffp->aout, &wanted_spec, &spec) < 0) {
2042 2043 2044
        /* avoid infinity loop on exit. --by bbcallen */
        if (is->abort_request)
            return -1;
Z
Zhang Rui 已提交
2045 2046
        av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
               wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2047 2048
        wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
        if (!wanted_spec.channels) {
Z
Zhang Rui 已提交
2049 2050 2051 2052 2053 2054 2055
            wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
            wanted_spec.channels = wanted_nb_channels;
            if (!wanted_spec.freq) {
                av_log(NULL, AV_LOG_ERROR,
                       "No more combinations to try, audio open failed\n");
                return -1;
            }
2056 2057 2058 2059
        }
        wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels);
    }
    if (spec.format != AUDIO_S16SYS) {
Z
Zhang Rui 已提交
2060 2061
        av_log(NULL, AV_LOG_ERROR,
               "SDL advised audio format %d is not supported!\n", spec.format);
2062 2063 2064 2065 2066
        return -1;
    }
    if (spec.channels != wanted_spec.channels) {
        wanted_channel_layout = av_get_default_channel_layout(spec.channels);
        if (!wanted_channel_layout) {
Z
Zhang Rui 已提交
2067 2068
            av_log(NULL, AV_LOG_ERROR,
                   "SDL advised channel count %d is not supported!\n", spec.channels);
2069 2070 2071 2072 2073 2074 2075
            return -1;
        }
    }

    audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
    audio_hw_params->freq = spec.freq;
    audio_hw_params->channel_layout = wanted_channel_layout;
Z
Zhang Rui 已提交
2076
    audio_hw_params->channels =  spec.channels;
Z
Zhang Rui 已提交
2077 2078 2079 2080 2081 2082
    audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1);
    audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->channels, audio_hw_params->freq, audio_hw_params->fmt, 1);
    if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
        av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
        return -1;
    }
2083 2084

    SDL_AoutSetDefaultLatencySeconds(ffp->aout, ((double)(2 * spec.size)) / audio_hw_params->bytes_per_sec);
2085 2086 2087 2088 2089 2090
    return spec.size;
}

/* open a given stream. Return 0 if OK */
static int stream_component_open(FFPlayer *ffp, int stream_index)
{
2091
    VideoState *is = ffp->is;
2092 2093 2094 2095 2096 2097
    AVFormatContext *ic = is->ic;
    AVCodecContext *avctx;
    AVCodec *codec;
    const char *forced_codec_name = NULL;
    AVDictionary *opts;
    AVDictionaryEntry *t = NULL;
Z
Zhang Rui 已提交
2098 2099
    int sample_rate, nb_channels;
    int64_t channel_layout;
2100
    int ret = 0;
2101
    int stream_lowres = ffp->lowres;
2102 2103 2104 2105 2106 2107 2108

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

    codec = avcodec_find_decoder(avctx->codec_id);

Z
Zhang Rui 已提交
2109
    switch (avctx->codec_type) {
Z
Zhang Rui 已提交
2110 2111 2112 2113
        case AVMEDIA_TYPE_AUDIO   : is->last_audio_stream    = stream_index; forced_codec_name = ffp->audio_codec_name; break;
        // FFP_MERGE: case AVMEDIA_TYPE_SUBTITLE:
        case AVMEDIA_TYPE_VIDEO   : is->last_video_stream    = stream_index; forced_codec_name = ffp->video_codec_name; break;
        default: break;
2114 2115 2116 2117
    }
    if (forced_codec_name)
        codec = avcodec_find_decoder_by_name(forced_codec_name);
    if (!codec) {
Z
Zhang Rui 已提交
2118 2119 2120 2121
        if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
                                      "No codec could be found with name '%s'\n", forced_codec_name);
        else                   av_log(NULL, AV_LOG_WARNING,
                                      "No codec could be found with id %d\n", avctx->codec_id);
2122 2123 2124 2125
        return -1;
    }

    avctx->codec_id = codec->id;
2126
    if(stream_lowres > av_codec_get_max_lowres(codec)){
2127
        av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
2128
                av_codec_get_max_lowres(codec));
2129
        stream_lowres = av_codec_get_max_lowres(codec);
2130
    }
2131
    av_codec_set_lowres(avctx, stream_lowres);
2132

2133
    if(stream_lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
2134 2135
    if (ffp->fast)
        avctx->flags2 |= AV_CODEC_FLAG2_FAST;
2136
    if(codec->capabilities & AV_CODEC_CAP_DR1)
2137 2138 2139 2140 2141
        avctx->flags |= CODEC_FLAG_EMU_EDGE;

    opts = filter_codec_opts(ffp->codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
    if (!av_dict_get(opts, "threads", NULL, 0))
        av_dict_set(&opts, "threads", "auto", 0);
2142
    if (stream_lowres)
Z
Zhang Rui 已提交
2143
        av_dict_set_int(&opts, "lowres", stream_lowres, 0);
Z
Zhang Rui 已提交
2144 2145
    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO)
        av_dict_set(&opts, "refcounted_frames", "1", 0);
2146 2147 2148
    if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
        goto fail;
    }
2149 2150
    if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
        av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
B
bbcallen 已提交
2151
#ifdef FFP_MERGE
Z
Zhang Rui 已提交
2152
        ret =  AVERROR_OPTION_NOT_FOUND;
2153
        goto fail;
B
bbcallen 已提交
2154
#endif
2155 2156
    }

2157
    is->eof = 0;
2158 2159 2160
    ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
    switch (avctx->codec_type) {
    case AVMEDIA_TYPE_AUDIO:
Z
Zhang Rui 已提交
2161 2162 2163 2164 2165 2166 2167 2168 2169
#if CONFIG_AVFILTER
        {
            AVFilterLink *link;

            is->audio_filter_src.freq           = avctx->sample_rate;
            is->audio_filter_src.channels       = avctx->channels;
            is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels);
            is->audio_filter_src.fmt            = avctx->sample_fmt;
            if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
2170
                goto fail;
Z
Zhang Rui 已提交
2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183
            link = is->out_audio_filter->inputs[0];
            sample_rate    = link->sample_rate;
            nb_channels    = link->channels;
            channel_layout = link->channel_layout;
        }
#else
        sample_rate    = avctx->sample_rate;
        nb_channels    = avctx->channels;
        channel_layout = avctx->channel_layout;
#endif

        /* prepare audio output */
        if ((ret = audio_open(ffp, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0)
2184
            goto fail;
Z
Zhang Rui 已提交
2185
        ffp_set_audio_codec_info(ffp, AVCODEC_MODULE_NAME, avcodec_get_name(avctx->codec_id));
Z
Zhang Rui 已提交
2186 2187
        is->audio_hw_buf_size = ret;
        is->audio_src = is->audio_tgt;
Z
Zhang Rui 已提交
2188
        is->audio_buf_size  = 0;
2189 2190 2191
        is->audio_buf_index = 0;

        /* init averaging filter */
Z
Zhang Rui 已提交
2192
        is->audio_diff_avg_coef  = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2193 2194
        is->audio_diff_avg_count = 0;
        /* since we do not have a precise anough audio fifo fullness,
Z
Zhang Rui 已提交
2195
           we correct audio sync only if larger than this threshold */
Z
Zhang Rui 已提交
2196
        is->audio_diff_threshold = 2.0 * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec;
2197

Z
Zhang Rui 已提交
2198 2199 2200
        is->audio_stream = stream_index;
        is->audio_st = ic->streams[stream_index];

2201
        decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread);
2202 2203 2204 2205
        if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) {
            is->auddec.start_pts = is->audio_st->start_time;
            is->auddec.start_pts_tb = is->audio_st->time_base;
        }
2206
        decoder_start(&is->auddec, audio_thread, ffp, "ff_audio_dec");
Z
Zhang Rui 已提交
2207
        SDL_AoutPauseAudio(ffp->aout, 0);
2208 2209 2210 2211
        break;
    case AVMEDIA_TYPE_VIDEO:
        is->video_stream = stream_index;
        is->video_st = ic->streams[stream_index];
Z
Zhang Rui 已提交
2212

2213 2214 2215 2216 2217
#ifdef FFP_MERGE
        is->viddec_width  = avctx->width;
        is->viddec_height = avctx->height;
#endif

2218
        decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
2219 2220 2221
        ffp->node_vdec = ffpipeline_open_video_decoder(ffp->pipeline, ffp);
        if (!ffp->node_vdec)
            goto fail;
2222
        decoder_start(&is->viddec, video_thread, ffp, "ff_video_dec");
Z
Zhang Rui 已提交
2223
        is->queue_attachments_req = 1;
2224 2225 2226

        if(is->video_st->avg_frame_rate.den && is->video_st->avg_frame_rate.num) {
            double fps = av_q2d(is->video_st->avg_frame_rate);
Z
Zhang Rui 已提交
2227
            SDL_ProfilerReset(&is->viddec.decode_profiler, fps + 0.5);
2228
            if (fps > ffp->max_fps && fps < 130.0) {
2229
                is->is_video_high_fps = 1;
2230
                av_log(ffp, AV_LOG_WARNING, "fps: %lf (too high)\n", fps);
2231
            } else {
2232
                av_log(ffp, AV_LOG_WARNING, "fps: %lf (normal)\n", fps);
2233 2234 2235 2236
            }
        }
        if(is->video_st->r_frame_rate.den && is->video_st->r_frame_rate.num) {
            double tbr = av_q2d(is->video_st->r_frame_rate);
2237
            if (tbr > ffp->max_fps && tbr < 130.0) {
2238
                is->is_video_high_fps = 1;
2239
                av_log(ffp, AV_LOG_WARNING, "fps: %lf (too high)\n", tbr);
2240
            } else {
2241
                av_log(ffp, AV_LOG_WARNING, "fps: %lf (normal)\n", tbr);
2242 2243 2244 2245 2246 2247 2248 2249 2250
            }
        }

        if (is->is_video_high_fps) {
            avctx->skip_frame       = FFMAX(avctx->skip_frame, AVDISCARD_NONREF);
            avctx->skip_loop_filter = FFMAX(avctx->skip_loop_filter, AVDISCARD_NONREF);
            avctx->skip_idct        = FFMAX(avctx->skip_loop_filter, AVDISCARD_NONREF);
        }

2251
        break;
Z
Zhang Rui 已提交
2252
    // FFP_MERGE: case AVMEDIA_TYPE_SUBTITLE:
2253 2254 2255
    default:
        break;
    }
2256 2257 2258 2259
fail:
    av_dict_free(&opts);

    return ret;
2260 2261
}

Z
Zhang Rui 已提交
2262
static void stream_component_close(FFPlayer *ffp, int stream_index)
2263
{
Z
Zhang Rui 已提交
2264
    VideoState *is = ffp->is;
2265 2266 2267 2268 2269 2270 2271 2272 2273
    AVFormatContext *ic = is->ic;
    AVCodecContext *avctx;

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

    switch (avctx->codec_type) {
    case AVMEDIA_TYPE_AUDIO:
2274
        decoder_abort(&is->auddec, &is->sampq);
2275
        SDL_AoutCloseAudio(ffp->aout);
2276

2277
        decoder_destroy(&is->auddec);
2278 2279 2280 2281 2282
        swr_free(&is->swr_ctx);
        av_freep(&is->audio_buf1);
        is->audio_buf1_size = 0;
        is->audio_buf = NULL;

Z
Zhang Rui 已提交
2283
#ifdef FFP_MERGE
2284 2285 2286 2287 2288 2289
        if (is->rdft) {
            av_rdft_end(is->rdft);
            av_freep(&is->rdft_data);
            is->rdft = NULL;
            is->rdft_bits = 0;
        }
Z
Zhang Rui 已提交
2290
#endif
2291 2292
        break;
    case AVMEDIA_TYPE_VIDEO:
2293
        decoder_abort(&is->viddec, &is->pictq);
2294
        decoder_destroy(&is->viddec);
2295
        break;
Z
Zhang Rui 已提交
2296
    // FFP_MERGE: case AVMEDIA_TYPE_SUBTITLE:
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311
    default:
        break;
    }

    ic->streams[stream_index]->discard = AVDISCARD_ALL;
    avcodec_close(avctx);
    switch (avctx->codec_type) {
    case AVMEDIA_TYPE_AUDIO:
        is->audio_st = NULL;
        is->audio_stream = -1;
        break;
    case AVMEDIA_TYPE_VIDEO:
        is->video_st = NULL;
        is->video_stream = -1;
        break;
Z
Zhang Rui 已提交
2312
    // FFP_MERGE: case AVMEDIA_TYPE_SUBTITLE:
2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
    default:
        break;
    }
}

static int decode_interrupt_cb(void *ctx)
{
    VideoState *is = ctx;
    return is->abort_request;
}

static int is_realtime(AVFormatContext *s)
{
Z
Zhang Rui 已提交
2326 2327 2328 2329
    if(   !strcmp(s->iformat->name, "rtp")
       || !strcmp(s->iformat->name, "rtsp")
       || !strcmp(s->iformat->name, "sdp")
    )
2330 2331
        return 1;

Z
Zhang Rui 已提交
2332 2333 2334 2335
    if(s->pb && (   !strncmp(s->filename, "rtp:", 4)
                 || !strncmp(s->filename, "udp:", 4)
                )
    )
2336 2337 2338 2339 2340 2341 2342 2343
        return 1;
    return 0;
}

/* this thread gets the stream from the disk or the network */
static int read_thread(void *arg)
{
    FFPlayer *ffp = arg;
2344
    VideoState *is = ffp->is;
2345
    AVFormatContext *ic = NULL;
Z
Zhang Rui 已提交
2346
    int err, i, ret __unused;
2347 2348
    int st_index[AVMEDIA_TYPE_NB];
    AVPacket pkt1, *pkt = &pkt1;
Z
Zhang Rui 已提交
2349
    int64_t stream_start_time;
2350
    int completed = 0;
2351 2352 2353 2354 2355
    int pkt_in_play_range = 0;
    AVDictionaryEntry *t;
    AVDictionary **opts;
    int orig_nb_streams;
    SDL_mutex *wait_mutex = SDL_CreateMutex();
2356
    int scan_all_pmts_set = 0;
2357
    int64_t pkt_ts;
2358
    int last_error = 0;
2359
    int64_t prev_io_tick_counter = 0;
Z
Zhang Rui 已提交
2360
    int64_t io_tick_counter = 0;
2361 2362 2363 2364

    memset(st_index, -1, sizeof(st_index));
    is->last_video_stream = is->video_stream = -1;
    is->last_audio_stream = is->audio_stream = -1;
Z
Zhang Rui 已提交
2365
#ifdef FFP_MERGE
2366
    is->last_subtitle_stream = is->subtitle_stream = -1;
Z
Zhang Rui 已提交
2367
#endif
2368
    is->eof = 0;
2369 2370

    ic = avformat_alloc_context();
2371 2372 2373 2374 2375
    if (!ic) {
        av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
        ret = AVERROR(ENOMEM);
        goto fail;
    }
2376 2377
    ic->interrupt_callback.callback = decode_interrupt_cb;
    ic->interrupt_callback.opaque = is;
2378 2379 2380 2381
    if (!av_dict_get(ffp->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
        av_dict_set(&ffp->format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
        scan_all_pmts_set = 1;
    }
2382 2383 2384 2385
    if (ffp->format_control_message) {
        av_format_set_control_message_cb(ic, ffp_format_control_message);
        av_format_set_opaque(ic, ffp);
    }
2386 2387
    if (av_stristart(is->filename, "rtmp", NULL) ||
        av_stristart(is->filename, "rtsp", NULL)) {
2388
        // There is total different meaning for 'timeout' option in rtmp
Z
Zhang Rui 已提交
2389
        av_log(ffp, AV_LOG_WARNING, "remove 'timeout' option for rtmp.\n");
2390 2391
        av_dict_set(&ffp->format_opts, "timeout", NULL, 0);
    }
2392 2393 2394 2395 2396 2397
    err = avformat_open_input(&ic, is->filename, is->iformat, &ffp->format_opts);
    if (err < 0) {
        print_error(is->filename, err);
        ret = -1;
        goto fail;
    }
2398 2399 2400
    if (scan_all_pmts_set)
        av_dict_set(&ffp->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);

2401 2402
    if ((t = av_dict_get(ffp->format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
        av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
B
bbcallen 已提交
2403
#ifdef FFP_MERGE
2404 2405
        ret = AVERROR_OPTION_NOT_FOUND;
        goto fail;
B
bbcallen 已提交
2406
#endif
2407 2408 2409 2410 2411 2412
    }
    is->ic = ic;

    if (ffp->genpts)
        ic->flags |= AVFMT_FLAG_GENPTS;

Z
Zhang Rui 已提交
2413 2414
    av_format_inject_global_side_data(ic);

2415 2416 2417 2418
    opts = setup_find_stream_info_opts(ic, ffp->codec_opts);
    orig_nb_streams = ic->nb_streams;

    err = avformat_find_stream_info(ic, opts);
2419 2420 2421 2422 2423

    for (i = 0; i < orig_nb_streams; i++)
        av_dict_free(&opts[i]);
    av_freep(&opts);

2424
    if (err < 0) {
Z
Zhang Rui 已提交
2425 2426
        av_log(NULL, AV_LOG_WARNING,
               "%s: could not find codec parameters\n", is->filename);
2427 2428 2429 2430 2431
        ret = -1;
        goto fail;
    }

    if (ic->pb)
Z
Zhang Rui 已提交
2432
        ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
2433 2434

    if (ffp->seek_by_bytes < 0)
Z
Zhang Rui 已提交
2435
        ffp->seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", ic->iformat->name);
2436 2437

    is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
2438
    av_log(ffp, AV_LOG_INFO, "max_frame_duration: %.3f\n", is->max_frame_duration);
2439

Z
Zhang Rui 已提交
2440 2441 2442
#ifdef FFP_MERGE
    if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
        window_title = av_asprintf("%s - %s", t->value, input_filename);
Z
Zhang Rui 已提交
2443

Z
Zhang Rui 已提交
2444
#endif
2445 2446 2447 2448 2449 2450 2451 2452 2453 2454
    /* if seeking requested, we execute it */
    if (ffp->start_time != AV_NOPTS_VALUE) {
        int64_t timestamp;

        timestamp = ffp->start_time;
        /* add the stream start time */
        if (ic->start_time != AV_NOPTS_VALUE)
            timestamp += ic->start_time;
        ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
        if (ret < 0) {
Z
Zhang Rui 已提交
2455
            av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
Z
Zhang Rui 已提交
2456
                    is->filename, (double)timestamp / AV_TIME_BASE);
2457 2458 2459 2460 2461
        }
    }

    is->realtime = is_realtime(ic);

2462 2463 2464
    if (true || ffp->show_status)
        av_dump_format(ic, 0, is->filename, 0);

B
bbcallen 已提交
2465 2466 2467 2468
    int video_stream_count = 0;
    int h264_stream_count = 0;
    int first_h264_stream = -1;
    for (i = 0; i < ic->nb_streams; i++) {
2469 2470 2471 2472 2473 2474 2475 2476
        AVStream *st = ic->streams[i];
        enum AVMediaType type = st->codec->codec_type;
        st->discard = AVDISCARD_ALL;
        if (ffp->wanted_stream_spec[type] && st_index[type] == -1)
            if (avformat_match_stream_specifier(ic, st, ffp->wanted_stream_spec[type]) > 0)
                st_index[type] = i;

        // choose first h264
B
bbcallen 已提交
2477 2478 2479 2480 2481 2482 2483 2484 2485 2486
        AVCodecContext *codec = ic->streams[i]->codec;
        if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_count++;
            if (codec->codec_id == AV_CODEC_ID_H264) {
                h264_stream_count++;
                if (first_h264_stream < 0)
                    first_h264_stream = i;
            }
        }
    }
2487 2488
    if (video_stream_count > 1 && st_index[AVMEDIA_TYPE_VIDEO] < 0) {
        st_index[AVMEDIA_TYPE_VIDEO] = first_h264_stream;
B
bbcallen 已提交
2489 2490
        av_log(NULL, AV_LOG_WARNING, "multiple video stream found, prefer first h264 stream: %d\n", first_h264_stream);
    }
2491 2492
    if (!ffp->video_disable)
        st_index[AVMEDIA_TYPE_VIDEO] =
Z
Zhang Rui 已提交
2493
            av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
2494
                                st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
2495 2496
    if (!ffp->audio_disable)
        st_index[AVMEDIA_TYPE_AUDIO] =
Z
Zhang Rui 已提交
2497
            av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
2498
                                st_index[AVMEDIA_TYPE_AUDIO],
Z
Zhang Rui 已提交
2499 2500 2501
                                st_index[AVMEDIA_TYPE_VIDEO],
                                NULL, 0);
#ifdef FFP_MERGE
2502 2503
    if (!ffp->video_disable && !ffp->subtitle_disable)
        st_index[AVMEDIA_TYPE_SUBTITLE] =
Z
Zhang Rui 已提交
2504
            av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
2505
                                st_index[AVMEDIA_TYPE_SUBTITLE],
Z
Zhang Rui 已提交
2506 2507 2508
                                (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
                                 st_index[AVMEDIA_TYPE_AUDIO] :
                                 st_index[AVMEDIA_TYPE_VIDEO]),
Z
Zhang Rui 已提交
2509
                                NULL, 0);
Z
Zhang Rui 已提交
2510
#endif
Z
Zhang Rui 已提交
2511
    ijkmeta_set_avformat_context_l(ffp->meta, ic);
Z
Zhang Rui 已提交
2512
    if (st_index[AVMEDIA_TYPE_VIDEO] >= 0)
Z
Zhang Rui 已提交
2513
        ijkmeta_set_int64_l(ffp->meta, IJKM_KEY_VIDEO_STREAM, st_index[AVMEDIA_TYPE_VIDEO]);
Z
Zhang Rui 已提交
2514
    if (st_index[AVMEDIA_TYPE_AUDIO] >= 0)
Z
Zhang Rui 已提交
2515
        ijkmeta_set_int64_l(ffp->meta, IJKM_KEY_AUDIO_STREAM, st_index[AVMEDIA_TYPE_AUDIO]);
2516 2517

    is->show_mode = ffp->show_mode;
Z
Zhang Rui 已提交
2518 2519 2520 2521
#ifdef FFP_MERGE // bbc: dunno if we need this
    if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
        AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
        AVCodecContext *avctx = st->codec;
Z
Zhang Rui 已提交
2522 2523 2524
        AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL);
        if (avctx->width)
            set_default_window_size(avctx->width, avctx->height, sar);
Z
Zhang Rui 已提交
2525 2526
    }
#endif
2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539

    /* open the streams */
    if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
        stream_component_open(ffp, st_index[AVMEDIA_TYPE_AUDIO]);
    }

    ret = -1;
    if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
        ret = stream_component_open(ffp, st_index[AVMEDIA_TYPE_VIDEO]);
    }
    if (is->show_mode == SHOW_MODE_NONE)
        is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;

Z
Zhang Rui 已提交
2540
#ifdef FFP_MERGE
2541 2542 2543
    if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
        stream_component_open(ffp, st_index[AVMEDIA_TYPE_SUBTITLE]);
    }
Z
Zhang Rui 已提交
2544
#endif
2545 2546

    if (is->video_stream < 0 && is->audio_stream < 0) {
2547 2548
        av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
               is->filename);
2549 2550 2551
        ret = -1;
        goto fail;
    }
2552 2553 2554 2555 2556 2557 2558 2559 2560
    if (is->audio_stream >= 0) {
        is->audioq.is_buffer_indicator = 1;
        is->buffer_indicator_queue = &is->audioq;
    } else if (is->video_stream >= 0) {
        is->videoq.is_buffer_indicator = 1;
        is->buffer_indicator_queue = &is->videoq;
    } else {
        assert("invalid streams");
    }
2561 2562 2563 2564

    if (ffp->infinite_buffer < 0 && is->realtime)
        ffp->infinite_buffer = 1;

Z
Zhang Rui 已提交
2565
    if (!ffp->start_on_prepared)
2566
        toggle_pause(ffp, 1);
2567 2568
    if (is->video_st && is->video_st->codec) {
        AVCodecContext *avctx = is->video_st->codec;
2569 2570
        ffp_notify_msg3(ffp, FFP_MSG_VIDEO_SIZE_CHANGED, avctx->width, avctx->height);
        ffp_notify_msg3(ffp, FFP_MSG_SAR_CHANGED, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
2571
    }
2572 2573
    ffp->prepared = true;
    ffp_notify_msg1(ffp, FFP_MSG_PREPARED);
Z
Zhang Rui 已提交
2574
    if (!ffp->start_on_prepared) {
2575
        while (is->pause_req && !is->abort_request) {
2576 2577 2578
            SDL_Delay(100);
        }
    }
Z
Zhang Rui 已提交
2579
    if (ffp->auto_resume) {
2580
        ffp_notify_msg1(ffp, FFP_REQ_START);
Z
Zhang Rui 已提交
2581
        ffp->auto_resume = 0;
2582
    }
Z
Zhang Rui 已提交
2583

2584 2585 2586
    for (;;) {
        if (is->abort_request)
            break;
Z
Zhang Rui 已提交
2587
#ifdef FFP_MERGE
2588 2589 2590 2591 2592 2593 2594
        if (is->paused != is->last_paused) {
            is->last_paused = is->paused;
            if (is->paused)
                is->read_pause_return = av_read_pause(ic);
            else
                av_read_play(ic);
        }
Z
Zhang Rui 已提交
2595
#endif
Z
Zhang Rui 已提交
2596
#if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2597
        if (is->paused &&
Z
Zhang Rui 已提交
2598 2599
                (!strcmp(ic->iformat->name, "rtsp") ||
                 (ic->pb && !strncmp(ffp->input_filename, "mmsh:", 5)))) {
2600 2601 2602 2603 2604
            /* wait 10 ms to avoid trying to get another packet */
            /* XXX: horrible */
            SDL_Delay(10);
            continue;
        }
Z
Zhang Rui 已提交
2605
#endif
2606 2607
        if (is->seek_req) {
            int64_t seek_target = is->seek_pos;
Z
Zhang Rui 已提交
2608 2609
            int64_t seek_min    = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
            int64_t seek_max    = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2610 2611 2612
// FIXME the +-2 is due to rounding being not done in the correct direction in generation
//      of the seek_pos/seek_rel variables

B
bbcallen 已提交
2613
            ffp_toggle_buffering(ffp, 1);
2614 2615
            ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
            if (ret < 0) {
Z
Zhang Rui 已提交
2616 2617
                av_log(NULL, AV_LOG_ERROR,
                       "%s: error while seeking\n", is->ic->filename);
2618 2619 2620 2621 2622
            } else {
                if (is->audio_stream >= 0) {
                    packet_queue_flush(&is->audioq);
                    packet_queue_put(&is->audioq, &flush_pkt);
                }
Z
Zhang Rui 已提交
2623
#ifdef FFP_MERGE
2624 2625 2626 2627
                if (is->subtitle_stream >= 0) {
                    packet_queue_flush(&is->subtitleq);
                    packet_queue_put(&is->subtitleq, &flush_pkt);
                }
Z
Zhang Rui 已提交
2628
#endif
2629
                if (is->video_stream >= 0) {
2630 2631 2632
                    if (ffp->node_vdec) {
                        ffpipenode_flush(ffp->node_vdec);
                    }
2633 2634 2635 2636
                    packet_queue_flush(&is->videoq);
                    packet_queue_put(&is->videoq, &flush_pkt);
                }
                if (is->seek_flags & AVSEEK_FLAG_BYTE) {
Z
Zhang Rui 已提交
2637
                   set_clock(&is->extclk, NAN, 0);
2638
                } else {
Z
Zhang Rui 已提交
2639
                   set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
2640 2641
                }
            }
2642
            ffp->current_high_water_mark_in_ms = ffp->start_high_water_mark_in_ms;
2643
            is->seek_req = 0;
Z
Zhang Rui 已提交
2644
            is->queue_attachments_req = 1;
2645
            is->eof = 0;
Z
Zhang Rui 已提交
2646 2647 2648 2649
#ifdef FFP_MERGE
            if (is->paused)
                step_to_next_frame(is);
#endif
B
bbcallen 已提交
2650
            completed = 0;
Z
Zhang Rui 已提交
2651
            SDL_LockMutex(ffp->is->play_mutex);
Z
Zhang Rui 已提交
2652
            if (ffp->auto_resume) {
2653
                is->pause_req = 0;
2654 2655
                if (ffp->packet_buffering)
                    is->buffering_on = 1;
Z
Zhang Rui 已提交
2656
                ffp->auto_resume = 0;
2657 2658 2659
                stream_update_pause_l(ffp);
            }
            if (is->pause_req)
2660
                step_to_next_frame_l(ffp);
Z
Zhang Rui 已提交
2661
            SDL_UnlockMutex(ffp->is->play_mutex);
2662
            ffp_notify_msg1(ffp, FFP_MSG_SEEK_COMPLETE);
B
bbcallen 已提交
2663
            ffp_toggle_buffering(ffp, 1);
2664 2665
        }
        if (is->queue_attachments_req) {
Z
Zhang Rui 已提交
2666 2667 2668 2669 2670
            if (is->video_st && (is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
                AVPacket copy;
                if ((ret = av_copy_packet(&copy, &is->video_st->attached_pic)) < 0)
                    goto fail;
                packet_queue_put(&is->videoq, &copy);
2671
                packet_queue_put_nullpacket(&is->videoq, is->video_stream);
Z
Zhang Rui 已提交
2672
            }
2673 2674 2675 2676
            is->queue_attachments_req = 0;
        }

        /* if the queue are full, no need to read more */
2677
        if (ffp->infinite_buffer<1 && !is->seek_req &&
Z
Zhang Rui 已提交
2678 2679
#ifdef FFP_MERGE
              (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
Z
Zhang Rui 已提交
2680
#else
2681 2682 2683 2684
              (((is->audioq.size + is->videoq.size > ffp->max_buffer_size)
                 && (is->audioq.nb_packets > 5 || is->audio_stream < 0 || is->audioq.abort_request)
                 && (is->videoq.nb_packets > 5 || is->video_stream < 0 || is->videoq.abort_request)
                )
Z
Zhang Rui 已提交
2685 2686
#endif
            || (   (is->audioq   .nb_packets > MIN_FRAMES || is->audio_stream < 0 || is->audioq.abort_request)
Z
Zhang Rui 已提交
2687 2688
                && (is->videoq   .nb_packets > MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request
                    || (is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC))
Z
Zhang Rui 已提交
2689
#ifdef FFP_MERGE
Z
Zhang Rui 已提交
2690
                && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0 || is->subtitleq.abort_request)))) {
Z
Zhang Rui 已提交
2691 2692 2693
#else
                ))) {
#endif
2694
            if (!is->eof) {
Z
Zhang Rui 已提交
2695
                ffp_toggle_buffering(ffp, 0);
Z
Zhang Rui 已提交
2696
            }
2697 2698 2699 2700 2701 2702
            /* wait 10 ms */
            SDL_LockMutex(wait_mutex);
            SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
            SDL_UnlockMutex(wait_mutex);
            continue;
        }
B
bbcallen 已提交
2703
        if ((!is->paused || completed) &&
2704
            (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
2705
            (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
2706 2707 2708 2709 2710 2711 2712
            if (ffp->loop != 1 && (!ffp->loop || --ffp->loop)) {
                stream_seek(is, ffp->start_time != AV_NOPTS_VALUE ? ffp->start_time : 0, 0, 0);
            } else if (ffp->autoexit) {
                ret = AVERROR_EOF;
                goto fail;
            } else {
                if (completed) {
2713
                    av_log(ffp, AV_LOG_INFO, "ffp_toggle_buffering: eof\n");
2714 2715
                    SDL_LockMutex(wait_mutex);
                    // infinite wait may block shutdown
B
bbcallen 已提交
2716
                    while(!is->abort_request && !is->seek_req)
Z
Zhang Rui 已提交
2717
                        SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 100);
2718
                    SDL_UnlockMutex(wait_mutex);
B
bbcallen 已提交
2719 2720
                    if (!is->abort_request)
                        continue;
2721 2722
                } else {
                    completed = 1;
Z
Zhang Rui 已提交
2723
                    ffp->auto_resume = 0;
2724 2725 2726 2727

                    // TODO: 0 it's a bit early to notify complete here
                    ffp_toggle_buffering(ffp, 0);
                    toggle_pause(ffp, 1);
Z
Zhang Rui 已提交
2728
                    if (ffp->error) {
2729
                        av_log(ffp, AV_LOG_INFO, "ffp_toggle_buffering: error: %d\n", ffp->error);
Z
Zhang Rui 已提交
2730 2731
                        ffp_notify_msg1(ffp, FFP_MSG_ERROR);
                    } else {
2732
                        av_log(ffp, AV_LOG_INFO, "ffp_toggle_buffering: completed: OK\n");
Z
Zhang Rui 已提交
2733 2734
                        ffp_notify_msg1(ffp, FFP_MSG_COMPLETED);
                    }
2735 2736 2737
                }
            }
        }
2738
        pkt->flags = 0;
2739 2740
        ret = av_read_frame(ic, pkt);
        if (ret < 0) {
2741
            if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
2742 2743 2744 2745 2746 2747 2748 2749
                if (is->video_stream >= 0)
                    packet_queue_put_nullpacket(&is->videoq, is->video_stream);
                if (is->audio_stream >= 0)
                    packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
#ifdef FFP_MERGE
                if (is->subtitle_stream >= 0)
                    packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
#endif
2750
                is->eof = 1;
2751
            }
2752
            if (ic->pb && ic->pb->error) {
2753 2754 2755 2756 2757 2758 2759 2760
                if (is->video_stream >= 0)
                    packet_queue_put_nullpacket(&is->videoq, is->video_stream);
                if (is->audio_stream >= 0)
                    packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
#ifdef FFP_MERGE
                if (is->subtitle_stream >= 0)
                    packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
#endif
2761
                is->eof = 1;
Z
Zhang Rui 已提交
2762
                ffp->error = ic->pb->error;
2763
                av_log(ffp, AV_LOG_ERROR, "av_read_frame error: %x(%c,%c,%c,%c): %s\n", ffp->error,
Z
Zhang Rui 已提交
2764 2765 2766
                      (char) (0xff & (ffp->error >> 24)),
                      (char) (0xff & (ffp->error >> 16)),
                      (char) (0xff & (ffp->error >> 8)),
Z
Zhang Rui 已提交
2767 2768
                      (char) (0xff & (ffp->error)),
                      ffp_get_error_string(ffp->error));
Z
Zhang Rui 已提交
2769
                // break;
Z
Zhang Rui 已提交
2770 2771
            } else {
                ffp->error = 0;
Z
Zhang Rui 已提交
2772
            }
2773
            if (is->eof) {
2774 2775 2776
                ffp_toggle_buffering(ffp, 0);
                SDL_Delay(1000);
            }
2777 2778 2779 2780
            SDL_LockMutex(wait_mutex);
            SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
            SDL_UnlockMutex(wait_mutex);
            continue;
2781
        } else {
2782
            is->eof = 0;
2783 2784
        }
        /* check if packet is in play range specified by user, then queue, otherwise discard */
Z
Zhang Rui 已提交
2785
        stream_start_time = ic->streams[pkt->stream_index]->start_time;
2786
        pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
2787
        pkt_in_play_range = ffp->duration == AV_NOPTS_VALUE ||
2788
                (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
Z
Zhang Rui 已提交
2789
                av_q2d(ic->streams[pkt->stream_index]->time_base) -
Z
Zhang Rui 已提交
2790 2791
                (double)(ffp->start_time != AV_NOPTS_VALUE ? ffp->start_time : 0) / 1000000
                <= ((double)ffp->duration / 1000000);
2792 2793
        if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
            packet_queue_put(&is->audioq, pkt);
Z
Zhang Rui 已提交
2794
        } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
Z
Zhang Rui 已提交
2795
                   && !(is->video_st && (is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC))) {
2796
            packet_queue_put(&is->videoq, pkt);
Z
Zhang Rui 已提交
2797
#ifdef FFP_MERGE
2798 2799
        } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
            packet_queue_put(&is->subtitleq, pkt);
Z
Zhang Rui 已提交
2800
#endif
2801 2802 2803
        } else {
            av_free_packet(pkt);
        }
Z
Zhang Rui 已提交
2804

2805 2806 2807 2808 2809 2810
        if (ffp->packet_buffering) {
            io_tick_counter = SDL_GetTickHR();
            if (abs((int)(io_tick_counter - prev_io_tick_counter)) > BUFFERING_CHECK_PER_MILLISECONDS) {
                prev_io_tick_counter = io_tick_counter;
                ffp_check_buffering_l(ffp);
            }
2811
        }
2812 2813 2814 2815 2816 2817 2818
    }
    /* wait until the end */
    while (!is->abort_request) {
        SDL_Delay(100);
    }

    ret = 0;
Z
Zhang Rui 已提交
2819
 fail:
2820 2821
    /* close each stream */
    if (is->audio_stream >= 0)
Z
Zhang Rui 已提交
2822
        stream_component_close(ffp, is->audio_stream);
2823
    if (is->video_stream >= 0)
Z
Zhang Rui 已提交
2824
        stream_component_close(ffp, is->video_stream);
Z
Zhang Rui 已提交
2825
#ifdef FFP_MERGE
2826
    if (is->subtitle_stream >= 0)
Z
Zhang Rui 已提交
2827
        stream_component_close(ffp, is->subtitle_stream);
Z
Zhang Rui 已提交
2828
#endif
2829
    if (ic) {
2830
        avformat_close_input(&is->ic);
2831
        is->ic = NULL;
2832 2833
    }

Z
Zhang Rui 已提交
2834
    if (!ffp->prepared || !is->abort_request) {
2835
        ffp->last_error = last_error;
2836
        ffp_notify_msg2(ffp, FFP_MSG_ERROR, last_error);
2837 2838 2839 2840 2841
    }
    SDL_DestroyMutex(wait_mutex);
    return 0;
}

2842
static int video_refresh_thread(void *arg);
2843 2844
static VideoState *stream_open(FFPlayer *ffp, const char *filename, AVInputFormat *iformat)
{
2845
    assert(!ffp->is);
Z
Zhang Rui 已提交
2846 2847 2848
    VideoState *is;

    is = av_mallocz(sizeof(VideoState));
2849 2850
    if (!is)
        return NULL;
2851 2852
    av_strlcpy(is->filename, filename, sizeof(is->filename));
    is->iformat = iformat;
Z
Zhang Rui 已提交
2853 2854
    is->ytop    = 0;
    is->xleft   = 0;
2855 2856

    /* start video display */
2857
    if (frame_queue_init(&is->pictq, &is->videoq, ffp->pictq_size, 1) < 0)
2858
        goto fail;
Z
Zhang Rui 已提交
2859
#ifdef FFP_MERGE
2860 2861
    if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
        goto fail;
Z
Zhang Rui 已提交
2862
#endif
2863 2864
    if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
        goto fail;
2865 2866 2867

    packet_queue_init(&is->videoq);
    packet_queue_init(&is->audioq);
Z
Zhang Rui 已提交
2868
#ifdef FFP_MERGE
2869
    packet_queue_init(&is->subtitleq);
Z
Zhang Rui 已提交
2870
#endif
2871 2872 2873

    is->continue_read_thread = SDL_CreateCond();

Z
Zhang Rui 已提交
2874 2875 2876
    init_clock(&is->vidclk, &is->videoq.serial);
    init_clock(&is->audclk, &is->audioq.serial);
    init_clock(&is->extclk, &is->extclk.serial);
2877 2878
    is->audio_clock_serial = -1;
    is->av_sync_type = ffp->av_sync_type;
2879

2880
    is->play_mutex = SDL_CreateMutex();
2881
    ffp->is = is;
2882
    is->pause_req = !ffp->start_on_prepared;
2883

Z
Zhang Rui 已提交
2884
    is->video_refresh_tid = SDL_CreateThreadEx(&is->_video_refresh_tid, video_refresh_thread, ffp, "ff_vout");
2885
    if (!is->video_refresh_tid) {
2886
        av_freep(&ffp->is);
2887 2888 2889
        return NULL;
    }

Z
Zhang Rui 已提交
2890
    is->read_tid = SDL_CreateThreadEx(&is->_read_tid, read_thread, ffp, "ff_read");
2891
    if (!is->read_tid) {
2892
fail:
2893
        is->abort_request = true;
2894 2895 2896
        if (is->video_refresh_tid)
            SDL_WaitThread(is->video_refresh_tid, NULL);
        stream_close(is);
2897 2898 2899 2900
        return NULL;
    }
    return is;
}
2901

Z
Zhang Rui 已提交
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921
// FFP_MERGE: stream_cycle_channel
// FFP_MERGE: toggle_full_screen
// FFP_MERGE: toggle_audio_display
// FFP_MERGE: refresh_loop_wait_event
// FFP_MERGE: event_loop
// FFP_MERGE: opt_frame_size
// FFP_MERGE: opt_width
// FFP_MERGE: opt_height
// FFP_MERGE: opt_format
// FFP_MERGE: opt_frame_pix_fmt
// FFP_MERGE: opt_sync
// FFP_MERGE: opt_seek
// FFP_MERGE: opt_duration
// FFP_MERGE: opt_show_mode
// FFP_MERGE: opt_input_file
// FFP_MERGE: opt_codec
// FFP_MERGE: dummy
// FFP_MERGE: options
// FFP_MERGE: show_usage
// FFP_MERGE: show_help_default
Z
Zhang Rui 已提交
2922
static int ffplay_video_refresh_thread(void *arg)
2923 2924
{
    FFPlayer *ffp = arg;
2925
    VideoState *is = ffp->is;
2926
    double remaining_time = 0.0;
2927
    while (!is->abort_request) {
2928
        if (remaining_time > 0.0)
B
bbcallen 已提交
2929
            av_usleep((int)(int64_t)(remaining_time * 1000000.0));
2930 2931
        remaining_time = REFRESH_RATE;
        if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
Z
Zhang Rui 已提交
2932
            video_refresh(ffp, &remaining_time);
2933
    }
2934 2935

    return 0;
2936
}
Z
Zhang Rui 已提交
2937 2938 2939 2940 2941 2942 2943 2944 2945
static int video_refresh_thread(void *arg)
{
    FFPlayer *ffp = (FFPlayer *)arg;

    IJKFF_Pipenode *node = ffpipeline_open_video_output(ffp->pipeline, ffp);
    int ret = ffpipenode_run_sync(node);
    ffpipenode_free_p(&node);
    return ret;
}
2946

2947 2948
static int lockmgr(void **mtx, enum AVLockOp op)
{
Z
Zhang Rui 已提交
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
    switch (op) {
    case AV_LOCK_CREATE:
        *mtx = SDL_CreateMutex();
        if (!*mtx)
            return 1;
        return 0;
    case AV_LOCK_OBTAIN:
        return !!SDL_LockMutex(*mtx);
    case AV_LOCK_RELEASE:
        return !!SDL_UnlockMutex(*mtx);
    case AV_LOCK_DESTROY:
        SDL_DestroyMutex(*mtx);
        return 0;
    }
    return 1;
2964 2965
}

Z
Zhang Rui 已提交
2966
// FFP_MERGE: main
2967 2968 2969 2970 2971 2972

/*****************************************************************************
 * end last line in ffplay.c
 ****************************************************************************/

static bool g_ffmpeg_global_inited = false;
Z
Zhang Rui 已提交
2973

2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004
inline static int log_level_av_to_ijk(int av_level)
{
    int ijk_level = IJK_LOG_VERBOSE;
    if      (av_level <= AV_LOG_PANIC)      ijk_level = IJK_LOG_FATAL;
    else if (av_level <= AV_LOG_FATAL)      ijk_level = IJK_LOG_FATAL;
    else if (av_level <= AV_LOG_ERROR)      ijk_level = IJK_LOG_ERROR;
    else if (av_level <= AV_LOG_WARNING)    ijk_level = IJK_LOG_WARN;
    else if (av_level <= AV_LOG_INFO)       ijk_level = IJK_LOG_INFO;
    // AV_LOG_VERBOSE means detailed info
    else if (av_level <= AV_LOG_VERBOSE)    ijk_level = IJK_LOG_INFO;
    else if (av_level <= AV_LOG_DEBUG)      ijk_level = IJK_LOG_DEBUG;
    else if (av_level <= AV_LOG_TRACE)      ijk_level = IJK_LOG_VERBOSE;
    else                                    ijk_level = IJK_LOG_VERBOSE;
    return ijk_level;
}

inline static int log_level_ijk_to_av(int ijk_level)
{
    int av_level = IJK_LOG_VERBOSE;
    if      (ijk_level >= IJK_LOG_SILENT)   av_level = AV_LOG_QUIET;
    else if (ijk_level >= IJK_LOG_FATAL)    av_level = AV_LOG_FATAL;
    else if (ijk_level >= IJK_LOG_ERROR)    av_level = AV_LOG_ERROR;
    else if (ijk_level >= IJK_LOG_WARN)     av_level = AV_LOG_WARNING;
    else if (ijk_level >= IJK_LOG_INFO)     av_level = AV_LOG_INFO;
    // AV_LOG_VERBOSE means detailed info
    else if (ijk_level >= IJK_LOG_DEBUG)    av_level = AV_LOG_DEBUG;
    else if (ijk_level >= IJK_LOG_VERBOSE)  av_level = AV_LOG_TRACE;
    else if (ijk_level >= IJK_LOG_DEFAULT)  av_level = AV_LOG_TRACE;
    else if (ijk_level >= IJK_LOG_UNKNOWN)  av_level = AV_LOG_TRACE;
    else                                    av_level = AV_LOG_TRACE;
    return av_level;
Z
Zhang Rui 已提交
3005
}
3006

3007
static void ffp_log_callback_brief(void *ptr, int level, const char *fmt, va_list vl)
3008
{
Z
Zhang Rui 已提交
3009 3010
    if (level > av_log_get_level())
        return;
3011

3012
    int ffplv __unused = log_level_av_to_ijk(level);
Z
Zhang Rui 已提交
3013
    VLOG(ffplv, IJK_LOG_TAG, fmt, vl);
3014 3015
}

3016 3017
static void ffp_log_callback_report(void *ptr, int level, const char *fmt, va_list vl)
{
Z
Zhang Rui 已提交
3018 3019
    if (level > av_log_get_level())
        return;
Z
Zhang Rui 已提交
3020

3021
    int ffplv __unused = log_level_av_to_ijk(level);
Z
Zhang Rui 已提交
3022

3023 3024 3025 3026 3027
    va_list vl2;
    char line[1024];
    static int print_prefix = 1;

    va_copy(vl2, vl);
Z
Zhang Rui 已提交
3028
    // av_log_default_callback(ptr, level, fmt, vl);
3029 3030 3031 3032 3033 3034
    av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
    va_end(vl2);

    ALOG(ffplv, IJK_LOG_TAG, "%s", line);
}

Z
Zhang Rui 已提交
3035
void ffp_global_init()
3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051
{
    if (g_ffmpeg_global_inited)
        return;

    /* register all codecs, demux and protocols */
    avcodec_register_all();
#if CONFIG_AVDEVICE
    avdevice_register_all();
#endif
#if CONFIG_AVFILTER
    avfilter_register_all();
#endif
    av_register_all();
    avformat_network_init();

    av_lockmgr_register(lockmgr);
Z
Zhang Rui 已提交
3052
    av_log_set_callback(ffp_log_callback_brief);
3053 3054

    av_init_packet(&flush_pkt);
Z
Zhang Rui 已提交
3055
    flush_pkt.data = (uint8_t *)&flush_pkt;
3056 3057 3058 3059

    g_ffmpeg_global_inited = true;
}

Z
Zhang Rui 已提交
3060
void ffp_global_uninit()
3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074
{
    if (!g_ffmpeg_global_inited)
        return;

    av_lockmgr_register(NULL);

#if CONFIG_AVFILTER
    avfilter_uninit();
    av_freep(&vfilters);
#endif
    avformat_network_deinit();

    g_ffmpeg_global_inited = false;
}
Z
Zhang Rui 已提交
3075

3076
void ffp_global_set_log_report(int use_report)
3077 3078 3079 3080 3081 3082 3083 3084
{
    if (use_report) {
        av_log_set_callback(ffp_log_callback_report);
    } else {
        av_log_set_callback(ffp_log_callback_brief);
    }
}

3085
void ffp_global_set_log_level(int log_level)
Z
Zhang Rui 已提交
3086
{
3087 3088
    int av_level = log_level_ijk_to_av(log_level);
    av_log_set_level(av_level);
Z
Zhang Rui 已提交
3089 3090
}

3091 3092
void ffp_io_stat_register(void (*cb)(const char *url, int type, int bytes))
{
Z
Zhang Rui 已提交
3093
    // avijk_io_stat_register(cb);
3094
}
Z
Zhang Rui 已提交
3095

Z
Zhang Rui 已提交
3096 3097 3098
void ffp_io_stat_complete_register(void (*cb)(const char *url,
                                              int64_t read_bytes, int64_t total_size,
                                              int64_t elpased_time, int64_t total_duration))
Z
Zhang Rui 已提交
3099
{
Z
Zhang Rui 已提交
3100
    // avijk_io_stat_complete_register(cb);
Z
Zhang Rui 已提交
3101 3102
}

3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
static const char *ffp_context_to_name(void *ptr)
{
    return "FFPlayer";
}


static void *ffp_context_child_next(void *obj, void *prev)
{
    return NULL;
}

static const AVClass *ffp_context_child_class_next(const AVClass *prev)
{
    return NULL;
}

const AVClass ffp_context_class = {
    .class_name       = "FFPlayer",
    .item_name        = ffp_context_to_name,
    .option           = ffp_context_options,
    .version          = LIBAVUTIL_VERSION_INT,
    .child_next       = ffp_context_child_next,
    .child_class_next = ffp_context_child_class_next,
};

Z
Zhang Rui 已提交
3128
FFPlayer *ffp_create()
Z
Zhang Rui 已提交
3129
{
Z
Zhang Rui 已提交
3130 3131
    av_log(NULL, AV_LOG_INFO, "av_version_info: %s\n", av_version_info());

Z
Zhang Rui 已提交
3132
    FFPlayer* ffp = (FFPlayer*) av_mallocz(sizeof(FFPlayer));
Z
Zhang Rui 已提交
3133 3134 3135
    if (!ffp)
        return NULL;

Z
Zhang Rui 已提交
3136
    msg_queue_init(&ffp->msg_queue);
Z
Zhang Rui 已提交
3137
    ffp_reset_internal(ffp);
3138
    ffp->av_class = &ffp_context_class;
Z
Zhang Rui 已提交
3139
    ffp->meta = ijkmeta_create();
3140 3141 3142

    av_opt_set_defaults(ffp);

Z
Zhang Rui 已提交
3143 3144 3145
    return ffp;
}

Z
Zhang Rui 已提交
3146
void ffp_destroy(FFPlayer *ffp)
Z
Zhang Rui 已提交
3147
{
Z
Zhang Rui 已提交
3148
    if (!ffp)
Z
Zhang Rui 已提交
3149 3150
        return;

3151
    if (ffp->is) {
Z
Zhang Rui 已提交
3152
        av_log(NULL, AV_LOG_WARNING, "ffp_destroy_ffplayer: force stream_close()");
3153
        stream_close(ffp->is);
3154 3155 3156
        ffp->is = NULL;
    }

Z
Zhang Rui 已提交
3157 3158
    SDL_VoutFreeP(&ffp->vout);
    SDL_AoutFreeP(&ffp->aout);
3159
    ffpipenode_free_p(&ffp->node_vdec);
Z
Zhang Rui 已提交
3160
    ffpipeline_free_p(&ffp->pipeline);
3161
    ijkmeta_destroy_p(&ffp->meta);
Z
Zhang Rui 已提交
3162
    ffp_reset_internal(ffp);
Z
Zhang Rui 已提交
3163 3164

    msg_queue_destroy(&ffp->msg_queue);
Z
Zhang Rui 已提交
3165

Z
Zhang Rui 已提交
3166

Z
Zhang Rui 已提交
3167
    av_free(ffp);
Z
Zhang Rui 已提交
3168 3169
}

Z
Zhang Rui 已提交
3170
void ffp_destroy_p(FFPlayer **pffp)
Z
Zhang Rui 已提交
3171
{
Z
Zhang Rui 已提交
3172 3173 3174 3175 3176
    if (!pffp)
        return;

    ffp_destroy(*pffp);
    *pffp = NULL;
Z
Zhang Rui 已提交
3177 3178
}

3179 3180 3181 3182 3183 3184
void ffp_set_format_callback(FFPlayer *ffp, ijk_format_control_message cb, void *opaque)
{
    ffp->format_control_message = cb;
    ffp->format_control_opaque  = opaque;
}

3185 3186 3187 3188 3189 3190 3191 3192 3193 3194
static AVDictionary **ffp_get_opt_dict(FFPlayer *ffp, int opt_category)
{
    assert(ffp);

    switch (opt_category) {
        case FFP_OPT_CATEGORY_FORMAT:   return &ffp->format_opts;
        case FFP_OPT_CATEGORY_CODEC:    return &ffp->codec_opts;
        case FFP_OPT_CATEGORY_SWS:      return &ffp->sws_opts;
        case FFP_OPT_CATEGORY_PLAYER:   return &ffp->player_opts;
        default:
3195
            av_log(ffp, AV_LOG_ERROR, "unknown option category %d\n", opt_category);
3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217
            return NULL;
    }
}

void ffp_set_option(FFPlayer *ffp, int opt_category, const char *name, const char *value)
{
    if (!ffp)
        return;

    AVDictionary **dict = ffp_get_opt_dict(ffp, opt_category);
    av_dict_set(dict, name, value, 0);
}

void ffp_set_option_int(FFPlayer *ffp, int opt_category, const char *name, int64_t value)
{
    if (!ffp)
        return;

    AVDictionary **dict = ffp_get_opt_dict(ffp, opt_category);
    av_dict_set_int(dict, name, value, 0);
}

Z
Zhang Rui 已提交
3218 3219 3220
void ffp_set_overlay_format(FFPlayer *ffp, int chroma_fourcc)
{
    switch (chroma_fourcc) {
Z
Zhang Rui 已提交
3221
        case SDL_FCC_I420:
Z
Zhang Rui 已提交
3222 3223
        case SDL_FCC_YV12:
        case SDL_FCC_RV16:
3224
        case SDL_FCC_RV24:
Z
Zhang Rui 已提交
3225 3226 3227 3228
        case SDL_FCC_RV32:
            ffp->overlay_format = chroma_fourcc;
            break;
        default:
3229
            av_log(ffp, AV_LOG_ERROR, "ffp_set_overlay_format: unknown chroma fourcc: %d\n", chroma_fourcc);
Z
Zhang Rui 已提交
3230 3231 3232 3233
            break;
    }
}

Z
Zhang Rui 已提交
3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261
int ffp_get_video_codec_info(FFPlayer *ffp, char **codec_info)
{
    if (!codec_info)
        return -1;

    // FIXME: not thread-safe
    if (ffp->video_codec_info) {
        *codec_info = strdup(ffp->video_codec_info);
    } else {
        *codec_info = NULL;
    }
    return 0;
}

int ffp_get_audio_codec_info(FFPlayer *ffp, char **codec_info)
{
    if (!codec_info)
        return -1;

    // FIXME: not thread-safe
    if (ffp->audio_codec_info) {
        *codec_info = strdup(ffp->audio_codec_info);
    } else {
        *codec_info = NULL;
    }
    return 0;
}

3262 3263 3264 3265 3266
static void ffp_show_dict(const char *tag, AVDictionary *dict)
{
    AVDictionaryEntry *t = NULL;

    while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) {
3267
        av_log(NULL, AV_LOG_INFO, "%-*s: %-*s = %s\n", 12, tag, 28, t->key, t->value);
3268 3269 3270
    }
}

Z
Zhang Rui 已提交
3271
int ffp_prepare_async_l(FFPlayer *ffp, const char *file_name)
Z
Zhang Rui 已提交
3272 3273
{
    assert(ffp);
3274
    assert(!ffp->is);
Z
Zhang Rui 已提交
3275 3276
    assert(file_name);

3277 3278 3279 3280 3281 3282 3283
    av_log(NULL, AV_LOG_INFO, "===== options =====\n");
    ffp_show_dict("player-opts", ffp->player_opts);
    ffp_show_dict("format-opts", ffp->format_opts);
    ffp_show_dict("codec-opts ", ffp->codec_opts);
    ffp_show_dict("sws-opts   ", ffp->sws_opts);
    av_log(NULL, AV_LOG_INFO, "===================\n");

3284
    av_opt_set_dict(ffp, &ffp->player_opts);
Z
Zhang Rui 已提交
3285 3286 3287 3288 3289
    if (!ffp->aout) {
        ffp->aout = ffpipeline_open_audio_output(ffp->pipeline, ffp);
        if (!ffp->aout)
            return -1;
    }
3290

Z
Zhang Rui 已提交
3291
    VideoState *is = stream_open(ffp, file_name, NULL);
3292
    if (!is) {
Z
Zhang Rui 已提交
3293
        av_log(NULL, AV_LOG_WARNING, "ffp_prepare_async_l: stream_open failed OOM");
Z
Zhang Rui 已提交
3294
        return EIJK_OUT_OF_MEMORY;
3295
    }
Z
Zhang Rui 已提交
3296

3297
    ffp->is = is;
Z
Zhang Rui 已提交
3298 3299 3300
    return 0;
}

Z
Zhang Rui 已提交
3301 3302 3303 3304 3305 3306 3307
int ffp_start_from_l(FFPlayer *ffp, long msec)
{
    assert(ffp);
    VideoState *is = ffp->is;
    if (!is)
        return EIJK_NULL_IS_PTR;

Z
Zhang Rui 已提交
3308
    ffp->auto_resume = 1;
Z
Zhang Rui 已提交
3309 3310 3311 3312 3313
    ffp_toggle_buffering(ffp, 1);
    ffp_seek_to_l(ffp, msec);
    return 0;
}

Z
Zhang Rui 已提交
3314
int ffp_start_l(FFPlayer *ffp)
Z
Zhang Rui 已提交
3315 3316
{
    assert(ffp);
3317 3318 3319 3320
    VideoState *is = ffp->is;
    if (!is)
        return EIJK_NULL_IS_PTR;

3321
    toggle_pause(ffp, 0);
Z
Zhang Rui 已提交
3322 3323 3324
    return 0;
}

Z
Zhang Rui 已提交
3325
int ffp_pause_l(FFPlayer *ffp)
Z
Zhang Rui 已提交
3326 3327
{
    assert(ffp);
3328 3329 3330 3331
    VideoState *is = ffp->is;
    if (!is)
        return EIJK_NULL_IS_PTR;

3332
    toggle_pause(ffp, 1);
Z
Zhang Rui 已提交
3333 3334
    return 0;
}
Z
Zhang Rui 已提交
3335

3336 3337 3338 3339 3340 3341 3342 3343 3344 3345
int ffp_is_paused_l(FFPlayer *ffp)
{
    assert(ffp);
    VideoState *is = ffp->is;
    if (!is)
        return 1;

    return is->paused;
}

Z
Zhang Rui 已提交
3346
int ffp_stop_l(FFPlayer *ffp)
Z
Zhang Rui 已提交
3347 3348
{
    assert(ffp);
3349
    VideoState *is = ffp->is;
Z
Zhang Rui 已提交
3350 3351 3352
    if (is)
        is->abort_request = 1;

3353
    msg_queue_abort(&ffp->msg_queue);
Z
Zhang Rui 已提交
3354 3355 3356
    return 0;
}

Z
Zhang Rui 已提交
3357
int ffp_wait_stop_l(FFPlayer *ffp)
Z
Zhang Rui 已提交
3358 3359
{
    assert(ffp);
3360

Z
Zhang Rui 已提交
3361 3362
    if (ffp->is) {
        ffp_stop_l(ffp);
3363
        stream_close(ffp->is);
Z
Zhang Rui 已提交
3364 3365
        ffp->is = NULL;
    }
Z
Zhang Rui 已提交
3366 3367
    return 0;
}
3368

Z
Zhang Rui 已提交
3369
int ffp_seek_to_l(FFPlayer *ffp, long msec)
Z
Zhang Rui 已提交
3370 3371 3372 3373 3374 3375
{
    assert(ffp);
    VideoState *is = ffp->is;
    if (!is)
        return EIJK_NULL_IS_PTR;

Z
Zhang Rui 已提交
3376 3377
    int64_t seek_pos = milliseconds_to_fftime(msec);
    int64_t start_time = is->ic->start_time;
3378
    if (start_time > 0 && start_time != AV_NOPTS_VALUE)
Z
Zhang Rui 已提交
3379 3380
        seek_pos += start_time;

Z
Zhang Rui 已提交
3381 3382 3383
    // FIXME: 9 seek by bytes
    // FIXME: 9 seek out of range
    // FIXME: 9 seekable
3384
    av_log(ffp, AV_LOG_DEBUG, "stream_seek %"PRId64"(%d) + %"PRId64", \n", seek_pos, (int)msec, start_time);
Z
Zhang Rui 已提交
3385
    stream_seek(is, seek_pos, 0, 0);
Z
Zhang Rui 已提交
3386 3387 3388
    return 0;
}

Z
Zhang Rui 已提交
3389
long ffp_get_current_position_l(FFPlayer *ffp)
3390 3391 3392 3393 3394 3395
{
    assert(ffp);
    VideoState *is = ffp->is;
    if (!is || !is->ic)
        return 0;

3396 3397 3398
    int64_t start_time = is->ic->start_time;
    int64_t start_diff = 0;
    if (start_time > 0 && start_time != AV_NOPTS_VALUE)
Z
Zhang Rui 已提交
3399
        start_diff = fftime_to_milliseconds(start_time);
3400 3401

    int64_t pos = 0;
Z
Zhang Rui 已提交
3402 3403
    double pos_clock = get_master_clock(is);
    if (isnan(pos_clock)) {
3404
        pos = fftime_to_milliseconds(is->seek_pos);
3405 3406 3407
    } else {
        pos = pos_clock * 1000;
    }
3408

3409
    if (pos < 0 || pos < start_diff)
3410 3411
        return 0;

3412
    int64_t adjust_pos = pos - start_diff;
3413
    return (long)adjust_pos;
3414 3415
}

Z
Zhang Rui 已提交
3416
long ffp_get_duration_l(FFPlayer *ffp)
3417 3418 3419 3420 3421 3422
{
    assert(ffp);
    VideoState *is = ffp->is;
    if (!is || !is->ic)
        return 0;

3423 3424 3425
    int64_t start_time = is->ic->start_time;
    int64_t start_diff = 0;
    if (start_time > 0 && start_time != AV_NOPTS_VALUE)
3426
        start_diff = fftime_to_milliseconds(start_time);
3427

3428
    int64_t duration = fftime_to_milliseconds(is->ic->duration);
3429
    if (duration < 0 || duration < start_diff)
3430 3431
        return 0;

3432
    int64_t adjust_duration = duration - start_diff;
3433
    return (long)adjust_duration;
3434
}
3435

3436 3437 3438 3439 3440 3441 3442 3443 3444
long ffp_get_playable_duration_l(FFPlayer *ffp)
{
    assert(ffp);
    if (!ffp)
        return 0;

    return (long)ffp->playable_duration_ms;
}

Z
Zhang Rui 已提交
3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502
void ffp_packet_queue_init(PacketQueue *q)
{
    return packet_queue_init(q);
}

void ffp_packet_queue_destroy(PacketQueue *q)
{
    return packet_queue_destroy(q);
}

void ffp_packet_queue_abort(PacketQueue *q)
{
    return packet_queue_abort(q);
}

void ffp_packet_queue_start(PacketQueue *q)
{
    return packet_queue_start(q);
}

void ffp_packet_queue_flush(PacketQueue *q)
{
    return packet_queue_flush(q);
}

int ffp_packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
{
    return packet_queue_get(q, pkt, block, serial);
}

int ffp_packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int *finished)
{
    return packet_queue_get_or_buffering(ffp, q, pkt, serial, finished);
}

int ffp_packet_queue_put(PacketQueue *q, AVPacket *pkt)
{
    return packet_queue_put(q, pkt);
}

bool ffp_is_flush_packet(AVPacket *pkt)
{
    if (!pkt)
        return false;

    return pkt->data == flush_pkt.data;
}

Frame *ffp_frame_queue_peek_writable(FrameQueue *f)
{
    return frame_queue_peek_writable(f);
}

void ffp_frame_queue_push(FrameQueue *f)
{
    return frame_queue_push(f);
}

3503 3504 3505 3506 3507 3508 3509 3510 3511 3512
int ffp_get_master_sync_type(VideoState *is)
{
    return get_master_sync_type(is);
}

double ffp_get_master_clock(VideoState *is)
{
    return get_master_clock(is);
}

3513
void ffp_toggle_buffering_l(FFPlayer *ffp, int buffering_on)
3514
{
3515 3516 3517
    if (!ffp->packet_buffering)
        return;

3518
    VideoState *is = ffp->is;
3519
    if (buffering_on && !is->buffering_on) {
3520
        av_log(ffp, AV_LOG_DEBUG, "ffp_toggle_buffering_l: start\n");
3521 3522
        is->buffering_on = 1;
        stream_update_pause_l(ffp);
3523
        ffp_notify_msg1(ffp, FFP_MSG_BUFFERING_START);
3524
    } else if (!buffering_on && is->buffering_on){
3525
        av_log(ffp, AV_LOG_DEBUG, "ffp_toggle_buffering_l: end\n");
3526 3527
        is->buffering_on = 0;
        stream_update_pause_l(ffp);
3528
        ffp_notify_msg1(ffp, FFP_MSG_BUFFERING_END);
3529 3530 3531 3532 3533 3534 3535 3536 3537
    }
}

void ffp_toggle_buffering(FFPlayer *ffp, int start_buffering)
{
    SDL_LockMutex(ffp->is->play_mutex);
    ffp_toggle_buffering_l(ffp, start_buffering);
    SDL_UnlockMutex(ffp->is->play_mutex);
}
3538 3539 3540 3541

void ffp_check_buffering_l(FFPlayer *ffp)
{
    VideoState *is            = ffp->is;
3542
    int hwm_in_ms             = ffp->current_high_water_mark_in_ms; // use fast water mark for first loading
3543 3544 3545 3546
    int buf_size_percent      = -1;
    int buf_time_percent      = -1;
    int hwm_in_bytes          = ffp->high_water_mark_in_bytes;
    int need_start_buffering  = 0;
3547 3548
    int audio_time_base_valid = 0;
    int video_time_base_valid = 0;
3549
    int64_t buf_time_position = -1;
3550 3551 3552 3553 3554 3555

    if(is->audio_st)
        audio_time_base_valid = is->audio_st->time_base.den > 0 && is->audio_st->time_base.num > 0;
    if(is->video_st)
        video_time_base_valid = is->video_st->time_base.den > 0 && is->video_st->time_base.num > 0;

3556 3557 3558 3559 3560 3561 3562 3563 3564
    if (hwm_in_ms > 0) {
        int     cached_duration_in_ms = -1;
        int64_t audio_cached_duration = -1;
        int64_t video_cached_duration = -1;

        if (is->audio_st && audio_time_base_valid) {
            audio_cached_duration = is->audioq.duration * av_q2d(is->audio_st->time_base) * 1000;
#ifdef FFP_SHOW_DEMUX_CACHE
            int audio_cached_percent = (int)av_rescale(audio_cached_duration, 1005, hwm_in_ms * 10);
3565
            av_log(ffp, AV_LOG_DEBUG, "audio cache=%%%d (%d/%d) (%d/%d)\n", audio_cached_percent,
Z
Zhang Rui 已提交
3566
                  (int)audio_cached_duration, hwm_in_ms,
Z
Zhang Rui 已提交
3567
                  is->audioq.size, hwm_in_bytes);
3568 3569 3570 3571 3572 3573 3574
#endif
        }

        if (is->video_st && video_time_base_valid) {
            video_cached_duration = is->videoq.duration * av_q2d(is->video_st->time_base) * 1000;
#ifdef FFP_SHOW_DEMUX_CACHE
            int video_cached_percent = (int)av_rescale(video_cached_duration, 1005, hwm_in_ms * 10);
3575
            av_log(ffp, AV_LOG_DEBUG, "video cache=%%%d (%d/%d) (%d/%d)\n", video_cached_percent,
Z
Zhang Rui 已提交
3576 3577
                  (int)video_cached_duration, hwm_in_ms,
                  is->videoq.size, hwm_in_bytes);
3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593
#endif
        }

        is->audioq_duration = audio_cached_duration;
        is->videoq_duration = video_cached_duration;

        if (video_cached_duration > 0 && audio_cached_duration > 0) {
            cached_duration_in_ms = (int)IJKMIN(video_cached_duration, audio_cached_duration);
        } else if (video_cached_duration > 0) {
            cached_duration_in_ms = (int)video_cached_duration;
        } else if (audio_cached_duration > 0) {
            cached_duration_in_ms = (int)audio_cached_duration;
        }

        if (cached_duration_in_ms >= 0) {
            buf_time_position = ffp_get_current_position_l(ffp) + cached_duration_in_ms;
3594 3595
            ffp->playable_duration_ms = buf_time_position;

3596 3597
            buf_time_percent = (int)av_rescale(cached_duration_in_ms, 1005, hwm_in_ms * 10);
#ifdef FFP_SHOW_DEMUX_CACHE
3598
            av_log(ffp, AV_LOG_DEBUG, "time cache=%%%d (%d/%d)\n", buf_time_percent, cached_duration_in_ms, hwm_in_ms);
3599 3600 3601
#endif
#ifdef FFP_NOTIFY_BUF_TIME
            ffp_notify_msg3(ffp, FFP_MSG_BUFFERING_TIME_UPDATE, cached_duration_in_ms, hwm_in_ms);
3602 3603 3604 3605 3606 3607 3608 3609
#endif
        }
    }

    int cached_size = is->audioq.size + is->videoq.size;
    if (hwm_in_bytes > 0) {
        buf_size_percent = (int)av_rescale(cached_size, 1005, hwm_in_bytes * 10);
#ifdef FFP_SHOW_DEMUX_CACHE
3610
        av_log(ffp, AV_LOG_DEBUG, "size cache=%%%d (%d/%d)\n", buf_size_percent, cached_size, hwm_in_bytes);
3611 3612 3613
#endif
#ifdef FFP_NOTIFY_BUF_BYTES
        ffp_notify_msg3(ffp, FFP_MSG_BUFFERING_BYTES_UPDATE, cached_size, hwm_in_bytes);
3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632
#endif
    }

    int buf_percent = -1;
    if (buf_time_percent >= 0) {
        // alwas depend on cache duration if valid
        if (buf_time_percent >= 100)
            need_start_buffering = 1;
        buf_percent = buf_time_percent;
    } else {
        if (buf_size_percent >= 100)
            need_start_buffering = 1;
        buf_percent = buf_size_percent;
    }

    if (buf_time_percent >= 0 && buf_size_percent >= 0) {
        buf_percent = FFMIN(buf_time_percent, buf_size_percent);
    }
    if (buf_percent) {
3633
#ifdef FFP_SHOW_BUF_POS
3634
        av_log(ffp, AV_LOG_DEBUG, "buf pos=%"PRId64", %%%d\n", buf_time_position, buf_percent);
3635
#endif
3636
        ffp_notify_msg3(ffp, FFP_MSG_BUFFERING_UPDATE, (int)buf_time_position, buf_percent);
3637 3638 3639
    }

    if (need_start_buffering) {
3640 3641 3642 3643 3644
        if (hwm_in_ms < ffp->next_high_water_mark_in_ms) {
            hwm_in_ms = ffp->next_high_water_mark_in_ms;
        } else {
            hwm_in_ms *= 2;
        }
3645 3646 3647 3648

        if (hwm_in_ms > ffp->max_high_water_mark_in_ms)
            hwm_in_ms = ffp->max_high_water_mark_in_ms;

3649
        ffp->current_high_water_mark_in_ms = hwm_in_ms;
3650 3651

        if (is->buffer_indicator_queue && is->buffer_indicator_queue->nb_packets > 0) {
3652 3653 3654 3655
            if (   (is->audioq.nb_packets > 5 || is->audio_stream < 0 || is->audioq.abort_request)
                && (is->videoq.nb_packets > 5 || is->video_stream < 0 || is->videoq.abort_request)) {
                ffp_toggle_buffering(ffp, 0);
            }
3656
        }
3657 3658
    }
}
3659

Z
Zhang Rui 已提交
3660 3661 3662 3663 3664 3665 3666 3667 3668 3669
int ffp_video_thread(FFPlayer *ffp)
{
    return ffplay_video_thread(ffp);
}

int ffp_video_refresh_thread(FFPlayer *ffp)
{
    return ffplay_video_refresh_thread(ffp);
}

Z
Zhang Rui 已提交
3670 3671 3672 3673
void ffp_set_video_codec_info(FFPlayer *ffp, const char *module, const char *codec)
{
    av_freep(&ffp->video_codec_info);
    ffp->video_codec_info = av_asprintf("%s, %s", module ? module : "", codec ? codec : "");
3674
    av_log(ffp, AV_LOG_INFO, "VideoCodec: %s\n", ffp->video_codec_info);
Z
Zhang Rui 已提交
3675 3676 3677 3678 3679 3680
}

void ffp_set_audio_codec_info(FFPlayer *ffp, const char *module, const char *codec)
{
    av_freep(&ffp->audio_codec_info);
    ffp->audio_codec_info = av_asprintf("%s, %s", module ? module : "", codec ? codec : "");
3681
    av_log(ffp, AV_LOG_INFO, "AudioCodec: %s\n", ffp->audio_codec_info);
Z
Zhang Rui 已提交
3682 3683
}

Z
Zhang Rui 已提交
3684 3685 3686 3687 3688 3689 3690 3691
IjkMediaMeta *ffp_get_meta_l(FFPlayer *ffp)
{
    if (!ffp)
        return NULL;

    return ffp->meta;
}

3692 3693 3694 3695 3696 3697
static int ffp_format_control_message(struct AVFormatContext *s, int type,
                                      void *data, size_t data_size)
{
    if (s == NULL)
        return -1;

3698
    FFPlayer *ffp = (FFPlayer *)av_format_get_opaque(s);
3699 3700 3701 3702 3703 3704 3705 3706
    if (ffp == NULL)
        return -1;

    if (!ffp->format_control_message)
        return -1;

    return ffp->format_control_message(ffp->format_control_opaque, type, data, data_size);
}