Bug 1523563 - Pass in mime type to MediaEncoder and give preference to it when passed. r=jib
authorAndreas Pehrson <apehrson@mozilla.com>
Wed, 19 Jun 2019 16:09:35 +0000
changeset 481088 7c42061bf905302cb5159f79f5db4accd60260de
parent 481087 944da9f033e8c2da0610742f7dcbf8a05c4a775b
child 481089 f5a1371cca6e8a7af4c65745489dbb0bba00a2f1
push id89078
push userpehrsons@gmail.com
push dateWed, 03 Jul 2019 09:31:19 +0000
treeherderautoland@d9f2bc3dd281 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjib
bugs1523563, 1512175
milestone69.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 1523563 - Pass in mime type to MediaEncoder and give preference to it when passed. r=jib Somewhere along the way this must have gotten broken. Until this, passing mime type to MediaRecorder has had no effect. This patch does two things: 1) Passes the mime type through from MediaRecorder to MediaEncoder 2) Gives preference to the mime type when passed, wrt picking codecs, however, we still yield to a video mime type when given a video track since that's how both Firefox and Chromium function today. Proper spec handling of mime type will be fixed in bug 1512175. Differential Revision: https://phabricator.services.mozilla.com/D35171
dom/media/MediaRecorder.cpp
dom/media/encoder/MediaEncoder.cpp
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -469,16 +469,17 @@ class MediaRecorder::Session : public Pr
  public:
   Session(MediaRecorder* aRecorder, uint32_t aTimeSlice)
       : mRecorder(aRecorder),
         mMediaStreamReady(false),
         mTimeSlice(aTimeSlice),
         mRunningState(RunningState::Idling) {
     MOZ_ASSERT(NS_IsMainThread());
 
+    aRecorder->GetMimeType(mMimeType);
     mMaxMemory = Preferences::GetUint("media.recorder.max_memory",
                                       MAX_ALLOW_MEMORY_BUFFER);
     mLastBlobTimeStamp = TimeStamp::Now();
   }
 
   void PrincipalChanged(MediaStreamTrack* aTrack) override {
     NS_ASSERTION(mMediaStreamTracks.Contains(aTrack),
                  "Principal changed for unrecorded track");
@@ -945,19 +946,19 @@ class MediaRecorder::Session : public Pr
       }
       MOZ_ASSERT(audioBitrate + videoBitrate <= bitrate);
     }
 
     // Allocate encoder and bind with union stream.
     // At this stage, the API doesn't allow UA to choose the output mimeType
     // format.
 
-    mEncoder = MediaEncoder::CreateEncoder(
-        mEncoderThread, NS_LITERAL_STRING(""), audioBitrate, videoBitrate,
-        aTrackTypes, aTrackRate);
+    mEncoder =
+        MediaEncoder::CreateEncoder(mEncoderThread, mMimeType, audioBitrate,
+                                    videoBitrate, aTrackTypes, aTrackRate);
 
     if (!mEncoder) {
       LOG(LogLevel::Error, ("Session.InitEncoder !mEncoder %p", this));
       DoSessionEndTask(NS_ERROR_ABORT);
       return;
     }
 
     mEncoderListener = MakeAndAddRef<EncoderListener>(mEncoderThread, this);
--- a/dom/media/encoder/MediaEncoder.cpp
+++ b/dom/media/encoder/MediaEncoder.cpp
@@ -632,52 +632,96 @@ already_AddRefed<MediaEncoder> MediaEnco
 
   if (!aTrackTypes) {
     MOZ_ASSERT(false);
     LOG(LogLevel::Error, ("No TrackTypes"));
     return nullptr;
   }
 #ifdef MOZ_WEBM_ENCODER
   else if (MediaEncoder::IsWebMEncoderEnabled() &&
-           (aMIMEType.EqualsLiteral(VIDEO_WEBM) ||
-            (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) {
+           aMIMEType.EqualsLiteral(VIDEO_WEBM)) {
+    if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK &&
+        MediaDecoder::IsOpusEnabled()) {
+      audioEncoder = MakeAndAddRef<OpusTrackEncoder>(aTrackRate);
+    }
+    if (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK) {
+      if (Preferences::GetBool("media.recorder.video.frame_drops", true)) {
+        videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
+            driftCompensator, aTrackRate, FrameDroppingMode::ALLOW);
+      } else {
+        videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
+            driftCompensator, aTrackRate, FrameDroppingMode::DISALLOW);
+      }
+    }
+    writer = MakeUnique<WebMWriter>(aTrackTypes);
+    mimeType = NS_LITERAL_STRING(VIDEO_WEBM);
+  } else if (MediaEncoder::IsWebMEncoderEnabled() &&
+             aMIMEType.EqualsLiteral(AUDIO_WEBM) &&
+             aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) {
     if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK &&
         MediaDecoder::IsOpusEnabled()) {
       audioEncoder = MakeAndAddRef<OpusTrackEncoder>(aTrackRate);
-      NS_ENSURE_TRUE(audioEncoder, nullptr);
     }
-    if (Preferences::GetBool("media.recorder.video.frame_drops", true)) {
-      videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
-          driftCompensator, aTrackRate, FrameDroppingMode::ALLOW);
+    if (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK) {
+      if (Preferences::GetBool("media.recorder.video.frame_drops", true)) {
+        videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
+            driftCompensator, aTrackRate, FrameDroppingMode::ALLOW);
+      } else {
+        videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
+            driftCompensator, aTrackRate, FrameDroppingMode::DISALLOW);
+      }
+      mimeType = NS_LITERAL_STRING(VIDEO_WEBM);
     } else {
-      videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
-          driftCompensator, aTrackRate, FrameDroppingMode::DISALLOW);
+      mimeType = NS_LITERAL_STRING(AUDIO_WEBM);
     }
     writer = MakeUnique<WebMWriter>(aTrackTypes);
-    NS_ENSURE_TRUE(writer, nullptr);
-    NS_ENSURE_TRUE(videoEncoder, nullptr);
+  }
+#endif  // MOZ_WEBM_ENCODER
+  else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() &&
+           aMIMEType.EqualsLiteral(AUDIO_OGG) &&
+           aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) {
+    writer = MakeUnique<OggWriter>();
+    audioEncoder = MakeAndAddRef<OpusTrackEncoder>(aTrackRate);
+    mimeType = NS_LITERAL_STRING(AUDIO_OGG);
+  }
+#ifdef MOZ_WEBM_ENCODER
+  else if (MediaEncoder::IsWebMEncoderEnabled() &&
+           (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK ||
+            !MediaDecoder::IsOggEnabled())) {
+    if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK &&
+        MediaDecoder::IsOpusEnabled()) {
+      audioEncoder = MakeAndAddRef<OpusTrackEncoder>(aTrackRate);
+    }
+    if (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK) {
+      if (Preferences::GetBool("media.recorder.video.frame_drops", true)) {
+        videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
+            driftCompensator, aTrackRate, FrameDroppingMode::ALLOW);
+      } else {
+        videoEncoder = MakeAndAddRef<VP8TrackEncoder>(
+            driftCompensator, aTrackRate, FrameDroppingMode::DISALLOW);
+      }
+    }
+    writer = MakeUnique<WebMWriter>(aTrackTypes);
     mimeType = NS_LITERAL_STRING(VIDEO_WEBM);
   }
 #endif  // MOZ_WEBM_ENCODER
   else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() &&
-           (aMIMEType.EqualsLiteral(AUDIO_OGG) ||
-            (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK))) {
+           aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) {
     writer = MakeUnique<OggWriter>();
     audioEncoder = MakeAndAddRef<OpusTrackEncoder>(aTrackRate);
-    NS_ENSURE_TRUE(writer, nullptr);
-    NS_ENSURE_TRUE(audioEncoder, nullptr);
     mimeType = NS_LITERAL_STRING(AUDIO_OGG);
   } else {
     LOG(LogLevel::Error,
         ("Can not find any encoder to record this media stream"));
     return nullptr;
   }
 
   LOG(LogLevel::Info,
-      ("Create encoder result:a[%p](%u bps) v[%p](%u bps) w[%p] mimeType = %s.",
+      ("Create encoder result:a[%p](%u bps) v[%p](%u bps) w[%p] mimeType = "
+       "%s.",
        audioEncoder.get(), aAudioBitrate, videoEncoder.get(), aVideoBitrate,
        writer.get(), NS_ConvertUTF16toUTF8(mimeType).get()));
 
   if (audioEncoder) {
     audioEncoder->SetWorkerThread(aEncoderThread);
     if (aAudioBitrate != 0) {
       audioEncoder->SetBitrate(aAudioBitrate);
     }
@@ -796,17 +840,18 @@ nsresult MediaEncoder::GetEncodedData(
     LOG(LogLevel::Verbose,
         ("Audio encoded TimeStamp = %f", GetEncodeTimeStamp()));
     if (NS_FAILED(rv)) {
       LOG(LogLevel::Warning, ("Failed to write encoded audio data to muxer"));
       return rv;
     }
   }
 
-  // In audio only or video only case, let unavailable track's flag to be true.
+  // In audio only or video only case, let unavailable track's flag to be
+  // true.
   bool isAudioCompleted = !mAudioEncoder || mAudioEncoder->IsEncodingComplete();
   bool isVideoCompleted = !mVideoEncoder || mVideoEncoder->IsEncodingComplete();
   rv = mWriter->GetContainerData(
       aOutputBufs,
       isAudioCompleted && isVideoCompleted ? ContainerWriter::FLUSH_NEEDED : 0);
   if (mWriter->IsWritingComplete()) {
     mCompleted = true;
     Shutdown();