Index: media/base/android/access_unit_queue.cc |
diff --git a/media/base/android/access_unit_queue.cc b/media/base/android/access_unit_queue.cc |
index 38d45f5468038bf3f6dc263da214edd40c3d402b..fed3529cae410432cec932dfd877fb83b64fe678 100644 |
--- a/media/base/android/access_unit_queue.cc |
+++ b/media/base/android/access_unit_queue.cc |
@@ -20,7 +20,8 @@ const int kDefaultHistoryChunksAmount = 0; |
AccessUnitQueue::AccessUnitQueue() |
: index_in_chunk_(0), |
history_chunks_amount_(kDefaultHistoryChunksAmount), |
- has_eos_(false) { |
+ has_eos_(false), |
+ emulate_config_changes_(false) { |
current_chunk_ = chunks_.end(); |
} |
@@ -57,29 +58,35 @@ void AccessUnitQueue::PushBack(const DemuxerData& data) { |
#endif |
// Create the next chunk and copy data to it. |
- DemuxerData* chunk = new DemuxerData(data); |
+ // It might be split if we emulate config changes |
+ std::vector<DemuxerData*> cloned_data = CloneData(data); |
+ DCHECK(!cloned_data.empty()); |
// EOS flag can only be in the last access unit. |
- bool has_eos = chunk->access_units.back().is_end_of_stream; |
+ bool has_eos = cloned_data.back()->access_units.back().is_end_of_stream; |
// Append this chunk to the queue. |
base::AutoLock lock(lock_); |
// Ignore the input after we have received EOS. |
if (has_eos_) { |
- delete chunk; |
+ for (DemuxerData* chunk : cloned_data) |
+ delete chunk; |
+ |
return; |
} |
- bool was_empty = (current_chunk_ == chunks_.end()); |
+ for (DemuxerData* chunk : cloned_data) { |
+ bool was_empty = (current_chunk_ == chunks_.end()); |
- // The container |chunks_| will own the chunk. |
- chunks_.push_back(chunk); |
+ // The container |chunks_| will own the chunk. |
+ chunks_.push_back(chunk); |
- // Position the current chunk. |
- if (was_empty) { |
- current_chunk_ = --chunks_.end(); |
- index_in_chunk_ = 0; |
+ // Position the current chunk. |
+ if (was_empty) { |
+ current_chunk_ = --chunks_.end(); |
+ index_in_chunk_ = 0; |
+ } |
} |
// We expect that the chunk containing EOS is the last chunk. |
@@ -182,16 +189,62 @@ AccessUnitQueue::Info AccessUnitQueue::GetInfo() const { |
return info; |
} |
+void AccessUnitQueue::EmulateConfigChanges(bool value) { |
+ emulate_config_changes_ = value; |
+} |
+ |
+void AccessUnitQueue::SetLastConfigs(const DemuxerConfigs& configs) { |
+ if (emulate_config_changes_) |
+ last_configs_ = configs; |
+} |
+ |
void AccessUnitQueue::SetHistorySizeForTesting(size_t history_chunks_amount) { |
history_chunks_amount_ = history_chunks_amount; |
} |
+std::vector<DemuxerData*> AccessUnitQueue::CloneData(const DemuxerData& data) { |
+ if (emulate_config_changes_ && |
+ (last_configs_.audio_codec != kUnknownAudioCodec || |
+ last_configs_.video_codec != kUnknownVideoCodec)) { |
+ std::vector<AccessUnit>::const_iterator begin = data.access_units.begin(); |
+ std::vector<AccessUnit>::const_iterator end = data.access_units.end(); |
+ std::vector<AccessUnit>::const_iterator key_frame; |
+ for (key_frame = begin; key_frame != end; ++key_frame) |
+ if (key_frame->is_key_frame) |
+ break; |
+ |
+ if (key_frame != end) { |
+ std::vector<DemuxerData*> result; |
+ |
+ result.push_back(new DemuxerData()); |
+ result.back()->access_units = std::vector<AccessUnit>(begin, key_frame); |
+ result.back()->access_units.push_back(AccessUnit()); |
+ result.back()->access_units.back().status = DemuxerStream::kConfigChanged; |
+ result.back()->demuxer_configs.push_back(last_configs_); |
+ |
+ result.push_back(new DemuxerData()); |
+ result.back()->access_units = std::vector<AccessUnit>(key_frame, end); |
+ |
+ return result; |
+ } |
+ } |
+ |
+ return std::vector<DemuxerData*>(1, new DemuxerData(data)); |
+} |
+ |
int AccessUnitQueue::GetUnconsumedAccessUnitLength() const { |
int result = 0; |
DataChunkQueue::const_iterator chunk; |
- for (chunk = current_chunk_; chunk != chunks_.end(); ++chunk) |
+ for (chunk = current_chunk_; chunk != chunks_.end(); ++chunk) { |
result += (*chunk)->access_units.size(); |
+ // Do not count configuration changes. |
+ if (!(*chunk)->demuxer_configs.empty()) { |
+ DCHECK((*chunk)->demuxer_configs.size() == 1); |
+ --result; |
+ } |
+ } |
+ |
result -= index_in_chunk_; |
return result; |
} |