summaryrefslogtreecommitdiffstats
path: root/media/libstagefright
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright')
-rw-r--r--media/libstagefright/AwesomePlayer.cpp148
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp3
-rw-r--r--media/libstagefright/MPEG4Writer.cpp174
-rw-r--r--media/libstagefright/MetaData.cpp12
-rw-r--r--media/libstagefright/OMXCodec.cpp12
-rw-r--r--media/libstagefright/WVMExtractor.cpp19
-rw-r--r--media/libstagefright/codecs/aacdec/Android.mk2
-rw-r--r--media/libstagefright/codecs/amrnb/dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/avc/dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/g711/dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/mp3dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/on2/dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/vorbis/dec/Android.mk2
-rw-r--r--media/libstagefright/colorconversion/Android.mk4
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp73
-rw-r--r--media/libstagefright/include/AwesomePlayer.h5
-rw-r--r--media/libstagefright/include/WVMExtractor.h20
18 files changed, 420 insertions, 66 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b45e5d3..fb7a871 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -24,11 +24,13 @@
#include "include/ARTSPController.h"
#include "include/AwesomePlayer.h"
+#include "include/DRMExtractor.h"
#include "include/SoftwareRenderer.h"
#include "include/NuCachedSource2.h"
#include "include/ThrottledSource.h"
#include "include/MPEG2TSExtractor.h"
#include "include/TimedTextPlayer.h"
+#include "include/WVMExtractor.h"
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -447,6 +449,7 @@ void AwesomePlayer::reset_l() {
cancelPlayerEvents();
+ mWVMExtractor.clear();
mCachedSource.clear();
mAudioTrack.clear();
mVideoTrack.clear();
@@ -545,6 +548,11 @@ bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
*durationUs = cachedDataRemaining * 8000000ll / bitrate;
*eos = (finalStatus != OK);
return true;
+ } else if (mWVMExtractor != NULL) {
+ status_t finalStatus;
+ *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
+ *eos = (finalStatus != OK);
+ return true;
}
return false;
@@ -637,6 +645,30 @@ void AwesomePlayer::onBufferingUpdate() {
}
}
}
+ } else if (mWVMExtractor != NULL) {
+ status_t finalStatus;
+
+ int64_t cachedDurationUs
+ = mWVMExtractor->getCachedDurationUs(&finalStatus);
+
+ bool eos = (finalStatus != OK);
+
+ if (eos) {
+ if (finalStatus == ERROR_END_OF_STREAM) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ }
+ if (mFlags & PREPARING) {
+ LOGV("cache has reached EOS, prepare is done.");
+ finishAsyncPrepare_l();
+ }
+ } else {
+ int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
+
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
+ }
}
int64_t cachedDurationUs;
@@ -1425,7 +1457,7 @@ void AwesomePlayer::onVideoEvent() {
mVideoBuffer = NULL;
}
- if (mSeeking == SEEK && mCachedSource != NULL && mAudioSource != NULL
+ if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
&& !(mFlags & SEEK_PREVIEW)) {
// We're going to seek the video source first, followed by
// the audio source.
@@ -1760,8 +1792,19 @@ status_t AwesomePlayer::prepareAsync_l() {
status_t AwesomePlayer::finishSetDataSource_l() {
sp<DataSource> dataSource;
+ bool isWidevineStreaming = false;
+ if (!strncasecmp("widevine://", mUri.string(), 11)) {
+ isWidevineStreaming = true;
+
+ String8 newURI = String8("http://");
+ newURI.append(mUri.string() + 11);
+
+ mUri = newURI;
+ }
+
if (!strncasecmp("http://", mUri.string(), 7)
- || !strncasecmp("https://", mUri.string(), 8)) {
+ || !strncasecmp("https://", mUri.string(), 8)
+ || isWidevineStreaming) {
mConnectingDataSource = HTTPBase::Create(
(mFlags & INCOGNITO)
? HTTPBase::kFlagIncognito
@@ -1778,16 +1821,24 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return err;
}
+ if (!isWidevineStreaming) {
+ // The widevine extractor does its own caching.
+
#if 0
- mCachedSource = new NuCachedSource2(
- new ThrottledSource(
- mConnectingDataSource, 50 * 1024 /* bytes/sec */));
+ mCachedSource = new NuCachedSource2(
+ new ThrottledSource(
+ mConnectingDataSource, 50 * 1024 /* bytes/sec */));
#else
- mCachedSource = new NuCachedSource2(mConnectingDataSource);
+ mCachedSource = new NuCachedSource2(mConnectingDataSource);
#endif
+
+ dataSource = mCachedSource;
+ } else {
+ dataSource = mConnectingDataSource;
+ }
+
mConnectingDataSource.clear();
- dataSource = mCachedSource;
String8 contentType = dataSource->getMIMEType();
@@ -1801,28 +1852,35 @@ status_t AwesomePlayer::finishSetDataSource_l() {
// could block on the datasource for a significant amount of time.
// During that time we'd be unable to abort the preparation phase
// without this prefill.
+ if (mCachedSource != NULL) {
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+
+ mLock.unlock();
+
+ for (;;) {
+ status_t finalStatus;
+ size_t cachedDataRemaining =
+ mCachedSource->approxDataRemaining(&finalStatus);
+
+ if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+ || (mFlags & PREPARE_CANCELLED)) {
+ break;
+ }
- mLock.unlock();
-
- for (;;) {
- status_t finalStatus;
- size_t cachedDataRemaining =
- mCachedSource->approxDataRemaining(&finalStatus);
-
- if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
- || (mFlags & PREPARE_CANCELLED)) {
- break;
+ usleep(200000);
}
- usleep(200000);
+ mLock.lock();
}
- mLock.lock();
- }
-
- if (mFlags & PREPARE_CANCELLED) {
- LOGI("Prepare cancelled while waiting for initial cache fill.");
- return UNKNOWN_ERROR;
+ if (mFlags & PREPARE_CANCELLED) {
+ LOGI("Prepare cancelled while waiting for initial cache fill.");
+ return UNKNOWN_ERROR;
+ }
}
} else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
if (mLooper == NULL) {
@@ -1856,10 +1914,29 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return UNKNOWN_ERROR;
}
- sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+ sp<MediaExtractor> extractor;
- if (extractor == NULL) {
- return UNKNOWN_ERROR;
+ if (isWidevineStreaming) {
+ String8 mimeType;
+ float confidence;
+ sp<AMessage> dummy;
+ bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
+
+ if (!success
+ || strcasecmp(
+ mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ mWVMExtractor = new WVMExtractor(dataSource);
+ mWVMExtractor->setAdaptiveStreamingMode(true);
+ extractor = mWVMExtractor;
+ } else {
+ extractor = MediaExtractor::Create(dataSource);
+
+ if (extractor == NULL) {
+ return UNKNOWN_ERROR;
+ }
}
dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
@@ -1871,7 +1948,15 @@ status_t AwesomePlayer::finishSetDataSource_l() {
}
}
- return setDataSource_l(extractor);
+ status_t err = setDataSource_l(extractor);
+
+ if (err != OK) {
+ mWVMExtractor.clear();
+
+ return err;
+ }
+
+ return OK;
}
void AwesomePlayer::abortPrepare(status_t err) {
@@ -1932,7 +2017,7 @@ void AwesomePlayer::onPrepareAsyncEvent() {
mFlags |= PREPARING_CONNECTED;
- if (mCachedSource != NULL || mRTSPController != NULL) {
+ if (isStreamingHTTP() || mRTSPController != NULL) {
postBufferingEvent_l();
} else {
finishAsyncPrepare_l();
@@ -1985,4 +2070,9 @@ status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
return OK;
}
+
+bool AwesomePlayer::isStreamingHTTP() const {
+ return mCachedSource != NULL || mWVMExtractor != NULL;
+}
+
} // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index c79d02e..6692809 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2171,6 +2171,9 @@ static bool isCompatibleBrand(uint32_t fourcc) {
// Just give these file types a chance.
FOURCC('q', 't', ' ', ' '), // Apple's QuickTime
FOURCC('M', 'S', 'N', 'V'), // Sony's PSP
+
+ FOURCC('3', 'g', '2', 'a'), // 3GPP2
+ FOURCC('3', 'g', '2', 'b'),
};
for (size_t i = 0;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index fd60f06..f6a8b17 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -33,6 +33,7 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/Utils.h>
#include <media/mediarecorder.h>
+#include <cutils/properties.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -257,7 +258,11 @@ MPEG4Writer::MPEG4Writer(const char *filename)
mOffset(0),
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
- mInterleaveDurationUs(1000000) {
+ mInterleaveDurationUs(1000000),
+ mLatitudex10000(0),
+ mLongitudex10000(0),
+ mAreGeoTagsAvailable(false),
+ mStartTimeOffsetMs(-1) {
mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
if (mFd >= 0) {
@@ -276,7 +281,11 @@ MPEG4Writer::MPEG4Writer(int fd)
mOffset(0),
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
- mInterleaveDurationUs(1000000) {
+ mInterleaveDurationUs(1000000),
+ mLatitudex10000(0),
+ mLongitudex10000(0),
+ mAreGeoTagsAvailable(false),
+ mStartTimeOffsetMs(-1) {
}
MPEG4Writer::~MPEG4Writer() {
@@ -724,6 +733,9 @@ void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
void MPEG4Writer::writeMoovBox(int64_t durationUs) {
beginBox("moov");
writeMvhdBox(durationUs);
+ if (mAreGeoTagsAvailable) {
+ writeUdtaBox();
+ }
int32_t id = 1;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it, ++id) {
@@ -732,7 +744,7 @@ void MPEG4Writer::writeMoovBox(int64_t durationUs) {
endBox(); // moov
}
-void MPEG4Writer::writeFtypBox(const MetaData *param) {
+void MPEG4Writer::writeFtypBox(MetaData *param) {
beginBox("ftyp");
int32_t fileType;
@@ -749,7 +761,27 @@ void MPEG4Writer::writeFtypBox(const MetaData *param) {
endBox();
}
+static bool isTestModeEnabled() {
+#if (PROPERTY_VALUE_MAX < 5)
+#error "PROPERTY_VALUE_MAX must be at least 5"
+#endif
+
+ // Test mode is enabled only if rw.media.record.test system
+ // property is enabled.
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("rw.media.record.test", value, NULL) &&
+ (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
+ return true;
+ }
+ return false;
+}
+
void MPEG4Writer::sendSessionSummary() {
+ // Send session summary only if test mode is enabled
+ if (!isTestModeEnabled()) {
+ return;
+ }
+
for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
it != mChunkInfos.end(); ++it) {
int trackNum = it->mTrack->getTrackId() << 28;
@@ -921,6 +953,77 @@ void MPEG4Writer::writeFourcc(const char *s) {
write(s, 1, 4);
}
+
+// Written in +/-DD.DDDD format
+void MPEG4Writer::writeLatitude(int degreex10000) {
+ bool isNegative = (degreex10000 < 0);
+ char sign = isNegative? '-': '+';
+
+ // Handle the whole part
+ char str[9];
+ int wholePart = degreex10000 / 10000;
+ if (wholePart == 0) {
+ snprintf(str, 5, "%c%.2d.", sign, wholePart);
+ } else {
+ snprintf(str, 5, "%+.2d.", wholePart);
+ }
+
+ // Handle the fractional part
+ int fractionalPart = degreex10000 - (wholePart * 10000);
+ if (fractionalPart < 0) {
+ fractionalPart = -fractionalPart;
+ }
+ snprintf(&str[4], 5, "%.4d", fractionalPart);
+
+ // Do not write the null terminator
+ write(str, 1, 8);
+}
+
+// Written in +/- DDD.DDDD format
+void MPEG4Writer::writeLongitude(int degreex10000) {
+ bool isNegative = (degreex10000 < 0);
+ char sign = isNegative? '-': '+';
+
+ // Handle the whole part
+ char str[10];
+ int wholePart = degreex10000 / 10000;
+ if (wholePart == 0) {
+ snprintf(str, 6, "%c%.3d.", sign, wholePart);
+ } else {
+ snprintf(str, 6, "%+.3d.", wholePart);
+ }
+
+ // Handle the fractional part
+ int fractionalPart = degreex10000 - (wholePart * 10000);
+ if (fractionalPart < 0) {
+ fractionalPart = -fractionalPart;
+ }
+ snprintf(&str[5], 5, "%.4d", fractionalPart);
+
+ // Do not write the null terminator
+ write(str, 1, 9);
+}
+
+/*
+ * Geodata is stored according to ISO-6709 standard.
+ * latitudex10000 is latitude in degrees times 10000, and
+ * longitudex10000 is longitude in degrees times 10000.
+ * The range for the latitude is in [-90, +90], and
+ * The range for the longitude is in [-180, +180]
+ */
+status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
+ // Is latitude or longitude out of range?
+ if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
+ longitudex10000 < -1800000 || longitudex10000 > 1800000) {
+ return BAD_VALUE;
+ }
+
+ mLatitudex10000 = latitudex10000;
+ mLongitudex10000 = longitudex10000;
+ mAreGeoTagsAvailable = true;
+ return OK;
+}
+
void MPEG4Writer::write(const void *data, size_t size) {
write(data, 1, size);
}
@@ -1345,10 +1448,15 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
* session, and it also helps eliminate the "recording" sound for
* camcorder applications.
*
- * Ideally, this platform-specific value should be defined
- * in media_profiles.xml file
+ * If client does not set the start time offset, we fall back to
+ * use the default initial delay value.
*/
- startTimeUs += kInitialDelayTimeUs;
+ int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
+ if (startTimeOffsetUs < 0) { // Start time offset was not set
+ startTimeOffsetUs = kInitialDelayTimeUs;
+ }
+ startTimeUs += startTimeOffsetUs;
+ LOGI("Start time offset: %lld us", startTimeOffsetUs);
}
meta->setInt64(kKeyTime, startTimeUs);
@@ -2140,6 +2248,12 @@ status_t MPEG4Writer::Track::threadEntry() {
}
void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
+
+ // Send track summary only if test mode is enabled.
+ if (!isTestModeEnabled()) {
+ return;
+ }
+
int trackNum = (mTrackId << 28);
mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
@@ -2154,13 +2268,24 @@ void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
mNumSamples);
- // The system delay time excluding the requested initial delay that
- // is used to eliminate the recording sound.
- int64_t initialDelayUs =
- mFirstSampleTimeRealUs - mStartTimeRealUs - kInitialDelayTimeUs;
- mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ {
+ // The system delay time excluding the requested initial delay that
+ // is used to eliminate the recording sound.
+ int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
+ if (startTimeOffsetUs < 0) { // Start time offset was not set
+ startTimeOffsetUs = kInitialDelayTimeUs;
+ }
+ int64_t initialDelayUs =
+ mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
(initialDelayUs) / 1000);
+ }
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
+ mMdatSizeBytes / 1024);
if (hasMultipleTracks) {
mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
@@ -2491,7 +2616,7 @@ void MPEG4Writer::Track::writeTkhdBox(time_t now) {
mOwner->writeInt32(0x07); // version=0, flags=7
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
- mOwner->writeInt32(mTrackId);
+ mOwner->writeInt32(mTrackId + 1); // track id starts with 1
mOwner->writeInt32(0); // reserved
int64_t trakDurationUs = getDurationUs();
int32_t mvhdTimeScale = mOwner->getTimeScale();
@@ -2722,4 +2847,29 @@ void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
mOwner->endBox(); // stco or co64
}
+void MPEG4Writer::writeUdtaBox() {
+ beginBox("udta");
+ writeGeoDataBox();
+ endBox();
+}
+
+/*
+ * Geodata is stored according to ISO-6709 standard.
+ */
+void MPEG4Writer::writeGeoDataBox() {
+ beginBox("\xA9xyz");
+ /*
+ * For historical reasons, any user data start
+ * with "\0xA9", must be followed by its assoicated
+ * language code.
+ * 0x0012: locale en
+ * 0x15c7: language 5575
+ */
+ writeInt32(0x001215c7);
+ writeLatitude(mLatitudex10000);
+ writeLongitude(mLongitudex10000);
+ writeInt8(0x2F);
+ endBox();
+}
+
} // namespace android
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index aac94a6..884f3b4 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -83,7 +83,7 @@ bool MetaData::setRect(
return setData(key, TYPE_RECT, &r, sizeof(r));
}
-bool MetaData::findCString(uint32_t key, const char **value) const {
+bool MetaData::findCString(uint32_t key, const char **value) {
uint32_t type;
const void *data;
size_t size;
@@ -96,7 +96,7 @@ bool MetaData::findCString(uint32_t key, const char **value) const {
return true;
}
-bool MetaData::findInt32(uint32_t key, int32_t *value) const {
+bool MetaData::findInt32(uint32_t key, int32_t *value) {
uint32_t type;
const void *data;
size_t size;
@@ -111,7 +111,7 @@ bool MetaData::findInt32(uint32_t key, int32_t *value) const {
return true;
}
-bool MetaData::findInt64(uint32_t key, int64_t *value) const {
+bool MetaData::findInt64(uint32_t key, int64_t *value) {
uint32_t type;
const void *data;
size_t size;
@@ -126,7 +126,7 @@ bool MetaData::findInt64(uint32_t key, int64_t *value) const {
return true;
}
-bool MetaData::findFloat(uint32_t key, float *value) const {
+bool MetaData::findFloat(uint32_t key, float *value) {
uint32_t type;
const void *data;
size_t size;
@@ -141,7 +141,7 @@ bool MetaData::findFloat(uint32_t key, float *value) const {
return true;
}
-bool MetaData::findPointer(uint32_t key, void **value) const {
+bool MetaData::findPointer(uint32_t key, void **value) {
uint32_t type;
const void *data;
size_t size;
@@ -159,7 +159,7 @@ bool MetaData::findPointer(uint32_t key, void **value) const {
bool MetaData::findRect(
uint32_t key,
int32_t *left, int32_t *top,
- int32_t *right, int32_t *bottom) const {
+ int32_t *right, int32_t *bottom) {
uint32_t type;
const void *data;
size_t size;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index cd5bdfb..0f0ffd4 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -4077,10 +4077,10 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
numChannels, params.nChannels);
}
- if (sampleRate != params.nSamplingRate) {
+ if (sampleRate != (int32_t)params.nSamplingRate) {
LOGW("Codec outputs at different sampling rate than "
"what the input stream contains (contains data at "
- "%d Hz, codec outputs %d Hz)",
+ "%d Hz, codec outputs %lu Hz)",
sampleRate, params.nSamplingRate);
}
@@ -4203,6 +4203,14 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
break;
}
}
+
+ // If the input format contains rotation information, flag the output
+ // format accordingly.
+
+ int32_t rotationDegrees;
+ if (mSource->getFormat()->findInt32(kKeyRotation, &rotationDegrees)) {
+ mOutputFormat->setInt32(kKeyRotation, rotationDegrees);
+ }
}
status_t OMXCodec::pause() {
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 7c72852..83a1eaa 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -45,7 +45,8 @@ namespace android {
static Mutex gWVMutex;
WVMExtractor::WVMExtractor(const sp<DataSource> &source)
- : mDataSource(source) {
+ : mDataSource(source),
+ mUseAdaptiveStreaming(false) {
{
Mutex::Autolock autoLock(gWVMutex);
if (gVendorLibHandle == NULL) {
@@ -100,5 +101,21 @@ sp<MetaData> WVMExtractor::getMetaData() {
return mImpl->getMetaData();
}
+int64_t WVMExtractor::getCachedDurationUs(status_t *finalStatus) {
+ // TODO: Fill this with life.
+
+ *finalStatus = OK;
+
+ return 0;
+}
+
+void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
+ mUseAdaptiveStreaming = adaptive;
+}
+
+bool WVMExtractor::getAdaptiveStreamingMode() const {
+ return mUseAdaptiveStreaming;
+}
+
} //namespace android
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 5ef54fd..359a2ec 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -176,6 +176,6 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_omx libstagefright_foundation libutils
LOCAL_MODULE := libstagefright_soft_aacdec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 296cae4..5862abc 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -79,6 +79,6 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_amrnb_common
LOCAL_MODULE := libstagefright_soft_amrdec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/dec/Android.mk b/media/libstagefright/codecs/avc/dec/Android.mk
index afecdc4..4d4533b 100644
--- a/media/libstagefright/codecs/avc/dec/Android.mk
+++ b/media/libstagefright/codecs/avc/dec/Android.mk
@@ -50,7 +50,7 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright libstagefright_omx libstagefright_foundation libutils
LOCAL_MODULE := libstagefright_soft_avcdec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
index b6953bc..6e98559 100644
--- a/media/libstagefright/codecs/g711/dec/Android.mk
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -26,6 +26,6 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright libstagefright_omx libstagefright_foundation libutils
LOCAL_MODULE := libstagefright_soft_g711dec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
index 65b642c..f1bec08 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -71,6 +71,6 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright libstagefright_omx libstagefright_foundation libutils
LOCAL_MODULE := libstagefright_soft_mpeg4dec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 2d35183..229988e 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -77,6 +77,6 @@ LOCAL_STATIC_LIBRARIES := \
libstagefright_mp3dec
LOCAL_MODULE := libstagefright_soft_mp3dec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 1b3088f..832b885 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -37,7 +37,7 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright libstagefright_omx libstagefright_foundation libutils
LOCAL_MODULE := libstagefright_soft_vpxdec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
index 06f0079..9251229 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.mk
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -32,7 +32,7 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_foundation libutils
LOCAL_MODULE := libstagefright_soft_vorbisdec
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index 62ba40f..702a7b4 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -9,6 +9,10 @@ LOCAL_C_INCLUDES := \
$(TOP)/frameworks/base/include/media/stagefright/openmax \
$(TOP)/hardware/msm7k
+ifneq ($(filter crespo crespo4g,$(TARGET_DEVICE)),)
+LOCAL_CFLAGS += -DTHIS_IS_CRESPO=1
+endif
+
LOCAL_MODULE:= libstagefright_color_conversion
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index ee86148..1828ac8 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -56,9 +56,23 @@ SoftwareRenderer::SoftwareRenderer(
}
int halFormat;
+ size_t bufWidth, bufHeight;
+
switch (mColorFormat) {
+#ifndef THIS_IS_CRESPO
+ case OMX_COLOR_FormatYUV420Planar:
+ {
+ halFormat = HAL_PIXEL_FORMAT_YV12;
+ bufWidth = (mWidth + 1) & ~1;
+ bufHeight = (mHeight + 1) & ~1;
+ break;
+ }
+#endif
+
default:
halFormat = HAL_PIXEL_FORMAT_RGB_565;
+ bufWidth = mWidth;
+ bufHeight = mHeight;
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_Format16bitRGB565);
@@ -75,13 +89,17 @@ SoftwareRenderer::SoftwareRenderer(
native_window_set_usage(
mNativeWindow.get(),
GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
- | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
+ | GRALLOC_USAGE_HW_TEXTURE
+#ifndef THIS_IS_CRESPO
+ | GRALLOC_USAGE_EXTERNAL_DISP
+#endif
+ ));
// Width must be multiple of 32???
CHECK_EQ(0, native_window_set_buffers_geometry(
mNativeWindow.get(),
- mCropRight - mCropLeft + 1,
- mCropBottom - mCropTop + 1,
+ bufWidth,
+ bufHeight,
halFormat));
uint32_t transform;
@@ -97,6 +115,14 @@ SoftwareRenderer::SoftwareRenderer(
CHECK_EQ(0, native_window_set_buffers_transform(
mNativeWindow.get(), transform));
}
+
+ android_native_rect_t crop;
+ crop.left = mCropLeft;
+ crop.top = mCropTop;
+ crop.right = mCropRight + 1;
+ crop.bottom = mCropBottom + 1;
+
+ CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
}
SoftwareRenderer::~SoftwareRenderer() {
@@ -104,6 +130,11 @@ SoftwareRenderer::~SoftwareRenderer() {
mConverter = NULL;
}
+static int ALIGN(int x, int y) {
+ // y must be a power of 2.
+ return (x + y - 1) & ~(y - 1);
+}
+
void SoftwareRenderer::render(
const void *data, size_t size, void *platformPrivate) {
ANativeWindowBuffer *buf;
@@ -127,14 +158,40 @@ void SoftwareRenderer::render(
mConverter->convert(
data,
mWidth, mHeight,
- mCropLeft, mCropTop, mCropRight, mCropBottom,
+ 0, 0, mWidth - 1, mHeight - 1,
dst,
buf->stride, buf->height,
- 0, 0,
- mCropRight - mCropLeft,
- mCropBottom - mCropTop);
+ 0, 0, mWidth - 1, mHeight - 1);
} else {
- TRESPASS();
+ CHECK_EQ(mColorFormat, OMX_COLOR_FormatYUV420Planar);
+
+ const uint8_t *src_y = (const uint8_t *)data;
+ const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
+ const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
+
+ uint8_t *dst_y = (uint8_t *)dst;
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ for (int y = 0; y < mHeight; ++y) {
+ memcpy(dst_y, src_y, mWidth);
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mHeight + 1) / 2; ++y) {
+ memcpy(dst_u, src_u, (mWidth + 1) / 2);
+ memcpy(dst_v, src_v, (mWidth + 1) / 2);
+
+ src_u += mWidth / 2;
+ src_v += mWidth / 2;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
}
CHECK_EQ(0, mapper.unlock(buf->handle));
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 835d2bb..3c9a121 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -45,6 +45,7 @@ class DrmManagerClinet;
class DecryptHandle;
class TimedTextPlayer;
+struct WVMExtractor;
struct AwesomeRenderer : public RefBase {
AwesomeRenderer() {}
@@ -231,6 +232,8 @@ private:
int64_t mLastVideoTimeUs;
TimedTextPlayer *mTextPlayer;
+ sp<WVMExtractor> mWVMExtractor;
+
status_t setDataSource_l(
const char *uri,
const KeyedVector<String8, String8> *headers = NULL);
@@ -286,6 +289,8 @@ private:
void shutdownVideoDecoder_l();
void setNativeWindow_l(const sp<ANativeWindow> &native);
+ bool isStreamingHTTP() const;
+
AwesomePlayer(const AwesomePlayer &);
AwesomePlayer &operator=(const AwesomePlayer &);
};
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index 0da45a8..62e5aa5 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -19,6 +19,7 @@
#define WVM_EXTRACTOR_H_
#include <media/stagefright/MediaExtractor.h>
+#include <utils/Errors.h>
namespace android {
@@ -33,12 +34,31 @@ public:
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ // Return the amount of data cached from the current
+ // playback positiion (in us).
+ // While more data is still being fetched *finalStatus == OK,
+ // Once fetching is completed (no more data available), *finalStatus != OK
+ // If fetching completed normally (i.e. reached EOS instead of IO error)
+ // *finalStatus == ERROR_END_OF_STREAM
+ int64_t getCachedDurationUs(status_t *finalStatus);
+
+ // Set to use adaptive streaming mode by the WV component.
+ // If adaptive == true, adaptive streaming mode will be used.
+ // Default mode is non-adaptive streaming mode.
+ // Should set to use adaptive streaming mode only if widevine:// protocol
+ // is used.
+ void setAdaptiveStreamingMode(bool adaptive);
+
+ // Retrieve the adaptive streaming mode used by the WV component.
+ bool getAdaptiveStreamingMode() const;
+
protected:
virtual ~WVMExtractor();
private:
sp<DataSource> mDataSource;
sp<MediaExtractor> mImpl;
+ bool mUseAdaptiveStreaming;
WVMExtractor(const WVMExtractor &);
WVMExtractor &operator=(const WVMExtractor &);