ThrottledSource.cpp revision f1d5aa162c02a16b7195a43a9bcea4d592600ac4
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "include/ThrottledSource.h"
18
19#include <media/stagefright/foundation/ADebug.h>
20
21namespace android {
22
23static int64_t getNowUs() {
24    struct timeval tv;
25    gettimeofday(&tv, NULL);
26
27    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
28}
29
30ThrottledSource::ThrottledSource(
31        const sp<DataSource> &source,
32        int32_t bandwidthLimitBytesPerSecond)
33    : mSource(source),
34      mBandwidthLimitBytesPerSecond(bandwidthLimitBytesPerSecond),
35      mStartTimeUs(-1),
36      mTotalTransferred(0) {
37    CHECK(mBandwidthLimitBytesPerSecond > 0);
38}
39
40status_t ThrottledSource::initCheck() const {
41    return mSource->initCheck();
42}
43
44ssize_t ThrottledSource::readAt(off64_t offset, void *data, size_t size) {
45    Mutex::Autolock autoLock(mLock);
46
47    ssize_t n = mSource->readAt(offset, data, size);
48
49    if (n <= 0) {
50        return n;
51    }
52
53    mTotalTransferred += n;
54
55    int64_t nowUs = getNowUs();
56
57    if (mStartTimeUs < 0) {
58        mStartTimeUs = nowUs;
59    }
60
61    // How long would it have taken to transfer everything we ever
62    // transferred given the limited bandwidth.
63    int64_t durationUs =
64        mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
65
66    int64_t whenUs = mStartTimeUs + durationUs;
67
68    if (whenUs > nowUs) {
69        usleep(whenUs - nowUs);
70    }
71
72    return n;
73}
74
75status_t ThrottledSource::getSize(off64_t *size) {
76    return mSource->getSize(size);
77}
78
79uint32_t ThrottledSource::flags() {
80    return mSource->flags();
81}
82
83}  // namespace android
84
85