Bug 1368904 - Handle unexpected error callback from GeckoHlsPlayer. r=JamesCheng
authorKilik Kuo <kikuo@mozilla.com>
Wed, 28 Jun 2017 15:09:00 -0700
changeset 366558 ddcdefe1d0b4ff63b84bc1148fc075e5fc66fa29
parent 366557 0889c455cf63f5f01d2d5af1bb7c1a75dc6241e2
child 366559 95095d0a8c6207283ef7bbd00a912fd6d9c08010
push id32104
push usercbook@mozilla.com
push dateThu, 29 Jun 2017 13:46:04 +0000
treeherdermozilla-central@d2aff6fc075d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersJamesCheng
bugs1368904
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1368904 - Handle unexpected error callback from GeckoHlsPlayer. r=JamesCheng MozReview-Commit-ID: CQDjFXiFDrQ
dom/media/hls/HLSDemuxer.cpp
dom/media/hls/HLSDemuxer.h
dom/media/hls/HLSResource.cpp
dom/media/hls/HLSResource.h
--- a/dom/media/hls/HLSDemuxer.cpp
+++ b/dom/media/hls/HLSDemuxer.cpp
@@ -77,39 +77,46 @@ public:
     : mMutex("HLSDemuxerCallbacksSupport")
     , mDemuxer(aDemuxer)
   {
     MOZ_ASSERT(mDemuxer);
   }
 
   void OnInitialized(bool aHasAudio, bool aHasVideo)
   {
-    HLS_DEBUG("HLSDemuxerCallbacksSupport",
-              "OnInitialized");
+    HLS_DEBUG("HLSDemuxerCallbacksSupport", "OnInitialized");
     MutexAutoLock lock(mMutex);
     if (!mDemuxer) { return; }
     RefPtr<HLSDemuxerCallbacksSupport> self = this;
     mDemuxer->GetTaskQueue()->Dispatch(NS_NewRunnableFunction(
      "HLSDemuxer::HLSDemuxerCallbacksSupport::OnInitialized",
      [=] () {
        MutexAutoLock lock(self->mMutex);
        if (self->mDemuxer) {
          self->mDemuxer->OnInitialized(aHasAudio, aHasVideo);
        }
      }));
   }
 
-  // TODO: Handle the unexpected error signal from the java implementation
-  // in bug 1368904.
   void OnError(int aErrorCode)
   {
-    HLS_DEBUG("HLSDemuxerCallbacksSupport",
-              "Got error(%d) from java side",
-              aErrorCode);
+    HLS_DEBUG("HLSDemuxerCallbacksSupport", "Got error(%d) from java side", aErrorCode);
+    MutexAutoLock lock(mMutex);
+    if (!mDemuxer) { return; }
+    RefPtr<HLSDemuxerCallbacksSupport> self = this;
+    mDemuxer->GetTaskQueue()->Dispatch(NS_NewRunnableFunction(
+     "HLSDemuxer::HLSDemuxerCallbacksSupport::OnError",
+     [=] () {
+       MutexAutoLock lock(self->mMutex);
+       if (self->mDemuxer) {
+         self->mDemuxer->OnError(aErrorCode);
+       }
+     }));
   }
+
   void Detach()
   {
     MutexAutoLock lock(mMutex);
     mDemuxer = nullptr;
   }
 
   Mutex mMutex;
 private:
@@ -146,16 +153,23 @@ HLSDemuxer::OnInitialized(bool aHasAudio
   }
   if (aHasVideo) {
     UpdateVideoInfo(0);
   }
 
   mInitPromise.ResolveIfExists(NS_OK, __func__);
 }
 
+void
+HLSDemuxer::OnError(int aErrorCode)
+{
+  MOZ_ASSERT(OnTaskQueue());
+  mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
+}
+
 RefPtr<HLSDemuxer::InitPromise>
 HLSDemuxer::Init()
 {
   RefPtr<HLSDemuxer> self = this;
   return InvokeAsync(GetTaskQueue(), __func__,
     [self](){
       RefPtr<InitPromise> p = self->mInitPromise.Ensure(__func__);
       return p;
--- a/dom/media/hls/HLSDemuxer.h
+++ b/dom/media/hls/HLSDemuxer.h
@@ -45,16 +45,17 @@ public:
   UniquePtr<EncryptionInfo> GetCrypto() override;
 
   bool ShouldComputeStartTime() const override { return true; }
 
   void NotifyDataArrived() override;
 
   AutoTaskQueue* GetTaskQueue() const { return mTaskQueue; }
   void OnInitialized(bool aHasAudio, bool aHasVideo);
+  void OnError(int aErrorCode);
 
 private:
   media::TimeUnit GetNextKeyFrameTime();
   void UpdateVideoInfo(int index);
   void UpdateAudioInfo(int index);
   bool OnTaskQueue() const;
   TrackInfo* GetTrackInfo(TrackInfo::TrackType);
   ~HLSDemuxer();
--- a/dom/media/hls/HLSResource.cpp
+++ b/dom/media/hls/HLSResource.cpp
@@ -13,63 +13,89 @@ namespace mozilla {
 
 HLSResourceCallbacksSupport::HLSResourceCallbacksSupport(HLSResource* aResource)
 {
   MOZ_ASSERT(aResource);
   mResource = aResource;
 }
 
 void
+HLSResourceCallbacksSupport::Detach()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mResource = nullptr;
+}
+
+void
 HLSResourceCallbacksSupport::OnDataArrived()
 {
-  MOZ_ASSERT(mResource);
-  mResource->onDataAvailable();
+  MOZ_ASSERT(NS_IsMainThread());
+  if (mResource) {
+    mResource->onDataAvailable();
+  }
 }
 
 void
 HLSResourceCallbacksSupport::OnError(int aErrorCode)
 {
-  MOZ_ASSERT(mResource);
+  MOZ_ASSERT(NS_IsMainThread());
+  if (mResource) {
+    mResource->onError(aErrorCode);
+  }
 }
 
 HLSResource::HLSResource(MediaResourceCallback* aCallback,
                          nsIChannel* aChannel,
                          nsIURI* aURI,
                          const MediaContainerType& aContainerType)
   : mCallback(aCallback)
   , mChannel(aChannel)
   , mURI(aURI)
   , mContainerType(aContainerType)
 {
   nsCString spec;
   nsresult rv = aURI->GetSpec(spec);
   (void)rv;
   HLSResourceCallbacksSupport::Init();
   mJavaCallbacks = GeckoHLSResourceWrapper::Callbacks::New();
-  HLSResourceCallbacksSupport::AttachNative(mJavaCallbacks,
-                                            mozilla::MakeUnique<HLSResourceCallbacksSupport>(this));
+  mCallbackSupport = new HLSResourceCallbacksSupport(this);
+  HLSResourceCallbacksSupport::AttachNative(mJavaCallbacks, mCallbackSupport);
   mHLSResourceWrapper = java::GeckoHLSResourceWrapper::Create(NS_ConvertUTF8toUTF16(spec),
                                                               mJavaCallbacks);
   MOZ_ASSERT(mHLSResourceWrapper);
 }
 
 void
 HLSResource::onDataAvailable()
 {
   MOZ_ASSERT(mCallback);
   HLS_DEBUG("HLSResource", "onDataAvailable");
   mCallback->NotifyDataArrived();
 }
 
+void
+HLSResource::onError(int aErrorCode)
+{
+  MOZ_ASSERT(mCallback);
+  HLS_DEBUG("HLSResource", "onError(%d)", aErrorCode);
+  // Since HLS source should be from the Internet, we treat all resource errors
+  // from GeckoHlsPlayer as network errors.
+  mCallback->NotifyNetworkError();
+}
+
 HLSResource::~HLSResource()
 {
+  HLS_DEBUG("HLSResource", "~HLSResource()");
+  if (mCallbackSupport) {
+    mCallbackSupport->Detach();
+    mCallbackSupport = nullptr;
+  }
   if (mJavaCallbacks) {
     HLSResourceCallbacksSupport::DisposeNative(mJavaCallbacks);
     mJavaCallbacks = nullptr;
   }
   if (mHLSResourceWrapper) {
     mHLSResourceWrapper->Destroy();
     mHLSResourceWrapper = nullptr;
   }
-  HLS_DEBUG("HLSResource", "Destroy");
 }
 
 } // namespace mozilla
--- a/dom/media/hls/HLSResource.h
+++ b/dom/media/hls/HLSResource.h
@@ -18,26 +18,29 @@ using namespace mozilla::java;
 
 namespace mozilla {
 
 class HLSResource;
 
 class HLSResourceCallbacksSupport
   : public GeckoHLSResourceWrapper::Callbacks::Natives<HLSResourceCallbacksSupport>
 {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(HLSResourceCallbacksSupport)
 public:
   typedef GeckoHLSResourceWrapper::Callbacks::Natives<HLSResourceCallbacksSupport> NativeCallbacks;
   using NativeCallbacks::DisposeNative;
   using NativeCallbacks::AttachNative;
 
   HLSResourceCallbacksSupport(HLSResource* aResource);
+  void Detach();
   void OnDataArrived();
   void OnError(int aErrorCode);
 
 private:
+  ~HLSResourceCallbacksSupport() {}
   HLSResource* mResource;
 };
 
 class HLSResource final : public MediaResource
 {
 public:
   HLSResource(MediaResourceCallback* aCallback,
               nsIChannel* aChannel,
@@ -99,16 +102,17 @@ public:
   java::GeckoHLSResourceWrapper::GlobalRef GetResourceWrapper() {
     return mHLSResourceWrapper;
   }
 
 private:
   friend class HLSResourceCallbacksSupport;
 
   void onDataAvailable();
+  void onError(int aErrorCode);
 
   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
     size += mContainerType.SizeOfExcludingThis(aMallocSizeOf);
 
     return size;
   }
@@ -119,12 +123,13 @@ private:
   }
 
   RefPtr<MediaResourceCallback> mCallback;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsIURI> mURI;
   const MediaContainerType mContainerType;
   java::GeckoHLSResourceWrapper::GlobalRef mHLSResourceWrapper;
   java::GeckoHLSResourceWrapper::Callbacks::GlobalRef mJavaCallbacks;
+  RefPtr<HLSResourceCallbacksSupport> mCallbackSupport;
 };
 
 } // namespace mozilla
 #endif /* HLSResource_h_ */