Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / formats / mp2t / mp2t_stream_parser_unittest.cc
blob6663a054814262dca5aa63809798656d3f6328db
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <algorithm>
6 #include <string>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/time/time.h"
13 #include "media/base/audio_decoder_config.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/stream_parser_buffer.h"
16 #include "media/base/test_data_util.h"
17 #include "media/base/text_track_config.h"
18 #include "media/base/video_decoder_config.h"
19 #include "media/formats/mp2t/mp2t_stream_parser.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 namespace media {
23 namespace mp2t {
25 namespace {
27 bool IsMonotonic(const StreamParser::BufferQueue& buffers) {
28 if (buffers.empty())
29 return true;
31 StreamParser::BufferQueue::const_iterator it1 = buffers.begin();
32 StreamParser::BufferQueue::const_iterator it2 = ++it1;
33 for ( ; it2 != buffers.end(); ++it1, ++it2) {
34 if ((*it2)->GetDecodeTimestamp() < (*it1)->GetDecodeTimestamp())
35 return false;
37 return true;
40 bool IsAlmostEqual(DecodeTimestamp t0, DecodeTimestamp t1) {
41 base::TimeDelta kMaxDeviation = base::TimeDelta::FromMilliseconds(5);
42 base::TimeDelta diff = t1 - t0;
43 return (diff >= -kMaxDeviation && diff <= kMaxDeviation);
46 } // namespace
48 class Mp2tStreamParserTest : public testing::Test {
49 public:
50 Mp2tStreamParserTest()
51 : segment_count_(0),
52 config_count_(0),
53 audio_frame_count_(0),
54 video_frame_count_(0),
55 has_video_(true),
56 audio_min_dts_(kNoDecodeTimestamp()),
57 audio_max_dts_(kNoDecodeTimestamp()),
58 video_min_dts_(kNoDecodeTimestamp()),
59 video_max_dts_(kNoDecodeTimestamp()) {
60 bool has_sbr = false;
61 parser_.reset(new Mp2tStreamParser(has_sbr));
64 protected:
65 scoped_ptr<Mp2tStreamParser> parser_;
66 int segment_count_;
67 int config_count_;
68 int audio_frame_count_;
69 int video_frame_count_;
70 bool has_video_;
71 DecodeTimestamp audio_min_dts_;
72 DecodeTimestamp audio_max_dts_;
73 DecodeTimestamp video_min_dts_;
74 DecodeTimestamp video_max_dts_;
76 void ResetStats() {
77 segment_count_ = 0;
78 config_count_ = 0;
79 audio_frame_count_ = 0;
80 video_frame_count_ = 0;
81 audio_min_dts_ = kNoDecodeTimestamp();
82 audio_max_dts_ = kNoDecodeTimestamp();
83 video_min_dts_ = kNoDecodeTimestamp();
84 video_max_dts_ = kNoDecodeTimestamp();
87 bool AppendData(const uint8* data, size_t length) {
88 return parser_->Parse(data, length);
91 bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
92 const uint8* start = data;
93 const uint8* end = data + length;
94 while (start < end) {
95 size_t append_size = std::min(piece_size,
96 static_cast<size_t>(end - start));
97 if (!AppendData(start, append_size))
98 return false;
99 start += append_size;
101 return true;
104 void OnInit(const StreamParser::InitParameters& params) {
105 DVLOG(1) << "OnInit: dur=" << params.duration.InMilliseconds()
106 << ", autoTimestampOffset=" << params.auto_update_timestamp_offset;
109 bool OnNewConfig(const AudioDecoderConfig& ac,
110 const VideoDecoderConfig& vc,
111 const StreamParser::TextTrackConfigMap& tc) {
112 DVLOG(1) << "OnNewConfig: audio=" << ac.IsValidConfig()
113 << ", video=" << vc.IsValidConfig();
114 config_count_++;
115 EXPECT_TRUE(ac.IsValidConfig());
116 EXPECT_EQ(vc.IsValidConfig(), has_video_);
117 return true;
121 void DumpBuffers(const std::string& label,
122 const StreamParser::BufferQueue& buffers) {
123 DVLOG(2) << "DumpBuffers: " << label << " size " << buffers.size();
124 for (StreamParser::BufferQueue::const_iterator buf = buffers.begin();
125 buf != buffers.end(); buf++) {
126 DVLOG(3) << " n=" << buf - buffers.begin()
127 << ", size=" << (*buf)->data_size()
128 << ", dur=" << (*buf)->duration().InMilliseconds();
132 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
133 const StreamParser::BufferQueue& video_buffers,
134 const StreamParser::TextBufferQueueMap& text_map) {
135 EXPECT_GT(config_count_, 0);
136 DumpBuffers("audio_buffers", audio_buffers);
137 DumpBuffers("video_buffers", video_buffers);
139 // TODO(wolenetz/acolwell): Add text track support to more MSE parsers. See
140 // http://crbug.com/336926.
141 if (!text_map.empty())
142 return false;
144 // Verify monotonicity.
145 if (!IsMonotonic(video_buffers))
146 return false;
147 if (!IsMonotonic(audio_buffers))
148 return false;
150 if (!video_buffers.empty()) {
151 DecodeTimestamp first_dts = video_buffers.front()->GetDecodeTimestamp();
152 DecodeTimestamp last_dts = video_buffers.back()->GetDecodeTimestamp();
153 if (video_max_dts_ != kNoDecodeTimestamp() && first_dts < video_max_dts_)
154 return false;
155 if (video_min_dts_ == kNoDecodeTimestamp())
156 video_min_dts_ = first_dts;
157 video_max_dts_ = last_dts;
159 if (!audio_buffers.empty()) {
160 DecodeTimestamp first_dts = audio_buffers.front()->GetDecodeTimestamp();
161 DecodeTimestamp last_dts = audio_buffers.back()->GetDecodeTimestamp();
162 if (audio_max_dts_ != kNoDecodeTimestamp() && first_dts < audio_max_dts_)
163 return false;
164 if (audio_min_dts_ == kNoDecodeTimestamp())
165 audio_min_dts_ = first_dts;
166 audio_max_dts_ = last_dts;
169 audio_frame_count_ += audio_buffers.size();
170 video_frame_count_ += video_buffers.size();
171 return true;
174 void OnKeyNeeded(EmeInitDataType type, const std::vector<uint8>& init_data) {
175 NOTREACHED() << "OnKeyNeeded not expected in the Mpeg2 TS parser";
178 void OnNewSegment() {
179 DVLOG(1) << "OnNewSegment";
180 segment_count_++;
183 void OnEndOfSegment() {
184 NOTREACHED() << "OnEndOfSegment not expected in the Mpeg2 TS parser";
187 void InitializeParser() {
188 parser_->Init(
189 base::Bind(&Mp2tStreamParserTest::OnInit, base::Unretained(this)),
190 base::Bind(&Mp2tStreamParserTest::OnNewConfig, base::Unretained(this)),
191 base::Bind(&Mp2tStreamParserTest::OnNewBuffers, base::Unretained(this)),
192 true,
193 base::Bind(&Mp2tStreamParserTest::OnKeyNeeded, base::Unretained(this)),
194 base::Bind(&Mp2tStreamParserTest::OnNewSegment, base::Unretained(this)),
195 base::Bind(&Mp2tStreamParserTest::OnEndOfSegment,
196 base::Unretained(this)),
197 new MediaLog());
200 bool ParseMpeg2TsFile(const std::string& filename, int append_bytes) {
201 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
202 EXPECT_TRUE(AppendDataInPieces(buffer->data(),
203 buffer->data_size(),
204 append_bytes));
205 return true;
209 TEST_F(Mp2tStreamParserTest, UnalignedAppend17) {
210 // Test small, non-segment-aligned appends.
211 InitializeParser();
212 ParseMpeg2TsFile("bear-1280x720.ts", 17);
213 parser_->Flush();
214 EXPECT_EQ(video_frame_count_, 82);
215 // This stream has no mid-stream configuration change.
216 EXPECT_EQ(config_count_, 1);
217 EXPECT_EQ(segment_count_, 1);
220 TEST_F(Mp2tStreamParserTest, UnalignedAppend512) {
221 // Test small, non-segment-aligned appends.
222 InitializeParser();
223 ParseMpeg2TsFile("bear-1280x720.ts", 512);
224 parser_->Flush();
225 EXPECT_EQ(video_frame_count_, 82);
226 // This stream has no mid-stream configuration change.
227 EXPECT_EQ(config_count_, 1);
228 EXPECT_EQ(segment_count_, 1);
231 TEST_F(Mp2tStreamParserTest, AppendAfterFlush512) {
232 InitializeParser();
233 ParseMpeg2TsFile("bear-1280x720.ts", 512);
234 parser_->Flush();
235 EXPECT_EQ(video_frame_count_, 82);
236 EXPECT_EQ(config_count_, 1);
237 EXPECT_EQ(segment_count_, 1);
239 ResetStats();
240 ParseMpeg2TsFile("bear-1280x720.ts", 512);
241 parser_->Flush();
242 EXPECT_EQ(video_frame_count_, 82);
243 EXPECT_EQ(config_count_, 1);
244 EXPECT_EQ(segment_count_, 1);
247 TEST_F(Mp2tStreamParserTest, TimestampWrapAround) {
248 // "bear-1280x720_ptswraparound.ts" has been transcoded
249 // from bear-1280x720.mp4 by applying a time offset of 95442s
250 // (close to 2^33 / 90000) which results in timestamps wrap around
251 // in the Mpeg2 TS stream.
252 InitializeParser();
253 ParseMpeg2TsFile("bear-1280x720_ptswraparound.ts", 512);
254 parser_->Flush();
255 EXPECT_EQ(video_frame_count_, 82);
257 EXPECT_TRUE(IsAlmostEqual(video_min_dts_,
258 DecodeTimestamp::FromSecondsD(95443.376)));
259 EXPECT_TRUE(IsAlmostEqual(video_max_dts_,
260 DecodeTimestamp::FromSecondsD(95446.079)));
262 // Note: for audio, AdtsStreamParser considers only the PTS (which is then
263 // used as the DTS).
264 // TODO(damienv): most of the time, audio streams just have PTS. Here, only
265 // the first PES packet has a DTS, all the other PES packets have PTS only.
266 // Reconsider the expected value for |audio_min_dts_| if DTS are used as part
267 // of the ADTS stream parser.
269 // Note: the last pts for audio is 95445.931 but this PES packet includes
270 // 9 ADTS frames with 1 AAC frame in each ADTS frame.
271 // So the PTS of the last AAC frame is:
272 // 95445.931 + 8 * (1024 / 44100) = 95446.117
273 EXPECT_TRUE(IsAlmostEqual(audio_min_dts_,
274 DecodeTimestamp::FromSecondsD(95443.400)));
275 EXPECT_TRUE(IsAlmostEqual(audio_max_dts_,
276 DecodeTimestamp::FromSecondsD(95446.117)));
279 TEST_F(Mp2tStreamParserTest, AudioInPrivateStream1) {
280 // Test small, non-segment-aligned appends.
281 InitializeParser();
282 has_video_ = false;
283 ParseMpeg2TsFile("bear_adts_in_private_stream_1.ts", 512);
284 parser_->Flush();
285 EXPECT_EQ(audio_frame_count_, 40);
286 EXPECT_EQ(video_frame_count_, 0);
287 // This stream has no mid-stream configuration change.
288 EXPECT_EQ(config_count_, 1);
289 EXPECT_EQ(segment_count_, 1);
292 } // namespace mp2t
293 } // namespace media