summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp57
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.h6
-rw-r--r--media/libstagefright/AwesomePlayer.cpp4
-rw-r--r--media/libstagefright/DRMExtractor.cpp8
-rw-r--r--media/libstagefright/DataSource.cpp2
-rw-r--r--media/libstagefright/WVMExtractor.cpp56
-rw-r--r--media/libstagefright/foundation/ABitReader.cpp8
-rw-r--r--media/libstagefright/include/WVMExtractor.h8
-rw-r--r--media/libstagefright/rtsp/MyHandler.h14
9 files changed, 131 insertions, 32 deletions
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index e72adc4..6d28298 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -38,7 +38,8 @@ NuPlayer::RTSPSource::RTSPSource(
mFlags(0),
mState(DISCONNECTED),
mFinalResult(OK),
- mDisconnectReplyID(0) {
+ mDisconnectReplyID(0),
+ mSeekGeneration(0) {
if (headers) {
mExtraHeaders = *headers;
@@ -146,14 +147,21 @@ status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
}
status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
+ sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
+ msg->setInt32("generation", ++mSeekGeneration);
+ msg->setInt64("timeUs", seekTimeUs);
+ msg->post(200000ll);
+
+ return OK;
+}
+
+void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
if (mState != CONNECTED) {
- return UNKNOWN_ERROR;
+ return;
}
mState = SEEKING;
mHandler->seek(seekTimeUs);
-
- return OK;
}
bool NuPlayer::RTSPSource::isSeekable() {
@@ -168,6 +176,20 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
mDisconnectReplyID = replyID;
finishDisconnectIfPossible();
return;
+ } else if (msg->what() == kWhatPerformSeek) {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mSeekGeneration) {
+ // obsolete.
+ return;
+ }
+
+ int64_t seekTimeUs;
+ CHECK(msg->findInt64("timeUs", &seekTimeUs));
+
+ performSeek(seekTimeUs);
+ return;
}
CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -208,21 +230,32 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
break;
}
- const TrackInfo &info = mTracks.editItemAt(trackIndex);
- sp<AnotherPacketSource> source = info.mSource;
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+ sp<AnotherPacketSource> source = info->mSource;
if (source != NULL) {
-#if 1
uint32_t rtpTime;
CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+ if (!info->mNPTMappingValid) {
+ // This is a live stream, we didn't receive any normal
+ // playtime mapping. Assume the first packets correspond
+ // to time 0.
+
+ ALOGV("This is a live stream, assuming time = 0");
+
+ info->mRTPTime = rtpTime;
+ info->mNormalPlaytimeUs = 0ll;
+ info->mNPTMappingValid = true;
+ }
+
int64_t nptUs =
- ((double)rtpTime - (double)info.mRTPTime)
- / info.mTimeScale
+ ((double)rtpTime - (double)info->mRTPTime)
+ / info->mTimeScale
* 1000000ll
- + info.mNormalPlaytimeUs;
+ + info->mNormalPlaytimeUs;
accessUnit->meta()->setInt64("timeUs", nptUs);
-#endif
source->queueAccessUnit(accessUnit);
}
@@ -278,6 +311,7 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
TrackInfo *info = &mTracks.editItemAt(trackIndex);
info->mRTPTime = rtpTime;
info->mNormalPlaytimeUs = nptUs;
+ info->mNPTMappingValid = true;
break;
}
@@ -305,6 +339,7 @@ void NuPlayer::RTSPSource::onConnected() {
info.mTimeScale = timeScale;
info.mRTPTime = 0;
info.mNormalPlaytimeUs = 0ll;
+ info.mNPTMappingValid = false;
if ((isAudio && mAudioTrack == NULL)
|| (isVideo && mVideoTrack == NULL)) {
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 66eab72..59d06ad 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -56,6 +56,7 @@ private:
enum {
kWhatNotify = 'noti',
kWhatDisconnect = 'disc',
+ kWhatPerformSeek = 'seek',
};
enum State {
@@ -76,6 +77,7 @@ private:
int32_t mTimeScale;
uint32_t mRTPTime;
int64_t mNormalPlaytimeUs;
+ bool mNPTMappingValid;
};
AString mURL;
@@ -95,12 +97,16 @@ private:
sp<AnotherPacketSource> mAudioTrack;
sp<AnotherPacketSource> mVideoTrack;
+ int32_t mSeekGeneration;
+
sp<AnotherPacketSource> getSource(bool audio);
void onConnected();
void onDisconnected(const sp<AMessage> &msg);
void finishDisconnectIfPossible();
+ void performSeek(int64_t seekTimeUs);
+
DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
};
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 964cb1f..8405264 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2091,7 +2091,7 @@ status_t AwesomePlayer::finishSetDataSource_l() {
String8 mimeType;
float confidence;
sp<AMessage> dummy;
- bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
+ bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
if (!success
|| strcasecmp(
@@ -2099,6 +2099,8 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return ERROR_UNSUPPORTED;
}
+ dataSource->DrmInitialization();
+
mWVMExtractor = new WVMExtractor(dataSource);
mWVMExtractor->setAdaptiveStreamingMode(true);
extractor = mWVMExtractor;
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 1f3d581..afc4a80 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -282,13 +282,13 @@ bool SniffDRM(
if (decryptHandle != NULL) {
if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
*mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
+ *confidence = 10.0f;
} else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
*mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
- } else if (decryptHandle->decryptApiType == DecryptApiType::WV_BASED) {
- *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
- LOGW("SniffWVM: found match\n");
+ *confidence = 10.0f;
+ } else {
+ return false;
}
- *confidence = 10.0f;
return true;
}
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index e471f73..d0a7880 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -32,6 +32,7 @@
#include "include/DRMExtractor.h"
#include "include/FLACExtractor.h"
#include "include/AACExtractor.h"
+#include "include/WVMExtractor.h"
#include "matroska/MatroskaExtractor.h"
@@ -120,6 +121,7 @@ void DataSource::RegisterDefaultSniffers() {
RegisterSniffer(SniffAAC);
RegisterSniffer(SniffAVI);
RegisterSniffer(SniffMPEG2PS);
+ RegisterSniffer(SniffWVM);
char value[PROPERTY_VALUE_MAX];
if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 26eda0c..79dedca 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -45,17 +45,12 @@ namespace android {
static Mutex gWVMutex;
WVMExtractor::WVMExtractor(const sp<DataSource> &source)
- : mDataSource(source) {
- {
- Mutex::Autolock autoLock(gWVMutex);
- if (gVendorLibHandle == NULL) {
- gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
- }
+ : mDataSource(source)
+{
+ Mutex::Autolock autoLock(gWVMutex);
- if (gVendorLibHandle == NULL) {
- LOGE("Failed to open libwvm.so");
- return;
- }
+ if (!getVendorLibHandle()) {
+ return;
}
typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
@@ -71,6 +66,19 @@ WVMExtractor::WVMExtractor(const sp<DataSource> &source)
}
}
+bool WVMExtractor::getVendorLibHandle()
+{
+ if (gVendorLibHandle == NULL) {
+ gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
+ }
+
+ if (gVendorLibHandle == NULL) {
+ LOGE("Failed to open libwvm.so");
+ }
+
+ return gVendorLibHandle != NULL;
+}
+
WVMExtractor::~WVMExtractor() {
}
@@ -113,5 +121,33 @@ void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
}
}
+bool SniffWVM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+
+ Mutex::Autolock autoLock(gWVMutex);
+
+ if (!WVMExtractor::getVendorLibHandle()) {
+ return false;
+ }
+
+ typedef WVMLoadableExtractor *(*SnifferFunc)(sp<DataSource>);
+ SnifferFunc snifferFunc =
+ (SnifferFunc) dlsym(gVendorLibHandle,
+ "_ZN7android15IsWidevineMediaENS_2spINS_10DataSourceEEE");
+
+ if (snifferFunc) {
+ if ((*snifferFunc)(source)) {
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
+ *confidence = 10.0f;
+ return true;
+ }
+ } else {
+ LOGE("IsWidevineMedia not found in libwvm.so");
+ }
+
+ return false;
+}
+
} //namespace android
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
index f07dd4f..5499c32 100644
--- a/media/libstagefright/foundation/ABitReader.cpp
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -79,7 +79,13 @@ void ABitReader::skipBits(size_t n) {
}
void ABitReader::putBits(uint32_t x, size_t n) {
- CHECK_LE(mNumBitsLeft + n, 32u);
+ CHECK_LE(n, 32u);
+
+ while (mNumBitsLeft + n > 32) {
+ mNumBitsLeft -= 8;
+ --mData;
+ ++mSize;
+ }
mReservoir = (mReservoir >> n) | (x << (32 - n));
mNumBitsLeft += n;
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index deecd25..9f763f9 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -23,6 +23,8 @@
namespace android {
+struct AMessage;
+class String8;
class DataSource;
class WVMLoadableExtractor : public MediaExtractor {
@@ -58,6 +60,8 @@ public:
// is used.
void setAdaptiveStreamingMode(bool adaptive);
+ static bool getVendorLibHandle();
+
protected:
virtual ~WVMExtractor();
@@ -69,6 +73,10 @@ private:
WVMExtractor &operator=(const WVMExtractor &);
};
+bool SniffWVM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
} // namespace android
#endif // DRM_EXTRACTOR_H_
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index dd049c2..21ef298 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1100,6 +1100,8 @@ struct MyHandler : public AHandler {
float npt1, npt2;
if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
// This is a live stream and therefore not seekable.
+
+ LOGI("This is a live stream");
return;
}
@@ -1386,12 +1388,14 @@ private:
msg->setInt32("what", kWhatConnected);
msg->post();
- for (size_t i = 0; i < mTracks.size(); ++i) {
- TrackInfo *info = &mTracks.editItemAt(i);
+ if (mSeekable) {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
- postNormalPlayTimeMapping(
- i,
- info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ postNormalPlayTimeMapping(
+ i,
+ info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ }
}
mFirstAccessUnit = false;