Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: media/muxers/webm_muxer_unittest.cc

Issue 2633623002: MediaRecorder: handle libwebm::Segment::AddFrame() errors and wire up to Blink (Closed)
Patch Set: I can haz moar testing? Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/muxers/webm_muxer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/muxers/webm_muxer.h" 5 #include "media/muxers/webm_muxer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 15 matching lines...) Expand all
26 using ::testing::InSequence; 26 using ::testing::InSequence;
27 using ::testing::Mock; 27 using ::testing::Mock;
28 using ::testing::Not; 28 using ::testing::Not;
29 using ::testing::Sequence; 29 using ::testing::Sequence;
30 using ::testing::TestWithParam; 30 using ::testing::TestWithParam;
31 using ::testing::ValuesIn; 31 using ::testing::ValuesIn;
32 using ::testing::WithArgs; 32 using ::testing::WithArgs;
33 33
34 namespace media { 34 namespace media {
35 35
36 struct kTestParams { 36 struct TestParams {
37 VideoCodec codec; 37 VideoCodec codec;
38 size_t num_video_tracks; 38 size_t num_video_tracks;
39 size_t num_audio_tracks; 39 size_t num_audio_tracks;
40 }; 40 };
41 41
42 class WebmMuxerTest : public TestWithParam<kTestParams> { 42 class WebmMuxerTest : public TestWithParam<TestParams> {
43 public: 43 public:
44 WebmMuxerTest() 44 WebmMuxerTest()
45 : webm_muxer_( 45 : webm_muxer_(
46 GetParam().codec, 46 GetParam().codec,
47 GetParam().num_video_tracks, 47 GetParam().num_video_tracks,
48 GetParam().num_audio_tracks, 48 GetParam().num_audio_tracks,
49 base::Bind(&WebmMuxerTest::WriteCallback, base::Unretained(this))), 49 base::Bind(&WebmMuxerTest::WriteCallback, base::Unretained(this))),
50 last_encoded_length_(0), 50 last_encoded_length_(0),
51 accumulated_position_(0) { 51 accumulated_position_(0) {
52 EXPECT_EQ(webm_muxer_.Position(), 0); 52 EXPECT_EQ(webm_muxer_.Position(), 0);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 102
103 const gfx::Size frame_size(160, 80); 103 const gfx::Size frame_size(160, 80);
104 const scoped_refptr<VideoFrame> video_frame = 104 const scoped_refptr<VideoFrame> video_frame =
105 VideoFrame::CreateBlackFrame(frame_size); 105 VideoFrame::CreateBlackFrame(frame_size);
106 const std::string encoded_data("abcdefghijklmnopqrstuvwxyz"); 106 const std::string encoded_data("abcdefghijklmnopqrstuvwxyz");
107 107
108 EXPECT_CALL(*this, WriteCallback(_)) 108 EXPECT_CALL(*this, WriteCallback(_))
109 .Times(AtLeast(1)) 109 .Times(AtLeast(1))
110 .WillRepeatedly( 110 .WillRepeatedly(
111 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen))); 111 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen)));
112 webm_muxer_.OnEncodedVideo(WebmMuxer::VideoParameters(video_frame), 112 EXPECT_TRUE(webm_muxer_.OnEncodedVideo(
113 base::WrapUnique(new std::string(encoded_data)), 113 WebmMuxer::VideoParameters(video_frame),
114 base::TimeTicks::Now(), false /* keyframe */); 114 base::WrapUnique(new std::string(encoded_data)), base::TimeTicks::Now(),
115 false /* keyframe */));
115 116
116 // First time around WriteCallback() is pinged a number of times to write the 117 // First time around WriteCallback() is pinged a number of times to write the
117 // Matroska header, but at the end it dumps |encoded_data|. 118 // Matroska header, but at the end it dumps |encoded_data|.
118 EXPECT_EQ(last_encoded_length_, encoded_data.size()); 119 EXPECT_EQ(last_encoded_length_, encoded_data.size());
119 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_); 120 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_);
120 EXPECT_GE(GetWebmMuxerPosition(), static_cast<int64_t>(last_encoded_length_)); 121 EXPECT_GE(GetWebmMuxerPosition(), static_cast<int64_t>(last_encoded_length_));
121 EXPECT_EQ(GetWebmSegmentMode(), mkvmuxer::Segment::kLive); 122 EXPECT_EQ(GetWebmSegmentMode(), mkvmuxer::Segment::kLive);
122 123
123 const int64_t begin_of_second_block = accumulated_position_; 124 const int64_t begin_of_second_block = accumulated_position_;
124 EXPECT_CALL(*this, WriteCallback(_)) 125 EXPECT_CALL(*this, WriteCallback(_))
125 .Times(AtLeast(1)) 126 .Times(AtLeast(1))
126 .WillRepeatedly( 127 .WillRepeatedly(
127 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen))); 128 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen)));
128 webm_muxer_.OnEncodedVideo(video_frame, 129 EXPECT_TRUE(webm_muxer_.OnEncodedVideo(
129 base::WrapUnique(new std::string(encoded_data)), 130 video_frame, base::WrapUnique(new std::string(encoded_data)),
130 base::TimeTicks::Now(), false /* keyframe */); 131 base::TimeTicks::Now(), false /* keyframe */));
131 132
132 // The second time around the callbacks should include a SimpleBlock header, 133 // The second time around the callbacks should include a SimpleBlock header,
133 // namely the track index, a timestamp and a flags byte, for a total of 6B. 134 // namely the track index, a timestamp and a flags byte, for a total of 6B.
134 EXPECT_EQ(last_encoded_length_, encoded_data.size()); 135 EXPECT_EQ(last_encoded_length_, encoded_data.size());
135 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_); 136 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_);
136 const uint32_t kSimpleBlockSize = 6u; 137 const uint32_t kSimpleBlockSize = 6u;
137 EXPECT_EQ(static_cast<int64_t>(begin_of_second_block + kSimpleBlockSize + 138 EXPECT_EQ(static_cast<int64_t>(begin_of_second_block + kSimpleBlockSize +
138 encoded_data.size()), 139 encoded_data.size()),
139 accumulated_position_); 140 accumulated_position_);
141
142 // Force an error in libwebm and expect OnEncodedVideo to fail.
143 webm_muxer_.ForceOneLibWebmErrorForTesting();
144 EXPECT_FALSE(
145 webm_muxer_.OnEncodedVideo(WebmMuxer::VideoParameters(video_frame),
146 base::MakeUnique<std::string>(encoded_data),
147 base::TimeTicks::Now(), true /* keyframe */));
140 } 148 }
141 149
142 TEST_P(WebmMuxerTest, OnEncodedAudioTwoFrames) { 150 TEST_P(WebmMuxerTest, OnEncodedAudioTwoFrames) {
143 if (GetParam().num_video_tracks > 0) 151 if (GetParam().num_video_tracks > 0)
144 return; 152 return;
145 153
146 const int sample_rate = 48000; 154 const int sample_rate = 48000;
147 const int bits_per_sample = 16; 155 const int bits_per_sample = 16;
148 const int frames_per_buffer = 480; 156 const int frames_per_buffer = 480;
149 media::AudioParameters audio_params( 157 media::AudioParameters audio_params(
150 media::AudioParameters::Format::AUDIO_PCM_LOW_LATENCY, 158 media::AudioParameters::Format::AUDIO_PCM_LOW_LATENCY,
151 media::CHANNEL_LAYOUT_MONO, sample_rate, bits_per_sample, 159 media::CHANNEL_LAYOUT_MONO, sample_rate, bits_per_sample,
152 frames_per_buffer); 160 frames_per_buffer);
153 161
154 const std::string encoded_data("abcdefghijklmnopqrstuvwxyz"); 162 const std::string encoded_data("abcdefghijklmnopqrstuvwxyz");
155 163
156 EXPECT_CALL(*this, WriteCallback(_)) 164 EXPECT_CALL(*this, WriteCallback(_))
157 .Times(AtLeast(1)) 165 .Times(AtLeast(1))
158 .WillRepeatedly( 166 .WillRepeatedly(
159 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen))); 167 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen)));
160 webm_muxer_.OnEncodedAudio(audio_params, 168 EXPECT_TRUE(webm_muxer_.OnEncodedAudio(
161 base::MakeUnique<std::string>(encoded_data), 169 audio_params, base::MakeUnique<std::string>(encoded_data),
162 base::TimeTicks::Now()); 170 base::TimeTicks::Now()));
163 171
164 // First time around WriteCallback() is pinged a number of times to write the 172 // First time around WriteCallback() is pinged a number of times to write the
165 // Matroska header, but at the end it dumps |encoded_data|. 173 // Matroska header, but at the end it dumps |encoded_data|.
166 EXPECT_EQ(last_encoded_length_, encoded_data.size()); 174 EXPECT_EQ(last_encoded_length_, encoded_data.size());
167 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_); 175 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_);
168 EXPECT_GE(GetWebmMuxerPosition(), static_cast<int64_t>(last_encoded_length_)); 176 EXPECT_GE(GetWebmMuxerPosition(), static_cast<int64_t>(last_encoded_length_));
169 EXPECT_EQ(GetWebmSegmentMode(), mkvmuxer::Segment::kLive); 177 EXPECT_EQ(GetWebmSegmentMode(), mkvmuxer::Segment::kLive);
170 178
171 const int64_t begin_of_second_block = accumulated_position_; 179 const int64_t begin_of_second_block = accumulated_position_;
172 EXPECT_CALL(*this, WriteCallback(_)) 180 EXPECT_CALL(*this, WriteCallback(_))
173 .Times(AtLeast(1)) 181 .Times(AtLeast(1))
174 .WillRepeatedly( 182 .WillRepeatedly(
175 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen))); 183 WithArgs<0>(Invoke(this, &WebmMuxerTest::SaveEncodedDataLen)));
176 webm_muxer_.OnEncodedAudio(audio_params, 184 EXPECT_TRUE(webm_muxer_.OnEncodedAudio(
177 base::MakeUnique<std::string>(encoded_data), 185 audio_params, base::MakeUnique<std::string>(encoded_data),
178 base::TimeTicks::Now()); 186 base::TimeTicks::Now()));
179 187
180 // The second time around the callbacks should include a SimpleBlock header, 188 // The second time around the callbacks should include a SimpleBlock header,
181 // namely the track index, a timestamp and a flags byte, for a total of 6B. 189 // namely the track index, a timestamp and a flags byte, for a total of 6B.
182 EXPECT_EQ(last_encoded_length_, encoded_data.size()); 190 EXPECT_EQ(last_encoded_length_, encoded_data.size());
183 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_); 191 EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_);
184 const uint32_t kSimpleBlockSize = 6u; 192 const uint32_t kSimpleBlockSize = 6u;
185 EXPECT_EQ(static_cast<int64_t>(begin_of_second_block + kSimpleBlockSize + 193 EXPECT_EQ(static_cast<int64_t>(begin_of_second_block + kSimpleBlockSize +
186 encoded_data.size()), 194 encoded_data.size()),
187 accumulated_position_); 195 accumulated_position_);
196
197 // Force an error in libwebm and expect OnEncodedAudio to fail.
198 webm_muxer_.ForceOneLibWebmErrorForTesting();
199 EXPECT_FALSE(webm_muxer_.OnEncodedAudio(
200 audio_params, base::MakeUnique<std::string>(encoded_data),
201 base::TimeTicks::Now()));
188 } 202 }
189 203
190 // This test verifies that when video data comes before audio data, we save the 204 // This test verifies that when video data comes before audio data, we save the
191 // encoded video frames and add it to the video track when audio data arrives. 205 // encoded video frames and add it to the video track when audio data arrives.
192 TEST_P(WebmMuxerTest, VideoIsStoredWhileWaitingForAudio) { 206 TEST_P(WebmMuxerTest, VideoIsStoredWhileWaitingForAudio) {
193 // This test is only relevant if we have both kinds of tracks. 207 // This test is only relevant if we have both kinds of tracks.
194 if (GetParam().num_video_tracks == 0 || GetParam().num_audio_tracks == 0) 208 if (GetParam().num_video_tracks == 0 || GetParam().num_audio_tracks == 0)
195 return; 209 return;
196 210
197 // First send a video keyframe 211 // First send a video keyframe.
198 const gfx::Size frame_size(160, 80); 212 const gfx::Size frame_size(160, 80);
199 const scoped_refptr<VideoFrame> video_frame = 213 const scoped_refptr<VideoFrame> video_frame =
200 VideoFrame::CreateBlackFrame(frame_size); 214 VideoFrame::CreateBlackFrame(frame_size);
201 const std::string encoded_video("thisisanencodedvideopacket"); 215 const std::string encoded_video("thisisanencodedvideopacket");
202 webm_muxer_.OnEncodedVideo(WebmMuxer::VideoParameters(video_frame), 216 EXPECT_TRUE(webm_muxer_.OnEncodedVideo(
203 base::WrapUnique(new std::string(encoded_video)), 217 WebmMuxer::VideoParameters(video_frame),
204 base::TimeTicks::Now(), true /* keyframe */); 218 base::WrapUnique(new std::string(encoded_video)), base::TimeTicks::Now(),
219 true /* keyframe */));
205 // A few encoded non key frames. 220 // A few encoded non key frames.
206 const int kNumNonKeyFrames = 2; 221 const int kNumNonKeyFrames = 2;
207 for (int i = 0; i < kNumNonKeyFrames; ++i) { 222 for (int i = 0; i < kNumNonKeyFrames; ++i) {
208 webm_muxer_.OnEncodedVideo(WebmMuxer::VideoParameters(video_frame), 223 EXPECT_TRUE(webm_muxer_.OnEncodedVideo(
209 base::WrapUnique(new std::string(encoded_video)), 224 WebmMuxer::VideoParameters(video_frame),
210 base::TimeTicks::Now(), false /* keyframe */); 225 base::WrapUnique(new std::string(encoded_video)),
226 base::TimeTicks::Now(), false /* keyframe */));
211 } 227 }
212 228
213 // Send some audio. The header will be written and muxing will proceed
214 // normally.
215 const int sample_rate = 48000; 229 const int sample_rate = 48000;
216 const int bits_per_sample = 16; 230 const int bits_per_sample = 16;
217 const int frames_per_buffer = 480; 231 const int frames_per_buffer = 480;
218 media::AudioParameters audio_params( 232 media::AudioParameters audio_params(
219 media::AudioParameters::Format::AUDIO_PCM_LOW_LATENCY, 233 media::AudioParameters::Format::AUDIO_PCM_LOW_LATENCY,
220 media::CHANNEL_LAYOUT_MONO, sample_rate, bits_per_sample, 234 media::CHANNEL_LAYOUT_MONO, sample_rate, bits_per_sample,
221 frames_per_buffer); 235 frames_per_buffer);
222 const std::string encoded_audio("thisisanencodedaudiopacket"); 236 const std::string encoded_audio("thisisanencodedaudiopacket");
223 237
224 // We should first get the encoded video frames, then the encoded audio frame. 238 // Force one libwebm error and verify OnEncodedAudio() fails.
239 webm_muxer_.ForceOneLibWebmErrorForTesting();
240 EXPECT_FALSE(webm_muxer_.OnEncodedAudio(
241 audio_params, base::WrapUnique(new std::string(encoded_audio)),
242 base::TimeTicks::Now()));
243
244 // We should get the queued encoded video frames, then an encoded audio frame.
225 Sequence s; 245 Sequence s;
226 EXPECT_CALL(*this, WriteCallback(Eq(encoded_video))) 246 EXPECT_CALL(*this, WriteCallback(Eq(encoded_video)))
227 .Times(1 + kNumNonKeyFrames) 247 .Times(1 + kNumNonKeyFrames)
228 .InSequence(s); 248 .InSequence(s);
229 EXPECT_CALL(*this, WriteCallback(Eq(encoded_audio))).Times(1).InSequence(s); 249 EXPECT_CALL(*this, WriteCallback(Eq(encoded_audio))).Times(1).InSequence(s);
230 // We'll also get lots of other header-related stuff. 250 // We'll also get lots of other header-related stuff.
231 EXPECT_CALL(*this, WriteCallback( 251 EXPECT_CALL(*this, WriteCallback(
232 AllOf(Not(Eq(encoded_video)), Not(Eq(encoded_audio))))) 252 AllOf(Not(Eq(encoded_video)), Not(Eq(encoded_audio)))))
233 .Times(AnyNumber()); 253 .Times(AnyNumber());
234 webm_muxer_.OnEncodedAudio(audio_params, 254 EXPECT_TRUE(webm_muxer_.OnEncodedAudio(
235 base::WrapUnique(new std::string(encoded_audio)), 255 audio_params, base::WrapUnique(new std::string(encoded_audio)),
236 base::TimeTicks::Now()); 256 base::TimeTicks::Now()));
237 } 257 }
238 258
239 const kTestParams kTestCases[] = { 259 const TestParams kTestCases[] = {
240 {kCodecVP8, 1 /* num_video_tracks */, 0 /*num_audio_tracks*/}, 260 {kCodecVP8, 1 /* num_video_tracks */, 0 /*num_audio_tracks*/},
241 {kCodecVP8, 0, 1}, 261 {kCodecVP8, 0, 1},
242 {kCodecVP8, 1, 1}, 262 {kCodecVP8, 1, 1},
243 {kCodecVP9, 1, 0}, 263 {kCodecVP9, 1, 0},
244 {kCodecVP9, 0, 1}, 264 {kCodecVP9, 0, 1},
245 {kCodecVP9, 1, 1}, 265 {kCodecVP9, 1, 1},
246 {kCodecH264, 1, 0}, 266 {kCodecH264, 1, 0},
247 {kCodecH264, 0, 1}, 267 {kCodecH264, 0, 1},
248 {kCodecH264, 1, 1}, 268 {kCodecH264, 1, 1},
249 }; 269 };
250 270
251 INSTANTIATE_TEST_CASE_P(, WebmMuxerTest, ValuesIn(kTestCases)); 271 INSTANTIATE_TEST_CASE_P(, WebmMuxerTest, ValuesIn(kTestCases));
252 272
253 } // namespace media 273 } // namespace media
OLDNEW
« no previous file with comments | « media/muxers/webm_muxer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698