| 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 "media/muxers/webm_muxer.h" | 5 #include "media/muxers/webm_muxer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "media/audio/audio_parameters.h" | 8 #include "media/audio/audio_parameters.h" |
| 9 #include "media/base/limits.h" | 9 #include "media/base/limits.h" |
| 10 #include "media/base/video_frame.h" | 10 #include "media/base/video_frame.h" |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 encoded_frames_queue_.pop_front(); | 140 encoded_frames_queue_.pop_front(); |
| 141 } | 141 } |
| 142 | 142 |
| 143 AddFrame(std::move(encoded_data), video_track_index_, timestamp, | 143 AddFrame(std::move(encoded_data), video_track_index_, timestamp, |
| 144 is_key_frame); | 144 is_key_frame); |
| 145 } | 145 } |
| 146 | 146 |
| 147 void WebmMuxer::OnEncodedAudio(const media::AudioParameters& params, | 147 void WebmMuxer::OnEncodedAudio(const media::AudioParameters& params, |
| 148 scoped_ptr<std::string> encoded_data, | 148 scoped_ptr<std::string> encoded_data, |
| 149 base::TimeTicks timestamp) { | 149 base::TimeTicks timestamp) { |
| 150 DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B"; | 150 DVLOG(2) << __FUNCTION__ << " - " << encoded_data->size() << "B"; |
| 151 DCHECK(thread_checker_.CalledOnValidThread()); | 151 DCHECK(thread_checker_.CalledOnValidThread()); |
| 152 | 152 |
| 153 if (!audio_track_index_) { | 153 if (!audio_track_index_) { |
| 154 AddAudioTrack(params); | 154 AddAudioTrack(params); |
| 155 if (first_frame_timestamp_.is_null()) | 155 if (first_frame_timestamp_.is_null()) |
| 156 first_frame_timestamp_ = timestamp; | 156 first_frame_timestamp_ = timestamp; |
| 157 } | 157 } |
| 158 | 158 |
| 159 // TODO(ajose): Don't drop audio data: http://crbug.com/547948 | 159 // TODO(ajose): Don't drop audio data: http://crbug.com/547948 |
| 160 // TODO(ajose): Support multiple tracks: http://crbug.com/528523 | 160 // TODO(ajose): Support multiple tracks: http://crbug.com/528523 |
| 161 if (has_video_ && !video_track_index_) { | 161 if (has_video_ && !video_track_index_) { |
| 162 DVLOG(1) << __FUNCTION__ << ": delaying until video track ready."; | 162 DVLOG(1) << __FUNCTION__ << ": delaying until video track ready."; |
| 163 return; | 163 return; |
| 164 } | 164 } |
| 165 | 165 |
| 166 // Dump all saved encoded video frames if any. | 166 // Dump all saved encoded video frames if any. |
| 167 while (!encoded_frames_queue_.empty()) { | 167 while (!encoded_frames_queue_.empty()) { |
| 168 AddFrame(std::move(encoded_frames_queue_.front()->data), video_track_index_, | 168 AddFrame(std::move(encoded_frames_queue_.front()->data), video_track_index_, |
| 169 encoded_frames_queue_.front()->timestamp, | 169 encoded_frames_queue_.front()->timestamp, |
| 170 encoded_frames_queue_.front()->is_keyframe); | 170 encoded_frames_queue_.front()->is_keyframe); |
| 171 encoded_frames_queue_.pop_front(); | 171 encoded_frames_queue_.pop_front(); |
| 172 } | 172 } |
| 173 | 173 |
| 174 AddFrame(std::move(encoded_data), audio_track_index_, timestamp, | 174 AddFrame(std::move(encoded_data), audio_track_index_, timestamp, |
| 175 true /* is_key_frame -- always true for audio */); | 175 true /* is_key_frame -- always true for audio */); |
| 176 } | 176 } |
| 177 | 177 |
| 178 void WebmMuxer::Pause() { |
| 179 DVLOG(1) << __FUNCTION__; |
| 180 DCHECK(thread_checker_.CalledOnValidThread()); |
| 181 if (!elapsed_time_in_pause_) |
| 182 elapsed_time_in_pause_.reset(new base::ElapsedTimer()); |
| 183 } |
| 184 |
| 185 void WebmMuxer::Resume() { |
| 186 DVLOG(1) << __FUNCTION__; |
| 187 DCHECK(thread_checker_.CalledOnValidThread()); |
| 188 if (elapsed_time_in_pause_) { |
| 189 total_time_in_pause_ += elapsed_time_in_pause_->Elapsed(); |
| 190 elapsed_time_in_pause_.reset(); |
| 191 } |
| 192 } |
| 193 |
| 178 void WebmMuxer::AddVideoTrack(const gfx::Size& frame_size, double frame_rate) { | 194 void WebmMuxer::AddVideoTrack(const gfx::Size& frame_size, double frame_rate) { |
| 179 DCHECK(thread_checker_.CalledOnValidThread()); | 195 DCHECK(thread_checker_.CalledOnValidThread()); |
| 180 DCHECK_EQ(0u, video_track_index_) | 196 DCHECK_EQ(0u, video_track_index_) |
| 181 << "WebmMuxer can only be initialized once."; | 197 << "WebmMuxer can only be initialized once."; |
| 182 | 198 |
| 183 video_track_index_ = | 199 video_track_index_ = |
| 184 segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0); | 200 segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0); |
| 185 DCHECK_GT(video_track_index_, 0u); | 201 DCHECK_GT(video_track_index_, 0u); |
| 186 | 202 |
| 187 mkvmuxer::VideoTrack* const video_track = | 203 mkvmuxer::VideoTrack* const video_track = |
| 188 reinterpret_cast<mkvmuxer::VideoTrack*>( | 204 reinterpret_cast<mkvmuxer::VideoTrack*>( |
| 189 segment_.GetTrackByNumber(video_track_index_)); | 205 segment_.GetTrackByNumber(video_track_index_)); |
| 190 DCHECK(video_track); | 206 DCHECK(video_track); |
| 191 video_track->set_codec_id(use_vp9_ ? mkvmuxer::Tracks::kVp9CodecId | 207 video_track->set_codec_id(use_vp9_ ? mkvmuxer::Tracks::kVp9CodecId |
| 192 : mkvmuxer::Tracks::kVp8CodecId); | 208 : mkvmuxer::Tracks::kVp8CodecId); |
| 193 DCHECK_EQ(0ull, video_track->crop_right()); | 209 DCHECK_EQ(0ull, video_track->crop_right()); |
| 194 DCHECK_EQ(0ull, video_track->crop_left()); | 210 DCHECK_EQ(0ull, video_track->crop_left()); |
| 195 DCHECK_EQ(0ull, video_track->crop_top()); | 211 DCHECK_EQ(0ull, video_track->crop_top()); |
| 196 DCHECK_EQ(0ull, video_track->crop_bottom()); | 212 DCHECK_EQ(0ull, video_track->crop_bottom()); |
| 197 | 213 |
| 198 video_track->set_frame_rate(frame_rate); | 214 video_track->set_frame_rate(frame_rate); |
| 199 video_track->set_default_duration(base::Time::kNanosecondsPerSecond / | 215 video_track->set_default_duration(base::Time::kNanosecondsPerSecond / |
| 200 frame_rate); | 216 frame_rate); |
| 201 // Segment's timestamps should be in milliseconds, DCHECK it. See | 217 // Segment's timestamps should be in milliseconds, DCHECK it. See |
| 202 // http://www.webmproject.org/docs/container/#muxer-guidelines | 218 // http://www.webmproject.org/docs/container/#muxer-guidelines |
| 203 DCHECK_EQ(1000000ull, segment_.GetSegmentInfo()->timecode_scale()); | 219 DCHECK_EQ(1000000ull, segment_.GetSegmentInfo()->timecode_scale()); |
| 204 } | 220 } |
| 205 | 221 |
| 206 void WebmMuxer::AddAudioTrack(const media::AudioParameters& params) { | 222 void WebmMuxer::AddAudioTrack(const media::AudioParameters& params) { |
| 223 DVLOG(1) << __FUNCTION__ << " " << params.AsHumanReadableString(); |
| 207 DCHECK(thread_checker_.CalledOnValidThread()); | 224 DCHECK(thread_checker_.CalledOnValidThread()); |
| 208 DCHECK_EQ(0u, audio_track_index_) | 225 DCHECK_EQ(0u, audio_track_index_) |
| 209 << "WebmMuxer audio can only be initialised once."; | 226 << "WebmMuxer audio can only be initialised once."; |
| 210 | 227 |
| 211 audio_track_index_ = | 228 audio_track_index_ = |
| 212 segment_.AddAudioTrack(params.sample_rate(), params.channels(), 0); | 229 segment_.AddAudioTrack(params.sample_rate(), params.channels(), 0); |
| 213 DCHECK_GT(audio_track_index_, 0u); | 230 DCHECK_GT(audio_track_index_, 0u); |
| 214 | 231 |
| 215 mkvmuxer::AudioTrack* const audio_track = | 232 mkvmuxer::AudioTrack* const audio_track = |
| 216 reinterpret_cast<mkvmuxer::AudioTrack*>( | 233 reinterpret_cast<mkvmuxer::AudioTrack*>( |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 280 |
| 264 void WebmMuxer::AddFrame(scoped_ptr<std::string> encoded_data, | 281 void WebmMuxer::AddFrame(scoped_ptr<std::string> encoded_data, |
| 265 uint8_t track_index, | 282 uint8_t track_index, |
| 266 base::TimeTicks timestamp, | 283 base::TimeTicks timestamp, |
| 267 bool is_key_frame) { | 284 bool is_key_frame) { |
| 268 DCHECK(thread_checker_.CalledOnValidThread()); | 285 DCHECK(thread_checker_.CalledOnValidThread()); |
| 269 DCHECK(!has_video_ || video_track_index_); | 286 DCHECK(!has_video_ || video_track_index_); |
| 270 DCHECK(!has_audio_ || audio_track_index_); | 287 DCHECK(!has_audio_ || audio_track_index_); |
| 271 | 288 |
| 272 most_recent_timestamp_ = | 289 most_recent_timestamp_ = |
| 273 std::max(most_recent_timestamp_, timestamp - first_frame_timestamp_); | 290 std::max(most_recent_timestamp_, |
| 291 timestamp - total_time_in_pause_ - first_frame_timestamp_); |
| 274 | 292 |
| 275 segment_.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data->data()), | 293 segment_.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data->data()), |
| 276 encoded_data->size(), track_index, | 294 encoded_data->size(), track_index, |
| 277 most_recent_timestamp_.InMicroseconds() * | 295 most_recent_timestamp_.InMicroseconds() * |
| 278 base::Time::kNanosecondsPerMicrosecond, | 296 base::Time::kNanosecondsPerMicrosecond, |
| 279 is_key_frame); | 297 is_key_frame); |
| 280 } | 298 } |
| 281 | 299 |
| 282 WebmMuxer::EncodedVideoFrame::EncodedVideoFrame(scoped_ptr<std::string> data, | 300 WebmMuxer::EncodedVideoFrame::EncodedVideoFrame(scoped_ptr<std::string> data, |
| 283 base::TimeTicks timestamp, | 301 base::TimeTicks timestamp, |
| 284 bool is_keyframe) | 302 bool is_keyframe) |
| 285 : data(std::move(data)), timestamp(timestamp), is_keyframe(is_keyframe) {} | 303 : data(std::move(data)), timestamp(timestamp), is_keyframe(is_keyframe) {} |
| 286 | 304 |
| 287 WebmMuxer::EncodedVideoFrame::~EncodedVideoFrame() {} | 305 WebmMuxer::EncodedVideoFrame::~EncodedVideoFrame() {} |
| 288 | 306 |
| 289 } // namespace media | 307 } // namespace media |
| OLD | NEW |