Commit ad7d871b authored by Dale Curtis's avatar Dale Curtis Committed by Commit Bot

Don't attempt to enable non-existant placeholder tracks.

The media pipeline does not expect to be called about track changes
prior to HaveCurrentData. There's also no reason for the element
to create disabled video+audio tracks and then tell the renderer
to enable those very same non-existant tracks. Just create them
as enabled instead.

It's possible we can remove even the creation of placeholder
tracks, but that's a bigger web facing change, so I don't want
to hold up this bug fix on that analysis.

BUG=873837
TEST=new unittest, twitter videos no longer hang.

Change-Id: I9863ae4feca29a58140e6dad1532bc8b7a380c3b
Reviewed-on: https://chromium-review.googlesource.com/1180347
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585334}
parent 3f6c31f0
...@@ -1828,8 +1828,6 @@ void HTMLMediaElement::SetReadyState(ReadyState state) { ...@@ -1828,8 +1828,6 @@ void HTMLMediaElement::SetReadyState(ReadyState state) {
if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) { if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) {
CreatePlaceholderTracksIfNecessary(); CreatePlaceholderTracksIfNecessary();
SelectInitialTracksIfNecessary();
MediaFragmentURIParser fragment_parser(current_src_); MediaFragmentURIParser fragment_parser(current_src_);
fragment_end_time_ = fragment_parser.EndTime(); fragment_end_time_ = fragment_parser.EndTime();
...@@ -3981,30 +3979,17 @@ void HTMLMediaElement::CreatePlaceholderTracksIfNecessary() { ...@@ -3981,30 +3979,17 @@ void HTMLMediaElement::CreatePlaceholderTracksIfNecessary() {
// didn't explicitly announce the tracks. // didn't explicitly announce the tracks.
if (HasAudio() && !audioTracks().length()) { if (HasAudio() && !audioTracks().length()) {
AddAudioTrack("audio", WebMediaPlayerClient::kAudioTrackKindMain, AddAudioTrack("audio", WebMediaPlayerClient::kAudioTrackKindMain,
"Audio Track", "", false); "Audio Track", "", true);
} }
// Create a placeholder video track if the player says it has video but it // Create a placeholder video track if the player says it has video but it
// didn't explicitly announce the tracks. // didn't explicitly announce the tracks.
if (HasVideo() && !videoTracks().length()) { if (HasVideo() && !videoTracks().length()) {
AddVideoTrack("video", WebMediaPlayerClient::kVideoTrackKindMain, AddVideoTrack("video", WebMediaPlayerClient::kVideoTrackKindMain,
"Video Track", "", false); "Video Track", "", true);
} }
} }
void HTMLMediaElement::SelectInitialTracksIfNecessary() {
if (!MediaTracksEnabledInternally())
return;
// Enable the first audio track if an audio track hasn't been enabled yet.
if (audioTracks().length() > 0 && !audioTracks().HasEnabledTrack())
audioTracks().AnonymousIndexedGetter(0)->setEnabled(true);
// Select the first video track if a video track hasn't been selected yet.
if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1)
videoTracks().AnonymousIndexedGetter(0)->setSelected(true);
}
void HTMLMediaElement::SetNetworkState(NetworkState state) { void HTMLMediaElement::SetNetworkState(NetworkState state) {
if (network_state_ == state) if (network_state_ == state)
return; return;
......
...@@ -534,16 +534,12 @@ class CORE_EXPORT HTMLMediaElement ...@@ -534,16 +534,12 @@ class CORE_EXPORT HTMLMediaElement
DirectionOfPlayback GetDirectionOfPlayback() const; DirectionOfPlayback GetDirectionOfPlayback() const;
// Creates placeholder AudioTrack and/or VideoTrack objects when // Creates placeholder AudioTrack and/or VideoTrack objects when
// WebMemediaPlayer objects advertise they have audio and/or video, but don't // WebMediaPlayer objects advertise they have audio and/or video, but don't
// explicitly signal them via addAudioTrack() and addVideoTrack(). // explicitly signal them via addAudioTrack() and addVideoTrack().
// FIXME: Remove this once all WebMediaPlayer implementations properly report // FIXME: Remove this once all WebMediaPlayer implementations properly report
// their track info. // their track info.
void CreatePlaceholderTracksIfNecessary(); void CreatePlaceholderTracksIfNecessary();
// Sets the selected/enabled tracks if they aren't set before we initially
// transition to kHaveMetadata.
void SelectInitialTracksIfNecessary();
void SetNetworkState(NetworkState); void SetNetworkState(NetworkState);
void AudioTracksTimerFired(TimerBase*); void AudioTracksTimerFired(TimerBase*);
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "third_party/blink/renderer/core/html/media/html_audio_element.h" #include "third_party/blink/renderer/core/html/media/html_audio_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/media/media_error.h" #include "third_party/blink/renderer/core/html/media/media_error.h"
#include "third_party/blink/renderer/core/html/track/audio_track_list.h"
#include "third_party/blink/renderer/core/html/track/video_track_list.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h" #include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h" #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
...@@ -26,8 +28,12 @@ namespace blink { ...@@ -26,8 +28,12 @@ namespace blink {
class MockWebMediaPlayer : public EmptyWebMediaPlayer { class MockWebMediaPlayer : public EmptyWebMediaPlayer {
public: public:
MOCK_CONST_METHOD0(HasAudio, bool());
MOCK_CONST_METHOD0(HasVideo, bool());
MOCK_CONST_METHOD0(Duration, double()); MOCK_CONST_METHOD0(Duration, double());
MOCK_CONST_METHOD0(CurrentTime, double()); MOCK_CONST_METHOD0(CurrentTime, double());
MOCK_METHOD1(EnabledAudioTracksChanged, void(const WebVector<TrackId>&));
MOCK_METHOD1(SelectedVideoTrackChanged, void(TrackId*));
MOCK_METHOD3( MOCK_METHOD3(
Load, Load,
WebMediaPlayer::LoadTiming(LoadType load_type, WebMediaPlayer::LoadTiming(LoadType load_type,
...@@ -69,7 +75,15 @@ class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> { ...@@ -69,7 +75,15 @@ class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
// Most tests do not care about this call, nor its return value. Those that // Most tests do not care about this call, nor its return value. Those that
// do will clear this expectation and set custom expectations/returns. // do will clear this expectation and set custom expectations/returns.
EXPECT_CALL(*MockMediaPlayer(), Load(_, _, _)) EXPECT_CALL(*mock_media_player, HasAudio())
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*mock_media_player, HasVideo())
.WillRepeatedly(testing::Return(true));
EXPECT_CALL(*mock_media_player, Duration())
.WillRepeatedly(testing::Return(1.0));
EXPECT_CALL(*mock_media_player, CurrentTime())
.WillRepeatedly(testing::Return(0));
EXPECT_CALL(*mock_media_player, Load(_, _, _))
.Times(AnyNumber()) .Times(AnyNumber())
.WillRepeatedly(Return(WebMediaPlayer::LoadTiming::kImmediate)); .WillRepeatedly(Return(WebMediaPlayer::LoadTiming::kImmediate));
...@@ -235,8 +249,6 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToEnded) { ...@@ -235,8 +249,6 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToEnded) {
MockWebMediaPlayer* mock_wmpi = MockWebMediaPlayer* mock_wmpi =
reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer()); reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
EXPECT_NE(mock_wmpi, nullptr); EXPECT_NE(mock_wmpi, nullptr);
EXPECT_CALL(*mock_wmpi, Duration()).WillRepeatedly(testing::Return(1.0));
EXPECT_CALL(*mock_wmpi, CurrentTime()).WillRepeatedly(testing::Return(0));
EXPECT_TRUE(CouldPlayIfEnoughData()); EXPECT_TRUE(CouldPlayIfEnoughData());
// Playback can only end once the ready state is above kHaveMetadata. // Playback can only end once the ready state is above kHaveMetadata.
...@@ -262,8 +274,6 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToError) { ...@@ -262,8 +274,6 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToError) {
MockWebMediaPlayer* mock_wmpi = MockWebMediaPlayer* mock_wmpi =
reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer()); reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
EXPECT_NE(mock_wmpi, nullptr); EXPECT_NE(mock_wmpi, nullptr);
EXPECT_CALL(*mock_wmpi, Duration()).WillRepeatedly(testing::Return(1.0));
EXPECT_CALL(*mock_wmpi, CurrentTime()).WillRepeatedly(testing::Return(0));
EXPECT_TRUE(CouldPlayIfEnoughData()); EXPECT_TRUE(CouldPlayIfEnoughData());
SetReadyState(HTMLMediaElement::kHaveMetadata); SetReadyState(HTMLMediaElement::kHaveMetadata);
...@@ -419,4 +429,19 @@ TEST_P(HTMLMediaElementTest, ImmediateMediaPlayerLoadDoesDelayWindowLoadEvent) { ...@@ -419,4 +429,19 @@ TEST_P(HTMLMediaElementTest, ImmediateMediaPlayerLoadDoesDelayWindowLoadEvent) {
EXPECT_TRUE(ShouldDelayLoadEvent()); EXPECT_TRUE(ShouldDelayLoadEvent());
} }
TEST_P(HTMLMediaElementTest, DefaultTracksAreEnabled) {
// Default tracks should start enabled, not be created then enabled.
EXPECT_CALL(*MockMediaPlayer(), EnabledAudioTracksChanged(_)).Times(0);
EXPECT_CALL(*MockMediaPlayer(), SelectedVideoTrackChanged(_)).Times(0);
Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
test::RunPendingTasks();
SetReadyState(HTMLMediaElement::kHaveFutureData);
ASSERT_EQ(1u, Media()->audioTracks().length());
ASSERT_EQ(1u, Media()->videoTracks().length());
EXPECT_TRUE(Media()->audioTracks().AnonymousIndexedGetter(0)->enabled());
EXPECT_TRUE(Media()->videoTracks().AnonymousIndexedGetter(0)->selected());
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment