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 |