Import Cobalt 11.153049
diff --git a/src/base/message_pump_io_starboard.cc b/src/base/message_pump_io_starboard.cc
index 2ef146d..45e8215 100644
--- a/src/base/message_pump_io_starboard.cc
+++ b/src/base/message_pump_io_starboard.cc
@@ -28,7 +28,8 @@
namespace base {
MessagePumpIOStarboard::SocketWatcher::SocketWatcher()
- : socket_(kSbSocketInvalid),
+ : interests_(kSbSocketWaiterInterestNone),
+ socket_(kSbSocketInvalid),
pump_(NULL),
watcher_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}
@@ -48,6 +49,7 @@
}
pump_ = NULL;
watcher_ = NULL;
+ interests_ = kSbSocketWaiterInterestNone;
return result;
}
@@ -147,6 +149,7 @@
controller->Init(socket, persistent);
controller->set_watcher(delegate);
controller->set_pump(this);
+ controller->set_interests(interests);
return true;
}
diff --git a/src/base/message_pump_io_starboard.h b/src/base/message_pump_io_starboard.h
index c840181..028115f 100644
--- a/src/base/message_pump_io_starboard.h
+++ b/src/base/message_pump_io_starboard.h
@@ -83,6 +83,7 @@
SbSocket Release();
int interests() const { return interests_; }
+ void set_interests(int interests) { interests_ = interests; }
void set_pump(MessagePumpIOStarboard* pump) { pump_ = pump; }
MessagePumpIOStarboard* pump() const { return pump_; }
diff --git a/src/cobalt/audio/audio_buffer_source_node.cc b/src/cobalt/audio/audio_buffer_source_node.cc
index 55aff8c..03b7199 100644
--- a/src/cobalt/audio/audio_buffer_source_node.cc
+++ b/src/cobalt/audio/audio_buffer_source_node.cc
@@ -111,35 +111,38 @@
size_t channels = static_cast<size_t>(buffer_->number_of_channels());
if (sample_type == kSampleTypeFloat32) {
- std::vector<float*> audio_buffer(channels, NULL);
+ std::vector<scoped_refptr<dom::Float32Array>> audio_buffer_storages(
+ channels);
+ std::vector<float*> audio_buffers(channels, NULL);
for (size_t i = 0; i < channels; ++i) {
scoped_refptr<dom::Float32Array> buffer_data =
buffer_->GetChannelData(static_cast<uint32>(i), NULL);
- scoped_refptr<dom::Float32Array> sub_array = buffer_data->Subarray(
+ audio_buffer_storages[i] = buffer_data->Subarray(
NULL, read_index_, read_index_ + number_of_frames);
- audio_buffer[i] = sub_array->data();
+ audio_buffers[i] = audio_buffer_storages[i]->data();
}
read_index_ += number_of_frames;
- scoped_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(static_cast<size_t>(number_of_frames), audio_buffer));
+ scoped_ptr<ShellAudioBus> audio_bus(new ShellAudioBus(
+ static_cast<size_t>(number_of_frames), audio_buffers));
return audio_bus.Pass();
} else if (sample_type == kSampleTypeInt16) {
- std::vector<int16*> audio_buffer(channels, NULL);
+ std::vector<scoped_refptr<dom::Int16Array>> audio_buffer_storages(channels);
+ std::vector<int16*> audio_buffers(channels, NULL);
for (size_t i = 0; i < channels; ++i) {
scoped_refptr<dom::Int16Array> buffer_data =
buffer_->GetChannelDataInt16(static_cast<uint32>(i), NULL);
- scoped_refptr<dom::Int16Array> sub_array = buffer_data->Subarray(
+ audio_buffer_storages[i] = buffer_data->Subarray(
NULL, read_index_, read_index_ + number_of_frames);
- audio_buffer[i] = sub_array->data();
+ audio_buffers[i] = audio_buffer_storages[i]->data();
}
read_index_ += number_of_frames;
- scoped_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(static_cast<size_t>(number_of_frames), audio_buffer));
+ scoped_ptr<ShellAudioBus> audio_bus(new ShellAudioBus(
+ static_cast<size_t>(number_of_frames), audio_buffers));
return audio_bus.Pass();
}
diff --git a/src/cobalt/audio/audio_device.cc b/src/cobalt/audio/audio_device.cc
index 5d740ab..535c784 100644
--- a/src/cobalt/audio/audio_device.cc
+++ b/src/cobalt/audio/audio_device.cc
@@ -170,14 +170,14 @@
*frames_in_buffer = static_cast<int>(frames_rendered_ - frames_consumed_);
if ((kFramesPerChannel - *frames_in_buffer) >= kRenderBufferSizeFrames) {
- bool silence = false;
-
// If there was silence last time we were called, then the buffer has
// already been zeroed out and we don't need to do it again.
if (!was_silence_last_update_) {
input_audio_bus_.ZeroAllFrames();
}
+ bool silence = true;
+
// Fill our temporary buffer with planar PCM float samples.
render_callback_->FillAudioBus(&input_audio_bus_, &silence);
@@ -345,7 +345,7 @@
if ((kFramesPerChannel - *total_frames) >= kRenderBufferSizeFrames) {
// Fill our temporary buffer with PCM float samples.
- bool silence = false;
+ bool silence = true;
render_callback_->FillAudioBus(&audio_bus_, &silence);
if (!silence) {
diff --git a/src/cobalt/audio/audio_device.h b/src/cobalt/audio/audio_device.h
index fec6cea..dd5f898 100644
--- a/src/cobalt/audio/audio_device.h
+++ b/src/cobalt/audio/audio_device.h
@@ -38,6 +38,10 @@
typedef ::media::ShellAudioBus ShellAudioBus;
#endif // defined(COBALT_MEDIA_SOURCE_2016)
+ // |silence| will be set to true before calling if |audio_buffer| contains
+ // only silence samples, it will be set to |false| otherwise. On return
+ // FillAudioBus() will set |silence| to |false| if it has modified
+ // |audio_buffer|.
virtual void FillAudioBus(ShellAudioBus* audio_buffer, bool* silence) = 0;
protected:
diff --git a/src/cobalt/audio/audio_node_input.cc b/src/cobalt/audio/audio_node_input.cc
index 2e76dcf..529986d 100644
--- a/src/cobalt/audio/audio_node_input.cc
+++ b/src/cobalt/audio/audio_node_input.cc
@@ -231,8 +231,6 @@
// This is called by Audio thread.
owner_node_->audio_lock()->AssertLocked();
- *silence = true;
-
// TODO: Consider computing computedNumberOfChannels and do up-mix or
// down-mix base on computedNumberOfChannels. The current implementation
// is based on the fact that the channelCountMode is max.
@@ -251,8 +249,12 @@
output_audio_bus->sample_type());
if (audio_bus) {
- MixAudioBuffer(owner_node_->channel_interpretation(), audio_bus.get(),
- output_audio_bus);
+ if (*silence && audio_bus->channels() == output_audio_bus->channels()) {
+ output_audio_bus->Assign(*audio_bus);
+ } else {
+ MixAudioBuffer(owner_node_->channel_interpretation(), audio_bus.get(),
+ output_audio_bus);
+ }
*silence = false;
}
}
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index ab3ce08..feed93d 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -139,7 +139,7 @@
// is actually occupied by JS objects, and the part that is not yet.
base::CVal<base::cval::SizeInBytes, base::CValPublic> js_reserved_memory;
- base::CVal<int64> app_start_time;
+ base::CVal<int64, base::CValPublic> app_start_time;
base::CVal<base::TimeDelta, base::CValPublic> app_lifetime;
};
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index db86c6d..7d0debb 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -444,10 +444,10 @@
// The time when a URL navigation starts. This is recorded after the previous
// WebModule is destroyed.
- base::CVal<int64> navigate_time_;
+ base::CVal<int64, base::CValPublic> navigate_time_;
// The time when the WebModule's Window.onload event is fired.
- base::CVal<int64> on_load_event_time_;
+ base::CVal<int64, base::CValPublic> on_load_event_time_;
#if defined(ENABLE_DEBUG_CONSOLE)
// Possibly null, but if not, will contain a reference to an instance of
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 87cfbf3..9d6ff51 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -263,6 +263,9 @@
// Initializes the ResourceProvider and dependent resources.
void SetResourceProvider(render_tree::ResourceProvider* resource_provider);
+ void OnStartDispatchEvent(const scoped_refptr<dom::Event>& event);
+ void OnStopDispatchEvent(const scoped_refptr<dom::Event>& event);
+
// Thread checker ensures all calls to the WebModule are made from the same
// thread that it is created in.
base::ThreadChecker thread_checker_;
@@ -556,6 +559,9 @@
base::Unretained(this)),
data.window_close_callback, data.window_minimize_callback,
data.options.camera_3d, media_session_client_->GetMediaSession(),
+ base::Bind(&WebModule::Impl::OnStartDispatchEvent,
+ base::Unretained(this)),
+ base::Bind(&WebModule::Impl::OnStopDispatchEvent, base::Unretained(this)),
data.options.csp_insecure_allowed_token, data.dom_max_element_depth,
data.options.video_playback_rate_multiplier,
#if defined(ENABLE_TEST_RUNNER)
@@ -679,17 +685,11 @@
DCHECK(is_running_);
DCHECK(window_);
- web_module_stat_tracker_->OnStartInjectEvent(event);
-
if (element) {
element->DispatchEvent(event);
} else {
window_->InjectEvent(event);
}
-
- web_module_stat_tracker_->OnEndInjectEvent(
- window_->HasPendingAnimationFrameCallbacks(),
- layout_manager_->IsRenderTreePending());
}
void WebModule::Impl::InjectKeyboardEvent(scoped_refptr<dom::Element> element,
@@ -905,6 +905,18 @@
}
}
+void WebModule::Impl::OnStartDispatchEvent(
+ const scoped_refptr<dom::Event>& event) {
+ web_module_stat_tracker_->OnStartDispatchEvent(event);
+}
+
+void WebModule::Impl::OnStopDispatchEvent(
+ const scoped_refptr<dom::Event>& event) {
+ web_module_stat_tracker_->OnStopDispatchEvent(
+ event, window_->HasPendingAnimationFrameCallbacks(),
+ layout_manager_->IsRenderTreePending());
+}
+
void WebModule::Impl::Start(render_tree::ResourceProvider* resource_provider) {
TRACE_EVENT0("cobalt::browser", "WebModule::Impl::Start()");
SetResourceProvider(resource_provider);
diff --git a/src/cobalt/browser/web_module_stat_tracker.cc b/src/cobalt/browser/web_module_stat_tracker.cc
index 187c076..59a4c2a 100644
--- a/src/cobalt/browser/web_module_stat_tracker.cc
+++ b/src/cobalt/browser/web_module_stat_tracker.cc
@@ -34,6 +34,7 @@
layout_stat_tracker_(new layout::LayoutStatTracker(name)),
should_track_event_stats_(should_track_event_stats),
current_event_type_(kEventTypeInvalid),
+ current_event_dispatched_event_(NULL),
name_(name),
event_is_processing_(StringPrintf("Event.%s.IsProcessing", name.c_str()),
false, "Nonzero when an event is being processed.") {
@@ -56,7 +57,7 @@
WebModuleStatTracker::~WebModuleStatTracker() { EndCurrentEvent(false); }
-void WebModuleStatTracker::OnStartInjectEvent(
+void WebModuleStatTracker::OnStartDispatchEvent(
const scoped_refptr<dom::Event>& event) {
if (!should_track_event_stats_) {
return;
@@ -85,28 +86,30 @@
if (current_event_type_ != kEventTypeInvalid) {
event_is_processing_ = true;
event_start_time_ = base::TimeTicks::Now();
+ current_event_dispatched_event_ = event;
dom_stat_tracker_->OnStartEvent();
layout_stat_tracker_->OnStartEvent();
stop_watch_durations_[kStopWatchTypeEvent] = base::TimeDelta();
- stop_watch_durations_[kStopWatchTypeInjectEvent] = base::TimeDelta();
+ stop_watch_durations_[kStopWatchTypeDispatchEvent] = base::TimeDelta();
stop_watches_[kStopWatchTypeEvent].Start();
- stop_watches_[kStopWatchTypeInjectEvent].Start();
+ stop_watches_[kStopWatchTypeDispatchEvent].Start();
}
}
-void WebModuleStatTracker::OnEndInjectEvent(
+void WebModuleStatTracker::OnStopDispatchEvent(
+ const scoped_refptr<dom::Event>& event,
bool are_animation_frame_callbacks_pending,
bool is_new_render_tree_pending) {
- // If the injection isn't currently being timed, then this event injection
- // isn't being tracked. Simply return.
- if (!stop_watches_[kStopWatchTypeInjectEvent].IsCounting()) {
+ // Verify that this dispatched event is the one currently being tracked.
+ if (event != current_event_dispatched_event_) {
return;
}
- stop_watches_[kStopWatchTypeInjectEvent].Stop();
+ current_event_dispatched_event_ = NULL;
+ stop_watches_[kStopWatchTypeDispatchEvent].Stop();
if (!are_animation_frame_callbacks_pending && !is_new_render_tree_pending) {
EndCurrentEvent(false);
@@ -123,7 +126,9 @@
void WebModuleStatTracker::OnRenderTreeProduced() { EndCurrentEvent(true); }
WebModuleStatTracker::EventStats::EventStats(const std::string& name)
- : produced_render_tree_(
+ : start_time(StringPrintf("Event.Time.%s.Start", name.c_str()), 0,
+ "The time that the event started."),
+ produced_render_tree(
StringPrintf("Event.%s.ProducedRenderTree", name.c_str()), false,
"Nonzero when the event produced a render tree."),
count_dom_html_elements_created(
@@ -179,12 +184,12 @@
duration_total(StringPrintf("Event.Duration.%s", name.c_str()),
base::TimeDelta(),
"Total duration of the event (in microseconds). This is "
- "the time elapsed from the event injection until the "
+ "the time elapsed from the event dispatch until the "
"render tree is produced."),
- duration_dom_inject_event(
- StringPrintf("Event.Duration.%s.DOM.InjectEvent", name.c_str()),
+ duration_dom_dispatch_event(
+ StringPrintf("Event.Duration.%s.DOM.DispatchEvent", name.c_str()),
base::TimeDelta(),
- "Injection duration, which includes JS, for event (in "
+ "Dispatch duration, which includes JS, for event (in "
"microseconds). This does not include subsequent DOM and Layout "
"processing."),
duration_dom_run_animation_frame_callbacks(
@@ -246,7 +251,8 @@
stop_watches_[kStopWatchTypeEvent].Stop();
EventStats* event_stats = event_stats_[current_event_type_];
- event_stats->produced_render_tree_ = was_render_tree_produced;
+ event_stats->start_time = event_start_time_.ToInternalValue();
+ event_stats->produced_render_tree = was_render_tree_produced;
// Update event counts
event_stats->count_dom_html_elements_created =
@@ -278,8 +284,8 @@
// Update event durations
event_stats->duration_total = stop_watch_durations_[kStopWatchTypeEvent];
- event_stats->duration_dom_inject_event =
- stop_watch_durations_[kStopWatchTypeInjectEvent];
+ event_stats->duration_dom_dispatch_event =
+ stop_watch_durations_[kStopWatchTypeDispatchEvent];
event_stats->duration_dom_run_animation_frame_callbacks =
dom_stat_tracker_->GetStopWatchTypeDuration(
dom::DomStatTracker::kStopWatchTypeRunAnimationFrameCallbacks);
@@ -349,7 +355,7 @@
<< "\"DurTotalUs\":"
<< stop_watch_durations_[kStopWatchTypeEvent].InMicroseconds() << ", "
<< "\"DurDomInjectEventUs\":"
- << stop_watch_durations_[kStopWatchTypeInjectEvent].InMicroseconds()
+ << stop_watch_durations_[kStopWatchTypeDispatchEvent].InMicroseconds()
<< ", "
<< "\"DurDomRunAnimationFrameCallbacksUs\":"
<< dom_stat_tracker_
diff --git a/src/cobalt/browser/web_module_stat_tracker.h b/src/cobalt/browser/web_module_stat_tracker.h
index 79045e3..594f1c6 100644
--- a/src/cobalt/browser/web_module_stat_tracker.h
+++ b/src/cobalt/browser/web_module_stat_tracker.h
@@ -34,7 +34,7 @@
class WebModuleStatTracker : public base::StopWatchOwner {
public:
WebModuleStatTracker(const std::string& name,
- bool should_track_injected_events);
+ bool should_track_dispatched_events);
~WebModuleStatTracker();
dom::DomStatTracker* dom_stat_tracker() const {
@@ -45,15 +45,16 @@
return layout_stat_tracker_.get();
}
- // |OnStartInjectEvent| starts event stat tracking if
- // |should_track_injected_events_| is true. Otherwise, it does nothing.
- void OnStartInjectEvent(const scoped_refptr<dom::Event>& event);
+ // |OnStartDispatchEvent| starts event stat tracking if
+ // |should_track_dispatched_events_| is true. Otherwise, it does nothing.
+ void OnStartDispatchEvent(const scoped_refptr<dom::Event>& event);
- // |OnEndInjectEvent| notifies the event stat tracking that the event has
- // finished being injected. If no animation frame callbacks and also no render
- // tree is pending, it also ends tracking of the event.
- void OnEndInjectEvent(bool are_animation_frame_callbacks_pending,
- bool is_new_render_tree_pending);
+ // |OnStopDispatchEvent| notifies the event stat tracking that |event| has
+ // finished being dispatched. If this is the event currently being tracked
+ // and nothing is pending, then it also ends tracking of the event.
+ void OnStopDispatchEvent(const scoped_refptr<dom::Event>& event,
+ bool are_animation_frame_callbacks_pending,
+ bool is_new_render_tree_pending);
// |OnRanAnimationFrameCallbacks| ends stat tracking for the current event
// if no render tree is pending.
@@ -74,14 +75,15 @@
enum StopWatchType {
kStopWatchTypeEvent,
- kStopWatchTypeInjectEvent,
+ kStopWatchTypeDispatchEvent,
kNumStopWatchTypes,
};
struct EventStats {
explicit EventStats(const std::string& name);
- base::CVal<bool, base::CValPublic> produced_render_tree_;
+ base::CVal<int64, base::CValPublic> start_time;
+ base::CVal<bool, base::CValPublic> produced_render_tree;
// Count-related
base::CVal<int, base::CValPublic> count_dom_html_elements_created;
@@ -102,7 +104,7 @@
// Duration-related
base::CVal<base::TimeDelta, base::CValPublic> duration_total;
- base::CVal<base::TimeDelta, base::CValPublic> duration_dom_inject_event;
+ base::CVal<base::TimeDelta, base::CValPublic> duration_dom_dispatch_event;
base::CVal<base::TimeDelta, base::CValPublic>
duration_dom_run_animation_frame_callbacks;
base::CVal<base::TimeDelta, base::CValPublic>
@@ -140,6 +142,10 @@
// Event-related
const bool should_track_event_stats_;
EventType current_event_type_;
+ // Raw pointer to the current event. This is used to verify that the event in
+ // |OnStopDispatchEvent| is the dispatched event being tracked.
+ dom::Event* current_event_dispatched_event_;
+
// Each individual |EventType| has its own entry in the vector.
ScopedVector<EventStats> event_stats_;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index ad8eeb1..d31d97a 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-132145
\ No newline at end of file
+153049
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index ec59efe..6af95d4 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -65,38 +65,22 @@
# Contains the current font package selection. This can be used to trade
# font quality, coverage, and latency for different font package sizes.
# The font package can be one of the following options:
- # 'expanded' -- The largest package. It includes everything in the
- # 'standard' package, along with 'bold' weight CJK. It is
- # recommended that 'local_font_cache_size_in_bytes' be
- # increased to 24MB when using this package to account for
- # the extra memory required by bold CJK. This package is
- # ~48.7MB.
# 'standard' -- The default package. It includes all sans-serif, serif,
# and FCC fonts, non-CJK fallback fonts in both 'normal' and
- # 'bold' weights, and 'normal' weight CJK ('bold' weight CJK
- # is synthesized from it). This package is ~29.4MB.
- # 'limited_with_jp' -- A significantly smaller package than 'standard'.
- # This package removes all but 'normal' and 'bold' weighted
+ # 'bold' weights, and 'normal' weight CJK ('bold' weight
+ # CJK is synthesized from it). This package is ~29.4MB.
+ # 'limited' -- A significantly smaller package than 'standard'. This
+ # package removes all but 'normal' and 'bold' weighted
# sans-serif and serif, removes the FCC fonts (which must be
# provided by the system or downloaded from the web),
- # removes the 'bold' weighted non-CJK fallback fonts (the
- # 'normal' weight is still included and is used to
- # synthesize bold), and replaces standard CJK with low
- # quality CJK. However, higher quality Japanese is still
- # included. Because low quality CJK cannot synthesize bold,
- # bold glyphs are unavailable in Chinese and Korean. This
- # package is ~10.9MB.
- # 'limited' -- A smaller package than 'limited_with_jp'. The two packages
- # are identical with the exception that 'limited' does not
- # include the higher quality Japanese font; instead it
- # relies on low quality CJK for all CJK characters. Because
+ # and replaces standard CJK with low quality CJK. Because
# low quality CJK cannot synthesize bold, bold glyphs are
- # unavailable in Chinese, Japanese, and Korean. This package
+ # unavailable in Chinese, Japanese and Korean. This package
# is ~7.7MB.
# 'minimal' -- The smallest possible font package. It only includes
# Roboto's Basic Latin characters. Everything else must be
# provided by the system or downloaded from the web. This
- # package is ~16.4KB.
+ # package is ~35.4KB.
# NOTE: When bold is needed, but unavailable, it is typically synthesized,
# resulting in lower quality glyphs than those generated directly from
# a bold font. However, this does not occur with low quality CJK,
@@ -129,7 +113,6 @@
'cobalt_font_package_override_fallback_lang_non_cjk%': -1,
'cobalt_font_package_override_fallback_lang_cjk%': -1,
'cobalt_font_package_override_fallback_lang_cjk_low_quality%': -1,
- 'cobalt_font_package_override_fallback_lang_jp%': -1,
'cobalt_font_package_override_fallback_emoji%': -1,
'cobalt_font_package_override_fallback_symbols%': -1,
@@ -559,6 +542,17 @@
# re-download video data. Note that the JavaScript app may experience
# significant difficulty if this value is too low.
'cobalt_media_buffer_video_budget_4k%': 60 * 1024 * 1024,
+
+ # Specifies the duration threshold of media source garbage collection. When
+ # the accumulated duration in a source buffer exceeds this value, the media
+ # source implementation will try to eject existing buffers from the cache.
+ # This is usually triggered when the video being played has a simple content
+ # and the encoded data is small. In such case this can limit how much is
+ # allocated for the book keeping data of the media buffers and avoid OOM of
+ # system heap.
+ # This should be set to 170 for most of the platforms. But it can be
+ # further reduced on systems with extremely low memory.
+ 'cobalt_media_source_garbage_collection_duration_threshold_in_seconds%': 170,
},
'target_defaults': {
@@ -585,6 +579,7 @@
'COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET=<(cobalt_media_buffer_non_video_budget)',
'COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P=<(cobalt_media_buffer_video_budget_1080p)',
'COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K=<(cobalt_media_buffer_video_budget_4k)',
+ 'COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS=<(cobalt_media_source_garbage_collection_duration_threshold_in_seconds)',
],
'cflags': [ '<@(compiler_flags)' ],
'ldflags': [ '<@(linker_flags)' ],
diff --git a/src/cobalt/build/copy_icu_data.gypi b/src/cobalt/build/copy_icu_data.gypi
index c2bfac3..9b9ba27 100644
--- a/src/cobalt/build/copy_icu_data.gypi
+++ b/src/cobalt/build/copy_icu_data.gypi
@@ -39,15 +39,21 @@
'little_endian%': '<(little_endian)',
'use_icu_dat_file%': '<(use_icu_dat_file)',
},
+ 'little_endian%': '<(little_endian)',
},
- #'inputs_icu%': [ '<(inputs_icu)' ],
- 'inputs_icu%': [ '<(static_contents_source_dir)/icu/' ],
+ 'conditions': [
+ ['little_endian==1', {
+ 'inputs_icu%': [ '<(static_contents_source_dir)/icu/icudt56l' ],
+ }, {
+ 'inputs_icu%': [ '<(static_contents_source_dir)/icu/icudt56b' ],
+ }],
+ ],
},
'copies': [
{
- 'destination': '<(static_contents_output_data_dir)/',
+ 'destination': '<(static_contents_output_data_dir)/icu/',
'files': [ '<(inputs_icu)' ],
},
],
diff --git a/src/cobalt/content/fonts/README.md b/src/cobalt/content/fonts/README.md
index 1181646..0c2edfc 100644
--- a/src/cobalt/content/fonts/README.md
+++ b/src/cobalt/content/fonts/README.md
@@ -41,23 +41,6 @@
}
### Package Profiles
-* 'expanded' -- The largest package. It includes everything in the 'standard'
- package, along with 'bold' weight CJK. It is recommended that
- 'local_font_cache_size_in_bytes' be increased to 24MB when
- using this package to account for the extra memory required by
- bold CJK. This package is ~48.7MB.
-
- Package category values:
- 'package_named_sans_serif': 4,
- 'package_named_serif': 3,
- 'package_named_fcc_fonts': 2,
- 'package_fallback_lang_non_cjk': 2,
- 'package_fallback_lang_cjk': 2,
- 'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
- 'package_fallback_emoji': 1,
- 'package_fallback_symbols': 1,
-
* 'standard' -- The default package. It includes all sans-serif, serif, and FCC
fonts, non-CJK fallback fonts in both 'normal' and 'bold'
weights, and 'normal' weight CJK ('bold' weight CJK is
@@ -70,20 +53,16 @@
'package_fallback_lang_non_cjk': 2,
'package_fallback_lang_cjk': 1,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 1,
'package_fallback_symbols': 1,
-* 'limited_with_jp' -- A significantly smaller package than 'standard'. This
- package removes all but 'normal' and 'bold' weighted sans-serif
- and serif, removes the FCC fonts (which must be provided by the
- system or downloaded from the web), removes the 'bold' weighted
- non-CJK fallback fonts (the 'normal' weight is still included
- and is used to synthesize bold), and replaces standard CJK with
- low quality CJK. However, higher quality Japanese is still
- included. Because low quality CJK cannot synthesize bold, bold
- glyphs are unavailable in Chinese and Korean. This package is
- ~10.9MB.
+* 'limited' -- A significantly smaller package than 'standard'. This package
+ removes all but 'normal' and 'bold' weighted sans-serif and
+ serif, removes the FCC fonts (which must be provided by the
+ system or downloaded from the web), and replaces standard CJK
+ with low quality CJK. Because low quality CJK cannot synthesize
+ bold, bold glyphs are unavailable in Chinese, Japanese and
+ Korean. This package is ~7.7MB.
Package category values:
'package_named_sans_serif': 2,
@@ -92,31 +71,12 @@
'package_fallback_lang_non_cjk': 1,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 1,
- 'package_fallback_emoji': 1,
- 'package_fallback_symbols': 1,
-
-* 'limited' -- A smaller package than 'limited_with_jp'. The two packages are
- identical with the exception that 'limited' does not include
- the higher quality Japanese font; instead it relies on low
- quality CJK for all CJK characters. Because low quality CJK
- cannot synthesize bold, bold glyphs are unavailable in Chinese,
- Japanese, and Korean. This package is ~7.7MB.
-
- Package category values:
- 'package_named_sans_serif': 2,
- 'package_named_serif': 0,
- 'package_named_fcc_fonts': 0,
- 'package_fallback_lang_non_cjk': 1,
- 'package_fallback_lang_cjk': 0,
- 'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 1,
'package_fallback_symbols': 1,
* 'minimal' -- The smallest possible font package. It only includes Roboto's
Basic Latin characters. Everything else must be provided by the
- system or downloaded from the web. This package is ~16.4KB.
+ system or downloaded from the web. This package is ~35.4KB.
Package category values:
'package_named_sans_serif': 0,
@@ -125,7 +85,6 @@
'package_fallback_lang_non_cjk': 0,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 0,
'package_fallback_symbols': 0,
@@ -160,10 +119,6 @@
included when 'package_fallback_lang_cjk' has a value of '0'. This is the
only category of fonts that is not synthetically boldable.
- * 'package_fallback_lang_jp':
- Higher quality Japanese language-specific fallback fonts. These should
- only be included when 'package_fallback_lang_cjk' has a value of '0'.
-
* 'package_fallback_emoji':
Emoji-related fallback fonts.
@@ -219,8 +174,6 @@
'package_fallback_lang_cjk'
* 'cobalt_font_package_override_fallback_lang_cjk_low_quality' ==>
'package_fallback_lang_cjk_low_quality'
- * 'cobalt_font_package_override_fallback_lang_jp' ==>
- 'package_fallback_lang_jp'
* 'cobalt_font_package_override_fallback_emoji' ==>
'package_fallback_emoji'
* 'cobalt_font_package_override_fallback_symbols' ==>
diff --git a/src/cobalt/content/fonts/config/common/fonts.xml b/src/cobalt/content/fonts/config/common/fonts.xml
index b60cc92..fc579cc 100644
--- a/src/cobalt/content/fonts/config/common/fonts.xml
+++ b/src/cobalt/content/fonts/config/common/fonts.xml
@@ -346,9 +346,6 @@
<family lang="ko" pages="0-4,17,30,32-39,41,43,46-159,169,172-215,249-251,254-255,497-498,512-658,660-682,685,687,689,691-696,698-702,704-718,760-761">
<font weight="400" style="normal" index="1">NotoSansCJK-Regular.ttc</font>
</family>
- <family lang="ja" pages="0,32,34-35,46-159,249-250,254-255,498,512-523,525-527,530-538,540-543,545-547,550,552,554-559,561,563-568,570,572-573,575-579,582-584,586-594,596-608,610-612,614-618,620,622-625,627-628,630-631,633-638,640,642-646,649-655,658,660-664,666,669-678,681,695-696,760-761">
- <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
- </family>
<family pages="0,32-33,35-39,41,43,48,50,254,496-502,4068,4072">
<font weight="400" style="normal">NotoEmoji-Regular.ttf</font>
</family>
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCJK-Bold.ttc b/src/cobalt/content/fonts/font_files/NotoSansCJK-Bold.ttc
deleted file mode 100644
index 09707f9..0000000
--- a/src/cobalt/content/fonts/font_files/NotoSansCJK-Bold.ttc
+++ /dev/null
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansJP-Regular.otf b/src/cobalt/content/fonts/font_files/NotoSansJP-Regular.otf
deleted file mode 100644
index 40b064a..0000000
--- a/src/cobalt/content/fonts/font_files/NotoSansJP-Regular.otf
+++ /dev/null
Binary files differ
diff --git a/src/cobalt/cssom/css_declared_style_data.h b/src/cobalt/cssom/css_declared_style_data.h
index 0ac19c7..3263fa2 100644
--- a/src/cobalt/cssom/css_declared_style_data.h
+++ b/src/cobalt/cssom/css_declared_style_data.h
@@ -17,10 +17,11 @@
#include <bitset>
#include <functional>
+#include <map>
#include <string>
#include "base/compiler_specific.h"
-#include "base/hash_tables.h"
+#include "base/containers/small_map.h"
#include "base/memory/ref_counted.h"
#include "cobalt/base/unused.h"
#include "cobalt/cssom/css_declaration_data.h"
@@ -36,7 +37,10 @@
public:
CSSDeclaredStyleData();
- typedef base::hash_map<PropertyKey, scoped_refptr<PropertyValue> >
+ // NOTE: The array size of base::SmallMap is based on extensive testing. Do
+ // not change it unless additional profiling data justifies it.
+ typedef base::SmallMap<std::map<PropertyKey, scoped_refptr<PropertyValue> >,
+ 8, std::equal_to<PropertyKey> >
PropertyValues;
// The length attribute must return the number of CSS declarations in the
diff --git a/src/cobalt/dom/custom_event_test.cc b/src/cobalt/dom/custom_event_test.cc
index 6a834a1..316de78 100644
--- a/src/cobalt/dom/custom_event_test.cc
+++ b/src/cobalt/dom/custom_event_test.cc
@@ -72,7 +72,9 @@
base::Closure() /* csp_policy_changed */,
base::Closure() /* ran_animation_frame_callbacks */,
dom::Window::CloseCallback() /* window_close */,
- base::Closure() /* window_minimize */, NULL, NULL)) {
+ base::Closure() /* window_minimize */, NULL, NULL,
+ dom::Window::OnStartDispatchEventCallback(),
+ dom::Window::OnStopDispatchEventCallback())) {
engine_ = script::JavaScriptEngine::CreateEngine(
script::JavaScriptEngine::Options());
global_environment_ = engine_->CreateGlobalEnvironment();
diff --git a/src/cobalt/dom/dom_stat_tracker.h b/src/cobalt/dom/dom_stat_tracker.h
index 35cedb7..e967385 100644
--- a/src/cobalt/dom/dom_stat_tracker.h
+++ b/src/cobalt/dom/dom_stat_tracker.h
@@ -104,11 +104,11 @@
// Tracking of videos produced by an event.
base::StopWatch event_video_start_delay_stop_watch_;
- base::CVal<base::TimeDelta> event_video_start_delay_;
+ base::CVal<base::TimeDelta, base::CValPublic> event_video_start_delay_;
// Count of HtmlScriptElement::Execute() calls and time of last call.
- base::CVal<int> script_element_execute_count_;
- base::CVal<int64> script_element_execute_time_;
+ base::CVal<int, base::CValPublic> script_element_execute_count_;
+ base::CVal<int64, base::CValPublic> script_element_execute_time_;
// Periodic counts. The counts are cleared after the CVals are updated in
// |FlushPeriodicTracking|.
diff --git a/src/cobalt/dom/element.cc b/src/cobalt/dom/element.cc
index 30330d9..6c6a07e 100644
--- a/src/cobalt/dom/element.cc
+++ b/src/cobalt/dom/element.cc
@@ -242,7 +242,7 @@
named_node_map_->SetAttributeInternal(attr_name, value);
}
- if (document) {
+ if (document && GetRootNode() == document) {
document->OnDOMMutation();
}
OnSetAttribute(name, value);
@@ -307,7 +307,7 @@
named_node_map_->RemoveAttributeInternal(attr_name);
}
- if (document) {
+ if (document && GetRootNode() == document) {
document->OnDOMMutation();
}
OnRemoveAttribute(name);
diff --git a/src/cobalt/dom/error_event_test.cc b/src/cobalt/dom/error_event_test.cc
index 105ec2e..28b8e88 100644
--- a/src/cobalt/dom/error_event_test.cc
+++ b/src/cobalt/dom/error_event_test.cc
@@ -72,7 +72,9 @@
base::Closure() /* csp_policy_changed */,
base::Closure() /* ran_animation_frame_callbacks */,
dom::Window::CloseCallback() /* window_close */,
- base::Closure() /* window_minimize */, NULL, NULL)) {
+ base::Closure() /* window_minimize */, NULL, NULL,
+ dom::Window::OnStartDispatchEventCallback(),
+ dom::Window::OnStopDispatchEventCallback())) {
engine_ = script::JavaScriptEngine::CreateEngine(
script::JavaScriptEngine::Options());
global_environment_ = engine_->CreateGlobalEnvironment();
diff --git a/src/cobalt/dom/html_link_element.cc b/src/cobalt/dom/html_link_element.cc
index ab3dfb6..5381bc9 100644
--- a/src/cobalt/dom/html_link_element.cc
+++ b/src/cobalt/dom/html_link_element.cc
@@ -144,15 +144,16 @@
base::Bind(&HTMLLinkElement::OnLoadingError, base::Unretained(this))));
}
-void HTMLLinkElement::OnLoadingDone(const std::string& content) {
- TRACK_MEMORY_SCOPE("DOM");
+void HTMLLinkElement::OnLoadingDone(scoped_ptr<std::string> content) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(content);
+ TRACK_MEMORY_SCOPE("DOM");
TRACE_EVENT0("cobalt::dom", "HTMLLinkElement::OnLoadingDone()");
Document* document = node_document();
if (rel() == "stylesheet") {
- OnStylesheetLoaded(document, content);
+ OnStylesheetLoaded(document, *content);
} else if (rel() == "splashscreen") {
- OnSplashscreenLoaded(document, content);
+ OnSplashscreenLoaded(document, *content);
} else {
NOTIMPLEMENTED();
return;
diff --git a/src/cobalt/dom/html_link_element.h b/src/cobalt/dom/html_link_element.h
index 1390480..1f20ffe 100644
--- a/src/cobalt/dom/html_link_element.h
+++ b/src/cobalt/dom/html_link_element.h
@@ -70,7 +70,7 @@
// From the spec: HTMLLinkElement.
void Obtain();
- void OnLoadingDone(const std::string& content);
+ void OnLoadingDone(scoped_ptr<std::string> content);
void OnLoadingError(const std::string& error);
void OnSplashscreenLoaded(Document* document, const std::string& content);
void OnStylesheetLoaded(Document* document, const std::string& content);
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index 380491c..2eece7e 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -125,7 +125,6 @@
paused_(true),
seeking_(false),
controls_(false),
- last_time_update_event_wall_time_(0),
last_time_update_event_movie_time_(std::numeric_limits<float>::max()),
processing_media_player_callback_(0),
media_source_url_(std::string(kMediaSourceUrlProtocol) + ':' +
@@ -1106,20 +1105,14 @@
}
void HTMLMediaElement::ScheduleTimeupdateEvent(bool periodic_event) {
- double now = base::Time::Now().ToDoubleT();
- double time_delta = now - last_time_update_event_wall_time_;
-
- // throttle the periodic events
- if (periodic_event && time_delta < kMaxTimeupdateEventFrequency) {
- return;
- }
-
// Some media engines make multiple "time changed" callbacks at the same time,
// but we only want one event at a given time so filter here
float movie_time = current_time(NULL);
if (movie_time != last_time_update_event_movie_time_) {
+ if (!periodic_event && playback_progress_timer_.IsRunning()) {
+ playback_progress_timer_.Reset();
+ }
ScheduleOwnEvent(base::Tokens::timeupdate());
- last_time_update_event_wall_time_ = now;
last_time_update_event_movie_time_ = movie_time;
}
}
@@ -1593,10 +1586,15 @@
ScheduleOwnEvent(base::Tokens::durationchange());
- float now = current_time(NULL);
- float dur = duration();
- if (now > dur) {
- Seek(dur);
+ double now = current_time(NULL);
+ // Reset and update |duration_|.
+ duration_ = std::numeric_limits<double>::quiet_NaN();
+ if (player_ && ready_state_ >= WebMediaPlayer::kReadyStateHaveMetadata) {
+ duration_ = player_->GetDuration();
+ }
+
+ if (now > duration_) {
+ Seek(static_cast<float>(duration_));
}
EndProcessingMediaPlayerCallback();
diff --git a/src/cobalt/dom/html_media_element.h b/src/cobalt/dom/html_media_element.h
index dc0fdaa..0c6f554 100644
--- a/src/cobalt/dom/html_media_element.h
+++ b/src/cobalt/dom/html_media_element.h
@@ -298,8 +298,6 @@
bool seeking_;
bool controls_;
- // The last time a timeupdate event was sent (wall clock).
- double last_time_update_event_wall_time_;
// The last time a timeupdate event was sent in movie time.
double last_time_update_event_movie_time_;
diff --git a/src/cobalt/dom/html_script_element.cc b/src/cobalt/dom/html_script_element.cc
index 652c504..ee3def5 100644
--- a/src/cobalt/dom/html_script_element.cc
+++ b/src/cobalt/dom/html_script_element.cc
@@ -15,6 +15,7 @@
#include "cobalt/dom/html_script_element.h"
#include <deque>
+#include <utility>
#include "base/bind.h"
#include "base/compiler_specific.h"
@@ -265,6 +266,8 @@
PreventGarbageCollection();
ExecuteExternal();
AllowGarbageCollection();
+ // Release the content string now that we're finished with it.
+ content_.reset();
} else {
// Executing the script block must just consist of firing a simple event
// named error at the element.
@@ -347,9 +350,9 @@
}
}
-void HTMLScriptElement::OnSyncLoadingDone(const std::string& content) {
+void HTMLScriptElement::OnSyncLoadingDone(scoped_ptr<std::string> content) {
TRACE_EVENT0("cobalt::dom", "HTMLScriptElement::OnSyncLoadingDone()");
- content_ = content;
+ content_ = content.Pass();
is_sync_load_successful_ = true;
}
@@ -360,16 +363,18 @@
// Algorithm for OnLoadingDone:
// https://www.w3.org/TR/html5/scripting-1.html#prepare-a-script
-void HTMLScriptElement::OnLoadingDone(const std::string& content) {
+void HTMLScriptElement::OnLoadingDone(scoped_ptr<std::string> content) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(load_option_ == 4 || load_option_ == 5);
+ DCHECK(content);
TRACE_EVENT0("cobalt::dom", "HTMLScriptElement::OnLoadingDone()");
if (!document_) {
AllowGarbageCollection();
return;
}
- content_ = content;
+ content_ = content.Pass();
+
switch (load_option_) {
case 4: {
// If the element has a src attribute, does not have an async attribute,
@@ -446,6 +451,13 @@
document_->DecreaseLoadingCounterAndMaybeDispatchLoadEvent();
} break;
}
+
+ // Release the content string now that we're finished with it.
+ content_.reset();
+
+ // Post a task to release the loader.
+ MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&HTMLScriptElement::ReleaseLoader, this));
}
// Algorithm for OnLoadingError:
@@ -490,6 +502,19 @@
// document until the task that is queued by the networking task source
// once the resource has been fetched (defined above) has been run.
document_->DecreaseLoadingCounterAndMaybeDispatchLoadEvent();
+
+ // Post a task to release the loader.
+ MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&HTMLScriptElement::ReleaseLoader, this));
+}
+
+void HTMLScriptElement::ExecuteExternal() {
+ DCHECK(content_);
+ Execute(*content_, base::SourceLocation(url_.spec(), 1, 1), true);
+}
+
+void HTMLScriptElement::ExecuteInternal() {
+ Execute(text_content().value(), inline_script_location_, false);
}
// Algorithm for Execute:
@@ -586,5 +611,11 @@
}
}
+void HTMLScriptElement::ReleaseLoader() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(loader_);
+ loader_.reset();
+}
+
} // namespace dom
} // namespace cobalt
diff --git a/src/cobalt/dom/html_script_element.h b/src/cobalt/dom/html_script_element.h
index 8307158..d121d34 100644
--- a/src/cobalt/dom/html_script_element.h
+++ b/src/cobalt/dom/html_script_element.h
@@ -89,18 +89,14 @@
//
void Prepare();
- void OnSyncLoadingDone(const std::string& content);
+ void OnSyncLoadingDone(scoped_ptr<std::string> content);
void OnSyncLoadingError(const std::string& error);
- void OnLoadingDone(const std::string& content);
+ void OnLoadingDone(scoped_ptr<std::string> content);
void OnLoadingError(const std::string& error);
- void ExecuteExternal() {
- Execute(content_, base::SourceLocation(url_.spec(), 1, 1), true);
- }
- void ExecuteInternal() {
- Execute(text_content().value(), inline_script_location_, false);
- }
+ void ExecuteExternal();
+ void ExecuteInternal();
void Execute(const std::string& content,
const base::SourceLocation& script_location, bool is_external);
@@ -108,6 +104,7 @@
const tracked_objects::Location& location, const base::Token& token);
void PreventGarbageCollection();
void AllowGarbageCollection();
+ void ReleaseLoader();
// Whether the script has been started.
bool is_already_started_;
@@ -131,8 +128,8 @@
bool is_sync_load_successful_;
// Resolved URL of the script.
GURL url_;
- // Content of the script.
- std::string content_;
+ // Content of the script. Released after Execute is called.
+ scoped_ptr<std::string> content_;
// Active requests disabling garbage collection.
int prevent_garbage_collection_count_;
diff --git a/src/cobalt/dom/html_video_element.cc b/src/cobalt/dom/html_video_element.cc
index 8b63f37..a5b806e 100644
--- a/src/cobalt/dom/html_video_element.cc
+++ b/src/cobalt/dom/html_video_element.cc
@@ -16,6 +16,9 @@
#include "base/logging.h"
#include "base/string_number_conversions.h"
+#include "cobalt/dom/dom_settings.h"
+#include "cobalt/dom/performance.h"
+#include "cobalt/dom/window.h"
#include "cobalt/math/size_f.h"
namespace cobalt {
@@ -76,15 +79,18 @@
return static_cast<uint32>(player()->GetNaturalSize().height());
}
-scoped_refptr<VideoPlaybackQuality> HTMLVideoElement::GetVideoPlaybackQuality()
- const {
- // TODO: Provide all attributes with valid values.
+scoped_refptr<VideoPlaybackQuality> HTMLVideoElement::GetVideoPlaybackQuality(
+ script::EnvironmentSettings* environment_settings) const {
+ DOMSettings* dom_settings =
+ base::polymorphic_downcast<DOMSettings*>(environment_settings);
+ DCHECK(dom_settings);
+ DCHECK(dom_settings->window());
+ DCHECK(dom_settings->window()->performance());
+
return new VideoPlaybackQuality(
- 0., // creation_time
+ dom_settings->window()->performance()->Now(),
player() ? static_cast<uint32>(player()->GetDecodedFrameCount()) : 0,
- player() ? static_cast<uint32>(player()->GetDroppedFrameCount()) : 0,
- 0, // corrupted_video_frames
- 0.); // total_frame_delay
+ player() ? static_cast<uint32>(player()->GetDroppedFrameCount()) : 0);
}
scoped_refptr<ShellVideoFrameProvider>
diff --git a/src/cobalt/dom/html_video_element.h b/src/cobalt/dom/html_video_element.h
index 45396d1..2fe480e 100644
--- a/src/cobalt/dom/html_video_element.h
+++ b/src/cobalt/dom/html_video_element.h
@@ -21,6 +21,7 @@
#include "cobalt/dom/video_playback_quality.h"
#include "cobalt/math/rect.h"
#include "cobalt/math/size_f.h"
+#include "cobalt/script/environment_settings.h"
#if !defined(COBALT_MEDIA_SOURCE_2016)
#include "media/base/shell_video_frame_provider.h"
#endif // !defined(COBALT_MEDIA_SOURCE_2016)
@@ -50,7 +51,8 @@
void set_height(uint32 height);
uint32 video_width() const;
uint32 video_height() const;
- scoped_refptr<VideoPlaybackQuality> GetVideoPlaybackQuality() const;
+ scoped_refptr<VideoPlaybackQuality> GetVideoPlaybackQuality(
+ script::EnvironmentSettings* environment_settings) const;
// Custom, not in any spec
//
diff --git a/src/cobalt/dom/html_video_element.idl b/src/cobalt/dom/html_video_element.idl
index 53259ab..d73e064 100644
--- a/src/cobalt/dom/html_video_element.idl
+++ b/src/cobalt/dom/html_video_element.idl
@@ -21,5 +21,5 @@
readonly attribute unsigned long videoHeight;
// https://www.w3.org/TR/media-source/#widl-HTMLVideoElement-getVideoPlaybackQuality-VideoPlaybackQuality
- VideoPlaybackQuality getVideoPlaybackQuality();
+ [CallWith=EnvironmentSettings] VideoPlaybackQuality getVideoPlaybackQuality();
};
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc
index 50376b2..40705ee 100644
--- a/src/cobalt/dom/node.cc
+++ b/src/cobalt/dom/node.cc
@@ -109,6 +109,10 @@
window = node_document()->default_view();
}
+ if (window) {
+ window->OnStartDispatchEvent(event);
+ }
+
typedef std::vector<scoped_refptr<Node> > Ancestors;
Ancestors ancestors;
for (Node* current = this->parent_node(); current != NULL;
@@ -159,6 +163,10 @@
event->set_event_phase(Event::kNone);
+ if (window) {
+ window->OnStopDispatchEvent(event);
+ }
+
// The event has completed being dispatched. Stop tracking it in the global
// stats.
GlobalStats::GetInstance()->StopJavaScriptEvent();
diff --git a/src/cobalt/dom/testing/stub_window.h b/src/cobalt/dom/testing/stub_window.h
index 53f53bd..a12c934 100644
--- a/src/cobalt/dom/testing/stub_window.h
+++ b/src/cobalt/dom/testing/stub_window.h
@@ -60,7 +60,9 @@
base::Closure() /* csp_policy_changed */,
base::Closure() /* ran_animation_frame_callbacks */,
dom::Window::CloseCallback() /* window_close */,
- base::Closure() /* window_minimize */, NULL, NULL);
+ base::Closure() /* window_minimize */, NULL, NULL,
+ dom::Window::OnStartDispatchEventCallback(),
+ dom::Window::OnStopDispatchEventCallback());
global_environment_->CreateGlobalObject(window_, &environment_settings_);
}
diff --git a/src/cobalt/dom/video_playback_quality.h b/src/cobalt/dom/video_playback_quality.h
index 471b929..d3e0e9b 100644
--- a/src/cobalt/dom/video_playback_quality.h
+++ b/src/cobalt/dom/video_playback_quality.h
@@ -27,21 +27,19 @@
class VideoPlaybackQuality : public script::Wrappable {
public:
VideoPlaybackQuality(double creation_time, uint32 total_video_frames,
- uint32 dropped_video_frames,
- uint32 corrupted_video_frames, double total_frame_delay)
+ uint32 dropped_video_frames)
: creation_time_(creation_time),
total_video_frames_(total_video_frames),
- dropped_video_frames_(dropped_video_frames),
- corrupted_video_frames_(corrupted_video_frames),
- total_frame_delay_(total_frame_delay) {}
+ dropped_video_frames_(dropped_video_frames) {}
// Web API: VideoPlaybackQuality
//
double creation_time() const { return creation_time_; }
uint32 total_video_frames() const { return total_video_frames_; }
uint32 dropped_video_frames() const { return dropped_video_frames_; }
- uint32 corrupted_video_frames() const { return corrupted_video_frames_; }
- double total_frame_delay() const { return total_frame_delay_; }
+ // Always returns 0 as Cobalt simply stops the playback on encountering
+ // corrupted video frames.
+ uint32 corrupted_video_frames() const { return 0; }
DEFINE_WRAPPABLE_TYPE(VideoPlaybackQuality);
@@ -49,8 +47,6 @@
double creation_time_;
uint32 total_video_frames_;
uint32 dropped_video_frames_;
- uint32 corrupted_video_frames_;
- double total_frame_delay_;
};
} // namespace dom
diff --git a/src/cobalt/dom/video_playback_quality.idl b/src/cobalt/dom/video_playback_quality.idl
index acc06c0..146f170 100644
--- a/src/cobalt/dom/video_playback_quality.idl
+++ b/src/cobalt/dom/video_playback_quality.idl
@@ -19,7 +19,6 @@
readonly attribute unsigned long totalVideoFrames;
readonly attribute unsigned long droppedVideoFrames;
readonly attribute unsigned long corruptedVideoFrames;
- readonly attribute double totalFrameDelay;
};
typedef double DOMHighResTimeStamp;
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 66dadf7..b68d8ba 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -82,42 +82,45 @@
const int64_t kPerformanceTimerMinResolutionInMicroseconds = 20;
} // namespace
-Window::Window(int width, int height, float device_pixel_ratio,
- base::ApplicationState initial_application_state,
- cssom::CSSParser* css_parser, Parser* dom_parser,
- loader::FetcherFactory* fetcher_factory,
- render_tree::ResourceProvider** resource_provider,
- loader::image::AnimatedImageTracker* animated_image_tracker,
- loader::image::ImageCache* image_cache,
- loader::image::ReducedCacheCapacityManager*
- reduced_image_cache_capacity_manager,
- loader::font::RemoteTypefaceCache* remote_typeface_cache,
- loader::mesh::MeshCache* mesh_cache,
- LocalStorageDatabase* local_storage_database,
- media::CanPlayTypeHandler* can_play_type_handler,
- media::WebMediaPlayerFactory* web_media_player_factory,
- script::ExecutionState* execution_state,
- script::ScriptRunner* script_runner,
- script::ScriptValueFactory* script_value_factory,
- MediaSource::Registry* media_source_registry,
- DomStatTracker* dom_stat_tracker, const GURL& url,
- const std::string& user_agent, const std::string& language,
- const std::string& font_language_script,
- const base::Callback<void(const GURL&)> navigation_callback,
- const base::Callback<void(const std::string&)>& error_callback,
- network_bridge::CookieJar* cookie_jar,
- const network_bridge::PostSender& post_sender,
- const std::string& default_security_policy,
- CspEnforcementType csp_enforcement_mode,
- const base::Closure& csp_policy_changed_callback,
- const base::Closure& ran_animation_frame_callbacks_callback,
- const CloseCallback& window_close_callback,
- const base::Closure& window_minimize_callback,
- const scoped_refptr<input::Camera3D>& camera_3d,
- const scoped_refptr<MediaSession>& media_session,
- int csp_insecure_allowed_token, int dom_max_element_depth,
- float video_playback_rate_multiplier, ClockType clock_type,
- const CacheCallback& splash_screen_cache_callback)
+Window::Window(
+ int width, int height, float device_pixel_ratio,
+ base::ApplicationState initial_application_state,
+ cssom::CSSParser* css_parser, Parser* dom_parser,
+ loader::FetcherFactory* fetcher_factory,
+ render_tree::ResourceProvider** resource_provider,
+ loader::image::AnimatedImageTracker* animated_image_tracker,
+ loader::image::ImageCache* image_cache,
+ loader::image::ReducedCacheCapacityManager*
+ reduced_image_cache_capacity_manager,
+ loader::font::RemoteTypefaceCache* remote_typeface_cache,
+ loader::mesh::MeshCache* mesh_cache,
+ LocalStorageDatabase* local_storage_database,
+ media::CanPlayTypeHandler* can_play_type_handler,
+ media::WebMediaPlayerFactory* web_media_player_factory,
+ script::ExecutionState* execution_state,
+ script::ScriptRunner* script_runner,
+ script::ScriptValueFactory* script_value_factory,
+ MediaSource::Registry* media_source_registry,
+ DomStatTracker* dom_stat_tracker, const GURL& url,
+ const std::string& user_agent, const std::string& language,
+ const std::string& font_language_script,
+ const base::Callback<void(const GURL&)> navigation_callback,
+ const base::Callback<void(const std::string&)>& error_callback,
+ network_bridge::CookieJar* cookie_jar,
+ const network_bridge::PostSender& post_sender,
+ const std::string& default_security_policy,
+ CspEnforcementType csp_enforcement_mode,
+ const base::Closure& csp_policy_changed_callback,
+ const base::Closure& ran_animation_frame_callbacks_callback,
+ const CloseCallback& window_close_callback,
+ const base::Closure& window_minimize_callback,
+ const scoped_refptr<input::Camera3D>& camera_3d,
+ const scoped_refptr<MediaSession>& media_session,
+ const OnStartDispatchEventCallback& on_start_dispatch_event_callback,
+ const OnStopDispatchEventCallback& on_stop_dispatch_event_callback,
+ int csp_insecure_allowed_token, int dom_max_element_depth,
+ float video_playback_rate_multiplier, ClockType clock_type,
+ const CacheCallback& splash_screen_cache_callback)
: width_(width),
height_(height),
device_pixel_ratio_(device_pixel_ratio),
@@ -176,7 +179,9 @@
ran_animation_frame_callbacks_callback),
window_close_callback_(window_close_callback),
window_minimize_callback_(window_minimize_callback),
- splash_screen_cache_callback_(splash_screen_cache_callback) {
+ splash_screen_cache_callback_(splash_screen_cache_callback),
+ on_start_dispatch_event_callback_(on_start_dispatch_event_callback),
+ on_stop_dispatch_event_callback_(on_stop_dispatch_event_callback) {
#if !defined(ENABLE_TEST_RUNNER)
UNREFERENCED_PARAMETER(clock_type);
#endif
@@ -578,6 +583,18 @@
}
}
+void Window::OnStartDispatchEvent(const scoped_refptr<dom::Event>& event) {
+ if (!on_start_dispatch_event_callback_.is_null()) {
+ on_start_dispatch_event_callback_.Run(event);
+ }
+}
+
+void Window::OnStopDispatchEvent(const scoped_refptr<dom::Event>& event) {
+ if (!on_stop_dispatch_event_callback_.is_null()) {
+ on_stop_dispatch_event_callback_.Run(event);
+ }
+}
+
void Window::TraceMembers(script::Tracer* tracer) {
tracer->Trace(performance_);
tracer->Trace(document_);
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 335353f..3e16727 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -98,11 +98,11 @@
typedef AnimationFrameRequestCallbackList::FrameRequestCallback
FrameRequestCallback;
typedef WindowTimers::TimerCallback TimerCallback;
- typedef base::Callback<scoped_ptr<loader::Decoder>(
- HTMLElementContext*, const scoped_refptr<Document>&,
- const base::SourceLocation&, const base::Closure&,
- const base::Callback<void(const std::string&)>&)>
- HTMLDecoderCreatorCallback;
+ typedef base::Callback<void(const scoped_refptr<dom::Event>& event)>
+ OnStartDispatchEventCallback;
+ typedef base::Callback<void(const scoped_refptr<dom::Event>& event)>
+ OnStopDispatchEventCallback;
+
// Callback that will be called when window.close() is called. The
// base::TimeDelta parameter will contain the document's timeline time when
// close() was called.
@@ -148,6 +148,9 @@
const base::Closure& window_minimize_callback,
const scoped_refptr<input::Camera3D>& camera_3d,
const scoped_refptr<cobalt::media_session::MediaSession>& media_session,
+ const OnStartDispatchEventCallback&
+ start_tracking_dispatch_event_callback,
+ const OnStopDispatchEventCallback& stop_tracking_dispatch_event_callback,
int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0,
float video_playback_rate_multiplier = 1.f,
ClockType clock_type = kClockTypeSystemTime,
@@ -335,6 +338,9 @@
// Cache the passed in splash screen content for the window.location URL.
void CacheSplashScreen(const std::string& content);
+ void OnStartDispatchEvent(const scoped_refptr<dom::Event>& event);
+ void OnStopDispatchEvent(const scoped_refptr<dom::Event>& event);
+
DEFINE_WRAPPABLE_TYPE(Window);
private:
@@ -396,6 +402,9 @@
CacheCallback splash_screen_cache_callback_;
+ OnStartDispatchEventCallback on_start_dispatch_event_callback_;
+ OnStopDispatchEventCallback on_stop_dispatch_event_callback_;
+
DISALLOW_COPY_AND_ASSIGN(Window);
};
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc
index 845c319..60989f1 100644
--- a/src/cobalt/dom/window_test.cc
+++ b/src/cobalt/dom/window_test.cc
@@ -61,7 +61,9 @@
base::Closure() /* csp_policy_changed */,
base::Closure() /* ran_animation_frame_callbacks */,
dom::Window::CloseCallback() /* window_close */,
- base::Closure() /* window_minimize */, NULL, NULL)) {}
+ base::Closure() /* window_minimize */, NULL, NULL,
+ dom::Window::OnStartDispatchEventCallback(),
+ dom::Window::OnStopDispatchEventCallback())) {}
~WindowTest() OVERRIDE {}
diff --git a/src/cobalt/loader/loader_test.cc b/src/cobalt/loader/loader_test.cc
index 1e7872a..570d839 100644
--- a/src/cobalt/loader/loader_test.cc
+++ b/src/cobalt/loader/loader_test.cc
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
@@ -40,8 +41,8 @@
public:
explicit TextDecoderCallback(base::RunLoop* run_loop) : run_loop_(run_loop) {}
- void OnDone(const std::string& text) {
- text_ = text;
+ void OnDone(scoped_ptr<std::string> text) {
+ text_ = *text;
MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure());
}
diff --git a/src/cobalt/loader/resource_cache.h b/src/cobalt/loader/resource_cache.h
index ab01730..12993ee 100644
--- a/src/cobalt/loader/resource_cache.h
+++ b/src/cobalt/loader/resource_cache.h
@@ -585,12 +585,13 @@
base::CVal<base::cval::SizeInBytes, base::CValPublic> memory_size_in_bytes_;
base::CVal<base::cval::SizeInBytes, base::CValPublic>
memory_capacity_in_bytes_;
- base::CVal<base::cval::SizeInBytes> memory_resources_loaded_in_bytes_;
+ base::CVal<base::cval::SizeInBytes, base::CValPublic>
+ memory_resources_loaded_in_bytes_;
- base::CVal<int> count_resources_requested_;
- base::CVal<int> count_resources_loading_;
- base::CVal<int> count_resources_loaded_;
- base::CVal<int> count_pending_callbacks_;
+ base::CVal<int, base::CValPublic> count_resources_requested_;
+ base::CVal<int, base::CValPublic> count_resources_loading_;
+ base::CVal<int, base::CValPublic> count_resources_loaded_;
+ base::CVal<int, base::CValPublic> count_pending_callbacks_;
DISALLOW_COPY_AND_ASSIGN(ResourceCache);
};
diff --git a/src/cobalt/loader/text_decoder.h b/src/cobalt/loader/text_decoder.h
index 11b78d4..2c1761c 100644
--- a/src/cobalt/loader/text_decoder.h
+++ b/src/cobalt/loader/text_decoder.h
@@ -17,6 +17,7 @@
#include <algorithm>
#include <string>
+#include <utility>
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -32,13 +33,14 @@
// results.
class TextDecoder : public Decoder {
public:
- explicit TextDecoder(base::Callback<void(const std::string&)> done_callback)
+ explicit TextDecoder(
+ base::Callback<void(scoped_ptr<std::string>)> done_callback)
: done_callback_(done_callback), suspended_(false) {}
~TextDecoder() OVERRIDE {}
// This function is used for binding callback for creating TextDecoder.
static scoped_ptr<Decoder> Create(
- base::Callback<void(const std::string&)> done_callback) {
+ base::Callback<void(scoped_ptr<std::string>)> done_callback) {
return scoped_ptr<Decoder>(new TextDecoder(done_callback));
}
@@ -48,7 +50,10 @@
if (suspended_) {
return;
}
- text_.append(data, size);
+ if (!text_) {
+ text_.reset(new std::string);
+ }
+ text_->append(data, size);
}
void DecodeChunkPassed(scoped_ptr<std::string> data) OVERRIDE {
@@ -58,10 +63,10 @@
return;
}
- if (text_.empty()) {
- std::swap(*data, text_);
+ if (!text_) {
+ text_ = data.Pass();
} else {
- text_.append(*data);
+ text_->append(*data);
}
}
@@ -70,11 +75,14 @@
if (suspended_) {
return;
}
- done_callback_.Run(text_);
+ if (!text_) {
+ text_.reset(new std::string);
+ }
+ done_callback_.Run(text_.Pass());
}
bool Suspend() OVERRIDE {
suspended_ = true;
- text_.clear();
+ text_.reset();
return true;
}
void Resume(render_tree::ResourceProvider* /*resource_provider*/) OVERRIDE {
@@ -83,8 +91,8 @@
private:
base::ThreadChecker thread_checker_;
- std::string text_;
- base::Callback<void(const std::string&)> done_callback_;
+ base::Callback<void(scoped_ptr<std::string>)> done_callback_;
+ scoped_ptr<std::string> text_;
bool suspended_;
};
diff --git a/src/cobalt/loader/text_decoder_test.cc b/src/cobalt/loader/text_decoder_test.cc
index 7c62696..29402dd 100644
--- a/src/cobalt/loader/text_decoder_test.cc
+++ b/src/cobalt/loader/text_decoder_test.cc
@@ -15,6 +15,7 @@
#include "cobalt/loader/text_decoder.h"
#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,7 +24,7 @@
namespace {
struct TextDecoderCallback {
- void Callback(const std::string& value) { text = value; }
+ void Callback(scoped_ptr<std::string> value) { text = *value; }
std::string text;
};
diff --git a/src/cobalt/media/base/shell_audio_bus.cc b/src/cobalt/media/base/shell_audio_bus.cc
index aea8fb0..81b569d 100644
--- a/src/cobalt/media/base/shell_audio_bus.cc
+++ b/src/cobalt/media/base/shell_audio_bus.cc
@@ -53,6 +53,31 @@
}
}
+void Sum(const float* source, float* destination, size_t size) {
+ while (size > 0) {
+ *destination += *source;
+ ++source;
+ ++destination;
+ --size;
+ }
+}
+
+void Sum(const int16* source, int16* destination, size_t size) {
+ while (size > 0) {
+ int sample_in_int32 = *destination + static_cast<int>(*source);
+ if (sample_in_int32 > std::numeric_limits<int16>::max()) {
+ *destination = std::numeric_limits<int16>::max();
+ } else if (sample_in_int32 < std::numeric_limits<int16>::min()) {
+ *destination = std::numeric_limits<int16>::min();
+ } else {
+ *destination = static_cast<int16>(sample_in_int32);
+ }
+ ++source;
+ ++destination;
+ --size;
+ }
+}
+
} // namespace
ShellAudioBus::ShellAudioBus(size_t channels, size_t frames,
@@ -148,6 +173,17 @@
return channel_data_[channel];
}
+uint8* ShellAudioBus::interleaved_data() {
+ DCHECK_EQ(storage_type_, kInterleaved);
+ return channel_data_[0];
+}
+
+uint8* ShellAudioBus::planar_data(size_t channel) {
+ DCHECK_LT(channel, channels_);
+ DCHECK_EQ(storage_type_, kPlanar);
+ return channel_data_[channel];
+}
+
void ShellAudioBus::ZeroFrames(size_t start_frame, size_t end_frame) {
DCHECK_LE(start_frame, end_frame);
DCHECK_LE(end_frame, frames_);
@@ -223,84 +259,103 @@
}
}
-template <typename SourceSampleType, typename DestSampleType,
- StorageType SourceStorageType, StorageType DestStorageType>
-void ShellAudioBus::MixForTypes(const ShellAudioBus& source) {
+template <StorageType SourceStorageType, StorageType DestStorageType>
+void ShellAudioBus::MixFloatSamples(const ShellAudioBus& source) {
const size_t frames = std::min(frames_, source.frames_);
+ if (SourceStorageType == DestStorageType) {
+ if (SourceStorageType == kInterleaved) {
+ Sum(reinterpret_cast<const float*>(source.interleaved_data()),
+ reinterpret_cast<float*>(interleaved_data()), frames * channels_);
+ return;
+ }
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ Sum(reinterpret_cast<const float*>(source.planar_data(channel)),
+ reinterpret_cast<float*>(planar_data(channel)), frames);
+ }
+ return;
+ }
+
for (size_t channel = 0; channel < channels_; ++channel) {
for (size_t frame = 0; frame < frames; ++frame) {
- *reinterpret_cast<DestSampleType*>(
- GetSamplePtrForType<DestSampleType, DestStorageType>(channel,
- frame)) +=
- source.GetSampleForType<SourceSampleType, SourceStorageType>(channel,
- frame);
+ *reinterpret_cast<float*>(
+ GetSamplePtrForType<float, DestStorageType>(channel, frame)) +=
+ source.GetSampleForType<float, SourceStorageType>(channel, frame);
+ }
+ }
+}
+
+template <StorageType SourceStorageType, StorageType DestStorageType>
+void ShellAudioBus::MixInt16Samples(const ShellAudioBus& source) {
+ const size_t frames = std::min(frames_, source.frames_);
+
+ if (SourceStorageType == DestStorageType) {
+ if (SourceStorageType == kInterleaved) {
+ Sum(reinterpret_cast<const int16*>(source.interleaved_data()),
+ reinterpret_cast<int16*>(interleaved_data()), frames * channels_);
+ return;
+ }
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ Sum(reinterpret_cast<const int16*>(source.planar_data(channel)),
+ reinterpret_cast<int16*>(planar_data(channel)), frames);
+ }
+ return;
+ }
+
+ for (size_t channel = 0; channel < channels_; ++channel) {
+ for (size_t frame = 0; frame < frames; ++frame) {
+ auto& dest_sample = *reinterpret_cast<int16*>(
+ GetSamplePtrForType<int16, DestStorageType>(channel, frame));
+ int source_sample =
+ source.GetSampleForType<int16, SourceStorageType>(channel, frame);
+ if (dest_sample + source_sample > std::numeric_limits<int16>::max()) {
+ dest_sample = std::numeric_limits<int16>::max();
+ } else if (dest_sample + source_sample <
+ std::numeric_limits<int16>::min()) {
+ dest_sample = std::numeric_limits<int16>::min();
+ } else {
+ dest_sample += source_sample;
+ }
}
}
}
void ShellAudioBus::Mix(const ShellAudioBus& source) {
DCHECK_EQ(channels_, source.channels_);
+ DCHECK_EQ(sample_type_, source.sample_type_);
- if (channels_ != source.channels_) {
+ if (channels_ != source.channels_ || sample_type_ != source.sample_type_) {
ZeroAllFrames();
return;
}
// Profiling has identified this area of code as hot, so instead of calling
- // GetSamplePtr, which branches each time it is called, we branch once
- // before we loop and inline the branch of the function we want.
- if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved && storage_type_ == kInterleaved) {
- MixForTypes<int16, int16, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<int16, int16, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<int16, int16, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<int16, int16, kPlanar, kPlanar>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved &&
+ // GetSamplePtr, which branches each time it is called, we branch once before
+ // we loop and inline the branch of the function we want.
+ if (source.sample_type_ == kInt16 && source.storage_type_ == kInterleaved &&
+ storage_type_ == kInterleaved) {
+ MixInt16Samples<kInterleaved, kInterleaved>(source);
+ } else if (sample_type_ == kInt16 && source.storage_type_ == kInterleaved &&
+ storage_type_ == kPlanar) {
+ MixInt16Samples<kInterleaved, kPlanar>(source);
+ } else if (sample_type_ == kInt16 && source.storage_type_ == kPlanar &&
storage_type_ == kInterleaved) {
- MixForTypes<int16, float, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<int16, float, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<int16, float, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kInt16 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<int16, float, kPlanar, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved &&
+ MixInt16Samples<kPlanar, kInterleaved>(source);
+ } else if (sample_type_ == kInt16 && source.storage_type_ == kPlanar &&
+ storage_type_ == kPlanar) {
+ MixInt16Samples<kPlanar, kPlanar>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kInterleaved &&
storage_type_ == kInterleaved) {
- MixForTypes<float, int16, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<float, int16, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<float, int16, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kInt16 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<float, int16, kPlanar, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved &&
+ MixFloatSamples<kInterleaved, kInterleaved>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kInterleaved &&
+ storage_type_ == kPlanar) {
+ MixFloatSamples<kInterleaved, kPlanar>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kPlanar &&
storage_type_ == kInterleaved) {
- MixForTypes<float, float, kInterleaved, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kInterleaved && storage_type_ == kPlanar) {
- MixForTypes<float, float, kInterleaved, kPlanar>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kInterleaved) {
- MixForTypes<float, float, kPlanar, kInterleaved>(source);
- } else if (source.sample_type_ == kFloat32 && sample_type_ == kFloat32 &&
- source.storage_type_ == kPlanar && storage_type_ == kPlanar) {
- MixForTypes<float, float, kPlanar, kPlanar>(source);
+ MixFloatSamples<kPlanar, kInterleaved>(source);
+ } else if (sample_type_ == kFloat32 && source.storage_type_ == kPlanar &&
+ storage_type_ == kPlanar) {
+ MixFloatSamples<kPlanar, kPlanar>(source);
} else {
NOTREACHED();
}
diff --git a/src/cobalt/media/base/shell_audio_bus.h b/src/cobalt/media/base/shell_audio_bus.h
index c9ef550..833d2dc 100644
--- a/src/cobalt/media/base/shell_audio_bus.h
+++ b/src/cobalt/media/base/shell_audio_bus.h
@@ -63,6 +63,8 @@
size_t GetSampleSizeInBytes() const;
const uint8* interleaved_data() const;
const uint8* planar_data(size_t channel) const;
+ uint8* interleaved_data();
+ uint8* planar_data(size_t channel);
int16 GetInt16Sample(size_t channel, size_t frame) const {
DCHECK_EQ(sample_type_, kInt16);
@@ -130,9 +132,11 @@
GetSamplePtrForType<SampleTypeName, T>(channel, frame));
}
- template <typename SourceSampleType, typename DestSampleType,
- StorageType SourceStorageType, StorageType DestStorageType>
- void MixForTypes(const ShellAudioBus& source);
+ template <StorageType SourceStorageType, StorageType DestStorageType>
+ void MixFloatSamples(const ShellAudioBus& source);
+
+ template <StorageType SourceStorageType, StorageType DestStorageType>
+ void MixInt16Samples(const ShellAudioBus& source);
private:
void SetFloat32Sample(size_t channel, size_t frame, float sample) {
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index e17dd70..3810a3f 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -204,15 +204,16 @@
}
void StarboardPlayer::SetBounds(int z_index, const gfx::Rect& rect) {
+ base::AutoLock auto_lock(lock_);
+
+ set_bounds_z_index_ = z_index;
+ set_bounds_rect_ = rect;
+
if (state_ == kSuspended) {
- pending_set_bounds_z_index_ = z_index;
- pending_set_bounds_rect_ = rect;
return;
}
- DCHECK(SbPlayerIsValid(player_));
- SbPlayerSetBounds(player_, z_index, rect.x(), rect.y(), rect.width(),
- rect.height());
+ UpdateBounds_Locked();
}
void StarboardPlayer::PrepareForSeek() {
@@ -363,6 +364,7 @@
base::AutoLock auto_lock(lock_);
state_ = kResuming;
+ UpdateBounds_Locked();
}
namespace {
@@ -441,14 +443,10 @@
}
ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
ToVideoFrameProviderOutputMode(output_mode_));
-
set_bounds_helper_->SetPlayer(this);
- if (pending_set_bounds_z_index_ && pending_set_bounds_rect_) {
- SetBounds(*pending_set_bounds_z_index_, *pending_set_bounds_rect_);
- pending_set_bounds_z_index_ = base::nullopt_t();
- pending_set_bounds_rect_ = base::nullopt_t();
- }
+ base::AutoLock auto_lock(lock_);
+ UpdateBounds_Locked();
}
SbDecodeTarget StarboardPlayer::GetCurrentSbDecodeTarget() {
@@ -459,6 +457,19 @@
return output_mode_;
}
+void StarboardPlayer::UpdateBounds_Locked() {
+ lock_.AssertAcquired();
+ DCHECK(SbPlayerIsValid(player_));
+
+ if (!set_bounds_z_index_ || !set_bounds_rect_) {
+ return;
+ }
+
+ auto& rect = *set_bounds_rect_;
+ SbPlayerSetBounds(player_, *set_bounds_z_index_, rect.x(), rect.y(),
+ rect.width(), rect.height());
+}
+
void StarboardPlayer::ClearDecoderBufferCache() {
DCHECK(message_loop_->BelongsToCurrentThread());
diff --git a/src/cobalt/media/base/starboard_player.h b/src/cobalt/media/base/starboard_player.h
index a2c9dc5..a15255d 100644
--- a/src/cobalt/media/base/starboard_player.h
+++ b/src/cobalt/media/base/starboard_player.h
@@ -114,6 +114,8 @@
void WriteNextBufferFromCache(DemuxerStream::Type type);
+ void UpdateBounds_Locked();
+
void ClearDecoderBufferCache();
void OnDecoderStatus(SbPlayer player, SbMediaType type,
@@ -156,15 +158,14 @@
bool paused_;
bool seek_pending_;
DecoderBufferCache decoder_buffer_cache_;
- // If |SetBounds| is called while we are in a suspended state, then the
- // |z_index| and |rect| that we are passed will be saved to here, and then
- // immediately set on the new player that we construct when we are resumed.
- base::optional<int> pending_set_bounds_z_index_;
- base::optional<gfx::Rect> pending_set_bounds_rect_;
// The following variables can be accessed from GetInfo(), which can be called
// from any threads. So some of their usages have to be guarded by |lock_|.
base::Lock lock_;
+
+ // Stores the |z_index| and |rect| parameters of the latest SetBounds() call.
+ base::optional<int> set_bounds_z_index_;
+ base::optional<gfx::Rect> set_bounds_rect_;
State state_;
SbPlayer player_;
uint32 cached_video_frames_decoded_;
diff --git a/src/cobalt/media/filters/shell_demuxer.cc b/src/cobalt/media/filters/shell_demuxer.cc
index 45e3af5..20472aa 100644
--- a/src/cobalt/media/filters/shell_demuxer.cc
+++ b/src/cobalt/media/filters/shell_demuxer.cc
@@ -195,8 +195,7 @@
stopped_(false),
flushing_(false),
audio_reached_eos_(false),
- video_reached_eos_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+ video_reached_eos_(false) {
DCHECK(message_loop_);
DCHECK(buffer_allocator_);
DCHECK(data_source_);
@@ -236,19 +235,12 @@
return;
}
- base::PostTaskAndReplyWithResult(
- blocking_thread_.message_loop_proxy(), FROM_HERE,
- base::Bind(&ShellDemuxer::ParseConfigBlocking, base::Unretained(this),
- status_cb),
- // ParseConfigDone() will run on the current thread. Use a WeakPtr to
- // ensure that ParseConfigDone() won't run if the current instance is
- // destroyed.
- base::Bind(&ShellDemuxer::ParseConfigDone, weak_ptr_factory_.GetWeakPtr(),
- status_cb));
+ blocking_thread_.message_loop_proxy()->PostTask(
+ FROM_HERE, base::Bind(&ShellDemuxer::ParseConfigBlocking,
+ base::Unretained(this), status_cb));
}
-PipelineStatus ShellDemuxer::ParseConfigBlocking(
- const PipelineStatusCB& status_cb) {
+void ShellDemuxer::ParseConfigBlocking(const PipelineStatusCB& status_cb) {
DCHECK(blocking_thread_.message_loop_proxy()->BelongsToCurrentThread());
DCHECK(!parser_);
@@ -263,17 +255,20 @@
if (status == PIPELINE_OK) {
status = DEMUXER_ERROR_COULD_NOT_PARSE;
}
- return status;
+ ParseConfigDone(status_cb, status);
+ return;
}
// instruct the parser to extract audio and video config from the file
if (!parser_->ParseConfig()) {
- return DEMUXER_ERROR_COULD_NOT_PARSE;
+ ParseConfigDone(status_cb, DEMUXER_ERROR_COULD_NOT_PARSE);
+ return;
}
// make sure we got a valid and complete configuration
if (!parser_->IsConfigComplete()) {
- return DEMUXER_ERROR_COULD_NOT_PARSE;
+ ParseConfigDone(status_cb, DEMUXER_ERROR_COULD_NOT_PARSE);
+ return;
}
// IsConfigComplete() should guarantee we know the duration
@@ -287,14 +282,14 @@
// successful parse of config data, inform the nonblocking demuxer thread
DCHECK_EQ(status, PIPELINE_OK);
- return PIPELINE_OK;
+ ParseConfigDone(status_cb, PIPELINE_OK);
}
void ShellDemuxer::ParseConfigDone(const PipelineStatusCB& status_cb,
PipelineStatus status) {
- DCHECK(MessageLoopBelongsToCurrentThread());
+ DCHECK(blocking_thread_.message_loop_proxy()->BelongsToCurrentThread());
- if (stopped_) {
+ if (HasStopCalled()) {
return;
}
@@ -324,7 +319,7 @@
scoped_refptr<ShellAU> au = parser_->GetNextAU(type);
// fatal parsing error returns NULL or malformed AU
if (!au || !au->IsValid()) {
- if (!stopped_) {
+ if (!HasStopCalled()) {
DLOG(ERROR) << "got back bad AU from parser";
host_->OnDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE);
}
@@ -364,7 +359,11 @@
void ShellDemuxer::AllocateBuffer() {
DCHECK(requested_au_);
- if (requested_au_ && !stopped_) {
+ if (HasStopCalled()) {
+ return;
+ }
+
+ if (requested_au_) {
size_t total_buffer_size = audio_demuxer_stream_->GetTotalBufferSize() +
video_demuxer_stream_->GetTotalBufferSize();
if (total_buffer_size >= COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET) {
@@ -407,7 +406,7 @@
TRACE_EVENT2("media_stack", "ShellDemuxer::Download()", "type", event_type,
"timestamp", requested_au_->GetTimestamp().InMicroseconds());
// do nothing if stopped
- if (stopped_) {
+ if (HasStopCalled()) {
DLOG(INFO) << "aborting download task, stopped";
return;
}
@@ -464,10 +463,11 @@
void ShellDemuxer::IssueNextRequest() {
DCHECK(!requested_au_);
// if we're stopped don't download anymore
- if (stopped_) {
+ if (HasStopCalled()) {
DLOG(INFO) << "stopped so request loop is stopping";
return;
}
+
DemuxerStream::Type type = DemuxerStream::UNKNOWN;
// if we have eos in one or both buffers the decision is easy
if (audio_reached_eos_ || video_reached_eos_) {
@@ -516,7 +516,11 @@
DCHECK(MessageLoopBelongsToCurrentThread());
// set our internal stop flag, to not treat read failures as
// errors anymore but as a natural part of stopping
- stopped_ = true;
+ {
+ base::AutoLock auto_lock(lock_for_stopped_);
+ stopped_ = true;
+ }
+
// stop the reader, which will stop the datasource and call back
reader_->Stop();
}
@@ -534,6 +538,11 @@
callback.Run();
}
+bool ShellDemuxer::HasStopCalled() {
+ base::AutoLock auto_lock(lock_for_stopped_);
+ return stopped_;
+}
+
void ShellDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
blocking_thread_.message_loop()->PostTask(
FROM_HERE, base::Bind(&ShellDemuxer::SeekTask, base::Unretained(this),
diff --git a/src/cobalt/media/filters/shell_demuxer.h b/src/cobalt/media/filters/shell_demuxer.h
index ca8ea29..5fde5c6 100644
--- a/src/cobalt/media/filters/shell_demuxer.h
+++ b/src/cobalt/media/filters/shell_demuxer.h
@@ -20,7 +20,6 @@
#include <vector>
#include "base/logging.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
#include "cobalt/media/base/decoder_buffer.h"
@@ -150,12 +149,11 @@
void ParseConfigDone(const PipelineStatusCB& status_cb,
PipelineStatus status);
void DataSourceStopped(const base::Closure& callback);
+ bool HasStopCalled();
// methods that perform blocking I/O, and are therefore run on the
- // blocking_thread_
- // download enough of the stream to parse the configuration. returns
- // false on error.
- PipelineStatus ParseConfigBlocking(const PipelineStatusCB& status_cb);
+ // blocking_thread_ download enough of the stream to parse the configuration.
+ void ParseConfigBlocking(const PipelineStatusCB& status_cb);
void AllocateBuffer();
void Download(scoped_refptr<DecoderBuffer> buffer);
void IssueNextRequest();
@@ -171,6 +169,7 @@
scoped_refptr<MediaLog> media_log_;
scoped_refptr<ShellDataSourceReader> reader_;
+ base::Lock lock_for_stopped_;
bool stopped_;
bool flushing_;
@@ -181,8 +180,6 @@
scoped_refptr<ShellAU> requested_au_;
bool audio_reached_eos_;
bool video_reached_eos_;
-
- base::WeakPtrFactory<ShellDemuxer> weak_ptr_factory_;
};
} // namespace media
diff --git a/src/cobalt/media/filters/source_buffer_stream.cc b/src/cobalt/media/filters/source_buffer_stream.cc
index 4f9ffb0..6327853 100644
--- a/src/cobalt/media/filters/source_buffer_stream.cc
+++ b/src/cobalt/media/filters/source_buffer_stream.cc
@@ -731,10 +731,29 @@
return false;
}
- // Return if we're under or at the memory limit.
- if (ranges_size + newDataSize <= memory_limit_) return true;
+ base::TimeDelta duration = GetBufferedDurationForGarbageCollection();
- size_t bytes_to_free = ranges_size + newDataSize - memory_limit_;
+ size_t bytes_to_free = 0;
+
+ // Check if we're under or at the memory/duration limit.
+ const auto kGcDurationThresholdInMilliseconds =
+ COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS *
+ 1000;
+
+ if (ranges_size + newDataSize > memory_limit_) {
+ bytes_to_free = ranges_size + newDataSize - memory_limit_;
+ } else if (duration.InMilliseconds() > kGcDurationThresholdInMilliseconds) {
+ // Estimate the size to free.
+ auto duration_to_free =
+ duration.InMilliseconds() - kGcDurationThresholdInMilliseconds;
+ bytes_to_free = ranges_size * duration_to_free / duration.InMilliseconds();
+ }
+
+ if (bytes_to_free == 0) {
+ return true;
+ }
+
+ DCHECK_GT(bytes_to_free, 0);
DVLOG(2) << __func__ << " " << GetStreamTypeName()
<< ": Before GC media_time=" << media_time.InSecondsF()
@@ -1834,5 +1853,14 @@
return true;
}
+base::TimeDelta SourceBufferStream::GetBufferedDurationForGarbageCollection()
+ const {
+ base::TimeDelta duration;
+ for (auto range : ranges_) {
+ duration += range->GetEndTimestamp() - range->GetStartTimestamp();
+ }
+ return duration;
+}
+
} // namespace media
} // namespace cobalt
diff --git a/src/cobalt/media/filters/source_buffer_stream.h b/src/cobalt/media/filters/source_buffer_stream.h
index edeac1a..de9d343 100644
--- a/src/cobalt/media/filters/source_buffer_stream.h
+++ b/src/cobalt/media/filters/source_buffer_stream.h
@@ -471,6 +471,10 @@
// appropriately and returns true. Otherwise returns false.
bool SetPendingBuffer(scoped_refptr<StreamParserBuffer>* out_buffer);
+ // Returns the accumulated duration of all ranges. This is solely used by
+ // garbage collection.
+ base::TimeDelta GetBufferedDurationForGarbageCollection() const;
+
// Used to report log messages that can help the web developer figure out what
// is wrong with the content.
scoped_refptr<MediaLog> media_log_;
diff --git a/src/cobalt/renderer/copy_font_data.gypi b/src/cobalt/renderer/copy_font_data.gypi
index b62574e..0102e42 100644
--- a/src/cobalt/renderer/copy_font_data.gypi
+++ b/src/cobalt/renderer/copy_font_data.gypi
@@ -21,22 +21,9 @@
'source_font_files_dir': '<(static_contents_source_dir)/fonts/font_files',
'conditions': [
- [ 'cobalt_font_package == "expanded"', {
- 'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
-
- 'package_named_sans_serif': 4,
- 'package_named_serif': 3,
- 'package_named_fcc_fonts': 2,
- 'package_fallback_lang_non_cjk': 2,
- 'package_fallback_lang_cjk': 2,
- 'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
- 'package_fallback_emoji': 1,
- 'package_fallback_symbols': 1,
- }],
-
# 'unlimited' is deprecated but is mapped to 'standard'
- [ 'cobalt_font_package == "standard" or cobalt_font_package == "unlimited"', {
+ # 'expanded' also currently maps to 'standard' but this may change in the future
+ [ 'cobalt_font_package == "standard" or cobalt_font_package == "unlimited" or cobalt_font_package == "expanded"', {
'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
'package_named_sans_serif': 4,
@@ -45,13 +32,12 @@
'package_fallback_lang_non_cjk': 2,
'package_fallback_lang_cjk': 1,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 1,
'package_fallback_symbols': 1,
}],
- # '10megabytes' is deprecated but is mapped to 'limited_with_jp'
- [ 'cobalt_font_package == "limited_with_jp" or cobalt_font_package == "10megabytes"', {
+ # '10megabytes' and 'limited_with_jp' are deprecated but map to 'limited'
+ [ 'cobalt_font_package == "limited" or cobalt_font_package == "limited_with_jp" or cobalt_font_package == "10megabytes"', {
'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
'package_named_sans_serif': 2,
@@ -60,21 +46,6 @@
'package_fallback_lang_non_cjk': 1,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 1,
- 'package_fallback_emoji': 1,
- 'package_fallback_symbols': 1,
- }],
-
- [ 'cobalt_font_package == "limited"', {
- 'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
-
- 'package_named_sans_serif': 2,
- 'package_named_serif': 0,
- 'package_named_fcc_fonts': 0,
- 'package_fallback_lang_non_cjk': 1,
- 'package_fallback_lang_cjk': 0,
- 'package_fallback_lang_cjk_low_quality': 1,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 1,
'package_fallback_symbols': 1,
}],
@@ -88,7 +59,6 @@
'package_fallback_lang_non_cjk': 0,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 0,
'package_fallback_symbols': 0,
}],
@@ -108,7 +78,6 @@
'package_fallback_lang_non_cjk': 0,
'package_fallback_lang_cjk': 0,
'package_fallback_lang_cjk_low_quality': 0,
- 'package_fallback_lang_jp': 0,
'package_fallback_emoji': 1,
'package_fallback_symbols': 0,
}],
@@ -131,9 +100,6 @@
[ 'cobalt_font_package_override_fallback_lang_cjk_low_quality >= 0', {
'package_fallback_lang_cjk_low_quality': '<(cobalt_font_package_override_fallback_lang_cjk_low_quality)',
}],
- [ 'cobalt_font_package_override_fallback_lang_jp >= 0', {
- 'package_fallback_lang_jp': '<(cobalt_font_package_override_fallback_lang_jp)',
- }],
[ 'cobalt_font_package_override_fallback_emoji >= 0', {
'package_fallback_emoji': '<(cobalt_font_package_override_fallback_emoji)',
}],
@@ -309,21 +275,11 @@
'<(source_font_files_dir)/NotoSansCJK-Regular.ttc',
],
}],
- [ 'package_fallback_lang_cjk >= 2', {
- 'files+': [
- '<(source_font_files_dir)/NotoSansCJK-Bold.ttc',
- ],
- }],
[ 'package_fallback_lang_cjk_low_quality >= 1', {
'files+': [
'<(source_font_files_dir)/DroidSansFallback.ttf',
],
}],
- [ 'package_fallback_lang_jp >= 1', {
- 'files+': [
- '<(source_font_files_dir)/NotoSansJP-Regular.otf',
- ],
- }],
[ 'package_fallback_emoji >= 1', {
'files+': [
'<(source_font_files_dir)/NotoEmoji-Regular.ttf',
diff --git a/src/cobalt/renderer/pipeline.cc b/src/cobalt/renderer/pipeline.cc
index f41aea3..98ca265 100644
--- a/src/cobalt/renderer/pipeline.cc
+++ b/src/cobalt/renderer/pipeline.cc
@@ -80,9 +80,6 @@
last_did_rasterize_(false),
last_animations_expired_(true),
last_stat_tracked_animations_expired_(true),
- rasterize_periodic_timer_("Renderer.Rasterize.Duration",
- kRasterizePeriodicTimerEntriesPerUpdate,
- false /*enable_entry_list_c_val*/),
rasterize_animations_timer_("Renderer.Rasterize.Animations",
kRasterizeAnimationsTimerMaxEntries,
true /*enable_entry_list_c_val*/),
@@ -352,14 +349,6 @@
bool animations_active =
!are_stat_tracked_animations_expired && did_rasterize;
- // The rasterization is only timed with the periodic timer when the render
- // tree has changed. This ensures that the frames being timed are consistent
- // between platforms that submit unchanged trees and those that don't.
- if (did_rasterize) {
- rasterize_periodic_timer_.Start(start_time);
- rasterize_periodic_timer_.Stop(end_time);
- }
-
if (last_animations_active || animations_active) {
// The rasterization is only timed with the animations timer when there are
// animations to track. This applies when animations were active during
diff --git a/src/cobalt/renderer/pipeline.h b/src/cobalt/renderer/pipeline.h
index 366ef0d..965035c 100644
--- a/src/cobalt/renderer/pipeline.h
+++ b/src/cobalt/renderer/pipeline.h
@@ -245,13 +245,9 @@
bool last_did_rasterize_;
// Timer tracking the amount of time spent in
- // |RasterizeSubmissionToRenderTarget| when the render tree has changed.
- // The tracking is flushed when the max count is hit.
- base::CValCollectionTimerStats<base::CValPublic> rasterize_periodic_timer_;
- // Timer tracking the amount of time spent in
// |RasterizeSubmissionToRenderTarget| while animations are active. The
// tracking is flushed when the animations expire.
- base::CValCollectionTimerStats<base::CValDebug> rasterize_animations_timer_;
+ base::CValCollectionTimerStats<base::CValPublic> rasterize_animations_timer_;
// Accumulates render tree rasterization interval times but does not flush
// them until the maximum number of samples is gathered.
@@ -265,16 +261,16 @@
rasterize_animations_interval_timer_;
// The total number of new render trees that have been rasterized.
- base::CVal<int> new_render_tree_rasterize_count_;
+ base::CVal<int, base::CValPublic> new_render_tree_rasterize_count_;
// The last time that a newly encountered render tree was first rasterized.
- base::CVal<int64> new_render_tree_rasterize_time_;
+ base::CVal<int64, base::CValPublic> new_render_tree_rasterize_time_;
// Whether or not animations are currently playing.
- base::CVal<bool> has_active_animations_c_val_;
+ base::CVal<bool, base::CValPublic> has_active_animations_c_val_;
// The most recent time animations started playing.
- base::CVal<int64> animations_start_time_;
+ base::CVal<int64, base::CValPublic> animations_start_time_;
// The most recent time animations ended playing.
- base::CVal<int64> animations_end_time_;
+ base::CVal<int64, base::CValPublic> animations_end_time_;
#if defined(ENABLE_DEBUG_CONSOLE)
// Dumps the current render tree to the console.
diff --git a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
index 1c5e2d4..2dd5667 100644
--- a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
@@ -234,6 +234,7 @@
// This surface may have already been in the cache if it was in there
// with a different scale. In that case, replace the old one.
cache_memory_usage_ -= found->second.GetEstimatedMemoryUsage();
+ SbBlitterDestroySurface(found->second.surface);
surface_map_.erase(found);
}
diff --git a/src/cobalt/script/mozjs-45/mozjs_engine.cc b/src/cobalt/script/mozjs-45/mozjs_engine.cc
index ea0f726..656553a 100644
--- a/src/cobalt/script/mozjs-45/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_engine.cc
@@ -144,7 +144,16 @@
: accumulated_extra_memory_cost_(0), options_(options) {
TRACE_EVENT0("cobalt::script", "MozjsEngine::MozjsEngine()");
SbOnce(&g_js_init_once_control, CallInitAndRegisterShutDownOnce);
- runtime_ = JS_NewRuntime(options_.js_options.gc_threshold_bytes);
+
+ // Set the nursery size to half of the GC threshold size. Analysis has shown
+ // that allocating less than this does not reduce the total amount of JS
+ // memory used, and allocating more does not provide performance improvements.
+ constexpr size_t kMinMaxNurseryBytes = 1 * 1024 * 1024;
+ uint32_t max_nursery_bytes =
+ std::max(options_.js_options.gc_threshold_bytes / 2, kMinMaxNurseryBytes);
+
+ runtime_ =
+ JS_NewRuntime(options_.js_options.gc_threshold_bytes, max_nursery_bytes);
CHECK(runtime_);
// Sets the size of the native stack that should not be exceeded.
diff --git a/src/starboard/nplb/socket_resolve_test.cc b/src/starboard/nplb/socket_resolve_test.cc
index ebca117..bf96ac3 100644
--- a/src/starboard/nplb/socket_resolve_test.cc
+++ b/src/starboard/nplb/socket_resolve_test.cc
@@ -37,7 +37,7 @@
const void* kNull = NULL;
// A random host name to use to test DNS resolution.
-const char* kTestHostName = "www.yahoo.com";
+const char kTestHostName[] = "www.example.com";
#define LOG_ADDRESS(i) "In returned address #" << (i)
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
index 850838f..6ccf433 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -231,10 +231,23 @@
codec_context_->channels = audio_header_.number_of_channels;
codec_context_->sample_rate = audio_header_.samples_per_second;
-
codec_context_->extradata = NULL;
codec_context_->extradata_size = 0;
+ if (codec_context_->codec_id == AV_CODEC_ID_OPUS &&
+ audio_header_.audio_specific_config_size > 0) {
+ // AV_INPUT_BUFFER_PADDING_SIZE is not defined in ancient avcodec.h. Use a
+ // large enough padding here explicitly.
+ const int kAvInputBufferPaddingSize = 256;
+ codec_context_->extradata_size = audio_header_.audio_specific_config_size;
+ codec_context_->extradata = static_cast<uint8_t*>(
+ av_malloc(codec_context_->extradata_size + kAvInputBufferPaddingSize));
+ SbMemoryCopy(codec_context_->extradata, audio_header_.audio_specific_config,
+ codec_context_->extradata_size);
+ SbMemorySet(codec_context_->extradata + codec_context_->extradata_size, 0,
+ kAvInputBufferPaddingSize);
+ }
+
AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
if (codec == NULL) {
@@ -264,13 +277,10 @@
void AudioDecoder::TeardownCodec() {
if (codec_context_) {
CloseCodec(codec_context_);
- av_free(codec_context_);
- codec_context_ = NULL;
+ av_freep(&codec_context_->extradata);
+ av_freep(&codec_context_);
}
- if (av_frame_) {
- av_free(av_frame_);
- av_frame_ = NULL;
- }
+ av_freep(&av_frame_);
}
} // namespace ffmpeg
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_resampler.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_resampler.cc
index 3892b04..9df9cdf 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_resampler.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_resampler.cc
@@ -115,7 +115,7 @@
AudioResampler::~AudioResampler() {
SB_DCHECK(thread_checker_.CalledOnValidThread());
avresample_close(context_);
- av_free(context_);
+ av_freep(&context_);
}
scoped_refptr<AudioResampler::DecodedAudio> AudioResampler::Resample(
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
index e1e9129..6d8981b 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -382,13 +382,9 @@
void VideoDecoder::TeardownCodec() {
if (codec_context_) {
CloseCodec(codec_context_);
- av_free(codec_context_);
- codec_context_ = NULL;
+ av_freep(&codec_context_);
}
- if (av_frame_) {
- av_free(av_frame_);
- av_frame_ = NULL;
- }
+ av_freep(&av_frame_);
if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
ScopedLock lock(decode_target_mutex_);
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
index 0b81764..58d48ad 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
@@ -64,9 +64,14 @@
} // namespace
-AudioRendererImpl::AudioRendererImpl(scoped_ptr<AudioDecoder> decoder,
- const SbMediaAudioHeader& audio_header)
- : eos_state_(kEOSNotReceived),
+AudioRendererImpl::AudioRendererImpl(
+ scoped_ptr<AudioDecoder> decoder,
+ const SbMediaAudioHeader& audio_header,
+ size_t max_cached_frames /*= kDefaultMaxCachedFrames*/,
+ size_t max_frames_per_append /* = kDefaultMaxFramesPerAppend*/)
+ : max_cached_frames_(max_cached_frames),
+ max_frames_per_append_(max_frames_per_append),
+ eos_state_(kEOSNotReceived),
channels_(audio_header.number_of_channels),
sink_sample_type_(GetSinkAudioSampleType()),
bytes_per_frame_(media::GetBytesPerSample(sink_sample_type_) * channels_),
@@ -76,7 +81,7 @@
consume_frames_called_(false),
seeking_(false),
seeking_to_pts_(0),
- frame_buffer_(kMaxCachedFrames * bytes_per_frame_),
+ frame_buffer_(max_cached_frames_ * bytes_per_frame_),
frames_sent_to_sink_(0),
pending_decoder_outputs_(0),
frames_consumed_by_sink_(0),
@@ -89,6 +94,8 @@
Bind(&AudioRendererImpl::ProcessAudioData, this)),
decoder_needs_full_reset_(false) {
SB_DCHECK(decoder_ != NULL);
+ SB_DCHECK(max_frames_per_append_ > 0);
+ SB_DCHECK(max_cached_frames_ >= max_frames_per_append_ * 2);
frame_buffers_[0] = &frame_buffer_[0];
@@ -316,7 +323,7 @@
channels_, destination_sample_rate, sink_sample_type_,
kSbMediaAudioFrameStorageTypeInterleaved,
reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
- kMaxCachedFrames, &AudioRendererImpl::UpdateSourceStatusFunc,
+ max_cached_frames_, &AudioRendererImpl::UpdateSourceStatusFunc,
&AudioRendererImpl::ConsumeFramesFunc, this);
SB_DCHECK(SbAudioSinkIsValid(audio_sink_));
@@ -337,7 +344,7 @@
if (*is_playing) {
*frames_in_buffer = static_cast<int>(frames_sent_to_sink_.load() -
frames_consumed_by_sink_.load());
- *offset_in_frames = frames_consumed_by_sink_.load() % kMaxCachedFrames;
+ *offset_in_frames = frames_consumed_by_sink_.load() % max_cached_frames_;
} else {
*frames_in_buffer = *offset_in_frames = 0;
}
@@ -398,14 +405,15 @@
// Loop until no audio is appended, i.e. AppendAudioToFrameBuffer() returns
// false.
- while (AppendAudioToFrameBuffer()) {
+ bool is_frame_buffer_full = false;
+ while (AppendAudioToFrameBuffer(&is_frame_buffer_full)) {
}
while (pending_decoder_outputs_ > 0) {
if (time_stretcher_.IsQueueFull()) {
// There is no room to do any further processing, schedule the function
// again for a later time. The delay time is 1/4 of the buffer size.
- const SbTimeMonotonic delay = kMaxCachedFrames * kSbTimeSecond /
+ const SbTimeMonotonic delay = max_cached_frames_ * kSbTimeSecond /
decoder_->GetSamplesPerSecond() / 4;
process_audio_data_scheduled_ = true;
Schedule(process_audio_data_closure_, delay);
@@ -439,7 +447,7 @@
// Loop until no audio is appended, i.e. AppendAudioToFrameBuffer() returns
// false.
- while (AppendAudioToFrameBuffer()) {
+ while (AppendAudioToFrameBuffer(&is_frame_buffer_full)) {
}
}
@@ -449,15 +457,14 @@
return;
}
- int64_t frames_in_buffer =
- frames_sent_to_sink_.load() - frames_consumed_by_sink_.load();
- if (kMaxCachedFrames - frames_in_buffer < kFrameAppendUnit &&
- eos_state_.load() < kEOSSentToSink) {
+ if (is_frame_buffer_full) {
// There are still audio data not appended so schedule a callback later.
SbTimeMonotonic delay = 0;
- if (kMaxCachedFrames - frames_in_buffer < kMaxCachedFrames / 4) {
+ int64_t frames_in_buffer =
+ frames_sent_to_sink_.load() - frames_consumed_by_sink_.load();
+ if (max_cached_frames_ - frames_in_buffer < max_cached_frames_ / 4) {
int frames_to_delay = static_cast<int>(
- kMaxCachedFrames / 4 - (kMaxCachedFrames - frames_in_buffer));
+ max_cached_frames_ / 4 - (max_cached_frames_ - frames_in_buffer));
delay = frames_to_delay * kSbTimeSecond / decoder_->GetSamplesPerSecond();
}
process_audio_data_scheduled_ = true;
@@ -465,8 +472,11 @@
}
}
-bool AudioRendererImpl::AppendAudioToFrameBuffer() {
+bool AudioRendererImpl::AppendAudioToFrameBuffer(bool* is_frame_buffer_full) {
SB_DCHECK(BelongsToCurrentThread());
+ SB_DCHECK(is_frame_buffer_full);
+
+ *is_frame_buffer_full = false;
if (seeking_.load() && time_stretcher_.IsQueueFull()) {
seeking_.store(false);
@@ -479,14 +489,15 @@
int frames_in_buffer = static_cast<int>(frames_sent_to_sink_.load() -
frames_consumed_by_sink_.load());
- if (kMaxCachedFrames - frames_in_buffer < kFrameAppendUnit) {
+ if (max_cached_frames_ - frames_in_buffer < max_frames_per_append_) {
+ *is_frame_buffer_full = true;
return false;
}
- int offset_to_append = frames_sent_to_sink_.load() % kMaxCachedFrames;
+ int offset_to_append = frames_sent_to_sink_.load() % max_cached_frames_;
scoped_refptr<DecodedAudio> decoded_audio =
- time_stretcher_.Read(kFrameAppendUnit, playback_rate_.load());
+ time_stretcher_.Read(max_frames_per_append_, playback_rate_.load());
SB_DCHECK(decoded_audio);
if (decoded_audio->frames() == 0 && eos_state_.load() == kEOSDecoded) {
eos_state_.store(kEOSSentToSink);
@@ -500,13 +511,13 @@
int frames_to_append = decoded_audio->frames();
int frames_appended = 0;
- if (frames_to_append > kMaxCachedFrames - offset_to_append) {
+ if (frames_to_append > max_cached_frames_ - offset_to_append) {
SbMemoryCopy(&frame_buffer_[offset_to_append * bytes_per_frame_],
source_buffer,
- (kMaxCachedFrames - offset_to_append) * bytes_per_frame_);
- source_buffer += (kMaxCachedFrames - offset_to_append) * bytes_per_frame_;
- frames_to_append -= kMaxCachedFrames - offset_to_append;
- frames_appended += kMaxCachedFrames - offset_to_append;
+ (max_cached_frames_ - offset_to_append) * bytes_per_frame_);
+ source_buffer += (max_cached_frames_ - offset_to_append) * bytes_per_frame_;
+ frames_to_append -= max_cached_frames_ - offset_to_append;
+ frames_appended += max_cached_frames_ - offset_to_append;
offset_to_append = 0;
}
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
index 7ab3a0a..c602812 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
@@ -44,8 +44,20 @@
// |AudioDecoder| interface, rather than a platform specific implementation.
class AudioRendererImpl : public AudioRenderer, private JobQueue::JobOwner {
public:
+ static const size_t kDefaultMaxCachedFrames = 256 * 1024;
+ static const size_t kDefaultMaxFramesPerAppend = 16384;
+
+ // |max_cached_frames| is a soft limit for the max audio frames this class can
+ // cache so it can:
+ // 1. Avoid using too much memory.
+ // 2. Have the audio cache full to simulate the state that the renderer can no
+ // longer accept more data.
+ // |max_frames_per_append| is the max number of frames that the audio renderer
+ // tries to append to the sink buffer at once.
AudioRendererImpl(scoped_ptr<AudioDecoder> decoder,
- const SbMediaAudioHeader& audio_header);
+ const SbMediaAudioHeader& audio_header,
+ size_t max_cached_frames = kDefaultMaxCachedFrames,
+ size_t max_frames_per_append = kDefaultMaxFramesPerAppend);
~AudioRendererImpl() SB_OVERRIDE;
void Initialize(const Closure& error_cb) SB_OVERRIDE;
@@ -69,6 +81,16 @@
SbMediaTime GetCurrentTime() SB_OVERRIDE;
protected:
+ enum EOSState {
+ kEOSNotReceived,
+ kEOSWrittenToDecoder,
+ kEOSDecoded,
+ kEOSSentToSink
+ };
+
+ const size_t max_cached_frames_;
+ const size_t max_frames_per_append_;
+
atomic_bool paused_;
atomic_bool consume_frames_called_;
atomic_bool seeking_;
@@ -85,22 +107,6 @@
atomic_double playback_rate_;
private:
- enum EOSState {
- kEOSNotReceived,
- kEOSWrittenToDecoder,
- kEOSDecoded,
- kEOSSentToSink
- };
-
- // Set a soft limit for the max audio frames we can cache so we can:
- // 1. Avoid using too much memory.
- // 2. Have the audio cache full to simulate the state that the renderer can no
- // longer accept more data.
- static const size_t kMaxCachedFrames = 256 * 1024;
- // The audio renderer tries to append |kAppendFrameUnit| frames every time to
- // the sink buffer.
- static const size_t kFrameAppendUnit = 16384;
-
void CreateAudioSinkAndResampler();
void UpdateSourceStatus(int* frames_in_buffer,
int* offset_in_frames,
@@ -113,7 +119,7 @@
void OnDecoderOutput();
void ProcessAudioData();
void FillResamplerAndTimeStretcher();
- bool AppendAudioToFrameBuffer();
+ bool AppendAudioToFrameBuffer(bool* is_frame_buffer_full);
// SbAudioSink callbacks
static void UpdateSourceStatusFunc(int* frames_in_buffer,