blob: 7560642a72f56cc924d6c1b191da4779cbdeeae2 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "LiveDataSource"
#include <utils/Log.h>
#include "LiveDataSource.h"
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#define SAVE_BACKUP 0
namespace android {
LiveDataSource::LiveDataSource()
: mOffset(0),
mFinalResult(OK),
mBackupFile(NULL) {
#if SAVE_BACKUP
mBackupFile = fopen("/data/misc/backup.ts", "wb");
CHECK(mBackupFile != NULL);
#endif
}
LiveDataSource::~LiveDataSource() {
if (mBackupFile != NULL) {
fclose(mBackupFile);
mBackupFile = NULL;
}
}
status_t LiveDataSource::initCheck() const {
return OK;
}
size_t LiveDataSource::countQueuedBuffers() {
Mutex::Autolock autoLock(mLock);
return mBufferQueue.size();
}
ssize_t LiveDataSource::readAtNonBlocking(
off64_t offset, void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
if (offset != mOffset) {
ALOGE("Attempt at reading non-sequentially from LiveDataSource.");
return -EPIPE;
}
size_t totalAvailable = 0;
for (List<sp<ABuffer> >::iterator it = mBufferQueue.begin();
it != mBufferQueue.end(); ++it) {
sp<ABuffer> buffer = *it;
totalAvailable += buffer->size();
if (totalAvailable >= size) {
break;
}
}
if (totalAvailable < size) {
return mFinalResult == OK ? -EWOULDBLOCK : mFinalResult;
}
return readAt_l(offset, data, size);
}
ssize_t LiveDataSource::readAt(off64_t offset, void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
return readAt_l(offset, data, size);
}
ssize_t LiveDataSource::readAt_l(off64_t offset, void *data, size_t size) {
if (offset != mOffset) {
ALOGE("Attempt at reading non-sequentially from LiveDataSource.");
return -EPIPE;
}
size_t sizeDone = 0;
while (sizeDone < size) {
while (mBufferQueue.empty() && mFinalResult == OK) {
mCondition.wait(mLock);
}
if (mBufferQueue.empty()) {
if (sizeDone > 0) {
mOffset += sizeDone;
return sizeDone;
}
return mFinalResult;
}
sp<ABuffer> buffer = *mBufferQueue.begin();
size_t copy = size - sizeDone;
if (copy > buffer->size()) {
copy = buffer->size();
}
memcpy((uint8_t *)data + sizeDone, buffer->data(), copy);
sizeDone += copy;
buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
if (buffer->size() == 0) {
mBufferQueue.erase(mBufferQueue.begin());
}
}
mOffset += sizeDone;
return sizeDone;
}
void LiveDataSource::queueBuffer(const sp<ABuffer> &buffer) {
Mutex::Autolock autoLock(mLock);
if (mFinalResult != OK) {
return;
}
#if SAVE_BACKUP
if (mBackupFile != NULL) {
CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mBackupFile),
buffer->size());
}
#endif
mBufferQueue.push_back(buffer);
mCondition.broadcast();
}
void LiveDataSource::queueEOS(status_t finalResult) {
CHECK_NE(finalResult, (status_t)OK);
Mutex::Autolock autoLock(mLock);
mFinalResult = finalResult;
mCondition.broadcast();
}
void LiveDataSource::reset() {
Mutex::Autolock autoLock(mLock);
// XXX FIXME: If we've done a partial read and waiting for more buffers,
// we'll mix old and new data...
mFinalResult = OK;
mBufferQueue.clear();
}
} // namespace android