Index: content/renderer/media/media_recorder_handler.cc |
diff --git a/content/renderer/media/media_recorder_handler.cc b/content/renderer/media/media_recorder_handler.cc |
index 7144af2f865b0577a58babb90cc7de40aead7b19..c260407494ac9455a5c2b8c3a51158c3e1a0574c 100644 |
--- a/content/renderer/media/media_recorder_handler.cc |
+++ b/content/renderer/media/media_recorder_handler.cc |
@@ -7,8 +7,13 @@ |
#include "base/bind.h" |
#include "base/location.h" |
#include "base/logging.h" |
+#include "base/strings/string_tokenizer.h" |
+#include "base/strings/string_util.h" |
+#include "content/renderer/media/audio_track_recorder.h" |
#include "content/renderer/media/video_track_recorder.h" |
#include "content/renderer/media/webrtc_uma_histograms.h" |
+#include "media/audio/audio_parameters.h" |
+#include "media/base/audio_bus.h" |
#include "media/base/bind_to_current_loop.h" |
#include "media/base/video_frame.h" |
#include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" |
@@ -27,9 +32,7 @@ MediaRecorderHandler::MediaRecorderHandler() |
: use_vp9_(false), |
recording_(false), |
client_(nullptr), |
- weak_factory_(this) { |
- DVLOG(3) << __FUNCTION__; |
-} |
+ weak_factory_(this) {} |
MediaRecorderHandler::~MediaRecorderHandler() { |
DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
@@ -41,9 +44,24 @@ MediaRecorderHandler::~MediaRecorderHandler() { |
bool MediaRecorderHandler::canSupportMimeType( |
const blink::WebString& mimeType) { |
DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
- // TODO(mcasas): So far only empty or "video/vp{8,9}" are supported. |
- return mimeType.isEmpty() || mimeType.utf8().compare("video/vp8") == 0 || |
- mimeType.utf8().compare("video/vp9") == 0; |
+ // Ensure we can support each passed MIME type. |
+ const std::string input = mimeType.utf8(); // Must outlive tokenizer! |
+ base::StringTokenizer tokenizer(input, ","); |
+ while (tokenizer.GetNext()) { |
+ // Strip whitespace. |
+ const std::string token(base::CollapseWhitespaceASCII( |
+ tokenizer.token(), true /* trim sequences with line breaks*/)); |
+ if (!token.empty() && |
+ !base::EqualsCaseInsensitiveASCII(token, "video/vp8") && |
+ !base::EqualsCaseInsensitiveASCII(token, "video/vp9") && |
+ !base::EqualsCaseInsensitiveASCII(token, "audio/opus") && |
+ !base::EqualsCaseInsensitiveASCII(token, "video/webm") && |
+ !base::EqualsCaseInsensitiveASCII(token, "audio/webm")) { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
} |
bool MediaRecorderHandler::initialize( |
@@ -82,44 +100,63 @@ bool MediaRecorderHandler::start(int timeslice) { |
timeslice_ = TimeDelta::FromMilliseconds(timeslice); |
slice_origin_timestamp_ = TimeTicks::Now(); |
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks; |
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks, audio_tracks; |
media_stream_.videoTracks(video_tracks); |
+ media_stream_.audioTracks(audio_tracks); |
-#if !defined(MEDIA_DISABLE_LIBWEBM) |
- DCHECK(!webm_muxer_); |
- |
- webm_muxer_.reset(new media::WebmMuxer( |
- use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, video_tracks.size() > 0, |
- false /* no audio for now - http://crbug.com/528519 */, |
- base::Bind(&MediaRecorderHandler::WriteData, |
- weak_factory_.GetWeakPtr()))); |
-#else |
+#if defined(MEDIA_DISABLE_LIBWEBM) |
LOG(WARNING) << "No muxer available"; |
return false; |
#endif |
- if (video_tracks.isEmpty()) { |
- // TODO(mcasas): Add audio_tracks and update the code in this function |
- // correspondingly, see http://crbug.com/528519. As of now, only video |
- // tracks are supported. |
- LOG(WARNING) << "Recording no video tracks is not implemented"; |
+ DCHECK(!webm_muxer_); |
+ |
+ if (video_tracks.isEmpty() && audio_tracks.isEmpty()) { |
+ LOG(WARNING) << __FUNCTION__ << ": no media tracks."; |
return false; |
} |
- // TODO(mcasas): The muxer API supports only one video track. Extend it to |
- // several video tracks, see http://crbug.com/528523. |
- LOG_IF(WARNING, video_tracks.size() > 1u) << "Recording multiple video" |
- << " tracks is not implemented. Only recording first video track."; |
- const blink::WebMediaStreamTrack& video_track = video_tracks[0]; |
- if (video_track.isNull()) |
- return false; |
- const VideoTrackRecorder::OnEncodedVideoCB on_encoded_video_cb = |
- media::BindToCurrentLoop(base::Bind(&MediaRecorderHandler::OnEncodedVideo, |
- weak_factory_.GetWeakPtr())); |
+ webm_muxer_.reset(new media::WebmMuxer( |
+ use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, |
+ video_tracks.size() > 0, audio_tracks.size() > 0, |
+ base::Bind(&MediaRecorderHandler::WriteData, |
+ weak_factory_.GetWeakPtr()))); |
- video_recorders_.push_back(new VideoTrackRecorder(use_vp9_, |
- video_track, |
- on_encoded_video_cb)); |
+ if (!video_tracks.isEmpty()) { |
+ // TODO(mcasas): The muxer API supports only one video track. Extend it to |
+ // several video tracks, see http://crbug.com/528523. |
+ LOG_IF(WARNING, video_tracks.size() > 1u) |
+ << "Recording multiple video tracks is not implemented. " |
+ << "Only recording first video track."; |
+ const blink::WebMediaStreamTrack& video_track = video_tracks[0]; |
+ if (video_track.isNull()) |
+ return false; |
+ |
+ const VideoTrackRecorder::OnEncodedVideoCB on_encoded_video_cb = |
+ media::BindToCurrentLoop(base::Bind( |
+ &MediaRecorderHandler::OnEncodedVideo, weak_factory_.GetWeakPtr())); |
+ |
+ video_recorders_.push_back( |
+ new VideoTrackRecorder(use_vp9_, video_track, on_encoded_video_cb)); |
+ } |
+ |
+ if (!audio_tracks.isEmpty()) { |
+ // TODO(ajose): The muxer API supports only one audio track. Extend it to |
+ // several tracks. |
+ LOG_IF(WARNING, audio_tracks.size() > 1u) |
+ << "Recording multiple audio" |
+ << " tracks is not implemented. Only recording first audio track."; |
+ const blink::WebMediaStreamTrack& audio_track = audio_tracks[0]; |
+ if (audio_track.isNull()) |
+ return false; |
+ |
+ const AudioTrackRecorder::OnEncodedAudioCB on_encoded_audio_cb = |
+ media::BindToCurrentLoop(base::Bind( |
+ &MediaRecorderHandler::OnEncodedAudio, weak_factory_.GetWeakPtr())); |
+ |
+ audio_recorders_.push_back( |
+ new AudioTrackRecorder(audio_track, on_encoded_audio_cb)); |
+ } |
recording_ = true; |
return true; |
@@ -132,6 +169,7 @@ void MediaRecorderHandler::stop() { |
recording_ = false; |
timeslice_ = TimeDelta::FromMilliseconds(0); |
video_recorders_.clear(); |
+ audio_recorders_.clear(); |
#if !defined(MEDIA_DISABLE_LIBWEBM) |
webm_muxer_.reset(); |
#endif |
@@ -167,6 +205,14 @@ void MediaRecorderHandler::OnEncodedVideo( |
#endif |
} |
+void MediaRecorderHandler::OnEncodedAudio(const media::AudioParameters& params, |
+ scoped_ptr<std::string> encoded_data, |
+ base::TimeTicks timestamp) { |
+ DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
+ if (webm_muxer_) |
+ webm_muxer_->OnEncodedAudio(params, encoded_data.Pass(), timestamp); |
+} |
+ |
void MediaRecorderHandler::WriteData(base::StringPiece data) { |
DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
@@ -191,4 +237,17 @@ void MediaRecorderHandler::OnVideoFrameForTesting( |
recorder->OnVideoFrameForTesting(frame, timestamp); |
} |
+void MediaRecorderHandler::OnAudioBusForTesting( |
+ const media::AudioBus& audio_bus, |
+ const base::TimeTicks& timestamp) { |
+ for (auto* recorder : audio_recorders_) |
+ recorder->OnData(audio_bus, timestamp); |
+} |
+ |
+void MediaRecorderHandler::SetAudioFormatForTesting( |
+ const media::AudioParameters& params) { |
+ for (auto* recorder : audio_recorders_) |
+ recorder->OnSetFormat(params); |
+} |
+ |
} // namespace content |