Chromium Code Reviews| 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..557608738acd17ba72b76901cf98756674f9a350 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() && |
| + token.compare("video/vp8") != 0 && |
|
mcasas
2015/11/19 22:44:00
what about
if (base::EqualsCaseInsensitiveASCII(to
ajose
2015/11/19 22:59:01
But what if another one of the tokens is unsupport
|
| + token.compare("video/vp9") != 0 && |
| + token.compare("audio/opus") != 0 && |
| + token.compare("video/webm") != 0 && |
| + token.compare("audio/webm") != 0) { |
| + 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 |