Fixes for b/4149416:expired license refresh, b/4126624:heartbeats, b/4171055: inconsistent license modes
Also includes b/3500025: A/V resync issues Change-Id: Ib885d7219d211b188f38e9427bdaecd10fbd7329
This commit is contained in:
@@ -8,7 +8,8 @@ LOCAL_SRC_FILES:= \
|
||||
WVMLogging.cpp \
|
||||
WVMExtractorImpl.cpp \
|
||||
WVMFileSource.cpp \
|
||||
WVMMediaSource.cpp
|
||||
WVMMediaSource.cpp \
|
||||
WVMInfoListener.cpp
|
||||
|
||||
LOCAL_C_INCLUDES:= \
|
||||
bionic \
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
#include "WVMExtractorImpl.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include "WVMFileSource.h"
|
||||
#include "WVMInfoListener.h"
|
||||
#include "WVMLogging.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "drm/DrmManagerClient.h"
|
||||
#include "drm/DrmConstraints.h"
|
||||
#include "drm/DrmInfoEvent.h"
|
||||
#include "AndroidHooks.h"
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
@@ -86,6 +89,8 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
{
|
||||
dataSource->getDrmInfo(&sDecryptHandle, &sDrmManagerClient);
|
||||
|
||||
//LOGD("WVMExtractorImpl::WVMExtractorImpl: uniqueId = %d", sDrmManagerClient->mUniqueId);
|
||||
|
||||
_ah006(android_printbuf);
|
||||
_ah002(_cb1);
|
||||
_ah004(_cb2);
|
||||
@@ -99,6 +104,16 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
|
||||
WVCredentials credentials;
|
||||
|
||||
// Set an info listener to handle messages from the drm plugin
|
||||
mInfoListener = new WVMInfoListener();
|
||||
|
||||
// Change #if 0 to #if 1 to enable heartbeats. Since the heartbeat server
|
||||
// is not yet returning valid responses, this will cause the player to
|
||||
// fail with an error, until the heartbeat server is working correctly.
|
||||
#if 0
|
||||
sDrmManagerClient->setOnInfoListener(mInfoListener);
|
||||
#endif
|
||||
|
||||
WVStatus result = WV_Initialize(NULL);
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Initialize returned status %d\n", result);
|
||||
@@ -107,22 +122,17 @@ WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
|
||||
// Enable for debugging HTTP messages
|
||||
// WV_SetLogging(WV_Logging_HTTP);
|
||||
|
||||
if (dataSource->getUri().size() == 0) {
|
||||
// No URI supplied, pull data from the data source
|
||||
mFileSource = new WVMFileSource(dataSource);
|
||||
result = WV_Setup(mSession, mFileSource.get(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
} else {
|
||||
// Use the URI
|
||||
result = WV_Setup(mSession, dataSource->getUri().string(),
|
||||
"RAW/RAW/RAW;destination=getdata", credentials,
|
||||
WV_OutputFormat_ES, kStreamCacheSize);
|
||||
}
|
||||
mFileSource = new WVMFileSource(dataSource);
|
||||
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);
|
||||
mSetupStatus = ERROR_IO;
|
||||
}
|
||||
|
||||
mInfoListener->setSession(mSession);
|
||||
}
|
||||
|
||||
WV_SetWarningToErrorMS(5000);
|
||||
@@ -233,6 +243,8 @@ status_t WVMExtractorImpl::readMetaData()
|
||||
|
||||
mHaveMetaData = true;
|
||||
|
||||
mInfoListener->configureHeartbeat();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -245,7 +257,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
int limit = 50;
|
||||
do {
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
bool auStart, sync;
|
||||
unsigned long long dts, pts;
|
||||
unsigned char buf[1];
|
||||
size_t bufSize = 0;
|
||||
@@ -255,7 +267,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
// pull some video data. But we can't use it yet, so just request 0 bytes.
|
||||
//
|
||||
(void)WV_GetEsData(mSession, WV_EsSelector_Video, buf, bufSize,
|
||||
bytesRead, auStart, dts, pts);
|
||||
bytesRead, auStart, dts, pts, sync);
|
||||
|
||||
result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_AVCC, config, size);
|
||||
if (result != WV_Status_OK)
|
||||
@@ -278,28 +290,7 @@ status_t WVMExtractorImpl::readAVCCMetaData(sp<MetaData> videoMetaData)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
unsigned char mp4_force[] =
|
||||
{ 0x01, 0x42, 0x00, 0x1e, 0xff, 0xe1, 0x00, 0x1b, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x01, 0x00, 0x04, 0x68, 0xcb, 0x8d, 0x48 } ;
|
||||
unsigned char wvm_force[] =
|
||||
{ 0x01, 0x42, 0x80, 0x1e, 0xff, 0xe1, 0x00, 0x1c, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x00, 0x01, 0x00, 0x05, 0x68, 0xcb, 0x8d, 0x48, 0x00 } ;
|
||||
unsigned char wvm_force_no_zero[] =
|
||||
{ 0x01, 0x42, 0x80, 0x1e, 0xff, 0xe1, 0x00, 0x1b, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x01, 0x00, 0x04, 0x68, 0xcb, 0x8d, 0x48 } ;
|
||||
unsigned char wvm_force_modprof[] =
|
||||
{ 0x01, 0x42, 0x00, 0x1e, 0xff, 0xe1, 0x00, 0x1c, 0x67, 0x42, 0x80, 0x1e, 0x96, 0x52, 0x01, 0x40,
|
||||
0x5f, 0xf3, 0x60, 0x2a, 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x09, 0xda,
|
||||
0x14, 0x2a, 0x48, 0x00, 0x01, 0x00, 0x05, 0x68, 0xcb, 0x8d, 0x48, 0x00 } ;
|
||||
|
||||
videoMetaData->setData(kKeyAVCC, kTypeAVCC, wvm_force_no_zero, sizeof(wvm_force_no_zero));
|
||||
#else
|
||||
videoMetaData->setData(kKeyAVCC, kTypeAVCC, config, size);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -312,7 +303,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp<MetaData> audioMetaData)
|
||||
int limit = 50;
|
||||
do {
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
bool auStart, sync;
|
||||
unsigned long long dts, pts;
|
||||
unsigned char buf[1];
|
||||
size_t bufSize = 0;
|
||||
@@ -322,7 +313,7 @@ status_t WVMExtractorImpl::readESDSMetaData(sp<MetaData> audioMetaData)
|
||||
// pull some audio data. But we can't use it yet, so just request 0 bytes.
|
||||
//
|
||||
(void)WV_GetEsData(mSession, WV_EsSelector_Audio, buf, bufSize,
|
||||
bytesRead, auStart, dts, pts);
|
||||
bytesRead, auStart, dts, pts, sync);
|
||||
|
||||
result = WV_Info_GetCodecConfig(mSession, WV_CodecConfigType_ESDS, config, size);
|
||||
if (result != WV_Status_OK)
|
||||
|
||||
60
proprietary/wvm/WVMInfoListener.cpp
Normal file
60
proprietary/wvm/WVMInfoListener.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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_TAG "WVMInfoListener"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "WVMExtractorImpl.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include "WVMFileSource.h"
|
||||
#include "WVMInfoListener.h"
|
||||
#include "WVMLogging.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
#include "media/stagefright/MediaDefs.h"
|
||||
#include "drm/DrmInfoEvent.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
void WVMInfoListener::setSession(WVSession *session)
|
||||
{
|
||||
mSession = session;
|
||||
}
|
||||
|
||||
void WVMInfoListener::onInfo(const DrmInfoEvent &event)
|
||||
{
|
||||
//LOGD("WVMMediaSource::onInfo: type=%d, msg=%s!!!",
|
||||
// event.getType(), event.getMessage().string());
|
||||
|
||||
if (event.getType() == MessageType_HeartbeatServer)
|
||||
mServerUrl = event.getMessage();
|
||||
else if (event.getType() == MessageType_HeartbeatPeriod)
|
||||
mPeriod = atoi(event.getMessage());
|
||||
}
|
||||
|
||||
void WVMInfoListener::configureHeartbeat()
|
||||
{
|
||||
// send the first time we have all the info
|
||||
if (mSession && mServerUrl.size() && mPeriod != -1) {
|
||||
//LOGD("WVMMediaSource::calling WV_ConfigureHeartbeat()");
|
||||
WV_ConfigureHeartbeat(mSession, mServerUrl, mPeriod);
|
||||
mSession = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -32,8 +32,6 @@ static void _cb(int code)
|
||||
WVMMediaSource::sLastError = (status_t)code;
|
||||
}
|
||||
|
||||
extern DrmManagerClient *gDrmManagerClient;
|
||||
|
||||
status_t WVMMediaSource::sLastError = NO_ERROR;
|
||||
|
||||
WVMMediaSource::WVMMediaSource(WVSession *session, WVEsSelector esSelector,
|
||||
@@ -156,18 +154,28 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
CHECK(mStarted);
|
||||
|
||||
*buffer = NULL;
|
||||
bool seekNextSync = false;
|
||||
|
||||
int64_t seekTimeUs;
|
||||
ReadOptions::SeekMode mode;
|
||||
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
|
||||
// Let video stream control seek
|
||||
if (mESSelector == WV_EsSelector_Video) {
|
||||
float scaleUsed;
|
||||
std::string when = usecToNPT(seekTimeUs) + std::string("-");
|
||||
WVStatus result = WV_Play(mSession, 1.0, &scaleUsed, when );
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Play returned status %d in WVMMediaSource::read\n", result);
|
||||
return ERROR_IO;
|
||||
//LOGD("%s seek mode=%d, seek time=%lld lateby=%lld",
|
||||
// (mESSelector == WV_EsSelector_Video) ? "video" : "audio",
|
||||
// mode, seekTimeUs, options->getLateBy());
|
||||
if (mode == ReadOptions::SEEK_NEXT_SYNC) {
|
||||
// Handle seek next sync by dropping frames on this track that are
|
||||
// prior to the specified time.
|
||||
seekNextSync = true;
|
||||
} else {
|
||||
// Let video stream control seek
|
||||
if (mESSelector == WV_EsSelector_Video) {
|
||||
float scaleUsed;
|
||||
std::string when = usecToNPT(seekTimeUs) + std::string("-");
|
||||
WVStatus result = WV_Play(mSession, 1.0, &scaleUsed, when );
|
||||
if (result != WV_Status_OK) {
|
||||
LOGE("WV_Play returned status %d in WVMMediaSource::read\n", result);
|
||||
return ERROR_IO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,17 +192,20 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
size_t bytesRead;
|
||||
bool auStart;
|
||||
size_t offset = 0;
|
||||
int64_t keyTime;
|
||||
|
||||
bool syncFrame;
|
||||
|
||||
// Pull full access units. Since we aren't sure how big they might be,
|
||||
// start with initial buffer size, then allocate a larger buffer if we
|
||||
// get more a number of bytes equal to the full buffer size and go back
|
||||
// get a number of bytes equal to the full buffer size and go back
|
||||
// for the rest. Only loop in this case, usually it's one pass through.
|
||||
|
||||
while (true) {
|
||||
size_t size = mediaBuf->size() - offset;
|
||||
|
||||
WVStatus result = WV_GetEsData(mSession, mESSelector, (uint8_t *)mediaBuf->data() + offset,
|
||||
size, bytesRead, auStart, mDts, mPts);
|
||||
size, bytesRead, auStart, mDts, mPts, syncFrame);
|
||||
if (result == WV_Status_End_Of_Media) {
|
||||
mediaBuf->release();
|
||||
return ERROR_END_OF_STREAM;
|
||||
@@ -222,8 +233,16 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
}
|
||||
|
||||
if (bytesRead == 0) {
|
||||
// Didn't get anything, sleep a bit so we don't hog the CPU then
|
||||
// try again.
|
||||
// Didn't get anything, sleep a bit so we don't hog the CPU then try again
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
#define PCR_HZ 90000
|
||||
keyTime = (int64_t)mPts * 1000000 / PCR_HZ;
|
||||
|
||||
if (seekNextSync && ((keyTime < seekTimeUs) || !syncFrame)) {
|
||||
// drop frames up to next sync if requested
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
@@ -249,9 +268,6 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
mediaBuf = newBuffer;
|
||||
}
|
||||
|
||||
#define PCR_HZ 90000
|
||||
int64_t keyTime = (int64_t)mDts * 1000000 / PCR_HZ;
|
||||
|
||||
mediaBuf->meta_data()->clear();
|
||||
mediaBuf->meta_data()->setInt64(kKeyTime, keyTime);
|
||||
|
||||
@@ -277,9 +293,9 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
LOGD("[%p] %s set range_length=%d, get range_length=%d kKeyTime=%lld\n", mediaBuf,
|
||||
LOGD("[%p] %s set range_length=%d, get range_length=%d kKeyTime=%lld sync=%d\n", mediaBuf,
|
||||
(mESSelector == WV_EsSelector_Video ? "video" : "audio"),
|
||||
bytesRead + offset, mediaBuf->range_length(), keyTime);
|
||||
bytesRead + offset, mediaBuf->range_length(), keyTime, syncFrame);
|
||||
#endif
|
||||
|
||||
*buffer = mediaBuf;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include "WVMInfoListener.h"
|
||||
#include <media/stagefright/MediaExtractor.h>
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include <utils/RefBase.h>
|
||||
@@ -57,6 +58,7 @@ private:
|
||||
sp<MetaData> mFileMetaData;
|
||||
sp<WVMFileSource> mFileSource;
|
||||
sp<DataSource> mDataSource;
|
||||
sp<WVMInfoListener> mInfoListener;
|
||||
|
||||
bool mHaveMetaData;
|
||||
|
||||
|
||||
51
proprietary/wvm/include/WVMInfoListener.h
Normal file
51
proprietary/wvm/include/WVMInfoListener.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef WVMINFO_LISTENER_H
|
||||
|
||||
#define WVMINFO_LISTENER_H
|
||||
|
||||
#include "AndroidConfig.h"
|
||||
#include "WVMMediaSource.h"
|
||||
#include <media/stagefright/DataSource.h>
|
||||
#include "WVStreamControlAPI.h"
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// Handles messages from the DRM plugin
|
||||
class WVMInfoListener : public DrmManagerClient::OnInfoListener {
|
||||
enum MessageType {
|
||||
MessageType_HeartbeatServer = 4000,
|
||||
MessageType_HeartbeatPeriod = 4001
|
||||
};
|
||||
|
||||
public:
|
||||
WVMInfoListener() : mPeriod(-1) {};
|
||||
virtual void onInfo(const DrmInfoEvent &event);
|
||||
void setSession(WVSession *session);
|
||||
void configureHeartbeat();
|
||||
|
||||
private:
|
||||
WVSession *mSession;
|
||||
std::string mServerUrl;
|
||||
int mPeriod;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // WVMINFO_LISTENER_H
|
||||
Reference in New Issue
Block a user