| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/media_recorder_handler.h" | 5 #include "content/renderer/media/media_recorder_handler.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "media/capture/webm_muxer.h" | 25 #include "media/capture/webm_muxer.h" |
| 26 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" | 26 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" |
| 27 #include "third_party/WebKit/public/platform/WebString.h" | 27 #include "third_party/WebKit/public/platform/WebString.h" |
| 28 | 28 |
| 29 using base::TimeDelta; | 29 using base::TimeDelta; |
| 30 using base::TimeTicks; | 30 using base::TimeTicks; |
| 31 | 31 |
| 32 namespace content { | 32 namespace content { |
| 33 | 33 |
| 34 MediaRecorderHandler::MediaRecorderHandler() | 34 MediaRecorderHandler::MediaRecorderHandler() |
| 35 : use_vp9_(false), | 35 : video_bits_per_second_(0), |
| 36 audio_bits_per_second_(0), |
| 37 use_vp9_(false), |
| 36 recording_(false), | 38 recording_(false), |
| 37 client_(nullptr), | 39 client_(nullptr), |
| 38 weak_factory_(this) {} | 40 weak_factory_(this) {} |
| 39 | 41 |
| 40 MediaRecorderHandler::~MediaRecorderHandler() { | 42 MediaRecorderHandler::~MediaRecorderHandler() { |
| 41 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 43 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 42 // Send a |last_in_slice| to our |client_|. | 44 // Send a |last_in_slice| to our |client_|. |
| 43 if (client_) | 45 if (client_) |
| 44 client_->writeData(nullptr, 0u, true); | 46 client_->writeData(nullptr, 0u, true); |
| 45 } | 47 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 if (found == &codecs[codecs_count]) | 79 if (found == &codecs[codecs_count]) |
| 78 return false; | 80 return false; |
| 79 } | 81 } |
| 80 return true; | 82 return true; |
| 81 } | 83 } |
| 82 | 84 |
| 83 bool MediaRecorderHandler::initialize( | 85 bool MediaRecorderHandler::initialize( |
| 84 blink::WebMediaRecorderHandlerClient* client, | 86 blink::WebMediaRecorderHandlerClient* client, |
| 85 const blink::WebMediaStream& media_stream, | 87 const blink::WebMediaStream& media_stream, |
| 86 const blink::WebString& type, | 88 const blink::WebString& type, |
| 87 const blink::WebString& codecs) { | 89 const blink::WebString& codecs, |
| 90 int32_t audio_bits_per_second, |
| 91 int32_t video_bits_per_second) { |
| 88 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 92 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 89 // Save histogram data so we can see how much MediaStream Recorder is used. | 93 // Save histogram data so we can see how much MediaStream Recorder is used. |
| 90 // The histogram counts the number of calls to the JS API. | 94 // The histogram counts the number of calls to the JS API. |
| 91 UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER); | 95 UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER); |
| 92 | 96 |
| 93 if (!canSupportMimeType(type, codecs)) { | 97 if (!canSupportMimeType(type, codecs)) { |
| 94 DLOG(ERROR) << "Can't support " << type.utf8() | 98 DLOG(ERROR) << "Can't support " << type.utf8() |
| 95 << ";codecs=" << codecs.utf8(); | 99 << ";codecs=" << codecs.utf8(); |
| 96 return false; | 100 return false; |
| 97 } | 101 } |
| 98 use_vp9_ = base::ToLowerASCII(codecs.utf8()).find("vp9") != std::string::npos; | 102 use_vp9_ = base::ToLowerASCII(codecs.utf8()).find("vp9") != std::string::npos; |
| 99 media_stream_ = media_stream; | 103 media_stream_ = media_stream; |
| 100 DCHECK(client); | 104 DCHECK(client); |
| 101 client_ = client; | 105 client_ = client; |
| 102 | 106 |
| 107 audio_bits_per_second_ = audio_bits_per_second; |
| 108 video_bits_per_second_ = video_bits_per_second; |
| 103 return true; | 109 return true; |
| 104 } | 110 } |
| 105 | 111 |
| 106 bool MediaRecorderHandler::start() { | 112 bool MediaRecorderHandler::start() { |
| 107 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 113 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 108 DCHECK(!recording_); | 114 DCHECK(!recording_); |
| 109 return start(0); | 115 return start(0); |
| 110 } | 116 } |
| 111 | 117 |
| 112 bool MediaRecorderHandler::start(int timeslice) { | 118 bool MediaRecorderHandler::start(int timeslice) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 << "Recording multiple video tracks is not implemented. " | 151 << "Recording multiple video tracks is not implemented. " |
| 146 << "Only recording first video track."; | 152 << "Only recording first video track."; |
| 147 const blink::WebMediaStreamTrack& video_track = video_tracks[0]; | 153 const blink::WebMediaStreamTrack& video_track = video_tracks[0]; |
| 148 if (video_track.isNull()) | 154 if (video_track.isNull()) |
| 149 return false; | 155 return false; |
| 150 | 156 |
| 151 const VideoTrackRecorder::OnEncodedVideoCB on_encoded_video_cb = | 157 const VideoTrackRecorder::OnEncodedVideoCB on_encoded_video_cb = |
| 152 media::BindToCurrentLoop(base::Bind( | 158 media::BindToCurrentLoop(base::Bind( |
| 153 &MediaRecorderHandler::OnEncodedVideo, weak_factory_.GetWeakPtr())); | 159 &MediaRecorderHandler::OnEncodedVideo, weak_factory_.GetWeakPtr())); |
| 154 | 160 |
| 155 video_recorders_.push_back( | 161 video_recorders_.push_back(new VideoTrackRecorder( |
| 156 new VideoTrackRecorder(use_vp9_, video_track, on_encoded_video_cb)); | 162 use_vp9_, video_track, on_encoded_video_cb, video_bits_per_second_)); |
| 157 } | 163 } |
| 158 | 164 |
| 159 if (use_audio_tracks) { | 165 if (use_audio_tracks) { |
| 160 // TODO(ajose): The muxer API supports only one audio track. Extend it to | 166 // TODO(ajose): The muxer API supports only one audio track. Extend it to |
| 161 // several tracks. | 167 // several tracks. |
| 162 LOG_IF(WARNING, audio_tracks.size() > 1u) | 168 LOG_IF(WARNING, audio_tracks.size() > 1u) |
| 163 << "Recording multiple audio" | 169 << "Recording multiple audio" |
| 164 << " tracks is not implemented. Only recording first audio track."; | 170 << " tracks is not implemented. Only recording first audio track."; |
| 165 const blink::WebMediaStreamTrack& audio_track = audio_tracks[0]; | 171 const blink::WebMediaStreamTrack& audio_track = audio_tracks[0]; |
| 166 if (audio_track.isNull()) | 172 if (audio_track.isNull()) |
| 167 return false; | 173 return false; |
| 168 | 174 |
| 169 const AudioTrackRecorder::OnEncodedAudioCB on_encoded_audio_cb = | 175 const AudioTrackRecorder::OnEncodedAudioCB on_encoded_audio_cb = |
| 170 media::BindToCurrentLoop(base::Bind( | 176 media::BindToCurrentLoop(base::Bind( |
| 171 &MediaRecorderHandler::OnEncodedAudio, weak_factory_.GetWeakPtr())); | 177 &MediaRecorderHandler::OnEncodedAudio, weak_factory_.GetWeakPtr())); |
| 172 | 178 |
| 173 audio_recorders_.push_back( | 179 audio_recorders_.push_back(new AudioTrackRecorder( |
| 174 new AudioTrackRecorder(audio_track, on_encoded_audio_cb)); | 180 audio_track, on_encoded_audio_cb, audio_bits_per_second_)); |
| 175 } | 181 } |
| 176 | 182 |
| 177 recording_ = true; | 183 recording_ = true; |
| 178 return true; | 184 return true; |
| 179 } | 185 } |
| 180 | 186 |
| 181 void MediaRecorderHandler::stop() { | 187 void MediaRecorderHandler::stop() { |
| 182 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 188 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 183 // Don't check |recording_| since we can go directly from pause() to stop(). | 189 // Don't check |recording_| since we can go directly from pause() to stop(). |
| 184 | 190 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 void MediaRecorderHandler::OnEncodedAudio(const media::AudioParameters& params, | 226 void MediaRecorderHandler::OnEncodedAudio(const media::AudioParameters& params, |
| 221 scoped_ptr<std::string> encoded_data, | 227 scoped_ptr<std::string> encoded_data, |
| 222 base::TimeTicks timestamp) { | 228 base::TimeTicks timestamp) { |
| 223 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 229 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 224 if (webm_muxer_) | 230 if (webm_muxer_) |
| 225 webm_muxer_->OnEncodedAudio(params, std::move(encoded_data), timestamp); | 231 webm_muxer_->OnEncodedAudio(params, std::move(encoded_data), timestamp); |
| 226 } | 232 } |
| 227 | 233 |
| 228 void MediaRecorderHandler::WriteData(base::StringPiece data) { | 234 void MediaRecorderHandler::WriteData(base::StringPiece data) { |
| 229 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 235 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 230 | |
| 231 // Non-buffered mode does not need to check timestamps. | 236 // Non-buffered mode does not need to check timestamps. |
| 232 if (timeslice_.is_zero()) { | 237 if (timeslice_.is_zero()) { |
| 233 client_->writeData(data.data(), data.length(), true /* lastInSlice */); | 238 client_->writeData(data.data(), data.length(), true /* lastInSlice */); |
| 234 return; | 239 return; |
| 235 } | 240 } |
| 236 | 241 |
| 237 const TimeTicks now = TimeTicks::Now(); | 242 const TimeTicks now = TimeTicks::Now(); |
| 238 const bool last_in_slice = now > slice_origin_timestamp_ + timeslice_; | 243 const bool last_in_slice = now > slice_origin_timestamp_ + timeslice_; |
| 239 DVLOG_IF(1, last_in_slice) << "Slice finished @ " << now; | 244 DVLOG_IF(1, last_in_slice) << "Slice finished @ " << now; |
| 240 if (last_in_slice) | 245 if (last_in_slice) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 256 recorder->OnData(audio_bus, timestamp); | 261 recorder->OnData(audio_bus, timestamp); |
| 257 } | 262 } |
| 258 | 263 |
| 259 void MediaRecorderHandler::SetAudioFormatForTesting( | 264 void MediaRecorderHandler::SetAudioFormatForTesting( |
| 260 const media::AudioParameters& params) { | 265 const media::AudioParameters& params) { |
| 261 for (auto* recorder : audio_recorders_) | 266 for (auto* recorder : audio_recorders_) |
| 262 recorder->OnSetFormat(params); | 267 recorder->OnSetFormat(params); |
| 263 } | 268 } |
| 264 | 269 |
| 265 } // namespace content | 270 } // namespace content |
| OLD | NEW |