Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/source_buffer_stream.h" | 5 #include "media/filters/source_buffer_stream.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 return SourceBufferRange::NO_GAPS_ALLOWED; | 87 return SourceBufferRange::NO_GAPS_ALLOWED; |
| 88 case SourceBufferStream::kText: | 88 case SourceBufferStream::kText: |
| 89 return SourceBufferRange::ALLOW_GAPS; | 89 return SourceBufferRange::ALLOW_GAPS; |
| 90 } | 90 } |
| 91 | 91 |
| 92 NOTREACHED(); | 92 NOTREACHED(); |
| 93 return SourceBufferRange::NO_GAPS_ALLOWED; | 93 return SourceBufferRange::NO_GAPS_ALLOWED; |
| 94 } | 94 } |
| 95 | 95 |
| 96 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 96 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
| 97 const LogCB& log_cb, | 97 const scoped_refptr<MediaLog>& media_log, |
| 98 bool splice_frames_enabled) | 98 bool splice_frames_enabled) |
| 99 : log_cb_(log_cb), | 99 : media_log_(media_log), |
| 100 current_config_index_(0), | 100 current_config_index_(0), |
| 101 append_config_index_(0), | 101 append_config_index_(0), |
| 102 seek_pending_(false), | 102 seek_pending_(false), |
| 103 end_of_stream_(false), | 103 end_of_stream_(false), |
| 104 seek_buffer_timestamp_(kNoTimestamp()), | 104 seek_buffer_timestamp_(kNoTimestamp()), |
| 105 selected_range_(NULL), | 105 selected_range_(NULL), |
| 106 media_segment_start_time_(kNoDecodeTimestamp()), | 106 media_segment_start_time_(kNoDecodeTimestamp()), |
| 107 range_for_next_append_(ranges_.end()), | 107 range_for_next_append_(ranges_.end()), |
| 108 new_media_segment_(false), | 108 new_media_segment_(false), |
| 109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 110 last_appended_buffer_is_keyframe_(false), | 110 last_appended_buffer_is_keyframe_(false), |
| 111 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 111 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 112 max_interbuffer_distance_(kNoTimestamp()), | 112 max_interbuffer_distance_(kNoTimestamp()), |
| 113 memory_limit_(kSourceBufferAudioMemoryLimit), | 113 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 114 config_change_pending_(false), | 114 config_change_pending_(false), |
| 115 splice_buffers_index_(0), | 115 splice_buffers_index_(0), |
| 116 pending_buffers_complete_(false), | 116 pending_buffers_complete_(false), |
| 117 splice_frames_enabled_(splice_frames_enabled) { | 117 splice_frames_enabled_(splice_frames_enabled), |
| 118 audio_splice_count_(0), | |
|
wolenetz
2015/07/13 22:25:29
Ditto oops, here and below! (PS2 fixes this CL to
| |
| 119 total_audio_splice_duration_(0.0), | |
| 120 min_audio_splice_duration_(0.0), | |
| 121 max_audio_splice_duration_(0.0) { | |
| 118 DCHECK(audio_config.IsValidConfig()); | 122 DCHECK(audio_config.IsValidConfig()); |
| 119 audio_configs_.push_back(audio_config); | 123 audio_configs_.push_back(audio_config); |
| 120 } | 124 } |
| 121 | 125 |
| 122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 126 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
| 123 const LogCB& log_cb, | 127 const scoped_refptr<MediaLog>& media_log, |
| 124 bool splice_frames_enabled) | 128 bool splice_frames_enabled) |
| 125 : log_cb_(log_cb), | 129 : media_log_(media_log), |
| 126 current_config_index_(0), | 130 current_config_index_(0), |
| 127 append_config_index_(0), | 131 append_config_index_(0), |
| 128 seek_pending_(false), | 132 seek_pending_(false), |
| 129 end_of_stream_(false), | 133 end_of_stream_(false), |
| 130 seek_buffer_timestamp_(kNoTimestamp()), | 134 seek_buffer_timestamp_(kNoTimestamp()), |
| 131 selected_range_(NULL), | 135 selected_range_(NULL), |
| 132 media_segment_start_time_(kNoDecodeTimestamp()), | 136 media_segment_start_time_(kNoDecodeTimestamp()), |
| 133 range_for_next_append_(ranges_.end()), | 137 range_for_next_append_(ranges_.end()), |
| 134 new_media_segment_(false), | 138 new_media_segment_(false), |
| 135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 139 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 136 last_appended_buffer_is_keyframe_(false), | 140 last_appended_buffer_is_keyframe_(false), |
| 137 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 141 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 138 max_interbuffer_distance_(kNoTimestamp()), | 142 max_interbuffer_distance_(kNoTimestamp()), |
| 139 memory_limit_(kSourceBufferVideoMemoryLimit), | 143 memory_limit_(kSourceBufferVideoMemoryLimit), |
| 140 config_change_pending_(false), | 144 config_change_pending_(false), |
| 141 splice_buffers_index_(0), | 145 splice_buffers_index_(0), |
| 142 pending_buffers_complete_(false), | 146 pending_buffers_complete_(false), |
| 143 splice_frames_enabled_(splice_frames_enabled) { | 147 splice_frames_enabled_(splice_frames_enabled), |
| 148 audio_splice_count_(0), | |
| 149 total_audio_splice_duration_(0.0), | |
| 150 min_audio_splice_duration_(0.0), | |
| 151 max_audio_splice_duration_(0.0) { | |
| 144 DCHECK(video_config.IsValidConfig()); | 152 DCHECK(video_config.IsValidConfig()); |
| 145 video_configs_.push_back(video_config); | 153 video_configs_.push_back(video_config); |
| 146 } | 154 } |
| 147 | 155 |
| 148 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 156 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
| 149 const LogCB& log_cb, | 157 const scoped_refptr<MediaLog>& media_log, |
| 150 bool splice_frames_enabled) | 158 bool splice_frames_enabled) |
| 151 : log_cb_(log_cb), | 159 : media_log_(media_log), |
| 152 current_config_index_(0), | 160 current_config_index_(0), |
| 153 append_config_index_(0), | 161 append_config_index_(0), |
| 154 text_track_config_(text_config), | 162 text_track_config_(text_config), |
| 155 seek_pending_(false), | 163 seek_pending_(false), |
| 156 end_of_stream_(false), | 164 end_of_stream_(false), |
| 157 seek_buffer_timestamp_(kNoTimestamp()), | 165 seek_buffer_timestamp_(kNoTimestamp()), |
| 158 selected_range_(NULL), | 166 selected_range_(NULL), |
| 159 media_segment_start_time_(kNoDecodeTimestamp()), | 167 media_segment_start_time_(kNoDecodeTimestamp()), |
| 160 range_for_next_append_(ranges_.end()), | 168 range_for_next_append_(ranges_.end()), |
| 161 new_media_segment_(false), | 169 new_media_segment_(false), |
| 162 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 170 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 163 last_appended_buffer_is_keyframe_(false), | 171 last_appended_buffer_is_keyframe_(false), |
| 164 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 172 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 165 max_interbuffer_distance_(kNoTimestamp()), | 173 max_interbuffer_distance_(kNoTimestamp()), |
| 166 memory_limit_(kSourceBufferAudioMemoryLimit), | 174 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 167 config_change_pending_(false), | 175 config_change_pending_(false), |
| 168 splice_buffers_index_(0), | 176 splice_buffers_index_(0), |
| 169 pending_buffers_complete_(false), | 177 pending_buffers_complete_(false), |
| 170 splice_frames_enabled_(splice_frames_enabled) { | 178 splice_frames_enabled_(splice_frames_enabled), |
| 179 audio_splice_count_(0), | |
| 180 total_audio_splice_duration_(0.0), | |
| 181 min_audio_splice_duration_(0.0), | |
| 182 max_audio_splice_duration_(0.0) { | |
| 171 } | 183 } |
| 172 | 184 |
| 173 SourceBufferStream::~SourceBufferStream() { | 185 SourceBufferStream::~SourceBufferStream() { |
| 174 while (!ranges_.empty()) { | 186 while (!ranges_.empty()) { |
| 175 delete ranges_.front(); | 187 delete ranges_.front(); |
| 176 ranges_.pop_front(); | 188 ranges_.pop_front(); |
| 177 } | 189 } |
| 178 } | 190 } |
| 179 | 191 |
| 180 void SourceBufferStream::OnNewMediaSegment( | 192 void SourceBufferStream::OnNewMediaSegment( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": buffers dts=[" | 228 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": buffers dts=[" |
| 217 << buffers.front()->GetDecodeTimestamp().InSecondsF() << ";" | 229 << buffers.front()->GetDecodeTimestamp().InSecondsF() << ";" |
| 218 << buffers.back()->GetDecodeTimestamp().InSecondsF() << "] pts=[" | 230 << buffers.back()->GetDecodeTimestamp().InSecondsF() << "] pts=[" |
| 219 << buffers.front()->timestamp().InSecondsF() << ";" | 231 << buffers.front()->timestamp().InSecondsF() << ";" |
| 220 << buffers.back()->timestamp().InSecondsF() << "(last frame dur=" | 232 << buffers.back()->timestamp().InSecondsF() << "(last frame dur=" |
| 221 << buffers.back()->duration().InSecondsF() << ")]"; | 233 << buffers.back()->duration().InSecondsF() << ")]"; |
| 222 | 234 |
| 223 // New media segments must begin with a keyframe. | 235 // New media segments must begin with a keyframe. |
| 224 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. | 236 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. |
| 225 if (new_media_segment_ && !buffers.front()->is_key_frame()) { | 237 if (new_media_segment_ && !buffers.front()->is_key_frame()) { |
| 226 MEDIA_LOG(ERROR, log_cb_) << "Media segment did not begin with key frame."; | 238 MEDIA_LOG(ERROR, media_log_) |
| 239 << "Media segment did not begin with key frame."; | |
| 227 return false; | 240 return false; |
| 228 } | 241 } |
| 229 | 242 |
| 230 // Buffers within a media segment should be monotonically increasing. | 243 // Buffers within a media segment should be monotonically increasing. |
| 231 if (!IsMonotonicallyIncreasing(buffers)) | 244 if (!IsMonotonicallyIncreasing(buffers)) |
| 232 return false; | 245 return false; |
| 233 | 246 |
| 234 if (media_segment_start_time_ < DecodeTimestamp() || | 247 if (media_segment_start_time_ < DecodeTimestamp() || |
| 235 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { | 248 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { |
| 236 MEDIA_LOG(ERROR, log_cb_) | 249 MEDIA_LOG(ERROR, media_log_) |
| 237 << "Cannot append a media segment with negative timestamps."; | 250 << "Cannot append a media segment with negative timestamps."; |
| 238 return false; | 251 return false; |
| 239 } | 252 } |
| 240 | 253 |
| 241 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), | 254 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), |
| 242 buffers.front()->is_key_frame())) { | 255 buffers.front()->is_key_frame())) { |
| 243 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); | 256 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); |
| 244 MEDIA_LOG(ERROR, log_cb_) << "Invalid same timestamp construct detected at" | 257 MEDIA_LOG(ERROR, media_log_) |
| 245 << " time " << dts.InSecondsF(); | 258 << "Invalid same timestamp construct detected at" |
| 259 << " time " << dts.InSecondsF(); | |
| 246 | 260 |
| 247 return false; | 261 return false; |
| 248 } | 262 } |
| 249 | 263 |
| 250 UpdateMaxInterbufferDistance(buffers); | 264 UpdateMaxInterbufferDistance(buffers); |
| 251 SetConfigIds(buffers); | 265 SetConfigIds(buffers); |
| 252 | 266 |
| 253 // Save a snapshot of stream state before range modifications are made. | 267 // Save a snapshot of stream state before range modifications are made. |
| 254 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 268 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
| 255 BufferQueue deleted_buffers; | 269 BufferQueue deleted_buffers; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 bool current_is_keyframe = (*itr)->is_key_frame(); | 537 bool current_is_keyframe = (*itr)->is_key_frame(); |
| 524 DCHECK(current_timestamp != kNoDecodeTimestamp()); | 538 DCHECK(current_timestamp != kNoDecodeTimestamp()); |
| 525 DCHECK((*itr)->duration() >= base::TimeDelta()) | 539 DCHECK((*itr)->duration() >= base::TimeDelta()) |
| 526 << "Packet with invalid duration." | 540 << "Packet with invalid duration." |
| 527 << " pts " << (*itr)->timestamp().InSecondsF() | 541 << " pts " << (*itr)->timestamp().InSecondsF() |
| 528 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() | 542 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() |
| 529 << " dur " << (*itr)->duration().InSecondsF(); | 543 << " dur " << (*itr)->duration().InSecondsF(); |
| 530 | 544 |
| 531 if (prev_timestamp != kNoDecodeTimestamp()) { | 545 if (prev_timestamp != kNoDecodeTimestamp()) { |
| 532 if (current_timestamp < prev_timestamp) { | 546 if (current_timestamp < prev_timestamp) { |
| 533 MEDIA_LOG(ERROR, log_cb_) << "Buffers did not monotonically increase."; | 547 MEDIA_LOG(ERROR, media_log_) |
| 548 << "Buffers did not monotonically increase."; | |
| 534 return false; | 549 return false; |
| 535 } | 550 } |
| 536 | 551 |
| 537 if (current_timestamp == prev_timestamp && | 552 if (current_timestamp == prev_timestamp && |
| 538 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, | 553 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, |
| 539 current_is_keyframe)) { | 554 current_is_keyframe)) { |
| 540 MEDIA_LOG(ERROR, log_cb_) << "Unexpected combination of buffers with" | 555 MEDIA_LOG(ERROR, media_log_) << "Unexpected combination of buffers with" |
| 541 << " the same timestamp detected at " | 556 << " the same timestamp detected at " |
| 542 << current_timestamp.InSecondsF(); | 557 << current_timestamp.InSecondsF(); |
| 543 return false; | 558 return false; |
| 544 } | 559 } |
| 545 } | 560 } |
| 546 | 561 |
| 547 prev_timestamp = current_timestamp; | 562 prev_timestamp = current_timestamp; |
| 548 prev_is_keyframe = current_is_keyframe; | 563 prev_is_keyframe = current_is_keyframe; |
| 549 } | 564 } |
| 550 return true; | 565 return true; |
| 551 } | 566 } |
| 552 | 567 |
| (...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1259 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); | 1274 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); |
| 1260 return max_interbuffer_distance_; | 1275 return max_interbuffer_distance_; |
| 1261 } | 1276 } |
| 1262 | 1277 |
| 1263 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { | 1278 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
| 1264 DCHECK(!audio_configs_.empty()); | 1279 DCHECK(!audio_configs_.empty()); |
| 1265 DCHECK(video_configs_.empty()); | 1280 DCHECK(video_configs_.empty()); |
| 1266 DVLOG(3) << "UpdateAudioConfig."; | 1281 DVLOG(3) << "UpdateAudioConfig."; |
| 1267 | 1282 |
| 1268 if (audio_configs_[0].codec() != config.codec()) { | 1283 if (audio_configs_[0].codec() != config.codec()) { |
| 1269 MEDIA_LOG(ERROR, log_cb_) << "Audio codec changes not allowed."; | 1284 MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed."; |
| 1270 return false; | 1285 return false; |
| 1271 } | 1286 } |
| 1272 | 1287 |
| 1273 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) { | 1288 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) { |
| 1274 MEDIA_LOG(ERROR, log_cb_) << "Audio encryption changes not allowed."; | 1289 MEDIA_LOG(ERROR, media_log_) << "Audio encryption changes not allowed."; |
| 1275 return false; | 1290 return false; |
| 1276 } | 1291 } |
| 1277 | 1292 |
| 1278 // Check to see if the new config matches an existing one. | 1293 // Check to see if the new config matches an existing one. |
| 1279 for (size_t i = 0; i < audio_configs_.size(); ++i) { | 1294 for (size_t i = 0; i < audio_configs_.size(); ++i) { |
| 1280 if (config.Matches(audio_configs_[i])) { | 1295 if (config.Matches(audio_configs_[i])) { |
| 1281 append_config_index_ = i; | 1296 append_config_index_ = i; |
| 1282 return true; | 1297 return true; |
| 1283 } | 1298 } |
| 1284 } | 1299 } |
| 1285 | 1300 |
| 1286 // No matches found so let's add this one to the list. | 1301 // No matches found so let's add this one to the list. |
| 1287 append_config_index_ = audio_configs_.size(); | 1302 append_config_index_ = audio_configs_.size(); |
| 1288 DVLOG(2) << "New audio config - index: " << append_config_index_; | 1303 DVLOG(2) << "New audio config - index: " << append_config_index_; |
| 1289 audio_configs_.resize(audio_configs_.size() + 1); | 1304 audio_configs_.resize(audio_configs_.size() + 1); |
| 1290 audio_configs_[append_config_index_] = config; | 1305 audio_configs_[append_config_index_] = config; |
| 1291 return true; | 1306 return true; |
| 1292 } | 1307 } |
| 1293 | 1308 |
| 1294 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { | 1309 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { |
| 1295 DCHECK(!video_configs_.empty()); | 1310 DCHECK(!video_configs_.empty()); |
| 1296 DCHECK(audio_configs_.empty()); | 1311 DCHECK(audio_configs_.empty()); |
| 1297 DVLOG(3) << "UpdateVideoConfig."; | 1312 DVLOG(3) << "UpdateVideoConfig."; |
| 1298 | 1313 |
| 1299 if (video_configs_[0].codec() != config.codec()) { | 1314 if (video_configs_[0].codec() != config.codec()) { |
| 1300 MEDIA_LOG(ERROR, log_cb_) << "Video codec changes not allowed."; | 1315 MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed."; |
| 1301 return false; | 1316 return false; |
| 1302 } | 1317 } |
| 1303 | 1318 |
| 1304 if (video_configs_[0].is_encrypted() != config.is_encrypted()) { | 1319 if (video_configs_[0].is_encrypted() != config.is_encrypted()) { |
| 1305 MEDIA_LOG(ERROR, log_cb_) << "Video encryption changes not allowed."; | 1320 MEDIA_LOG(ERROR, media_log_) << "Video encryption changes not allowed."; |
| 1306 return false; | 1321 return false; |
| 1307 } | 1322 } |
| 1308 | 1323 |
| 1309 // Check to see if the new config matches an existing one. | 1324 // Check to see if the new config matches an existing one. |
| 1310 for (size_t i = 0; i < video_configs_.size(); ++i) { | 1325 for (size_t i = 0; i < video_configs_.size(); ++i) { |
| 1311 if (config.Matches(video_configs_[i])) { | 1326 if (config.Matches(video_configs_[i])) { |
| 1312 append_config_index_ = i; | 1327 append_config_index_ = i; |
| 1313 return true; | 1328 return true; |
| 1314 } | 1329 } |
| 1315 } | 1330 } |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1600 return false; | 1615 return false; |
| 1601 | 1616 |
| 1602 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1617 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
| 1603 splice_buffers_index_ = 0; | 1618 splice_buffers_index_ = 0; |
| 1604 pending_buffer_.swap(*out_buffer); | 1619 pending_buffer_.swap(*out_buffer); |
| 1605 pending_buffers_complete_ = false; | 1620 pending_buffers_complete_ = false; |
| 1606 return true; | 1621 return true; |
| 1607 } | 1622 } |
| 1608 | 1623 |
| 1609 } // namespace media | 1624 } // namespace media |
| OLD | NEW |