| 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 DCHECK(audio_config.IsValidConfig()); | 118 DCHECK(audio_config.IsValidConfig()); |
| 119 audio_configs_.push_back(audio_config); | 119 audio_configs_.push_back(audio_config); |
| 120 } | 120 } |
| 121 | 121 |
| 122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
| 123 const LogCB& log_cb, | 123 const scoped_refptr<MediaLog>& media_log, |
| 124 bool splice_frames_enabled) | 124 bool splice_frames_enabled) |
| 125 : log_cb_(log_cb), | 125 : media_log_(media_log), |
| 126 current_config_index_(0), | 126 current_config_index_(0), |
| 127 append_config_index_(0), | 127 append_config_index_(0), |
| 128 seek_pending_(false), | 128 seek_pending_(false), |
| 129 end_of_stream_(false), | 129 end_of_stream_(false), |
| 130 seek_buffer_timestamp_(kNoTimestamp()), | 130 seek_buffer_timestamp_(kNoTimestamp()), |
| 131 selected_range_(NULL), | 131 selected_range_(NULL), |
| 132 media_segment_start_time_(kNoDecodeTimestamp()), | 132 media_segment_start_time_(kNoDecodeTimestamp()), |
| 133 range_for_next_append_(ranges_.end()), | 133 range_for_next_append_(ranges_.end()), |
| 134 new_media_segment_(false), | 134 new_media_segment_(false), |
| 135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 136 last_appended_buffer_is_keyframe_(false), | 136 last_appended_buffer_is_keyframe_(false), |
| 137 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 137 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 138 max_interbuffer_distance_(kNoTimestamp()), | 138 max_interbuffer_distance_(kNoTimestamp()), |
| 139 memory_limit_(kSourceBufferVideoMemoryLimit), | 139 memory_limit_(kSourceBufferVideoMemoryLimit), |
| 140 config_change_pending_(false), | 140 config_change_pending_(false), |
| 141 splice_buffers_index_(0), | 141 splice_buffers_index_(0), |
| 142 pending_buffers_complete_(false), | 142 pending_buffers_complete_(false), |
| 143 splice_frames_enabled_(splice_frames_enabled) { | 143 splice_frames_enabled_(splice_frames_enabled) { |
| 144 DCHECK(video_config.IsValidConfig()); | 144 DCHECK(video_config.IsValidConfig()); |
| 145 video_configs_.push_back(video_config); | 145 video_configs_.push_back(video_config); |
| 146 } | 146 } |
| 147 | 147 |
| 148 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 148 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
| 149 const LogCB& log_cb, | 149 const scoped_refptr<MediaLog>& media_log, |
| 150 bool splice_frames_enabled) | 150 bool splice_frames_enabled) |
| 151 : log_cb_(log_cb), | 151 : media_log_(media_log), |
| 152 current_config_index_(0), | 152 current_config_index_(0), |
| 153 append_config_index_(0), | 153 append_config_index_(0), |
| 154 text_track_config_(text_config), | 154 text_track_config_(text_config), |
| 155 seek_pending_(false), | 155 seek_pending_(false), |
| 156 end_of_stream_(false), | 156 end_of_stream_(false), |
| 157 seek_buffer_timestamp_(kNoTimestamp()), | 157 seek_buffer_timestamp_(kNoTimestamp()), |
| 158 selected_range_(NULL), | 158 selected_range_(NULL), |
| 159 media_segment_start_time_(kNoDecodeTimestamp()), | 159 media_segment_start_time_(kNoDecodeTimestamp()), |
| 160 range_for_next_append_(ranges_.end()), | 160 range_for_next_append_(ranges_.end()), |
| 161 new_media_segment_(false), | 161 new_media_segment_(false), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": buffers dts=[" | 216 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": buffers dts=[" |
| 217 << buffers.front()->GetDecodeTimestamp().InSecondsF() << ";" | 217 << buffers.front()->GetDecodeTimestamp().InSecondsF() << ";" |
| 218 << buffers.back()->GetDecodeTimestamp().InSecondsF() << "] pts=[" | 218 << buffers.back()->GetDecodeTimestamp().InSecondsF() << "] pts=[" |
| 219 << buffers.front()->timestamp().InSecondsF() << ";" | 219 << buffers.front()->timestamp().InSecondsF() << ";" |
| 220 << buffers.back()->timestamp().InSecondsF() << "(last frame dur=" | 220 << buffers.back()->timestamp().InSecondsF() << "(last frame dur=" |
| 221 << buffers.back()->duration().InSecondsF() << ")]"; | 221 << buffers.back()->duration().InSecondsF() << ")]"; |
| 222 | 222 |
| 223 // New media segments must begin with a keyframe. | 223 // New media segments must begin with a keyframe. |
| 224 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. | 224 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. |
| 225 if (new_media_segment_ && !buffers.front()->is_key_frame()) { | 225 if (new_media_segment_ && !buffers.front()->is_key_frame()) { |
| 226 MEDIA_LOG(ERROR, log_cb_) << "Media segment did not begin with key frame."; | 226 MEDIA_LOG(ERROR, media_log_) |
| 227 << "Media segment did not begin with key frame."; |
| 227 return false; | 228 return false; |
| 228 } | 229 } |
| 229 | 230 |
| 230 // Buffers within a media segment should be monotonically increasing. | 231 // Buffers within a media segment should be monotonically increasing. |
| 231 if (!IsMonotonicallyIncreasing(buffers)) | 232 if (!IsMonotonicallyIncreasing(buffers)) |
| 232 return false; | 233 return false; |
| 233 | 234 |
| 234 if (media_segment_start_time_ < DecodeTimestamp() || | 235 if (media_segment_start_time_ < DecodeTimestamp() || |
| 235 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { | 236 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { |
| 236 MEDIA_LOG(ERROR, log_cb_) | 237 MEDIA_LOG(ERROR, media_log_) |
| 237 << "Cannot append a media segment with negative timestamps."; | 238 << "Cannot append a media segment with negative timestamps."; |
| 238 return false; | 239 return false; |
| 239 } | 240 } |
| 240 | 241 |
| 241 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), | 242 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), |
| 242 buffers.front()->is_key_frame())) { | 243 buffers.front()->is_key_frame())) { |
| 243 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); | 244 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); |
| 244 MEDIA_LOG(ERROR, log_cb_) << "Invalid same timestamp construct detected at" | 245 MEDIA_LOG(ERROR, media_log_) |
| 245 << " time " << dts.InSecondsF(); | 246 << "Invalid same timestamp construct detected at" |
| 247 << " time " << dts.InSecondsF(); |
| 246 | 248 |
| 247 return false; | 249 return false; |
| 248 } | 250 } |
| 249 | 251 |
| 250 UpdateMaxInterbufferDistance(buffers); | 252 UpdateMaxInterbufferDistance(buffers); |
| 251 SetConfigIds(buffers); | 253 SetConfigIds(buffers); |
| 252 | 254 |
| 253 // Save a snapshot of stream state before range modifications are made. | 255 // Save a snapshot of stream state before range modifications are made. |
| 254 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 256 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
| 255 BufferQueue deleted_buffers; | 257 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(); | 525 bool current_is_keyframe = (*itr)->is_key_frame(); |
| 524 DCHECK(current_timestamp != kNoDecodeTimestamp()); | 526 DCHECK(current_timestamp != kNoDecodeTimestamp()); |
| 525 DCHECK((*itr)->duration() >= base::TimeDelta()) | 527 DCHECK((*itr)->duration() >= base::TimeDelta()) |
| 526 << "Packet with invalid duration." | 528 << "Packet with invalid duration." |
| 527 << " pts " << (*itr)->timestamp().InSecondsF() | 529 << " pts " << (*itr)->timestamp().InSecondsF() |
| 528 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() | 530 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() |
| 529 << " dur " << (*itr)->duration().InSecondsF(); | 531 << " dur " << (*itr)->duration().InSecondsF(); |
| 530 | 532 |
| 531 if (prev_timestamp != kNoDecodeTimestamp()) { | 533 if (prev_timestamp != kNoDecodeTimestamp()) { |
| 532 if (current_timestamp < prev_timestamp) { | 534 if (current_timestamp < prev_timestamp) { |
| 533 MEDIA_LOG(ERROR, log_cb_) << "Buffers did not monotonically increase."; | 535 MEDIA_LOG(ERROR, media_log_) |
| 536 << "Buffers did not monotonically increase."; |
| 534 return false; | 537 return false; |
| 535 } | 538 } |
| 536 | 539 |
| 537 if (current_timestamp == prev_timestamp && | 540 if (current_timestamp == prev_timestamp && |
| 538 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, | 541 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, |
| 539 current_is_keyframe)) { | 542 current_is_keyframe)) { |
| 540 MEDIA_LOG(ERROR, log_cb_) << "Unexpected combination of buffers with" | 543 MEDIA_LOG(ERROR, media_log_) << "Unexpected combination of buffers with" |
| 541 << " the same timestamp detected at " | 544 << " the same timestamp detected at " |
| 542 << current_timestamp.InSecondsF(); | 545 << current_timestamp.InSecondsF(); |
| 543 return false; | 546 return false; |
| 544 } | 547 } |
| 545 } | 548 } |
| 546 | 549 |
| 547 prev_timestamp = current_timestamp; | 550 prev_timestamp = current_timestamp; |
| 548 prev_is_keyframe = current_is_keyframe; | 551 prev_is_keyframe = current_is_keyframe; |
| 549 } | 552 } |
| 550 return true; | 553 return true; |
| 551 } | 554 } |
| 552 | 555 |
| (...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); | 1262 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); |
| 1260 return max_interbuffer_distance_; | 1263 return max_interbuffer_distance_; |
| 1261 } | 1264 } |
| 1262 | 1265 |
| 1263 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { | 1266 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
| 1264 DCHECK(!audio_configs_.empty()); | 1267 DCHECK(!audio_configs_.empty()); |
| 1265 DCHECK(video_configs_.empty()); | 1268 DCHECK(video_configs_.empty()); |
| 1266 DVLOG(3) << "UpdateAudioConfig."; | 1269 DVLOG(3) << "UpdateAudioConfig."; |
| 1267 | 1270 |
| 1268 if (audio_configs_[0].codec() != config.codec()) { | 1271 if (audio_configs_[0].codec() != config.codec()) { |
| 1269 MEDIA_LOG(ERROR, log_cb_) << "Audio codec changes not allowed."; | 1272 MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed."; |
| 1270 return false; | 1273 return false; |
| 1271 } | 1274 } |
| 1272 | 1275 |
| 1273 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) { | 1276 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) { |
| 1274 MEDIA_LOG(ERROR, log_cb_) << "Audio encryption changes not allowed."; | 1277 MEDIA_LOG(ERROR, media_log_) << "Audio encryption changes not allowed."; |
| 1275 return false; | 1278 return false; |
| 1276 } | 1279 } |
| 1277 | 1280 |
| 1278 // Check to see if the new config matches an existing one. | 1281 // Check to see if the new config matches an existing one. |
| 1279 for (size_t i = 0; i < audio_configs_.size(); ++i) { | 1282 for (size_t i = 0; i < audio_configs_.size(); ++i) { |
| 1280 if (config.Matches(audio_configs_[i])) { | 1283 if (config.Matches(audio_configs_[i])) { |
| 1281 append_config_index_ = i; | 1284 append_config_index_ = i; |
| 1282 return true; | 1285 return true; |
| 1283 } | 1286 } |
| 1284 } | 1287 } |
| 1285 | 1288 |
| 1286 // No matches found so let's add this one to the list. | 1289 // No matches found so let's add this one to the list. |
| 1287 append_config_index_ = audio_configs_.size(); | 1290 append_config_index_ = audio_configs_.size(); |
| 1288 DVLOG(2) << "New audio config - index: " << append_config_index_; | 1291 DVLOG(2) << "New audio config - index: " << append_config_index_; |
| 1289 audio_configs_.resize(audio_configs_.size() + 1); | 1292 audio_configs_.resize(audio_configs_.size() + 1); |
| 1290 audio_configs_[append_config_index_] = config; | 1293 audio_configs_[append_config_index_] = config; |
| 1291 return true; | 1294 return true; |
| 1292 } | 1295 } |
| 1293 | 1296 |
| 1294 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { | 1297 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { |
| 1295 DCHECK(!video_configs_.empty()); | 1298 DCHECK(!video_configs_.empty()); |
| 1296 DCHECK(audio_configs_.empty()); | 1299 DCHECK(audio_configs_.empty()); |
| 1297 DVLOG(3) << "UpdateVideoConfig."; | 1300 DVLOG(3) << "UpdateVideoConfig."; |
| 1298 | 1301 |
| 1299 if (video_configs_[0].codec() != config.codec()) { | 1302 if (video_configs_[0].codec() != config.codec()) { |
| 1300 MEDIA_LOG(ERROR, log_cb_) << "Video codec changes not allowed."; | 1303 MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed."; |
| 1301 return false; | 1304 return false; |
| 1302 } | 1305 } |
| 1303 | 1306 |
| 1304 if (video_configs_[0].is_encrypted() != config.is_encrypted()) { | 1307 if (video_configs_[0].is_encrypted() != config.is_encrypted()) { |
| 1305 MEDIA_LOG(ERROR, log_cb_) << "Video encryption changes not allowed."; | 1308 MEDIA_LOG(ERROR, media_log_) << "Video encryption changes not allowed."; |
| 1306 return false; | 1309 return false; |
| 1307 } | 1310 } |
| 1308 | 1311 |
| 1309 // Check to see if the new config matches an existing one. | 1312 // Check to see if the new config matches an existing one. |
| 1310 for (size_t i = 0; i < video_configs_.size(); ++i) { | 1313 for (size_t i = 0; i < video_configs_.size(); ++i) { |
| 1311 if (config.Matches(video_configs_[i])) { | 1314 if (config.Matches(video_configs_[i])) { |
| 1312 append_config_index_ = i; | 1315 append_config_index_ = i; |
| 1313 return true; | 1316 return true; |
| 1314 } | 1317 } |
| 1315 } | 1318 } |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1600 return false; | 1603 return false; |
| 1601 | 1604 |
| 1602 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1605 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
| 1603 splice_buffers_index_ = 0; | 1606 splice_buffers_index_ = 0; |
| 1604 pending_buffer_.swap(*out_buffer); | 1607 pending_buffer_.swap(*out_buffer); |
| 1605 pending_buffers_complete_ = false; | 1608 pending_buffers_complete_ = false; |
| 1606 return true; | 1609 return true; |
| 1607 } | 1610 } |
| 1608 | 1611 |
| 1609 } // namespace media | 1612 } // namespace media |
| OLD | NEW |