| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/filters/frame_processor.h" | 5 #include "media/filters/frame_processor.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <cstdlib> | 9 #include <cstdlib> |
| 10 | 10 |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "media/base/stream_parser_buffer.h" | 13 #include "media/base/stream_parser_buffer.h" |
| 14 #include "media/base/timestamp_constants.h" | 14 #include "media/base/timestamp_constants.h" |
| 15 | 15 |
| 16 namespace media { | 16 namespace media { |
| 17 | 17 |
| 18 const int kMaxDroppedPrerollWarnings = 10; | 18 const int kMaxDroppedPrerollWarnings = 10; |
| 19 const int kMaxDtsBeyondPtsWarnings = 10; | 19 const int kMaxDtsBeyondPtsWarnings = 10; |
| 20 | 20 |
| 21 // Helper class to capture per-track details needed by a frame processor. Some | 21 // Helper class to capture per-track details needed by a frame processor. Some |
| 22 // of this information may be duplicated in the short-term in the associated | 22 // of this information may be duplicated in the short-term in the associated |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 const scoped_refptr<MediaLog>& media_log) | 165 const scoped_refptr<MediaLog>& media_log) |
| 166 : group_start_timestamp_(kNoTimestamp), | 166 : group_start_timestamp_(kNoTimestamp), |
| 167 update_duration_cb_(update_duration_cb), | 167 update_duration_cb_(update_duration_cb), |
| 168 media_log_(media_log) { | 168 media_log_(media_log) { |
| 169 DVLOG(2) << __func__ << "()"; | 169 DVLOG(2) << __func__ << "()"; |
| 170 DCHECK(!update_duration_cb.is_null()); | 170 DCHECK(!update_duration_cb.is_null()); |
| 171 } | 171 } |
| 172 | 172 |
| 173 FrameProcessor::~FrameProcessor() { | 173 FrameProcessor::~FrameProcessor() { |
| 174 DVLOG(2) << __func__ << "()"; | 174 DVLOG(2) << __func__ << "()"; |
| 175 base::STLDeleteValues(&track_buffers_); | |
| 176 } | 175 } |
| 177 | 176 |
| 178 void FrameProcessor::SetSequenceMode(bool sequence_mode) { | 177 void FrameProcessor::SetSequenceMode(bool sequence_mode) { |
| 179 DVLOG(2) << __func__ << "(" << sequence_mode << ")"; | 178 DVLOG(2) << __func__ << "(" << sequence_mode << ")"; |
| 180 // Per June 9, 2016 MSE spec editor's draft: | 179 // Per June 9, 2016 MSE spec editor's draft: |
| 181 // https://rawgit.com/w3c/media-source/d8f901f22/ | 180 // https://rawgit.com/w3c/media-source/d8f901f22/ |
| 182 // index.html#widl-SourceBuffer-mode | 181 // index.html#widl-SourceBuffer-mode |
| 183 // Step 7: If the new mode equals "sequence", then set the group start | 182 // Step 7: If the new mode equals "sequence", then set the group start |
| 184 // timestamp to the group end timestamp. | 183 // timestamp to the group end timestamp. |
| 185 if (sequence_mode) { | 184 if (sequence_mode) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 DVLOG(2) << __func__ << "(): id=" << id; | 252 DVLOG(2) << __func__ << "(): id=" << id; |
| 254 | 253 |
| 255 MseTrackBuffer* existing_track = FindTrack(id); | 254 MseTrackBuffer* existing_track = FindTrack(id); |
| 256 DCHECK(!existing_track); | 255 DCHECK(!existing_track); |
| 257 if (existing_track) { | 256 if (existing_track) { |
| 258 MEDIA_LOG(ERROR, media_log_) << "Failure adding track with duplicate ID " | 257 MEDIA_LOG(ERROR, media_log_) << "Failure adding track with duplicate ID " |
| 259 << id; | 258 << id; |
| 260 return false; | 259 return false; |
| 261 } | 260 } |
| 262 | 261 |
| 263 track_buffers_[id] = new MseTrackBuffer(stream); | 262 track_buffers_[id] = base::MakeUnique<MseTrackBuffer>(stream); |
| 264 return true; | 263 return true; |
| 265 } | 264 } |
| 266 | 265 |
| 267 bool FrameProcessor::UpdateTrack(StreamParser::TrackId old_id, | 266 bool FrameProcessor::UpdateTrack(StreamParser::TrackId old_id, |
| 268 StreamParser::TrackId new_id) { | 267 StreamParser::TrackId new_id) { |
| 269 DVLOG(2) << __func__ << "() : old_id=" << old_id << ", new_id=" << new_id; | 268 DVLOG(2) << __func__ << "() : old_id=" << old_id << ", new_id=" << new_id; |
| 270 | 269 |
| 271 if (old_id == new_id || !FindTrack(old_id) || FindTrack(new_id)) { | 270 if (old_id == new_id || !FindTrack(old_id) || FindTrack(new_id)) { |
| 272 MEDIA_LOG(ERROR, media_log_) << "Failure updating track id from " << old_id | 271 MEDIA_LOG(ERROR, media_log_) << "Failure updating track id from " << old_id |
| 273 << " to " << new_id; | 272 << " to " << new_id; |
| 274 return false; | 273 return false; |
| 275 } | 274 } |
| 276 | 275 |
| 277 track_buffers_[new_id] = track_buffers_[old_id]; | 276 track_buffers_[new_id] = std::move(track_buffers_[old_id]); |
| 278 CHECK_EQ(1u, track_buffers_.erase(old_id)); | 277 CHECK_EQ(1u, track_buffers_.erase(old_id)); |
| 279 return true; | 278 return true; |
| 280 } | 279 } |
| 281 | 280 |
| 282 void FrameProcessor::SetAllTrackBuffersNeedRandomAccessPoint() { | 281 void FrameProcessor::SetAllTrackBuffersNeedRandomAccessPoint() { |
| 283 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 282 for (auto itr = track_buffers_.begin(); itr != track_buffers_.end(); ++itr) { |
| 284 itr != track_buffers_.end(); | |
| 285 ++itr) { | |
| 286 itr->second->set_needs_random_access_point(true); | 283 itr->second->set_needs_random_access_point(true); |
| 287 } | 284 } |
| 288 } | 285 } |
| 289 | 286 |
| 290 void FrameProcessor::Reset() { | 287 void FrameProcessor::Reset() { |
| 291 DVLOG(2) << __func__ << "()"; | 288 DVLOG(2) << __func__ << "()"; |
| 292 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 289 for (auto itr = track_buffers_.begin(); itr != track_buffers_.end(); ++itr) { |
| 293 itr != track_buffers_.end(); ++itr) { | |
| 294 itr->second->Reset(); | 290 itr->second->Reset(); |
| 295 } | 291 } |
| 296 | 292 |
| 297 // Maintain current |coded_frame_group_last_dts_| state for Reset() during | 293 // Maintain current |coded_frame_group_last_dts_| state for Reset() during |
| 298 // sequence mode. Reset it here only if in segments mode. In sequence mode, | 294 // sequence mode. Reset it here only if in segments mode. In sequence mode, |
| 299 // the current coded frame group may be continued across Reset() operations to | 295 // the current coded frame group may be continued across Reset() operations to |
| 300 // allow the stream to coaelesce what might otherwise be gaps in the buffered | 296 // allow the stream to coalesce what might otherwise be gaps in the buffered |
| 301 // ranges. See also the declaration for |coded_frame_group_last_dts_|. | 297 // ranges. See also the declaration for |coded_frame_group_last_dts_|. |
| 302 if (!sequence_mode_) { | 298 if (!sequence_mode_) { |
| 303 coded_frame_group_last_dts_ = kNoDecodeTimestamp(); | 299 coded_frame_group_last_dts_ = kNoDecodeTimestamp(); |
| 304 return; | 300 return; |
| 305 } | 301 } |
| 306 | 302 |
| 307 // Sequence mode | 303 // Sequence mode |
| 308 DCHECK(kNoTimestamp != group_end_timestamp_); | 304 DCHECK(kNoTimestamp != group_end_timestamp_); |
| 309 group_start_timestamp_ = group_end_timestamp_; | 305 group_start_timestamp_ = group_end_timestamp_; |
| 310 } | 306 } |
| 311 | 307 |
| 312 void FrameProcessor::OnPossibleAudioConfigUpdate( | 308 void FrameProcessor::OnPossibleAudioConfigUpdate( |
| 313 const AudioDecoderConfig& config) { | 309 const AudioDecoderConfig& config) { |
| 314 DCHECK(config.IsValidConfig()); | 310 DCHECK(config.IsValidConfig()); |
| 315 | 311 |
| 316 // Always clear the preroll buffer when a config update is received. | 312 // Always clear the preroll buffer when a config update is received. |
| 317 audio_preroll_buffer_ = NULL; | 313 audio_preroll_buffer_ = NULL; |
| 318 | 314 |
| 319 if (config.Matches(current_audio_config_)) | 315 if (config.Matches(current_audio_config_)) |
| 320 return; | 316 return; |
| 321 | 317 |
| 322 current_audio_config_ = config; | 318 current_audio_config_ = config; |
| 323 sample_duration_ = base::TimeDelta::FromSecondsD( | 319 sample_duration_ = base::TimeDelta::FromSecondsD( |
| 324 1.0 / current_audio_config_.samples_per_second()); | 320 1.0 / current_audio_config_.samples_per_second()); |
| 325 } | 321 } |
| 326 | 322 |
| 327 MseTrackBuffer* FrameProcessor::FindTrack(StreamParser::TrackId id) { | 323 MseTrackBuffer* FrameProcessor::FindTrack(StreamParser::TrackId id) { |
| 328 TrackBufferMap::iterator itr = track_buffers_.find(id); | 324 auto itr = track_buffers_.find(id); |
| 329 if (itr == track_buffers_.end()) | 325 if (itr == track_buffers_.end()) |
| 330 return NULL; | 326 return NULL; |
| 331 | 327 |
| 332 return itr->second; | 328 return itr->second.get(); |
| 333 } | 329 } |
| 334 | 330 |
| 335 void FrameProcessor::NotifyStartOfCodedFrameGroup( | 331 void FrameProcessor::NotifyStartOfCodedFrameGroup( |
| 336 DecodeTimestamp start_timestamp) { | 332 DecodeTimestamp start_timestamp) { |
| 337 DVLOG(2) << __func__ << "(" << start_timestamp.InSecondsF() << ")"; | 333 DVLOG(2) << __func__ << "(" << start_timestamp.InSecondsF() << ")"; |
| 338 | 334 |
| 339 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 335 for (auto itr = track_buffers_.begin(); itr != track_buffers_.end(); ++itr) { |
| 340 itr != track_buffers_.end(); | |
| 341 ++itr) { | |
| 342 itr->second->stream()->OnStartOfCodedFrameGroup(start_timestamp); | 336 itr->second->stream()->OnStartOfCodedFrameGroup(start_timestamp); |
| 343 } | 337 } |
| 344 } | 338 } |
| 345 | 339 |
| 346 bool FrameProcessor::FlushProcessedFrames() { | 340 bool FrameProcessor::FlushProcessedFrames() { |
| 347 DVLOG(2) << __func__ << "()"; | 341 DVLOG(2) << __func__ << "()"; |
| 348 | 342 |
| 349 bool result = true; | 343 bool result = true; |
| 350 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 344 for (auto itr = track_buffers_.begin(); itr != track_buffers_.end(); ++itr) { |
| 351 itr != track_buffers_.end(); | |
| 352 ++itr) { | |
| 353 if (!itr->second->FlushProcessedFrames()) | 345 if (!itr->second->FlushProcessedFrames()) |
| 354 result = false; | 346 result = false; |
| 355 } | 347 } |
| 356 | 348 |
| 357 return result; | 349 return result; |
| 358 } | 350 } |
| 359 | 351 |
| 360 bool FrameProcessor::HandlePartialAppendWindowTrimming( | 352 bool FrameProcessor::HandlePartialAppendWindowTrimming( |
| 361 base::TimeDelta append_window_start, | 353 base::TimeDelta append_window_start, |
| 362 base::TimeDelta append_window_end, | 354 base::TimeDelta append_window_end, |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 // Step 21 is currently handled differently. See MediaSourceState's | 738 // Step 21 is currently handled differently. See MediaSourceState's |
| 747 // |auto_update_timestamp_offset_|. | 739 // |auto_update_timestamp_offset_|. |
| 748 return true; | 740 return true; |
| 749 } | 741 } |
| 750 | 742 |
| 751 NOTREACHED(); | 743 NOTREACHED(); |
| 752 return false; | 744 return false; |
| 753 } | 745 } |
| 754 | 746 |
| 755 } // namespace media | 747 } // namespace media |
| OLD | NEW |