Bug 1315631 - don't dispatch |this| in the constructor. r=jya a=ritu
authorJW Wang <jwwang@mozilla.com>
Wed, 30 Nov 2016 12:03:40 +0800
changeset 359014 0b450f6d7994c57b1b6d7847fa4ced05fe471072
parent 359013 b0a358343e70cd35f7ab67e80fa3f6af07490044
child 359015 a4196f4641360bc2f8fb34fd608cb37b68fc169a
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, ritu
bugs1315631
milestone51.0
Bug 1315631 - don't dispatch |this| in the constructor. r=jya a=ritu Because it will change the ref-count which might cause destructor to run before exiting the constructor.
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderReader.h
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
dom/media/ogg/OggReader.cpp
dom/media/ogg/OggReader.h
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -231,19 +231,24 @@ MediaDecoderReader::MediaDecoderReader(A
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mDecoder && mDecoder->DataArrivedEvent()) {
     mDataArrivedListener = mDecoder->DataArrivedEvent()->Connect(
       mTaskQueue, this, &MediaDecoderReader::NotifyDataArrived);
   }
 
   ReaderQueue::Instance().Add(this);
+}
 
+nsresult
+MediaDecoderReader::Init()
+{
   // Dispatch initialization that needs to happen on that task queue.
   mTaskQueue->Dispatch(NewRunnableMethod(this, &MediaDecoderReader::InitializationTask));
+  return InitInternal();
 }
 
 void
 MediaDecoderReader::InitializationTask()
 {
   if (!mDecoder) {
     return;
   }
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -84,17 +84,17 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
 
   // The caller must ensure that Shutdown() is called before aDecoder is
   // destroyed.
   explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder);
 
   // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
   // on failure.
-  virtual nsresult Init() { return NS_OK; }
+  nsresult Init();
 
   // Called by MDSM in dormant state to release resources allocated by this
   // reader. The reader can resume decoding by calling Seek() to a specific
   // position.
   virtual void ReleaseResources() {}
 
   // Destroys the decoding state. The reader cannot be made usable again.
   // This is different from ReleaseMediaResources() as it is irreversable,
@@ -399,16 +399,18 @@ protected:
 
   // Used to send TimedMetadata to the listener.
   TimedMetadataEventProducer mTimedMetadataEvent;
 
   // Notify if this media is not seekable.
   MediaEventProducer<void> mOnMediaNotSeekable;
 
 private:
+  virtual nsresult InitInternal() { return NS_OK; }
+
   // Does any spinup that needs to happen on this task queue. This runs on a
   // different thread than Init, and there should not be ordering dependencies
   // between the two (even though in practice, Init will always run first right
   // now thanks to the tail dispatcher).
   void InitializationTask();
 
   // Read header data for all bitstreams in the file. Fills aInfo with
   // the data required to present the media, and optionally fills *aTags
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -159,17 +159,17 @@ MediaFormatReader::InitLayersBackendType
   RefPtr<LayerManager> layerManager =
     nsContentUtils::LayerManagerForDocument(element->OwnerDoc());
   NS_ENSURE_TRUE_VOID(layerManager);
 
   mLayersBackendType = layerManager->GetCompositorBackendType();
 }
 
 nsresult
-MediaFormatReader::Init()
+MediaFormatReader::InitInternal()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
 
   InitLayersBackendType();
 
   mAudio.mTaskQueue =
     new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   mVideo.mTaskQueue =
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -28,18 +28,16 @@ class MediaFormatReader final : public M
 public:
   MediaFormatReader(AbstractMediaDecoder* aDecoder,
                     MediaDataDemuxer* aDemuxer,
                     VideoFrameContainer* aVideoFrameContainer = nullptr,
                     layers::LayersBackend aLayersBackend = layers::LayersBackend::LAYERS_NONE);
 
   virtual ~MediaFormatReader();
 
-  nsresult Init() override;
-
   size_t SizeOfVideoQueueInFrames() override;
   size_t SizeOfAudioQueueInFrames() override;
 
   RefPtr<MediaDataPromise>
   RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold) override;
 
   RefPtr<MediaDataPromise> RequestAudioData() override;
 
@@ -97,16 +95,17 @@ public:
 
   // Returns a string describing the state of the decoder data.
   // Used for debugging purposes.
   void GetMozDebugReaderData(nsAString& aString);
 
   void SetVideoBlankDecode(bool aIsBlankDecode) override;
 
 private:
+  nsresult InitInternal() override;
 
   bool HasVideo() const { return mVideo.mTrackDemuxer; }
   bool HasAudio() const { return mAudio.mTrackDemuxer; }
 
   bool IsWaitingOnCDMResource();
 
   bool InitDemuxer();
   // Notify the demuxer that new data has been received.
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -160,17 +160,17 @@ OggReader::~OggReader()
     nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
       LOG(LogLevel::Debug, (nsPrintfCString("Reporting telemetry MEDIA_OGG_LOADED_IS_CHAINED=%d", isChained).get()));
       Telemetry::Accumulate(Telemetry::ID::MEDIA_OGG_LOADED_IS_CHAINED, isChained);
     });
     AbstractThread::MainThread()->Dispatch(task.forget());
   }
 }
 
-nsresult OggReader::Init() {
+nsresult OggReader::InitInternal() {
   int ret = ogg_sync_init(&mOggState);
   NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE);
   return NS_OK;
 }
 
 nsresult OggReader::ResetDecode(TrackSet aTracks)
 {
   return ResetDecode(false, aTracks);
--- a/dom/media/ogg/OggReader.h
+++ b/dom/media/ogg/OggReader.h
@@ -27,31 +27,32 @@ class OggReader final : public MediaDeco
 {
 public:
   explicit OggReader(AbstractMediaDecoder* aDecoder);
 
 protected:
   ~OggReader();
 
 public:
-  nsresult Init() override;
   nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
                                                    TrackInfo::kVideoTrack)) override;
   bool DecodeAudioData() override;
 
   // If the Theora granulepos has not been captured, it may read several packets
   // until one with a granulepos has been captured, to ensure that all packets
   // read have valid time info.
   bool DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) override;
 
   nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
   RefPtr<SeekPromise> Seek(SeekTarget aTarget, int64_t aEndTime) override;
   media::TimeIntervals GetBuffered() override;
 
 private:
+  nsresult InitInternal() override;
+
   bool HasAudio() {
     return (mVorbisState != 0 && mVorbisState->mActive) ||
            (mOpusState != 0 && mOpusState->mActive);
   }
 
   bool HasVideo() {
     return mTheoraState != 0 && mTheoraState->mActive;
   }