| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "content/renderer/media/video_track_recorder.h" | 10 #include "content/renderer/media/video_track_recorder.h" |
| 11 #include "content/renderer/media/webrtc_uma_histograms.h" | 11 #include "content/renderer/media/webrtc_uma_histograms.h" |
| 12 #include "media/base/bind_to_current_loop.h" | 12 #include "media/base/bind_to_current_loop.h" |
| 13 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
| 14 #include "media/capture/webm_muxer.h" | |
| 15 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" | 14 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" |
| 16 #include "third_party/WebKit/public/platform/WebString.h" | 15 #include "third_party/WebKit/public/platform/WebString.h" |
| 17 | 16 |
| 17 #if !defined(MEDIA_DISABLE_LIBWEBM) |
| 18 #include "media/capture/webm_muxer.h" |
| 19 #endif |
| 20 |
| 18 using base::TimeDelta; | 21 using base::TimeDelta; |
| 19 using base::TimeTicks; | 22 using base::TimeTicks; |
| 20 | 23 |
| 21 namespace content { | 24 namespace content { |
| 22 | 25 |
| 23 MediaRecorderHandler::MediaRecorderHandler() | 26 MediaRecorderHandler::MediaRecorderHandler() |
| 24 : use_vp9_(false), | 27 : use_vp9_(false), |
| 25 recording_(false), | 28 recording_(false), |
| 26 client_(nullptr), | 29 client_(nullptr), |
| 27 weak_factory_(this) { | 30 weak_factory_(this) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 bool MediaRecorderHandler::start() { | 70 bool MediaRecorderHandler::start() { |
| 68 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 71 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 69 DCHECK(!recording_); | 72 DCHECK(!recording_); |
| 70 return start(0); | 73 return start(0); |
| 71 } | 74 } |
| 72 | 75 |
| 73 bool MediaRecorderHandler::start(int timeslice) { | 76 bool MediaRecorderHandler::start(int timeslice) { |
| 74 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 77 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 75 DCHECK(!recording_); | 78 DCHECK(!recording_); |
| 76 DCHECK(!media_stream_.isNull()); | 79 DCHECK(!media_stream_.isNull()); |
| 77 DCHECK(!webm_muxer_); | |
| 78 DCHECK(timeslice_.is_zero()); | 80 DCHECK(timeslice_.is_zero()); |
| 79 | 81 |
| 80 timeslice_ = TimeDelta::FromMilliseconds(timeslice); | 82 timeslice_ = TimeDelta::FromMilliseconds(timeslice); |
| 81 slice_origin_timestamp_ = TimeTicks::Now(); | 83 slice_origin_timestamp_ = TimeTicks::Now(); |
| 82 | 84 |
| 83 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; | 85 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; |
| 84 media_stream_.videoTracks(video_tracks); | 86 media_stream_.videoTracks(video_tracks); |
| 85 | 87 |
| 88 #if !defined(MEDIA_DISABLE_LIBWEBM) |
| 89 DCHECK(!webm_muxer_); |
| 90 |
| 86 webm_muxer_.reset(new media::WebmMuxer( | 91 webm_muxer_.reset(new media::WebmMuxer( |
| 87 use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, video_tracks.size() > 0, | 92 use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, video_tracks.size() > 0, |
| 88 false /* no audio for now - http://crbug.com/528519 */, | 93 false /* no audio for now - http://crbug.com/528519 */, |
| 89 base::Bind(&MediaRecorderHandler::WriteData, | 94 base::Bind(&MediaRecorderHandler::WriteData, |
| 90 weak_factory_.GetWeakPtr()))); | 95 weak_factory_.GetWeakPtr()))); |
| 96 #else |
| 97 LOG(WARNING) << "No muxer available"; |
| 98 return false; |
| 99 #endif |
| 91 | 100 |
| 92 if (video_tracks.isEmpty()) { | 101 if (video_tracks.isEmpty()) { |
| 93 // TODO(mcasas): Add audio_tracks and update the code in this function | 102 // TODO(mcasas): Add audio_tracks and update the code in this function |
| 94 // correspondingly, see http://crbug.com/528519. As of now, only video | 103 // correspondingly, see http://crbug.com/528519. As of now, only video |
| 95 // tracks are supported. | 104 // tracks are supported. |
| 96 LOG(WARNING) << "Recording no video tracks is not implemented"; | 105 LOG(WARNING) << "Recording no video tracks is not implemented"; |
| 97 return false; | 106 return false; |
| 98 } | 107 } |
| 99 // TODO(mcasas): The muxer API supports only one video track. Extend it to | 108 // TODO(mcasas): The muxer API supports only one video track. Extend it to |
| 100 // several video tracks, see http://crbug.com/528523. | 109 // several video tracks, see http://crbug.com/528523. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 116 return true; | 125 return true; |
| 117 } | 126 } |
| 118 | 127 |
| 119 void MediaRecorderHandler::stop() { | 128 void MediaRecorderHandler::stop() { |
| 120 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 129 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 121 DCHECK(recording_); | 130 DCHECK(recording_); |
| 122 | 131 |
| 123 recording_ = false; | 132 recording_ = false; |
| 124 timeslice_ = TimeDelta::FromMilliseconds(0); | 133 timeslice_ = TimeDelta::FromMilliseconds(0); |
| 125 video_recorders_.clear(); | 134 video_recorders_.clear(); |
| 135 #if !defined(MEDIA_DISABLE_LIBWEBM) |
| 126 webm_muxer_.reset(); | 136 webm_muxer_.reset(); |
| 137 #endif |
| 127 } | 138 } |
| 128 | 139 |
| 129 void MediaRecorderHandler::pause() { | 140 void MediaRecorderHandler::pause() { |
| 130 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 141 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 131 DCHECK(recording_); | 142 DCHECK(recording_); |
| 132 recording_ = false; | 143 recording_ = false; |
| 133 for (const auto& video_recorder : video_recorders_) | 144 for (const auto& video_recorder : video_recorders_) |
| 134 video_recorder->Pause(); | 145 video_recorder->Pause(); |
| 135 } | 146 } |
| 136 | 147 |
| 137 void MediaRecorderHandler::resume() { | 148 void MediaRecorderHandler::resume() { |
| 138 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 149 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 139 DCHECK(!recording_); | 150 DCHECK(!recording_); |
| 140 recording_ = true; | 151 recording_ = true; |
| 141 for (const auto& video_recorder : video_recorders_) | 152 for (const auto& video_recorder : video_recorders_) |
| 142 video_recorder->Resume(); | 153 video_recorder->Resume(); |
| 143 } | 154 } |
| 144 | 155 |
| 145 void MediaRecorderHandler::OnEncodedVideo( | 156 void MediaRecorderHandler::OnEncodedVideo( |
| 146 const scoped_refptr<media::VideoFrame>& video_frame, | 157 const scoped_refptr<media::VideoFrame>& video_frame, |
| 147 scoped_ptr<std::string> encoded_data, | 158 scoped_ptr<std::string> encoded_data, |
| 148 TimeTicks timestamp, | 159 TimeTicks timestamp, |
| 149 bool is_key_frame) { | 160 bool is_key_frame) { |
| 150 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 161 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 162 #if !defined(MEDIA_DISABLE_LIBWEBM) |
| 151 if (!webm_muxer_) | 163 if (!webm_muxer_) |
| 152 return; | 164 return; |
| 153 webm_muxer_->OnEncodedVideo(video_frame, encoded_data.Pass(), timestamp, | 165 webm_muxer_->OnEncodedVideo(video_frame, encoded_data.Pass(), timestamp, |
| 154 is_key_frame); | 166 is_key_frame); |
| 167 #endif |
| 155 } | 168 } |
| 156 | 169 |
| 157 void MediaRecorderHandler::WriteData(base::StringPiece data) { | 170 void MediaRecorderHandler::WriteData(base::StringPiece data) { |
| 158 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 171 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 159 | 172 |
| 160 // Non-buffered mode does not need to check timestamps. | 173 // Non-buffered mode does not need to check timestamps. |
| 161 if (timeslice_.is_zero()) { | 174 if (timeslice_.is_zero()) { |
| 162 client_->writeData(data.data(), data.length(), true /* lastInSlice */); | 175 client_->writeData(data.data(), data.length(), true /* lastInSlice */); |
| 163 return; | 176 return; |
| 164 } | 177 } |
| 165 | 178 |
| 166 const TimeTicks now = TimeTicks::Now(); | 179 const TimeTicks now = TimeTicks::Now(); |
| 167 const bool last_in_slice = now > slice_origin_timestamp_ + timeslice_; | 180 const bool last_in_slice = now > slice_origin_timestamp_ + timeslice_; |
| 168 DVLOG_IF(1, last_in_slice) << "Slice finished @ " << now; | 181 DVLOG_IF(1, last_in_slice) << "Slice finished @ " << now; |
| 169 if (last_in_slice) | 182 if (last_in_slice) |
| 170 slice_origin_timestamp_ = now; | 183 slice_origin_timestamp_ = now; |
| 171 client_->writeData(data.data(), data.length(), last_in_slice); | 184 client_->writeData(data.data(), data.length(), last_in_slice); |
| 172 } | 185 } |
| 173 | 186 |
| 174 void MediaRecorderHandler::OnVideoFrameForTesting( | 187 void MediaRecorderHandler::OnVideoFrameForTesting( |
| 175 const scoped_refptr<media::VideoFrame>& frame, | 188 const scoped_refptr<media::VideoFrame>& frame, |
| 176 const TimeTicks& timestamp) { | 189 const TimeTicks& timestamp) { |
| 177 for (auto* recorder : video_recorders_) | 190 for (auto* recorder : video_recorders_) |
| 178 recorder->OnVideoFrameForTesting(frame, timestamp); | 191 recorder->OnVideoFrameForTesting(frame, timestamp); |
| 179 } | 192 } |
| 180 | 193 |
| 181 } // namespace content | 194 } // namespace content |
| OLD | NEW |