Merge "Add caching mechanism to speed up midi file reading speed." am: 145a0becf0 am: be670f474b
Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/1429788
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: Id5a6ebfb5f08180cad4657c256ad152a5390d936
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index da272e3..f682b6e 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -21,6 +21,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <algorithm>
#include <media/MidiIoWrapper.h>
#include <media/MediaExtractorPluginApi.h>
@@ -33,6 +34,8 @@
}
namespace android {
+int MidiIoWrapper::sCacheBufferSize = 0;
+Mutex MidiIoWrapper::mCacheLock;
MidiIoWrapper::MidiIoWrapper(const char *path) {
ALOGV("MidiIoWrapper(%s)", path);
@@ -40,6 +43,8 @@
mBase = 0;
mLength = lseek(mFd, 0, SEEK_END);
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::MidiIoWrapper(int fd, off64_t offset, int64_t size) {
@@ -48,6 +53,8 @@
mBase = offset;
mLength = size;
mDataSource = nullptr;
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
class MidiIoWrapper::DataSourceUnwrapper {
@@ -97,6 +104,8 @@
} else {
mLength = 0;
}
+ mCacheBuffer = NULL;
+ mCacheBufRangeLength = 0;
}
MidiIoWrapper::~MidiIoWrapper() {
@@ -105,11 +114,80 @@
close(mFd);
}
delete mDataSource;
+
+ if (NULL != mCacheBuffer) {
+ delete [] mCacheBuffer;
+ mCacheBuffer = NULL;
+ {
+ Mutex::Autolock _l(mCacheLock);
+ sCacheBufferSize -= mLength;
+ }
+ }
}
int MidiIoWrapper::readAt(void *buffer, int offset, int size) {
ALOGV("readAt(%p, %d, %d)", buffer, offset, size);
+ if (offset < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (offset + size > mLength) {
+ size = mLength - offset;
+ }
+
+ if (mCacheBuffer == NULL) {
+ Mutex::Autolock _l(mCacheLock);
+ if (sCacheBufferSize + mLength <= kTotalCacheSize) {
+ mCacheBuffer = new (std::nothrow) unsigned char[mLength];
+ if (NULL != mCacheBuffer) {
+ sCacheBufferSize += mLength;
+ ALOGV("sCacheBufferSize : %d", sCacheBufferSize);
+ } else {
+ ALOGE("failed to allocate memory for mCacheBuffer");
+ }
+ } else {
+ ALOGV("not allocate memory for mCacheBuffer");
+ }
+ }
+
+ if (mCacheBuffer != NULL) {
+ if (mCacheBufRangeLength > 0 && mCacheBufRangeLength >= (offset + size)) {
+ /* Use buffered data */
+ memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+ return size;
+ } else {
+ /* Buffer new data */
+ int64_t beyondCacheBufRangeLength = (offset + size) - mCacheBufRangeLength;
+ int64_t numRequiredBytesToCache =
+ std::max((int64_t)kSingleCacheSize, beyondCacheBufRangeLength);
+ int64_t availableReadLength = mLength - mCacheBufRangeLength;
+ int64_t readSize = std::min(availableReadLength, numRequiredBytesToCache);
+ int actualNumBytesRead =
+ unbufferedReadAt(mCacheBuffer + mCacheBufRangeLength,
+ mCacheBufRangeLength, readSize);
+ if(actualNumBytesRead > 0) {
+ mCacheBufRangeLength += actualNumBytesRead;
+ if (offset >= mCacheBufRangeLength) {
+ return 0;
+ } else if (offset + size >= mCacheBufRangeLength) {
+ memcpy(buffer, (void*)(mCacheBuffer + offset), mCacheBufRangeLength - offset);
+ return mCacheBufRangeLength - offset;
+ } else {
+ memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+ return size;
+ }
+ } else {
+ return actualNumBytesRead;
+ }
+ }
+ } else {
+ return unbufferedReadAt(buffer, offset, size);
+ }
+}
+
+int MidiIoWrapper::unbufferedReadAt(void *buffer, int offset, int size) {
+ ALOGV("unbufferedReadAt(%p, %d, %d)", buffer, offset, size);
if (mDataSource != NULL) {
return mDataSource->readAt(offset, buffer, size);
}
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 0cdd4ad..5fa745c 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -18,6 +18,7 @@
#define MIDI_IO_WRAPPER_H_
#include <libsonivox/eas_types.h>
+#include <utils/Mutex.h>
namespace android {
@@ -32,17 +33,27 @@
~MidiIoWrapper();
int readAt(void *buffer, int offset, int size);
+ int unbufferedReadAt(void *buffer, int offset, int size);
int size();
EAS_FILE_LOCATOR getLocator();
private:
+ enum {
+ kTotalCacheSize = 1024 * 1024 + 512 * 1024,
+ kSingleCacheSize = 65536,
+ };
+
int mFd;
off64_t mBase;
int64_t mLength;
class DataSourceUnwrapper;
DataSourceUnwrapper *mDataSource;
EAS_FILE mEasFile;
+ unsigned char *mCacheBuffer;
+ int64_t mCacheBufRangeLength;
+ static int sCacheBufferSize;
+ static Mutex mCacheLock;
};