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 "base/logging.h" 6#include "media/base/channel_layout.h" 7#include "media/formats/webm/tracks_builder.h" 8#include "media/formats/webm/webm_constants.h" 9#include "media/formats/webm/webm_tracks_parser.h" 10#include "testing/gmock/include/gmock/gmock.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13using ::testing::InSequence; 14using ::testing::Return; 15using ::testing::_; 16 17namespace media { 18 19static const double kDefaultTimecodeScaleInUs = 1000.0; // 1 ms resolution 20 21class WebMTracksParserTest : public testing::Test { 22 public: 23 WebMTracksParserTest() {} 24}; 25 26static void VerifyTextTrackInfo(const uint8* buffer, 27 int buffer_size, 28 TextKind text_kind, 29 const std::string& name, 30 const std::string& language) { 31 scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), false)); 32 33 int result = parser->Parse(buffer, buffer_size); 34 EXPECT_GT(result, 0); 35 EXPECT_EQ(result, buffer_size); 36 37 const WebMTracksParser::TextTracks& text_tracks = parser->text_tracks(); 38 EXPECT_EQ(text_tracks.size(), WebMTracksParser::TextTracks::size_type(1)); 39 40 const WebMTracksParser::TextTracks::const_iterator itr = text_tracks.begin(); 41 EXPECT_EQ(itr->first, 1); // track num 42 43 const TextTrackConfig& config = itr->second; 44 EXPECT_EQ(config.kind(), text_kind); 45 EXPECT_TRUE(config.label() == name); 46 EXPECT_TRUE(config.language() == language); 47} 48 49TEST_F(WebMTracksParserTest, SubtitleNoNameNoLang) { 50 InSequence s; 51 52 TracksBuilder tb; 53 tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", ""); 54 55 const std::vector<uint8> buf = tb.Finish(); 56 VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", ""); 57} 58 59TEST_F(WebMTracksParserTest, SubtitleYesNameNoLang) { 60 InSequence s; 61 62 TracksBuilder tb; 63 tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Spock", ""); 64 65 const std::vector<uint8> buf = tb.Finish(); 66 VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Spock", ""); 67} 68 69TEST_F(WebMTracksParserTest, SubtitleNoNameYesLang) { 70 InSequence s; 71 72 TracksBuilder tb; 73 tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "eng"); 74 75 const std::vector<uint8> buf = tb.Finish(); 76 VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "eng"); 77} 78 79TEST_F(WebMTracksParserTest, SubtitleYesNameYesLang) { 80 InSequence s; 81 82 TracksBuilder tb; 83 tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Picard", "fre"); 84 85 const std::vector<uint8> buf = tb.Finish(); 86 VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Picard", "fre"); 87} 88 89TEST_F(WebMTracksParserTest, IgnoringTextTracks) { 90 InSequence s; 91 92 TracksBuilder tb; 93 tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Subtitles", "fre"); 94 tb.AddTextTrack(2, 2, kWebMCodecSubtitles, "Commentary", "fre"); 95 96 const std::vector<uint8> buf = tb.Finish(); 97 scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true)); 98 99 int result = parser->Parse(&buf[0], buf.size()); 100 EXPECT_GT(result, 0); 101 EXPECT_EQ(result, static_cast<int>(buf.size())); 102 103 EXPECT_EQ(parser->text_tracks().size(), 0u); 104 105 const std::set<int64>& ignored_tracks = parser->ignored_tracks(); 106 EXPECT_TRUE(ignored_tracks.find(1) != ignored_tracks.end()); 107 EXPECT_TRUE(ignored_tracks.find(2) != ignored_tracks.end()); 108 109 // Test again w/o ignoring the test tracks. 110 parser.reset(new WebMTracksParser(LogCB(), false)); 111 112 result = parser->Parse(&buf[0], buf.size()); 113 EXPECT_GT(result, 0); 114 115 EXPECT_EQ(parser->ignored_tracks().size(), 0u); 116 EXPECT_EQ(parser->text_tracks().size(), 2u); 117} 118 119TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationUnset) { 120 // Other audio/video decoder config fields are necessary in the test 121 // audio/video TrackEntry configurations. This method does only very minimal 122 // verification of their inclusion and parsing; the goal is to confirm 123 // TrackEntry DefaultDuration defaults to -1 if not included in audio or 124 // video TrackEntry. 125 TracksBuilder tb; 126 tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", -1, 2, 8000); 127 tb.AddVideoTrack(2, 2, "V_VP8", "video", "", -1, 320, 240); 128 const std::vector<uint8> buf = tb.Finish(); 129 130 scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true)); 131 int result = parser->Parse(&buf[0], buf.size()); 132 EXPECT_LE(0, result); 133 EXPECT_EQ(static_cast<int>(buf.size()), result); 134 135 EXPECT_EQ(kNoTimestamp(), 136 parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs)); 137 EXPECT_EQ(kNoTimestamp(), 138 parser->GetVideoDefaultDuration(kDefaultTimecodeScaleInUs)); 139 140 const VideoDecoderConfig& video_config = parser->video_decoder_config(); 141 EXPECT_TRUE(video_config.IsValidConfig()); 142 EXPECT_EQ(320, video_config.coded_size().width()); 143 EXPECT_EQ(240, video_config.coded_size().height()); 144 145 const AudioDecoderConfig& audio_config = parser->audio_decoder_config(); 146 EXPECT_TRUE(audio_config.IsValidConfig()); 147 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout()); 148 EXPECT_EQ(8000, audio_config.samples_per_second()); 149} 150 151TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationSet) { 152 // Confirm audio or video TrackEntry DefaultDuration values are parsed, if 153 // present. 154 TracksBuilder tb; 155 tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 12345678, 2, 8000); 156 tb.AddVideoTrack(2, 2, "V_VP8", "video", "", 987654321, 320, 240); 157 const std::vector<uint8> buf = tb.Finish(); 158 159 scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true)); 160 int result = parser->Parse(&buf[0], buf.size()); 161 EXPECT_LE(0, result); 162 EXPECT_EQ(static_cast<int>(buf.size()), result); 163 164 EXPECT_EQ(base::TimeDelta::FromMicroseconds(12000), 165 parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs)); 166 EXPECT_EQ(base::TimeDelta::FromMicroseconds(985000), 167 parser->GetVideoDefaultDuration(5000.0)); // 5 ms resolution 168 EXPECT_EQ(kNoTimestamp(), parser->GetAudioDefaultDuration(12346.0)); 169 EXPECT_EQ(base::TimeDelta::FromMicroseconds(12345), 170 parser->GetAudioDefaultDuration(12345.0)); 171 EXPECT_EQ(base::TimeDelta::FromMicroseconds(12003), 172 parser->GetAudioDefaultDuration(1000.3)); // 1.0003 ms resolution 173} 174 175TEST_F(WebMTracksParserTest, InvalidZeroDefaultDurationSet) { 176 // Confirm parse error if TrackEntry DefaultDuration is present, but is 0ns. 177 TracksBuilder tb(true); 178 tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 0, 2, 8000); 179 const std::vector<uint8> buf = tb.Finish(); 180 181 scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true)); 182 EXPECT_EQ(-1, parser->Parse(&buf[0], buf.size())); 183} 184 185TEST_F(WebMTracksParserTest, HighTrackUID) { 186 // Confirm no parse error if TrackEntry TrackUID has MSb set 187 // (http://crbug.com/397067). 188 TracksBuilder tb(true); 189 tb.AddAudioTrack(1, 1ULL << 31, "A_VORBIS", "audio", "", 40, 2, 8000); 190 const std::vector<uint8> buf = tb.Finish(); 191 192 scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true)); 193 EXPECT_GT(parser->Parse(&buf[0], buf.size()),0); 194} 195 196} // namespace media 197