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 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
14 #include "media/base/audio_splicer.h" | 14 #include "media/base/audio_splicer.h" |
15 #include "media/filters/source_buffer_platform.h" | 15 #include "media/filters/source_buffer_platform.h" |
16 #include "media/filters/source_buffer_range.h" | 16 #include "media/filters/source_buffer_range.h" |
17 | 17 |
18 namespace media { | 18 namespace media { |
19 | 19 |
| 20 namespace { |
| 21 |
| 22 enum { |
| 23 // An arbitrarily-chosen number to estimate the duration of a buffer if none |
| 24 // is set and there's not enough information to get a better estimate. |
| 25 kDefaultBufferDurationInMs = 125, |
| 26 |
| 27 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings |
| 28 // and successes. Though these values are high enough to possibly exhaust the |
| 29 // media internals event cache (along with other events), these logs are |
| 30 // important for debugging splice generation. |
| 31 kMaxSpliceGenerationWarningLogs = 50, |
| 32 kMaxSpliceGenerationSuccessLogs = 20, |
| 33 }; |
| 34 |
20 // Helper method that returns true if |ranges| is sorted in increasing order, | 35 // Helper method that returns true if |ranges| is sorted in increasing order, |
21 // false otherwise. | 36 // false otherwise. |
22 static bool IsRangeListSorted( | 37 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { |
23 const std::list<media::SourceBufferRange*>& ranges) { | |
24 DecodeTimestamp prev = kNoDecodeTimestamp(); | 38 DecodeTimestamp prev = kNoDecodeTimestamp(); |
25 for (std::list<SourceBufferRange*>::const_iterator itr = | 39 for (std::list<SourceBufferRange*>::const_iterator itr = |
26 ranges.begin(); itr != ranges.end(); ++itr) { | 40 ranges.begin(); itr != ranges.end(); ++itr) { |
27 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 41 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) |
28 return false; | 42 return false; |
29 prev = (*itr)->GetEndTimestamp(); | 43 prev = (*itr)->GetEndTimestamp(); |
30 } | 44 } |
31 return true; | 45 return true; |
32 } | 46 } |
33 | 47 |
34 // Returns an estimate of how far from the beginning or end of a range a buffer | 48 // Returns an estimate of how far from the beginning or end of a range a buffer |
35 // can be to still be considered in the range, given the |approximate_duration| | 49 // can be to still be considered in the range, given the |approximate_duration| |
36 // of a buffer in the stream. | 50 // of a buffer in the stream. |
37 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use | 51 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use |
38 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp) | 52 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp) |
39 // instead of an overall maximum interbuffer delta for range discontinuity | 53 // instead of an overall maximum interbuffer delta for range discontinuity |
40 // detection, and adjust similarly for splice frame discontinuity detection. | 54 // detection, and adjust similarly for splice frame discontinuity detection. |
41 // See http://crbug.com/351489 and http://crbug.com/351166. | 55 // See http://crbug.com/351489 and http://crbug.com/351166. |
42 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { | 56 base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { |
43 // Because we do not know exactly when is the next timestamp, any buffer | 57 // 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 | 58 // that starts within 2x the approximate duration of a buffer is considered |
45 // within this range. | 59 // within this range. |
46 return 2 * approximate_duration; | 60 return 2 * approximate_duration; |
47 } | 61 } |
48 | 62 |
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. | |
51 static int kDefaultBufferDurationInMs = 125; | |
52 | |
53 // The amount of time the beginning of the buffered data can differ from the | 63 // 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. | 64 // start time in order to still be considered the start of stream. |
55 static base::TimeDelta kSeekToStartFudgeRoom() { | 65 base::TimeDelta kSeekToStartFudgeRoom() { |
56 return base::TimeDelta::FromMilliseconds(1000); | 66 return base::TimeDelta::FromMilliseconds(1000); |
57 } | 67 } |
58 | 68 |
59 // Helper method for logging, converts a range into a readable string. | 69 // Helper method for logging, converts a range into a readable string. |
60 static std::string RangeToString(const SourceBufferRange& range) { | 70 std::string RangeToString(const SourceBufferRange& range) { |
61 std::stringstream ss; | 71 std::stringstream ss; |
62 ss << "[" << range.GetStartTimestamp().InSecondsF() | 72 ss << "[" << range.GetStartTimestamp().InSecondsF() |
63 << ";" << range.GetEndTimestamp().InSecondsF() | 73 << ";" << range.GetEndTimestamp().InSecondsF() |
64 << "(" << range.GetBufferedEndTimestamp().InSecondsF() << ")]"; | 74 << "(" << range.GetBufferedEndTimestamp().InSecondsF() << ")]"; |
65 return ss.str(); | 75 return ss.str(); |
66 } | 76 } |
67 | 77 |
68 // Helper method for logging, converts a set of ranges into a readable string. | 78 // Helper method for logging, converts a set of ranges into a readable string. |
69 static std::string RangesToString(const SourceBufferStream::RangeList& ranges) { | 79 std::string RangesToString(const SourceBufferStream::RangeList& ranges) { |
70 if (ranges.empty()) | 80 if (ranges.empty()) |
71 return "<EMPTY>"; | 81 return "<EMPTY>"; |
72 | 82 |
73 std::stringstream ss; | 83 std::stringstream ss; |
74 for (const auto* range_ptr : ranges) { | 84 for (const auto* range_ptr : ranges) { |
75 if (range_ptr != ranges.front()) | 85 if (range_ptr != ranges.front()) |
76 ss << " "; | 86 ss << " "; |
77 ss << RangeToString(*range_ptr); | 87 ss << RangeToString(*range_ptr); |
78 } | 88 } |
79 return ss.str(); | 89 return ss.str(); |
80 } | 90 } |
81 | 91 |
82 static SourceBufferRange::GapPolicy TypeToGapPolicy( | 92 SourceBufferRange::GapPolicy TypeToGapPolicy(SourceBufferStream::Type type) { |
83 SourceBufferStream::Type type) { | |
84 switch (type) { | 93 switch (type) { |
85 case SourceBufferStream::kAudio: | 94 case SourceBufferStream::kAudio: |
86 case SourceBufferStream::kVideo: | 95 case SourceBufferStream::kVideo: |
87 return SourceBufferRange::NO_GAPS_ALLOWED; | 96 return SourceBufferRange::NO_GAPS_ALLOWED; |
88 case SourceBufferStream::kText: | 97 case SourceBufferStream::kText: |
89 return SourceBufferRange::ALLOW_GAPS; | 98 return SourceBufferRange::ALLOW_GAPS; |
90 } | 99 } |
91 | 100 |
92 NOTREACHED(); | 101 NOTREACHED(); |
93 return SourceBufferRange::NO_GAPS_ALLOWED; | 102 return SourceBufferRange::NO_GAPS_ALLOWED; |
94 } | 103 } |
95 | 104 |
| 105 } // namespace |
| 106 |
96 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 107 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
97 const scoped_refptr<MediaLog>& media_log, | 108 const scoped_refptr<MediaLog>& media_log, |
98 bool splice_frames_enabled) | 109 bool splice_frames_enabled) |
99 : media_log_(media_log), | 110 : media_log_(media_log), |
100 current_config_index_(0), | 111 current_config_index_(0), |
101 append_config_index_(0), | 112 append_config_index_(0), |
102 seek_pending_(false), | 113 seek_pending_(false), |
103 end_of_stream_(false), | 114 end_of_stream_(false), |
104 seek_buffer_timestamp_(kNoTimestamp()), | 115 seek_buffer_timestamp_(kNoTimestamp()), |
105 selected_range_(NULL), | 116 selected_range_(NULL), |
106 media_segment_start_time_(kNoDecodeTimestamp()), | 117 media_segment_start_time_(kNoDecodeTimestamp()), |
107 range_for_next_append_(ranges_.end()), | 118 range_for_next_append_(ranges_.end()), |
108 new_media_segment_(false), | 119 new_media_segment_(false), |
109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 120 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
110 last_appended_buffer_is_keyframe_(false), | 121 last_appended_buffer_is_keyframe_(false), |
111 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 122 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
112 max_interbuffer_distance_(kNoTimestamp()), | 123 max_interbuffer_distance_(kNoTimestamp()), |
113 memory_limit_(kSourceBufferAudioMemoryLimit), | 124 memory_limit_(kSourceBufferAudioMemoryLimit), |
114 config_change_pending_(false), | 125 config_change_pending_(false), |
115 splice_buffers_index_(0), | 126 splice_buffers_index_(0), |
116 pending_buffers_complete_(false), | 127 pending_buffers_complete_(false), |
117 splice_frames_enabled_(splice_frames_enabled) { | 128 splice_frames_enabled_(splice_frames_enabled), |
| 129 num_splice_generation_warning_logs_(0), |
| 130 num_splice_generation_success_logs_(0) { |
118 DCHECK(audio_config.IsValidConfig()); | 131 DCHECK(audio_config.IsValidConfig()); |
119 audio_configs_.push_back(audio_config); | 132 audio_configs_.push_back(audio_config); |
120 } | 133 } |
121 | 134 |
122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 135 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
123 const scoped_refptr<MediaLog>& media_log, | 136 const scoped_refptr<MediaLog>& media_log, |
124 bool splice_frames_enabled) | 137 bool splice_frames_enabled) |
125 : media_log_(media_log), | 138 : media_log_(media_log), |
126 current_config_index_(0), | 139 current_config_index_(0), |
127 append_config_index_(0), | 140 append_config_index_(0), |
128 seek_pending_(false), | 141 seek_pending_(false), |
129 end_of_stream_(false), | 142 end_of_stream_(false), |
130 seek_buffer_timestamp_(kNoTimestamp()), | 143 seek_buffer_timestamp_(kNoTimestamp()), |
131 selected_range_(NULL), | 144 selected_range_(NULL), |
132 media_segment_start_time_(kNoDecodeTimestamp()), | 145 media_segment_start_time_(kNoDecodeTimestamp()), |
133 range_for_next_append_(ranges_.end()), | 146 range_for_next_append_(ranges_.end()), |
134 new_media_segment_(false), | 147 new_media_segment_(false), |
135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 148 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
136 last_appended_buffer_is_keyframe_(false), | 149 last_appended_buffer_is_keyframe_(false), |
137 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 150 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
138 max_interbuffer_distance_(kNoTimestamp()), | 151 max_interbuffer_distance_(kNoTimestamp()), |
139 memory_limit_(kSourceBufferVideoMemoryLimit), | 152 memory_limit_(kSourceBufferVideoMemoryLimit), |
140 config_change_pending_(false), | 153 config_change_pending_(false), |
141 splice_buffers_index_(0), | 154 splice_buffers_index_(0), |
142 pending_buffers_complete_(false), | 155 pending_buffers_complete_(false), |
143 splice_frames_enabled_(splice_frames_enabled) { | 156 splice_frames_enabled_(splice_frames_enabled), |
| 157 num_splice_generation_warning_logs_(0), |
| 158 num_splice_generation_success_logs_(0) { |
144 DCHECK(video_config.IsValidConfig()); | 159 DCHECK(video_config.IsValidConfig()); |
145 video_configs_.push_back(video_config); | 160 video_configs_.push_back(video_config); |
146 } | 161 } |
147 | 162 |
148 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 163 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
149 const scoped_refptr<MediaLog>& media_log, | 164 const scoped_refptr<MediaLog>& media_log, |
150 bool splice_frames_enabled) | 165 bool splice_frames_enabled) |
151 : media_log_(media_log), | 166 : media_log_(media_log), |
152 current_config_index_(0), | 167 current_config_index_(0), |
153 append_config_index_(0), | 168 append_config_index_(0), |
154 text_track_config_(text_config), | 169 text_track_config_(text_config), |
155 seek_pending_(false), | 170 seek_pending_(false), |
156 end_of_stream_(false), | 171 end_of_stream_(false), |
157 seek_buffer_timestamp_(kNoTimestamp()), | 172 seek_buffer_timestamp_(kNoTimestamp()), |
158 selected_range_(NULL), | 173 selected_range_(NULL), |
159 media_segment_start_time_(kNoDecodeTimestamp()), | 174 media_segment_start_time_(kNoDecodeTimestamp()), |
160 range_for_next_append_(ranges_.end()), | 175 range_for_next_append_(ranges_.end()), |
161 new_media_segment_(false), | 176 new_media_segment_(false), |
162 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 177 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
163 last_appended_buffer_is_keyframe_(false), | 178 last_appended_buffer_is_keyframe_(false), |
164 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 179 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
165 max_interbuffer_distance_(kNoTimestamp()), | 180 max_interbuffer_distance_(kNoTimestamp()), |
166 memory_limit_(kSourceBufferAudioMemoryLimit), | 181 memory_limit_(kSourceBufferAudioMemoryLimit), |
167 config_change_pending_(false), | 182 config_change_pending_(false), |
168 splice_buffers_index_(0), | 183 splice_buffers_index_(0), |
169 pending_buffers_complete_(false), | 184 pending_buffers_complete_(false), |
170 splice_frames_enabled_(splice_frames_enabled) { | 185 splice_frames_enabled_(splice_frames_enabled), |
171 } | 186 num_splice_generation_warning_logs_(0), |
| 187 num_splice_generation_success_logs_(0) {} |
172 | 188 |
173 SourceBufferStream::~SourceBufferStream() { | 189 SourceBufferStream::~SourceBufferStream() { |
174 while (!ranges_.empty()) { | 190 while (!ranges_.empty()) { |
175 delete ranges_.front(); | 191 delete ranges_.front(); |
176 ranges_.pop_front(); | 192 ranges_.pop_front(); |
177 } | 193 } |
178 } | 194 } |
179 | 195 |
180 void SourceBufferStream::OnNewMediaSegment( | 196 void SourceBufferStream::OnNewMediaSegment( |
181 DecodeTimestamp media_segment_start_time) { | 197 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)) { | 1557 splice_dts, max_splice_end_dts, &pre_splice_buffers)) { |
1542 return; | 1558 return; |
1543 } | 1559 } |
1544 | 1560 |
1545 // If there are gaps in the timeline, it's possible that we only find buffers | 1561 // 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 | 1562 // after the splice point but within the splice range. For simplicity, we do |
1547 // not generate splice frames in this case. | 1563 // not generate splice frames in this case. |
1548 // | 1564 // |
1549 // We also do not want to generate splices if the first new buffer replaces an | 1565 // We also do not want to generate splices if the first new buffer replaces an |
1550 // existing buffer exactly. | 1566 // existing buffer exactly. |
1551 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) | 1567 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) { |
| 1568 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
| 1569 kMaxSpliceGenerationWarningLogs) |
| 1570 << "Skipping splice frame generation: first new buffer at " |
| 1571 << splice_timestamp.InMicroseconds() |
| 1572 << "us begins at or before existing buffer at " |
| 1573 << pre_splice_buffers.front()->timestamp().InMicroseconds() << "us."; |
| 1574 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the " |
| 1575 "first new buffer."; |
1552 return; | 1576 return; |
| 1577 } |
1553 | 1578 |
1554 // If any |pre_splice_buffers| are already splices or preroll, do not generate | 1579 // If any |pre_splice_buffers| are already splices or preroll, do not generate |
1555 // a splice. | 1580 // a splice. |
1556 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) { | 1581 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) { |
1557 const BufferQueue& original_splice_buffers = | 1582 const BufferQueue& original_splice_buffers = |
1558 pre_splice_buffers[i]->splice_buffers(); | 1583 pre_splice_buffers[i]->splice_buffers(); |
1559 if (!original_splice_buffers.empty()) { | 1584 if (!original_splice_buffers.empty()) { |
| 1585 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
| 1586 kMaxSpliceGenerationWarningLogs) |
| 1587 << "Skipping splice frame generation: overlapped buffers at " |
| 1588 << pre_splice_buffers[i]->timestamp().InMicroseconds() |
| 1589 << "us are in a previously buffered splice."; |
1560 DVLOG(1) << "Can't generate splice: overlapped buffers contain a " | 1590 DVLOG(1) << "Can't generate splice: overlapped buffers contain a " |
1561 "pre-existing splice."; | 1591 "pre-existing splice."; |
1562 return; | 1592 return; |
1563 } | 1593 } |
1564 | 1594 |
1565 if (pre_splice_buffers[i]->preroll_buffer().get()) { | 1595 if (pre_splice_buffers[i]->preroll_buffer().get()) { |
| 1596 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
| 1597 kMaxSpliceGenerationWarningLogs) |
| 1598 << "Skipping splice frame generation: overlapped buffers at " |
| 1599 << pre_splice_buffers[i]->timestamp().InMicroseconds() |
| 1600 << "us contain preroll."; |
1566 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll."; | 1601 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll."; |
1567 return; | 1602 return; |
1568 } | 1603 } |
1569 } | 1604 } |
1570 | 1605 |
1571 // Don't generate splice frames which represent less than a millisecond (which | 1606 // Don't generate splice frames which represent less than a millisecond (which |
1572 // is frequently the extent of timestamp resolution for poorly encoded media) | 1607 // is frequently the extent of timestamp resolution for poorly encoded media) |
1573 // or less than two frames (need at least two to crossfade). | 1608 // or less than two samples (need at least two to crossfade). |
1574 const base::TimeDelta splice_duration = | 1609 const base::TimeDelta splice_duration = |
1575 pre_splice_buffers.back()->timestamp() + | 1610 pre_splice_buffers.back()->timestamp() + |
1576 pre_splice_buffers.back()->duration() - splice_timestamp; | 1611 pre_splice_buffers.back()->duration() - splice_timestamp; |
1577 const base::TimeDelta minimum_splice_duration = std::max( | 1612 const base::TimeDelta minimum_splice_duration = std::max( |
1578 base::TimeDelta::FromMilliseconds(1), | 1613 base::TimeDelta::FromMilliseconds(1), |
1579 base::TimeDelta::FromSecondsD( | 1614 base::TimeDelta::FromSecondsD( |
1580 2.0 / audio_configs_[append_config_index_].samples_per_second())); | 1615 2.0 / audio_configs_[append_config_index_].samples_per_second())); |
1581 if (splice_duration < minimum_splice_duration) { | 1616 if (splice_duration < minimum_splice_duration) { |
| 1617 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
| 1618 kMaxSpliceGenerationWarningLogs) |
| 1619 << "Skipping splice frame generation: not enough samples for splicing " |
| 1620 "new buffer at " |
| 1621 << splice_timestamp.InMicroseconds() << "us. Have " |
| 1622 << splice_duration.InMicroseconds() << "us, but need " |
| 1623 << minimum_splice_duration.InMicroseconds() << "us."; |
1582 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have " | 1624 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have " |
1583 << splice_duration.InMicroseconds() << " us, but need " | 1625 << splice_duration.InMicroseconds() << "us, but need " |
1584 << minimum_splice_duration.InMicroseconds() << " us."; | 1626 << minimum_splice_duration.InMicroseconds() << "us."; |
1585 return; | 1627 return; |
1586 } | 1628 } |
1587 | 1629 |
1588 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp() | 1630 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp() |
1589 << ", splice duration: " << splice_duration.InMicroseconds() | 1631 << ", splice duration: " << splice_duration.InMicroseconds() |
1590 << " us"; | 1632 << " us"; |
| 1633 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_success_logs_, |
| 1634 kMaxSpliceGenerationSuccessLogs) |
| 1635 << "Generated splice of overlap duration " |
| 1636 << splice_duration.InMicroseconds() << "us into new buffer at " |
| 1637 << splice_timestamp.InMicroseconds() << "us."; |
1591 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers); | 1638 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers); |
1592 } | 1639 } |
1593 | 1640 |
1594 bool SourceBufferStream::SetPendingBuffer( | 1641 bool SourceBufferStream::SetPendingBuffer( |
1595 scoped_refptr<StreamParserBuffer>* out_buffer) { | 1642 scoped_refptr<StreamParserBuffer>* out_buffer) { |
1596 DCHECK(out_buffer->get()); | 1643 DCHECK(out_buffer->get()); |
1597 DCHECK(!pending_buffer_.get()); | 1644 DCHECK(!pending_buffer_.get()); |
1598 | 1645 |
1599 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty(); | 1646 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty(); |
1600 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); | 1647 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); |
1601 | 1648 |
1602 if (!have_splice_buffers && !have_preroll_buffer) | 1649 if (!have_splice_buffers && !have_preroll_buffer) |
1603 return false; | 1650 return false; |
1604 | 1651 |
1605 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1652 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1606 splice_buffers_index_ = 0; | 1653 splice_buffers_index_ = 0; |
1607 pending_buffer_.swap(*out_buffer); | 1654 pending_buffer_.swap(*out_buffer); |
1608 pending_buffers_complete_ = false; | 1655 pending_buffers_complete_ = false; |
1609 return true; | 1656 return true; |
1610 } | 1657 } |
1611 | 1658 |
1612 } // namespace media | 1659 } // namespace media |
OLD | NEW |