Exemple #1
0
static int cache_fill_buffer(struct stream *cache, char *buffer, int max_len)
{
    struct priv *s = cache->priv;
    assert(s->cache_thread_running);

    pthread_mutex_lock(&s->mutex);

    if (cache->pos != s->read_filepos)
        MP_ERR(s, "!!! read_filepos differs !!! report this bug...\n");

    int readb = 0;
    if (max_len > 0) {
        double retry_time = 0;
        int64_t retry = s->reads - 1; // try at least 1 read on EOF
        while (1) {
            readb = read_buffer(s, buffer, max_len, s->read_filepos);
            s->read_filepos += readb;
            if (readb > 0)
                break;
            if (s->eof && s->read_filepos >= s->max_filepos && s->reads >= retry)
                break;
            s->idle = false;
            if (mp_cancel_test(s->cache->cancel))
                break;
            cache_wakeup_and_wait(s, &retry_time);
        }
    }

    // wakeup the cache thread, possibly make it read more data ahead
    pthread_cond_signal(&s->wakeup);
    pthread_mutex_unlock(&s->mutex);
    return readb;
}
Exemple #2
0
// Runs in the main thread
// mutex must be held, but is sometimes temporarily dropped
static int cache_read(struct priv *s, unsigned char *buf, int size)
{
    if (size <= 0)
        return 0;

    double retry = 0;
    while (s->read_filepos >= s->max_filepos ||
           s->read_filepos < s->min_filepos)
    {
        if (s->eof && s->read_filepos >= s->max_filepos)
            return 0;
        if (cache_wakeup_and_wait(s, &retry) == CACHE_INTERRUPTED)
            return 0;
    }

    int64_t newb = s->max_filepos - s->read_filepos; // new bytes in the buffer

    int64_t pos = s->read_filepos - s->offset; // file pos to buffer memory pos
    if (pos < 0)
        pos += s->buffer_size;
    else if (pos >= s->buffer_size)
        pos -= s->buffer_size;

    if (newb > s->buffer_size - pos)
        newb = s->buffer_size - pos; // handle wrap...

    newb = FFMIN(newb, size);

    memcpy(buf, &s->buffer[pos], newb);

    s->read_filepos += newb;
    return newb;
}
Exemple #3
0
static int cache_control(stream_t *cache, int cmd, void *arg)
{
    struct priv *s = cache->priv;
    int r = STREAM_ERROR;

    assert(cmd > 0);

    pthread_mutex_lock(&s->mutex);

    r = cache_get_cached_control(cache, cmd, arg);
    if (r != STREAM_ERROR)
        goto done;

    MP_VERBOSE(s, "blocking for STREAM_CTRL %d\n", cmd);

    s->control = cmd;
    s->control_arg = arg;
    double retry = 0;
    while (s->control != CACHE_CTRL_NONE) {
        if (mp_cancel_test(s->cache->cancel)) {
            s->eof = 1;
            r = STREAM_UNSUPPORTED;
            goto done;
        }
        cache_wakeup_and_wait(s, &retry);
    }
    r = s->control_res;
    if (s->control_flush) {
        stream_drop_buffers(cache);
        cache->pos = s->read_filepos;
    }

done:
    pthread_mutex_unlock(&s->mutex);
    return r;
}
Exemple #4
0
static int cache_control(stream_t *cache, int cmd, void *arg)
{
    struct priv *s = cache->priv;
    int r = STREAM_ERROR;

    assert(cmd > 0);

    pthread_mutex_lock(&s->mutex);

    r = cache_get_cached_control(cache, cmd, arg);
    if (r != STREAM_ERROR)
        goto done;

    mp_msg(MSGT_CACHE, MSGL_V, "[cache] blocking for STREAM_CTRL %d\n", cmd);

    s->control = cmd;
    s->control_arg = arg;
    double retry = 0;
    while (s->control != CACHE_CTRL_NONE) {
        if (cache_wakeup_and_wait(s, &retry) == CACHE_INTERRUPTED) {
            s->eof = 1;
            r = STREAM_UNSUPPORTED;
            goto done;
        }
    }
    r = s->control_res;
    if (s->control_flush) {
        cache->pos = s->read_filepos;
        cache->eof = 0;
        cache->buf_pos = cache->buf_len = 0;
    }

done:
    pthread_mutex_unlock(&s->mutex);
    return r;
}