Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / formats / mp2t / mp2t_stream_parser_unittest.cc
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.
4
5 #include <algorithm>
6 #include <string>
7
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"
21
22 namespace media {
23 namespace mp2t {
24
25 class Mp2tStreamParserTest : public testing::Test {
26  public:
27   Mp2tStreamParserTest()
28       : audio_frame_count_(0),
29         video_frame_count_(0),
30         video_min_dts_(kNoTimestamp()),
31         video_max_dts_(kNoTimestamp()) {
32     bool has_sbr = false;
33     parser_.reset(new Mp2tStreamParser(has_sbr));
34   }
35
36  protected:
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_;
42
43   bool AppendData(const uint8* data, size_t length) {
44     return parser_->Parse(data, length);
45   }
46
47   bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
48     const uint8* start = data;
49     const uint8* end = data + length;
50     while (start < end) {
51       size_t append_size = std::min(piece_size,
52                                     static_cast<size_t>(end - start));
53       if (!AppendData(start, append_size))
54         return false;
55       start += append_size;
56     }
57     return true;
58   }
59
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;
65   }
66
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());
75     return true;
76   }
77
78
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();
87     }
88   }
89
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();
97
98     // TODO(wolenetz/acolwell): Add text track support to more MSE parsers. See
99     // http://crbug.com/336926.
100     if (!text_map.empty())
101       return false;
102
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())
112           return false;
113       }
114     }
115
116     return true;
117   }
118
119   void OnKeyNeeded(const std::string& type,
120                    const std::vector<uint8>& init_data) {
121     DVLOG(1) << "OnKeyNeeded: " << init_data.size();
122   }
123
124   void OnNewSegment() {
125     DVLOG(1) << "OnNewSegment";
126   }
127
128   void OnEndOfSegment() {
129     DVLOG(1) << "OnEndOfSegment()";
130   }
131
132   void InitializeParser() {
133     parser_->Init(
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)),
140         true,
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)),
147         LogCB());
148   }
149
150   bool ParseMpeg2TsFile(const std::string& filename, int append_bytes) {
151     scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
152     EXPECT_TRUE(AppendDataInPieces(buffer->data(),
153                                    buffer->data_size(),
154                                    append_bytes));
155     return true;
156   }
157 };
158
159 TEST_F(Mp2tStreamParserTest, UnalignedAppend17) {
160   // Test small, non-segment-aligned appends.
161   InitializeParser();
162   ParseMpeg2TsFile("bear-1280x720.ts", 17);
163   EXPECT_EQ(video_frame_count_, 81);
164   parser_->Flush();
165   EXPECT_EQ(video_frame_count_, 82);
166 }
167
168 TEST_F(Mp2tStreamParserTest, UnalignedAppend512) {
169   // Test small, non-segment-aligned appends.
170   InitializeParser();
171   ParseMpeg2TsFile("bear-1280x720.ts", 512);
172   EXPECT_EQ(video_frame_count_, 81);
173   parser_->Flush();
174   EXPECT_EQ(video_frame_count_, 82);
175 }
176
177 TEST_F(Mp2tStreamParserTest, AppendAfterFlush512) {
178   InitializeParser();
179   ParseMpeg2TsFile("bear-1280x720.ts", 512);
180   parser_->Flush();
181
182   ParseMpeg2TsFile("bear-1280x720.ts", 512);
183   parser_->Flush();
184 }
185
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.
191   InitializeParser();
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));
196 }
197
198 }  // namespace mp2t
199 }  // namespace media