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

Side by Side Diff: media/base/android/media_codec_player_unittest.cc

Issue 1254293003: MediaCodecPlayer implementation (stage 4 - preroll) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-browserseek
Patch Set: Added unit test for video-only preroll Created 5 years, 4 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
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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/logging.h" 6 #include "base/logging.h"
7 #include "base/timer/timer.h" 7 #include "base/timer/timer.h"
8 #include "media/base/android/demuxer_android.h" 8 #include "media/base/android/demuxer_android.h"
9 #include "media/base/android/media_codec_bridge.h" 9 #include "media/base/android/media_codec_bridge.h"
10 #include "media/base/android/media_codec_player.h" 10 #include "media/base/android/media_codec_player.h"
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 230
231 class MockDemuxerAndroid : public DemuxerAndroid { 231 class MockDemuxerAndroid : public DemuxerAndroid {
232 public: 232 public:
233 MockDemuxerAndroid() 233 MockDemuxerAndroid()
234 : client_(nullptr), num_seeks_(0), num_browser_seeks_(0) {} 234 : client_(nullptr), num_seeks_(0), num_browser_seeks_(0) {}
235 ~MockDemuxerAndroid() override {} 235 ~MockDemuxerAndroid() override {}
236 236
237 // DemuxerAndroid implementation 237 // DemuxerAndroid implementation
238 void Initialize(DemuxerAndroidClient* client) override; 238 void Initialize(DemuxerAndroidClient* client) override;
239 void RequestDemuxerData(DemuxerStream::Type type) override; 239 void RequestDemuxerData(DemuxerStream::Type type) override;
240 void RequestDemuxerSeek(const base::TimeDelta& time_to_seek, 240 void RequestDemuxerSeek(const base::TimeDelta& seek_request,
241 bool is_browser_seek) override; 241 bool is_browser_seek) override;
242 242
243 // Sets the audio data factory. 243 // Sets the audio data factory.
244 void SetAudioFactory(scoped_ptr<AudioFactory> factory) { 244 void SetAudioFactory(scoped_ptr<AudioFactory> factory) {
245 audio_factory_ = factory.Pass(); 245 audio_factory_ = factory.Pass();
246 } 246 }
247 247
248 // Sets the video data factory. 248 // Sets the video data factory.
249 void SetVideoFactory(scoped_ptr<VideoFactory> factory) { 249 void SetVideoFactory(scoped_ptr<VideoFactory> factory) {
250 video_factory_ = factory.Pass(); 250 video_factory_ = factory.Pass();
251 } 251 }
252 252
253 // Set the preroll interval after seek for audio stream.
254 void SetAudioPrerollInterval(base::TimeDelta value) {
255 audio_preroll_interval_ = value;
256 }
257
258 // Set the preroll interval after seek for video stream.
259 void SetVideoPrerollInterval(base::TimeDelta value) {
260 video_preroll_interval_ = value;
261 }
262
253 // Sets the delay in OnDemuxerSeekDone response. 263 // Sets the delay in OnDemuxerSeekDone response.
254 void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; } 264 void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; }
255 265
256 // Post DemuxerConfigs to the client (i.e. the player) on correct thread. 266 // Post DemuxerConfigs to the client (i.e. the player) on correct thread.
257 void PostConfigs(const DemuxerConfigs& configs); 267 void PostConfigs(const DemuxerConfigs& configs);
258 268
259 // Post DemuxerConfigs derived from data factories that has been set. 269 // Post DemuxerConfigs derived from data factories that has been set.
260 void PostInternalConfigs(); 270 void PostInternalConfigs();
261 271
262 // Conditions to wait for. 272 // Conditions to wait for.
263 bool IsInitialized() const { return client_; } 273 bool IsInitialized() const { return client_; }
264 bool HasPendingConfigs() const { return pending_configs_; } 274 bool HasPendingConfigs() const { return pending_configs_; }
265 bool ReceivedSeekRequest() const { return num_seeks_ > 0; } 275 bool ReceivedSeekRequest() const { return num_seeks_ > 0; }
266 bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_ > 0; } 276 bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_ > 0; }
267 277
268 private: 278 private:
269 DemuxerAndroidClient* client_; 279 DemuxerAndroidClient* client_;
270 scoped_ptr<DemuxerConfigs> pending_configs_; 280 scoped_ptr<DemuxerConfigs> pending_configs_;
271 scoped_ptr<AudioFactory> audio_factory_; 281 scoped_ptr<AudioFactory> audio_factory_;
272 scoped_ptr<VideoFactory> video_factory_; 282 scoped_ptr<VideoFactory> video_factory_;
283 base::TimeDelta audio_preroll_interval_;
284 base::TimeDelta video_preroll_interval_;
273 base::TimeDelta seek_done_delay_; 285 base::TimeDelta seek_done_delay_;
274 int num_seeks_; 286 int num_seeks_;
275 int num_browser_seeks_; 287 int num_browser_seeks_;
276 288
277 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); 289 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid);
278 }; 290 };
279 291
280 void MockDemuxerAndroid::Initialize(DemuxerAndroidClient* client) { 292 void MockDemuxerAndroid::Initialize(DemuxerAndroidClient* client) {
281 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__; 293 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__;
282 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 294 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
(...skipping 19 matching lines...) Expand all
302 chunk.type = type; 314 chunk.type = type;
303 315
304 // Post to Media thread. 316 // Post to Media thread.
305 DCHECK(client_); 317 DCHECK(client_);
306 GetMediaTaskRunner()->PostDelayedTask( 318 GetMediaTaskRunner()->PostDelayedTask(
307 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerDataAvailable, 319 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerDataAvailable,
308 base::Unretained(client_), chunk), 320 base::Unretained(client_), chunk),
309 delay); 321 delay);
310 } 322 }
311 323
312 void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& time_to_seek, 324 void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& seek_request,
313 bool is_browser_seek) { 325 bool is_browser_seek) {
314 // Tell data factories to start next chunk with the new timestamp. 326 // Tell data factories to start next chunk with the new timestamp.
315 if (audio_factory_) 327 if (audio_factory_) {
328 base::TimeDelta time_to_seek =
329 std::max(base::TimeDelta(), seek_request - audio_preroll_interval_);
316 audio_factory_->SeekTo(time_to_seek); 330 audio_factory_->SeekTo(time_to_seek);
331 }
317 if (video_factory_) { 332 if (video_factory_) {
333 base::TimeDelta time_to_seek =
334 std::max(base::TimeDelta(), seek_request - video_preroll_interval_);
318 video_factory_->SeekTo(time_to_seek); 335 video_factory_->SeekTo(time_to_seek);
319 video_factory_->RequestKeyFrame(); 336 video_factory_->RequestKeyFrame();
320 } 337 }
321 338
322 ++num_seeks_; 339 ++num_seeks_;
323 if (is_browser_seek) 340 if (is_browser_seek)
324 ++num_browser_seeks_; 341 ++num_browser_seeks_;
325 342
326 // Post OnDemuxerSeekDone() to the player. 343 // Post OnDemuxerSeekDone() to the player.
327 DCHECK(client_); 344 DCHECK(client_);
328 base::TimeDelta reported_seek_time = 345 base::TimeDelta reported_seek_time =
329 is_browser_seek ? time_to_seek : kNoTimestamp(); 346 is_browser_seek ? seek_request : kNoTimestamp();
330 GetMediaTaskRunner()->PostDelayedTask( 347 GetMediaTaskRunner()->PostDelayedTask(
331 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone, 348 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone,
332 base::Unretained(client_), reported_seek_time), 349 base::Unretained(client_), reported_seek_time),
333 seek_done_delay_); 350 seek_done_delay_);
334 } 351 }
335 352
336 void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs& configs) { 353 void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs& configs) {
337 RUN_ON_MEDIA_THREAD(MockDemuxerAndroid, PostConfigs, configs); 354 RUN_ON_MEDIA_THREAD(MockDemuxerAndroid, PostConfigs, configs);
338 355
339 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__; 356 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__;
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after
1048 reconfigure_timeout)); 1065 reconfigure_timeout));
1049 1066
1050 // Timestamps should start at the new seek position 1067 // Timestamps should start at the new seek position
1051 EXPECT_LE(seek_position, manager_.pts_stat_.min()); 1068 EXPECT_LE(seek_position, manager_.pts_stat_.min());
1052 1069
1053 // The player should have reported the seek completion to the manager. 1070 // The player should have reported the seek completion to the manager.
1054 EXPECT_TRUE(WaitForCondition(base::Bind( 1071 EXPECT_TRUE(WaitForCondition(base::Bind(
1055 &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_)))); 1072 &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
1056 } 1073 }
1057 1074
1075 TEST_F(MediaCodecPlayerTest, VideoPrerollAfterSeek) {
1076 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
1077
1078 // A simple test for preroll for video stream only. After the seek is done
1079 // the data factory generates the frames with pts before the seek time, and
1080 // they should not be rendered. We deduce which frame is rendered by looking
1081 // at the reported time progress.
1082
1083 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(600);
1084 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(500);
1085 base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
1086
1087 // Tell demuxer to make the first frame 100ms earlier than the seek request.
1088 demuxer_->SetVideoPrerollInterval(base::TimeDelta::FromMilliseconds(100));
1089
1090 demuxer_->SetVideoFactory(
1091 scoped_ptr<VideoFactory>(new VideoFactory(duration)));
1092
1093 CreatePlayer();
1094 SetVideoSurface();
1095
1096 // Wait till the player is initialized on media thread.
1097 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
1098 base::Unretained(demuxer_))));
1099
1100 // Post configuration after the player has been initialized.
1101 demuxer_->PostInternalConfigs();
1102
1103 // Issue SeekTo().
1104 player_->SeekTo(seek_position);
1105
1106 // Start the playback and make sure it is started.
1107 player_->Start();
1108
1109 EXPECT_TRUE(
1110 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
1111 base::Unretained(&manager_)),
1112 start_timeout));
1113
1114 // Wait for completion.
1115 EXPECT_TRUE(
1116 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
1117 base::Unretained(&manager_))));
1118
1119 // The first pts should be equal than seek position even if video frames
1120 // started 100 ms eralier than the seek request.
1121 EXPECT_EQ(seek_position, manager_.pts_stat_.min());
1122
1123 EXPECT_EQ(6, manager_.pts_stat_.num_values());
1124 }
1125
1058 } // namespace media 1126 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698