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 |