| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/base/android/test_data_factory.h" | 5 #include "media/base/android/test_data_factory.h" |
| 6 | 6 |
| 7 #include <iterator> |
| 8 |
| 7 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 8 #include "media/base/android/demuxer_stream_player_params.h" | 10 #include "media/base/android/demuxer_stream_player_params.h" |
| 9 #include "media/base/decoder_buffer.h" | 11 #include "media/base/decoder_buffer.h" |
| 10 #include "media/base/test_data_util.h" | 12 #include "media/base/test_data_util.h" |
| 11 | 13 |
| 12 namespace media { | 14 namespace media { |
| 13 | 15 |
| 14 DemuxerConfigs TestDataFactory::CreateAudioConfigs(AudioCodec audio_codec, | 16 DemuxerConfigs TestDataFactory::CreateAudioConfigs(AudioCodec audio_codec, |
| 15 base::TimeDelta duration) { | 17 base::TimeDelta duration) { |
| 16 DemuxerConfigs configs; | 18 DemuxerConfigs configs; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 configs.duration = duration; | 55 configs.duration = duration; |
| 54 | 56 |
| 55 return configs; | 57 return configs; |
| 56 } | 58 } |
| 57 | 59 |
| 58 TestDataFactory::TestDataFactory(const char* file_name_template, | 60 TestDataFactory::TestDataFactory(const char* file_name_template, |
| 59 base::TimeDelta duration, | 61 base::TimeDelta duration, |
| 60 base::TimeDelta frame_period) | 62 base::TimeDelta frame_period) |
| 61 : duration_(duration), | 63 : duration_(duration), |
| 62 frame_period_(frame_period), | 64 frame_period_(frame_period), |
| 65 total_chunks_(0), |
| 63 starvation_mode_(false), | 66 starvation_mode_(false), |
| 64 eos_reached_(false) { | 67 eos_reached_(false) { |
| 65 LoadPackets(file_name_template); | 68 LoadPackets(file_name_template); |
| 66 } | 69 } |
| 67 | 70 |
| 68 TestDataFactory::~TestDataFactory() {} | 71 TestDataFactory::~TestDataFactory() {} |
| 69 | 72 |
| 70 bool TestDataFactory::CreateChunk(DemuxerData* chunk, base::TimeDelta* delay) { | 73 bool TestDataFactory::CreateChunk(DemuxerData* chunk, base::TimeDelta* delay) { |
| 71 DCHECK(chunk); | 74 DCHECK(chunk); |
| 72 DCHECK(delay); | 75 DCHECK(delay); |
| 73 | 76 |
| 74 if (eos_reached_) | 77 if (eos_reached_) |
| 75 return false; | 78 return false; |
| 76 | 79 |
| 77 *delay = base::TimeDelta(); | 80 *delay = base::TimeDelta(); |
| 78 | 81 |
| 82 if (!total_chunks_ && |
| 83 HasReconfigForInterval(base::TimeDelta::FromMilliseconds(-1), |
| 84 base::TimeDelta())) { |
| 85 // Since the configs AU has to come last in the chunk the initial configs |
| 86 // preceeding any other data has to be the only unit in the chunk. |
| 87 AddConfiguration(chunk); |
| 88 ++total_chunks_; |
| 89 return true; |
| 90 } |
| 91 |
| 79 for (int i = 0; i < 4; ++i) { | 92 for (int i = 0; i < 4; ++i) { |
| 80 chunk->access_units.push_back(AccessUnit()); | 93 chunk->access_units.push_back(AccessUnit()); |
| 81 AccessUnit& unit = chunk->access_units.back(); | 94 AccessUnit& unit = chunk->access_units.back(); |
| 82 unit.status = DemuxerStream::kOk; | 95 unit.status = DemuxerStream::kOk; |
| 83 | 96 |
| 84 unit.timestamp = regular_pts_; | 97 unit.timestamp = regular_pts_; |
| 85 regular_pts_ += frame_period_; | 98 regular_pts_ += frame_period_; |
| 86 | 99 |
| 87 if (unit.timestamp > duration_) { | 100 if (unit.timestamp > duration_) { |
| 88 if (starvation_mode_) | 101 if (starvation_mode_) |
| 89 return false; | 102 return false; |
| 90 | 103 |
| 91 unit.is_end_of_stream = true; | 104 unit.is_end_of_stream = true; |
| 92 eos_reached_ = true; | 105 eos_reached_ = true; |
| 93 break; // EOS units have no data. | 106 break; // EOS units have no data. |
| 94 } | 107 } |
| 95 | 108 |
| 96 unit.data = packet_[i]; | 109 unit.data = packet_[i]; |
| 97 | 110 |
| 98 // Allow for modification by subclasses. | 111 // Allow for modification by subclasses. |
| 99 ModifyAccessUnit(i, &unit); | 112 ModifyAccessUnit(i, &unit); |
| 100 | 113 |
| 101 // Maintain last PTS. ModifyAccessUnit() can modify unit's PTS. | 114 // Maintain last PTS. ModifyAccessUnit() can modify unit's PTS. |
| 102 if (last_pts_ < unit.timestamp) | 115 if (last_pts_ < unit.timestamp) |
| 103 last_pts_ = unit.timestamp; | 116 last_pts_ = unit.timestamp; |
| 104 } | 117 } |
| 105 | 118 |
| 119 // Replace last access unit with |kConfigChanged| if we have a config |
| 120 // request for the chunk's interval. |
| 121 base::TimeDelta chunk_end_pts = regular_pts_; |
| 122 |
| 123 // The interval is [first, last) |
| 124 if (HasReconfigForInterval(chunk_begin_pts_, chunk_end_pts)) { |
| 125 eos_reached_ = false; |
| 126 regular_pts_ -= frame_period_; |
| 127 chunk->access_units.pop_back(); |
| 128 AddConfiguration(chunk); |
| 129 } |
| 130 chunk_begin_pts_ = chunk_end_pts; |
| 131 |
| 132 ++total_chunks_; |
| 106 return true; | 133 return true; |
| 107 } | 134 } |
| 108 | 135 |
| 109 void TestDataFactory::SeekTo(const base::TimeDelta& seek_time) { | 136 void TestDataFactory::SeekTo(const base::TimeDelta& seek_time) { |
| 110 regular_pts_ = seek_time; | 137 regular_pts_ = seek_time; |
| 138 chunk_begin_pts_ = seek_time; |
| 111 last_pts_ = base::TimeDelta(); | 139 last_pts_ = base::TimeDelta(); |
| 112 eos_reached_ = false; | 140 eos_reached_ = false; |
| 113 } | 141 } |
| 114 | 142 |
| 143 void TestDataFactory::RequestInitialConfigs() { |
| 144 reconfigs_.insert(base::TimeDelta::FromMilliseconds(-1)); |
| 145 } |
| 146 |
| 147 void TestDataFactory::RequestConfigChange(base::TimeDelta config_position) { |
| 148 reconfigs_.insert(config_position); |
| 149 } |
| 150 |
| 115 void TestDataFactory::LoadPackets(const char* file_name_template) { | 151 void TestDataFactory::LoadPackets(const char* file_name_template) { |
| 116 for (int i = 0; i < 4; ++i) { | 152 for (int i = 0; i < 4; ++i) { |
| 117 scoped_refptr<DecoderBuffer> buffer = | 153 scoped_refptr<DecoderBuffer> buffer = |
| 118 ReadTestDataFile(base::StringPrintf(file_name_template, i)); | 154 ReadTestDataFile(base::StringPrintf(file_name_template, i)); |
| 119 packet_[i] = std::vector<uint8>(buffer->data(), | 155 packet_[i] = std::vector<uint8>(buffer->data(), |
| 120 buffer->data() + buffer->data_size()); | 156 buffer->data() + buffer->data_size()); |
| 121 } | 157 } |
| 122 } | 158 } |
| 123 | 159 |
| 160 bool TestDataFactory::HasReconfigForInterval(base::TimeDelta left, |
| 161 base::TimeDelta right) const { |
| 162 // |first| points to an element greater or equal to |left|. |
| 163 PTSSet::const_iterator first = reconfigs_.lower_bound(left); |
| 164 |
| 165 // |last| points to an element greater or equal to |right|. |
| 166 PTSSet::const_iterator last = reconfigs_.lower_bound(right); |
| 167 |
| 168 return std::distance(first, last); |
| 169 } |
| 170 |
| 171 void TestDataFactory::AddConfiguration(DemuxerData* chunk) { |
| 172 DCHECK(chunk); |
| 173 chunk->access_units.push_back(AccessUnit()); |
| 174 AccessUnit& unit = chunk->access_units.back(); |
| 175 unit.status = DemuxerStream::kConfigChanged; |
| 176 |
| 177 DCHECK(chunk->demuxer_configs.empty()); |
| 178 chunk->demuxer_configs.push_back(GetConfigs()); |
| 179 } |
| 180 |
| 124 } // namespace media | 181 } // namespace media |
| OLD | NEW |