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,