Backed out changesets ef6465b02d0d f749e3f70ffc ecd54a3fbfdd 8f472a850073 (bug 879717)
authorRandell Jesup <rjesup@jesup.org>
Mon, 13 Oct 2014 22:18:22 -0400
changeset 234643 189ac924dfa6121245d15226ec9e1cc78d962715
parent 234642 e5c0de9492d1240ee31e21d584604e262fe0993b
child 234644 d56d0157891e97004f6a55b7000a5883917dae77
push id611
push userraliiev@mozilla.com
push dateMon, 05 Jan 2015 23:23:16 +0000
treeherdermozilla-release@345cd3b9c445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs879717
milestone35.0a2
backs outef6465b02d0d15a0f29b4f0d8823994feb6658da
f749e3f70ffc956291c4738140c896d1a9e718c0
ecd54a3fbfddd0260566ff8a0269e3bca3223a2c
8f472a850073d4b0ad52e276bdfcac39263cf780
Backed out changesets ef6465b02d0d f749e3f70ffc ecd54a3fbfdd 8f472a850073 (bug 879717)
content/html/content/public/HTMLMediaElement.h
content/html/content/src/HTMLMediaElement.cpp
content/media/test/mochitest.ini
content/media/test/test_bug879717.html
dom/camera/CameraPreviewMediaStream.cpp
dom/camera/CameraPreviewMediaStream.h
dom/camera/DOMCameraControl.cpp
dom/camera/DOMCameraControlListener.cpp
dom/camera/test/test_camera.html
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -280,23 +280,16 @@ public:
   /**
    * Called when there's been an error fetching the resource. This decides
    * whether it's appropriate to fire an error event.
    */
   void NotifyLoadError();
 
   void NotifyMediaTrackEnabled(MediaTrack* aTrack);
 
-  /**
-   * Called by a DOMMediaStream when it has tracks available.
-   * This allows us to setup audio and video outputs after the stream
-   * has already reported that playback started, in case they are added late.
-   */
-  void NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream);
-
   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
 
   /**
    * Returns the current load ID. Asynchronous events store the ID that was
    * current when they were enqueued, and if it has changed when they come to
    * fire, they consider themselves cancelled, and don't fire.
    */
   uint32_t GetCurrentLoadID() { return mCurrentLoadID; }
@@ -618,17 +611,16 @@ public:
     return FinishDecoderSetup(aDecoder, aStream, nullptr, nullptr);
   }
 
 protected:
   virtual ~HTMLMediaElement();
 
   class MediaLoadListener;
   class StreamListener;
-  class MediaStreamTracksAvailableCallback;
 
   virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
   virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
 
   class WakeLockBoolWrapper {
   public:
     explicit WakeLockBoolWrapper(bool val = false)
       : mValue(val), mCanPlay(true), mOuter(nullptr) {}
@@ -1021,19 +1013,16 @@ protected:
   // These events get re-dispatched when the bfcache is exited.
   nsTArray<nsString> mPendingEvents;
 
   // Media loading flags. See:
   //   http://www.whatwg.org/specs/web-apps/current-work/#video)
   nsMediaNetworkState mNetworkState;
   nsMediaReadyState mReadyState;
 
-  // Last value passed from codec or stream source to UpdateReadyStateForData.
-  NextFrameStatus mLastNextFrameStatus;
-
   enum LoadAlgorithmState {
     // No load algorithm instance is waiting for a source to be added to the
     // media in order to continue loading.
     NOT_WAITING,
     // We've run the load algorithm, and we tried all source children of the
     // media element, and failed to load any successfully. We're waiting for
     // another source element to be added to the media element, and will try
     // to load any such element when its added.
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -66,18 +66,16 @@
 #include "nsURIHashKey.h"
 #include "nsJSUtils.h"
 #include "MediaStreamGraph.h"
 #include "nsIScriptError.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "mozilla/dom/MediaSource.h"
 #include "MediaMetadataManager.h"
 #include "MediaSourceDecoder.h"
-#include "AudioStreamTrack.h"
-#include "VideoStreamTrack.h"
 
 #include "AudioChannelService.h"
 
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/WakeLock.h"
 
 #include "mozilla/dom/AudioTrack.h"
 #include "mozilla/dom/AudioTrackList.h"
@@ -661,20 +659,17 @@ void HTMLMediaElement::AbortExistingLoad
   mLoadedDataFired = false;
   mAutoplaying = true;
   mIsLoadingFromSourceChildren = false;
   mSuspendedAfterFirstFrame = false;
   mAllowSuspendAfterFirstFrame = true;
   mHaveQueuedSelectResource = false;
   mSuspendedForPreloadNone = false;
   mDownloadSuspendedByCache = false;
-  mHasAudio = false;
-  mHasVideo = false;
   mSourcePointer = nullptr;
-  mLastNextFrameStatus = NEXT_FRAME_UNINITIALIZED;
 
   mTags = nullptr;
 
   if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
     NS_ASSERTION(!mDecoder && !mSrcStream, "How did someone setup a new stream/decoder already?");
     ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
     mPaused = true;
@@ -898,49 +893,16 @@ void HTMLMediaElement::NotifyMediaTrackE
     } else {
       SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_TRACK);
     }
   } else if (VideoTrack* track = aTrack->AsVideoTrack()) {
     mDisableVideo = !track->Selected();
   }
 }
 
-void HTMLMediaElement::NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream)
-{
-  if (!mSrcStream || mSrcStream != aStream) {
-    return;
-  }
-
-  bool oldHasAudio = mHasAudio;
-  bool oldHasVideo = mHasVideo;
-
-  nsAutoTArray<nsRefPtr<AudioStreamTrack>,1> audioTracks;
-  aStream->GetAudioTracks(audioTracks);
-  nsAutoTArray<nsRefPtr<VideoStreamTrack>,1> videoTracks;
-  aStream->GetVideoTracks(videoTracks);
-
-  mHasAudio = !audioTracks.IsEmpty();
-  mHasVideo = !videoTracks.IsEmpty();
-
-  if (!oldHasAudio && mHasAudio) {
-    GetSrcMediaStream()->AddAudioOutput(this);
-    GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume));
-  }
-  if (!oldHasVideo && mHasVideo ) {
-    VideoFrameContainer* container = GetVideoFrameContainer();
-    if (container) {
-      GetSrcMediaStream()->AddVideoOutput(container);
-    }
-    // mHasVideo changed so make sure the screen wakelock is updated
-    NotifyOwnerDocumentActivityChanged();
-  }
-
-  CheckAutoplayDataReady();
-}
-
 void HTMLMediaElement::LoadFromSourceChildren()
 {
   NS_ASSERTION(mDelayingLoadEvent,
                "Should delay load event (if in document) during load");
   NS_ASSERTION(mIsLoadingFromSourceChildren,
                "Must remember we're loading from source children");
 
   nsIDocument* parentDoc = OwnerDoc()->GetParentDocument();
@@ -2020,17 +1982,16 @@ HTMLMediaElement::LookupMediaElementURIT
 }
 
 HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mSrcStreamListener(nullptr),
     mCurrentLoadID(0),
     mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
     mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING),
-    mLastNextFrameStatus(NEXT_FRAME_UNINITIALIZED),
     mLoadWaitStatus(NOT_WAITING),
     mVolume(1.0),
     mPreloadAction(PRELOAD_UNDEFINED),
     mMediaSize(-1,-1),
     mLastCurrentTime(0.0),
     mFragmentStart(-1.0),
     mFragmentEnd(-1.0),
     mDefaultPlaybackRate(1.0),
@@ -2849,38 +2810,16 @@ private:
   bool mHaveCurrentData;
   bool mBlocked;
 
   // mMutex protects the fields below; they can be accessed on any thread
   Mutex mMutex;
   bool mPendingNotifyOutput;
 };
 
-class HTMLMediaElement::MediaStreamTracksAvailableCallback:
-    public DOMMediaStream::OnTracksAvailableCallback
-{
-public:
-  explicit MediaStreamTracksAvailableCallback(HTMLMediaElement* aElement,
-                                              DOMMediaStream::TrackTypeHints aExpectedTracks = 0):
-      DOMMediaStream::OnTracksAvailableCallback(aExpectedTracks),
-      mElement(aElement)
-    {}
-  virtual void NotifyTracksAvailable(DOMMediaStream* aStream)
-  {
-    NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
-
-    if (!mElement) {
-      return;
-    }
-    mElement->NotifyMediaStreamTracksAvailable(aStream);
-  }
-private:
-  HTMLMediaElement* mElement;
-};
-
 void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
 {
   NS_ASSERTION(!mSrcStream && !mSrcStreamListener, "Should have been ended already");
 
   mSrcStream = aStream;
 
   nsRefPtr<MediaStream> stream = mSrcStream->GetStream();
   if (stream) {
@@ -2892,55 +2831,53 @@ void HTMLMediaElement::SetupSrcMediaStre
   mSrcStreamListener = new StreamListener(this);
   GetSrcMediaStream()->AddListener(mSrcStreamListener);
   if (mPaused) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
   }
   if (mPausedForInactiveDocumentOrChannel) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
   }
-
-  mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this, DOMMediaStream::HINT_CONTENTS_AUDIO));
-  mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this, DOMMediaStream::HINT_CONTENTS_VIDEO));
-
-  MediaInfo mediaInfo;
-  mediaInfo.mAudio.mHasAudio = mHasAudio;
-  mediaInfo.mVideo.mHasVideo = mHasVideo;
-  MetadataLoaded(&mediaInfo, nullptr);
-
-  DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
-  mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
-
   ChangeDelayLoadStatus(false);
+  GetSrcMediaStream()->AddAudioOutput(this);
+  GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume));
+  VideoFrameContainer* container = GetVideoFrameContainer();
+  if (container) {
+    GetSrcMediaStream()->AddVideoOutput(container);
+  }
 
   // Note: we must call DisconnectTrackListListeners(...)  before dropping
   // mSrcStream
   mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks());
 
+  ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
+  DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
+  DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
+  ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
   AddRemoveSelfReference();
   // FirstFrameLoaded() will be called when the stream has current data.
 }
 
 void HTMLMediaElement::EndSrcMediaStreamPlayback()
 {
   MediaStream* stream = GetSrcMediaStream();
   if (stream) {
     stream->RemoveListener(mSrcStreamListener);
   }
   mSrcStream->DisconnectTrackListListeners(AudioTracks(), VideoTracks());
 
   // Kill its reference to this element
   mSrcStreamListener->Forget();
   mSrcStreamListener = nullptr;
-  if (stream && mHasAudio) {
+  if (stream) {
     stream->RemoveAudioOutput(this);
   }
   VideoFrameContainer* container = GetVideoFrameContainer();
   if (container) {
-    if (stream && mHasVideo) {
+    if (stream) {
       stream->RemoveVideoOutput(container);
     }
     container->ClearCurrentFrame();
   }
   if (mPaused && stream) {
     stream->ChangeExplicitBlockerCount(-1);
   }
   if (mPausedForInactiveDocumentOrChannel && stream) {
@@ -2982,29 +2919,23 @@ void HTMLMediaElement::MetadataLoaded(co
   // delete the VideoFrameContainer. This happens when the src is changed to an
   // audio only file.
   if (!aInfo->HasVideo() && mVideoFrameContainer) {
     // call ForgetElement() such that callbacks from |mVideoFrameContainer|
     // won't reach us anymore.
     mVideoFrameContainer->ForgetElement();
     mVideoFrameContainer = nullptr;
   }
-
-  if (IsVideo()) {
-    // Update the screen wakelock in case mHasVideo changed
-    NotifyOwnerDocumentActivityChanged();
-  }
 }
 
 void HTMLMediaElement::FirstFrameLoaded()
 {
   NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended");
 
   ChangeDelayLoadStatus(false);
-  UpdateReadyStateForData(NEXT_FRAME_UNAVAILABLE);
 
   if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
       !HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
       mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) {
     mSuspendedAfterFirstFrame = true;
     mDecoder->Suspend();
   }
 }
@@ -3157,28 +3088,20 @@ void HTMLMediaElement::DownloadStalled()
 
 bool HTMLMediaElement::ShouldCheckAllowOrigin()
 {
   return mCORSMode != CORS_NONE;
 }
 
 void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatus aNextFrame)
 {
-  mLastNextFrameStatus = aNextFrame;
-
   if (mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
     // aNextFrame might have a next frame because the decoder can advance
     // on its own thread before MetadataLoaded gets a chance to run.
     // The arrival of more data can't change us out of this readyState.
-
-    return;
-  }
-
-  if (!mHasAudio && !mHasVideo) {
-    // No tracks available yet, don't advance from HAVE_METADATA
     return;
   }
 
   if (aNextFrame == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING) {
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
     return;
   }
 
@@ -3191,24 +3114,16 @@ void HTMLMediaElement::UpdateReadyStateF
     // this transition if the decoder is in ended state; the readyState
     // should remain at HAVE_CURRENT_DATA in this case.
     // Note that this state transition includes the case where we finished
     // downloaded the whole data stream.
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
     return;
   }
 
-  if (mReadyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && mHasVideo) {
-    VideoFrameContainer* container = GetVideoFrameContainer();
-    if (container && mMediaSize == nsIntSize(-1,-1)) {
-      // No frame has been set yet. Don't advance.
-      return;
-    }
-  }
-
   if (aNextFrame != MediaDecoderOwner::NEXT_FRAME_AVAILABLE) {
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
     if (!mWaitingFired && aNextFrame == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING) {
       FireTimeUpdate(false);
       DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
       mWaitingFired = true;
     }
     return;
@@ -3339,25 +3254,24 @@ void HTMLMediaElement::ChangeNetworkStat
   } else if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE && !mError) {
     // Fire 'suspend' event when entering NETWORK_IDLE and no error presented.
     DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
   }
 }
 
 bool HTMLMediaElement::CanActivateAutoplay()
 {
-  // For stream inputs, we activate autoplay on HAVE_METADATA because
+  // For stream inputs, we activate autoplay on HAVE_CURRENT_DATA because
   // this element itself might be blocking the stream from making progress by
   // being paused.
   return !mPausedForInactiveDocumentOrChannel &&
          mAutoplaying &&
          mPaused &&
          ((mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
-          (mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA)) &&
-         (mHasAudio || mHasVideo) &&
+          (mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)) &&
          HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
          mAutoplayEnabled &&
          !IsEditable();
 }
 
 void HTMLMediaElement::CheckAutoplayDataReady()
 {
   if (CanActivateAutoplay()) {
@@ -3376,24 +3290,34 @@ void HTMLMediaElement::CheckAutoplayData
       GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
     }
     DispatchAsyncEvent(NS_LITERAL_STRING("play"));
   }
 }
 
 VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
 {
-  if (mVideoFrameContainer)
-    return mVideoFrameContainer;
+  // If we have loaded the metadata, and the size of the video is still
+  // (-1, -1), the media has no video. Don't go a create a video frame
+  // container.
+  if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA &&
+      mMediaSize == nsIntSize(-1, -1)) {
+    return nullptr;
+  }
 
   // Only video frames need an image container.
   if (!IsVideo()) {
     return nullptr;
   }
 
+  mHasVideo = true;
+
+  if (mVideoFrameContainer)
+    return mVideoFrameContainer;
+
   mVideoFrameContainer =
     new VideoFrameContainer(this, LayerManager::CreateAsynchronousImageContainer());
 
   return mVideoFrameContainer;
 }
 
 nsresult HTMLMediaElement::DispatchEvent(const nsAString& aName)
 {
@@ -3496,17 +3420,16 @@ void HTMLMediaElement::NotifyDecoderPrin
     mMediaKeys->Shutdown();
   }
 #endif
 }
 
 void HTMLMediaElement::UpdateMediaSize(nsIntSize size)
 {
   mMediaSize = size;
-  UpdateReadyStateForData(mLastNextFrameStatus);
 }
 
 void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents)
 {
   if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
     mPausedForInactiveDocumentOrChannel = aPauseElement;
     if (aPauseElement) {
 #ifdef MOZ_EME
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -314,17 +314,16 @@ skip-if = buildapp == 'mulet' || os == '
 [test_bug465498.html]
 [test_bug493187.html]
 [test_bug495145.html]
 [test_bug495300.html]
 [test_bug654550.html]
 [test_bug686942.html]
 [test_bug726904.html]
 [test_bug874897.html]
-[test_bug879717.html]
 [test_bug883173.html]
 [test_bug895091.html]
 [test_bug895305.html]
 [test_bug919265.html]
 [test_bug957847.html]
 [test_bug1018933.html]
 [test_can_play_type.html]
 [test_can_play_type_mpeg.html]
deleted file mode 100644
--- a/content/media/test/test_bug879717.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for bug 879717, check that a video element can be drawn into a canvas directly on 'play' event</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  <script type="text/javascript" src="manifest.js"></script>
-</head>
-<body>
-<video id="v1" autoplay />
-<video id="v2" autoplay />
-<canvas id="c1" />
-<canvas id="c2" />
-<pre id="test">
-<script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
-
-var media = getPlayableVideo(gSmallTests);
-
-var checkDrawImage = function(video, canvas, name) {
-  var exception = null;
-  var exceptionName = "nothing";
-  try {
-    var ctx = canvas.getContext('2d');
-    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
-  } catch (e) {
-    exception = e;
-    exceptionName = e.name;
-  }
-  ok(exception === null || video.ended,
-    "drawImage shouldn't throw an exception on play of " + name + ", got " + exceptionName);
-};
-
-if (media == null) {
-  todo(false, "No media supported.");
-  SimpleTest.finish();
-} else {
-  v1.src = media.name;
-  v2.mozSrcObject = v1.mozCaptureStream();
-
-  var v1Tested = false;
-  var v2Tested = false;
-
-  v1.addEventListener('play', function() {
-    checkDrawImage(v1, c1, media.name);
-
-    v1Tested = true;
-    if (v2Tested) {
-      SimpleTest.finish();
-    }
-  });
-
-  v2.addEventListener('play', function() {
-    checkDrawImage(v2, c2, "stream of " + media.name);
-
-    v2Tested = true;
-    if (v1Tested) {
-      SimpleTest.finish();
-    }
-  });
-}
-</script>
-</pre>
-</body>
-</html>
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -14,32 +14,29 @@
  */
 #define MAX_INVALIDATE_PENDING 4
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
-static const TrackID TRACK_VIDEO = 2;
-
 void
 FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
 {
   nsRefPtr<nsIRunnable> task = aRunnable;
   NS_DispatchToMainThread(task);
 }
 
 CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
   : MediaStream(aWrapper)
   , mMutex("mozilla::camera::CameraPreviewMediaStream")
   , mInvalidatePending(0)
   , mDiscardedFrames(0)
   , mRateLimit(false)
-  , mTrackCreated(false)
 {
   SetGraphImpl(MediaStreamGraph::GetInstance());
   mFakeMediaStreamGraph = new FakeMediaStreamGraph();
   mIsConsumed = false;
 }
 
 void
 CameraPreviewMediaStream::AddAudioOutput(void* aKey)
@@ -110,32 +107,16 @@ CameraPreviewMediaStream::RemoveListener
   MutexAutoLock lock(mMutex);
 
   nsRefPtr<MediaStreamListener> listener(aListener);
   mListeners.RemoveElement(aListener);
   listener->NotifyEvent(mFakeMediaStreamGraph, MediaStreamListener::EVENT_REMOVED);
 }
 
 void
-CameraPreviewMediaStream::OnPreviewStateChange(bool aActive)
-{
-  MutexAutoLock lock(mMutex);
-  if (!mTrackCreated && aActive) {
-    mTrackCreated = true;
-    VideoSegment tmpSegment;
-    uint32_t trackEvent = aActive ? MediaStreamListener::TRACK_EVENT_CREATED
-                                  : MediaStreamListener::TRACK_EVENT_ENDED;
-    for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-      MediaStreamListener* l = mListeners[j];
-      l->NotifyQueuedTrackChanges(mFakeMediaStreamGraph, TRACK_VIDEO, 0, 0, trackEvent, tmpSegment);
-    }
-  }
-}
-
-void
 CameraPreviewMediaStream::Destroy()
 {
   MutexAutoLock lock(mMutex);
   DestroyImpl();
 }
 
 void
 CameraPreviewMediaStream::Invalidate()
--- a/dom/camera/CameraPreviewMediaStream.h
+++ b/dom/camera/CameraPreviewMediaStream.h
@@ -46,32 +46,30 @@ public:
   virtual void SetAudioOutputVolume(void* aKey, float aVolume) MOZ_OVERRIDE;
   virtual void RemoveAudioOutput(void* aKey) MOZ_OVERRIDE;
   virtual void AddVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void RemoveVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void ChangeExplicitBlockerCount(int32_t aDelta) MOZ_OVERRIDE;
   virtual void AddListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void Destroy();
-  void OnPreviewStateChange(bool aActive);
 
   void Invalidate();
 
   // Call these on any thread.
   void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage);
   void ClearCurrentFrame();
   void RateLimit(bool aLimit);
 
 protected:
   // mMutex protects all the class' fields.
   // This class is not registered to MediaStreamGraph.
   // It needs to protect all the fields.
   Mutex mMutex;
   int32_t mInvalidatePending;
   uint32_t mDiscardedFrames;
   bool mRateLimit;
-  bool mTrackCreated;
   nsRefPtr<FakeMediaStreamGraph> mFakeMediaStreamGraph;
 };
 
 }
 
 #endif // DOM_CAMERA_CAMERAPREVIEWMEDIASTREAM_H
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -213,18 +213,17 @@ nsDOMCameraControl::nsDOMCameraControl(u
     config.mPreviewSize.height = aInitialConfig.mPreviewSize.mHeight;
     config.mRecorderProfile = aInitialConfig.mRecorderProfile;
   }
 
   mCameraControl = ICameraControl::Create(aCameraId);
   mCurrentConfiguration = initialConfig.forget();
 
   // Attach our DOM-facing media stream to our viewfinder stream.
-  SetHintContents(HINT_CONTENTS_VIDEO);
-  InitStreamCommon(mInput);
+  mStream = mInput;
   MOZ_ASSERT(mWindow, "Shouldn't be created with a null window!");
   if (mWindow->GetExtantDoc()) {
     CombineWithPrincipal(mWindow->GetExtantDoc()->NodePrincipal());
   }
 
   // Register a listener for camera events.
   mListener = new DOMCameraControlListener(this, mInput);
   mCameraControl->AddListener(mListener);
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -132,17 +132,16 @@ DOMCameraControlListener::OnPreviewState
       DOM_CAMERA_LOGI("Preview started\n");
       break;
 
     default:
       DOM_CAMERA_LOGE("Unknown preview state %d\n", aState);
       MOZ_ASSERT_UNREACHABLE("Invalid preview state");
       return;
   }
-  mStream->OnPreviewStateChange(aState == kPreviewStarted);
   NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
 }
 
 void
 DOMCameraControlListener::OnRecorderStateChange(RecorderState aState,
                                                 int32_t aStatus, int32_t aTrackNum)
 {
   class Callback : public DOMCallback
--- a/dom/camera/test/test_camera.html
+++ b/dom/camera/test/test_camera.html
@@ -104,36 +104,28 @@ var Camera = {
   takePictureSuccess: function taken_foto(blob) {
     ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
     ok("image/" + test.fileFormat ==  blob.type, "Blob Type = " + blob.type);
   },
   takePictureEvent: function taken_foto_evt(e) {
     var blob = e.data;
     var img = new Image();
     var test = this._currentTest;
-    var onPreviewStateChange = function(e) {
-      if (e.newState === 'started') {
-        ok(true, "viewfinder is ready and playing after resume");
-        Camera.cameraObj.removeEventListener('previewstatechange', onPreviewStateChange);
-        Camera._testsCompleted++;
-        if(Camera._testsCompleted == Camera._tests.length) {
-          ok(true, "test finishing");
-          SimpleTest.finish();
-        } else {
-          Camera.runTests();
-        }
-      }
-    }
-    Camera.cameraObj.addEventListener('previewstatechange', onPreviewStateChange);
     img.onload = function Imgsize() {
       ok(this.width == test.pictureSize.width, "The image taken has the width " +
                                               this.width + " pictureSize width = " + test.pictureSize.width);
       ok(this.height == test.pictureSize.height, "The image taken has the height " +
                                               this.height + " picturesize height = " + test.pictureSize.height);
-      Camera.cameraObj.resumePreview();
+      Camera._testsCompleted++;
+      if(Camera._testsCompleted == Camera._tests.length) {
+        ok(true, "test finishing");
+        SimpleTest.finish();
+      } else {
+        Camera.runTests();
+      }
     }
     ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
     ok("image/" + test.fileFormat ==  blob.type, "Blob Type = " + blob.type);
     img.src = window.URL.createObjectURL(blob);
   },
   shutter: function onShutter () {
     Camera._shutter++;