mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 862182. r=roc,doublec
This commit is contained in:
parent
97aa06ad85
commit
01b2b87eff
@ -2389,7 +2389,7 @@ nsresult HTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
|
||||
decoder->SetMediaSeekable(aOriginal->IsMediaSeekable());
|
||||
}
|
||||
|
||||
MediaResource* resource = originalResource->CloneData(decoder);
|
||||
nsRefPtr<MediaResource> resource = originalResource->CloneData(decoder);
|
||||
if (!resource) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -2421,7 +2421,7 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
|
||||
|
||||
MediaResource* resource = MediaResource::Create(decoder, aChannel);
|
||||
nsRefPtr<MediaResource> resource = MediaResource::Create(decoder, aChannel);
|
||||
if (!resource)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
return principal.forget();
|
||||
}
|
||||
virtual bool CanClone() { return false; }
|
||||
virtual MediaResource* CloneData(MediaDecoder* aDecoder)
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -102,7 +102,7 @@ public:
|
||||
virtual int64_t GetNextCachedData(int64_t aOffset) { return aOffset; }
|
||||
virtual int64_t GetCachedDataEnd(int64_t aOffset) { return mLength; }
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
|
||||
virtual bool IsSuspendedByCache(MediaResource** aActiveResource) { return false; }
|
||||
virtual bool IsSuspendedByCache() { return false; }
|
||||
virtual bool IsSuspended() { return false; }
|
||||
virtual nsresult ReadFromCache(char* aBuffer,
|
||||
int64_t aOffset,
|
||||
|
@ -1830,7 +1830,7 @@ MediaCacheStream::IsTransportSeekable()
|
||||
}
|
||||
|
||||
bool
|
||||
MediaCacheStream::AreAllStreamsForResourceSuspended(MediaResource** aActiveStream)
|
||||
MediaCacheStream::AreAllStreamsForResourceSuspended()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
|
||||
MediaCache::ResourceStreamIterator iter(mResourceID);
|
||||
@ -1847,15 +1847,9 @@ MediaCacheStream::AreAllStreamsForResourceSuspended(MediaResource** aActiveStrea
|
||||
if (stream->mChannelOffset > dataOffset) {
|
||||
continue;
|
||||
}
|
||||
if (aActiveStream) {
|
||||
*aActiveStream = stream->mClient;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aActiveStream) {
|
||||
*aActiveStream = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -331,9 +331,7 @@ public:
|
||||
|
||||
// Returns true when all streams for this resource are suspended or their
|
||||
// channel has ended.
|
||||
// If aActiveResource is non-null, fills it with a pointer to a stream
|
||||
// for this resource that is not suspended or ended.
|
||||
bool AreAllStreamsForResourceSuspended(MediaResource** aActiveResource);
|
||||
bool AreAllStreamsForResourceSuspended();
|
||||
|
||||
// These methods must be called on a different thread from the main
|
||||
// thread. They should always be called on the same thread for a given
|
||||
|
@ -409,7 +409,7 @@ MediaDecoder::~MediaDecoder()
|
||||
}
|
||||
|
||||
nsresult MediaDecoder::OpenResource(MediaResource* aResource,
|
||||
nsIStreamListener** aStreamListener)
|
||||
nsIStreamListener** aStreamListener)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (aStreamListener) {
|
||||
@ -425,7 +425,6 @@ nsresult MediaDecoder::OpenResource(MediaResource* aResource,
|
||||
nsresult rv = aResource->Open(aStreamListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
|
||||
delete aResource;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -948,9 +947,7 @@ void MediaDecoder::NotifySuspendedStatusChanged()
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mResource)
|
||||
return;
|
||||
MediaResource* activeStream;
|
||||
bool suspended = mResource->IsSuspendedByCache(&activeStream);
|
||||
|
||||
bool suspended = mResource->IsSuspendedByCache();
|
||||
if (mOwner) {
|
||||
mOwner->NotifySuspendedByCache(suspended);
|
||||
UpdateReadyStateForData();
|
||||
|
@ -296,6 +296,12 @@ public:
|
||||
|
||||
// Get the current MediaResource being used. Its URI will be returned
|
||||
// by currentSrc. Returns what was passed to Load(), if Load() has been called.
|
||||
// Note: The MediaResource is refcounted, but it outlives the MediaDecoder,
|
||||
// so it's OK to use the reference returned by this function without
|
||||
// refcounting, *unless* you need to store and use the reference after the
|
||||
// MediaDecoder has been destroyed. You might need to do this if you're
|
||||
// wrapping the MediaResource in some kind of byte stream interface to be
|
||||
// passed to a platform decoder.
|
||||
MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE
|
||||
{
|
||||
return mResource;
|
||||
|
@ -713,15 +713,16 @@ bool ChannelMediaResource::CanClone()
|
||||
return mCacheStream.IsAvailableForSharing();
|
||||
}
|
||||
|
||||
MediaResource* ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
already_AddRefed<MediaResource> ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
NS_ASSERTION(mCacheStream.IsAvailableForSharing(), "Stream can't be cloned");
|
||||
|
||||
ChannelMediaResource* resource = new ChannelMediaResource(aDecoder,
|
||||
nullptr,
|
||||
mURI,
|
||||
GetContentType());
|
||||
nsRefPtr<ChannelMediaResource> resource =
|
||||
new ChannelMediaResource(aDecoder,
|
||||
nullptr,
|
||||
mURI,
|
||||
GetContentType());
|
||||
if (resource) {
|
||||
// Initially the clone is treated as suspended by the cache, because
|
||||
// we don't have a channel. If the cache needs to read data from the clone
|
||||
@ -734,7 +735,7 @@ MediaResource* ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
resource->mChannelStatistics = new MediaChannelStatistics(mChannelStatistics);
|
||||
resource->mChannelStatistics->Stop();
|
||||
}
|
||||
return resource;
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
void ChannelMediaResource::CloseChannel()
|
||||
@ -1187,9 +1188,9 @@ ChannelMediaResource::EnsureCacheUpToDate()
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelMediaResource::IsSuspendedByCache(MediaResource** aActiveResource)
|
||||
ChannelMediaResource::IsSuspendedByCache()
|
||||
{
|
||||
return mCacheStream.AreAllStreamsForResourceSuspended(aActiveResource);
|
||||
return mCacheStream.AreAllStreamsForResourceSuspended();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1283,7 +1284,7 @@ public:
|
||||
virtual void Resume() {}
|
||||
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
|
||||
virtual bool CanClone();
|
||||
virtual MediaResource* CloneData(MediaDecoder* aDecoder);
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
|
||||
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
|
||||
|
||||
// These methods are called off the main thread.
|
||||
@ -1326,13 +1327,7 @@ public:
|
||||
return std::max(aOffset, mSize);
|
||||
}
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
|
||||
virtual bool IsSuspendedByCache(MediaResource** aActiveResource)
|
||||
{
|
||||
if (aActiveResource) {
|
||||
*aActiveResource = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual bool IsSuspendedByCache() { return false; }
|
||||
virtual bool IsSuspended() { return false; }
|
||||
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
|
||||
|
||||
@ -1504,7 +1499,7 @@ bool FileMediaResource::CanClone()
|
||||
return true;
|
||||
}
|
||||
|
||||
MediaResource* FileMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
@ -1527,7 +1522,8 @@ MediaResource* FileMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
if (NS_FAILED(rv))
|
||||
return nullptr;
|
||||
|
||||
return new FileMediaResource(aDecoder, channel, mURI, GetContentType());
|
||||
nsRefPtr<MediaResource> resource(new FileMediaResource(aDecoder, channel, mURI, GetContentType()));
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
|
||||
@ -1592,7 +1588,7 @@ int64_t FileMediaResource::Tell()
|
||||
return offset;
|
||||
}
|
||||
|
||||
MediaResource*
|
||||
already_AddRefed<MediaResource>
|
||||
MediaResource::Create(MediaDecoder* aDecoder, nsIChannel* aChannel)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
@ -1609,10 +1605,13 @@ MediaResource::Create(MediaDecoder* aDecoder, nsIChannel* aChannel)
|
||||
aChannel->GetContentType(contentType);
|
||||
|
||||
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
|
||||
nsRefPtr<MediaResource> resource;
|
||||
if (fc || IsBlobURI(uri)) {
|
||||
return new FileMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
resource = new FileMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
} else {
|
||||
resource = new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
}
|
||||
return new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
void BaseMediaResource::MoveLoadsToBackground() {
|
||||
|
@ -196,8 +196,6 @@ public:
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaResource)
|
||||
|
||||
virtual ~MediaResource() {}
|
||||
|
||||
// The following can be called on the main thread only:
|
||||
// Get the URI
|
||||
virtual nsIURI* URI() const { return nullptr; }
|
||||
@ -224,7 +222,7 @@ public:
|
||||
// Create a new stream of the same type that refers to the same URI
|
||||
// with a new channel. Any cached data associated with the original
|
||||
// stream should be accessible in the new stream too.
|
||||
virtual MediaResource* CloneData(MediaDecoder* aDecoder) = 0;
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) = 0;
|
||||
// Set statistics to be recorded to the object passed in.
|
||||
virtual void RecordStatisticsTo(MediaChannelStatistics *aStatistics) { }
|
||||
|
||||
@ -313,9 +311,7 @@ public:
|
||||
// changes.
|
||||
// For resources using the media cache, this returns true only when all
|
||||
// streams for the same resource are all suspended.
|
||||
// If aActiveResource is non-null, fills it with a pointer to a stream
|
||||
// for this resource that is not suspended or ended.
|
||||
virtual bool IsSuspendedByCache(MediaResource** aActiveResource) = 0;
|
||||
virtual bool IsSuspendedByCache() = 0;
|
||||
// Returns true if this stream has been suspended.
|
||||
virtual bool IsSuspended() = 0;
|
||||
// Reads only data which is cached in the media cache. If you try to read
|
||||
@ -335,7 +331,7 @@ public:
|
||||
* Create a resource, reading data from the channel. Call on main thread only.
|
||||
* The caller must follow up by calling resource->Open().
|
||||
*/
|
||||
static MediaResource* Create(MediaDecoder* aDecoder, nsIChannel* aChannel);
|
||||
static already_AddRefed<MediaResource> Create(MediaDecoder* aDecoder, nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Open the stream. This creates a stream listener and returns it in
|
||||
@ -374,6 +370,8 @@ public:
|
||||
// nsIChannel when the MediaResource is created. Safe to call from
|
||||
// any thread.
|
||||
virtual const nsCString& GetContentType() const = 0;
|
||||
protected:
|
||||
virtual ~MediaResource() {};
|
||||
};
|
||||
|
||||
class BaseMediaResource : public MediaResource {
|
||||
@ -496,7 +494,7 @@ public:
|
||||
// Return true if the stream has been closed.
|
||||
bool IsClosed() const { return mCacheStream.IsClosed(); }
|
||||
virtual bool CanClone();
|
||||
virtual MediaResource* CloneData(MediaDecoder* aDecoder);
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
|
||||
// Set statistics to be recorded to the object passed in. If not called,
|
||||
// |ChannelMediaResource| will create it's own statistics objects in |Open|.
|
||||
void RecordStatisticsTo(MediaChannelStatistics *aStatistics) MOZ_OVERRIDE {
|
||||
@ -526,7 +524,7 @@ public:
|
||||
virtual int64_t GetNextCachedData(int64_t aOffset);
|
||||
virtual int64_t GetCachedDataEnd(int64_t aOffset);
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset);
|
||||
virtual bool IsSuspendedByCache(MediaResource** aActiveResource);
|
||||
virtual bool IsSuspendedByCache();
|
||||
virtual bool IsSuspended();
|
||||
virtual bool IsTransportSeekable() MOZ_OVERRIDE;
|
||||
|
||||
@ -547,7 +545,7 @@ public:
|
||||
void Revoke() { mResource = nullptr; }
|
||||
|
||||
private:
|
||||
ChannelMediaResource* mResource;
|
||||
nsRefPtr<ChannelMediaResource> mResource;
|
||||
};
|
||||
friend class Listener;
|
||||
|
||||
|
@ -22,7 +22,6 @@ struct VideoPlane {
|
||||
|
||||
struct VideoFrame {
|
||||
int64_t mTimeUs;
|
||||
int64_t mEndTimeUs;
|
||||
bool mKeyFrame;
|
||||
bool mShouldSkip;
|
||||
void *mData;
|
||||
|
@ -43,7 +43,7 @@ nsresult MediaOmxReader::Init(MediaDecoderReader* aCloneDonor)
|
||||
}
|
||||
|
||||
nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
|
||||
@ -118,7 +118,7 @@ nsresult MediaOmxReader::ResetDecode()
|
||||
}
|
||||
|
||||
bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
int64_t aTimeThreshold)
|
||||
int64_t aTimeThreshold)
|
||||
{
|
||||
// Record number of frames decoded and parsed. Automatically update the
|
||||
// stats counters using the AutoNotifyDecoded stack-based class.
|
||||
@ -339,7 +339,7 @@ void MediaOmxReader::OnDecodeThreadFinish() {
|
||||
|
||||
void MediaOmxReader::OnDecodeThreadStart() {
|
||||
if (mOmxDecoder.get()) {
|
||||
nsresult result = mOmxDecoder->Play();
|
||||
DebugOnly<nsresult> result = mOmxDecoder->Play();
|
||||
NS_ASSERTION(result == NS_OK, "OmxDecoder should be in play state to continue decoding");
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ VideoGraphicBuffer::VideoGraphicBuffer(const android::wp<android::OmxDecoder> aO
|
||||
android::MediaBuffer *aBuffer,
|
||||
SurfaceDescriptor *aDescriptor)
|
||||
: GraphicBufferLocked(*aDescriptor),
|
||||
mOmxDecoder(aOmxDecoder),
|
||||
mMediaBuffer(aBuffer)
|
||||
mMediaBuffer(aBuffer),
|
||||
mOmxDecoder(aOmxDecoder)
|
||||
{
|
||||
mMediaBuffer->add_ref();
|
||||
}
|
||||
@ -74,7 +74,7 @@ namespace android {
|
||||
|
||||
MediaStreamSource::MediaStreamSource(MediaResource *aResource,
|
||||
AbstractMediaDecoder *aDecoder) :
|
||||
mDecoder(aDecoder), mResource(aResource)
|
||||
mResource(aResource), mDecoder(aDecoder)
|
||||
{
|
||||
}
|
||||
|
||||
@ -127,8 +127,8 @@ using namespace android;
|
||||
|
||||
OmxDecoder::OmxDecoder(MediaResource *aResource,
|
||||
AbstractMediaDecoder *aDecoder) :
|
||||
mResource(aResource),
|
||||
mDecoder(aDecoder),
|
||||
mResource(aResource),
|
||||
mVideoWidth(0),
|
||||
mVideoHeight(0),
|
||||
mVideoColorFormat(0),
|
||||
@ -141,8 +141,8 @@ OmxDecoder::OmxDecoder(MediaResource *aResource,
|
||||
mVideoBuffer(nullptr),
|
||||
mAudioBuffer(nullptr),
|
||||
mIsVideoSeeking(false),
|
||||
mPaused(false),
|
||||
mAudioMetadataRead(false)
|
||||
mAudioMetadataRead(false),
|
||||
mPaused(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ bool OmxDecoder::Init() {
|
||||
// OMXClient::connect() always returns OK and abort's fatally if
|
||||
// it can't connect.
|
||||
OMXClient client;
|
||||
status_t err = client.connect();
|
||||
DebugOnly<status_t> err = client.connect();
|
||||
NS_ASSERTION(err == OK, "Failed to connect to OMX in mediaserver.");
|
||||
sp<IOMX> omx = client.interface();
|
||||
|
||||
@ -512,7 +512,6 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
|
||||
|
||||
if (err == OK && mVideoBuffer->range_length() > 0) {
|
||||
int64_t timeUs;
|
||||
int64_t durationUs;
|
||||
int32_t unreadable;
|
||||
int32_t keyFrame;
|
||||
|
||||
@ -545,7 +544,6 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
|
||||
aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, &newDescriptor);
|
||||
aFrame->mRotation = mVideoRotation;
|
||||
aFrame->mTimeUs = timeUs;
|
||||
aFrame->mEndTimeUs = timeUs + durationUs;
|
||||
aFrame->mKeyFrame = keyFrame;
|
||||
aFrame->Y.mWidth = mVideoWidth;
|
||||
aFrame->Y.mHeight = mVideoHeight;
|
||||
@ -560,8 +558,6 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
|
||||
if (!ToVideoFrame(aFrame, timeUs, data, length, keyFrame)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aFrame->mEndTimeUs = timeUs + durationUs;
|
||||
}
|
||||
|
||||
if (aKeyframeSkip && timeUs < aTimeUs) {
|
||||
@ -696,3 +692,4 @@ void OmxDecoder::Pause() {
|
||||
}
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
|
@ -38,10 +38,10 @@ class MediaStreamSource : public DataSource {
|
||||
typedef mozilla::MediaResource MediaResource;
|
||||
typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
|
||||
|
||||
MediaResource *mResource;
|
||||
nsRefPtr<MediaResource> mResource;
|
||||
AbstractMediaDecoder *mDecoder;
|
||||
public:
|
||||
MediaStreamSource(MediaResource *aResource,
|
||||
MediaStreamSource(MediaResource* aResource,
|
||||
AbstractMediaDecoder *aDecoder);
|
||||
|
||||
virtual status_t initCheck() const;
|
||||
@ -80,7 +80,7 @@ class OmxDecoder : public RefBase {
|
||||
};
|
||||
|
||||
AbstractMediaDecoder *mDecoder;
|
||||
MediaResource *mResource;
|
||||
nsRefPtr<MediaResource> mResource;
|
||||
sp<GonkNativeWindow> mNativeWindow;
|
||||
sp<GonkNativeWindowClient> mNativeWindowClient;
|
||||
sp<MediaSource> mVideoTrack;
|
||||
|
@ -273,15 +273,16 @@ bool MediaPluginHost::FindDecoder(const nsACString& aMimeType, const char* const
|
||||
|
||||
MPAPI::Decoder *MediaPluginHost::CreateDecoder(MediaResource *aResource, const nsACString& aMimeType)
|
||||
{
|
||||
const char *chars;
|
||||
size_t len = NS_CStringGetData(aMimeType, &chars, nullptr);
|
||||
NS_ENSURE_TRUE(aResource, nullptr);
|
||||
|
||||
Decoder *decoder = new Decoder();
|
||||
nsAutoPtr<Decoder> decoder(new Decoder());
|
||||
if (!decoder) {
|
||||
return nullptr;
|
||||
}
|
||||
decoder->mResource = aResource;
|
||||
|
||||
const char *chars;
|
||||
size_t len = NS_CStringGetData(aMimeType, &chars, nullptr);
|
||||
for (size_t n = 0; n < mPlugins.Length(); ++n) {
|
||||
Manifest *plugin = mPlugins[n];
|
||||
const char* const *codecs;
|
||||
@ -289,7 +290,8 @@ MPAPI::Decoder *MediaPluginHost::CreateDecoder(MediaResource *aResource, const n
|
||||
continue;
|
||||
}
|
||||
if (plugin->CreateDecoder(&sPluginHost, decoder, chars, len)) {
|
||||
return decoder;
|
||||
aResource->AddRef();
|
||||
return decoder.forget();
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,6 +301,12 @@ MPAPI::Decoder *MediaPluginHost::CreateDecoder(MediaResource *aResource, const n
|
||||
void MediaPluginHost::DestroyDecoder(Decoder *aDecoder)
|
||||
{
|
||||
aDecoder->DestroyDecoder(aDecoder);
|
||||
MediaResource* resource = GetResource(aDecoder);
|
||||
if (resource) {
|
||||
// resource *shouldn't* be null, but check anyway just in case the plugin
|
||||
// decoder does something stupid.
|
||||
resource->Release();
|
||||
}
|
||||
delete aDecoder;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user