Bug 1168456 - Remove NotifyWaitingForResourcesStatusChanged() call from MediaCodecReader r=bholley,bwu

This commit is contained in:
Sotaro Ikeda 2015-05-28 11:11:46 -07:00
parent c14569449f
commit 6a032542b6
8 changed files with 121 additions and 96 deletions

View File

@ -182,9 +182,6 @@ MediaDecoderReader::AsyncReadMetadata()
mDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
// PreReadMetadata causes us to try to allocate various hardware and OS
// resources, which may not be available at the moment.
PreReadMetadata();
if (IsWaitingMediaResources()) {
return MetadataPromise::CreateAndReject(Reason::WAITING_FOR_RESOURCES, __func__);
}

View File

@ -165,13 +165,10 @@ public:
virtual bool HasVideo() = 0;
// The default implementation of AsyncReadMetadata is implemented in terms of
// synchronous PreReadMetadata() / ReadMetadata() calls. Implementations may also
// synchronous ReadMetadata() calls. Implementations may also
// override AsyncReadMetadata to create a more proper async implementation.
virtual nsRefPtr<MetadataPromise> AsyncReadMetadata();
// A function that is called before ReadMetadata() call.
virtual void PreReadMetadata() {};
// Read header data for all bitstreams in the file. Fills aInfo with
// the data required to present the media, and optionally fills *aTags
// with tag metadata from the file.

View File

@ -486,6 +486,11 @@ MediaCodecProxy::resourceReserved()
releaseCodec();
if (!allocateCodec()) {
SetMediaCodecFree();
// Notification
sp<CodecResourceListener> listener = mListener.promote();
if (listener != nullptr) {
listener->codecCanceled();
}
return;
}
@ -501,6 +506,17 @@ MediaCodecProxy::resourceReserved()
}
}
void
MediaCodecProxy::resourceCanceled()
{
SetMediaCodecFree();
// Notification
sp<CodecResourceListener> listener = mListener.promote();
if (listener != nullptr) {
listener->codecCanceled();
}
}
bool MediaCodecProxy::Prepare()
{

View File

@ -152,7 +152,7 @@ protected:
// MediaResourceHandler::EventListener::resourceReserved()
virtual void resourceReserved();
// MediaResourceHandler::EventListener::resourceCanceled()
virtual void resourceCanceled() {}
virtual void resourceCanceled();
private:
// Forbidden

View File

@ -268,7 +268,6 @@ MediaCodecReader::ProcessCachedDataTask::Run()
MediaCodecReader::MediaCodecReader(AbstractMediaDecoder* aDecoder)
: MediaOmxCommonReader(aDecoder)
, mExtractor(nullptr)
, mIsWaitingResources(false)
, mTextureClientIndexesLock("MediaCodecReader::mTextureClientIndexesLock")
, mColorConverterBufferSize(0)
, mParserMonitor("MediaCodecReader::mParserMonitor")
@ -289,19 +288,6 @@ MediaCodecReader::Init(MediaDecoderReader* aCloneDonor)
return NS_OK;
}
bool
MediaCodecReader::IsWaitingMediaResources()
{
return mIsWaitingResources;
}
void
MediaCodecReader::UpdateIsWaitingMediaResources()
{
mIsWaitingResources = (mVideoTrack.mCodec != nullptr) &&
(!mVideoTrack.mCodec->allocated());
}
void
MediaCodecReader::ReleaseMediaResources()
{
@ -644,58 +630,66 @@ MediaCodecReader::ParseDataSegment(const char* aBuffer,
return true;
}
void
MediaCodecReader::PreReadMetadata()
{
UpdateIsWaitingMediaResources();
}
nsresult
MediaCodecReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
nsRefPtr<MediaDecoderReader::MetadataPromise>
MediaCodecReader::AsyncReadMetadata()
{
MOZ_ASSERT(OnTaskQueue());
if (!ReallocateResources()) {
return NS_ERROR_FAILURE;
if (!ReallocateExtractorResources()) {
return MediaDecoderReader::MetadataPromise::CreateAndReject(
ReadMetadataFailureReason::METADATA_ERROR, __func__);
}
bool incrementalParserNeeded =
mDecoder->GetResource()->GetContentType().EqualsASCII(AUDIO_MP3);
if (incrementalParserNeeded && !TriggerIncrementalParser()) {
return NS_ERROR_FAILURE;
return MediaDecoderReader::MetadataPromise::CreateAndReject(
ReadMetadataFailureReason::METADATA_ERROR, __func__);
}
// Bug 1050667, both MediaDecoderStateMachine and MediaCodecReader
// relies on IsWaitingMediaResources() function. And the waiting state will be
// changed by binder thread, so we store the waiting state in a cache value to
// make them in the same waiting state.
UpdateIsWaitingMediaResources();
if (IsWaitingMediaResources()) {
return NS_OK;
}
nsRefPtr<MediaDecoderReader::MetadataPromise> p = mMetadataPromise.Ensure(__func__);
nsRefPtr<MediaCodecReader> self = this;
mMediaResourceRequest.Begin(CreateMediaCodecs()
->RefableThen(GetTaskQueue(), __func__,
[self] (bool) -> void {
self->mMediaResourceRequest.Complete();
self->HandleResourceAllocated();
}, [self] (bool) -> void {
self->mMediaResourceRequest.Complete();
self->mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
}));
return p;
}
void
MediaCodecReader::HandleResourceAllocated()
{
// Configure video codec after the codecReserved.
if (mVideoTrack.mSource != nullptr) {
if (!ConfigureMediaCodec(mVideoTrack)) {
DestroyMediaCodec(mVideoTrack);
return NS_ERROR_FAILURE;
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
return;
}
}
// TODO: start streaming
if (!UpdateDuration()) {
return NS_ERROR_FAILURE;
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
return;
}
if (!UpdateAudioInfo()) {
return NS_ERROR_FAILURE;
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
return;
}
if (!UpdateVideoInfo()) {
return NS_ERROR_FAILURE;
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
return;
}
// Set the total duration (the max of the audio and video track).
@ -724,14 +718,15 @@ MediaCodecReader::ReadMetadata(MediaInfo* aInfo,
mozilla::TimeStamp::Now());
}
*aInfo = mInfo;
*aTags = nullptr;
nsRefPtr<MetadataHolder> metadata = new MetadataHolder();
metadata->mInfo = mInfo;
metadata->mTags = nullptr;
#ifdef MOZ_AUDIO_OFFLOAD
CheckAudioOffload();
#endif
return NS_OK;
mMetadataPromise.Resolve(metadata, __func__);
}
nsresult
@ -1080,13 +1075,12 @@ MediaCodecReader::GetAudioOffloadTrack()
}
bool
MediaCodecReader::ReallocateResources()
MediaCodecReader::ReallocateExtractorResources()
{
if (CreateLooper() &&
CreateExtractor() &&
CreateMediaSources() &&
CreateTaskQueues() &&
CreateMediaCodecs()) {
CreateTaskQueues()) {
return true;
}
@ -1097,6 +1091,10 @@ MediaCodecReader::ReallocateResources()
void
MediaCodecReader::ReleaseCriticalResources()
{
mMediaResourceRequest.DisconnectIfExists();
mMediaResourcePromise.RejectIfExists(true, __func__);
mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);
ResetDecode();
// Before freeing a video codec, all video buffers needed to be released
// even from graphics pipeline.
@ -1292,21 +1290,35 @@ MediaCodecReader::CreateTaskQueues()
return true;
}
bool
nsRefPtr<MediaOmxCommonReader::MediaResourcePromise>
MediaCodecReader::CreateMediaCodecs()
{
if (CreateMediaCodec(mLooper, mAudioTrack, false, nullptr) &&
CreateMediaCodec(mLooper, mVideoTrack, true, mVideoListener)) {
return true;
bool isWaiting = false;
nsRefPtr<MediaResourcePromise> p = mMediaResourcePromise.Ensure(__func__);
if (!CreateMediaCodec(mLooper, mAudioTrack, false, isWaiting, nullptr)) {
mMediaResourcePromise.Reject(true, __func__);
return p;
}
return false;
if (!CreateMediaCodec(mLooper, mVideoTrack, true, isWaiting, mVideoListener)) {
mMediaResourcePromise.Reject(true, __func__);
return p;
}
if (!isWaiting) {
// No MediaCodec allocation wait.
mMediaResourcePromise.Resolve(true, __func__);
}
return p;
}
bool
MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
Track& aTrack,
bool aAsync,
bool& aIsWaiting,
wp<MediaCodecProxy::CodecResourceListener> aListener)
{
if (aTrack.mSource != nullptr && aTrack.mCodec == nullptr) {
@ -1351,10 +1363,14 @@ MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper,
DestroyMediaCodec(aTrack);
return false;
}
} else if (aAsync && !aTrack.mCodec->AsyncAskMediaCodec()) {
NS_WARNING("Couldn't request MediaCodec asynchronously");
DestroyMediaCodec(aTrack);
return false;
} else if (aAsync) {
if (aTrack.mCodec->AsyncAskMediaCodec()) {
aIsWaiting = true;
} else {
NS_WARNING("Couldn't request MediaCodec asynchronously");
DestroyMediaCodec(aTrack);
return false;
}
}
}
@ -1919,18 +1935,14 @@ MediaCodecReader::ClearColorConverterBuffer()
void
MediaCodecReader::VideoCodecReserved()
{
mDecoder->NotifyWaitingForResourcesStatusChanged();
mMediaResourcePromise.ResolveIfExists(true, __func__);
}
// Called on Binder thread.
void
MediaCodecReader::VideoCodecCanceled()
{
if (mVideoTrack.mTaskQueue) {
RefPtr<nsIRunnable> task =
NS_NewRunnableMethod(this, &MediaCodecReader::ReleaseCriticalResources);
mVideoTrack.mTaskQueue->Dispatch(task.forget());
}
mMediaResourcePromise.RejectIfExists(true, __func__);
}
} // namespace mozilla

View File

@ -52,6 +52,7 @@ class MediaCodecReader : public MediaOmxCommonReader
{
typedef mozilla::layers::TextureClient TextureClient;
typedef mozilla::layers::FenceHandle FenceHandle;
typedef MediaOmxCommonReader::MediaResourcePromise MediaResourcePromise;
public:
MediaCodecReader(AbstractMediaDecoder* aDecoder);
@ -61,9 +62,6 @@ public:
// on failure.
virtual nsresult Init(MediaDecoderReader* aCloneDonor);
// True if this reader is waiting media resource allocation
virtual bool IsWaitingMediaResources();
// True when this reader need to become dormant state
virtual bool IsDormantNeeded() { return true;}
@ -94,13 +92,7 @@ public:
virtual bool HasAudio();
virtual bool HasVideo();
virtual void PreReadMetadata() override;
// Read header data for all bitstreams in the file. Fills aInfo with
// the data required to present the media, and optionally fills *aTags
// with tag metadata from the file.
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags);
virtual nsRefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
// Moves the decode head to aTime microseconds. aStartTime and aEndTime
// denote the start and end times of the media in usecs, and aCurrentTime
@ -184,14 +176,14 @@ protected:
virtual bool CreateExtractor();
// Check the underlying HW resource is available and store the result in
// mIsWaitingResources.
void UpdateIsWaitingMediaResources();
virtual void HandleResourceAllocated();
android::sp<android::MediaExtractor> mExtractor;
// A cache value updated by UpdateIsWaitingMediaResources(), makes the
// "waiting resources state" is synchronous to StateMachine.
bool mIsWaitingResources;
MediaPromiseHolder<MediaDecoderReader::MetadataPromise> mMetadataPromise;
// XXX Remove after bug 1168008 land.
MediaPromiseConsumerHolder<MediaResourcePromise> mMediaResourceRequest;
MediaPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
private:
@ -339,7 +331,7 @@ private:
MediaCodecReader() = delete;
const MediaCodecReader& operator=(const MediaCodecReader& rhs) = delete;
bool ReallocateResources();
bool ReallocateExtractorResources();
void ReleaseCriticalResources();
void ReleaseResources();
@ -351,10 +343,11 @@ private:
bool CreateMediaSources();
void DestroyMediaSources();
bool CreateMediaCodecs();
nsRefPtr<MediaResourcePromise> CreateMediaCodecs();
static bool CreateMediaCodec(android::sp<android::ALooper>& aLooper,
Track& aTrack,
bool aAsync,
bool& aIsWaiting,
android::wp<android::MediaCodecProxy::CodecResourceListener> aListener);
static bool ConfigureMediaCodec(Track& aTrack);
void DestroyMediaCodecs();

View File

@ -88,20 +88,28 @@ RtspMediaCodecReader::RequestVideoData(bool aSkipToNextKeyframe,
return MediaCodecReader::RequestVideoData(aSkipToNextKeyframe, aTimeThreshold);
}
nsresult
RtspMediaCodecReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
nsRefPtr<MediaDecoderReader::MetadataPromise>
RtspMediaCodecReader::AsyncReadMetadata()
{
mRtspResource->DisablePlayoutDelay();
EnsureActive();
nsresult rv = MediaCodecReader::ReadMetadata(aInfo, aTags);
nsRefPtr<MediaDecoderReader::MetadataPromise> p =
MediaCodecReader::AsyncReadMetadata();
// Send a PAUSE to the RTSP server because the underlying media resource is
// not ready.
SetIdle();
if (rv == NS_OK && !IsWaitingMediaResources()) {
mRtspResource->EnablePlayoutDelay();
}
return p;
}
return rv;
void
RtspMediaCodecReader::HandleResourceAllocated()
{
EnsureActive();
MediaCodecReader::HandleResourceAllocated();
mRtspResource->EnablePlayoutDelay();;
}
} // namespace mozilla

View File

@ -58,8 +58,10 @@ public:
// Disptach a DecodeAudioDataTask to decode audio data.
virtual nsRefPtr<AudioDataPromise> RequestAudioData() override;
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual nsRefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata()
override;
virtual void HandleResourceAllocated() override;
private:
// A pointer to RtspMediaResource for calling the Rtsp specific function.