| Index: media/base/android/media_codec_player_unittest.cc
|
| diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc
|
| deleted file mode 100644
|
| index 380a8bd35872d9802020bf1a4444bb42b1a4f13b..0000000000000000000000000000000000000000
|
| --- a/media/base/android/media_codec_player_unittest.cc
|
| +++ /dev/null
|
| @@ -1,2283 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "media/base/android/media_codec_player.h"
|
| -
|
| -#include <stdint.h>
|
| -#include <memory>
|
| -#include <utility>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/logging.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/timer/timer.h"
|
| -#include "media/base/android/demuxer_android.h"
|
| -#include "media/base/android/media_codec_util.h"
|
| -#include "media/base/android/media_player_manager.h"
|
| -#include "media/base/android/media_task_runner.h"
|
| -#include "media/base/android/sdk_media_codec_bridge.h"
|
| -#include "media/base/android/test_data_factory.h"
|
| -#include "media/base/android/test_statistics.h"
|
| -#include "media/base/timestamp_constants.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "ui/gl/android/surface_texture.h"
|
| -
|
| -namespace media {
|
| -
|
| -#define RUN_ON_MEDIA_THREAD(CLASS, METHOD, ...) \
|
| - do { \
|
| - if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \
|
| - GetMediaTaskRunner()->PostTask( \
|
| - FROM_HERE, \
|
| - base::Bind(&CLASS::METHOD, base::Unretained(this), ##__VA_ARGS__)); \
|
| - return; \
|
| - } \
|
| - } while (0)
|
| -
|
| -namespace {
|
| -
|
| -const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200);
|
| -const base::TimeDelta kAudioFramePeriod =
|
| - base::TimeDelta::FromSecondsD(1024.0 / 44100); // 1024 samples @ 44100 Hz
|
| -const base::TimeDelta kVideoFramePeriod = base::TimeDelta::FromMilliseconds(20);
|
| -
|
| -enum Flags {
|
| - kAlwaysReconfigAudio = 0x1,
|
| - kAlwaysReconfigVideo = 0x2,
|
| -};
|
| -
|
| -// The predicate that always returns false, used for WaitForDelay implementation
|
| -bool AlwaysFalse() {
|
| - return false;
|
| -}
|
| -
|
| -// The method used to compare two time values of type T in expectations.
|
| -// Type T requires that a difference of type base::TimeDelta is defined.
|
| -template <typename T>
|
| -bool AlmostEqual(T a, T b, double tolerance_ms) {
|
| - return (a - b).magnitude().InMilliseconds() <= tolerance_ms;
|
| -}
|
| -
|
| -// A helper function to calculate the expected number of frames.
|
| -int GetFrameCount(base::TimeDelta duration,
|
| - base::TimeDelta frame_period,
|
| - int num_reconfigs) {
|
| - // A chunk has 4 access units. The last unit timestamp must exceed the
|
| - // duration. Last chunk has 3 regular access units and one stand-alone EOS
|
| - // unit that we do not count.
|
| -
|
| - // Number of time intervals to exceed duration.
|
| - int num_intervals = duration / frame_period + 1.0;
|
| -
|
| - // To cover these intervals we need one extra unit at the beginning and a one
|
| - // for each reconfiguration.
|
| - int num_units = num_intervals + 1 + num_reconfigs;
|
| -
|
| - // Number of 4-unit chunks that hold these units:
|
| - int num_chunks = (num_units + 3) / 4;
|
| -
|
| - // Altogether these chunks hold 4*num_chunks units, but we do not count
|
| - // reconfiguration units and last EOS as frames.
|
| - return 4 * num_chunks - 1 - num_reconfigs;
|
| -}
|
| -
|
| -// Mock of MediaPlayerManager for testing purpose.
|
| -
|
| -class MockMediaPlayerManager : public MediaPlayerManager {
|
| - public:
|
| - MockMediaPlayerManager()
|
| - : playback_allowed_(true),
|
| - playback_completed_(false),
|
| - num_seeks_completed_(0),
|
| - num_audio_codecs_created_(0),
|
| - num_video_codecs_created_(0),
|
| - weak_ptr_factory_(this) {}
|
| - ~MockMediaPlayerManager() override {}
|
| -
|
| - MediaResourceGetter* GetMediaResourceGetter() override { return nullptr; }
|
| - MediaUrlInterceptor* GetMediaUrlInterceptor() override { return nullptr; }
|
| -
|
| - // Regular time update callback, reports current playback time to
|
| - // MediaPlayerManager.
|
| - void OnTimeUpdate(int player_id,
|
| - base::TimeDelta current_timestamp,
|
| - base::TimeTicks current_time_ticks) override {
|
| - pts_stat_.AddValue(current_timestamp);
|
| - }
|
| -
|
| - void OnMediaMetadataChanged(int player_id,
|
| - base::TimeDelta duration,
|
| - int width,
|
| - int height,
|
| - bool success) override {
|
| - media_metadata_.duration = duration;
|
| - media_metadata_.width = width;
|
| - media_metadata_.height = height;
|
| - media_metadata_.modified = true;
|
| - }
|
| -
|
| - void OnPlaybackComplete(int player_id) override {
|
| - playback_completed_ = true;
|
| - }
|
| -
|
| - void OnMediaInterrupted(int player_id) override {}
|
| - void OnBufferingUpdate(int player_id, int percentage) override {}
|
| - void OnSeekComplete(int player_id,
|
| - const base::TimeDelta& current_time) override {
|
| - ++num_seeks_completed_;
|
| - }
|
| - void OnError(int player_id, int error) override {}
|
| - void OnVideoSizeChanged(int player_id, int width, int height) override {}
|
| - void OnWaitingForDecryptionKey(int player_id) override {}
|
| - MediaPlayerAndroid* GetFullscreenPlayer() override { return nullptr; }
|
| - MediaPlayerAndroid* GetPlayer(int player_id) override { return nullptr; }
|
| - bool RequestPlay(int player_id,
|
| - base::TimeDelta duration,
|
| - bool has_audio) override {
|
| - return playback_allowed_;
|
| - }
|
| -
|
| - void OnMediaResourcesRequested(int player_id) {}
|
| -
|
| - // Time update callback that reports the internal progress of the stream.
|
| - // Implementation dependent, used for testing only.
|
| - void OnDecodersTimeUpdate(DemuxerStream::Type stream_type,
|
| - base::TimeDelta now_playing,
|
| - base::TimeDelta last_buffered) {
|
| - render_stat_[stream_type].AddValue(
|
| - PTSTime(now_playing, base::TimeTicks::Now()));
|
| - }
|
| -
|
| - // Notification called on MediaCodec creation.
|
| - // Implementation dependent, used for testing only.
|
| - void OnMediaCodecCreated(DemuxerStream::Type stream_type) {
|
| - if (stream_type == DemuxerStream::AUDIO)
|
| - ++num_audio_codecs_created_;
|
| - else if (stream_type == DemuxerStream::VIDEO)
|
| - ++num_video_codecs_created_;
|
| - }
|
| -
|
| - // First frame information
|
| - base::TimeDelta FirstFramePTS(DemuxerStream::Type stream_type) const {
|
| - return render_stat_[stream_type].min().pts;
|
| - }
|
| - base::TimeTicks FirstFrameTime(DemuxerStream::Type stream_type) const {
|
| - return render_stat_[stream_type].min().time;
|
| - }
|
| -
|
| - base::WeakPtr<MockMediaPlayerManager> GetWeakPtr() {
|
| - return weak_ptr_factory_.GetWeakPtr();
|
| - }
|
| -
|
| - void SetPlaybackAllowed(bool value) { playback_allowed_ = value; }
|
| -
|
| - // Conditions to wait for.
|
| - bool IsMetadataChanged() const { return media_metadata_.modified; }
|
| - bool IsPlaybackCompleted() const { return playback_completed_; }
|
| - bool IsPlaybackStarted() const { return pts_stat_.num_values() > 0; }
|
| - bool IsPlaybackBeyondPosition(const base::TimeDelta& pts) const {
|
| - return pts_stat_.max() > pts;
|
| - }
|
| - bool IsSeekCompleted() const { return num_seeks_completed_ > 0; }
|
| - bool HasFirstFrame(DemuxerStream::Type stream_type) const {
|
| - return render_stat_[stream_type].num_values() != 0;
|
| - }
|
| -
|
| - int num_audio_codecs_created() const { return num_audio_codecs_created_; }
|
| - int num_video_codecs_created() const { return num_video_codecs_created_; }
|
| -
|
| - struct MediaMetadata {
|
| - base::TimeDelta duration;
|
| - int width;
|
| - int height;
|
| - bool modified;
|
| - MediaMetadata() : width(0), height(0), modified(false) {}
|
| - };
|
| - MediaMetadata media_metadata_;
|
| -
|
| - struct PTSTime {
|
| - base::TimeDelta pts;
|
| - base::TimeTicks time;
|
| -
|
| - PTSTime() : pts(), time() {}
|
| - PTSTime(base::TimeDelta p, base::TimeTicks t) : pts(p), time(t) {}
|
| - bool is_null() const { return time.is_null(); }
|
| - bool operator<(const PTSTime& rhs) const { return time < rhs.time; }
|
| - };
|
| - Minimax<PTSTime> render_stat_[DemuxerStream::NUM_TYPES];
|
| -
|
| - Minimax<base::TimeDelta> pts_stat_;
|
| -
|
| - private:
|
| - bool playback_allowed_;
|
| - bool playback_completed_;
|
| - int num_seeks_completed_;
|
| - int num_audio_codecs_created_;
|
| - int num_video_codecs_created_;
|
| -
|
| - base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager);
|
| -};
|
| -
|
| -// Helper method that creates demuxer configuration.
|
| -
|
| -DemuxerConfigs CreateAudioVideoConfigs(const base::TimeDelta& duration,
|
| - const gfx::Size& video_size) {
|
| - DemuxerConfigs configs =
|
| - TestDataFactory::CreateAudioConfigs(kCodecAAC, duration);
|
| - configs.video_codec = kCodecVP8;
|
| - configs.video_size = video_size;
|
| - configs.is_video_encrypted = false;
|
| - return configs;
|
| -}
|
| -
|
| -DemuxerConfigs CreateAudioVideoConfigs(const TestDataFactory* audio,
|
| - const TestDataFactory* video) {
|
| - DemuxerConfigs result = audio->GetConfigs();
|
| - DemuxerConfigs vconf = video->GetConfigs();
|
| -
|
| - result.video_codec = vconf.video_codec;
|
| - result.video_size = vconf.video_size;
|
| - result.is_video_encrypted = vconf.is_video_encrypted;
|
| - result.duration = std::max(result.duration, vconf.duration);
|
| - return result;
|
| -}
|
| -
|
| -// AudioFactory creates data chunks that simulate audio stream from demuxer.
|
| -
|
| -class AudioFactory : public TestDataFactory {
|
| - public:
|
| - AudioFactory(base::TimeDelta duration)
|
| - : TestDataFactory("aac-44100-packet-%d", duration, kAudioFramePeriod) {}
|
| -
|
| - DemuxerConfigs GetConfigs() const override {
|
| - return TestDataFactory::CreateAudioConfigs(kCodecAAC, duration_);
|
| - }
|
| -
|
| - protected:
|
| - void ModifyChunk(DemuxerData* chunk) override {
|
| - DCHECK(chunk);
|
| - for (AccessUnit& unit : chunk->access_units) {
|
| - if (!unit.data.empty())
|
| - unit.is_key_frame = true;
|
| - }
|
| - }
|
| -};
|
| -
|
| -// VideoFactory creates a video stream from demuxer.
|
| -
|
| -class VideoFactory : public TestDataFactory {
|
| - public:
|
| - VideoFactory(base::TimeDelta duration)
|
| - : TestDataFactory("h264-320x180-frame-%d", duration, kVideoFramePeriod),
|
| - key_frame_requested_(true) {}
|
| -
|
| - DemuxerConfigs GetConfigs() const override {
|
| - return TestDataFactory::CreateVideoConfigs(kCodecH264, duration_,
|
| - gfx::Size(320, 180));
|
| - }
|
| -
|
| - void RequestKeyFrame() { key_frame_requested_ = true; }
|
| -
|
| - protected:
|
| - void ModifyChunk(DemuxerData* chunk) override {
|
| - // The frames are taken from High profile and some are B-frames.
|
| - // The first 4 frames appear in the file in the following order:
|
| - //
|
| - // Frames: I P B P
|
| - // Decoding order: 0 1 2 3
|
| - // Presentation order: 0 2 1 4(3)
|
| - //
|
| - // I keep the last PTS to be 3 for simplicity.
|
| -
|
| - // If the chunk contains EOS, it should not break the presentation order.
|
| - // For instance, the following chunk is ok:
|
| - //
|
| - // Frames: I P B EOS
|
| - // Decoding order: 0 1 2 -
|
| - // Presentation order: 0 2 1 -
|
| - //
|
| - // while this might cause decoder to block:
|
| - //
|
| - // Frames: I P EOS
|
| - // Decoding order: 0 1 -
|
| - // Presentation order: 0 2 - <------- might wait for the B frame forever
|
| - //
|
| - // With current base class implementation that always has EOS at the 4th
|
| - // place we are covered (http://crbug.com/526755)
|
| -
|
| - DCHECK(chunk);
|
| - DCHECK(chunk->access_units.size() == 4);
|
| -
|
| - // Swap pts for second and third frames.
|
| - base::TimeDelta tmp = chunk->access_units[1].timestamp;
|
| - chunk->access_units[1].timestamp = chunk->access_units[2].timestamp;
|
| - chunk->access_units[2].timestamp = tmp;
|
| -
|
| - // Make first frame a key frame.
|
| - if (key_frame_requested_) {
|
| - chunk->access_units[0].is_key_frame = true;
|
| - key_frame_requested_ = false;
|
| - }
|
| - }
|
| -
|
| - private:
|
| - bool key_frame_requested_;
|
| -};
|
| -
|
| -// Mock of DemuxerAndroid for testing purpose.
|
| -
|
| -class MockDemuxerAndroid : public DemuxerAndroid {
|
| - public:
|
| - MockDemuxerAndroid(base::MessageLoop* ui_message_loop);
|
| - ~MockDemuxerAndroid() override;
|
| -
|
| - // DemuxerAndroid implementation
|
| - void Initialize(DemuxerAndroidClient* client) override;
|
| - void RequestDemuxerData(DemuxerStream::Type type) override;
|
| - void RequestDemuxerSeek(const base::TimeDelta& seek_request,
|
| - bool is_browser_seek) override;
|
| -
|
| - // Helper methods that enable using a weak pointer when posting to the player.
|
| - void OnDemuxerDataAvailable(const DemuxerData& chunk);
|
| - void OnDemuxerSeekDone(base::TimeDelta reported_seek_time);
|
| -
|
| - // Sets the callback that is fired when demuxer is deleted (deletion
|
| - // happens on the Media thread).
|
| - void SetDemuxerDeletedCallback(base::Closure cb) { demuxer_deleted_cb_ = cb; }
|
| -
|
| - // Sets the audio data factory.
|
| - void SetAudioFactory(std::unique_ptr<AudioFactory> factory) {
|
| - audio_factory_ = std::move(factory);
|
| - }
|
| -
|
| - // Sets the video data factory.
|
| - void SetVideoFactory(std::unique_ptr<VideoFactory> factory) {
|
| - video_factory_ = std::move(factory);
|
| - }
|
| -
|
| - // Accessors for data factories.
|
| - AudioFactory* audio_factory() const { return audio_factory_.get(); }
|
| - VideoFactory* video_factory() const { return video_factory_.get(); }
|
| -
|
| - // Set the preroll interval after seek for audio stream.
|
| - void SetAudioPrerollInterval(base::TimeDelta value) {
|
| - audio_preroll_interval_ = value;
|
| - }
|
| -
|
| - // Set the preroll interval after seek for video stream.
|
| - void SetVideoPrerollInterval(base::TimeDelta value) {
|
| - video_preroll_interval_ = value;
|
| - }
|
| -
|
| - // Sets the delay in OnDemuxerSeekDone response.
|
| - void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; }
|
| -
|
| - // Post DemuxerConfigs to the client (i.e. the player) on correct thread.
|
| - void PostConfigs(const DemuxerConfigs& configs);
|
| -
|
| - // Post DemuxerConfigs derived from data factories that has been set.
|
| - void PostInternalConfigs();
|
| -
|
| - // Conditions to wait for.
|
| - bool IsInitialized() const { return client_; }
|
| - bool HasPendingConfigs() const { return !!pending_configs_; }
|
| - bool ReceivedSeekRequest() const { return num_seeks_ > 0; }
|
| - bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_ > 0; }
|
| -
|
| - private:
|
| - base::MessageLoop* ui_message_loop_;
|
| - DemuxerAndroidClient* client_;
|
| -
|
| - std::unique_ptr<DemuxerConfigs> pending_configs_;
|
| - std::unique_ptr<AudioFactory> audio_factory_;
|
| - std::unique_ptr<VideoFactory> video_factory_;
|
| -
|
| - base::TimeDelta audio_preroll_interval_;
|
| - base::TimeDelta video_preroll_interval_;
|
| - base::TimeDelta seek_done_delay_;
|
| -
|
| - int num_seeks_;
|
| - int num_browser_seeks_;
|
| -
|
| - base::Closure demuxer_deleted_cb_;
|
| -
|
| - // NOTE: WeakPtrFactory must be the last data member to be destroyed first.
|
| - base::WeakPtrFactory<MockDemuxerAndroid> weak_factory_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid);
|
| -};
|
| -
|
| -MockDemuxerAndroid::MockDemuxerAndroid(base::MessageLoop* ui_message_loop)
|
| - : ui_message_loop_(ui_message_loop),
|
| - client_(nullptr),
|
| - num_seeks_(0),
|
| - num_browser_seeks_(0),
|
| - weak_factory_(this) {}
|
| -
|
| -MockDemuxerAndroid::~MockDemuxerAndroid() {
|
| - DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__;
|
| - DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| -
|
| - if (!demuxer_deleted_cb_.is_null())
|
| - ui_message_loop_->PostTask(FROM_HERE, demuxer_deleted_cb_);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::Initialize(DemuxerAndroidClient* client) {
|
| - DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__;
|
| - DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| -
|
| - client_ = client;
|
| - if (pending_configs_)
|
| - client_->OnDemuxerConfigsAvailable(*pending_configs_);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::RequestDemuxerData(DemuxerStream::Type type) {
|
| - DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| -
|
| - DemuxerData chunk;
|
| - base::TimeDelta delay;
|
| -
|
| - bool created = false;
|
| - if (type == DemuxerStream::AUDIO && audio_factory_)
|
| - created = audio_factory_->CreateChunk(&chunk, &delay);
|
| - else if (type == DemuxerStream::VIDEO && video_factory_)
|
| - created = video_factory_->CreateChunk(&chunk, &delay);
|
| -
|
| - if (!created)
|
| - return;
|
| -
|
| - // Request key frame after |kConfigChanged|
|
| - if (type == DemuxerStream::VIDEO && !chunk.demuxer_configs.empty())
|
| - video_factory_->RequestKeyFrame();
|
| -
|
| - chunk.type = type;
|
| -
|
| - // Post to the Media thread. Use the weak pointer to prevent the data arrival
|
| - // after the player has been deleted.
|
| - GetMediaTaskRunner()->PostDelayedTask(
|
| - FROM_HERE, base::Bind(&MockDemuxerAndroid::OnDemuxerDataAvailable,
|
| - weak_factory_.GetWeakPtr(), chunk),
|
| - delay);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& seek_request,
|
| - bool is_browser_seek) {
|
| - // Tell data factories to start next chunk with the new timestamp.
|
| - if (audio_factory_) {
|
| - base::TimeDelta time_to_seek =
|
| - std::max(base::TimeDelta(), seek_request - audio_preroll_interval_);
|
| - audio_factory_->SeekTo(time_to_seek);
|
| - }
|
| - if (video_factory_) {
|
| - base::TimeDelta time_to_seek =
|
| - std::max(base::TimeDelta(), seek_request - video_preroll_interval_);
|
| - video_factory_->SeekTo(time_to_seek);
|
| - video_factory_->RequestKeyFrame();
|
| - }
|
| -
|
| - ++num_seeks_;
|
| - if (is_browser_seek)
|
| - ++num_browser_seeks_;
|
| -
|
| - // Post OnDemuxerSeekDone() to the player.
|
| - DCHECK(client_);
|
| - base::TimeDelta reported_seek_time =
|
| - is_browser_seek ? seek_request : kNoTimestamp;
|
| - GetMediaTaskRunner()->PostDelayedTask(
|
| - FROM_HERE, base::Bind(&MockDemuxerAndroid::OnDemuxerSeekDone,
|
| - weak_factory_.GetWeakPtr(), reported_seek_time),
|
| - seek_done_delay_);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::OnDemuxerDataAvailable(const DemuxerData& chunk) {
|
| - DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| - DCHECK(client_);
|
| - client_->OnDemuxerDataAvailable(chunk);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::OnDemuxerSeekDone(base::TimeDelta reported_seek_time) {
|
| - DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| - DCHECK(client_);
|
| - client_->OnDemuxerSeekDone(reported_seek_time);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs& configs) {
|
| - RUN_ON_MEDIA_THREAD(MockDemuxerAndroid, PostConfigs, configs);
|
| -
|
| - DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__;
|
| -
|
| - DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| -
|
| - if (client_)
|
| - client_->OnDemuxerConfigsAvailable(configs);
|
| - else
|
| - pending_configs_ = base::MakeUnique<DemuxerConfigs>(configs);
|
| -}
|
| -
|
| -void MockDemuxerAndroid::PostInternalConfigs() {
|
| - ASSERT_TRUE(audio_factory_ || video_factory_);
|
| -
|
| - if (audio_factory_ && video_factory_) {
|
| - PostConfigs(
|
| - CreateAudioVideoConfigs(audio_factory_.get(), video_factory_.get()));
|
| - } else if (audio_factory_) {
|
| - PostConfigs(audio_factory_->GetConfigs());
|
| - } else if (video_factory_) {
|
| - PostConfigs(video_factory_->GetConfigs());
|
| - }
|
| -}
|
| -
|
| -} // namespace (anonymous)
|
| -
|
| -// The test fixture for MediaCodecPlayer
|
| -
|
| -class MediaCodecPlayerTest : public testing::Test {
|
| - public:
|
| - MediaCodecPlayerTest();
|
| -
|
| - // Conditions to wait for.
|
| - bool IsPaused() const { return !(player_ && player_->IsPlaying()); }
|
| -
|
| - protected:
|
| - typedef base::Callback<bool()> Predicate;
|
| -
|
| - void TearDown() override;
|
| -
|
| - void CreatePlayer();
|
| - void SetVideoSurface();
|
| - void SetVideoSurfaceB();
|
| - void RemoveVideoSurface();
|
| -
|
| - // Waits for condition to become true or for timeout to expire.
|
| - // Returns true if the condition becomes true.
|
| - bool WaitForCondition(const Predicate& condition,
|
| - const base::TimeDelta& timeout = kDefaultTimeout);
|
| -
|
| - // Waits for timeout to expire.
|
| - void WaitForDelay(const base::TimeDelta& timeout);
|
| -
|
| - // Waits till playback position as determined by maximal reported pts
|
| - // reaches the given value or for timeout to expire. Returns true if the
|
| - // playback has passed the given position.
|
| - bool WaitForPlaybackBeyondPosition(
|
| - const base::TimeDelta& pts,
|
| - const base::TimeDelta& timeout = kDefaultTimeout);
|
| -
|
| - // Helper method that starts video only stream. Waits till it actually
|
| - // started.
|
| - bool StartVideoPlayback(base::TimeDelta duration, const char* test_name);
|
| -
|
| - // Helper method that starts audio and video streams.
|
| - bool StartAVPlayback(std::unique_ptr<AudioFactory> audio_factory,
|
| - std::unique_ptr<VideoFactory> video_factory,
|
| - uint32_t flags,
|
| - const char* test_name);
|
| -
|
| - // Helper method that starts audio and video streams with preroll.
|
| - // The preroll is achieved by setting significant video preroll interval
|
| - // so video will have to catch up with audio. To make room for this interval
|
| - // the Start() command is preceded by SeekTo().
|
| - bool StartAVSeekAndPreroll(std::unique_ptr<AudioFactory> audio_factory,
|
| - std::unique_ptr<VideoFactory> video_factory,
|
| - base::TimeDelta seek_position,
|
| - uint32_t flags,
|
| - const char* test_name);
|
| -
|
| - // Callback sent when demuxer is being deleted.
|
| - void OnDemuxerDeleted() { demuxer_ = nullptr; }
|
| -
|
| - bool IsDemuxerDeleted() const { return !demuxer_; }
|
| -
|
| - base::MessageLoop message_loop_;
|
| - MockMediaPlayerManager manager_;
|
| - MockDemuxerAndroid* demuxer_; // owned by player_
|
| - scoped_refptr<gl::SurfaceTexture> surface_texture_a_;
|
| - scoped_refptr<gl::SurfaceTexture> surface_texture_b_;
|
| - MediaCodecPlayer* player_; // raw pointer due to DeleteOnCorrectThread()
|
| -
|
| - private:
|
| - bool is_timeout_expired() const { return is_timeout_expired_; }
|
| - void SetTimeoutExpired(bool value) { is_timeout_expired_ = value; }
|
| -
|
| - bool is_timeout_expired_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MediaCodecPlayerTest);
|
| -};
|
| -
|
| -MediaCodecPlayerTest::MediaCodecPlayerTest()
|
| - : demuxer_(new MockDemuxerAndroid(&message_loop_)),
|
| - player_(nullptr),
|
| - is_timeout_expired_(false) {}
|
| -
|
| -void MediaCodecPlayerTest::TearDown() {
|
| - DVLOG(1) << __FUNCTION__;
|
| -
|
| - // Wait till the player is destroyed on the Media thread.
|
| -
|
| - if (player_) {
|
| - // The player deletes the demuxer on the Media thread. The demuxer's
|
| - // destructor sends a notification to the UI thread. When this notification
|
| - // arrives we can conclude that player started destroying its member
|
| - // variables. By that time the media codecs should have been released.
|
| -
|
| - DCHECK(demuxer_);
|
| - demuxer_->SetDemuxerDeletedCallback(base::Bind(
|
| - &MediaCodecPlayerTest::OnDemuxerDeleted, base::Unretained(this)));
|
| -
|
| - player_->DeleteOnCorrectThread();
|
| -
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MediaCodecPlayerTest::IsDemuxerDeleted,
|
| - base::Unretained(this)),
|
| - base::TimeDelta::FromMilliseconds(500)));
|
| -
|
| - player_ = nullptr;
|
| - }
|
| -}
|
| -
|
| -void MediaCodecPlayerTest::CreatePlayer() {
|
| - DCHECK(demuxer_);
|
| - player_ = new MediaCodecPlayer(
|
| - 0, // player_id
|
| - manager_.GetWeakPtr(),
|
| - base::Bind(&MockMediaPlayerManager::OnMediaResourcesRequested,
|
| - base::Unretained(&manager_)),
|
| - base::WrapUnique(demuxer_), GURL(), kDefaultMediaSessionId);
|
| -
|
| - DCHECK(player_);
|
| -}
|
| -
|
| -void MediaCodecPlayerTest::SetVideoSurface() {
|
| - surface_texture_a_ = gl::SurfaceTexture::Create(0);
|
| - gl::ScopedJavaSurface surface(surface_texture_a_.get());
|
| -
|
| - ASSERT_NE(nullptr, player_);
|
| - player_->SetVideoSurface(std::move(surface));
|
| -}
|
| -
|
| -void MediaCodecPlayerTest::SetVideoSurfaceB() {
|
| - surface_texture_b_ = gl::SurfaceTexture::Create(1);
|
| - gl::ScopedJavaSurface surface(surface_texture_b_.get());
|
| -
|
| - ASSERT_NE(nullptr, player_);
|
| - player_->SetVideoSurface(std::move(surface));
|
| -}
|
| -
|
| -void MediaCodecPlayerTest::RemoveVideoSurface() {
|
| - player_->SetVideoSurface(gl::ScopedJavaSurface());
|
| - surface_texture_a_ = NULL;
|
| -}
|
| -
|
| -bool MediaCodecPlayerTest::WaitForCondition(const Predicate& condition,
|
| - const base::TimeDelta& timeout) {
|
| - // Let the message_loop_ process events.
|
| - // We start the timer and RunUntilIdle() until it signals.
|
| -
|
| - SetTimeoutExpired(false);
|
| -
|
| - base::Timer timer(false, false);
|
| - timer.Start(FROM_HERE, timeout,
|
| - base::Bind(&MediaCodecPlayerTest::SetTimeoutExpired,
|
| - base::Unretained(this), true));
|
| -
|
| - do {
|
| - if (condition.Run()) {
|
| - timer.Stop();
|
| - return true;
|
| - }
|
| - message_loop_.RunUntilIdle();
|
| - } while (!is_timeout_expired());
|
| -
|
| - DCHECK(!timer.IsRunning());
|
| - return false;
|
| -}
|
| -
|
| -void MediaCodecPlayerTest::WaitForDelay(const base::TimeDelta& timeout) {
|
| - WaitForCondition(base::Bind(&AlwaysFalse), timeout);
|
| -}
|
| -
|
| -bool MediaCodecPlayerTest::WaitForPlaybackBeyondPosition(
|
| - const base::TimeDelta& pts,
|
| - const base::TimeDelta& timeout) {
|
| - return WaitForCondition(
|
| - base::Bind(&MockMediaPlayerManager::IsPlaybackBeyondPosition,
|
| - base::Unretained(&manager_), pts),
|
| - timeout);
|
| -}
|
| -
|
| -bool MediaCodecPlayerTest::StartVideoPlayback(base::TimeDelta duration,
|
| - const char* test_name) {
|
| - const base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| -
|
| - demuxer_->SetVideoFactory(base::MakeUnique<VideoFactory>(duration));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - if (!demuxer_->IsInitialized()) {
|
| - DVLOG(0) << test_name << ": demuxer is not initialized";
|
| - return false;
|
| - }
|
| -
|
| - SetVideoSurface();
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Start the player.
|
| - EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - start_timeout));
|
| -
|
| - if (!manager_.IsPlaybackStarted()) {
|
| - DVLOG(0) << test_name << ": playback did not start";
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool MediaCodecPlayerTest::StartAVPlayback(
|
| - std::unique_ptr<AudioFactory> audio_factory,
|
| - std::unique_ptr<VideoFactory> video_factory,
|
| - uint32_t flags,
|
| - const char* test_name) {
|
| - demuxer_->SetAudioFactory(std::move(audio_factory));
|
| - demuxer_->SetVideoFactory(std::move(video_factory));
|
| -
|
| - CreatePlayer();
|
| - SetVideoSurface();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - if (!demuxer_->IsInitialized()) {
|
| - DVLOG(0) << test_name << ": demuxer is not initialized";
|
| - return false;
|
| - }
|
| -
|
| - // Ask decoders to always reconfigure after the player has been initialized.
|
| - if (flags & kAlwaysReconfigAudio)
|
| - player_->SetAlwaysReconfigureForTests(DemuxerStream::AUDIO);
|
| - if (flags & kAlwaysReconfigVideo)
|
| - player_->SetAlwaysReconfigureForTests(DemuxerStream::VIDEO);
|
| -
|
| - // Set a testing callback to receive PTS from decoders.
|
| - player_->SetDecodersTimeCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Set a testing callback to receive MediaCodec creation events from decoders.
|
| - player_->SetCodecCreatedCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Start and wait for playback.
|
| - player_->Start();
|
| -
|
| - // Wait till we start to play.
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
|
| -
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - start_timeout));
|
| -
|
| - if (!manager_.IsPlaybackStarted()) {
|
| - DVLOG(0) << test_name << ": playback did not start";
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool MediaCodecPlayerTest::StartAVSeekAndPreroll(
|
| - std::unique_ptr<AudioFactory> audio_factory,
|
| - std::unique_ptr<VideoFactory> video_factory,
|
| - base::TimeDelta seek_position,
|
| - uint32_t flags,
|
| - const char* test_name) {
|
| - // Initialize A/V playback
|
| -
|
| - demuxer_->SetAudioFactory(std::move(audio_factory));
|
| - demuxer_->SetVideoFactory(std::move(video_factory));
|
| -
|
| - CreatePlayer();
|
| - SetVideoSurface();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - if (!demuxer_->IsInitialized()) {
|
| - DVLOG(0) << test_name << ": demuxer is not initialized";
|
| - return false;
|
| - }
|
| -
|
| - // Ask decoders to always reconfigure after the player has been initialized.
|
| - if (flags & kAlwaysReconfigAudio)
|
| - player_->SetAlwaysReconfigureForTests(DemuxerStream::AUDIO);
|
| - if (flags & kAlwaysReconfigVideo)
|
| - player_->SetAlwaysReconfigureForTests(DemuxerStream::VIDEO);
|
| -
|
| - // Set a testing callback to receive PTS from decoders.
|
| - player_->SetDecodersTimeCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Set a testing callback to receive MediaCodec creation events from decoders.
|
| - player_->SetCodecCreatedCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Issue SeekTo().
|
| - player_->SeekTo(seek_position);
|
| -
|
| - // Start the playback.
|
| - player_->Start();
|
| -
|
| - // Wait till preroll starts.
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayer::IsPrerollingForTests,
|
| - base::Unretained(player_), DemuxerStream::VIDEO),
|
| - start_timeout));
|
| -
|
| - if (!player_->IsPrerollingForTests(DemuxerStream::VIDEO)) {
|
| - DVLOG(0) << test_name << ": preroll did not happen for video";
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, SetAudioConfigsBeforePlayerCreation) {
|
| - // Post configuration when there is no player yet.
|
| - EXPECT_EQ(nullptr, player_);
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
|
| -
|
| - demuxer_->PostConfigs(
|
| - TestDataFactory::CreateAudioConfigs(kCodecAAC, duration));
|
| -
|
| - // Wait until the configuration gets to the media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockDemuxerAndroid::HasPendingConfigs, base::Unretained(demuxer_))));
|
| -
|
| - // Then create the player.
|
| - CreatePlayer();
|
| -
|
| - // Configuration should propagate through the player and to the manager.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsMetadataChanged,
|
| - base::Unretained(&manager_))));
|
| -
|
| - EXPECT_EQ(duration, manager_.media_metadata_.duration);
|
| - EXPECT_EQ(0, manager_.media_metadata_.width);
|
| - EXPECT_EQ(0, manager_.media_metadata_.height);
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, SetAudioConfigsAfterPlayerCreation) {
|
| - CreatePlayer();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
|
| - demuxer_->PostConfigs(
|
| - TestDataFactory::CreateAudioConfigs(kCodecAAC, duration));
|
| -
|
| - // Configuration should propagate through the player and to the manager.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsMetadataChanged,
|
| - base::Unretained(&manager_))));
|
| -
|
| - EXPECT_EQ(duration, manager_.media_metadata_.duration);
|
| - EXPECT_EQ(0, manager_.media_metadata_.width);
|
| - EXPECT_EQ(0, manager_.media_metadata_.height);
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, SetAudioVideoConfigsAfterPlayerCreation) {
|
| - CreatePlayer();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
|
| - demuxer_->PostConfigs(CreateAudioVideoConfigs(duration, gfx::Size(320, 240)));
|
| -
|
| - // Configuration should propagate through the player and to the manager.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsMetadataChanged,
|
| - base::Unretained(&manager_))));
|
| -
|
| - EXPECT_EQ(duration, manager_.media_metadata_.duration);
|
| - EXPECT_EQ(320, manager_.media_metadata_.width);
|
| - EXPECT_EQ(240, manager_.media_metadata_.height);
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AudioPlayTillCompletion) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(2000);
|
| -
|
| - demuxer_->SetAudioFactory(base::MakeUnique<AudioFactory>(duration));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - EXPECT_FALSE(manager_.IsPlaybackCompleted());
|
| -
|
| - player_->Start();
|
| -
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - timeout));
|
| -
|
| - // Current timestamp reflects "now playing" time. It might come with delay
|
| - // relative to the frame's PTS. Allow for 100 ms delay here.
|
| - base::TimeDelta audio_pts_delay = base::TimeDelta::FromMilliseconds(100);
|
| - EXPECT_LT(duration - audio_pts_delay, manager_.pts_stat_.max());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, AudioNoPermission) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| -
|
| - manager_.SetPlaybackAllowed(false);
|
| -
|
| - demuxer_->SetAudioFactory(base::MakeUnique<AudioFactory>(duration));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - EXPECT_FALSE(manager_.IsPlaybackCompleted());
|
| -
|
| - player_->Start();
|
| -
|
| - // Playback should not start.
|
| - EXPECT_FALSE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - start_timeout));
|
| -}
|
| -
|
| -// crbug.com/618274
|
| -#if defined(OS_ANDROID)
|
| -#define MAYBE_VideoPlayTillCompletion DISABLED_VideoPlayTillCompletion
|
| -#else
|
| -#define MAYBE_VideoPlayTillCompletion VideoPlayTillCompletion
|
| -#endif
|
| -TEST_F(MediaCodecPlayerTest, MAYBE_VideoPlayTillCompletion) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
|
| - base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(2000);
|
| -
|
| - ASSERT_TRUE(StartVideoPlayback(duration, "VideoPlayTillCompletion"));
|
| -
|
| - // Wait till completion.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - timeout));
|
| -
|
| - EXPECT_LE(duration, manager_.pts_stat_.max());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, VideoNoPermission) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
|
| - const base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| -
|
| - manager_.SetPlaybackAllowed(false);
|
| -
|
| - demuxer_->SetVideoFactory(base::MakeUnique<VideoFactory>(duration));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - SetVideoSurface();
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Start the player.
|
| - EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| - player_->Start();
|
| -
|
| - // Playback should not start.
|
| - EXPECT_FALSE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - start_timeout));
|
| -}
|
| -
|
| -// http://crbug.com/518900
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AudioSeekAfterStop) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Play for 300 ms, then Pause, then Seek to beginning. The playback should
|
| - // start from the beginning.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| -
|
| - demuxer_->SetAudioFactory(base::WrapUnique(new AudioFactory(duration)));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Post configuration.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Start the player.
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // Wait for 300 ms and stop. The 300 ms interval takes into account potential
|
| - // audio delay: audio takes time reconfiguring after the first several packets
|
| - // get written to the audio track.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(300));
|
| -
|
| - player_->Pause(true);
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // Wait till the Pause is completed.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayerTest::IsPaused, base::Unretained(this))));
|
| -
|
| - // Clear statistics.
|
| - manager_.pts_stat_.Clear();
|
| -
|
| - // Now we can seek to the beginning and start the playback.
|
| - player_->SeekTo(base::TimeDelta());
|
| -
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // Make sure we started from the beginninig
|
| - EXPECT_GT(base::TimeDelta::FromMilliseconds(40), manager_.pts_stat_.min());
|
| -
|
| - // The player should have reported the seek completion to the manager.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AudioSeekThenPlay) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Issue Seek command immediately followed by Start. The playback should
|
| - // start at the seek position.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(500);
|
| -
|
| - demuxer_->SetAudioFactory(base::MakeUnique<AudioFactory>(duration));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Post configuration.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Seek and immediately start.
|
| - player_->SeekTo(seek_position);
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // The playback should start at |seek_position|
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
|
| -
|
| - // The player should have reported the seek completion to the manager.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AudioSeekThenPlayThenConfig) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Issue Seek command immediately followed by Start but without prior demuxer
|
| - // configuration. Start should wait for configuration. After it has been
|
| - // posted the playback should start at the seek position.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(500);
|
| -
|
| - demuxer_->SetAudioFactory(base::MakeUnique<AudioFactory>(duration));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Seek and immediately start.
|
| - player_->SeekTo(seek_position);
|
| - player_->Start();
|
| -
|
| - // Make sure the player is waiting.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| - EXPECT_FALSE(player_->IsPlaying());
|
| -
|
| - // Post configuration.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Wait for playback to start.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // The playback should start at |seek_position|
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
|
| -
|
| - // The player should have reported the seek completion to the manager.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| -}
|
| -
|
| -// http://crbug.com/518900
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AudioSeekWhilePlaying) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Play for 300 ms, then issue several Seek commands in the row.
|
| - // The playback should continue at the last seek position.
|
| -
|
| - // To test this condition without analyzing the reported time details
|
| - // and without introducing dependency on implementation I make a long (10s)
|
| - // duration and test that the playback resumes after big time jump (5s) in a
|
| - // short period of time (200 ms).
|
| - base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
|
| -
|
| - demuxer_->SetAudioFactory(base::WrapUnique(new AudioFactory(duration)));
|
| -
|
| - CreatePlayer();
|
| -
|
| - // Post configuration.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Start the player.
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // Wait for 300 ms.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(300));
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // Seek forward several times.
|
| - player_->SeekTo(base::TimeDelta::FromSeconds(3));
|
| - player_->SeekTo(base::TimeDelta::FromSeconds(4));
|
| - player_->SeekTo(base::TimeDelta::FromSeconds(5));
|
| -
|
| - // Make sure that we reached the last timestamp within default timeout,
|
| - // i.e. 200 ms.
|
| - EXPECT_TRUE(WaitForPlaybackBeyondPosition(base::TimeDelta::FromSeconds(5)));
|
| - EXPECT_TRUE(player_->IsPlaying());
|
| -
|
| - // The player should have reported the seek completion to the manager.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| -}
|
| -
|
| -// Disabled per http://crbug.com/611489.
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoReplaceSurface) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1500);
|
| -
|
| - ASSERT_TRUE(StartVideoPlayback(duration, "VideoReplaceSurface"));
|
| -
|
| - // Wait for some time and check statistics.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // Set new video surface without removing the old one.
|
| - SetVideoSurfaceB();
|
| -
|
| - // We should receive a browser seek request.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Playback should continue with a new surface. Wait till completion.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - timeout));
|
| - EXPECT_LE(duration, manager_.pts_stat_.max());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoRemoveAndSetSurface) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - ASSERT_TRUE(StartVideoPlayback(duration, "VideoRemoveAndSetSurface"));
|
| -
|
| - // Wait for some time and check statistics.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // Remove video surface.
|
| - RemoveVideoSurface();
|
| -
|
| - // We should be stuck waiting for the new surface.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| - EXPECT_FALSE(player_->IsPlaying());
|
| -
|
| - // Save last PTS and clear statistics.
|
| - base::TimeDelta max_pts_before_removal = manager_.pts_stat_.max();
|
| - manager_.pts_stat_.Clear();
|
| -
|
| - // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| - EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| -
|
| - // Extra RemoveVideoSurface() should not change anything.
|
| - RemoveVideoSurface();
|
| -
|
| - // Set another video surface.
|
| - SetVideoSurfaceB();
|
| -
|
| - // We should receive a browser seek request.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Playback should continue with a new surface. Wait till it starts again.
|
| - base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(800);
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - reconfigure_timeout));
|
| -
|
| - // Timestamps should not go back.
|
| - EXPECT_LE(max_pts_before_removal, manager_.pts_stat_.max());
|
| -}
|
| -
|
| -// http://crbug.com/518900
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoReleaseAndStart) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - ASSERT_TRUE(StartVideoPlayback(duration, "VideoReleaseAndStart"));
|
| -
|
| - // Wait for some time and check statistics.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // When the user presses Tasks button Chrome calls Pause() and Release().
|
| - player_->Pause(true);
|
| - player_->Release();
|
| -
|
| - // Make sure we are not playing any more.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| - EXPECT_FALSE(player_->IsPlaying());
|
| -
|
| - // Save last PTS and clear statistics.
|
| - base::TimeDelta max_pts_before_backgrounding = manager_.pts_stat_.max();
|
| - manager_.pts_stat_.Clear();
|
| -
|
| - // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| - EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| -
|
| - // Restart.
|
| - SetVideoSurface();
|
| - player_->Start();
|
| -
|
| - // We should receive a browser seek request.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - // Wait for playback to start again.
|
| - base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(800);
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - reconfigure_timeout));
|
| -
|
| - // Timestamps should not go back.
|
| - EXPECT_LE(max_pts_before_backgrounding, manager_.pts_stat_.max());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoSeekAndRelease) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - ASSERT_TRUE(StartVideoPlayback(duration, "VideoSeekAndRelease"));
|
| -
|
| - // Wait for some time and check statistics.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // Issue SeekTo() immediately followed by Release().
|
| - player_->SeekTo(seek_position);
|
| - player_->Release();
|
| -
|
| - // Make sure we are not playing any more.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(400));
|
| - EXPECT_FALSE(player_->IsPlaying());
|
| -
|
| - // The Release() should not cancel the SeekTo() and we should have received
|
| - // the seek request by this time.
|
| - EXPECT_TRUE(demuxer_->ReceivedSeekRequest());
|
| -
|
| - // The player should have reported the seek completion to the manager.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| -
|
| - // Clear statistics.
|
| - manager_.pts_stat_.Clear();
|
| -
|
| - // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| - EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| -
|
| - // Restart.
|
| - SetVideoSurface();
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start again.
|
| - base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(800);
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - reconfigure_timeout));
|
| -
|
| - // Timestamps should start at the new seek position
|
| - EXPECT_LE(seek_position, manager_.pts_stat_.min());
|
| -}
|
| -
|
| -// Flaky test: https://crbug.com/609444
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoReleaseWhileWaitingForSeek) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - ASSERT_TRUE(StartVideoPlayback(duration, "VideoReleaseWhileWaitingForSeek"));
|
| -
|
| - // Wait for some time and check statistics.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| -
|
| - // Make sure we played at least 100 ms.
|
| - EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| -
|
| - // Set artificial delay in the OnDemuxerSeekDone response so we can
|
| - // issue commands while the player is in the STATE_WAITING_FOR_SEEK.
|
| - demuxer_->SetSeekDoneDelay(base::TimeDelta::FromMilliseconds(100));
|
| -
|
| - // Issue SeekTo().
|
| - player_->SeekTo(seek_position);
|
| -
|
| - // Wait for the seek request to demuxer.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockDemuxerAndroid::ReceivedSeekRequest, base::Unretained(demuxer_))));
|
| -
|
| - // The player is supposed to be in STATE_WAITING_FOR_SEEK. Issue Release().
|
| - player_->Release();
|
| -
|
| - // Make sure we are not playing any more.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(400));
|
| - EXPECT_FALSE(player_->IsPlaying());
|
| -
|
| - // Clear statistics.
|
| - manager_.pts_stat_.Clear();
|
| -
|
| - // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| - EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| -
|
| - // Restart.
|
| - SetVideoSurface();
|
| - player_->Start();
|
| -
|
| - // Wait for playback to start again.
|
| - base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(1000);
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - reconfigure_timeout));
|
| -
|
| - // Timestamps should start at the new seek position
|
| - EXPECT_LE(seek_position, manager_.pts_stat_.min());
|
| -
|
| - // The player should have reported the seek completion to the manager.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(
|
| - &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| -}
|
| -
|
| -// Disabled per http://crbug.com/611489.
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoPrerollAfterSeek) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // A simple test for preroll for video stream only. After the seek is done
|
| - // the data factory generates the frames with pts before the seek time, and
|
| - // they should not be rendered. We deduce which frame is rendered by looking
|
| - // at the reported time progress.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(600);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(500);
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| -
|
| - // Tell demuxer to make the first frame 100ms earlier than the seek request.
|
| - demuxer_->SetVideoPrerollInterval(base::TimeDelta::FromMilliseconds(100));
|
| -
|
| - demuxer_->SetVideoFactory(base::WrapUnique(new VideoFactory(duration)));
|
| -
|
| - CreatePlayer();
|
| - SetVideoSurface();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| - if (!demuxer_->IsInitialized()) {
|
| - DVLOG(0) << "VideoPrerollAfterSeek: demuxer is not initialized";
|
| - return;
|
| - }
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Issue SeekTo().
|
| - player_->SeekTo(seek_position);
|
| -
|
| - // Start the playback and make sure it is started.
|
| - player_->Start();
|
| -
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - start_timeout));
|
| -
|
| - // Wait for completion.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // The first pts should be equal than seek position even if video frames
|
| - // started 100 ms eralier than the seek request.
|
| - EXPECT_EQ(seek_position, manager_.pts_stat_.min());
|
| -
|
| - EXPECT_EQ(6, manager_.pts_stat_.num_values());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVPrerollAudioWaitsForVideo) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that during prerolling neither audio nor video plays and that both
|
| - // resume simultaneously after preroll is finished. In other words, test
|
| - // that preroll works.
|
| - // We put the video into the long preroll and intercept the time when first
|
| - // rendering happens in each stream. The moment of rendering is approximated
|
| - // with a decoder PTS that is delivered by a test-only callback.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| -
|
| - // Set significant preroll interval. 500 ms means 25 frames, at 10 ms
|
| - // per frame it would take 250 ms to preroll.
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500);
|
| - base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - demuxer_->SetVideoPrerollInterval(preroll_intvl);
|
| -
|
| - ASSERT_TRUE(StartAVSeekAndPreroll(std::move(audio_factory),
|
| - std::move(video_factory), seek_position, 0,
|
| - "AVPrerollAudioWaitsForVideo"));
|
| -
|
| - // Wait till preroll finishes and the real playback starts.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - preroll_timeout));
|
| -
|
| - // Ensure that the first audio and video pts are close to each other and are
|
| - // reported at the close moments in time.
|
| -
|
| - EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockMediaPlayerManager::HasFirstFrame,
|
| - base::Unretained(&manager_), DemuxerStream::VIDEO)));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
|
| - manager_.FirstFramePTS(DemuxerStream::VIDEO), 25));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
|
| - manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
|
| -
|
| - // The playback should start at |seek_position|
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVPrerollReleaseAndRestart) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that player will resume prerolling if prerolling is interrupted by
|
| - // Release() and Start().
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| -
|
| - // Set significant preroll interval. 500 ms means 25 frames, at 10 ms
|
| - // per frame it would take 250 ms to preroll.
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500);
|
| -
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| - base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - demuxer_->SetVideoPrerollInterval(preroll_intvl);
|
| -
|
| - ASSERT_TRUE(StartAVSeekAndPreroll(std::move(audio_factory),
|
| - std::move(video_factory), seek_position, 0,
|
| - "AVPrerollReleaseAndRestart"));
|
| -
|
| - // Issue Release().
|
| - player_->Release();
|
| -
|
| - // Make sure we have not been playing.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(400));
|
| -
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO));
|
| -
|
| - EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO));
|
| - EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO));
|
| - EXPECT_EQ(0, manager_.pts_stat_.num_values());
|
| -
|
| - // Restart. Release() removed the video surface, we need to set it again.
|
| - SetVideoSurface();
|
| - player_->Start();
|
| -
|
| - // The playback should pass through prerolling phase.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayer::IsPrerollingForTests,
|
| - base::Unretained(player_), DemuxerStream::VIDEO),
|
| - start_timeout));
|
| -
|
| - // Wait till preroll finishes and the real playback starts.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - preroll_timeout));
|
| -
|
| - // Ensure that the first audio and video pts are close to each other and are
|
| - // reported at the close moments in time.
|
| -
|
| - EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockMediaPlayerManager::HasFirstFrame,
|
| - base::Unretained(&manager_), DemuxerStream::VIDEO)));
|
| -
|
| - // Release() might disacrd first audio frame.
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
|
| - manager_.FirstFramePTS(DemuxerStream::VIDEO), 50));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
|
| - manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
|
| -
|
| - // The playback should start at |seek_position|, but Release() might discard
|
| - // the first audio frame.
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 50));
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVPrerollStopAndRestart) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that if Pause() happens during the preroll phase,
|
| - // we continue to do preroll after restart.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| -
|
| - // Set significant preroll interval. 500 ms means 25 frames, at 10 ms
|
| - // per frame it would take 250 ms to preroll.
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500);
|
| -
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| - base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - demuxer_->SetVideoPrerollInterval(preroll_intvl);
|
| -
|
| - ASSERT_TRUE(StartAVSeekAndPreroll(std::move(audio_factory),
|
| - std::move(video_factory), seek_position, 0,
|
| - "AVPrerollStopAndRestart"));
|
| -
|
| - // Video stream should be prerolling. Request to stop.
|
| - EXPECT_FALSE(IsPaused());
|
| - player_->Pause(true);
|
| -
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayerTest::IsPaused, base::Unretained(this))));
|
| -
|
| - // Test that we have not been playing.
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO));
|
| -
|
| - EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO));
|
| - EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO));
|
| - EXPECT_EQ(0, manager_.pts_stat_.num_values());
|
| -
|
| - // Restart.
|
| - player_->Start();
|
| -
|
| - // There should be preroll after the start.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayer::IsPrerollingForTests,
|
| - base::Unretained(player_), DemuxerStream::VIDEO),
|
| - start_timeout));
|
| -
|
| - // Wait for a short period of time, so that preroll is still ongoing,
|
| - // and pause again.
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(100));
|
| -
|
| - EXPECT_FALSE(IsPaused());
|
| - player_->Pause(true);
|
| -
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayerTest::IsPaused, base::Unretained(this))));
|
| -
|
| - // Check that we still haven't started rendering.
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO));
|
| -
|
| - EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO));
|
| - EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO));
|
| - EXPECT_EQ(0, manager_.pts_stat_.num_values());
|
| -
|
| - // Restart again.
|
| - player_->Start();
|
| -
|
| - // Wait till we start to play.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - preroll_timeout));
|
| -
|
| - // Check that we did prerolling, i.e. audio did wait for video.
|
| - EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockMediaPlayerManager::HasFirstFrame,
|
| - base::Unretained(&manager_), DemuxerStream::VIDEO)));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
|
| - manager_.FirstFramePTS(DemuxerStream::VIDEO), 25));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
|
| - manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
|
| -
|
| - // The playback should start at |seek_position|
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVPrerollVideoEndsWhilePrerolling) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that when one stream ends in the preroll phase and another is not
|
| - // the preroll finishes and playback continues after it.
|
| -
|
| - // http://crbug.com/526755
|
| - // TODO(timav): remove these logs after verifying that the bug is fixed.
|
| - DVLOG(0) << "AVPrerollVideoEndsWhilePrerolling: begin";
|
| -
|
| - base::TimeDelta audio_duration = base::TimeDelta::FromMilliseconds(1100);
|
| - base::TimeDelta video_duration = base::TimeDelta::FromMilliseconds(900);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta video_preroll_intvl = base::TimeDelta::FromMilliseconds(200);
|
| -
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| - base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(400);
|
| -
|
| - demuxer_->SetVideoPrerollInterval(video_preroll_intvl);
|
| -
|
| - demuxer_->SetAudioFactory(base::MakeUnique<AudioFactory>(audio_duration));
|
| - demuxer_->SetVideoFactory(base::MakeUnique<VideoFactory>(video_duration));
|
| -
|
| - CreatePlayer();
|
| - SetVideoSurface();
|
| -
|
| - // Set special testing callback to receive PTS from decoders.
|
| - player_->SetDecodersTimeCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - if (!demuxer_->IsInitialized()) {
|
| - DVLOG(0) << "AVPrerollVideoEndsWhilePrerolling: demuxer is not initialized";
|
| - return;
|
| - }
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Issue SeekTo().
|
| - player_->SeekTo(seek_position);
|
| -
|
| - // Start the playback.
|
| - player_->Start();
|
| -
|
| - // The video decoder should start prerolling.
|
| - // Wait till preroll starts.
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MediaCodecPlayer::IsPrerollingForTests,
|
| - base::Unretained(player_), DemuxerStream::VIDEO),
|
| - start_timeout));
|
| -
|
| - // Wait for playback to start.
|
| - bool playback_started =
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - preroll_timeout);
|
| -
|
| - // http://crbug.com/526755
|
| - if (!playback_started) {
|
| - DVLOG(0) << "AVPrerollVideoEndsWhilePrerolling: playback did not start for "
|
| - << preroll_timeout;
|
| - }
|
| - ASSERT_TRUE(playback_started);
|
| -
|
| - EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| -
|
| - // Play till completion.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_))));
|
| -
|
| - // There should not be any video frames.
|
| - EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO));
|
| -
|
| - // http://crbug.com/526755
|
| - DVLOG(0) << "AVPrerollVideoEndsWhilePrerolling: end";
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_VideoConfigChangeWhilePlaying) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that video only playback continues after video config change.
|
| -
|
| - // Initialize video playback
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta config_change_position =
|
| - base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - demuxer_->SetVideoFactory(base::MakeUnique<VideoFactory>(duration));
|
| -
|
| - demuxer_->video_factory()->RequestConfigChange(config_change_position);
|
| -
|
| - CreatePlayer();
|
| - SetVideoSurface();
|
| -
|
| - // Wait till the player is initialized on media thread.
|
| - EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
|
| - base::Unretained(demuxer_))));
|
| -
|
| - if (!demuxer_->IsInitialized()) {
|
| - DVLOG(0) << "VideoConfigChangeWhilePlaying: demuxer is not initialized";
|
| - return;
|
| - }
|
| -
|
| - // Ask decoders to always reconfigure after the player has been initialized.
|
| - player_->SetAlwaysReconfigureForTests(DemuxerStream::VIDEO);
|
| -
|
| - // Set a testing callback to receive PTS from decoders.
|
| - player_->SetDecodersTimeCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Set a testing callback to receive MediaCodec creation events from decoders.
|
| - player_->SetCodecCreatedCallbackForTests(
|
| - base::Bind(&MockMediaPlayerManager::OnMediaCodecCreated,
|
| - base::Unretained(&manager_)));
|
| -
|
| - // Post configuration after the player has been initialized.
|
| - demuxer_->PostInternalConfigs();
|
| -
|
| - // Start and wait for playback.
|
| - player_->Start();
|
| -
|
| - // Wait till we start to play.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - start_timeout));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The video codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss video frames
|
| - int expected_video_frames = GetFrameCount(duration, kVideoFramePeriod, 1);
|
| - EXPECT_EQ(expected_video_frames,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].num_values());
|
| -}
|
| -
|
| -// https://crbug.com/587195
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVVideoConfigChangeWhilePlaying) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that A/V playback continues after video config change.
|
| -
|
| - // Initialize A/V playback
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta config_change_position =
|
| - base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - video_factory->RequestConfigChange(config_change_position);
|
| -
|
| - ASSERT_TRUE(StartAVPlayback(std::move(audio_factory),
|
| - std::move(video_factory), kAlwaysReconfigVideo,
|
| - "AVVideoConfigChangeWhilePlaying"));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The audio codec should be kept.
|
| - EXPECT_EQ(1, manager_.num_audio_codecs_created());
|
| -
|
| - // The video codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss video frames
|
| - int expected_video_frames = GetFrameCount(duration, kVideoFramePeriod, 1);
|
| - EXPECT_EQ(expected_video_frames,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].num_values());
|
| -
|
| - // Check that we did not miss audio frames. We expect one postponed frames
|
| - // that are not reported.
|
| - // For Nexus 4 KitKat the AAC decoder seems to swallow the first frame
|
| - // but reports the last pts twice, maybe it just shifts the reported PTS.
|
| - int expected_audio_frames = GetFrameCount(duration, kAudioFramePeriod, 0) - 1;
|
| - EXPECT_EQ(expected_audio_frames,
|
| - manager_.render_stat_[DemuxerStream::AUDIO].num_values());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVAudioConfigChangeWhilePlaying) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that A/V playback continues after audio config change.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta config_change_position =
|
| - base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - audio_factory->RequestConfigChange(config_change_position);
|
| -
|
| - ASSERT_TRUE(StartAVPlayback(std::move(audio_factory),
|
| - std::move(video_factory), kAlwaysReconfigAudio,
|
| - "AVAudioConfigChangeWhilePlaying"));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The audio codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_audio_codecs_created());
|
| -
|
| - // The video codec should be kept.
|
| - EXPECT_EQ(1, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss video frames.
|
| - int expected_video_frames = GetFrameCount(duration, kVideoFramePeriod, 0);
|
| - EXPECT_EQ(expected_video_frames,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].num_values());
|
| -
|
| - // Check that we did not miss audio frames. We expect two postponed frames
|
| - // that are not reported.
|
| - int expected_audio_frames = GetFrameCount(duration, kAudioFramePeriod, 1) - 2;
|
| - EXPECT_EQ(expected_audio_frames,
|
| - manager_.render_stat_[DemuxerStream::AUDIO].num_values());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVSimultaneousConfigChange_1) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that the playback continues if audio and video config changes happen
|
| - // at the same time.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta config_change_audio = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta config_change_video = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - audio_factory->RequestConfigChange(config_change_audio);
|
| - video_factory->RequestConfigChange(config_change_video);
|
| -
|
| - ASSERT_TRUE(StartAVPlayback(std::move(audio_factory),
|
| - std::move(video_factory),
|
| - kAlwaysReconfigAudio | kAlwaysReconfigVideo,
|
| - "AVSimultaneousConfigChange_1"));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The audio codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_audio_codecs_created());
|
| -
|
| - // The video codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss video frames.
|
| - int expected_video_frames = GetFrameCount(duration, kVideoFramePeriod, 1);
|
| - EXPECT_EQ(expected_video_frames,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].num_values());
|
| -
|
| - // Check that we did not miss audio frames. We expect two postponed frames
|
| - // that are not reported.
|
| - int expected_audio_frames = GetFrameCount(duration, kAudioFramePeriod, 1) - 2;
|
| - EXPECT_EQ(expected_audio_frames,
|
| - manager_.render_stat_[DemuxerStream::AUDIO].num_values());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVSimultaneousConfigChange_2) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that the playback continues if audio and video config changes happen
|
| - // at the same time. Move audio change moment slightly to make it drained
|
| - // after video.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta config_change_audio = base::TimeDelta::FromMilliseconds(1020);
|
| - base::TimeDelta config_change_video = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - audio_factory->RequestConfigChange(config_change_audio);
|
| - video_factory->RequestConfigChange(config_change_video);
|
| -
|
| - ASSERT_TRUE(StartAVPlayback(std::move(audio_factory),
|
| - std::move(video_factory),
|
| - kAlwaysReconfigAudio | kAlwaysReconfigVideo,
|
| - "AVSimultaneousConfigChange_2"));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The audio codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_audio_codecs_created());
|
| -
|
| - // The video codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss video frames.
|
| - int expected_video_frames = GetFrameCount(duration, kVideoFramePeriod, 1);
|
| - EXPECT_EQ(expected_video_frames,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].num_values());
|
| -
|
| - // Check that we did not miss audio frames. We expect two postponed frames
|
| - // that are not reported.
|
| - int expected_audio_frames = GetFrameCount(duration, kAudioFramePeriod, 1) - 2;
|
| - EXPECT_EQ(expected_audio_frames,
|
| - manager_.render_stat_[DemuxerStream::AUDIO].num_values());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVAudioEndsAcrossVideoConfigChange) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that audio can end while video config change processing.
|
| -
|
| - base::TimeDelta audio_duration = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta video_duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta config_change_video = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(audio_duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(video_duration));
|
| -
|
| - video_factory->RequestConfigChange(config_change_video);
|
| -
|
| - ASSERT_TRUE(StartAVPlayback(std::move(audio_factory),
|
| - std::move(video_factory), kAlwaysReconfigVideo,
|
| - "AVAudioEndsAcrossVideoConfigChange"));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The audio codec should not be recreated.
|
| - EXPECT_EQ(1, manager_.num_audio_codecs_created());
|
| -
|
| - // The video codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss video frames.
|
| - int expected_video_frames =
|
| - GetFrameCount(video_duration, kVideoFramePeriod, 1);
|
| - EXPECT_EQ(expected_video_frames,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].num_values());
|
| -
|
| - // Check the last video frame timestamp. The maximum render pts may differ
|
| - // from |video_duration| because of the testing artefact: if the last video
|
| - // chunk is incomplete if will have different last pts due to B-frames
|
| - // rearrangements.
|
| - EXPECT_LE(video_duration,
|
| - manager_.render_stat_[DemuxerStream::VIDEO].max().pts);
|
| -
|
| - // Check that the playback time reported by the player goes past
|
| - // the audio time and corresponds to video after the audio ended.
|
| - EXPECT_EQ(video_duration, manager_.pts_stat_.max());
|
| -}
|
| -
|
| -// https://crbug.com/587195
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVVideoEndsAcrossAudioConfigChange) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that video can end while audio config change processing.
|
| - base::TimeDelta audio_duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta video_duration = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta config_change_audio = base::TimeDelta::FromMilliseconds(1000);
|
| -
|
| - base::TimeDelta completion_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(audio_duration));
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(video_duration));
|
| -
|
| - audio_factory->RequestConfigChange(config_change_audio);
|
| -
|
| - ASSERT_TRUE(StartAVPlayback(std::move(audio_factory),
|
| - std::move(video_factory), kAlwaysReconfigAudio,
|
| - "AVVideoEndsAcrossAudioConfigChange"));
|
| -
|
| - // Wait till completion
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| - base::Unretained(&manager_)),
|
| - completion_timeout));
|
| -
|
| - // The audio codec should be recreated upon config changes.
|
| - EXPECT_EQ(2, manager_.num_audio_codecs_created());
|
| -
|
| - // The video codec should not be recreated.
|
| - EXPECT_EQ(1, manager_.num_video_codecs_created());
|
| -
|
| - // Check that we did not miss audio frames. We expect two postponed frames
|
| - // that are not reported.
|
| - int expected_audio_frames =
|
| - GetFrameCount(audio_duration, kAudioFramePeriod, 1) - 2;
|
| - EXPECT_EQ(expected_audio_frames,
|
| - manager_.render_stat_[DemuxerStream::AUDIO].num_values());
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVPrerollAcrossVideoConfigChange) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that preroll continues if interrupted by video config change.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta config_change_position =
|
| - base::TimeDelta::FromMilliseconds(800);
|
| - base::TimeDelta video_preroll_intvl = base::TimeDelta::FromMilliseconds(500);
|
| - base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - demuxer_->SetVideoPrerollInterval(video_preroll_intvl);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| -
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| - video_factory->RequestConfigChange(config_change_position);
|
| -
|
| - ASSERT_TRUE(StartAVSeekAndPreroll(
|
| - std::move(audio_factory), std::move(video_factory), seek_position,
|
| - kAlwaysReconfigVideo, "AVPrerollAcrossVideoConfigChange"));
|
| -
|
| - // Wait till preroll finishes and the real playback starts.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - preroll_timeout));
|
| -
|
| - // The presense of config change should not affect preroll behavior:
|
| -
|
| - // Ensure that the first audio and video pts are close to each other and are
|
| - // reported at the close moments in time.
|
| -
|
| - EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockMediaPlayerManager::HasFirstFrame,
|
| - base::Unretained(&manager_), DemuxerStream::VIDEO)));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
|
| - manager_.FirstFramePTS(DemuxerStream::VIDEO), 25));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
|
| - manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
|
| -
|
| - // The playback should start at |seek_position|
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
|
| -}
|
| -
|
| -TEST_F(MediaCodecPlayerTest, DISABLED_AVPrerollAcrossAudioConfigChange) {
|
| - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| -
|
| - // Test that preroll continues if interrupted by video config change.
|
| -
|
| - base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200);
|
| - base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| - base::TimeDelta config_change_position =
|
| - base::TimeDelta::FromMilliseconds(800);
|
| - base::TimeDelta audio_preroll_intvl = base::TimeDelta::FromMilliseconds(400);
|
| - base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(3000);
|
| -
|
| - demuxer_->SetAudioPrerollInterval(audio_preroll_intvl);
|
| -
|
| - std::unique_ptr<AudioFactory> audio_factory(new AudioFactory(duration));
|
| - audio_factory->RequestConfigChange(config_change_position);
|
| -
|
| - std::unique_ptr<VideoFactory> video_factory(new VideoFactory(duration));
|
| -
|
| - ASSERT_TRUE(StartAVSeekAndPreroll(
|
| - std::move(audio_factory), std::move(video_factory), seek_position,
|
| - kAlwaysReconfigAudio, "AVPrerollAcrossAudioConfigChange"));
|
| -
|
| - // Wait till preroll finishes and the real playback starts.
|
| - EXPECT_TRUE(
|
| - WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| - base::Unretained(&manager_)),
|
| - preroll_timeout));
|
| -
|
| - // The presense of config change should not affect preroll behavior:
|
| -
|
| - // Ensure that the first audio and video pts are close to each other and are
|
| - // reported at the close moments in time.
|
| -
|
| - EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO));
|
| - EXPECT_TRUE(WaitForCondition(
|
| - base::Bind(&MockMediaPlayerManager::HasFirstFrame,
|
| - base::Unretained(&manager_), DemuxerStream::VIDEO)));
|
| -
|
| - // Wait for some more video
|
| - WaitForDelay(base::TimeDelta::FromMilliseconds(100));
|
| -
|
| - EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO),
|
| - manager_.FirstFramePTS(DemuxerStream::VIDEO), 25));
|
| -
|
| - // Because for video preroll the first frame after preroll renders during the
|
| - // preroll stage (and not after the preroll is done) we cannot guarantee the
|
| - // proper video timimg in this test.
|
| - // TODO(timav): maybe we should not call the testing callback for
|
| - // kRenderAfterPreroll for video (for audio we already do not call).
|
| - // EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO),
|
| - // manager_.FirstFrameTime(DemuxerStream::VIDEO), 50));
|
| -
|
| - // The playback should start at |seek_position|
|
| - EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 25));
|
| -}
|
| -
|
| -} // namespace media
|
|
|