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.
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"
25 class Mp2tStreamParserTest : public testing::Test {
27 Mp2tStreamParserTest()
28 : audio_frame_count_(0),
29 video_frame_count_(0),
30 video_min_dts_(kNoTimestamp()),
31 video_max_dts_(kNoTimestamp()) {
33 parser_.reset(new Mp2tStreamParser(has_sbr));
37 scoped_ptr<Mp2tStreamParser> parser_;
38 int audio_frame_count_;
39 int video_frame_count_;
40 base::TimeDelta video_min_dts_;
41 base::TimeDelta video_max_dts_;
43 bool AppendData(const uint8* data, size_t length) {
44 return parser_->Parse(data, length);
47 bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
48 const uint8* start = data;
49 const uint8* end = data + length;
51 size_t append_size = std::min(piece_size,
52 static_cast<size_t>(end - start));
53 if (!AppendData(start, append_size))
60 void OnInit(bool init_ok,
61 const StreamParser::InitParameters& params) {
62 DVLOG(1) << "OnInit: ok=" << init_ok
63 << ", dur=" << params.duration.InMilliseconds()
64 << ", autoTimestampOffset=" << params.auto_update_timestamp_offset;
67 bool OnNewConfig(const AudioDecoderConfig& ac,
68 const VideoDecoderConfig& vc,
69 const StreamParser::TextTrackConfigMap& tc) {
70 DVLOG(1) << "OnNewConfig: audio=" << ac.IsValidConfig()
71 << ", video=" << vc.IsValidConfig();
72 // Test streams have both audio and video, verify the configs are valid.
73 EXPECT_TRUE(ac.IsValidConfig());
74 EXPECT_TRUE(vc.IsValidConfig());
79 void DumpBuffers(const std::string& label,
80 const StreamParser::BufferQueue& buffers) {
81 DVLOG(2) << "DumpBuffers: " << label << " size " << buffers.size();
82 for (StreamParser::BufferQueue::const_iterator buf = buffers.begin();
83 buf != buffers.end(); buf++) {
84 DVLOG(3) << " n=" << buf - buffers.begin()
85 << ", size=" << (*buf)->data_size()
86 << ", dur=" << (*buf)->duration().InMilliseconds();
90 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
91 const StreamParser::BufferQueue& video_buffers,
92 const StreamParser::TextBufferQueueMap& text_map) {
93 DumpBuffers("audio_buffers", audio_buffers);
94 DumpBuffers("video_buffers", video_buffers);
95 audio_frame_count_ += audio_buffers.size();
96 video_frame_count_ += video_buffers.size();
98 // TODO(wolenetz/acolwell): Add text track support to more MSE parsers. See
99 // http://crbug.com/336926.
100 if (!text_map.empty())
103 if (video_min_dts_ == kNoTimestamp() && !video_buffers.empty())
104 video_min_dts_ = video_buffers.front()->GetDecodeTimestamp();
105 if (!video_buffers.empty()) {
106 video_max_dts_ = video_buffers.back()->GetDecodeTimestamp();
107 // Verify monotonicity.
108 StreamParser::BufferQueue::const_iterator it1 = video_buffers.begin();
109 StreamParser::BufferQueue::const_iterator it2 = ++it1;
110 for ( ; it2 != video_buffers.end(); ++it1, ++it2) {
111 if ((*it2)->GetDecodeTimestamp() < (*it1)->GetDecodeTimestamp())
119 void OnKeyNeeded(const std::string& type,
120 const std::vector<uint8>& init_data) {
121 DVLOG(1) << "OnKeyNeeded: " << init_data.size();
124 void OnNewSegment() {
125 DVLOG(1) << "OnNewSegment";
128 void OnEndOfSegment() {
129 DVLOG(1) << "OnEndOfSegment()";
132 void InitializeParser() {
134 base::Bind(&Mp2tStreamParserTest::OnInit,
135 base::Unretained(this)),
136 base::Bind(&Mp2tStreamParserTest::OnNewConfig,
137 base::Unretained(this)),
138 base::Bind(&Mp2tStreamParserTest::OnNewBuffers,
139 base::Unretained(this)),
141 base::Bind(&Mp2tStreamParserTest::OnKeyNeeded,
142 base::Unretained(this)),
143 base::Bind(&Mp2tStreamParserTest::OnNewSegment,
144 base::Unretained(this)),
145 base::Bind(&Mp2tStreamParserTest::OnEndOfSegment,
146 base::Unretained(this)),
150 bool ParseMpeg2TsFile(const std::string& filename, int append_bytes) {
151 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
152 EXPECT_TRUE(AppendDataInPieces(buffer->data(),
159 TEST_F(Mp2tStreamParserTest, UnalignedAppend17) {
160 // Test small, non-segment-aligned appends.
162 ParseMpeg2TsFile("bear-1280x720.ts", 17);
163 EXPECT_EQ(video_frame_count_, 81);
165 EXPECT_EQ(video_frame_count_, 82);
168 TEST_F(Mp2tStreamParserTest, UnalignedAppend512) {
169 // Test small, non-segment-aligned appends.
171 ParseMpeg2TsFile("bear-1280x720.ts", 512);
172 EXPECT_EQ(video_frame_count_, 81);
174 EXPECT_EQ(video_frame_count_, 82);
177 TEST_F(Mp2tStreamParserTest, AppendAfterFlush512) {
179 ParseMpeg2TsFile("bear-1280x720.ts", 512);
182 ParseMpeg2TsFile("bear-1280x720.ts", 512);
186 TEST_F(Mp2tStreamParserTest, TimestampWrapAround) {
187 // "bear-1280x720_ptswraparound.ts" has been transcoded
188 // from bear-1280x720.mp4 by applying a time offset of 95442s
189 // (close to 2^33 / 90000) which results in timestamps wrap around
190 // in the Mpeg2 TS stream.
192 ParseMpeg2TsFile("bear-1280x720_ptswraparound.ts", 512);
193 EXPECT_EQ(video_frame_count_, 81);
194 EXPECT_GE(video_min_dts_, base::TimeDelta::FromSeconds(95443 - 10));
195 EXPECT_LE(video_max_dts_, base::TimeDelta::FromSeconds(95443 + 10));