am 8c5545ef: Merge "Fix for b/4198446 HC - Support for Widevine Adaptive VOD Fix for b/4075745 libWVStreamControlAPI crashes when dlopened() and dlclosed() Added error logging to diagnose problems such as b/4430078 Playback of newly rented movie fails with "licens
* commit '8c5545ef76f39094b016986c7deec02df682356d': Fix for b/4198446 HC - Support for Widevine Adaptive VOD Fix for b/4075745 libWVStreamControlAPI crashes when dlopened() and dlclosed() Added error logging to diagnose problems such as b/4430078 Playback of newly rented movie fails with "license expired"
This commit is contained in:
@@ -76,7 +76,7 @@ static int _cb2(char *in, char *out, int length, char *iv)
|
||||
namespace android {
|
||||
|
||||
// DLL entry - construct an extractor and return it
|
||||
MediaExtractor *GetInstance(sp<DataSource> dataSource) {
|
||||
WVMLoadableExtractor *GetInstance(sp<DataSource> dataSource) {
|
||||
return new WVMExtractorImpl(dataSource);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
: mFileMetaData(new MetaData()),
|
||||
mDataSource(dataSource),
|
||||
mHaveMetaData(false),
|
||||
mUseAdaptiveStreaming(false),
|
||||
mIsLiveStream(false),
|
||||
mSession(NULL),
|
||||
mSetupStatus(OK)
|
||||
{
|
||||
@@ -102,12 +104,16 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
} else
|
||||
mSetupStatus = ERROR_NO_LICENSE;
|
||||
|
||||
WVCredentials credentials;
|
||||
|
||||
// Set an info listener to handle messages from the drm plugin
|
||||
mInfoListener = new WVMInfoListener();
|
||||
|
||||
sDrmManagerClient->setOnInfoListener(mInfoListener);
|
||||
}
|
||||
|
||||
void WVMExtractorImpl::Initialize()
|
||||
{
|
||||
//LOGD("WVMExtractorImpl::Initialize(%d)\n", getAdaptiveStreamingMode());
|
||||
WVCredentials credentials;
|
||||
|
||||
WVStatus result = WV_Initialize(NULL);
|
||||
if (result != WV_Status_OK) {
|
||||
@@ -117,10 +123,20 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
// Enable for debugging HTTP messages
|
||||
// WV_SetLogging(WV_Logging_HTTP);
|
||||
|
||||
mFileSource = new WVMFileSource(dataSource);
|
||||
result = WV_Setup(mSession, mFileSource.get(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
if (mDataSource->getUri().size() > 0 && getAdaptiveStreamingMode()) {
|
||||
// Use the URI - streaming case, only for widevine:// protocol
|
||||
result = WV_Setup(mSession, mDataSource->getUri().string(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
|
||||
mIsLiveStream = (mDataSource->getUri().getPathExtension().find(".m3u8") == 0);
|
||||
} else {
|
||||
// No URI supplied or not adaptive, pull data from the stagefright data source.
|
||||
mFileSource = new WVMFileSource(mDataSource);
|
||||
result = WV_Setup(mSession, mFileSource.get(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
}
|
||||
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Setup returned status %d in WVMMediaSource::start\n", result);
|
||||
@@ -152,6 +168,8 @@ status_t WVMExtractorImpl::readMetaData()
|
||||
if (mHaveMetaData)
|
||||
return OK;
|
||||
|
||||
Initialize();
|
||||
|
||||
if (mSetupStatus != OK)
|
||||
return mSetupStatus;
|
||||
|
||||
@@ -162,11 +180,11 @@ status_t WVMExtractorImpl::readMetaData()
|
||||
unsigned short level;
|
||||
unsigned short width, height;
|
||||
float aspect, frameRate;
|
||||
unsigned long bitRate;
|
||||
unsigned long videoBitRate;
|
||||
|
||||
WVStatus result = WV_Info_GetVideoConfiguration(mSession, &videoType, &videoStreamID,
|
||||
&videoProfile, &level, &width, &height,
|
||||
&aspect, &frameRate, &bitRate);
|
||||
&aspect, &frameRate, &videoBitRate);
|
||||
if (result != WV_Status_OK)
|
||||
return ERROR_MALFORMED;
|
||||
|
||||
@@ -176,15 +194,21 @@ status_t WVMExtractorImpl::readMetaData()
|
||||
unsigned short audioProfile;
|
||||
unsigned short numChannels;
|
||||
unsigned long sampleRate;
|
||||
unsigned long audioBitRate;
|
||||
|
||||
result = WV_Info_GetAudioConfiguration(mSession, &audioType, &audioStreamID, &audioProfile,
|
||||
&numChannels, &sampleRate, &bitRate);
|
||||
&numChannels, &sampleRate, &audioBitRate);
|
||||
if (result != WV_Status_OK)
|
||||
return ERROR_MALFORMED;
|
||||
|
||||
std::string durationString = WV_Info_GetDuration(mSession, "sec");
|
||||
if (durationString == "") {
|
||||
return ERROR_MALFORMED;
|
||||
// We won't have a duration for live streams, and Stagefright doesn't seem to
|
||||
// have a way to represent that. Give a default duration of 1 hour for now.
|
||||
if (mIsLiveStream)
|
||||
durationString = "3600";
|
||||
else
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
|
||||
int64_t duration = (int64_t)(strtod(durationString.c_str(), NULL) * 1000000);
|
||||
@@ -195,6 +219,9 @@ status_t WVMExtractorImpl::readMetaData()
|
||||
audioMetaData->setInt64(kKeyDuration, duration);
|
||||
videoMetaData->setInt64(kKeyDuration, duration);
|
||||
|
||||
audioMetaData->setInt32(kKeyBitRate, audioBitRate);
|
||||
videoMetaData->setInt32(kKeyBitRate, videoBitRate);
|
||||
|
||||
switch(videoType) {
|
||||
case WV_VideoType_H264:
|
||||
videoMetaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
|
||||
@@ -406,5 +433,61 @@ sp<MetaData> WVMExtractorImpl::getMetaData() {
|
||||
return mFileMetaData;
|
||||
}
|
||||
|
||||
int64_t WVMExtractorImpl::getCachedDurationUs(status_t *finalStatus) {
|
||||
const size_t kMaxEncodedRates = 10;
|
||||
unsigned long encodedRates[kMaxEncodedRates];
|
||||
size_t ratesReturned, currentTrack;
|
||||
uint64_t durationUs = 0;
|
||||
|
||||
WVStatus status = WV_Info_GetAdaptiveBitrates(mSession, encodedRates, kMaxEncodedRates,
|
||||
&ratesReturned, ¤tTrack);
|
||||
if (status == WV_Status_OK) {
|
||||
if (currentTrack == kMaxEncodedRates || ratesReturned == 0) {
|
||||
*finalStatus = ERROR_IO;
|
||||
} else {
|
||||
unsigned long long bytesBuffered;
|
||||
status = WV_Info_BytesBuffered(mSession, &bytesBuffered);
|
||||
if (status == WV_Status_OK) {
|
||||
*finalStatus = OK;
|
||||
durationUs = 8000000LL * bytesBuffered / encodedRates[currentTrack];
|
||||
} else if (status == WV_Status_End_Of_Media) {
|
||||
*finalStatus = ERROR_END_OF_STREAM;
|
||||
}
|
||||
|
||||
// Log the current adaptive rate every 5 seconds
|
||||
// FIXME: need to see if there is a way to send this info to the app
|
||||
time_t now = time(0);
|
||||
static time_t lastLogTime = now;
|
||||
if (now > lastLogTime + 5) {
|
||||
lastLogTime = now;
|
||||
LOGI("using adaptive track #%d, rate=%ld\n",
|
||||
currentTrack, encodedRates[currentTrack]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*finalStatus = ERROR_IO;
|
||||
}
|
||||
|
||||
// Scale the duration to account for Stagefright's conservative buffering.
|
||||
// This provides much more responsive operation and due to the ability to
|
||||
// adapt, we don't need to prebuffer so much data. Based on testing, 2x
|
||||
// is a reasonable compromise between faster startup time and additional
|
||||
// pauses after playback starts.
|
||||
|
||||
return durationUs * 2;
|
||||
}
|
||||
|
||||
void WVMExtractorImpl::setAdaptiveStreamingMode(bool adaptive)
|
||||
{
|
||||
//LOGD("WVMExtractorImpl::setAdaptiveStreamingMode(%d)", adaptive);
|
||||
mUseAdaptiveStreaming = adaptive;
|
||||
}
|
||||
|
||||
bool WVMExtractorImpl::getAdaptiveStreamingMode() const
|
||||
{
|
||||
//LOGD("WVMExtractorImpl::getAdaptiveStreamingMode - %d", mUseAdaptiveStreaming);
|
||||
return mUseAdaptiveStreaming;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
Reference in New Issue
Block a user