Skip to content

Commit

Permalink
Provide fine grained media playback time thru interpolation
Browse files Browse the repository at this point in the history
This CL includes the following changes:
1. Reduces the interval of media time update msg to 16 ms
2. Use interpolation to calculate the current playback time, and guarantee that time is always incrementing

BUG=327425

Review URL: https://codereview.chromium.org/545993002

Cr-Commit-Position: refs/heads/master@{#294612}
  • Loading branch information
qinmin authored and Commit bot committed Sep 12, 2014
1 parent eb19494 commit 4360c7c
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 36 deletions.
10 changes: 6 additions & 4 deletions content/browser/media/android/browser_media_player_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,12 @@ void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
player->SetVideoSurface(gfx::ScopedJavaSurface());
}

void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
base::TimeDelta current_time) {
Send(
new MediaPlayerMsg_MediaTimeUpdate(RoutingID(), player_id, current_time));
void BrowserMediaPlayerManager::OnTimeUpdate(
int player_id,
base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks) {
Send(new MediaPlayerMsg_MediaTimeUpdate(
RoutingID(), player_id, current_timestamp, current_time_ticks));
}

void BrowserMediaPlayerManager::SetVideoSurface(
Expand Down
4 changes: 3 additions & 1 deletion content/browser/media/android/browser_media_player_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ class CONTENT_EXPORT BrowserMediaPlayerManager

// media::MediaPlayerManager overrides.
virtual void OnTimeUpdate(
int player_id, base::TimeDelta current_time) OVERRIDE;
int player_id,
base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks) OVERRIDE;
virtual void OnMediaMetadataChanged(
int player_id,
base::TimeDelta duration,
Expand Down
5 changes: 3 additions & 2 deletions content/common/media/media_player_messages_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,10 @@ IPC_MESSAGE_ROUTED3(MediaPlayerMsg_MediaVideoSizeChanged,
int /* height */)

// The current play time has updated.
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaTimeUpdate,
IPC_MESSAGE_ROUTED3(MediaPlayerMsg_MediaTimeUpdate,
int /* player_id */,
base::TimeDelta /* current_time */)
base::TimeDelta /* current_timestamp */,
base::TimeTicks /* current_time_ticks */)

// The player has been released.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlayerReleased,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,13 @@ void RendererMediaPlayerManager::OnVideoSizeChanged(int player_id,
player->OnVideoSizeChanged(width, height);
}

void RendererMediaPlayerManager::OnTimeUpdate(int player_id,
base::TimeDelta current_time) {
void RendererMediaPlayerManager::OnTimeUpdate(
int player_id,
base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks) {
WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
if (player)
player->OnTimeUpdate(current_time);
player->OnTimeUpdate(current_timestamp, current_time_ticks);
}

void RendererMediaPlayerManager::OnMediaPlayerReleased(int player_id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,13 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
void OnMediaPlaybackCompleted(int player_id);
void OnMediaBufferingUpdate(int player_id, int percent);
void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
void OnSeekCompleted(int player_id, const base::TimeDelta& current_time);
void OnSeekCompleted(int player_id,
const base::TimeDelta& current_timestamp);
void OnMediaError(int player_id, int error);
void OnVideoSizeChanged(int player_id, int width, int height);
void OnTimeUpdate(int player_id, base::TimeDelta current_time);
void OnTimeUpdate(int player_id,
base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks);
void OnMediaPlayerReleased(int player_id);
void OnConnectedToRemoteDevice(int player_id,
const std::string& remote_playback_message);
Expand Down
41 changes: 31 additions & 10 deletions content/renderer/media/android/webmediaplayer_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/android/media_common_android.h"
#include "media/base/android/media_player_android.h"
#include "media/base/bind_to_current_loop.h"
// TODO(xhwang): Remove when we remove prefixed EME implementation.
Expand Down Expand Up @@ -143,12 +144,12 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
video_frame_provider_client_(NULL),
pending_playback_(false),
player_type_(MEDIA_PLAYER_TYPE_URL),
current_time_(0),
is_remote_(false),
media_log_(media_log),
web_cdm_(NULL),
allow_stored_credentials_(false),
is_local_resource_(false),
interpolator_(&default_tick_clock_),
weak_factory_(this) {
DCHECK(player_manager_);
DCHECK(cdm_manager_);
Expand All @@ -168,6 +169,7 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
}
#endif // defined(VIDEO_HOLE)
TryCreateStreamTextureProxyIfNeeded();
interpolator_.SetUpperBound(base::TimeDelta());
}

WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
Expand Down Expand Up @@ -465,7 +467,9 @@ double WebMediaPlayerAndroid::currentTime() const {
pending_seek_time_.InSecondsF() : seek_time_.InSecondsF();
}

return current_time_;
return std::min(
(const_cast<media::TimeDeltaInterpolator*>(
&interpolator_))->GetInterpolatedTime(), duration_).InSecondsF();
}

WebSize WebMediaPlayerAndroid::naturalSize() const {
Expand Down Expand Up @@ -718,7 +722,8 @@ void WebMediaPlayerAndroid::OnMediaMetadataChanged(
// cause duration() query.
if (!ignore_metadata_duration_change_ && duration_ != duration) {
duration_ = duration;

if (is_local_resource_)
buffered_[0].end = duration_.InSecondsF();
// Client readyState transition from HAVE_NOTHING to HAVE_METADATA
// already triggers a durationchanged event. If this is a different
// transition, remember to signal durationchanged.
Expand Down Expand Up @@ -751,7 +756,7 @@ void WebMediaPlayerAndroid::OnPlaybackComplete() {
// at a time which is smaller than the duration. This makes webkit never
// know that the playback has finished. To solve this, we set the
// current time to media duration when OnPlaybackComplete() get called.
OnTimeUpdate(duration_);
interpolator_.SetBounds(duration_, duration_);
client_->timeChanged();

// if the loop attribute is set, timeChanged() will update the current time
Expand Down Expand Up @@ -783,8 +788,7 @@ void WebMediaPlayerAndroid::OnSeekComplete(
seek(pending_seek_time_.InSecondsF());
return;
}

OnTimeUpdate(current_time);
interpolator_.SetBounds(current_time, current_time);

UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);

Expand Down Expand Up @@ -868,11 +872,24 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
client_->timeChanged();
}

void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) {
void WebMediaPlayerAndroid::OnTimeUpdate(base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks) {
DCHECK(main_thread_checker_.CalledOnValidThread());
current_time_ = current_time.InSecondsF();
if (is_local_resource_ && current_time_ <= duration())
buffered_[0].end = current_time_;
// Compensate the current_timestamp with the IPC latency.
base::TimeDelta lower_bound =
base::TimeTicks::Now() - current_time_ticks + current_timestamp;
base::TimeDelta upper_bound = lower_bound;
// We should get another time update in about |kTimeUpdateInterval|
// milliseconds.
if (is_playing_) {
upper_bound += base::TimeDelta::FromMilliseconds(
media::kTimeUpdateInterval);
}
// if the lower_bound is smaller than the current time, just use the current
// time so that the timer is always progressing.
lower_bound =
std::min(lower_bound, base::TimeDelta::FromSecondsD(currentTime()));
interpolator_.SetBounds(lower_bound, upper_bound);
}

void WebMediaPlayerAndroid::OnConnectedToRemoteDevice(
Expand Down Expand Up @@ -1293,6 +1310,10 @@ void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
is_playing_ = is_playing;
if (!delegate_ || was_playing == is_playing_)
return;
if (is_playing)
interpolator_.StartInterpolating();
else
interpolator_.StopInterpolating();
if (is_playing)
delegate_->DidPlay(this);
else
Expand Down
17 changes: 11 additions & 6 deletions content/renderer/media/android/webmediaplayer_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/layers/video_frame_provider.h"
#include "content/common/media/media_player_messages_enums_android.h"
Expand All @@ -26,6 +27,7 @@
#include "media/base/android/media_player_android.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_keys.h"
#include "media/base/time_delta_interpolator.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebSize.h"
Expand Down Expand Up @@ -185,7 +187,8 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
void OnDurationChanged(const base::TimeDelta& duration);

// Called to update the current time.
void OnTimeUpdate(const base::TimeDelta& current_time);
void OnTimeUpdate(base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks);

// Functions called when media player status changes.
void OnConnectedToRemoteDevice(const std::string& remote_playback_message);
Expand Down Expand Up @@ -455,11 +458,6 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,

MediaPlayerHostMsg_Initialize_Type player_type_;

// The current playing time. Because the media player is in the browser
// process, it will regularly update the |current_time_| by calling
// OnTimeUpdate().
double current_time_;

// Whether the browser is currently connected to a remote media player.
bool is_remote_;

Expand Down Expand Up @@ -496,6 +494,13 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Whether the resource is local.
bool is_local_resource_;

// base::TickClock used by |interpolator_|.
base::DefaultTickClock default_tick_clock_;

// Tracks the most recent media time update and provides interpolated values
// as playback progresses.
media::TimeDeltaInterpolator interpolator_;

// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<WebMediaPlayerAndroid> weak_factory_;

Expand Down
15 changes: 15 additions & 0 deletions media/base/android/media_common_android.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2014 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.

#ifndef MEDIA_BASE_ANDROID_MEDIA_COMMON_ANDROID_H_
#define MEDIA_BASE_ANDROID_MEDIA_COMMON_ANDROID_H_

namespace media {

// Time update message is sent to the render process every 100ms.
static const int kTimeUpdateInterval = 100;

} // namespace media

#endif // MEDIA_BASE_ANDROID_MEDIA_COMMON_ANDROID_H_
7 changes: 3 additions & 4 deletions media/base/android/media_player_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_util.h"
#include "jni/MediaPlayerBridge_jni.h"
#include "media/base/android/media_common_android.h"
#include "media/base/android/media_player_manager.h"
#include "media/base/android/media_resource_getter.h"
#include "media/base/android/media_url_interceptor.h"

using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;

// Time update happens every 250ms.
const int kTimeUpdateInterval = 250;

namespace media {

MediaPlayerBridge::MediaPlayerBridge(
Expand Down Expand Up @@ -509,7 +507,8 @@ void MediaPlayerBridge::SeekInternal(base::TimeDelta time) {
}

void MediaPlayerBridge::OnTimeUpdateTimerFired() {
manager()->OnTimeUpdate(player_id(), GetCurrentTime());
manager()->OnTimeUpdate(
player_id(), GetCurrentTime(), base::TimeTicks::Now());
}

bool MediaPlayerBridge::RegisterMediaPlayerBridge(JNIEnv* env) {
Expand Down
6 changes: 4 additions & 2 deletions media/base/android/media_player_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ class MEDIA_EXPORT MediaPlayerManager {
virtual MediaUrlInterceptor* GetMediaUrlInterceptor() = 0;

// Called when time update messages need to be sent. Args: player ID,
// current time.
virtual void OnTimeUpdate(int player_id, base::TimeDelta current_time) = 0;
// current timestamp, current time ticks.
virtual void OnTimeUpdate(int player_id,
base::TimeDelta current_timestamp,
base::TimeTicks current_time_ticks) = 0;

// Called when media metadata changed. Args: player ID, duration of the
// media, width, height, whether the metadata is successfully extracted.
Expand Down
4 changes: 3 additions & 1 deletion media/base/android/media_source_player.cc
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,9 @@ void MediaSourcePlayer::UpdateTimestamps(
base::TimeDelta max_presentation_timestamp) {
interpolator_.SetBounds(current_presentation_timestamp,
max_presentation_timestamp);
manager()->OnTimeUpdate(player_id(), GetCurrentTime());
manager()->OnTimeUpdate(player_id(),
GetCurrentTime(),
base::TimeTicks::Now());
}

void MediaSourcePlayer::ProcessPendingEvents() {
Expand Down
3 changes: 2 additions & 1 deletion media/base/android/media_source_player_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class MockMediaPlayerManager : public MediaPlayerManager {
return NULL;
}
virtual void OnTimeUpdate(int player_id,
base::TimeDelta current_time) OVERRIDE {
base::TimeDelta current_time,
base::TimeTicks current_time_ticks) OVERRIDE {
timestamp_updated_ = true;
}
virtual void OnMediaMetadataChanged(
Expand Down
1 change: 1 addition & 0 deletions media/media.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -1690,6 +1690,7 @@
'base/android/browser_cdm_factory_android.cc',
'base/android/media_codec_bridge.cc',
'base/android/media_codec_bridge.h',
'base/android/media_common_android.h',
'base/android/media_decoder_job.cc',
'base/android/media_decoder_job.h',
'base/android/media_drm_bridge.cc',
Expand Down

0 comments on commit 4360c7c

Please sign in to comment.