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 30 matching lines...) Expand all Loading... | |
| 41 // See http://crbug.com/351489 and http://crbug.com/351166. | 41 // See http://crbug.com/351489 and http://crbug.com/351166. |
| 42 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { | 42 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { |
| 43 // Because we do not know exactly when is the next timestamp, any buffer | 43 // Because we do not know exactly when is the next timestamp, any buffer |
| 44 // that starts within 2x the approximate duration of a buffer is considered | 44 // that starts within 2x the approximate duration of a buffer is considered |
| 45 // within this range. | 45 // within this range. |
| 46 return 2 * approximate_duration; | 46 return 2 * approximate_duration; |
| 47 } | 47 } |
| 48 | 48 |
| 49 // An arbitrarily-chosen number to estimate the duration of a buffer if none | 49 // An arbitrarily-chosen number to estimate the duration of a buffer if none |
| 50 // is set and there's not enough information to get a better estimate. | 50 // is set and there's not enough information to get a better estimate. |
| 51 static int kDefaultBufferDurationInMs = 125; | 51 static int kDefaultBufferDurationInMs = 125; |
|
DaleCurtis
2015/07/16 20:39:22
These three should all be marked const.
wolenetz
2015/07/17 17:38:15
Good catch! I've converted these to enum values, a
| |
| 52 | 52 |
| 53 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings | |
|
DaleCurtis
2015/07/16 20:39:21
I feel like these will be hit really fast.
chcunningham
2015/07/17 01:36:26
I wouldn't have guessed so. Do you expect we have
wolenetz
2015/07/17 17:38:15
I think there is room to increase, though there is
DaleCurtis
2015/07/17 18:22:34
Yes I definitely think we need a more programmatic
| |
| 54 // and successes. | |
| 55 static int kMaxSpliceGenerationWarningLogs = 5; | |
| 56 static int kMaxSpliceGenerationSuccessLogs = 5; | |
| 57 | |
| 53 // The amount of time the beginning of the buffered data can differ from the | 58 // The amount of time the beginning of the buffered data can differ from the |
| 54 // start time in order to still be considered the start of stream. | 59 // start time in order to still be considered the start of stream. |
| 55 static base::TimeDelta kSeekToStartFudgeRoom() { | 60 static base::TimeDelta kSeekToStartFudgeRoom() { |
| 56 return base::TimeDelta::FromMilliseconds(1000); | 61 return base::TimeDelta::FromMilliseconds(1000); |
| 57 } | 62 } |
| 58 | 63 |
| 59 // Helper method for logging, converts a range into a readable string. | 64 // Helper method for logging, converts a range into a readable string. |
| 60 static std::string RangeToString(const SourceBufferRange& range) { | 65 static std::string RangeToString(const SourceBufferRange& range) { |
| 61 std::stringstream ss; | 66 std::stringstream ss; |
| 62 ss << "[" << range.GetStartTimestamp().InSecondsF() | 67 ss << "[" << range.GetStartTimestamp().InSecondsF() |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 range_for_next_append_(ranges_.end()), | 112 range_for_next_append_(ranges_.end()), |
| 108 new_media_segment_(false), | 113 new_media_segment_(false), |
| 109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 114 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 110 last_appended_buffer_is_keyframe_(false), | 115 last_appended_buffer_is_keyframe_(false), |
| 111 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 116 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 112 max_interbuffer_distance_(kNoTimestamp()), | 117 max_interbuffer_distance_(kNoTimestamp()), |
| 113 memory_limit_(kSourceBufferAudioMemoryLimit), | 118 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 114 config_change_pending_(false), | 119 config_change_pending_(false), |
| 115 splice_buffers_index_(0), | 120 splice_buffers_index_(0), |
| 116 pending_buffers_complete_(false), | 121 pending_buffers_complete_(false), |
| 117 splice_frames_enabled_(splice_frames_enabled) { | 122 splice_frames_enabled_(splice_frames_enabled), |
| 123 num_splice_generation_warning_logs_(0), | |
| 124 num_splice_generation_success_logs_(0) { | |
| 118 DCHECK(audio_config.IsValidConfig()); | 125 DCHECK(audio_config.IsValidConfig()); |
| 119 audio_configs_.push_back(audio_config); | 126 audio_configs_.push_back(audio_config); |
| 120 } | 127 } |
| 121 | 128 |
| 122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 129 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
| 123 const scoped_refptr<MediaLog>& media_log, | 130 const scoped_refptr<MediaLog>& media_log, |
| 124 bool splice_frames_enabled) | 131 bool splice_frames_enabled) |
| 125 : media_log_(media_log), | 132 : media_log_(media_log), |
| 126 current_config_index_(0), | 133 current_config_index_(0), |
| 127 append_config_index_(0), | 134 append_config_index_(0), |
| 128 seek_pending_(false), | 135 seek_pending_(false), |
| 129 end_of_stream_(false), | 136 end_of_stream_(false), |
| 130 seek_buffer_timestamp_(kNoTimestamp()), | 137 seek_buffer_timestamp_(kNoTimestamp()), |
| 131 selected_range_(NULL), | 138 selected_range_(NULL), |
| 132 media_segment_start_time_(kNoDecodeTimestamp()), | 139 media_segment_start_time_(kNoDecodeTimestamp()), |
| 133 range_for_next_append_(ranges_.end()), | 140 range_for_next_append_(ranges_.end()), |
| 134 new_media_segment_(false), | 141 new_media_segment_(false), |
| 135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 142 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 136 last_appended_buffer_is_keyframe_(false), | 143 last_appended_buffer_is_keyframe_(false), |
| 137 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 144 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 138 max_interbuffer_distance_(kNoTimestamp()), | 145 max_interbuffer_distance_(kNoTimestamp()), |
| 139 memory_limit_(kSourceBufferVideoMemoryLimit), | 146 memory_limit_(kSourceBufferVideoMemoryLimit), |
| 140 config_change_pending_(false), | 147 config_change_pending_(false), |
| 141 splice_buffers_index_(0), | 148 splice_buffers_index_(0), |
| 142 pending_buffers_complete_(false), | 149 pending_buffers_complete_(false), |
| 143 splice_frames_enabled_(splice_frames_enabled) { | 150 splice_frames_enabled_(splice_frames_enabled), |
| 151 num_splice_generation_warning_logs_(0), | |
| 152 num_splice_generation_success_logs_(0) { | |
| 144 DCHECK(video_config.IsValidConfig()); | 153 DCHECK(video_config.IsValidConfig()); |
| 145 video_configs_.push_back(video_config); | 154 video_configs_.push_back(video_config); |
| 146 } | 155 } |
| 147 | 156 |
| 148 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 157 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
| 149 const scoped_refptr<MediaLog>& media_log, | 158 const scoped_refptr<MediaLog>& media_log, |
| 150 bool splice_frames_enabled) | 159 bool splice_frames_enabled) |
| 151 : media_log_(media_log), | 160 : media_log_(media_log), |
| 152 current_config_index_(0), | 161 current_config_index_(0), |
| 153 append_config_index_(0), | 162 append_config_index_(0), |
| 154 text_track_config_(text_config), | 163 text_track_config_(text_config), |
| 155 seek_pending_(false), | 164 seek_pending_(false), |
| 156 end_of_stream_(false), | 165 end_of_stream_(false), |
| 157 seek_buffer_timestamp_(kNoTimestamp()), | 166 seek_buffer_timestamp_(kNoTimestamp()), |
| 158 selected_range_(NULL), | 167 selected_range_(NULL), |
| 159 media_segment_start_time_(kNoDecodeTimestamp()), | 168 media_segment_start_time_(kNoDecodeTimestamp()), |
| 160 range_for_next_append_(ranges_.end()), | 169 range_for_next_append_(ranges_.end()), |
| 161 new_media_segment_(false), | 170 new_media_segment_(false), |
| 162 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 171 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 163 last_appended_buffer_is_keyframe_(false), | 172 last_appended_buffer_is_keyframe_(false), |
| 164 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 173 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 165 max_interbuffer_distance_(kNoTimestamp()), | 174 max_interbuffer_distance_(kNoTimestamp()), |
| 166 memory_limit_(kSourceBufferAudioMemoryLimit), | 175 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 167 config_change_pending_(false), | 176 config_change_pending_(false), |
| 168 splice_buffers_index_(0), | 177 splice_buffers_index_(0), |
| 169 pending_buffers_complete_(false), | 178 pending_buffers_complete_(false), |
| 170 splice_frames_enabled_(splice_frames_enabled) { | 179 splice_frames_enabled_(splice_frames_enabled), |
| 171 } | 180 num_splice_generation_warning_logs_(0), |
| 181 num_splice_generation_success_logs_(0) {} | |
| 172 | 182 |
| 173 SourceBufferStream::~SourceBufferStream() { | 183 SourceBufferStream::~SourceBufferStream() { |
| 174 while (!ranges_.empty()) { | 184 while (!ranges_.empty()) { |
| 175 delete ranges_.front(); | 185 delete ranges_.front(); |
| 176 ranges_.pop_front(); | 186 ranges_.pop_front(); |
| 177 } | 187 } |
| 178 } | 188 } |
| 179 | 189 |
| 180 void SourceBufferStream::OnNewMediaSegment( | 190 void SourceBufferStream::OnNewMediaSegment( |
| 181 DecodeTimestamp media_segment_start_time) { | 191 DecodeTimestamp media_segment_start_time) { |
| (...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1541 splice_dts, max_splice_end_dts, &pre_splice_buffers)) { | 1551 splice_dts, max_splice_end_dts, &pre_splice_buffers)) { |
| 1542 return; | 1552 return; |
| 1543 } | 1553 } |
| 1544 | 1554 |
| 1545 // If there are gaps in the timeline, it's possible that we only find buffers | 1555 // If there are gaps in the timeline, it's possible that we only find buffers |
| 1546 // after the splice point but within the splice range. For simplicity, we do | 1556 // after the splice point but within the splice range. For simplicity, we do |
| 1547 // not generate splice frames in this case. | 1557 // not generate splice frames in this case. |
| 1548 // | 1558 // |
| 1549 // We also do not want to generate splices if the first new buffer replaces an | 1559 // We also do not want to generate splices if the first new buffer replaces an |
| 1550 // existing buffer exactly. | 1560 // existing buffer exactly. |
| 1551 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) | 1561 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) { |
| 1562 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
| 1563 kMaxSpliceGenerationWarningLogs) | |
| 1564 << "Skipping splice frame buffering: first new buffer at " | |
|
DaleCurtis
2015/07/16 20:39:22
s/buffering/generation/ ditto for all the rest.
wolenetz
2015/07/17 17:38:15
Done
| |
| 1565 << splice_timestamp.InMicroseconds() | |
| 1566 << "us begins at or before existing buffer at " | |
| 1567 << pre_splice_buffers.front()->timestamp().InMicroseconds() << "us."; | |
| 1568 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the " | |
|
DaleCurtis
2015/07/16 20:39:21
Do we need both of these?
wolenetz
2015/07/17 17:38:15
I think the DVLOGs have value still (in the LIMITE
| |
| 1569 "first new buffer."; | |
| 1552 return; | 1570 return; |
| 1571 } | |
| 1553 | 1572 |
| 1554 // If any |pre_splice_buffers| are already splices or preroll, do not generate | 1573 // If any |pre_splice_buffers| are already splices or preroll, do not generate |
| 1555 // a splice. | 1574 // a splice. |
| 1556 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) { | 1575 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) { |
| 1557 const BufferQueue& original_splice_buffers = | 1576 const BufferQueue& original_splice_buffers = |
| 1558 pre_splice_buffers[i]->splice_buffers(); | 1577 pre_splice_buffers[i]->splice_buffers(); |
| 1559 if (!original_splice_buffers.empty()) { | 1578 if (!original_splice_buffers.empty()) { |
| 1579 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
| 1580 kMaxSpliceGenerationWarningLogs) | |
| 1581 << "Skipping splice frame buffering: overlapped buffers at " | |
| 1582 << pre_splice_buffers[i]->timestamp().InMicroseconds() | |
| 1583 << "us are in a previously buffered splice."; | |
| 1560 DVLOG(1) << "Can't generate splice: overlapped buffers contain a " | 1584 DVLOG(1) << "Can't generate splice: overlapped buffers contain a " |
| 1561 "pre-existing splice."; | 1585 "pre-existing splice."; |
| 1562 return; | 1586 return; |
| 1563 } | 1587 } |
| 1564 | 1588 |
| 1565 if (pre_splice_buffers[i]->preroll_buffer().get()) { | 1589 if (pre_splice_buffers[i]->preroll_buffer().get()) { |
| 1590 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
| 1591 kMaxSpliceGenerationWarningLogs) | |
| 1592 << "Skipping splice frame buffering: overlapped buffers at " | |
| 1593 << pre_splice_buffers[i]->timestamp().InMicroseconds() | |
| 1594 << "us contain preroll."; | |
| 1566 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll."; | 1595 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll."; |
| 1567 return; | 1596 return; |
| 1568 } | 1597 } |
| 1569 } | 1598 } |
| 1570 | 1599 |
| 1571 // Don't generate splice frames which represent less than a millisecond (which | 1600 // Don't generate splice frames which represent less than a millisecond (which |
| 1572 // is frequently the extent of timestamp resolution for poorly encoded media) | 1601 // is frequently the extent of timestamp resolution for poorly encoded media) |
| 1573 // or less than two frames (need at least two to crossfade). | 1602 // or less than two frames (need at least two to crossfade). |
| 1574 const base::TimeDelta splice_duration = | 1603 const base::TimeDelta splice_duration = |
| 1575 pre_splice_buffers.back()->timestamp() + | 1604 pre_splice_buffers.back()->timestamp() + |
| 1576 pre_splice_buffers.back()->duration() - splice_timestamp; | 1605 pre_splice_buffers.back()->duration() - splice_timestamp; |
| 1577 const base::TimeDelta minimum_splice_duration = std::max( | 1606 const base::TimeDelta minimum_splice_duration = std::max( |
| 1578 base::TimeDelta::FromMilliseconds(1), | 1607 base::TimeDelta::FromMilliseconds(1), |
| 1579 base::TimeDelta::FromSecondsD( | 1608 base::TimeDelta::FromSecondsD( |
| 1580 2.0 / audio_configs_[append_config_index_].samples_per_second())); | 1609 2.0 / audio_configs_[append_config_index_].samples_per_second())); |
| 1581 if (splice_duration < minimum_splice_duration) { | 1610 if (splice_duration < minimum_splice_duration) { |
| 1611 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
| 1612 kMaxSpliceGenerationWarningLogs) | |
| 1613 << "Skipping splice frame buffering: not enough samples for splicing " | |
| 1614 "new buffer at " | |
| 1615 << splice_timestamp.InMicroseconds() << "us. Have " | |
| 1616 << splice_duration.InMicroseconds() << "us, but need " | |
| 1617 << minimum_splice_duration.InMicroseconds() << "us."; | |
| 1582 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have " | 1618 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have " |
| 1583 << splice_duration.InMicroseconds() << " us, but need " | 1619 << splice_duration.InMicroseconds() << "us, but need " |
| 1584 << minimum_splice_duration.InMicroseconds() << " us."; | 1620 << minimum_splice_duration.InMicroseconds() << "us."; |
| 1585 return; | 1621 return; |
| 1586 } | 1622 } |
| 1587 | 1623 |
| 1588 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp() | 1624 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp() |
| 1589 << ", splice duration: " << splice_duration.InMicroseconds() | 1625 << ", splice duration: " << splice_duration.InMicroseconds() |
| 1590 << " us"; | 1626 << " us"; |
| 1627 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_success_logs_, | |
| 1628 kMaxSpliceGenerationSuccessLogs) | |
| 1629 << "Generated splice of overlap duration " | |
| 1630 << splice_duration.InMicroseconds() << "us into new buffer at " | |
| 1631 << splice_timestamp.InMicroseconds() << "us."; | |
| 1591 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers); | 1632 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers); |
| 1592 } | 1633 } |
| 1593 | 1634 |
| 1594 bool SourceBufferStream::SetPendingBuffer( | 1635 bool SourceBufferStream::SetPendingBuffer( |
| 1595 scoped_refptr<StreamParserBuffer>* out_buffer) { | 1636 scoped_refptr<StreamParserBuffer>* out_buffer) { |
| 1596 DCHECK(out_buffer->get()); | 1637 DCHECK(out_buffer->get()); |
| 1597 DCHECK(!pending_buffer_.get()); | 1638 DCHECK(!pending_buffer_.get()); |
| 1598 | 1639 |
| 1599 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty(); | 1640 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty(); |
| 1600 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); | 1641 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); |
| 1601 | 1642 |
| 1602 if (!have_splice_buffers && !have_preroll_buffer) | 1643 if (!have_splice_buffers && !have_preroll_buffer) |
| 1603 return false; | 1644 return false; |
| 1604 | 1645 |
| 1605 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1646 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
| 1606 splice_buffers_index_ = 0; | 1647 splice_buffers_index_ = 0; |
| 1607 pending_buffer_.swap(*out_buffer); | 1648 pending_buffer_.swap(*out_buffer); |
| 1608 pending_buffers_complete_ = false; | 1649 pending_buffers_complete_ = false; |
| 1609 return true; | 1650 return true; |
| 1610 } | 1651 } |
| 1611 | 1652 |
| 1612 } // namespace media | 1653 } // namespace media |
| OLD | NEW |