| 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;
|
| }
|
|
|