Bug 1210045 - Fix GonkVideoDecoderManager shutdown during initialization r=bwu

This commit is contained in:
Sotaro Ikeda 2015-10-15 22:25:57 -07:00
parent 0efa947850
commit 3d8057f05f
3 changed files with 39 additions and 56 deletions

View File

@ -36,7 +36,7 @@ public:
nsresult Flush();
// Shutdown decoder and rejects the init promise.
nsresult Shutdown();
virtual nsresult Shutdown();
// True if sample is queued.
bool HasQueuedSample();

View File

@ -59,16 +59,22 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
nsIntSize frameSize(mVideoWidth, mVideoHeight);
mPicture = pictureRect;
mInitialFrame = frameSize;
mVideoListener = new VideoResourceListener(this);
mVideoListener = new VideoResourceListener();
}
GonkVideoDecoderManager::~GonkVideoDecoderManager()
{
mVideoListener->NotifyManagerRelease();
MOZ_COUNT_DTOR(GonkVideoDecoderManager);
}
nsresult
GonkVideoDecoderManager::Shutdown()
{
mVideoCodecRequest.DisconnectIfExists();
return GonkDecoderManager::Shutdown();
}
nsRefPtr<MediaDataDecoder::InitPromise>
GonkVideoDecoderManager::Init()
{
@ -107,6 +113,16 @@ GonkVideoDecoderManager::Init()
}
nsRefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
android::sp<GonkVideoDecoderManager> self = this;
mVideoCodecRequest.Begin(mVideoListener->Init()
->Then(mReaderTaskQueue, __func__,
[self] (bool) -> void {
self->mVideoCodecRequest.Complete();
self->codecReserved();
}, [self] (bool) -> void {
self->mVideoCodecRequest.Complete();
self->codecCanceled();
}));
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
mDecoder->AsyncAskMediaCodec();
@ -399,6 +415,9 @@ void GonkVideoDecoderManager::ReleaseVideoBuffer() {
void
GonkVideoDecoderManager::codecReserved()
{
if (mInitPromise.IsEmpty()) {
return;
}
GVDM_LOG("codecReserved");
sp<AMessage> format = new AMessage;
sp<Surface> surface;
@ -427,7 +446,7 @@ GonkVideoDecoderManager::codecReserved()
return;
}
mInitPromise.ResolveIfExists(TrackType::kVideoTrack, __func__);
mInitPromise.Resolve(TrackType::kVideoTrack, __func__);
}
void
@ -456,66 +475,24 @@ GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
}
}
GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener(GonkVideoDecoderManager *aManager)
: mManager(aManager)
GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener()
{
}
GonkVideoDecoderManager::VideoResourceListener::~VideoResourceListener()
{
mManager = nullptr;
}
void
GonkVideoDecoderManager::VideoResourceListener::codecReserved()
{
// This class holds VideoResourceListener reference to prevent it's destroyed.
class CodecListenerHolder : public nsRunnable {
public:
CodecListenerHolder(VideoResourceListener* aListener)
: mVideoListener(aListener) {}
NS_IMETHOD Run()
{
mVideoListener->NotifyCodecReserved();
mVideoListener = nullptr;
return NS_OK;
}
android::sp<VideoResourceListener> mVideoListener;
};
if (mManager) {
nsRefPtr<CodecListenerHolder> runner = new CodecListenerHolder(this);
mManager->mReaderTaskQueue->Dispatch(runner.forget());
}
mVideoCodecPromise.Resolve(true, __func__);
}
void
GonkVideoDecoderManager::VideoResourceListener::codecCanceled()
{
if (mManager) {
MOZ_ASSERT(mManager->mReaderTaskQueue->IsCurrentThreadIn());
nsCOMPtr<nsIRunnable> r =
NS_NewNonOwningRunnableMethod(mManager, &GonkVideoDecoderManager::codecCanceled);
mManager->mReaderTaskQueue->Dispatch(r.forget());
}
}
void
GonkVideoDecoderManager::VideoResourceListener::NotifyManagerRelease()
{
MOZ_ASSERT_IF(mManager, mManager->mReaderTaskQueue->IsCurrentThreadIn());
mManager = nullptr;
}
void
GonkVideoDecoderManager::VideoResourceListener::NotifyCodecReserved()
{
if (mManager) {
MOZ_ASSERT(mManager->mReaderTaskQueue->IsCurrentThreadIn());
mManager->codecReserved();
}
mVideoCodecPromise.Reject(true, __func__);
}
uint8_t *

View File

@ -36,6 +36,8 @@ typedef android::MediaCodecProxy MediaCodecProxy;
typedef mozilla::layers::TextureClient TextureClient;
public:
typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> MediaResourcePromise;
GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
const VideoInfo& aConfig);
@ -46,6 +48,8 @@ public:
nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) override;
nsresult Shutdown() override;
static void RecycleCallback(TextureClient* aClient, void* aClosure);
private:
@ -67,24 +71,25 @@ private:
class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
{
public:
VideoResourceListener(GonkVideoDecoderManager *aManager);
VideoResourceListener();
~VideoResourceListener();
nsRefPtr<MediaResourcePromise> Init()
{
nsRefPtr<MediaResourcePromise> p = mVideoCodecPromise.Ensure(__func__);
return p.forget();
}
void codecReserved() override;
void codecCanceled() override;
void NotifyManagerRelease();
void NotifyCodecReserved();
private:
// Forbidden
VideoResourceListener() = delete;
VideoResourceListener(const VideoResourceListener &rhs) = delete;
const VideoResourceListener &operator=(const VideoResourceListener &rhs) = delete;
GonkVideoDecoderManager *mManager;
MozPromiseHolder<MediaResourcePromise> mVideoCodecPromise;
};
friend class VideoResourceListener;
bool SetVideoFormat();
@ -113,6 +118,7 @@ private:
MediaInfo mInfo;
android::sp<VideoResourceListener> mVideoListener;
MozPromiseRequestHolder<MediaResourcePromise> mVideoCodecRequest;
FrameInfo mFrameInfo;
// color converter