summaryrefslogtreecommitdiff
path: root/chromium/chromecast
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-06-18 14:10:49 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2015-06-18 13:53:24 +0000
commit813fbf95af77a531c57a8c497345ad2c61d475b3 (patch)
tree821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/chromecast
parentaf6588f8d723931a298c995fa97259bb7f7deb55 (diff)
downloadqtwebengine-chromium-813fbf95af77a531c57a8c497345ad2c61d475b3.tar.gz
BASELINE: Update chromium to 44.0.2403.47
Change-Id: Ie056fedba95cf5e5c76b30c4b2c80fca4764aa2f Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/chromecast')
-rw-r--r--chromium/chromecast/BUILD.gn21
-rw-r--r--chromium/chromecast/DEPS1
-rw-r--r--chromium/chromecast/OWNERS1
-rw-r--r--chromium/chromecast/android/DEPS1
-rw-r--r--chromium/chromecast/app/cast_main_delegate.cc26
-rw-r--r--chromium/chromecast/app/cast_main_delegate.h15
-rw-r--r--chromium/chromecast/app/resources/shell_devtools_discovery_page.html34
-rw-r--r--chromium/chromecast/base/BUILD.gn12
-rw-r--r--chromium/chromecast/base/cast_paths.cc (renamed from chromium/chromecast/common/cast_paths.cc)2
-rw-r--r--chromium/chromecast/base/cast_paths.h (renamed from chromium/chromecast/common/cast_paths.h)6
-rw-r--r--chromium/chromecast/base/cast_sys_info_dummy.cc79
-rw-r--r--chromium/chromecast/base/cast_sys_info_dummy.h42
-rw-r--r--chromium/chromecast/base/cast_sys_info_util.h21
-rw-r--r--chromium/chromecast/base/cast_sys_info_util_simple.cc16
-rw-r--r--chromium/chromecast/base/metrics/BUILD.gn35
-rw-r--r--chromium/chromecast/base/metrics/cast_histograms.h21
-rw-r--r--chromium/chromecast/base/metrics/cast_metrics_helper.cc111
-rw-r--r--chromium/chromecast/base/metrics/cast_metrics_helper.h48
-rw-r--r--chromium/chromecast/base/metrics/cast_metrics_test_helper.cc33
-rw-r--r--chromium/chromecast/base/metrics/grouped_histogram.cc181
-rw-r--r--chromium/chromecast/base/metrics/grouped_histogram.h25
-rw-r--r--chromium/chromecast/base/serializers.cc33
-rw-r--r--chromium/chromecast/base/serializers.h29
-rw-r--r--chromium/chromecast/base/serializers_unittest.cc76
-rw-r--r--chromium/chromecast/browser/DEPS7
-rw-r--r--chromium/chromecast/browser/android/apk/AndroidManifest.xml141
-rw-r--r--chromium/chromecast/browser/android/apk/AndroidManifest.xml.jinja257
-rw-r--r--chromium/chromecast/browser/android/cast_window_android.cc90
-rw-r--r--chromium/chromecast/browser/android/cast_window_android.h49
-rw-r--r--chromium/chromecast/browser/android/cast_window_manager.cc4
-rw-r--r--chromium/chromecast/browser/android/external_video_surface_container_impl.cc91
-rw-r--r--chromium/chromecast/browser/android/external_video_surface_container_impl.h57
-rw-r--r--chromium/chromecast/browser/cast_browser_context.cc37
-rw-r--r--chromium/chromecast/browser/cast_browser_context.h40
-rw-r--r--chromium/chromecast/browser/cast_browser_main_parts.cc309
-rw-r--r--chromium/chromecast/browser/cast_browser_main_parts.h23
-rw-r--r--chromium/chromecast/browser/cast_browser_process.cc61
-rw-r--r--chromium/chromecast/browser/cast_browser_process.h43
-rw-r--r--chromium/chromecast/browser/cast_content_browser_client.cc244
-rw-r--r--chromium/chromecast/browser/cast_content_browser_client.h94
-rw-r--r--chromium/chromecast/browser/cast_content_browser_client_simple.cc30
-rw-r--r--chromium/chromecast/browser/cast_content_window.cc60
-rw-r--r--chromium/chromecast/browser/cast_content_window.h23
-rw-r--r--chromium/chromecast/browser/cast_download_manager_delegate.h16
-rw-r--r--chromium/chromecast/browser/cast_http_user_agent_settings.cc21
-rw-r--r--chromium/chromecast/browser/cast_http_user_agent_settings.h8
-rw-r--r--chromium/chromecast/browser/cast_network_delegate.cc3
-rw-r--r--chromium/chromecast/browser/cast_network_delegate.h13
-rw-r--r--chromium/chromecast/browser/cast_network_delegate_simple.cc6
-rw-r--r--chromium/chromecast/browser/cast_permission_manager.cc72
-rw-r--r--chromium/chromecast/browser/cast_permission_manager.h56
-rw-r--r--chromium/chromecast/browser/cast_quota_permission_context.cc23
-rw-r--r--chromium/chromecast/browser/cast_quota_permission_context.h30
-rw-r--r--chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.cc26
-rw-r--r--chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.h29
-rw-r--r--chromium/chromecast/browser/devtools/cast_dev_tools_delegate.cc132
-rw-r--r--chromium/chromecast/browser/devtools/cast_dev_tools_delegate.h51
-rw-r--r--chromium/chromecast/browser/devtools/remote_debugging_server.cc87
-rw-r--r--chromium/chromecast/browser/devtools/remote_debugging_server.h11
-rw-r--r--chromium/chromecast/browser/geolocation/cast_access_token_store.h7
-rw-r--r--chromium/chromecast/browser/media/cast_browser_cdm_factory.cc58
-rw-r--r--chromium/chromecast/browser/media/cast_browser_cdm_factory.h44
-rw-r--r--chromium/chromecast/browser/media/cast_browser_cdm_factory_simple.cc18
-rw-r--r--chromium/chromecast/browser/media/cast_media_client_android.cc44
-rw-r--r--chromium/chromecast/browser/media/cast_media_client_android.h41
-rw-r--r--chromium/chromecast/browser/media/cma_message_filter_host.cc540
-rw-r--r--chromium/chromecast/browser/media/cma_message_filter_host.h126
-rw-r--r--chromium/chromecast/browser/media/cma_message_loop.cc37
-rw-r--r--chromium/chromecast/browser/media/cma_message_loop.h44
-rw-r--r--chromium/chromecast/browser/media/media_pipeline_host.cc174
-rw-r--r--chromium/chromecast/browser/media/media_pipeline_host.h86
-rw-r--r--chromium/chromecast/browser/metrics/cast_metrics_service_client.cc166
-rw-r--r--chromium/chromecast/browser/metrics/cast_metrics_service_client.h57
-rw-r--r--chromium/chromecast/browser/metrics/cast_metrics_service_client_unittest.cc45
-rw-r--r--chromium/chromecast/browser/metrics/cast_stability_metrics_provider.cc10
-rw-r--r--chromium/chromecast/browser/metrics/cast_stability_metrics_provider.h20
-rw-r--r--chromium/chromecast/browser/metrics/external_metrics.cc19
-rw-r--r--chromium/chromecast/browser/metrics/external_metrics.h11
-rw-r--r--chromium/chromecast/browser/metrics/platform_metrics_providers.h21
-rw-r--r--chromium/chromecast/browser/metrics/platform_metrics_providers_simple.cc19
-rw-r--r--chromium/chromecast/browser/pref_service_helper.cc76
-rw-r--r--chromium/chromecast/browser/pref_service_helper.h43
-rw-r--r--chromium/chromecast/browser/pref_service_helper_simple.cc17
-rw-r--r--chromium/chromecast/browser/service/cast_service.cc22
-rw-r--r--chromium/chromecast/browser/service/cast_service.h54
-rw-r--r--chromium/chromecast/browser/service/cast_service_android.cc30
-rw-r--r--chromium/chromecast/browser/service/cast_service_android.h12
-rw-r--r--chromium/chromecast/browser/service/cast_service_simple.cc35
-rw-r--r--chromium/chromecast/browser/service/cast_service_simple.h14
-rw-r--r--chromium/chromecast/browser/url_request_context_factory.cc56
-rw-r--r--chromium/chromecast/browser/url_request_context_factory.h4
-rw-r--r--chromium/chromecast/browser/webui/webui_cast.h18
-rw-r--r--chromium/chromecast/build/args.gn14
-rw-r--r--chromium/chromecast/build/tests/test_list.gypi54
-rw-r--r--chromium/chromecast/chromecast.gni10
-rw-r--r--chromium/chromecast/chromecast.gyp344
-rw-r--r--chromium/chromecast/chromecast_tests.gypi286
-rw-r--r--chromium/chromecast/common/cast_content_client.cc51
-rw-r--r--chromium/chromecast/common/cast_content_client.h12
-rw-r--r--chromium/chromecast/common/cast_resource_delegate.h24
-rw-r--r--chromium/chromecast/common/chromecast_config.cc144
-rw-r--r--chromium/chromecast/common/chromecast_config.h85
-rw-r--r--chromium/chromecast/common/chromecast_switches.cc21
-rw-r--r--chromium/chromecast/common/chromecast_switches.h13
-rw-r--r--chromium/chromecast/common/media/DEPS4
-rw-r--r--chromium/chromecast/common/media/OWNERS25
-rw-r--r--chromium/chromecast/common/media/cast_message_generator.cc15
-rw-r--r--chromium/chromecast/common/media/cast_message_generator.h8
-rw-r--r--chromium/chromecast/common/media/cast_messages.h17
-rw-r--r--chromium/chromecast/common/media/cma_ipc_common.h21
-rw-r--r--chromium/chromecast/common/media/cma_message_generator.cc39
-rw-r--r--chromium/chromecast/common/media/cma_message_generator.h8
-rw-r--r--chromium/chromecast/common/media/cma_messages.h115
-rw-r--r--chromium/chromecast/common/media/cma_param_traits.cc135
-rw-r--r--chromium/chromecast/common/media/cma_param_traits.h35
-rw-r--r--chromium/chromecast/common/media/cma_param_traits_macros.h54
-rw-r--r--chromium/chromecast/common/media/shared_memory_chunk.cc36
-rw-r--r--chromium/chromecast/common/media/shared_memory_chunk.h40
-rw-r--r--chromium/chromecast/common/pref_names.cc4
-rw-r--r--chromium/chromecast/common/pref_names.h1
-rw-r--r--chromium/chromecast/common/version.h.in6
-rw-r--r--chromium/chromecast/crash/android/cast_crash_reporter_client_android.cc7
-rw-r--r--chromium/chromecast/crash/android/cast_crash_reporter_client_android.h17
-rw-r--r--chromium/chromecast/crash/android/crash_handler.cc118
-rw-r--r--chromium/chromecast/crash/android/crash_handler.h14
-rw-r--r--chromium/chromecast/crash/cast_crash_keys.cc53
-rw-r--r--chromium/chromecast/crash/cast_crash_keys.h22
-rw-r--r--chromium/chromecast/crash/cast_crash_reporter_client.cc58
-rw-r--r--chromium/chromecast/crash/cast_crash_reporter_client.h36
-rw-r--r--chromium/chromecast/crash/cast_crash_reporter_client_simple.cc17
-rw-r--r--chromium/chromecast/graphics/DEPS3
-rw-r--r--chromium/chromecast/graphics/cast_egl_platform_default.cc41
-rw-r--r--chromium/chromecast/graphics/graphics_properties_default.cc15
-rw-r--r--chromium/chromecast/graphics/osd_plane_default.cc73
-rw-r--r--chromium/chromecast/media/BUILD.gn53
-rw-r--r--chromium/chromecast/media/DEPS1
-rw-r--r--chromium/chromecast/media/base/BUILD.gn38
-rw-r--r--chromium/chromecast/media/base/cast_media_default.cc17
-rw-r--r--chromium/chromecast/media/base/decrypt_context_clearkey.h6
-rw-r--r--chromium/chromecast/media/base/key_systems_common.h12
-rw-r--r--chromium/chromecast/media/base/key_systems_common_simple.cc8
-rw-r--r--chromium/chromecast/media/base/media_caps.cc38
-rw-r--r--chromium/chromecast/media/base/media_caps.h30
-rw-r--r--chromium/chromecast/media/base/media_codec_support.cc16
-rw-r--r--chromium/chromecast/media/base/media_codec_support.h34
-rw-r--r--chromium/chromecast/media/base/media_codec_support_simple.cc21
-rw-r--r--chromium/chromecast/media/base/switching_media_renderer.cc102
-rw-r--r--chromium/chromecast/media/base/switching_media_renderer.h66
-rw-r--r--chromium/chromecast/media/cdm/BUILD.gn18
-rw-r--r--chromium/chromecast/media/cdm/browser_cdm_cast.cc209
-rw-r--r--chromium/chromecast/media/cdm/browser_cdm_cast.h147
-rw-r--r--chromium/chromecast/media/cdm/playready_drm_delegate_android.cc85
-rw-r--r--chromium/chromecast/media/cdm/playready_drm_delegate_android.h34
-rw-r--r--chromium/chromecast/media/cma/BUILD.gn14
-rw-r--r--chromium/chromecast/media/cma/backend/BUILD.gn37
-rw-r--r--chromium/chromecast/media/cma/backend/audio_pipeline_device.h9
-rw-r--r--chromium/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc44
-rw-r--r--chromium/chromecast/media/cma/backend/media_pipeline_device_fake.cc112
-rw-r--r--chromium/chromecast/media/cma/backend/media_pipeline_device_fake.h8
-rw-r--r--chromium/chromecast/media/cma/backend/media_pipeline_device_params.cc2
-rw-r--r--chromium/chromecast/media/cma/backend/media_pipeline_device_params.h24
-rw-r--r--chromium/chromecast/media/cma/backend/video_pipeline_device.h9
-rw-r--r--chromium/chromecast/media/cma/backend/video_plane.cc54
-rw-r--r--chromium/chromecast/media/cma/backend/video_plane.h62
-rw-r--r--chromium/chromecast/media/cma/backend/video_plane_fake.cc33
-rw-r--r--chromium/chromecast/media/cma/backend/video_plane_fake.h31
-rw-r--r--chromium/chromecast/media/cma/backend/video_plane_fake_factory.cc15
-rw-r--r--chromium/chromecast/media/cma/base/BUILD.gn35
-rw-r--r--chromium/chromecast/media/cma/base/balanced_media_task_runner_factory.cc8
-rw-r--r--chromium/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc2
-rw-r--r--chromium/chromecast/media/cma/base/buffering_controller.cc5
-rw-r--r--chromium/chromecast/media/cma/base/buffering_controller.h3
-rw-r--r--chromium/chromecast/media/cma/base/buffering_controller_unittest.cc6
-rw-r--r--chromium/chromecast/media/cma/base/buffering_defs.cc14
-rw-r--r--chromium/chromecast/media/cma/base/buffering_defs.h19
-rw-r--r--chromium/chromecast/media/cma/base/buffering_frame_provider.h6
-rw-r--r--chromium/chromecast/media/cma/base/buffering_frame_provider_unittest.cc2
-rw-r--r--chromium/chromecast/media/cma/base/buffering_state.cc6
-rw-r--r--chromium/chromecast/media/cma/base/buffering_state.h4
-rw-r--r--chromium/chromecast/media/cma/base/decoder_buffer_adapter.cc2
-rw-r--r--chromium/chromecast/media/cma/base/decoder_buffer_adapter.h14
-rw-r--r--chromium/chromecast/media/cma/base/decoder_buffer_base.h2
-rw-r--r--chromium/chromecast/media/cma/base/decoder_config_adapter.cc126
-rw-r--r--chromium/chromecast/media/cma/base/decoder_config_adapter.h29
-rw-r--r--chromium/chromecast/media/cma/filters/BUILD.gn20
-rw-r--r--chromium/chromecast/media/cma/filters/cma_renderer.cc472
-rw-r--r--chromium/chromecast/media/cma/filters/cma_renderer.h151
-rw-r--r--chromium/chromecast/media/cma/filters/demuxer_stream_adapter.cc11
-rw-r--r--chromium/chromecast/media/cma/filters/demuxer_stream_adapter.h6
-rw-r--r--chromium/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc20
-rw-r--r--chromium/chromecast/media/cma/ipc/BUILD.gn21
-rw-r--r--chromium/chromecast/media/cma/ipc/media_message_fifo.cc10
-rw-r--r--chromium/chromecast/media/cma/ipc/media_message_fifo.h23
-rw-r--r--chromium/chromecast/media/cma/ipc/media_message_fifo_unittest.cc8
-rw-r--r--chromium/chromecast/media/cma/ipc/media_message_unittest.cc8
-rw-r--r--chromium/chromecast/media/cma/ipc_streamer/BUILD.gn28
-rw-r--r--chromium/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc10
-rw-r--r--chromium/chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h6
-rw-r--r--chromium/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc24
-rw-r--r--chromium/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc12
-rw-r--r--chromium/chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.cc4
-rw-r--r--chromium/chromecast/media/cma/pipeline/BUILD.gn44
-rw-r--r--chromium/chromecast/media/cma/pipeline/audio_pipeline.cc (renamed from chromium/chromecast/browser/webui/webui_cast_simple.cc)12
-rw-r--r--chromium/chromecast/media/cma/pipeline/audio_pipeline.h34
-rw-r--r--chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.cc161
-rw-r--r--chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.h79
-rw-r--r--chromium/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc211
-rw-r--r--chromium/chromecast/media/cma/pipeline/av_pipeline_client.cc17
-rw-r--r--chromium/chromecast/media/cma/pipeline/av_pipeline_client.h35
-rw-r--r--chromium/chromecast/media/cma/pipeline/av_pipeline_impl.cc387
-rw-r--r--chromium/chromecast/media/cma/pipeline/av_pipeline_impl.h172
-rw-r--r--chromium/chromecast/media/cma/pipeline/decrypt_util.cc128
-rw-r--r--chromium/chromecast/media/cma/pipeline/decrypt_util.h31
-rw-r--r--chromium/chromecast/media/cma/pipeline/load_type.h20
-rw-r--r--chromium/chromecast/media/cma/pipeline/media_pipeline.h69
-rw-r--r--chromium/chromecast/media/cma/pipeline/media_pipeline_client.cc17
-rw-r--r--chromium/chromecast/media/cma/pipeline/media_pipeline_client.h37
-rw-r--r--chromium/chromecast/media/cma/pipeline/media_pipeline_impl.cc373
-rw-r--r--chromium/chromecast/media/cma/pipeline/media_pipeline_impl.h113
-rw-r--r--chromium/chromecast/media/cma/pipeline/video_pipeline.cc (renamed from chromium/chromecast/common/chromecast_config_simple.cc)9
-rw-r--r--chromium/chromecast/media/cma/pipeline/video_pipeline.h28
-rw-r--r--chromium/chromecast/media/cma/pipeline/video_pipeline_client.cc17
-rw-r--r--chromium/chromecast/media/cma/pipeline/video_pipeline_client.h35
-rw-r--r--chromium/chromecast/media/cma/pipeline/video_pipeline_impl.cc178
-rw-r--r--chromium/chromecast/media/cma/pipeline/video_pipeline_impl.h82
-rw-r--r--chromium/chromecast/media/media.gyp116
-rw-r--r--chromium/chromecast/net/connectivity_checker.cc184
-rw-r--r--chromium/chromecast/net/connectivity_checker.h99
-rw-r--r--chromium/chromecast/net/net_switches.cc17
-rw-r--r--chromium/chromecast/net/net_switches.h15
-rw-r--r--chromium/chromecast/net/net_util_cast.cc33
-rw-r--r--chromium/chromecast/net/net_util_cast.h20
-rw-r--r--chromium/chromecast/net/network_change_notifier_cast.cc20
-rw-r--r--chromium/chromecast/net/network_change_notifier_cast.h34
-rw-r--r--chromium/chromecast/net/network_change_notifier_factory_cast.cc7
-rw-r--r--chromium/chromecast/net/network_change_notifier_factory_cast.h8
-rw-r--r--chromium/chromecast/public/DEPS8
-rw-r--r--chromium/chromecast/public/cast_egl_platform.h60
-rw-r--r--chromium/chromecast/public/cast_egl_platform_shlib.h25
-rw-r--r--chromium/chromecast/public/cast_media_shlib.h40
-rw-r--r--chromium/chromecast/public/cast_sys_info.h75
-rw-r--r--chromium/chromecast/public/chromecast_export.h12
-rw-r--r--chromium/chromecast/public/graphics_properties_shlib.h32
-rw-r--r--chromium/chromecast/public/graphics_types.h30
-rw-r--r--chromium/chromecast/public/media/decoder_config.h157
-rw-r--r--chromium/chromecast/public/osd_plane.h40
-rw-r--r--chromium/chromecast/public/osd_plane_shlib.h25
-rw-r--r--chromium/chromecast/public/osd_surface.h56
-rw-r--r--chromium/chromecast/renderer/DEPS4
-rw-r--r--chromium/chromecast/renderer/cast_content_renderer_client.cc147
-rw-r--r--chromium/chromecast/renderer/cast_content_renderer_client.h45
-rw-r--r--chromium/chromecast/renderer/cast_content_renderer_client_simple.cc21
-rw-r--r--chromium/chromecast/renderer/cast_media_load_deferrer.cc27
-rw-r--r--chromium/chromecast/renderer/cast_media_load_deferrer.h35
-rw-r--r--chromium/chromecast/renderer/cast_render_process_observer.cc64
-rw-r--r--chromium/chromecast/renderer/cast_render_process_observer.h51
-rw-r--r--chromium/chromecast/renderer/key_systems_cast.cc49
-rw-r--r--chromium/chromecast/renderer/key_systems_cast.h8
-rw-r--r--chromium/chromecast/renderer/media/audio_pipeline_proxy.cc311
-rw-r--r--chromium/chromecast/renderer/media/audio_pipeline_proxy.h79
-rw-r--r--chromium/chromecast/renderer/media/capabilities_message_filter.cc32
-rw-r--r--chromium/chromecast/renderer/media/capabilities_message_filter.h29
-rw-r--r--chromium/chromecast/renderer/media/chromecast_media_renderer_factory.cc76
-rw-r--r--chromium/chromecast/renderer/media/chromecast_media_renderer_factory.h44
-rw-r--r--chromium/chromecast/renderer/media/cma_message_filter_proxy.cc272
-rw-r--r--chromium/chromecast/renderer/media/cma_message_filter_proxy.h135
-rw-r--r--chromium/chromecast/renderer/media/cma_renderer_unittest.cc125
-rw-r--r--chromium/chromecast/renderer/media/media_channel_proxy.cc79
-rw-r--r--chromium/chromecast/renderer/media/media_channel_proxy.h68
-rw-r--r--chromium/chromecast/renderer/media/media_pipeline_proxy.cc283
-rw-r--r--chromium/chromecast/renderer/media/media_pipeline_proxy.h85
-rw-r--r--chromium/chromecast/renderer/media/video_pipeline_proxy.cc299
-rw-r--r--chromium/chromecast/renderer/media/video_pipeline_proxy.h76
-rwxr-xr-xchromium/chromecast/tools/build/generate_test_lists.py130
-rwxr-xr-xchromium/chromecast/tools/trace.py185
275 files changed, 13793 insertions, 1850 deletions
diff --git a/chromium/chromecast/BUILD.gn b/chromium/chromecast/BUILD.gn
new file mode 100644
index 00000000000..6169cf86808
--- /dev/null
+++ b/chromium/chromecast/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chromecast/chromecast.gni")
+
+config("config") {
+ defines = []
+
+ if (use_playready) {
+ defines += [ "PLAYREADY_CDM_AVAILABLE" ]
+ }
+}
+
+component("chromecast") {
+ deps = [
+ "//chromecast/base",
+ "//chromecast/base/metrics",
+ "//chromecast/media",
+ ]
+}
diff --git a/chromium/chromecast/DEPS b/chromium/chromecast/DEPS
index d2783405985..eae26b0f640 100644
--- a/chromium/chromecast/DEPS
+++ b/chromium/chromecast/DEPS
@@ -5,6 +5,7 @@ include_rules = [
# sub-directory within chromecast/.
"-chromecast",
"+chromecast/base",
+ "+chromecast/public",
# Other Chromecast-wide dependencies.
"+content/public/common",
diff --git a/chromium/chromecast/OWNERS b/chromium/chromecast/OWNERS
index 45c91ccae95..470605e46e3 100644
--- a/chromium/chromecast/OWNERS
+++ b/chromium/chromecast/OWNERS
@@ -1,4 +1,3 @@
damienv@chromium.org
gunsch@chromium.org
-kolla@chromium.org
lcwu@chromium.org
diff --git a/chromium/chromecast/android/DEPS b/chromium/chromecast/android/DEPS
index 9659c0589ed..df718c8e423 100644
--- a/chromium/chromecast/android/DEPS
+++ b/chromium/chromecast/android/DEPS
@@ -3,4 +3,5 @@ include_rules = [
"+chromecast/android",
"+chromecast/browser/android",
"+chromecast/crash/android",
+ "+components/external_video_surface",
]
diff --git a/chromium/chromecast/app/cast_main_delegate.cc b/chromium/chromecast/app/cast_main_delegate.cc
index 78e4d55e0c5..58c7507eaf3 100644
--- a/chromium/chromecast/app/cast_main_delegate.cc
+++ b/chromium/chromecast/app/cast_main_delegate.cc
@@ -4,16 +4,21 @@
#include "chromecast/app/cast_main_delegate.h"
+#include <string>
+
#include "base/command_line.h"
#include "base/cpu.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/posix/global_descriptors.h"
+#include "chromecast/base/cast_paths.h"
#include "chromecast/browser/cast_content_browser_client.h"
-#include "chromecast/common/cast_paths.h"
#include "chromecast/common/cast_resource_delegate.h"
#include "chromecast/common/global_descriptors.h"
+#include "chromecast/crash/cast_crash_reporter_client.h"
#include "chromecast/renderer/cast_content_renderer_client.h"
+#include "components/crash/app/crash_reporter_client.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/common/content_switches.h"
#include "ui/base/resource/resource_bundle.h"
@@ -22,6 +27,15 @@
#include "chromecast/crash/android/crash_handler.h"
#endif // defined(OS_ANDROID)
+namespace {
+
+#if !defined(OS_ANDROID)
+base::LazyInstance<chromecast::CastCrashReporterClient>::Leaky
+ g_crash_reporter_client = LAZY_INSTANCE_INITIALIZER;
+#endif // !defined(OS_ANDROID)
+
+} // namespace
+
namespace chromecast {
namespace shell {
@@ -69,6 +83,12 @@ void CastMainDelegate::PreSandboxStartup() {
base::FilePath log_file;
PathService::Get(FILE_CAST_ANDROID_LOG, &log_file);
chromecast::CrashHandler::Initialize(process_type, log_file);
+#else
+ crash_reporter::SetCrashReporterClient(g_crash_reporter_client.Pointer());
+
+ if (process_type != switches::kZygoteProcess) {
+ CastCrashReporterClient::InitCrashReporter(process_type);
+ }
#endif // defined(OS_ANDROID)
InitializeResourceBundle();
@@ -92,6 +112,10 @@ int CastMainDelegate::RunProcess(
#if !defined(OS_ANDROID)
void CastMainDelegate::ZygoteForked() {
+ const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
+ std::string process_type =
+ command_line->GetSwitchValueASCII(switches::kProcessType);
+ CastCrashReporterClient::InitCrashReporter(process_type);
}
#endif // !defined(OS_ANDROID)
diff --git a/chromium/chromecast/app/cast_main_delegate.h b/chromium/chromecast/app/cast_main_delegate.h
index d078655f69d..0fe77690126 100644
--- a/chromium/chromecast/app/cast_main_delegate.h
+++ b/chromium/chromecast/app/cast_main_delegate.h
@@ -26,20 +26,19 @@ class CastContentRendererClient;
class CastMainDelegate : public content::ContentMainDelegate {
public:
CastMainDelegate();
- virtual ~CastMainDelegate();
+ ~CastMainDelegate() override;
// content::ContentMainDelegate implementation:
- virtual bool BasicStartupComplete(int* exit_code) override;
- virtual void PreSandboxStartup() override;
- virtual int RunProcess(
+ bool BasicStartupComplete(int* exit_code) override;
+ void PreSandboxStartup() override;
+ int RunProcess(
const std::string& process_type,
const content::MainFunctionParams& main_function_params) override;
#if !defined(OS_ANDROID)
- virtual void ZygoteForked() override;
+ void ZygoteForked() override;
#endif // !defined(OS_ANDROID)
- virtual content::ContentBrowserClient* CreateContentBrowserClient() override;
- virtual content::ContentRendererClient*
- CreateContentRendererClient() override;
+ content::ContentBrowserClient* CreateContentBrowserClient() override;
+ content::ContentRendererClient* CreateContentRendererClient() override;
private:
void InitializeResourceBundle();
diff --git a/chromium/chromecast/app/resources/shell_devtools_discovery_page.html b/chromium/chromecast/app/resources/shell_devtools_discovery_page.html
index 09bb9c438a8..f8d69d9523f 100644
--- a/chromium/chromecast/app/resources/shell_devtools_discovery_page.html
+++ b/chromium/chromecast/app/resources/shell_devtools_discovery_page.html
@@ -2,18 +2,6 @@
<head>
<title>Cast shell remote debugging</title>
<style>
- .local-ui-link {
- background-color: #eee;
- border: 1px solid #ccc;
- color: #333;
- display: block;
- font-family: monospace;
- font-size: 11px;
- margin: 4px;
- padding: 4px;
- width: 100%;
- }
-
.help {
font-size: 11px;
}
@@ -50,15 +38,6 @@ function appendItem(metadata) {
frontend_link.textContent = 'Remote Debugging (AppEngine)'
frontend_link.href = metadata.devtoolsFrontendUrl;
item_container.appendChild(frontend_link);
-
- var devtools_protocol_link = document.createElement('textarea');
- devtools_protocol_link.className = 'local-ui-link';
- devtools_protocol_link.value = metadata.devtoolsFrontendUrl.replace(
- "https://chrome-devtools-frontend.appspot.com",
- "chrome-devtools://devtools/remote");
- // Highlight text when clicked.
- devtools_protocol_link.onclick = function() { this.select(); }
- item_container.appendChild(devtools_protocol_link);
} else {
frontend_header.textContent += " (already has active debugging session)";
}
@@ -69,16 +48,9 @@ function appendItem(metadata) {
<h3>Help</h3>
<div id="help">
- Note: there are two debugging options presented for each page above. Either
- is a valid way to initiate a remote debugging session.
- <ul>
- <li>For the first option (link), you may have to select the shield icon in
- the address bar to establish a connection. See the <a
- href="https://support.google.com/chrome/answer/1342714?hl=en">help
- center</a> for more information.</li>
- <li>For the second option (textarea), simply copy/paste the URL into
- Chrome's URL bar.</li>
- </ul>
+ You may have to select the shield icon in the address bar to establish a connection.
+ See the <a href="https://support.google.com/chrome/answer/1342714?hl=en">help
+ center</a> for more information.
</div>
</body>
diff --git a/chromium/chromecast/base/BUILD.gn b/chromium/chromecast/base/BUILD.gn
new file mode 100644
index 00000000000..b105a71926a
--- /dev/null
+++ b/chromium/chromecast/base/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("base") {
+ sources = [
+ "cast_paths.cc",
+ "cast_paths.h",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/common/cast_paths.cc b/chromium/chromecast/base/cast_paths.cc
index d5d471ce97a..ce726848dcc 100644
--- a/chromium/chromecast/common/cast_paths.cc
+++ b/chromium/chromecast/base/cast_paths.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chromecast/common/cast_paths.h"
+#include "chromecast/base/cast_paths.h"
#include "base/base_paths.h"
#include "base/files/file_path.h"
diff --git a/chromium/chromecast/common/cast_paths.h b/chromium/chromecast/base/cast_paths.h
index 5ab156c20fb..11433a407ef 100644
--- a/chromium/chromecast/common/cast_paths.h
+++ b/chromium/chromecast/base/cast_paths.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROMECAST_COMMON_CAST_PATHS_H_
-#define CHROMECAST_COMMON_CAST_PATHS_H_
+#ifndef CHROMECAST_BASE_CAST_PATHS_H_
+#define CHROMECAST_BASE_CAST_PATHS_H_
#include "build/build_config.h"
@@ -31,4 +31,4 @@ void RegisterPathProvider();
} // namespace chromecast
-#endif // CHROMECAST_COMMON_CAST_PATHS_H_
+#endif // CHROMECAST_BASE_CAST_PATHS_H_
diff --git a/chromium/chromecast/base/cast_sys_info_dummy.cc b/chromium/chromecast/base/cast_sys_info_dummy.cc
new file mode 100644
index 00000000000..57e8beae188
--- /dev/null
+++ b/chromium/chromecast/base/cast_sys_info_dummy.cc
@@ -0,0 +1,79 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/base/cast_sys_info_dummy.h"
+
+namespace chromecast {
+
+CastSysInfoDummy::CastSysInfoDummy() {
+}
+
+CastSysInfoDummy::~CastSysInfoDummy() {
+}
+
+CastSysInfo::BuildType CastSysInfoDummy::GetBuildType() {
+ return BUILD_ENG;
+}
+
+std::string CastSysInfoDummy::GetSystemReleaseChannel() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetSerialNumber() {
+ return "dummy.serial.number";
+}
+
+std::string CastSysInfoDummy::GetProductName() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetDeviceModel() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetBoardName() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetBoardRevision() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetManufacturer() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetSystemBuildNumber() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetFactoryCountry() {
+ return "US";
+}
+
+std::string CastSysInfoDummy::GetFactoryLocale(std::string* second_locale) {
+ return "en-US";
+}
+
+std::string CastSysInfoDummy::GetWifiInterface() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetApInterface() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetGlVendor() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetGlRenderer() {
+ return "";
+}
+
+std::string CastSysInfoDummy::GetGlVersion() {
+ return "";
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/base/cast_sys_info_dummy.h b/chromium/chromecast/base/cast_sys_info_dummy.h
new file mode 100644
index 00000000000..89a8b8beeb9
--- /dev/null
+++ b/chromium/chromecast/base/cast_sys_info_dummy.h
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BASE_CAST_SYS_INFO_DUMMY_H_
+#define CHROMECAST_BASE_CAST_SYS_INFO_DUMMY_H_
+
+#include "base/macros.h"
+#include "chromecast/public/cast_sys_info.h"
+
+namespace chromecast {
+
+class CastSysInfoDummy : public CastSysInfo {
+ public:
+ CastSysInfoDummy();
+ ~CastSysInfoDummy() override;
+
+ // CastSysInfo implementation:
+ BuildType GetBuildType() override;
+ std::string GetSystemReleaseChannel() override;
+ std::string GetSerialNumber() override;
+ std::string GetProductName() override;
+ std::string GetDeviceModel() override;
+ std::string GetBoardName() override;
+ std::string GetBoardRevision() override;
+ std::string GetManufacturer() override;
+ std::string GetSystemBuildNumber() override;
+ std::string GetFactoryCountry() override;
+ std::string GetFactoryLocale(std::string* second_locale) override;
+ std::string GetWifiInterface() override;
+ std::string GetApInterface() override;
+ std::string GetGlVendor() override;
+ std::string GetGlRenderer() override;
+ std::string GetGlVersion() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CastSysInfoDummy);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_BASE_CAST_SYS_INFO_DUMMY_H_
diff --git a/chromium/chromecast/base/cast_sys_info_util.h b/chromium/chromecast/base/cast_sys_info_util.h
new file mode 100644
index 00000000000..05ca069d655
--- /dev/null
+++ b/chromium/chromecast/base/cast_sys_info_util.h
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BASE_CAST_SYS_INFO_UTIL_H_
+#define CHROMECAST_BASE_CAST_SYS_INFO_UTIL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace chromecast {
+
+class CastSysInfo;
+
+scoped_ptr<CastSysInfo> CreateSysInfo();
+
+} // namespace chromecast
+
+#endif // CHROMECAST_BASE_CAST_SYS_INFO_UTIL_H_
diff --git a/chromium/chromecast/base/cast_sys_info_util_simple.cc b/chromium/chromecast/base/cast_sys_info_util_simple.cc
new file mode 100644
index 00000000000..68ab9dffb2c
--- /dev/null
+++ b/chromium/chromecast/base/cast_sys_info_util_simple.cc
@@ -0,0 +1,16 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/base/cast_sys_info_util.h"
+
+#include "chromecast/base/cast_sys_info_dummy.h"
+
+namespace chromecast {
+
+// static
+scoped_ptr<CastSysInfo> CreateSysInfo() {
+ return make_scoped_ptr(new CastSysInfoDummy());
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/base/metrics/BUILD.gn b/chromium/chromecast/base/metrics/BUILD.gn
new file mode 100644
index 00000000000..7ed81a562fe
--- /dev/null
+++ b/chromium/chromecast/base/metrics/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("metrics") {
+ sources = [
+ "cast_histograms.h",
+ "cast_metrics_helper.cc",
+ "cast_metrics_helper.h",
+ "grouped_histogram.cc",
+ "grouped_histogram.h",
+ ]
+
+ deps = [
+ "//chromecast/base",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
+
+source_set("test_support") {
+ testonly = true
+
+ sources = [
+ "cast_metrics_test_helper.cc",
+ "cast_metrics_test_helper.h",
+ ]
+
+ deps = [
+ ":metrics",
+ "//chromecast/base",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/base/metrics/cast_histograms.h b/chromium/chromecast/base/metrics/cast_histograms.h
index 4907c1a84ef..19cb98e7cfb 100644
--- a/chromium/chromecast/base/metrics/cast_histograms.h
+++ b/chromium/chromecast/base/metrics/cast_histograms.h
@@ -12,15 +12,14 @@
// through base::subtle::Release_Store() and base::subtle::Acquire_Load().
// If the histogram name changes between subsequent calls, use this non-cached
// version that always calls histogram_factory_get_invocation.
-#define STATIC_HISTOGRAM_POINTER_BLOCK_NO_CACHE( \
- constant_histogram_name, \
- histogram_add_method_invocation, \
- histogram_factory_get_invocation) \
- do { \
+#define STATIC_HISTOGRAM_POINTER_BLOCK_NO_CACHE( \
+ constant_histogram_name, histogram_add_method_invocation, \
+ histogram_factory_get_invocation) \
+ do { \
base::HistogramBase* histogram_pointer = histogram_factory_get_invocation; \
- if (DCHECK_IS_ON) \
- histogram_pointer->CheckName(constant_histogram_name); \
- histogram_pointer->histogram_add_method_invocation; \
+ if (DCHECK_IS_ON()) \
+ histogram_pointer->CheckName(constant_histogram_name); \
+ histogram_pointer->histogram_add_method_invocation; \
} while (0)
#define UMA_HISTOGRAM_CUSTOM_TIMES_NO_CACHE( \
@@ -40,10 +39,4 @@
base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag))
-#define UMA_HISTOGRAM_ENUMERATION_COUNT_NO_CACHE(name, sample, count, \
- boundary_value) \
- STATIC_HISTOGRAM_POINTER_BLOCK_NO_CACHE(name, AddCount(sample, count), \
- base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
- boundary_value + 1, base::HistogramBase::kUmaTargetedHistogramFlag))
-
#endif // CHROMECAST_BASE_METRICS_CAST_HISTOGRAMS_H_
diff --git a/chromium/chromecast/base/metrics/cast_metrics_helper.cc b/chromium/chromecast/base/metrics/cast_metrics_helper.cc
index e4923552e1f..85cdfe8931e 100644
--- a/chromium/chromecast/base/metrics/cast_metrics_helper.cc
+++ b/chromium/chromecast/base/metrics/cast_metrics_helper.cc
@@ -10,7 +10,10 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/metrics/user_metrics.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "chromecast/base/metrics/cast_histograms.h"
+#include "chromecast/base/metrics/grouped_histogram.h"
namespace chromecast {
namespace metrics {
@@ -35,8 +38,55 @@ const int kDisplayedFramesPerSecondPeriod = 1000000;
// Sample every 5 seconds, represented in microseconds.
const int kNominalVideoSamplePeriod = 5000000;
+const char kMetricsNameAppInfoDelimiter = '#';
+
} // namespace
+// static
+
+// NOTE(gfhuang): This is a hacky way to encode/decode app infos into a
+// string. Mainly because it's hard to add another metrics serialization type
+// into components/metrics/serialization/.
+// static
+bool CastMetricsHelper::DecodeAppInfoFromMetricsName(
+ const std::string& metrics_name,
+ std::string* action_name,
+ std::string* app_id,
+ std::string* session_id,
+ std::string* sdk_version) {
+ DCHECK(action_name);
+ DCHECK(app_id);
+ DCHECK(session_id);
+ DCHECK(sdk_version);
+ if (metrics_name.find(kMetricsNameAppInfoDelimiter) == std::string::npos)
+ return false;
+
+ std::vector<std::string> tokens;
+ base::SplitString(metrics_name, kMetricsNameAppInfoDelimiter, &tokens);
+ DCHECK_EQ(tokens.size(), 4u);
+ // The order of tokens should match EncodeAppInfoIntoMetricsName().
+ *action_name = tokens[0];
+ *app_id = tokens[1];
+ *session_id = tokens[2];
+ *sdk_version = tokens[3];
+ return true;
+}
+
+// static
+std::string CastMetricsHelper::EncodeAppInfoIntoMetricsName(
+ const std::string& action_name,
+ const std::string& app_id,
+ const std::string& session_id,
+ const std::string& sdk_version) {
+ std::vector<std::string> parts;
+ parts.push_back(action_name);
+ parts.push_back(app_id);
+ parts.push_back(session_id);
+ parts.push_back(sdk_version);
+ return JoinString(parts, kMetricsNameAppInfoDelimiter);
+}
+
+// static
CastMetricsHelper* CastMetricsHelper::GetInstance() {
DCHECK(g_instance);
return g_instance;
@@ -45,7 +95,8 @@ CastMetricsHelper* CastMetricsHelper::GetInstance() {
CastMetricsHelper::CastMetricsHelper(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy)
: message_loop_proxy_(message_loop_proxy),
- metrics_sink_(NULL) {
+ metrics_sink_(NULL),
+ record_action_callback_(base::Bind(&base::RecordComputedAction)) {
DCHECK(message_loop_proxy_.get());
DCHECK(!g_instance);
g_instance = this;
@@ -62,21 +113,49 @@ CastMetricsHelper::~CastMetricsHelper() {
g_instance = NULL;
}
-void CastMetricsHelper::TagAppStart(const std::string& arg_app_name) {
- MAKE_SURE_THREAD(TagAppStart, arg_app_name);
- app_name_ = arg_app_name;
+void CastMetricsHelper::UpdateCurrentAppInfo(const std::string& app_id,
+ const std::string& session_id) {
+ MAKE_SURE_THREAD(UpdateCurrentAppInfo, app_id, session_id);
+ app_id_ = app_id;
+ session_id_ = session_id;
app_start_time_ = base::TimeTicks::Now();
new_startup_time_ = true;
+ TagAppStartForGroupedHistograms(app_id_);
+ sdk_version_.clear();
+}
+
+void CastMetricsHelper::UpdateSDKInfo(const std::string& sdk_version) {
+ MAKE_SURE_THREAD(UpdateSDKInfo, sdk_version);
+ sdk_version_ = sdk_version;
}
void CastMetricsHelper::LogMediaPlay() {
MAKE_SURE_THREAD(LogMediaPlay);
- base::RecordComputedAction(GetMetricsNameWithAppName("MediaPlay", ""));
+ RecordSimpleAction(EncodeAppInfoIntoMetricsName(
+ "MediaPlay",
+ app_id_,
+ session_id_,
+ sdk_version_));
}
void CastMetricsHelper::LogMediaPause() {
MAKE_SURE_THREAD(LogMediaPause);
- base::RecordComputedAction(GetMetricsNameWithAppName("MediaPause", ""));
+ RecordSimpleAction(EncodeAppInfoIntoMetricsName(
+ "MediaPause",
+ app_id_,
+ session_id_,
+ sdk_version_));
+}
+
+void CastMetricsHelper::LogTimeToFirstPaint() {
+ MAKE_SURE_THREAD(LogTimeToFirstPaint);
+ if (app_id_.empty())
+ return;
+ base::TimeDelta launch_time = base::TimeTicks::Now() - app_start_time_;
+ const std::string uma_name(GetMetricsNameWithAppName("Startup",
+ "TimeToFirstPaint"));
+ LogMediumTimeHistogramEvent(uma_name, launch_time);
+ LOG(INFO) << uma_name << " is " << launch_time.InSecondsF() << " seconds.";
}
void CastMetricsHelper::LogTimeToDisplayVideo() {
@@ -174,10 +253,10 @@ std::string CastMetricsHelper::GetMetricsNameWithAppName(
const std::string& suffix) const {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
std::string metrics_name(prefix);
- if (!app_name_.empty()) {
+ if (!app_id_.empty()) {
if (!metrics_name.empty())
metrics_name.push_back('.');
- metrics_name.append(app_name_);
+ metrics_name.append(app_id_);
}
if (!suffix.empty()) {
if (!metrics_name.empty())
@@ -192,6 +271,22 @@ void CastMetricsHelper::SetMetricsSink(MetricsSink* delegate) {
metrics_sink_ = delegate;
}
+void CastMetricsHelper::SetRecordActionCallback(
+ const RecordActionCallback& callback) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ record_action_callback_ = callback;
+}
+
+void CastMetricsHelper::RecordSimpleAction(const std::string& action) {
+ MAKE_SURE_THREAD(RecordSimpleAction, action);
+
+ if (metrics_sink_) {
+ metrics_sink_->OnAction(action);
+ } else {
+ record_action_callback_.Run(action);
+ }
+}
+
void CastMetricsHelper::LogEnumerationHistogramEvent(
const std::string& name, int value, int num_buckets) {
MAKE_SURE_THREAD(LogEnumerationHistogramEvent, name, value, num_buckets);
diff --git a/chromium/chromecast/base/metrics/cast_metrics_helper.h b/chromium/chromecast/base/metrics/cast_metrics_helper.h
index 4f06a46e1c0..144d9dc3b32 100644
--- a/chromium/chromecast/base/metrics/cast_metrics_helper.h
+++ b/chromium/chromecast/base/metrics/cast_metrics_helper.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
@@ -28,10 +29,13 @@ class CastMetricsHelper {
kAbortedBuffering,
};
+ typedef base::Callback<void(const std::string&)> RecordActionCallback;
+
class MetricsSink {
public:
virtual ~MetricsSink() {}
+ virtual void OnAction(const std::string& action) = 0;
virtual void OnEnumerationEvent(const std::string& name,
int value, int num_buckets) = 0;
virtual void OnTimeEvent(const std::string& name,
@@ -41,19 +45,40 @@ class CastMetricsHelper {
int num_buckets) = 0;
};
+ // Decodes action_name/app_id/session_id/sdk_version from metrics name.
+ // Return false if the metrics name is not generated from
+ // EncodeAppInfoIntoMetricsName() with correct format.
+ static bool DecodeAppInfoFromMetricsName(
+ const std::string& metrics_name,
+ std::string* action_name,
+ std::string* app_id,
+ std::string* session_id,
+ std::string* sdk_version);
+
static CastMetricsHelper* GetInstance();
explicit CastMetricsHelper(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy);
virtual ~CastMetricsHelper();
- // This function stores the name and startup time of the active application.
- virtual void TagAppStart(const std::string& app_name);
+ // This function updates the info and stores the startup time of the current
+ // active application
+ virtual void UpdateCurrentAppInfo(const std::string& app_id,
+ const std::string& session_id);
+ // This function updates the sdk version of the current active application
+ virtual void UpdateSDKInfo(const std::string& sdk_version);
// Logs UMA record for media play/pause user actions.
virtual void LogMediaPlay();
virtual void LogMediaPause();
+ // Logs a simple UMA user action.
+ // This is used as an in-place replacement of content::RecordComputedAction().
+ virtual void RecordSimpleAction(const std::string& action);
+
+ // Logs UMA record of the time the app made its first paint.
+ virtual void LogTimeToFirstPaint();
+
// Logs UMA record of the elapsed time from the app launch
// to the time first video frame is displayed.
virtual void LogTimeToDisplayVideo();
@@ -81,6 +106,11 @@ class CastMetricsHelper {
// Caller retains ownership of MetricsSink.
virtual void SetMetricsSink(MetricsSink* delegate);
+ // Sets a default callback to record user action when MetricsSink is not set.
+ // This function could be called multiple times (in unittests), and
+ // CastMetricsHelper only honors the last one.
+ virtual void SetRecordActionCallback(const RecordActionCallback& callback);
+
protected:
// Creates a CastMetricsHelper instance with no MessageLoopProxy. This should
// only be used by tests, since invoking any non-overridden methods on this
@@ -88,6 +118,12 @@ class CastMetricsHelper {
CastMetricsHelper();
private:
+ static std::string EncodeAppInfoIntoMetricsName(
+ const std::string& action_name,
+ const std::string& app_id,
+ const std::string& session_id,
+ const std::string& sdk_version);
+
void LogEnumerationHistogramEvent(const std::string& name,
int value, int num_buckets);
void LogTimeHistogramEvent(const std::string& name,
@@ -103,8 +139,10 @@ class CastMetricsHelper {
// Start time of the most recent app.
base::TimeTicks app_start_time_;
- // Currently running app name. Used to construct histogram name.
- std::string app_name_;
+ // Currently running app id. Used to construct histogram name.
+ std::string app_id_;
+ std::string session_id_;
+ std::string sdk_version_;
// Whether a new app start time has been stored but not recorded.
// After the startup time has been used to generate an UMA event,
@@ -114,6 +152,8 @@ class CastMetricsHelper {
base::TimeTicks previous_video_stat_sample_time_;
MetricsSink* metrics_sink_;
+ // Default RecordAction callback when metrics_sink_ is not set.
+ RecordActionCallback record_action_callback_;
DISALLOW_COPY_AND_ASSIGN(CastMetricsHelper);
};
diff --git a/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc b/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc
index 6aa2a86a6c8..c78abe10409 100644
--- a/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc
+++ b/chromium/chromecast/base/metrics/cast_metrics_test_helper.cc
@@ -16,21 +16,23 @@ namespace {
class CastMetricsHelperStub : public CastMetricsHelper {
public:
CastMetricsHelperStub();
- virtual ~CastMetricsHelperStub();
-
- virtual void TagAppStart(const std::string& arg_app_name) override;
- virtual void LogMediaPlay() override;
- virtual void LogMediaPause() override;
- virtual void LogTimeToDisplayVideo() override;
- virtual void LogTimeToBufferAv(BufferingType buffering_type,
- base::TimeDelta time) override;
- virtual void ResetVideoFrameSampling() override;
- virtual void LogFramesPer5Seconds(
+ ~CastMetricsHelperStub() override;
+
+ void UpdateCurrentAppInfo(const std::string& app_id,
+ const std::string& session_id) override;
+ void UpdateSDKInfo(const std::string& sdk_version) override;
+ void LogMediaPlay() override;
+ void LogMediaPause() override;
+ void LogTimeToDisplayVideo() override;
+ void LogTimeToBufferAv(BufferingType buffering_type,
+ base::TimeDelta time) override;
+ void ResetVideoFrameSampling() override;
+ void LogFramesPer5Seconds(
int displayed_frames, int dropped_frames,
int delayed_frames, int error_frames) override;
- virtual std::string GetMetricsNameWithAppName(
+ std::string GetMetricsNameWithAppName(
const std::string& prefix, const std::string& suffix) const override;
- virtual void SetMetricsSink(MetricsSink* delegate) override;
+ void SetMetricsSink(MetricsSink* delegate) override;
private:
DISALLOW_COPY_AND_ASSIGN(CastMetricsHelperStub);
@@ -49,7 +51,12 @@ CastMetricsHelperStub::~CastMetricsHelperStub() {
stub_instance_exists = false;
}
-void CastMetricsHelperStub::TagAppStart(const std::string& arg_app_name) {
+void CastMetricsHelperStub::UpdateCurrentAppInfo(
+ const std::string& app_id,
+ const std::string& session_id) {
+}
+
+void CastMetricsHelperStub::UpdateSDKInfo(const std::string& sdk_version) {
}
void CastMetricsHelperStub::LogMediaPlay() {
diff --git a/chromium/chromecast/base/metrics/grouped_histogram.cc b/chromium/chromecast/base/metrics/grouped_histogram.cc
new file mode 100644
index 00000000000..83188506694
--- /dev/null
+++ b/chromium/chromecast/base/metrics/grouped_histogram.cc
@@ -0,0 +1,181 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/base/metrics/grouped_histogram.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+
+namespace chromecast {
+namespace metrics {
+
+namespace {
+
+const char kAppNameErrorNoApp[] = "ERROR_NO_APP_REGISTERED";
+
+// Current app name guarded by lock.
+struct CurrentAppNameWithLock {
+ base::Lock lock;
+ std::string app_name;
+};
+
+base::LazyInstance<CurrentAppNameWithLock> g_current_app =
+ LAZY_INSTANCE_INITIALIZER;
+
+std::string GetAppName() {
+ base::AutoLock lock(g_current_app.Get().lock);
+ const std::string& app_name = g_current_app.Get().app_name;
+ return app_name.empty() ? kAppNameErrorNoApp : app_name;
+}
+
+struct HistogramArgs {
+ const char* name;
+ int minimum;
+ int maximum;
+ size_t bucket_count;
+};
+
+// List of metrics to collect using a GroupedHistogram.
+//
+// When adding more Histograms to this list, find the source of the
+// Histogram and look for the construction arguments it uses to add it in.
+const HistogramArgs kHistogramsToGroup[] = {
+ {
+ "DNS.TotalTime",
+ 1,
+ 1000 * 60 * 60,
+ 100,
+ },
+ {
+ "Net.DNS_Resolution_And_TCP_Connection_Latency2",
+ 1,
+ 1000 * 60 * 10,
+ 100,
+ },
+ {
+ "Net.SSL_Connection_Latency2",
+ 1,
+ 1000 * 60,
+ 100,
+ },
+ {
+ "Net.TCP_Connection_Latency",
+ 1,
+ 1000 * 60 * 10,
+ 100,
+ },
+ {
+ "Net.HttpJob.TotalTime",
+ 1,
+ 1000 * 10,
+ 50,
+ },
+};
+
+// This class is used to override a Histogram to generate per-app metrics.
+// It intercepts calls to Add() for a given metric and generates new metrics
+// of the form "<metric-name>.<app-name>".
+class GroupedHistogram : public base::Histogram {
+ public:
+ GroupedHistogram(const std::string& metric_to_override,
+ Sample minimum,
+ Sample maximum,
+ const base::BucketRanges* ranges)
+ : Histogram(metric_to_override, minimum, maximum, ranges),
+ metric_to_group_(metric_to_override),
+ minimum_(minimum),
+ maximum_(maximum),
+ bucket_count_(ranges->bucket_count()) {
+ }
+
+ ~GroupedHistogram() override {
+ }
+
+ // base::Histogram implementation:
+ void Add(Sample value) override {
+ Histogram::Add(value);
+ std::string name(base::StringPrintf("%s.%s",
+ histogram_name().c_str(),
+ GetAppName().c_str()));
+ HistogramBase* grouped_histogram =
+ base::Histogram::FactoryGet(name,
+ minimum_,
+ maximum_,
+ bucket_count_,
+ flags());
+ DCHECK(grouped_histogram);
+ grouped_histogram->Add(value);
+ }
+
+ private:
+ // Saved construction arguments for reconstructing the Histogram later (with
+ // a suffixed app name).
+ std::string metric_to_group_;
+ Sample minimum_;
+ Sample maximum_;
+ size_t bucket_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(GroupedHistogram);
+};
+
+// Registers a GroupedHistogram with StatisticsRecorder. Must be called
+// before any Histogram of the same name has been used.
+// It acts similarly to Histogram::FactoryGet but checks that
+// the histogram is being newly created and does not already exist.
+void PreregisterHistogram(const std::string& name,
+ GroupedHistogram::Sample minimum,
+ GroupedHistogram::Sample maximum,
+ size_t bucket_count,
+ int32 flags) {
+ DCHECK(base::StatisticsRecorder::IsActive());
+ DCHECK(base::Histogram::InspectConstructionArguments(
+ name, &minimum, &maximum, &bucket_count));
+ DCHECK(!base::StatisticsRecorder::FindHistogram(name))
+ << "Failed to preregister " << name << ", Histogram already exists.";
+
+ // To avoid racy destruction at shutdown, the following will be leaked.
+ base::BucketRanges* ranges = new base::BucketRanges(bucket_count + 1);
+ base::Histogram::InitializeBucketRanges(minimum, maximum, ranges);
+ const base::BucketRanges* registered_ranges =
+ base::StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
+
+ GroupedHistogram* tentative_histogram =
+ new GroupedHistogram(name, minimum, maximum, registered_ranges);
+
+ tentative_histogram->SetFlags(flags);
+ base::HistogramBase* histogram =
+ base::StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
+
+ DCHECK_EQ(histogram, tentative_histogram);
+ DCHECK_EQ(base::HISTOGRAM, histogram->GetHistogramType());
+ DCHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count));
+}
+
+} // namespace
+
+void PreregisterAllGroupedHistograms() {
+ base::StatisticsRecorder::Initialize();
+ for (size_t i = 0; i < arraysize(kHistogramsToGroup); ++i) {
+ PreregisterHistogram(
+ kHistogramsToGroup[i].name,
+ kHistogramsToGroup[i].minimum,
+ kHistogramsToGroup[i].maximum,
+ kHistogramsToGroup[i].bucket_count,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ }
+}
+
+void TagAppStartForGroupedHistograms(const std::string& app_name) {
+ base::AutoLock lock(g_current_app.Get().lock);
+ g_current_app.Get().app_name = app_name;
+}
+
+} // namespace metrics
+} // namespace chromecast
diff --git a/chromium/chromecast/base/metrics/grouped_histogram.h b/chromium/chromecast/base/metrics/grouped_histogram.h
new file mode 100644
index 00000000000..b5202e621f1
--- /dev/null
+++ b/chromium/chromecast/base/metrics/grouped_histogram.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BASE_METRICS_GROUPED_HISTOGRAM_H_
+#define CHROMECAST_BASE_METRICS_GROUPED_HISTOGRAM_H_
+
+#include <string>
+
+namespace chromecast {
+namespace metrics {
+
+// Registers a predefined list of histograms to be collected per-app. Must be
+// called before any histograms of the same name are used or registration will
+// fail.
+void PreregisterAllGroupedHistograms();
+
+// Sets the current app name to be used for subsequent grouped histogram
+// samples (a new metric is generated with the app name as a suffix).
+void TagAppStartForGroupedHistograms(const std::string& app_name);
+
+} // namespace metrics
+} // namespace chromecast
+
+#endif // CHROMECAST_BASE_METRICS_GROUPED_HISTOGRAM_H_
diff --git a/chromium/chromecast/base/serializers.cc b/chromium/chromecast/base/serializers.cc
new file mode 100644
index 00000000000..366a5d2f59b
--- /dev/null
+++ b/chromium/chromecast/base/serializers.cc
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/base/serializers.h"
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/logging.h"
+
+namespace chromecast {
+
+scoped_ptr<base::Value> DeserializeFromJson(const std::string& text) {
+ JSONStringValueDeserializer deserializer(text);
+
+ int error_code;
+ std::string error_msg;
+ scoped_ptr<base::Value> value(
+ deserializer.Deserialize(&error_code, &error_msg));
+ DLOG_IF(ERROR, !value) << "JSON error " << error_code << ":" << error_msg;
+
+ // Value will hold the nullptr in case of an error.
+ return value.Pass();
+}
+
+scoped_ptr<std::string> SerializeToJson(const base::Value& value) {
+ scoped_ptr<std::string> json_str(new std::string());
+ JSONStringValueSerializer serializer(json_str.get());
+ if (!serializer.Serialize(value))
+ json_str.reset(nullptr);
+ return json_str.Pass();
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/base/serializers.h b/chromium/chromecast/base/serializers.h
new file mode 100644
index 00000000000..df278fdbc0f
--- /dev/null
+++ b/chromium/chromecast/base/serializers.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BASE_SERIALIZERS_H_
+#define CHROMECAST_BASE_SERIALIZERS_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace base {
+class Value;
+}
+
+namespace chromecast {
+
+// Helper function which deserializes JSON |text| into a base::Value. If |text|
+// is empty, is not valid JSON, or if some other deserialization error occurs,
+// the return value will hold the NULL pointer.
+scoped_ptr<base::Value> DeserializeFromJson(const std::string& text);
+
+// Helper function which serializes |value| into a JSON string. If a
+// serialization error occurs,the return value will hold the NULL pointer.
+scoped_ptr<std::string> SerializeToJson(const base::Value& value);
+
+} // namespace chromecast
+
+#endif // CHROMECAST_BASE_SERIALIZERS_H_
diff --git a/chromium/chromecast/base/serializers_unittest.cc b/chromium/chromecast/base/serializers_unittest.cc
new file mode 100644
index 00000000000..e82d0dc321a
--- /dev/null
+++ b/chromium/chromecast/base/serializers_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/values.h"
+#include "chromecast/base/serializers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace {
+const char kEmptyJsonString[] = "{}";
+const char kProperJsonString[] =
+ "{\n"
+ " \"compound\": {\n"
+ " \"a\": 1,\n"
+ " \"b\": 2\n"
+ " },\n"
+ " \"some_String\": \"1337\",\n"
+ " \"some_int\": 42,\n"
+ " \"the_list\": [ \"val1\", \"val2\" ]\n"
+ "}\n";
+const char kPoorlyFormedJsonString[] = "{\"key\":";
+const char kTestKey[] = "test_key";
+const char kTestValue[] = "test_value";
+
+} // namespace
+
+TEST(DeserializeFromJson, EmptyString) {
+ std::string str;
+ scoped_ptr<base::Value> value = DeserializeFromJson(str);
+ EXPECT_EQ(nullptr, value.get());
+}
+
+TEST(DeserializeFromJson, EmptyJsonObject) {
+ std::string str = kEmptyJsonString;
+ scoped_ptr<base::Value> value = DeserializeFromJson(str);
+ EXPECT_NE(nullptr, value.get());
+}
+
+TEST(DeserializeFromJson, ProperJsonObject) {
+ std::string str = kProperJsonString;
+ scoped_ptr<base::Value> value = DeserializeFromJson(str);
+ EXPECT_NE(nullptr, value.get());
+}
+
+TEST(DeserializeFromJson, PoorlyFormedJsonObject) {
+ std::string str = kPoorlyFormedJsonString;
+ scoped_ptr<base::Value> value = DeserializeFromJson(str);
+ EXPECT_EQ(nullptr, value.get());
+}
+
+TEST(SerializeToJson, BadValue) {
+ base::BinaryValue value(scoped_ptr<char[]>(new char[12]), 12);
+ scoped_ptr<std::string> str = SerializeToJson(value);
+ EXPECT_EQ(nullptr, str.get());
+}
+
+TEST(SerializeToJson, EmptyValue) {
+ base::DictionaryValue value;
+ scoped_ptr<std::string> str = SerializeToJson(value);
+ ASSERT_NE(nullptr, str.get());
+ EXPECT_EQ(kEmptyJsonString, *str);
+}
+
+TEST(SerializeToJson, PopulatedValue) {
+ base::DictionaryValue orig_value;
+ orig_value.SetString(kTestKey, kTestValue);
+ scoped_ptr<std::string> str = SerializeToJson(orig_value);
+ ASSERT_NE(nullptr, str.get());
+
+ scoped_ptr<base::Value> new_value = DeserializeFromJson(*str);
+ ASSERT_NE(nullptr, new_value.get());
+ EXPECT_TRUE(new_value->Equals(&orig_value));
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/DEPS b/chromium/chromecast/browser/DEPS
index fcbae35b8d6..4efe5cf0160 100644
--- a/chromium/chromecast/browser/DEPS
+++ b/chromium/chromecast/browser/DEPS
@@ -3,7 +3,14 @@ include_rules = [
# embedder and can include from all other chromecast/ directories.
"+cc/base/switches.h",
"+chromecast",
+ "+components/cdm/browser",
"+components/crash",
+ "+components/devtools_discovery",
+ "+components/devtools_http_handler",
+ "+components/external_video_surface",
+ "+components/network_hints/browser",
"+content/public/browser",
+ "+gin/v8_initializer.h",
+ "+media/audio",
"+media/base",
]
diff --git a/chromium/chromecast/browser/android/apk/AndroidManifest.xml b/chromium/chromecast/browser/android/apk/AndroidManifest.xml
deleted file mode 100644
index 8dc8d978ed5..00000000000
--- a/chromium/chromecast/browser/android/apk/AndroidManifest.xml
+++ /dev/null
@@ -1,141 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Copyright 2014 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.chromium.chromecast.shell">
-
- <permission android:name="org.chromium.chromecast.shell.permission.SANDBOX"
- android:protectionLevel="signature" />
-
- <application android:name="org.chromium.chromecast.shell.CastApplication"
- android:icon="@mipmap/app_icon"
- android:label="@string/app_name">
- <activity android:name="org.chromium.chromecast.shell.CastShellActivity"
- android:theme="@style/CastShellTheme"
- android:exported="true"
- android:hardwareAccelerated="true"
- android:taskAffinity=".CastShellActivity"
- android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
- android:excludeFromRecents="true"
- android:noHistory="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
-
- <!-- The following service entries exist in order to allow us to
- start more than one sandboxed process. -->
- <service android:name="org.chromium.content.app.SandboxedProcessService0"
- android:process=":sandboxed_process0"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService1"
- android:process=":sandboxed_process1"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService2"
- android:process=":sandboxed_process2"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService3"
- android:process=":sandboxed_process3"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService4"
- android:process=":sandboxed_process4"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService5"
- android:process=":sandboxed_process5"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService6"
- android:process=":sandboxed_process6"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService7"
- android:process=":sandboxed_process7"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService8"
- android:process=":sandboxed_process8"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService9"
- android:process=":sandboxed_process9"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService10"
- android:process=":sandboxed_process10"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService11"
- android:process=":sandboxed_process11"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService12"
- android:process=":sandboxed_process12"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService13"
- android:process=":sandboxed_process13"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService14"
- android:process=":sandboxed_process14"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService15"
- android:process=":sandboxed_process15"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService16"
- android:process=":sandboxed_process16"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService17"
- android:process=":sandboxed_process17"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService18"
- android:process=":sandboxed_process18"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- <service android:name="org.chromium.content.app.SandboxedProcessService19"
- android:process=":sandboxed_process19"
- android:permission="org.chromium.chromecast.shell.permission.SANDBOX"
- android:isolatedProcess="true"
- android:exported="false" />
- </application>
-
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.WAKE_LOCK"/>
-
-</manifest>
diff --git a/chromium/chromecast/browser/android/apk/AndroidManifest.xml.jinja2 b/chromium/chromecast/browser/android/apk/AndroidManifest.xml.jinja2
new file mode 100644
index 00000000000..7b02275ffcf
--- /dev/null
+++ b/chromium/chromecast/browser/android/apk/AndroidManifest.xml.jinja2
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright 2014 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.chromium.chromecast.shell">
+
+ <application android:name="org.chromium.chromecast.shell.CastApplication"
+ android:icon="@mipmap/app_icon"
+ android:label="@string/app_name">
+ <activity android:name="org.chromium.chromecast.shell.CastShellActivity"
+ android:theme="@style/CastShellTheme"
+ android:exported="true"
+ android:hardwareAccelerated="true"
+ android:taskAffinity=".CastShellActivity"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
+ android:excludeFromRecents="true"
+ android:noHistory="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+
+ <!-- The following service entries exist in order to allow us to
+ start more than one sandboxed process. -->
+ {% set num_sandboxed_services = 20 %}
+ <meta-data android:name="org.chromium.content.browser.NUM_SANDBOXED_SERVICES"
+ android:value="{{ num_sandboxed_services }}"/>
+ {% for i in range(num_sandboxed_services) %}
+ <service android:name="org.chromium.content.app.SandboxedProcessService{{ i }}"
+ android:process=":sandboxed_process{{ i }}"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ {% endfor %}
+
+ {% set num_privileged_services = 3 %}
+ <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
+ android:value="{{ num_privileged_services }}"/>
+ {% for i in range(num_privileged_services) %}
+ <service android:name="org.chromium.content.app.PrivilegedProcessService{{ i }}"
+ android:process=":privileged_process{{ i }}"
+ android:isolatedProcess="false"
+ android:exported="false" />
+ {% endfor %}
+ </application>
+
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+
+</manifest>
diff --git a/chromium/chromecast/browser/android/cast_window_android.cc b/chromium/chromecast/browser/android/cast_window_android.cc
index ef279802cfe..7c2e3547b30 100644
--- a/chromium/chromecast/browser/android/cast_window_android.cc
+++ b/chromium/chromecast/browser/android/cast_window_android.cc
@@ -6,12 +6,16 @@
#include "base/message_loop/message_loop_proxy.h"
#include "chromecast/browser/android/cast_window_manager.h"
+#include "chromecast/browser/cast_content_window.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/renderer_preferences.h"
#include "jni/CastWindowAndroid_jni.h"
+#include "ui/gfx/skia_util.h"
namespace chromecast {
namespace shell {
@@ -29,67 +33,67 @@ bool CastWindowAndroid::RegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
-CastWindowAndroid::CastWindowAndroid(content::WebContents* web_contents)
- : content::WebContentsObserver(web_contents),
- weak_factory_(this) {
-}
-
-CastWindowAndroid::~CastWindowAndroid() {
-}
-
// static
CastWindowAndroid* CastWindowAndroid::CreateNewWindow(
content::BrowserContext* browser_context,
const GURL& url) {
- content::WebContents::CreateParams create_params(browser_context);
- create_params.routing_id = MSG_ROUTING_NONE;
- content::WebContents* web_contents =
- content::WebContents::Create(create_params);
- CastWindowAndroid* shell = CreateCastWindowAndroid(
- web_contents,
- create_params.initial_size);
+ CastWindowAndroid* window_android = new CastWindowAndroid(browser_context);
+ window_android->Initialize();
+
if (!url.is_empty())
- shell->LoadURL(url);
- return shell;
+ window_android->LoadURL(url);
+
+ content::RenderWidgetHostView* rwhv =
+ window_android->web_contents_->GetRenderWidgetHostView();
+ if (rwhv) {
+ rwhv->SetBackgroundColor(SK_ColorBLACK);
+ }
+
+ return window_android;
}
-// static
-CastWindowAndroid* CastWindowAndroid::CreateCastWindowAndroid(
- content::WebContents* web_contents,
- const gfx::Size& initial_size) {
- CastWindowAndroid* shell = new CastWindowAndroid(web_contents);
+CastWindowAndroid::CastWindowAndroid(content::BrowserContext* browser_context)
+ : browser_context_(browser_context),
+ content_window_(new CastContentWindow),
+ weak_factory_(this) {
+}
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jobject> shell_android(
- CreateCastWindowView(shell));
+void CastWindowAndroid::Initialize() {
+ web_contents_ =
+ content_window_->CreateWebContents(gfx::Size(), browser_context_);
+ web_contents_->SetDelegate(this);
+ content::WebContentsObserver::Observe(web_contents_.get());
- shell->java_object_.Reset(env, shell_android.Release());
- shell->web_contents_.reset(web_contents);
- web_contents->SetDelegate(shell);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ window_java_.Reset(CreateCastWindowView(this));
Java_CastWindowAndroid_initFromNativeWebContents(
- env, shell->java_object_.obj(), reinterpret_cast<jint>(web_contents));
+ env, window_java_.obj(), web_contents_->GetJavaWebContents().obj(),
+ web_contents_->GetRenderProcessHost()->GetID());
// Enabling hole-punching also requires runtime renderer preference
- web_contents->GetMutableRendererPrefs()->
- use_video_overlay_for_embedded_encrypted_video = true;
- web_contents->GetRenderViewHost()->SyncRendererPrefs();
+ content::RendererPreferences* prefs =
+ web_contents_->GetMutableRendererPrefs();
+ prefs->use_video_overlay_for_embedded_encrypted_video = true;
+ prefs->use_view_overlay_for_all_video = true;
+ web_contents_->GetRenderViewHost()->SyncRendererPrefs();
+}
- return shell;
+CastWindowAndroid::~CastWindowAndroid() {
}
void CastWindowAndroid::Close() {
// Close page first, which fires the window.unload event. The WebContents
// itself will be destroyed after browser-process has received renderer
// notification that the page is closed.
- web_contents_->GetRenderViewHost()->ClosePage();
+ web_contents_->ClosePage();
}
void CastWindowAndroid::Destroy() {
// Note: if multiple windows becomes supported, this may close other devtools
// sessions.
content::DevToolsAgentHost::DetachAllClients();
- CloseCastWindowView(java_object_.obj());
+ CloseCastWindowView(window_java_.obj());
delete this;
}
@@ -105,7 +109,7 @@ void CastWindowAndroid::LoadURL(const GURL& url) {
void CastWindowAndroid::AddNewContents(content::WebContents* source,
content::WebContents* new_contents,
WindowOpenDisposition disposition,
- const gfx::Rect& initial_pos,
+ const gfx::Rect& initial_rect,
bool user_gesture,
bool* was_blocked) {
NOTIMPLEMENTED();
@@ -121,20 +125,6 @@ void CastWindowAndroid::CloseContents(content::WebContents* source) {
// give (and guarantee) the renderer enough time to finish 'onunload'
// handler (but we don't want to wait any longer than that to delay the
// starting of next app).
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
- // When shutting down in a test context, the last remaining WebContents
- // is torn down at browser-thread shutdown time. Call Destroy directly to
- // avoid losing the last posted task to delete this object.
- // TODO(gunsch): This could probably be avoided by using a
- // CompletionCallback in StopCurrentApp to wait until the app is completely
- // stopped. This might require a separate message loop and might only be
- // appropriate for test contexts or during shutdown, since it triggers a
- // wait on the main thread.
- Destroy();
- return;
- }
-
base::MessageLoopProxy::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&CastWindowAndroid::Destroy, weak_factory_.GetWeakPtr()),
diff --git a/chromium/chromecast/browser/android/cast_window_android.h b/chromium/chromecast/browser/android/cast_window_android.h
index fec8b39e1fd..7c5cd7415f1 100644
--- a/chromium/chromecast/browser/android/cast_window_android.h
+++ b/chromium/chromecast/browser/android/cast_window_android.h
@@ -21,8 +21,8 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/size.h"
class GURL;
@@ -33,6 +33,7 @@ class WebContents;
} // namespace content
namespace chromecast {
+class CastContentWindow;
namespace shell {
class CastWindowAndroid : public content::WebContentsDelegate,
@@ -43,7 +44,7 @@ class CastWindowAndroid : public content::WebContentsDelegate,
content::BrowserContext* browser_context,
const GURL& url);
- virtual ~CastWindowAndroid();
+ ~CastWindowAndroid() override;
void LoadURL(const GURL& url);
// Calls RVH::ClosePage() and waits for acknowledgement before closing/
@@ -56,35 +57,33 @@ class CastWindowAndroid : public content::WebContentsDelegate,
static bool RegisterJni(JNIEnv* env);
// content::WebContentsDelegate implementation:
- virtual void AddNewContents(content::WebContents* source,
- content::WebContents* new_contents,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_pos,
- bool user_gesture,
- bool* was_blocked) override;
- virtual void CloseContents(content::WebContents* source) override;
- virtual bool CanOverscrollContent() const override;
- virtual bool AddMessageToConsole(content::WebContents* source,
- int32 level,
- const base::string16& message,
- int32 line_no,
- const base::string16& source_id) override;
- virtual void ActivateContents(content::WebContents* contents) override;
- virtual void DeactivateContents(content::WebContents* contents) override;
+ void AddNewContents(content::WebContents* source,
+ content::WebContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_rect,
+ bool user_gesture,
+ bool* was_blocked) override;
+ void CloseContents(content::WebContents* source) override;
+ bool CanOverscrollContent() const override;
+ bool AddMessageToConsole(content::WebContents* source,
+ int32 level,
+ const base::string16& message,
+ int32 line_no,
+ const base::string16& source_id) override;
+ void ActivateContents(content::WebContents* contents) override;
+ void DeactivateContents(content::WebContents* contents) override;
// content::WebContentsObserver implementation:
- virtual void RenderProcessGone(base::TerminationStatus status) override;
+ void RenderProcessGone(base::TerminationStatus status) override;
private:
- explicit CastWindowAndroid(content::WebContents* web_contents);
+ explicit CastWindowAndroid(content::BrowserContext* browser_context);
+ void Initialize();
- // Helper to create a new CastWindowAndroid given a newly created WebContents.
- static CastWindowAndroid* CreateCastWindowAndroid(
- content::WebContents* web_contents,
- const gfx::Size& initial_size);
-
- base::android::ScopedJavaGlobalRef<jobject> java_object_;
+ content::BrowserContext* browser_context_;
+ base::android::ScopedJavaGlobalRef<jobject> window_java_;
scoped_ptr<content::WebContents> web_contents_;
+ scoped_ptr<CastContentWindow> content_window_;
base::WeakPtrFactory<CastWindowAndroid> weak_factory_;
diff --git a/chromium/chromecast/browser/android/cast_window_manager.cc b/chromium/chromecast/browser/android/cast_window_manager.cc
index 814731caafd..01fe689b3d5 100644
--- a/chromium/chromecast/browser/android/cast_window_manager.cc
+++ b/chromium/chromecast/browser/android/cast_window_manager.cc
@@ -11,12 +11,12 @@
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
+#include "base/prefs/pref_service.h"
#include "chromecast/browser/android/cast_window_android.h"
#include "chromecast/browser/cast_browser_context.h"
#include "chromecast/browser/cast_browser_main_parts.h"
#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/cast_content_browser_client.h"
-#include "chromecast/common/chromecast_config.h"
#include "chromecast/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
@@ -80,7 +80,7 @@ void EnableDevTools(JNIEnv* env, jclass clazz, jboolean enable) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// The specific port value doesn't matter since Android uses Unix domain
// sockets, only whether or not it is zero.
- chromecast::ChromecastConfig::GetInstance()->pref_service()->
+ CastBrowserProcess::GetInstance()->pref_service()->
SetInteger(prefs::kRemoteDebuggingPort, enable ? 1 : 0);
}
diff --git a/chromium/chromecast/browser/android/external_video_surface_container_impl.cc b/chromium/chromecast/browser/android/external_video_surface_container_impl.cc
deleted file mode 100644
index 5dbb144cbae..00000000000
--- a/chromium/chromecast/browser/android/external_video_surface_container_impl.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromecast/browser/android/external_video_surface_container_impl.h"
-
-#include "base/android/jni_android.h"
-#include "content/public/browser/android/content_view_core.h"
-#include "jni/ExternalVideoSurfaceContainer_jni.h"
-#include "ui/gfx/rect_f.h"
-
-namespace chromecast {
-namespace shell {
-
-ExternalVideoSurfaceContainerImpl::ExternalVideoSurfaceContainerImpl(
- content::WebContents* web_contents) {
- content::ContentViewCore* cvc =
- content::ContentViewCore::FromWebContents(web_contents);
- if (cvc) {
- JNIEnv* env = base::android::AttachCurrentThread();
- jobject_.Reset(
- Java_ExternalVideoSurfaceContainer_create(
- env, reinterpret_cast<intptr_t>(this), cvc->GetJavaObject().obj()));
- }
-}
-
-ExternalVideoSurfaceContainerImpl::~ExternalVideoSurfaceContainerImpl() {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ExternalVideoSurfaceContainer_destroy(env, jobject_.obj());
- jobject_.Reset();
-}
-
-void ExternalVideoSurfaceContainerImpl::RequestExternalVideoSurface(
- int player_id,
- const SurfaceCreatedCB& surface_created_cb,
- const SurfaceDestroyedCB& surface_destroyed_cb) {
- surface_created_cb_ = surface_created_cb;
- surface_destroyed_cb_ = surface_destroyed_cb;
-
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ExternalVideoSurfaceContainer_requestExternalVideoSurface(
- env, jobject_.obj(), static_cast<jint>(player_id));
-}
-
-void ExternalVideoSurfaceContainerImpl::ReleaseExternalVideoSurface(
- int player_id) {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ExternalVideoSurfaceContainer_releaseExternalVideoSurface(
- env, jobject_.obj(), static_cast<jint>(player_id));
-
- surface_created_cb_.Reset();
- surface_destroyed_cb_.Reset();
-}
-
-void ExternalVideoSurfaceContainerImpl::OnFrameInfoUpdated() {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ExternalVideoSurfaceContainer_onFrameInfoUpdated(env, jobject_.obj());
-}
-
-void ExternalVideoSurfaceContainerImpl::OnExternalVideoSurfacePositionChanged(
- int player_id, const gfx::RectF& rect) {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ExternalVideoSurfaceContainer_onExternalVideoSurfacePositionChanged(
- env,
- jobject_.obj(),
- static_cast<jint>(player_id),
- static_cast<jfloat>(rect.x()),
- static_cast<jfloat>(rect.y()),
- static_cast<jfloat>(rect.x() + rect.width()),
- static_cast<jfloat>(rect.y() + rect.height()));
-}
-
-// Methods called from Java.
-void ExternalVideoSurfaceContainerImpl::SurfaceCreated(
- JNIEnv* env, jobject obj, jint player_id, jobject jsurface) {
- if (!surface_created_cb_.is_null())
- surface_created_cb_.Run(static_cast<int>(player_id), jsurface);
-}
-
-void ExternalVideoSurfaceContainerImpl::SurfaceDestroyed(
- JNIEnv* env, jobject obj, jint player_id) {
- if (!surface_destroyed_cb_.is_null())
- surface_destroyed_cb_.Run(static_cast<int>(player_id));
-}
-
-bool RegisterExternalVideoSurfaceContainer(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-} // namespace shell
-} // namespace chromecast
diff --git a/chromium/chromecast/browser/android/external_video_surface_container_impl.h b/chromium/chromecast/browser/android/external_video_surface_container_impl.h
deleted file mode 100644
index b05b1882960..00000000000
--- a/chromium/chromecast/browser/android/external_video_surface_container_impl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMECAST_BROWSER_ANDROID_EXTERNAL_VIDEO_SURFACE_CONTAINER_IMPL_H_
-#define CHROMECAST_BROWSER_ANDROID_EXTERNAL_VIDEO_SURFACE_CONTAINER_IMPL_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "content/public/browser/android/external_video_surface_container.h"
-
-namespace chromecast {
-namespace shell {
-
-class ExternalVideoSurfaceContainerImpl
- : public content::ExternalVideoSurfaceContainer {
- public:
- typedef base::Callback<void(int, jobject)> SurfaceCreatedCB;
- typedef base::Callback<void(int)> SurfaceDestroyedCB;
-
- ExternalVideoSurfaceContainerImpl(content::WebContents* contents);
-
- // ExternalVideoSurfaceContainer implementation.
- virtual void RequestExternalVideoSurface(
- int player_id,
- const SurfaceCreatedCB& surface_created_cb,
- const SurfaceDestroyedCB& surface_destroyed_cb) override;
- virtual void ReleaseExternalVideoSurface(int player_id) override;
- virtual void OnFrameInfoUpdated() override;
- virtual void OnExternalVideoSurfacePositionChanged(
- int player_id, const gfx::RectF& rect) override;
-
- // Methods called from Java.
- void SurfaceCreated(
- JNIEnv* env, jobject obj, jint player_id, jobject jsurface);
- void SurfaceDestroyed(JNIEnv* env, jobject obj, jint player_id);
-
- private:
- virtual ~ExternalVideoSurfaceContainerImpl();
-
- base::android::ScopedJavaGlobalRef<jobject> jobject_;
-
- SurfaceCreatedCB surface_created_cb_;
- SurfaceDestroyedCB surface_destroyed_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(ExternalVideoSurfaceContainerImpl);
-};
-
-bool RegisterExternalVideoSurfaceContainer(JNIEnv* env);
-
-} // namespace shell
-} // namespace chromecast
-
-#endif // CHROMECAST_BROWSER_ANDROID_EXTERNAL_VIDEO_SURFACE_CONTAINER_IMPL_H_
diff --git a/chromium/chromecast/browser/cast_browser_context.cc b/chromium/chromecast/browser/cast_browser_context.cc
index ed19a05ef1f..51a9fc02550 100644
--- a/chromium/chromecast/browser/cast_browser_context.cc
+++ b/chromium/chromecast/browser/cast_browser_context.cc
@@ -8,9 +8,10 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/path_service.h"
+#include "chromecast/base/cast_paths.h"
#include "chromecast/browser/cast_download_manager_delegate.h"
+#include "chromecast/browser/cast_permission_manager.h"
#include "chromecast/browser/url_request_context_factory.h"
-#include "chromecast/common/cast_paths.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition.h"
@@ -27,15 +28,15 @@ class CastBrowserContext::CastResourceContext :
explicit CastResourceContext(
URLRequestContextFactory* url_request_context_factory) :
url_request_context_factory_(url_request_context_factory) {}
- virtual ~CastResourceContext() {}
+ ~CastResourceContext() override {}
// ResourceContext implementation:
- virtual net::HostResolver* GetHostResolver() override {
+ net::HostResolver* GetHostResolver() override {
return url_request_context_factory_->GetMainGetter()->
GetURLRequestContext()->host_resolver();
}
- virtual net::URLRequestContext* GetRequestContext() override {
+ net::URLRequestContext* GetRequestContext() override {
return url_request_context_factory_->GetMainGetter()->
GetURLRequestContext();
}
@@ -77,6 +78,12 @@ void CastBrowserContext::InitWhileIOAllowed() {
#endif // defined(OS_ANDROID)
}
+scoped_ptr<content::ZoomLevelDelegate>
+CastBrowserContext::CreateZoomLevelDelegate(
+ const base::FilePath& partition_path) {
+ return nullptr;
+}
+
base::FilePath CastBrowserContext::GetPath() const {
return path_;
}
@@ -110,6 +117,10 @@ CastBrowserContext::GetMediaRequestContextForStoragePartition(
return GetMediaRequestContext();
}
+net::URLRequestContextGetter* CastBrowserContext::GetSystemRequestContext() {
+ return url_request_context_factory_->GetSystemGetter();
+}
+
content::ResourceContext* CastBrowserContext::GetResourceContext() {
return resource_context_.get();
}
@@ -120,23 +131,25 @@ CastBrowserContext::GetDownloadManagerDelegate() {
}
content::BrowserPluginGuestManager* CastBrowserContext::GetGuestManager() {
- NOTIMPLEMENTED();
- return NULL;
+ return nullptr;
}
storage::SpecialStoragePolicy* CastBrowserContext::GetSpecialStoragePolicy() {
- NOTIMPLEMENTED();
- return NULL;
+ return nullptr;
}
content::PushMessagingService* CastBrowserContext::GetPushMessagingService() {
- NOTIMPLEMENTED();
- return NULL;
+ return nullptr;
}
content::SSLHostStateDelegate* CastBrowserContext::GetSSLHostStateDelegate() {
- NOTIMPLEMENTED();
- return NULL;
+ return nullptr;
+}
+
+content::PermissionManager* CastBrowserContext::GetPermissionManager() {
+ if (!permission_manager_.get())
+ permission_manager_.reset(new CastPermissionManager());
+ return permission_manager_.get();
}
} // namespace shell
diff --git a/chromium/chromecast/browser/cast_browser_context.h b/chromium/chromecast/browser/cast_browser_context.h
index 931d886fd13..ae0cf13002e 100644
--- a/chromium/chromecast/browser/cast_browser_context.h
+++ b/chromium/chromecast/browser/cast_browser_context.h
@@ -23,28 +23,31 @@ class CastBrowserContext : public content::BrowserContext {
public:
explicit CastBrowserContext(
URLRequestContextFactory* url_request_context_factory);
- virtual ~CastBrowserContext();
+ ~CastBrowserContext() override;
// BrowserContext implementation:
- virtual base::FilePath GetPath() const override;
- virtual bool IsOffTheRecord() const override;
- virtual net::URLRequestContextGetter* GetRequestContext() override;
- virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess(
+ scoped_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(
+ const base::FilePath& partition_path) override;
+ base::FilePath GetPath() const override;
+ bool IsOffTheRecord() const override;
+ net::URLRequestContextGetter* GetRequestContext() override;
+ net::URLRequestContextGetter* GetRequestContextForRenderProcess(
int renderer_child_id) override;
- virtual net::URLRequestContextGetter* GetMediaRequestContext() override;
- virtual net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess(
+ net::URLRequestContextGetter* GetMediaRequestContext() override;
+ net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess(
int renderer_child_id) override;
- virtual net::URLRequestContextGetter*
- GetMediaRequestContextForStoragePartition(
- const base::FilePath& partition_path,
- bool in_memory) override;
- virtual content::ResourceContext* GetResourceContext() override;
- virtual content::DownloadManagerDelegate*
- GetDownloadManagerDelegate() override;
- virtual content::BrowserPluginGuestManager* GetGuestManager() override;
- virtual storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override;
- virtual content::PushMessagingService* GetPushMessagingService() override;
- virtual content::SSLHostStateDelegate* GetSSLHostStateDelegate() override;
+ net::URLRequestContextGetter* GetMediaRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory) override;
+ content::ResourceContext* GetResourceContext() override;
+ content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
+ content::BrowserPluginGuestManager* GetGuestManager() override;
+ storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override;
+ content::PushMessagingService* GetPushMessagingService() override;
+ content::SSLHostStateDelegate* GetSSLHostStateDelegate() override;
+ content::PermissionManager* GetPermissionManager() override;
+
+ net::URLRequestContextGetter* GetSystemRequestContext();
private:
class CastResourceContext;
@@ -57,6 +60,7 @@ class CastBrowserContext : public content::BrowserContext {
base::FilePath path_;
scoped_ptr<CastResourceContext> resource_context_;
scoped_ptr<CastDownloadManagerDelegate> download_manager_delegate_;
+ scoped_ptr<content::PermissionManager> permission_manager_;
DISALLOW_COPY_AND_ASSIGN(CastBrowserContext);
};
diff --git a/chromium/chromecast/browser/cast_browser_main_parts.cc b/chromium/chromecast/browser/cast_browser_main_parts.cc
index cb072003646..91b13cef9f7 100644
--- a/chromium/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromium/chromecast/browser/cast_browser_main_parts.cc
@@ -4,32 +4,149 @@
#include "chromecast/browser/cast_browser_main_parts.h"
+#include <string>
+#if !defined(OS_ANDROID)
+#include <signal.h>
+#include <sys/prctl.h>
+#endif
+
#include "base/command_line.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
+#include "base/run_loop.h"
#include "cc/base/switches.h"
+#include "chromecast/base/cast_paths.h"
+#include "chromecast/base/cast_sys_info_util.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
+#include "chromecast/base/metrics/grouped_histogram.h"
#include "chromecast/browser/cast_browser_context.h"
#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/devtools/remote_debugging_server.h"
#include "chromecast/browser/metrics/cast_metrics_prefs.h"
#include "chromecast/browser/metrics/cast_metrics_service_client.h"
+#include "chromecast/browser/pref_service_helper.h"
#include "chromecast/browser/service/cast_service.h"
#include "chromecast/browser/url_request_context_factory.h"
-#include "chromecast/browser/webui/webui_cast.h"
-#include "chromecast/common/chromecast_config.h"
+#include "chromecast/common/chromecast_switches.h"
#include "chromecast/common/platform_client_auth.h"
-#include "chromecast/net/network_change_notifier_cast.h"
-#include "chromecast/net/network_change_notifier_factory_cast.h"
+#include "chromecast/media/base/key_systems_common.h"
+#include "chromecast/net/connectivity_checker.h"
+#include "chromecast/public/cast_media_shlib.h"
+#include "chromecast/public/cast_sys_info.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h"
+#include "media/audio/audio_manager.h"
+#include "media/audio/audio_manager_factory.h"
+#include "media/base/browser_cdm_factory.h"
#include "media/base/media_switches.h"
#if defined(OS_ANDROID)
+#include "chromecast/browser/media/cast_media_client_android.h"
#include "chromecast/crash/android/crash_handler.h"
#include "components/crash/browser/crash_dump_manager_android.h"
+#include "media/base/android/media_client_android.h"
#include "net/android/network_change_notifier_factory_android.h"
-#endif // defined(OS_ANDROID)
+#else
+#include "chromecast/browser/media/cast_browser_cdm_factory.h"
+#include "chromecast/net/network_change_notifier_factory_cast.h"
+#endif
+
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/gfx/screen.h"
+#endif
+
+namespace {
+
+#if !defined(OS_ANDROID)
+int kSignalsToRunClosure[] = { SIGTERM, SIGINT, };
+
+// Closure to run on SIGTERM and SIGINT.
+base::Closure* g_signal_closure = NULL;
+
+void RunClosureOnSignal(int signum) {
+ LOG(ERROR) << "Got signal " << signum;
+ DCHECK(g_signal_closure);
+ // Expect main thread got this signal. Otherwise, weak_ptr of run_loop will
+ // crash the process.
+ g_signal_closure->Run();
+}
+
+void RegisterClosureOnSignal(const base::Closure& closure) {
+ DCHECK(!g_signal_closure);
+ DCHECK_GT(arraysize(kSignalsToRunClosure), 0U);
+
+ // Allow memory leak by intention.
+ g_signal_closure = new base::Closure(closure);
+
+ struct sigaction sa_new;
+ memset(&sa_new, 0, sizeof(sa_new));
+ sa_new.sa_handler = RunClosureOnSignal;
+ sigfillset(&sa_new.sa_mask);
+ sa_new.sa_flags = SA_RESTART;
+
+ for (size_t i = 0; i < arraysize(kSignalsToRunClosure); i++) {
+ struct sigaction sa_old;
+ if (sigaction(kSignalsToRunClosure[i], &sa_new, &sa_old) == -1) {
+ NOTREACHED();
+ } else {
+ DCHECK_EQ(sa_old.sa_handler, SIG_DFL);
+ }
+ }
+
+ // Get the first signal to exit when the parent process dies.
+ prctl(PR_SET_PDEATHSIG, kSignalsToRunClosure[0]);
+}
+
+const int kKillOnAlarmTimeoutSec = 5; // 5 seconds
+
+void KillOnAlarm(int signum) {
+ LOG(ERROR) << "Got alarm signal for termination: " << signum;
+ raise(SIGKILL);
+}
+
+void RegisterKillOnAlarm(int timeout_seconds) {
+ struct sigaction sa_new;
+ memset(&sa_new, 0, sizeof(sa_new));
+ sa_new.sa_handler = KillOnAlarm;
+ sigfillset(&sa_new.sa_mask);
+ sa_new.sa_flags = SA_RESTART;
+
+ struct sigaction sa_old;
+ if (sigaction(SIGALRM, &sa_new, &sa_old) == -1) {
+ NOTREACHED();
+ } else {
+ DCHECK_EQ(sa_old.sa_handler, SIG_DFL);
+ }
+
+ if (alarm(timeout_seconds) > 0)
+ NOTREACHED() << "Previous alarm() was cancelled";
+}
+
+void DeregisterKillOnAlarm() {
+ // Explicitly cancel any outstanding alarm() calls.
+ alarm(0);
+
+ struct sigaction sa_new;
+ memset(&sa_new, 0, sizeof(sa_new));
+ sa_new.sa_handler = SIG_DFL;
+ sigfillset(&sa_new.sa_mask);
+ sa_new.sa_flags = SA_RESTART;
+
+ struct sigaction sa_old;
+ if (sigaction(SIGALRM, &sa_new, &sa_old) == -1) {
+ NOTREACHED();
+ } else {
+ DCHECK_EQ(sa_old.sa_handler, KillOnAlarm);
+ }
+}
+#endif // !defined(OS_ANDROID)
+
+} // namespace
namespace chromecast {
namespace shell {
@@ -43,28 +160,34 @@ struct DefaultCommandLineSwitch {
DefaultCommandLineSwitch g_default_switches[] = {
#if defined(OS_ANDROID)
- { switches::kMediaDrmEnableNonCompositing, ""},
+ // Disables Chromecast-specific WiFi-related features on ATV for now.
+ { switches::kNoWifi, "" },
{ switches::kEnableOverlayFullscreenVideo, ""},
{ switches::kDisableInfobarForProtectedMediaIdentifier, ""},
{ switches::kDisableGestureRequirementForMediaPlayback, ""},
- { switches::kForceUseOverlayEmbeddedVideo, ""},
#endif
- { switches::kDisableApplicationCache, "" },
- { switches::kDisablePlugins, "" },
// Always enable HTMLMediaElement logs.
{ switches::kBlinkPlatformLogChannels, "Media"},
-#if defined(OS_LINUX) && defined(ARCH_CPU_X86_FAMILY)
+#if defined(DISABLE_DISPLAY)
+ { switches::kDisableGpu, "" },
+#endif
+#if defined(OS_LINUX)
+#if defined(ARCH_CPU_X86_FAMILY)
// This is needed for now to enable the egltest Ozone platform to work with
// current Linux/NVidia OpenGL drivers.
{ switches::kIgnoreGpuBlacklist, ""},
- // TODO(gusfernandez): This is needed to fix a bug with
- // glPostSubBufferCHROMIUM (crbug.com/429200)
- { cc::switches::kUIDisablePartialSwap, ""},
+#elif defined(ARCH_CPU_ARM_FAMILY) && !defined(DISABLE_DISPLAY)
+ // On Linux arm, enable CMA pipeline by default.
+ { switches::kEnableCmaMediaPipeline, "" },
#endif
+#endif // defined(OS_LINUX)
+ // Needed to fix a bug where the raster thread doesn't get scheduled for a
+ // substantial time (~5 seconds). See https://crbug.com/441895.
+ { switches::kUseNormalPriorityForTileTaskWorkerThreads, "" },
{ NULL, NULL }, // Termination
};
-void AddDefaultCommandLineSwitches(CommandLine* command_line) {
+void AddDefaultCommandLineSwitches(base::CommandLine* command_line) {
int i = 0;
while (g_default_switches[i].switch_name != NULL) {
command_line->AppendSwitchASCII(
@@ -78,12 +201,14 @@ void AddDefaultCommandLineSwitches(CommandLine* command_line) {
CastBrowserMainParts::CastBrowserMainParts(
const content::MainFunctionParams& parameters,
- URLRequestContextFactory* url_request_context_factory)
+ URLRequestContextFactory* url_request_context_factory,
+ scoped_ptr<::media::AudioManagerFactory> audio_manager_factory)
: BrowserMainParts(),
cast_browser_process_(new CastBrowserProcess()),
parameters_(parameters),
- url_request_context_factory_(url_request_context_factory) {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ url_request_context_factory_(url_request_context_factory),
+ audio_manager_factory_(audio_manager_factory.Pass()) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
AddDefaultCommandLineSwitches(command_line);
}
@@ -91,6 +216,17 @@ CastBrowserMainParts::~CastBrowserMainParts() {
}
void CastBrowserMainParts::PreMainMessageLoopStart() {
+ // GroupedHistograms needs to be initialized before any threads are created
+ // to prevent race conditions between calls to Preregister and those threads
+ // attempting to collect metrics.
+ // This call must also be before NetworkChangeNotifier, as it generates
+ // Net/DNS metrics.
+ metrics::PreregisterAllGroupedHistograms();
+
+ // Set the platform's implementation of AudioManagerFactory.
+ if (audio_manager_factory_)
+ ::media::AudioManager::SetFactory(audio_manager_factory_.release());
+
#if defined(OS_ANDROID)
net::NetworkChangeNotifier::SetFactory(
new net::NetworkChangeNotifierFactoryAndroid());
@@ -101,8 +237,8 @@ void CastBrowserMainParts::PreMainMessageLoopStart() {
}
void CastBrowserMainParts::PostMainMessageLoopStart() {
- cast_browser_process_->SetMetricsHelper(
- new metrics::CastMetricsHelper(base::MessageLoopProxy::current()));
+ cast_browser_process_->SetMetricsHelper(make_scoped_ptr(
+ new metrics::CastMetricsHelper(base::MessageLoopProxy::current())));
#if defined(OS_ANDROID)
base::MessageLoopForUI::current()->Start();
@@ -110,66 +246,143 @@ void CastBrowserMainParts::PostMainMessageLoopStart() {
}
int CastBrowserMainParts::PreCreateThreads() {
- PrefRegistrySimple* pref_registry = new PrefRegistrySimple();
- metrics::RegisterPrefs(pref_registry);
- ChromecastConfig::Create(pref_registry);
+#if defined(OS_ANDROID)
+ // GPU process is started immediately after threads are created, requiring
+ // CrashDumpManager to be initialized beforehand.
+ base::FilePath crash_dumps_dir;
+ if (!chromecast::CrashHandler::GetCrashDumpLocation(&crash_dumps_dir)) {
+ LOG(ERROR) << "Could not find crash dump location.";
+ }
+ cast_browser_process_->SetCrashDumpManager(
+ make_scoped_ptr(new breakpad::CrashDumpManager(crash_dumps_dir)));
+#else
+ base::FilePath home_dir;
+ CHECK(PathService::Get(DIR_CAST_HOME, &home_dir));
+ if (!base::CreateDirectory(home_dir))
+ return 1;
+#endif
+
+#if defined(USE_AURA)
+ // Screen can (and should) exist even with no displays connected. Its presence
+ // is assumed as an interface to access display information, e.g. from metrics
+ // code. See CastContentWindow::CreateWindowTree for update when resolution
+ // is available.
+ DCHECK(!gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE));
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
+ aura::TestScreen::Create(gfx::Size(0, 0)));
+#endif
return 0;
}
void CastBrowserMainParts::PreMainMessageLoopRun() {
+ // Set GL strings so GPU config code can make correct feature blacklisting/
+ // whitelisting decisions.
+ // Note: SetGLStrings MUST be called after GpuDataManager::Initialize.
+ scoped_ptr<CastSysInfo> sys_info = CreateSysInfo();
+ content::GpuDataManager::GetInstance()->SetGLStrings(
+ sys_info->GetGlVendor(), sys_info->GetGlRenderer(),
+ sys_info->GetGlVersion());
+
+ scoped_refptr<PrefRegistrySimple> pref_registry(new PrefRegistrySimple());
+ metrics::RegisterPrefs(pref_registry.get());
+ cast_browser_process_->SetPrefService(
+ PrefServiceHelper::CreatePrefService(pref_registry.get()));
+
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+#if defined(OS_ANDROID)
+ ::media::SetMediaClientAndroid(new media::CastMediaClientAndroid());
+#else
+ if (cmd_line->HasSwitch(switches::kEnableCmaMediaPipeline))
+ ::media::SetBrowserCdmFactory(new media::CastBrowserCdmFactory());
+#endif // defined(OS_ANDROID)
+
+ cast_browser_process_->SetConnectivityChecker(
+ make_scoped_refptr(new ConnectivityChecker(
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::IO))));
+
url_request_context_factory_->InitializeOnUIThread();
cast_browser_process_->SetBrowserContext(
- new CastBrowserContext(url_request_context_factory_));
+ make_scoped_ptr(new CastBrowserContext(url_request_context_factory_)));
cast_browser_process_->SetMetricsServiceClient(
metrics::CastMetricsServiceClient::Create(
content::BrowserThread::GetBlockingPool(),
- ChromecastConfig::GetInstance()->pref_service(),
+ cast_browser_process_->pref_service(),
cast_browser_process_->browser_context()->GetRequestContext()));
-#if defined(OS_ANDROID)
- base::FilePath crash_dumps_dir;
- if (!chromecast::CrashHandler::GetCrashDumpLocation(&crash_dumps_dir)) {
- LOG(ERROR) << "Could not find crash dump location.";
- }
- cast_browser_process_->SetCrashDumpManager(
- new breakpad::CrashDumpManager(crash_dumps_dir));
-#endif
-
- if (!PlatformClientAuth::Initialize()) {
+ if (!PlatformClientAuth::Initialize())
LOG(ERROR) << "PlatformClientAuth::Initialize failed.";
- }
- cast_browser_process_->SetRemoteDebuggingServer(new RemoteDebuggingServer());
+ cast_browser_process_->SetRemoteDebuggingServer(
+ make_scoped_ptr(new RemoteDebuggingServer()));
- InitializeWebUI();
+ media::CastMediaShlib::Initialize(cmd_line->argv());
cast_browser_process_->SetCastService(CastService::Create(
cast_browser_process_->browser_context(),
- url_request_context_factory_->GetSystemGetter(),
- base::Bind(
- &metrics::CastMetricsServiceClient::EnableMetricsService,
- base::Unretained(cast_browser_process_->metrics_service_client()))));
+ cast_browser_process_->pref_service(),
+ cast_browser_process_->metrics_service_client(),
+ url_request_context_factory_->GetSystemGetter()));
+ cast_browser_process_->cast_service()->Initialize();
- // Initializing network delegates must happen after Cast service is created.
+ // Initializing metrics service and network delegates must happen after cast
+ // service is intialized because CastMetricsServiceClient and
+ // CastNetworkDelegate may use components initialized by cast service.
+ cast_browser_process_->metrics_service_client()
+ ->Initialize(cast_browser_process_->cast_service());
url_request_context_factory_->InitializeNetworkDelegates();
+
cast_browser_process_->cast_service()->Start();
}
bool CastBrowserMainParts::MainMessageLoopRun(int* result_code) {
- // If parameters_.ui_task is not NULL, we are running browser tests. In this
- // case, the browser's main message loop will not run.
+#if defined(OS_ANDROID)
+ // Android does not use native main MessageLoop.
+ NOTREACHED();
+ return true;
+#else
+ base::RunLoop run_loop;
+ base::Closure quit_closure(run_loop.QuitClosure());
+ RegisterClosureOnSignal(quit_closure);
+
+ // If parameters_.ui_task is not NULL, we are running browser tests.
if (parameters_.ui_task) {
- parameters_.ui_task->Run();
- } else {
- base::MessageLoopForUI::current()->Run();
+ base::MessageLoop* message_loop = base::MessageLoopForUI::current();
+ message_loop->PostTask(FROM_HERE, *parameters_.ui_task);
+ message_loop->PostTask(FROM_HERE, quit_closure);
}
+
+ run_loop.Run();
+
+ // Once the main loop has stopped running, we give the browser process a few
+ // seconds to stop cast service and finalize all resources. If a hang occurs
+ // and cast services refuse to terminate successfully, then we SIGKILL the
+ // current process to avoid indefinte hangs.
+ RegisterKillOnAlarm(kKillOnAlarmTimeoutSec);
+
+ cast_browser_process_->cast_service()->Stop();
return true;
+#endif
}
void CastBrowserMainParts::PostMainMessageLoopRun() {
- cast_browser_process_->cast_service()->Stop();
+#if defined(OS_ANDROID)
+ // Android does not use native main MessageLoop.
+ NOTREACHED();
+#else
+ cast_browser_process_->cast_service()->Finalize();
+ cast_browser_process_->metrics_service_client()->Finalize();
cast_browser_process_.reset();
+
+#if defined(USE_AURA)
+ aura::Env::DeleteInstance();
+#endif
+
+ DeregisterKillOnAlarm();
+#endif
+
+ media::CastMediaShlib::Finalize();
}
} // namespace shell
diff --git a/chromium/chromecast/browser/cast_browser_main_parts.h b/chromium/chromecast/browser/cast_browser_main_parts.h
index 3220faf8e08..49954cef55d 100644
--- a/chromium/chromecast/browser/cast_browser_main_parts.h
+++ b/chromium/chromecast/browser/cast_browser_main_parts.h
@@ -11,6 +11,10 @@
#include "content/public/browser/browser_main_parts.h"
#include "content/public/common/main_function_params.h"
+namespace media {
+class AudioManagerFactory;
+}
+
namespace chromecast {
namespace shell {
class CastBrowserProcess;
@@ -18,23 +22,26 @@ class URLRequestContextFactory;
class CastBrowserMainParts : public content::BrowserMainParts {
public:
+ // This class does not take ownership of |url_request_content_factory|.
CastBrowserMainParts(
const content::MainFunctionParams& parameters,
- URLRequestContextFactory* url_request_context_factory);
- virtual ~CastBrowserMainParts();
+ URLRequestContextFactory* url_request_context_factory,
+ scoped_ptr<::media::AudioManagerFactory> audio_manager_factory);
+ ~CastBrowserMainParts() override;
// content::BrowserMainParts implementation:
- virtual void PreMainMessageLoopStart() override;
- virtual void PostMainMessageLoopStart() override;
- virtual int PreCreateThreads() override;
- virtual void PreMainMessageLoopRun() override;
- virtual bool MainMessageLoopRun(int* result_code) override;
- virtual void PostMainMessageLoopRun() override;
+ void PreMainMessageLoopStart() override;
+ void PostMainMessageLoopStart() override;
+ int PreCreateThreads() override;
+ void PreMainMessageLoopRun() override;
+ bool MainMessageLoopRun(int* result_code) override;
+ void PostMainMessageLoopRun() override;
private:
scoped_ptr<CastBrowserProcess> cast_browser_process_;
const content::MainFunctionParams parameters_; // For running browser tests.
URLRequestContextFactory* const url_request_context_factory_;
+ scoped_ptr<::media::AudioManagerFactory> audio_manager_factory_;
DISALLOW_COPY_AND_ASSIGN(CastBrowserMainParts);
};
diff --git a/chromium/chromecast/browser/cast_browser_process.cc b/chromium/chromecast/browser/cast_browser_process.cc
index 050ff0d3fe8..25fcd44ff4a 100644
--- a/chromium/chromecast/browser/cast_browser_process.cc
+++ b/chromium/chromecast/browser/cast_browser_process.cc
@@ -5,20 +5,19 @@
#include "chromecast/browser/cast_browser_process.h"
#include "base/logging.h"
+#include "base/prefs/pref_service.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "chromecast/browser/cast_browser_context.h"
+#include "chromecast/browser/cast_resource_dispatcher_host_delegate.h"
#include "chromecast/browser/devtools/remote_debugging_server.h"
#include "chromecast/browser/metrics/cast_metrics_service_client.h"
#include "chromecast/browser/service/cast_service.h"
+#include "chromecast/net/connectivity_checker.h"
#if defined(OS_ANDROID)
#include "components/crash/browser/crash_dump_manager_android.h"
#endif // defined(OS_ANDROID)
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#endif
-
namespace chromecast {
namespace shell {
@@ -39,48 +38,64 @@ CastBrowserProcess::CastBrowserProcess() {
CastBrowserProcess::~CastBrowserProcess() {
DCHECK_EQ(g_instance, this);
-#if defined(USE_AURA)
- aura::Env::DeleteInstance();
-#endif
+ if (pref_service_)
+ pref_service_->CommitPendingWrite();
g_instance = NULL;
}
void CastBrowserProcess::SetBrowserContext(
- CastBrowserContext* browser_context) {
+ scoped_ptr<CastBrowserContext> browser_context) {
DCHECK(!browser_context_);
- browser_context_.reset(browser_context);
+ browser_context_.swap(browser_context);
}
-void CastBrowserProcess::SetCastService(CastService* cast_service) {
+void CastBrowserProcess::SetCastService(scoped_ptr<CastService> cast_service) {
DCHECK(!cast_service_);
- cast_service_.reset(cast_service);
-}
-
-void CastBrowserProcess::SetRemoteDebuggingServer(
- RemoteDebuggingServer* remote_debugging_server) {
- DCHECK(!remote_debugging_server_);
- remote_debugging_server_.reset(remote_debugging_server);
+ cast_service_.swap(cast_service);
}
void CastBrowserProcess::SetMetricsHelper(
- metrics::CastMetricsHelper* metrics_helper) {
+ scoped_ptr<metrics::CastMetricsHelper> metrics_helper) {
DCHECK(!metrics_helper_);
- metrics_helper_.reset(metrics_helper);
+ metrics_helper_.swap(metrics_helper);
}
void CastBrowserProcess::SetMetricsServiceClient(
- metrics::CastMetricsServiceClient* metrics_service_client) {
+ scoped_ptr<metrics::CastMetricsServiceClient> metrics_service_client) {
DCHECK(!metrics_service_client_);
- metrics_service_client_.reset(metrics_service_client);
+ metrics_service_client_.swap(metrics_service_client);
+}
+
+void CastBrowserProcess::SetPrefService(scoped_ptr<PrefService> pref_service) {
+ DCHECK(!pref_service_);
+ pref_service_.swap(pref_service);
+}
+
+void CastBrowserProcess::SetRemoteDebuggingServer(
+ scoped_ptr<RemoteDebuggingServer> remote_debugging_server) {
+ DCHECK(!remote_debugging_server_);
+ remote_debugging_server_.swap(remote_debugging_server);
+}
+
+void CastBrowserProcess::SetResourceDispatcherHostDelegate(
+ scoped_ptr<CastResourceDispatcherHostDelegate> delegate) {
+ DCHECK(!resource_dispatcher_host_delegate_);
+ resource_dispatcher_host_delegate_.swap(delegate);
}
#if defined(OS_ANDROID)
void CastBrowserProcess::SetCrashDumpManager(
- breakpad::CrashDumpManager* crash_dump_manager) {
+ scoped_ptr<breakpad::CrashDumpManager> crash_dump_manager) {
DCHECK(!crash_dump_manager_);
- crash_dump_manager_.reset(crash_dump_manager);
+ crash_dump_manager_.swap(crash_dump_manager);
}
#endif // defined(OS_ANDROID)
+void CastBrowserProcess::SetConnectivityChecker(
+ scoped_refptr<ConnectivityChecker> connectivity_checker) {
+ DCHECK(!connectivity_checker_);
+ connectivity_checker_.swap(connectivity_checker);
+}
+
} // namespace shell
} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_browser_process.h b/chromium/chromecast/browser/cast_browser_process.h
index 7f0ac7910df..f4bec89e7a1 100644
--- a/chromium/chromecast/browser/cast_browser_process.h
+++ b/chromium/chromecast/browser/cast_browser_process.h
@@ -6,15 +6,18 @@
#define CHROMECAST_BROWSER_CAST_BROWSER_PROCESS_H_
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+class PrefService;
+
namespace breakpad {
class CrashDumpManager;
} // namespace breakpad
namespace chromecast {
class CastService;
-class WebCryptoServer;
+class ConnectivityChecker;
namespace metrics {
class CastMetricsHelper;
@@ -23,6 +26,7 @@ class CastMetricsServiceClient;
namespace shell {
class CastBrowserContext;
+class CastResourceDispatcherHostDelegate;
class RemoteDebuggingServer;
class CastBrowserProcess {
@@ -34,30 +38,51 @@ class CastBrowserProcess {
CastBrowserProcess();
virtual ~CastBrowserProcess();
- void SetBrowserContext(CastBrowserContext* browser_context);
- void SetCastService(CastService* cast_service);
- void SetRemoteDebuggingServer(RemoteDebuggingServer* remote_debugging_server);
- void SetMetricsHelper(metrics::CastMetricsHelper* metrics_helper);
+ void SetBrowserContext(scoped_ptr<CastBrowserContext> browser_context);
+ void SetCastService(scoped_ptr<CastService> cast_service);
+ void SetMetricsHelper(scoped_ptr<metrics::CastMetricsHelper> metrics_helper);
void SetMetricsServiceClient(
- metrics::CastMetricsServiceClient* metrics_service_client);
+ scoped_ptr<metrics::CastMetricsServiceClient> metrics_service_client);
+ void SetPrefService(scoped_ptr<PrefService> pref_service);
+ void SetRemoteDebuggingServer(
+ scoped_ptr<RemoteDebuggingServer> remote_debugging_server);
+ void SetResourceDispatcherHostDelegate(
+ scoped_ptr<CastResourceDispatcherHostDelegate> delegate);
#if defined(OS_ANDROID)
- void SetCrashDumpManager(breakpad::CrashDumpManager* crash_dump_manager);
+ void SetCrashDumpManager(
+ scoped_ptr<breakpad::CrashDumpManager> crash_dump_manager);
#endif // defined(OS_ANDROID)
+ void SetConnectivityChecker(
+ scoped_refptr<ConnectivityChecker> connectivity_checker);
CastBrowserContext* browser_context() const { return browser_context_.get(); }
CastService* cast_service() const { return cast_service_.get(); }
metrics::CastMetricsServiceClient* metrics_service_client() const {
return metrics_service_client_.get();
}
+ PrefService* pref_service() const { return pref_service_.get(); }
+ CastResourceDispatcherHostDelegate* resource_dispatcher_host_delegate()
+ const {
+ return resource_dispatcher_host_delegate_.get();
+ }
+ ConnectivityChecker* connectivity_checker() const {
+ return connectivity_checker_.get();
+ }
private:
- scoped_ptr<CastBrowserContext> browser_context_;
+ // Note: The following order should match the order they are set in
+ // CastBrowserMainParts.
scoped_ptr<metrics::CastMetricsHelper> metrics_helper_;
+ scoped_ptr<PrefService> pref_service_;
+ scoped_refptr<ConnectivityChecker> connectivity_checker_;
+ scoped_ptr<CastBrowserContext> browser_context_;
scoped_ptr<metrics::CastMetricsServiceClient> metrics_service_client_;
- scoped_ptr<RemoteDebuggingServer> remote_debugging_server_;
+ scoped_ptr<CastResourceDispatcherHostDelegate>
+ resource_dispatcher_host_delegate_;
#if defined(OS_ANDROID)
scoped_ptr<breakpad::CrashDumpManager> crash_dump_manager_;
#endif // defined(OS_ANDROID)
+ scoped_ptr<RemoteDebuggingServer> remote_debugging_server_;
// Note: CastService must be destroyed before others.
scoped_ptr<CastService> cast_service_;
diff --git a/chromium/chromecast/browser/cast_content_browser_client.cc b/chromium/chromecast/browser/cast_content_browser_client.cc
index 397603d8e1a..3e075faadf7 100644
--- a/chromium/chromecast/browser/cast_content_browser_client.cc
+++ b/chromium/chromecast/browser/cast_content_browser_client.cc
@@ -4,42 +4,57 @@
#include "chromecast/browser/cast_content_browser_client.h"
+#include <string>
+
+#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/files/scoped_file.h"
+#include "base/i18n/icu_util.h"
#include "base/i18n/rtl.h"
#include "base/path_service.h"
+#include "chromecast/base/cast_paths.h"
#include "chromecast/browser/cast_browser_context.h"
#include "chromecast/browser/cast_browser_main_parts.h"
#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/cast_network_delegate.h"
-#include "chromecast/browser/devtools/cast_dev_tools_delegate.h"
+#include "chromecast/browser/cast_quota_permission_context.h"
+#include "chromecast/browser/cast_resource_dispatcher_host_delegate.h"
#include "chromecast/browser/geolocation/cast_access_token_store.h"
+#include "chromecast/browser/media/cma_message_filter_host.h"
#include "chromecast/browser/url_request_context_factory.h"
-#include "chromecast/common/cast_paths.h"
+#include "chromecast/common/chromecast_switches.h"
#include "chromecast/common/global_descriptors.h"
#include "components/crash/app/breakpad_linux.h"
+#include "components/crash/browser/crash_handler_host_linux.h"
+#include "components/network_hints/browser/network_hints_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/certificate_request_result_type.h"
+#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_dispatcher_host.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
+#include "gin/v8_initializer.h"
+#include "media/audio/audio_manager_factory.h"
#include "net/ssl/ssl_cert_request_info.h"
-
-#if defined(OS_ANDROID)
-#include "chromecast/browser/android/external_video_surface_container_impl.h"
-#endif // defined(OS_ANDROID)
+#include "net/url_request/url_request_context_getter.h"
+#include "ui/gl/gl_switches.h"
#if defined(OS_ANDROID)
#include "components/crash/browser/crash_dump_manager_android.h"
+#include "components/external_video_surface/browser/android/external_video_surface_container_impl.h"
#endif // defined(OS_ANDROID)
namespace chromecast {
namespace shell {
CastContentBrowserClient::CastContentBrowserClient()
- : url_request_context_factory_(new URLRequestContextFactory()) {
+ : v8_natives_fd_(-1),
+ v8_snapshot_fd_(-1),
+ url_request_context_factory_(new URLRequestContextFactory()) {
}
CastContentBrowserClient::~CastContentBrowserClient() {
@@ -52,11 +67,47 @@ CastContentBrowserClient::~CastContentBrowserClient() {
content::BrowserMainParts* CastContentBrowserClient::CreateBrowserMainParts(
const content::MainFunctionParams& parameters) {
return new CastBrowserMainParts(parameters,
- url_request_context_factory_.get());
+ url_request_context_factory_.get(),
+ PlatformCreateAudioManagerFactory());
}
void CastContentBrowserClient::RenderProcessWillLaunch(
content::RenderProcessHost* host) {
+#if !defined(OS_ANDROID)
+ scoped_refptr<media::CmaMessageFilterHost> cma_message_filter(
+ new media::CmaMessageFilterHost(host->GetID()));
+ host->AddFilter(cma_message_filter.get());
+#endif // !defined(OS_ANDROID)
+
+ // Forcibly trigger I/O-thread URLRequestContext initialization before
+ // getting HostResolver.
+ content::BrowserThread::PostTaskAndReplyWithResult(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&net::URLRequestContextGetter::GetURLRequestContext,
+ base::Unretained(
+ url_request_context_factory_->GetSystemGetter())),
+ base::Bind(&CastContentBrowserClient::AddNetworkHintsMessageFilter,
+ base::Unretained(this), host->GetID()));
+
+ auto extra_filters = PlatformGetBrowserMessageFilters();
+ for (auto const& filter : extra_filters) {
+ host->AddFilter(filter.get());
+ }
+}
+
+void CastContentBrowserClient::AddNetworkHintsMessageFilter(
+ int render_process_id, net::URLRequestContext* context) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id);
+ if (!host)
+ return;
+
+ scoped_refptr<content::BrowserMessageFilter> network_hints_message_filter(
+ new network_hints::NetworkHintsMessageFilter(
+ url_request_context_factory_->host_resolver()));
+ host->AddFilter(network_hints_message_filter.get());
}
net::URLRequestContextGetter* CastContentBrowserClient::CreateRequestContext(
@@ -79,9 +130,6 @@ bool CastContentBrowserClient::IsHandledURL(const GURL& url) {
content::kChromeUIScheme,
content::kChromeDevToolsScheme,
url::kDataScheme,
-#if defined(OS_ANDROID)
- url::kFileScheme,
-#endif // defined(OS_ANDROID)
};
const std::string& scheme = url.scheme();
@@ -89,6 +137,12 @@ bool CastContentBrowserClient::IsHandledURL(const GURL& url) {
if (scheme == kProtocolList[i])
return true;
}
+
+ if (scheme == url::kFileScheme) {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableLocalFileAccesses);
+ }
+
return false;
}
@@ -98,15 +152,42 @@ void CastContentBrowserClient::AppendExtraCommandLineSwitches(
std::string process_type =
command_line->GetSwitchValueNative(switches::kProcessType);
+ base::CommandLine* browser_command_line =
+ base::CommandLine::ForCurrentProcess();
+
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+ if (process_type != switches::kZygoteProcess) {
+ command_line->AppendSwitch(::switches::kV8NativesPassedByFD);
+ command_line->AppendSwitch(::switches::kV8SnapshotPassedByFD);
+ }
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+
+ // IsCrashReporterEnabled() is set when InitCrashReporter() is called, and
+ // controlled by GetBreakpadClient()->EnableBreakpadForProcess(), therefore
+ // it's ok to add switch to every process here.
+ if (breakpad::IsCrashReporterEnabled()) {
+ command_line->AppendSwitch(switches::kEnableCrashReporter);
+ }
// Renderer process command-line
if (process_type == switches::kRendererProcess) {
// Any browser command-line switches that should be propagated to
// the renderer go here.
-#if defined(OS_ANDROID)
- command_line->AppendSwitch(switches::kForceUseOverlayEmbeddedVideo);
-#endif // defined(OS_ANDROID)
+
+ if (browser_command_line->HasSwitch(switches::kEnableCmaMediaPipeline))
+ command_line->AppendSwitch(switches::kEnableCmaMediaPipeline);
}
+
+#if defined(OS_LINUX)
+ // Necessary for accelerated 2d canvas. By default on Linux, Chromium assumes
+ // GLES2 contexts can be lost to a power-save mode, which breaks GPU canvas
+ // apps.
+ if (process_type == switches::kGpuProcess) {
+ command_line->AppendSwitch(switches::kGpuNoContextLost);
+ }
+#endif
+
+ PlatformAppendExtraCommandLineSwitches(command_line);
}
content::AccessTokenStore* CastContentBrowserClient::CreateAccessTokenStore() {
@@ -116,7 +197,6 @@ content::AccessTokenStore* CastContentBrowserClient::CreateAccessTokenStore() {
void CastContentBrowserClient::OverrideWebkitPrefs(
content::RenderViewHost* render_view_host,
- const GURL& url,
content::WebPreferences* prefs) {
prefs->allow_scripts_to_close_windows = true;
// TODO(lcwu): http://crbug.com/391089. This pref is set to true by default
@@ -126,11 +206,23 @@ void CastContentBrowserClient::OverrideWebkitPrefs(
prefs->allow_running_insecure_content = true;
}
+void CastContentBrowserClient::ResourceDispatcherHostCreated() {
+ CastBrowserProcess::GetInstance()->SetResourceDispatcherHostDelegate(
+ make_scoped_ptr(new CastResourceDispatcherHostDelegate));
+ content::ResourceDispatcherHost::Get()->SetDelegate(
+ CastBrowserProcess::GetInstance()->resource_dispatcher_host_delegate());
+}
+
std::string CastContentBrowserClient::GetApplicationLocale() {
const std::string locale(base::i18n::GetConfiguredLocale());
return locale.empty() ? "en-US" : locale;
}
+content::QuotaPermissionContext*
+CastContentBrowserClient::CreateQuotaPermissionContext() {
+ return new CastQuotaPermissionContext();
+}
+
void CastContentBrowserClient::AllowCertificateError(
int render_process_id,
int render_view_id,
@@ -150,16 +242,15 @@ void CastContentBrowserClient::AllowCertificateError(
}
void CastContentBrowserClient::SelectClientCertificate(
- int render_process_id,
- int render_view_id,
+ content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
- const base::Callback<void(net::X509Certificate*)>& callback) {
+ scoped_ptr<content::ClientCertificateDelegate> delegate) {
GURL requesting_url("https://" + cert_request_info->host_and_port.ToString());
if (!requesting_url.is_valid()) {
LOG(ERROR) << "Invalid URL string: "
<< requesting_url.possibly_invalid_spec();
- callback.Run(NULL);
+ delegate->ContinueWithCertificate(nullptr);
return;
}
@@ -170,28 +261,33 @@ void CastContentBrowserClient::SelectClientCertificate(
// it, because CastNetworkDelegate is bound to the IO thread.
// Subsequently, the callback must then itself be performed back here
// on the UI thread.
+ //
+ // TODO(davidben): Stop using child ID to identify an app.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserThread::PostTaskAndReplyWithResult(
- content::BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &CastContentBrowserClient::SelectClientCertificateOnIOThread,
- base::Unretained(this),
- requesting_url),
- callback);
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CastContentBrowserClient::SelectClientCertificateOnIOThread,
+ base::Unretained(this), requesting_url,
+ web_contents->GetRenderProcessHost()->GetID()),
+ base::Bind(&content::ClientCertificateDelegate::ContinueWithCertificate,
+ base::Owned(delegate.release())));
}
net::X509Certificate*
CastContentBrowserClient::SelectClientCertificateOnIOThread(
- GURL requesting_url) {
+ GURL requesting_url,
+ int render_process_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
CastNetworkDelegate* network_delegate =
url_request_context_factory_->app_network_delegate();
- if (network_delegate->IsWhitelisted(requesting_url, false)) {
+ if (network_delegate->IsWhitelisted(requesting_url,
+ render_process_id, false)) {
return CastNetworkDelegate::DeviceCert();
} else {
LOG(ERROR) << "Invalid host for client certificate request: "
- << requesting_url.host();
+ << requesting_url.host()
+ << " with render_process_id: "
+ << render_process_id;
return NULL;
}
}
@@ -215,27 +311,35 @@ bool CastContentBrowserClient::CanCreateWindow(
return false;
}
-content::DevToolsManagerDelegate*
-CastContentBrowserClient::GetDevToolsManagerDelegate() {
- return new CastDevToolsManagerDelegate();
-}
-
void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line,
int child_process_id,
content::FileDescriptorInfo* mappings) {
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+ if (v8_natives_fd_.get() == -1 || v8_snapshot_fd_.get() == -1) {
+ int v8_natives_fd = -1;
+ int v8_snapshot_fd = -1;
+ if (gin::V8Initializer::OpenV8FilesForChildProcesses(&v8_natives_fd,
+ &v8_snapshot_fd)) {
+ v8_natives_fd_.reset(v8_natives_fd);
+ v8_snapshot_fd_.reset(v8_snapshot_fd);
+ }
+ }
+ DCHECK(v8_natives_fd_.get() != -1 && v8_snapshot_fd_.get() != -1);
+ mappings->Share(kV8NativesDataDescriptor, v8_natives_fd_.get());
+ mappings->Share(kV8SnapshotDataDescriptor, v8_snapshot_fd_.get());
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
#if defined(OS_ANDROID)
- int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
- base::FilePath pak_file;
- CHECK(PathService::Get(FILE_CAST_PAK, &pak_file));
- base::File pak_with_flags(pak_file, flags);
- if (!pak_with_flags.IsValid()) {
+ const int flags_open_read = base::File::FLAG_OPEN | base::File::FLAG_READ;
+ base::FilePath pak_file_path;
+ CHECK(PathService::Get(FILE_CAST_PAK, &pak_file_path));
+ base::File pak_file(pak_file_path, flags_open_read);
+ if (!pak_file.IsValid()) {
NOTREACHED() << "Failed to open file when creating renderer process: "
<< "cast_shell.pak";
}
- mappings->Transfer(
- kAndroidPakDescriptor,
- base::ScopedFD(pak_with_flags.TakePlatformFile()));
+ mappings->Transfer(kAndroidPakDescriptor,
+ base::ScopedFD(pak_file.TakePlatformFile()));
if (breakpad::IsCrashReporterEnabled()) {
base::File minidump_file(
@@ -249,6 +353,21 @@ void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
base::ScopedFD(minidump_file.TakePlatformFile()));
}
}
+
+ base::FilePath app_data_path;
+ CHECK(PathService::Get(base::DIR_ANDROID_APP_DATA, &app_data_path));
+ base::FilePath icudata_path =
+ app_data_path.AppendASCII(base::i18n::kIcuDataFileName);
+ base::File icudata_file(icudata_path, flags_open_read);
+ if (!icudata_file.IsValid())
+ NOTREACHED() << "Failed to open ICU file when creating renderer process";
+ mappings->Transfer(kAndroidICUDataDescriptor,
+ base::ScopedFD(icudata_file.TakePlatformFile()));
+#else
+ int crash_signal_fd = GetCrashSignalFD(command_line);
+ if (crash_signal_fd >= 0) {
+ mappings->Share(kCrashDumpSignal, crash_signal_fd);
+ }
#endif // defined(OS_ANDROID)
}
@@ -256,10 +375,49 @@ void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
content::ExternalVideoSurfaceContainer*
CastContentBrowserClient::OverrideCreateExternalVideoSurfaceContainer(
content::WebContents* web_contents) {
- return new ExternalVideoSurfaceContainerImpl(web_contents);
+ return external_video_surface::ExternalVideoSurfaceContainerImpl::Create(
+ web_contents);
}
#endif // defined(OS_ANDROID) && defined(VIDEO_HOLE)
+#if !defined(OS_ANDROID)
+int CastContentBrowserClient::GetCrashSignalFD(
+ const base::CommandLine& command_line) {
+ std::string process_type =
+ command_line.GetSwitchValueASCII(switches::kProcessType);
+
+ if (process_type == switches::kRendererProcess ||
+ process_type == switches::kGpuProcess) {
+ breakpad::CrashHandlerHostLinux* crash_handler =
+ crash_handlers_[process_type];
+ if (!crash_handler) {
+ crash_handler = CreateCrashHandlerHost(process_type);
+ crash_handlers_[process_type] = crash_handler;
+ }
+ return crash_handler->GetDeathSignalSocket();
+ }
+
+ return -1;
+}
+
+breakpad::CrashHandlerHostLinux*
+CastContentBrowserClient::CreateCrashHandlerHost(
+ const std::string& process_type) {
+ // Let cast shell dump to /tmp. Internal minidump generator code can move it
+ // to /data/minidumps later, since /data/minidumps is file lock-controlled.
+ base::FilePath dumps_path;
+ PathService::Get(base::DIR_TEMP, &dumps_path);
+
+ // Alway set "upload" to false to use our own uploader.
+ breakpad::CrashHandlerHostLinux* crash_handler =
+ new breakpad::CrashHandlerHostLinux(
+ process_type, dumps_path, false /* upload */);
+ // StartUploaderThread() even though upload is diferred.
+ // Breakpad-related memory is freed in the uploader thread.
+ crash_handler->StartUploaderThread();
+ return crash_handler;
+}
+#endif // !defined(OS_ANDROID)
} // namespace shell
} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_content_browser_client.h b/chromium/chromecast/browser/cast_content_browser_client.h
index 00ae07228f7..5e5c262f92a 100644
--- a/chromium/chromecast/browser/cast_content_browser_client.h
+++ b/chromium/chromecast/browser/cast_content_browser_client.h
@@ -5,10 +5,30 @@
#ifndef CHROMECAST_BROWSER_CAST_CONTENT_BROWSER_CLIENT_H_
#define CHROMECAST_BROWSER_CAST_CONTENT_BROWSER_CLIENT_H_
+#include <map>
+#include <string>
+#include <vector>
+
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/content_browser_client.h"
+namespace breakpad {
+class CrashHandlerHostLinux;
+}
+
+namespace content {
+class BrowserMessageFilter;
+}
+
+namespace media {
+class AudioManagerFactory;
+}
+
+namespace net {
+class HostResolver;
+}
+
namespace chromecast {
namespace shell {
@@ -18,27 +38,35 @@ class URLRequestContextFactory;
class CastContentBrowserClient: public content::ContentBrowserClient {
public:
CastContentBrowserClient();
- virtual ~CastContentBrowserClient();
+ ~CastContentBrowserClient() override;
+
+ // Appends extra command line arguments before launching a new process.
+ void PlatformAppendExtraCommandLineSwitches(base::CommandLine* command_line);
+
+ // Returns any BrowserMessageFilters from the platform implementation that
+ // should be added when launching a new render process.
+ std::vector<scoped_refptr<content::BrowserMessageFilter>>
+ PlatformGetBrowserMessageFilters();
// content::ContentBrowserClient implementation:
- virtual content::BrowserMainParts* CreateBrowserMainParts(
+ content::BrowserMainParts* CreateBrowserMainParts(
const content::MainFunctionParams& parameters) override;
- virtual void RenderProcessWillLaunch(
- content::RenderProcessHost* host) override;
- virtual net::URLRequestContextGetter* CreateRequestContext(
+ void RenderProcessWillLaunch(content::RenderProcessHost* host) override;
+ net::URLRequestContextGetter* CreateRequestContext(
content::BrowserContext* browser_context,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors)
override;
- virtual bool IsHandledURL(const GURL& url) override;
- virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
- int child_process_id) override;
- virtual content::AccessTokenStore* CreateAccessTokenStore() override;
- virtual void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
- const GURL& url,
- content::WebPreferences* prefs) override;
- virtual std::string GetApplicationLocale() override;
- virtual void AllowCertificateError(
+ bool IsHandledURL(const GURL& url) override;
+ void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
+ int child_process_id) override;
+ content::AccessTokenStore* CreateAccessTokenStore() override;
+ void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
+ content::WebPreferences* prefs) override;
+ void ResourceDispatcherHostCreated() override;
+ std::string GetApplicationLocale() override;
+ content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
+ void AllowCertificateError(
int render_process_id,
int render_view_id,
int cert_error,
@@ -50,12 +78,11 @@ class CastContentBrowserClient: public content::ContentBrowserClient {
bool expired_previous_decision,
const base::Callback<void(bool)>& callback,
content::CertificateRequestResultType* result) override;
- virtual void SelectClientCertificate(
- int render_process_id,
- int render_frame_id,
+ void SelectClientCertificate(
+ content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
- const base::Callback<void(net::X509Certificate*)>& callback) override;
- virtual bool CanCreateWindow(
+ scoped_ptr<content::ClientCertificateDelegate> delegate) override;
+ bool CanCreateWindow(
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
@@ -70,21 +97,40 @@ class CastContentBrowserClient: public content::ContentBrowserClient {
int render_process_id,
int opener_id,
bool* no_javascript_access) override;
- virtual content::DevToolsManagerDelegate*
- GetDevToolsManagerDelegate() override;
- virtual void GetAdditionalMappedFilesForChildProcess(
+ void GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line,
int child_process_id,
content::FileDescriptorInfo* mappings) override;
#if defined(OS_ANDROID) && defined(VIDEO_HOLE)
- virtual content::ExternalVideoSurfaceContainer*
+ content::ExternalVideoSurfaceContainer*
OverrideCreateExternalVideoSurfaceContainer(
content::WebContents* web_contents) override;
#endif // defined(OS_ANDROID) && defined(VIDEO_HOLE)
private:
+ void AddNetworkHintsMessageFilter(int render_process_id,
+ net::URLRequestContext* context);
+
net::X509Certificate* SelectClientCertificateOnIOThread(
- GURL requesting_url);
+ GURL requesting_url,
+ int render_process_id);
+
+ scoped_ptr<::media::AudioManagerFactory> PlatformCreateAudioManagerFactory();
+
+#if !defined(OS_ANDROID)
+ // Returns the crash signal FD corresponding to the current process type.
+ int GetCrashSignalFD(const base::CommandLine& command_line);
+
+ // Creates a CrashHandlerHost instance for the given process type.
+ breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
+ const std::string& process_type);
+
+ // A static cache to hold crash_handlers for each process_type
+ std::map<std::string, breakpad::CrashHandlerHostLinux*> crash_handlers_;
+#endif
+
+ base::ScopedFD v8_natives_fd_;
+ base::ScopedFD v8_snapshot_fd_;
scoped_ptr<URLRequestContextFactory> url_request_context_factory_;
diff --git a/chromium/chromecast/browser/cast_content_browser_client_simple.cc b/chromium/chromecast/browser/cast_content_browser_client_simple.cc
new file mode 100644
index 00000000000..bde5a71d028
--- /dev/null
+++ b/chromium/chromecast/browser/cast_content_browser_client_simple.cc
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/cast_content_browser_client.h"
+
+#include "content/public/browser/browser_message_filter.h"
+#include "media/audio/audio_manager_factory.h"
+
+namespace chromecast {
+namespace shell {
+
+void CastContentBrowserClient::PlatformAppendExtraCommandLineSwitches(
+ base::CommandLine* command_line) {
+}
+
+std::vector<scoped_refptr<content::BrowserMessageFilter>>
+CastContentBrowserClient::PlatformGetBrowserMessageFilters() {
+ return std::vector<scoped_refptr<content::BrowserMessageFilter>>();
+}
+
+scoped_ptr<::media::AudioManagerFactory>
+CastContentBrowserClient::PlatformCreateAudioManagerFactory() {
+ // Return nullptr. The factory will not be set, and the statically linked
+ // implementation of AudioManager will be used.
+ return scoped_ptr<::media::AudioManagerFactory>();
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_content_window.cc b/chromium/chromecast/browser/cast_content_window.cc
index 8cf64b33295..27c91b74cb4 100644
--- a/chromium/chromecast/browser/cast_content_window.cc
+++ b/chromium/chromecast/browser/cast_content_window.cc
@@ -5,12 +5,14 @@
#include "chromecast/browser/cast_content_window.h"
#include "base/threading/thread_restrictions.h"
+#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message.h"
#if defined(USE_AURA)
#include "ui/aura/env.h"
#include "ui/aura/layout_manager.h"
+#include "ui/aura/test/test_focus_client.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
@@ -22,24 +24,24 @@ namespace chromecast {
class CastFillLayout : public aura::LayoutManager {
public:
explicit CastFillLayout(aura::Window* root) : root_(root) {}
- virtual ~CastFillLayout() {}
+ ~CastFillLayout() override {}
private:
- virtual void OnWindowResized() override {}
+ void OnWindowResized() override {}
- virtual void OnWindowAddedToLayout(aura::Window* child) override {
+ void OnWindowAddedToLayout(aura::Window* child) override {
child->SetBounds(root_->bounds());
}
- virtual void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
+ void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
- virtual void OnWindowRemovedFromLayout(aura::Window* child) override {}
+ void OnWindowRemovedFromLayout(aura::Window* child) override {}
- virtual void OnChildWindowVisibilityChanged(aura::Window* child,
- bool visible) override {}
+ void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) override {}
- virtual void SetChildBounds(aura::Window* child,
- const gfx::Rect& requested_bounds) override {
+ void SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) override {
SetChildBoundsDirect(child, requested_bounds);
}
@@ -59,9 +61,9 @@ CastContentWindow::~CastContentWindow() {
#endif
}
-scoped_ptr<content::WebContents> CastContentWindow::Create(
+void CastContentWindow::CreateWindowTree(
const gfx::Size& initial_size,
- content::BrowserContext* browser_context) {
+ content::WebContents* web_contents) {
#if defined(USE_AURA)
// Aura initialization
// TODO(lcwu): We only need a minimal implementation of gfx::Screen
@@ -83,16 +85,14 @@ scoped_ptr<content::WebContents> CastContentWindow::Create(
window_tree_host_->InitHost();
window_tree_host_->window()->SetLayoutManager(
new CastFillLayout(window_tree_host_->window()));
- window_tree_host_->Show();
-#endif
+ window_tree_host_->compositor()->SetBackgroundColor(SK_ColorBLACK);
- content::WebContents::CreateParams create_params(browser_context, NULL);
- create_params.routing_id = MSG_ROUTING_NONE;
- create_params.initial_size = initial_size;
- content::WebContents* web_contents = content::WebContents::Create(
- create_params);
+ focus_client_.reset(new aura::test::TestFocusClient());
+ aura::client::SetFocusClient(
+ window_tree_host_->window(), focus_client_.get());
+
+ window_tree_host_->Show();
-#if defined(USE_AURA)
// Add and show content's view/window
aura::Window* content_window = web_contents->GetNativeView();
aura::Window* parent = window_tree_host_->window();
@@ -101,8 +101,30 @@ scoped_ptr<content::WebContents> CastContentWindow::Create(
}
content_window->Show();
#endif
+}
+scoped_ptr<content::WebContents> CastContentWindow::CreateWebContents(
+ const gfx::Size& initial_size,
+ content::BrowserContext* browser_context) {
+ content::WebContents::CreateParams create_params(browser_context, NULL);
+ create_params.routing_id = MSG_ROUTING_NONE;
+ create_params.initial_size = initial_size;
+ content::WebContents* web_contents = content::WebContents::Create(
+ create_params);
+ content::WebContentsObserver::Observe(web_contents);
return make_scoped_ptr(web_contents);
}
+void CastContentWindow::DidFirstVisuallyNonEmptyPaint() {
+ metrics::CastMetricsHelper::GetInstance()->LogTimeToFirstPaint();
+}
+
+void CastContentWindow::MediaPaused() {
+ metrics::CastMetricsHelper::GetInstance()->LogMediaPause();
+}
+
+void CastContentWindow::MediaStartedPlaying() {
+ metrics::CastMetricsHelper::GetInstance()->LogMediaPlay();
+}
+
} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_content_window.h b/chromium/chromecast/browser/cast_content_window.h
index 7101db1f00a..1360a5e0ca4 100644
--- a/chromium/chromecast/browser/cast_content_window.h
+++ b/chromium/chromecast/browser/cast_content_window.h
@@ -7,10 +7,14 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/web_contents_observer.h"
namespace aura {
class WindowTreeHost;
-}
+namespace test {
+class TestFocusClient;
+} // namespace test
+} // namespace aura
namespace content {
class BrowserContext;
@@ -23,21 +27,30 @@ class Size;
namespace chromecast {
-class CastContentWindow {
+class CastContentWindow : public content::WebContentsObserver {
public:
CastContentWindow();
// Removes the window from the screen.
- ~CastContentWindow();
+ ~CastContentWindow() override;
+
+ // Create a window with the given size for |web_contents|.
+ void CreateWindowTree(const gfx::Size& initial_size,
+ content::WebContents* web_contents);
- // Create a window with the given size.
- scoped_ptr<content::WebContents> Create(
+ scoped_ptr<content::WebContents> CreateWebContents(
const gfx::Size& initial_size,
content::BrowserContext* browser_context);
+ // content::WebContentsObserver implementation:
+ void DidFirstVisuallyNonEmptyPaint() override;
+ void MediaPaused() override;
+ void MediaStartedPlaying() override;
+
private:
#if defined(USE_AURA)
scoped_ptr<aura::WindowTreeHost> window_tree_host_;
+ scoped_ptr<aura::test::TestFocusClient> focus_client_;
#endif
DISALLOW_COPY_AND_ASSIGN(CastContentWindow);
diff --git a/chromium/chromecast/browser/cast_download_manager_delegate.h b/chromium/chromecast/browser/cast_download_manager_delegate.h
index d77e07f1da9..e6c963f131f 100644
--- a/chromium/chromecast/browser/cast_download_manager_delegate.h
+++ b/chromium/chromecast/browser/cast_download_manager_delegate.h
@@ -14,20 +14,18 @@ namespace shell {
class CastDownloadManagerDelegate : public content::DownloadManagerDelegate {
public:
CastDownloadManagerDelegate();
- virtual ~CastDownloadManagerDelegate();
+ ~CastDownloadManagerDelegate() override;
// content::DownloadManagerDelegate implementation:
- virtual void GetNextId(
- const content::DownloadIdCallback& callback) override;
- virtual bool DetermineDownloadTarget(
+ void GetNextId(const content::DownloadIdCallback& callback) override;
+ bool DetermineDownloadTarget(
content::DownloadItem* item,
const content::DownloadTargetCallback& callback) override;
- virtual bool ShouldOpenFileBasedOnExtension(
- const base::FilePath& path) override;
- virtual bool ShouldCompleteDownload(
+ bool ShouldOpenFileBasedOnExtension(const base::FilePath& path) override;
+ bool ShouldCompleteDownload(
content::DownloadItem* item,
const base::Closure& complete_callback) override;
- virtual bool ShouldOpenDownload(
+ bool ShouldOpenDownload(
content::DownloadItem* item,
const content::DownloadOpenDelayedCallback& callback) override;
@@ -38,4 +36,4 @@ class CastDownloadManagerDelegate : public content::DownloadManagerDelegate {
} // namespace shell
} // namespace chromecast
-#endif // CHROMECAST_BROWSER_CAST_DOWNLOAD_MANAGER_DELEGATE_H_ \ No newline at end of file
+#endif // CHROMECAST_BROWSER_CAST_DOWNLOAD_MANAGER_DELEGATE_H_
diff --git a/chromium/chromecast/browser/cast_http_user_agent_settings.cc b/chromium/chromecast/browser/cast_http_user_agent_settings.cc
index 9eb27058666..ef752dc3287 100644
--- a/chromium/chromecast/browser/cast_http_user_agent_settings.cc
+++ b/chromium/chromecast/browser/cast_http_user_agent_settings.cc
@@ -4,6 +4,7 @@
#include "chromecast/browser/cast_http_user_agent_settings.h"
+#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "chromecast/common/cast_content_client.h"
#include "content/public/browser/browser_thread.h"
@@ -19,23 +20,33 @@ namespace chromecast {
namespace shell {
CastHttpUserAgentSettings::CastHttpUserAgentSettings() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
CastHttpUserAgentSettings::~CastHttpUserAgentSettings() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
std::string CastHttpUserAgentSettings::GetAcceptLanguage() const {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
- if (accept_language_.empty()) {
+ std::string new_locale(
+#if defined(OS_ANDROID)
+ // TODO(byungchul): Use transient locale set when new app starts.
+ base::android::GetDefaultLocale()
+#else
+ base::i18n::GetConfiguredLocale()
+#endif
+ );
+ if (new_locale != last_locale_ || accept_language_.empty()) {
+ last_locale_ = new_locale;
accept_language_ = net::HttpUtil::GenerateAcceptLanguageHeader(
#if defined(OS_ANDROID)
- base::android::GetDefaultLocale()
+ last_locale_
#else
l10n_util::GetStringUTF8(IDS_CHROMECAST_SETTINGS_ACCEPT_LANGUAGES)
-#endif // defined(OS_ANDROID)
+#endif
);
+ LOG(INFO) << "Locale changed: accept_language=" << accept_language_;
}
return accept_language_;
}
diff --git a/chromium/chromecast/browser/cast_http_user_agent_settings.h b/chromium/chromecast/browser/cast_http_user_agent_settings.h
index 90a432b11b5..8deb7f2585a 100644
--- a/chromium/chromecast/browser/cast_http_user_agent_settings.h
+++ b/chromium/chromecast/browser/cast_http_user_agent_settings.h
@@ -7,7 +7,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/prefs/pref_member.h"
#include "net/url_request/http_user_agent_settings.h"
namespace chromecast {
@@ -16,13 +15,14 @@ namespace shell {
class CastHttpUserAgentSettings : public net::HttpUserAgentSettings {
public:
CastHttpUserAgentSettings();
- virtual ~CastHttpUserAgentSettings();
+ ~CastHttpUserAgentSettings() override;
// net::HttpUserAgentSettings implementation:
- virtual std::string GetAcceptLanguage() const override;
- virtual std::string GetUserAgent() const override;
+ std::string GetAcceptLanguage() const override;
+ std::string GetUserAgent() const override;
private:
+ mutable std::string last_locale_;
mutable std::string accept_language_;
DISALLOW_COPY_AND_ASSIGN(CastHttpUserAgentSettings);
diff --git a/chromium/chromecast/browser/cast_network_delegate.cc b/chromium/chromecast/browser/cast_network_delegate.cc
index ff0fcc958e2..51d9fd4aa5b 100644
--- a/chromium/chromecast/browser/cast_network_delegate.cc
+++ b/chromium/chromecast/browser/cast_network_delegate.cc
@@ -20,13 +20,10 @@ CastNetworkDelegate::~CastNetworkDelegate() {
bool CastNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
const base::FilePath& path) const {
-#if defined(OS_ANDROID)
- // On Chromecast, there's no reason to allow local file access.
if (base::CommandLine::ForCurrentProcess()->
HasSwitch(switches::kEnableLocalFileAccesses)) {
return true;
}
-#endif // defined(OS_ANDROID)
LOG(WARNING) << "Could not access file " << path.value()
<< ". All file accesses are forbidden.";
diff --git a/chromium/chromecast/browser/cast_network_delegate.h b/chromium/chromecast/browser/cast_network_delegate.h
index 982237f8630..f3372ebbd88 100644
--- a/chromium/chromecast/browser/cast_network_delegate.h
+++ b/chromium/chromecast/browser/cast_network_delegate.h
@@ -5,7 +5,7 @@
#ifndef CHROMECAST_BROWSER_CAST_NETWORK_DELEGATE_H_
#define CHROMECAST_BROWSER_CAST_NETWORK_DELEGATE_H_
-#include "net/base/network_delegate.h"
+#include "net/base/network_delegate_impl.h"
namespace net {
class X509Certificate;
@@ -14,22 +14,23 @@ class X509Certificate;
namespace chromecast {
namespace shell {
-class CastNetworkDelegate : public net::NetworkDelegate {
+class CastNetworkDelegate : public net::NetworkDelegateImpl {
public:
static CastNetworkDelegate* Create();
static net::X509Certificate* DeviceCert();
CastNetworkDelegate();
- virtual ~CastNetworkDelegate();
+ ~CastNetworkDelegate() override;
virtual void Initialize(bool use_sync_signing) = 0;
- virtual bool IsWhitelisted(const GURL& gurl, bool for_device_auth) const = 0;
+ virtual bool IsWhitelisted(const GURL& gurl, int render_process_id,
+ bool for_device_auth) const = 0;
private:
// net::NetworkDelegate implementation:
- virtual bool OnCanAccessFile(const net::URLRequest& request,
- const base::FilePath& path) const override;
+ bool OnCanAccessFile(const net::URLRequest& request,
+ const base::FilePath& path) const override;
DISALLOW_COPY_AND_ASSIGN(CastNetworkDelegate);
};
diff --git a/chromium/chromecast/browser/cast_network_delegate_simple.cc b/chromium/chromecast/browser/cast_network_delegate_simple.cc
index 14aabf5d42d..2ba0cd6dae1 100644
--- a/chromium/chromecast/browser/cast_network_delegate_simple.cc
+++ b/chromium/chromecast/browser/cast_network_delegate_simple.cc
@@ -18,9 +18,9 @@ class CastNetworkDelegateSimple : public CastNetworkDelegate {
private:
// CastNetworkDelegate implementation:
- virtual void Initialize(bool use_sync_signing) override {}
- virtual bool IsWhitelisted(const GURL& gurl,
- bool for_device_auth) const override {
+ void Initialize(bool use_sync_signing) override {}
+ bool IsWhitelisted(const GURL& gurl, int render_process_id,
+ bool for_device_auth) const override {
return false;
}
diff --git a/chromium/chromecast/browser/cast_permission_manager.cc b/chromium/chromecast/browser/cast_permission_manager.cc
new file mode 100644
index 00000000000..54352c0db79
--- /dev/null
+++ b/chromium/chromecast/browser/cast_permission_manager.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/cast_permission_manager.h"
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "content/public/browser/permission_type.h"
+
+namespace chromecast {
+namespace shell {
+
+CastPermissionManager::CastPermissionManager()
+ : content::PermissionManager() {
+}
+
+CastPermissionManager::~CastPermissionManager() {
+}
+
+void CastPermissionManager::RequestPermission(
+ content::PermissionType permission,
+ content::WebContents* web_contents,
+ int request_id,
+ const GURL& origin,
+ bool user_gesture,
+ const base::Callback<void(content::PermissionStatus)>& callback) {
+ LOG(INFO) << __FUNCTION__ << ": " << static_cast<int>(permission);
+ callback.Run(content::PermissionStatus::PERMISSION_STATUS_GRANTED);
+}
+
+void CastPermissionManager::CancelPermissionRequest(
+ content::PermissionType permission,
+ content::WebContents* web_contents,
+ int request_id,
+ const GURL& origin) {
+}
+
+void CastPermissionManager::ResetPermission(
+ content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) {
+}
+
+content::PermissionStatus CastPermissionManager::GetPermissionStatus(
+ content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) {
+ LOG(INFO) << __FUNCTION__ << ": " << static_cast<int>(permission);
+ return content::PermissionStatus::PERMISSION_STATUS_GRANTED;
+}
+
+void CastPermissionManager::RegisterPermissionUsage(
+ content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) {
+}
+
+int CastPermissionManager::SubscribePermissionStatusChange(
+ content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ const base::Callback<void(content::PermissionStatus)>& callback) {
+ return -1;
+}
+
+void CastPermissionManager::UnsubscribePermissionStatusChange(
+ int subscription_id) {
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_permission_manager.h b/chromium/chromecast/browser/cast_permission_manager.h
new file mode 100644
index 00000000000..c82f08a4be2
--- /dev/null
+++ b/chromium/chromecast/browser/cast_permission_manager.h
@@ -0,0 +1,56 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_CAST_PERMISSION_MANAGER_H_
+#define CHROMECAST_BROWSER_CAST_PERMISSION_MANAGER_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "content/public/browser/permission_manager.h"
+
+namespace chromecast {
+namespace shell {
+
+class CastPermissionManager : public content::PermissionManager {
+ public:
+ CastPermissionManager();
+ ~CastPermissionManager() override;
+
+ // content::PermissionManager implementation:
+ void RequestPermission(
+ content::PermissionType permission,
+ content::WebContents* web_contents,
+ int request_id,
+ const GURL& requesting_origin,
+ bool user_gesture,
+ const base::Callback<void(content::PermissionStatus)>& callback) override;
+ void CancelPermissionRequest(content::PermissionType permission,
+ content::WebContents* web_contents,
+ int request_id,
+ const GURL& requesting_origin) override;
+ void ResetPermission(content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) override;
+ content::PermissionStatus GetPermissionStatus(
+ content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) override;
+ void RegisterPermissionUsage(content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) override;
+ int SubscribePermissionStatusChange(
+ content::PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ const base::Callback<void(content::PermissionStatus)>& callback) override;
+ void UnsubscribePermissionStatusChange(int subscription_id) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CastPermissionManager);
+};
+
+} // namespace shell
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_CAST_PERMISSION_MANAGER_H_
diff --git a/chromium/chromecast/browser/cast_quota_permission_context.cc b/chromium/chromecast/browser/cast_quota_permission_context.cc
new file mode 100644
index 00000000000..e0ca80460e9
--- /dev/null
+++ b/chromium/chromecast/browser/cast_quota_permission_context.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/cast_quota_permission_context.h"
+
+namespace chromecast {
+
+CastQuotaPermissionContext::CastQuotaPermissionContext() {
+}
+
+CastQuotaPermissionContext::~CastQuotaPermissionContext() {
+}
+
+void CastQuotaPermissionContext::RequestQuotaPermission(
+ const content::StorageQuotaParams& params,
+ int render_process_id,
+ const PermissionCallback& callback) {
+ callback.Run(
+ content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW);
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_quota_permission_context.h b/chromium/chromecast/browser/cast_quota_permission_context.h
new file mode 100644
index 00000000000..2dc418616c7
--- /dev/null
+++ b/chromium/chromecast/browser/cast_quota_permission_context.h
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_CAST_QUOTA_PERMISSION_CONTEXT_H_
+#define CHROMECAST_BROWSER_CAST_QUOTA_PERMISSION_CONTEXT_H_
+
+#include "base/macros.h"
+#include "content/public/browser/quota_permission_context.h"
+
+namespace chromecast {
+
+class CastQuotaPermissionContext : public content::QuotaPermissionContext {
+ public:
+ CastQuotaPermissionContext();
+
+ // content::QuotaPermissionContext implementation:
+ void RequestQuotaPermission(const content::StorageQuotaParams& params,
+ int render_process_id,
+ const PermissionCallback& callback) override;
+
+ private:
+ ~CastQuotaPermissionContext() override;
+
+ DISALLOW_COPY_AND_ASSIGN(CastQuotaPermissionContext);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_CAST_QUOTA_PERMISSION_CONTEXT_H_
diff --git a/chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.cc b/chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.cc
new file mode 100644
index 00000000000..9a935fb3923
--- /dev/null
+++ b/chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.cc
@@ -0,0 +1,26 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/cast_resource_dispatcher_host_delegate.h"
+
+#include "chromecast/browser/cast_browser_process.h"
+#include "chromecast/net/connectivity_checker.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
+
+namespace chromecast {
+namespace shell {
+
+void CastResourceDispatcherHostDelegate::RequestComplete(
+ net::URLRequest* url_request) {
+ if (!url_request->status().is_success()) {
+ LOG(ERROR) << "Failed to load resource " << url_request->url()
+ << "; status:" << url_request->status().status() << ", error:"
+ << net::ErrorToShortString(url_request->status().error());
+ CastBrowserProcess::GetInstance()->connectivity_checker()->Check();
+ }
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.h b/chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.h
new file mode 100644
index 00000000000..8295ccd0706
--- /dev/null
+++ b/chromium/chromecast/browser/cast_resource_dispatcher_host_delegate.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_CAST_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
+#define CHROMECAST_BROWSER_CAST_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
+
+#include "base/macros.h"
+#include "content/public/browser/resource_dispatcher_host_delegate.h"
+
+namespace chromecast {
+namespace shell {
+
+class CastResourceDispatcherHostDelegate
+ : public content::ResourceDispatcherHostDelegate {
+ public:
+ CastResourceDispatcherHostDelegate() {}
+
+ // content::ResourceDispatcherHostDelegate implementation:
+ void RequestComplete(net::URLRequest* url_request) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CastResourceDispatcherHostDelegate);
+};
+
+} // namespace shell
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_CAST_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
diff --git a/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.cc b/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.cc
index 354e384e228..93f17044a90 100644
--- a/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.cc
+++ b/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.cc
@@ -4,94 +4,13 @@
#include "chromecast/browser/devtools/cast_dev_tools_delegate.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/devtools_target.h"
-#include "content/public/browser/favicon_status.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
#include "grit/shell_resources.h"
#include "ui/base/resource/resource_bundle.h"
namespace chromecast {
namespace shell {
-namespace {
-
-const char kTargetTypePage[] = "page";
-const char kTargetTypeServiceWorker[] = "service_worker";
-const char kTargetTypeSharedWorker[] = "worker";
-const char kTargetTypeOther[] = "other";
-
-class Target : public content::DevToolsTarget {
- public:
- explicit Target(scoped_refptr<content::DevToolsAgentHost> agent_host);
-
- virtual std::string GetId() const override { return agent_host_->GetId(); }
- virtual std::string GetParentId() const override { return std::string(); }
- virtual std::string GetType() const override {
- switch (agent_host_->GetType()) {
- case content::DevToolsAgentHost::TYPE_WEB_CONTENTS:
- return kTargetTypePage;
- case content::DevToolsAgentHost::TYPE_SERVICE_WORKER:
- return kTargetTypeServiceWorker;
- case content::DevToolsAgentHost::TYPE_SHARED_WORKER:
- return kTargetTypeSharedWorker;
- default:
- break;
- }
- return kTargetTypeOther;
- }
- virtual std::string GetTitle() const override {
- return agent_host_->GetTitle();
- }
- virtual std::string GetDescription() const override { return std::string(); }
- virtual GURL GetURL() const override {
- return agent_host_->GetURL();
- }
- virtual GURL GetFaviconURL() const override { return favicon_url_; }
- virtual base::TimeTicks GetLastActivityTime() const override {
- return last_activity_time_;
- }
- virtual bool IsAttached() const override {
- return agent_host_->IsAttached();
- }
- virtual scoped_refptr<content::DevToolsAgentHost> GetAgentHost()
- const override {
- return agent_host_;
- }
- virtual bool Activate() const override {
- return agent_host_->Activate();
- }
- virtual bool Close() const override {
- return agent_host_->Close();
- }
-
- private:
- scoped_refptr<content::DevToolsAgentHost> agent_host_;
- GURL favicon_url_;
- base::TimeTicks last_activity_time_;
-
- DISALLOW_COPY_AND_ASSIGN(Target);
-};
-
-Target::Target(scoped_refptr<content::DevToolsAgentHost> agent_host)
- : agent_host_(agent_host) {
- if (content::WebContents* web_contents = agent_host_->GetWebContents()) {
- content::NavigationController& controller = web_contents->GetController();
- content::NavigationEntry* entry = controller.GetActiveEntry();
- if (entry != NULL && entry->GetURL().is_valid())
- favicon_url_ = entry->GetFavicon().url;
- last_activity_time_ = web_contents->GetLastActiveTime();
- }
-}
-
-} // namespace
-
// CastDevToolsDelegate -----------------------------------------------------
CastDevToolsDelegate::CastDevToolsDelegate() {
@@ -109,54 +28,13 @@ std::string CastDevToolsDelegate::GetDiscoveryPageHTML() {
#endif // defined(OS_ANDROID)
}
-bool CastDevToolsDelegate::BundlesFrontendResources() {
- return false;
-}
-
-base::FilePath CastDevToolsDelegate::GetDebugFrontendDir() {
- return base::FilePath();
-}
-
-scoped_ptr<net::StreamListenSocket>
-CastDevToolsDelegate::CreateSocketForTethering(
- net::StreamListenSocket::Delegate* delegate,
- std::string* name) {
- return scoped_ptr<net::StreamListenSocket>();
-}
-
-// CastDevToolsManagerDelegate -----------------------------------------------
-
-CastDevToolsManagerDelegate::CastDevToolsManagerDelegate() {
-}
-
-CastDevToolsManagerDelegate::~CastDevToolsManagerDelegate() {
-}
-
-base::DictionaryValue* CastDevToolsManagerDelegate::HandleCommand(
- content::DevToolsAgentHost* agent_host,
- base::DictionaryValue* command) {
- return NULL;
-}
-
-std::string CastDevToolsManagerDelegate::GetPageThumbnailData(
- const GURL& url) {
- return "";
-}
-
-scoped_ptr<content::DevToolsTarget>
-CastDevToolsManagerDelegate::CreateNewTarget(const GURL& url) {
- return scoped_ptr<content::DevToolsTarget>();
+std::string CastDevToolsDelegate::GetFrontendResource(
+ const std::string& path) {
+ return std::string();
}
-void CastDevToolsManagerDelegate::EnumerateTargets(TargetCallback callback) {
- TargetList targets;
- content::DevToolsAgentHost::List agents =
- content::DevToolsAgentHost::GetOrCreateAll();
- for (content::DevToolsAgentHost::List::iterator it = agents.begin();
- it != agents.end(); ++it) {
- targets.push_back(new Target(*it));
- }
- callback.Run(targets);
+std::string CastDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
+ return std::string();
}
} // namespace shell
diff --git a/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.h b/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.h
index 18160708337..190abec1244 100644
--- a/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.h
+++ b/chromium/chromecast/browser/devtools/cast_dev_tools_delegate.h
@@ -5,62 +5,27 @@
#ifndef CHROMECAST_BROWSER_DEVTOOLS_CAST_DEV_TOOLS_DELEGATE_H_
#define CHROMECAST_BROWSER_DEVTOOLS_CAST_DEV_TOOLS_DELEGATE_H_
-#include "content/public/browser/devtools_http_handler_delegate.h"
-#include "content/public/browser/devtools_manager_delegate.h"
+#include "components/devtools_http_handler/devtools_http_handler_delegate.h"
#include "net/socket/stream_listen_socket.h"
-namespace base {
-class FilePath;
-}
-
-namespace content {
-class BrowserContext;
-}
-
namespace chromecast {
namespace shell {
-class CastDevToolsDelegate : public content::DevToolsHttpHandlerDelegate {
+class CastDevToolsDelegate :
+ public devtools_http_handler::DevToolsHttpHandlerDelegate {
public:
CastDevToolsDelegate();
- virtual ~CastDevToolsDelegate();
+ ~CastDevToolsDelegate() override;
- // DevToolsHttpHandlerDelegate implementation.
- virtual std::string GetDiscoveryPageHTML() override;
- virtual bool BundlesFrontendResources() override;
- virtual base::FilePath GetDebugFrontendDir() override;
- virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
- net::StreamListenSocket::Delegate* delegate,
- std::string* name) override;
+ // devtools_http_handler::DevToolsHttpHandlerDelegate implementation.
+ std::string GetDiscoveryPageHTML() override;
+ std::string GetFrontendResource(const std::string& path) override;
+ std::string GetPageThumbnailData(const GURL& url) override;
private:
DISALLOW_COPY_AND_ASSIGN(CastDevToolsDelegate);
};
-class CastDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
- public:
- CastDevToolsManagerDelegate();
- virtual ~CastDevToolsManagerDelegate();
-
- // DevToolsManagerDelegate implementation.
- virtual void Inspect(
- content::BrowserContext* browser_context,
- content::DevToolsAgentHost* agent_host) override {}
- virtual void DevToolsAgentStateChanged(
- content::DevToolsAgentHost* agent_host,
- bool attached) override {}
- virtual base::DictionaryValue* HandleCommand(
- content::DevToolsAgentHost* agent_host,
- base::DictionaryValue* command) override;
- virtual scoped_ptr<content::DevToolsTarget> CreateNewTarget(
- const GURL& url) override;
- virtual void EnumerateTargets(TargetCallback callback) override;
- virtual std::string GetPageThumbnailData(const GURL& url) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CastDevToolsManagerDelegate);
-};
-
} // namespace shell
} // namespace chromecast
diff --git a/chromium/chromecast/browser/devtools/remote_debugging_server.cc b/chromium/chromecast/browser/devtools/remote_debugging_server.cc
index e0abdc072d8..6391b6d6303 100644
--- a/chromium/chromecast/browser/devtools/remote_debugging_server.cc
+++ b/chromium/chromecast/browser/devtools/remote_debugging_server.cc
@@ -9,14 +9,16 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
+#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/devtools/cast_dev_tools_delegate.h"
-#include "chromecast/common/chromecast_config.h"
+#include "chromecast/common/cast_content_client.h"
#include "chromecast/common/pref_names.h"
+#include "components/devtools_http_handler/devtools_http_handler.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/devtools_http_handler.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
+#include "net/base/net_errors.h"
#include "net/socket/tcp_server_socket.h"
#if defined(OS_ANDROID)
@@ -24,54 +26,71 @@
#include "net/socket/unix_domain_server_socket_posix.h"
#endif // defined(OS_ANDROID)
+using devtools_http_handler::DevToolsHttpHandler;
+
namespace chromecast {
namespace shell {
namespace {
const char kFrontEndURL[] =
- "https://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
-const int kDefaultRemoteDebuggingPort = 9222;
+ "https://chrome-devtools-frontend.appspot.com/serve_rev/%s/inspector.html";
+const uint16 kDefaultRemoteDebuggingPort = 9222;
+
+const int kBackLog = 10;
#if defined(OS_ANDROID)
class UnixDomainServerSocketFactory
- : public content::DevToolsHttpHandler::ServerSocketFactory {
+ : public DevToolsHttpHandler::ServerSocketFactory {
public:
explicit UnixDomainServerSocketFactory(const std::string& socket_name)
- : content::DevToolsHttpHandler::ServerSocketFactory(socket_name, 0, 1) {}
+ : socket_name_(socket_name) {}
private:
- // content::DevToolsHttpHandler::ServerSocketFactory.
- virtual scoped_ptr<net::ServerSocket> Create() const override {
- return scoped_ptr<net::ServerSocket>(
+ // devtools_http_handler::DevToolsHttpHandler::ServerSocketFactory.
+ scoped_ptr<net::ServerSocket> CreateForHttpServer() override {
+ scoped_ptr<net::ServerSocket> socket(
new net::UnixDomainServerSocket(
base::Bind(&content::CanUserConnectToDevTools),
true /* use_abstract_namespace */));
+ if (socket->ListenWithAddressAndPort(socket_name_, 0, kBackLog) != net::OK)
+ return scoped_ptr<net::ServerSocket>();
+
+ return socket;
}
+ std::string socket_name_;
+
DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
};
#else
class TCPServerSocketFactory
- : public content::DevToolsHttpHandler::ServerSocketFactory {
+ : public DevToolsHttpHandler::ServerSocketFactory {
public:
- TCPServerSocketFactory(const std::string& address, int port, int backlog)
- : content::DevToolsHttpHandler::ServerSocketFactory(
- address, port, backlog) {}
+ TCPServerSocketFactory(const std::string& address, uint16 port)
+ : address_(address), port_(port) {
+ }
private:
- // content::DevToolsHttpHandler::ServerSocketFactory.
- virtual scoped_ptr<net::ServerSocket> Create() const override {
- return scoped_ptr<net::ServerSocket>(
- new net::TCPServerSocket(NULL, net::NetLog::Source()));
+ // devtools_http_handler::DevToolsHttpHandler::ServerSocketFactory.
+ scoped_ptr<net::ServerSocket> CreateForHttpServer() override {
+ scoped_ptr<net::ServerSocket> socket(
+ new net::TCPServerSocket(nullptr, net::NetLog::Source()));
+ if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK)
+ return scoped_ptr<net::ServerSocket>();
+
+ return socket;
}
+ std::string address_;
+ uint16 port_;
+
DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
};
#endif
-scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>
-CreateSocketFactory(int port) {
+scoped_ptr<DevToolsHttpHandler::ServerSocketFactory>
+CreateSocketFactory(uint16 port) {
#if defined(OS_ANDROID)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
std::string socket_name = "cast_shell_devtools_remote";
@@ -79,11 +98,11 @@ CreateSocketFactory(int port) {
socket_name = command_line->GetSwitchValueASCII(
switches::kRemoteDebuggingSocketName);
}
- return scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>(
+ return scoped_ptr<DevToolsHttpHandler::ServerSocketFactory>(
new UnixDomainServerSocketFactory(socket_name));
#else
- return scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>(
- new TCPServerSocketFactory("0.0.0.0", port, 1));
+ return scoped_ptr<DevToolsHttpHandler::ServerSocketFactory>(
+ new TCPServerSocketFactory("0.0.0.0", port));
#endif
}
@@ -93,12 +112,10 @@ std::string GetFrontendUrl() {
} // namespace
-RemoteDebuggingServer::RemoteDebuggingServer()
- : devtools_http_handler_(NULL),
- port_(0) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+RemoteDebuggingServer::RemoteDebuggingServer() : port_(0) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
pref_port_.Init(prefs::kRemoteDebuggingPort,
- ChromecastConfig::GetInstance()->pref_service(),
+ CastBrowserProcess::GetInstance()->pref_service(),
base::Bind(&RemoteDebuggingServer::OnPortChanged,
base::Unretained(this)));
@@ -115,10 +132,7 @@ RemoteDebuggingServer::~RemoteDebuggingServer() {
}
void RemoteDebuggingServer::OnPortChanged() {
- int new_port = *pref_port_;
- if (new_port < 0) {
- new_port = 0;
- }
+ uint16 new_port = static_cast<uint16>(std::max(*pref_port_, 0));
VLOG(1) << "OnPortChanged called: old_port=" << port_
<< ", new_port=" << new_port;
@@ -129,18 +143,19 @@ void RemoteDebuggingServer::OnPortChanged() {
if (devtools_http_handler_) {
LOG(INFO) << "Stop old devtools: port=" << port_;
- // Note: Stop destroys devtools_http_handler_.
- devtools_http_handler_->Stop();
- devtools_http_handler_ = NULL;
+ devtools_http_handler_.reset();
}
port_ = new_port;
if (port_ > 0) {
- devtools_http_handler_ = content::DevToolsHttpHandler::Start(
+ devtools_http_handler_.reset(new DevToolsHttpHandler(
CreateSocketFactory(port_),
GetFrontendUrl(),
new CastDevToolsDelegate(),
- base::FilePath());
+ base::FilePath(),
+ base::FilePath(),
+ std::string(),
+ GetUserAgent()));
LOG(INFO) << "Devtools started: port=" << port_;
}
}
diff --git a/chromium/chromecast/browser/devtools/remote_debugging_server.h b/chromium/chromecast/browser/devtools/remote_debugging_server.h
index 3248bb77828..399b34449f9 100644
--- a/chromium/chromecast/browser/devtools/remote_debugging_server.h
+++ b/chromium/chromecast/browser/devtools/remote_debugging_server.h
@@ -5,15 +5,18 @@
#ifndef CHROMECAST_BROWSER_DEVTOOLS_REMOTE_DEBUGGING_SERVER_H_
#define CHROMECAST_BROWSER_DEVTOOLS_REMOTE_DEBUGGING_SERVER_H_
+#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_member.h"
-namespace content {
+namespace devtools_http_handler {
class DevToolsHttpHandler;
-} // namespace content
+}
namespace chromecast {
namespace shell {
+class CastDevToolsManagerDelegate;
+
class RemoteDebuggingServer {
public:
RemoteDebuggingServer();
@@ -27,10 +30,10 @@ class RemoteDebuggingServer {
// on device startup.
bool ShouldStartImmediately();
- content::DevToolsHttpHandler* devtools_http_handler_;
+ scoped_ptr<devtools_http_handler::DevToolsHttpHandler> devtools_http_handler_;
IntegerPrefMember pref_port_;
- int port_;
+ uint16 port_;
DISALLOW_COPY_AND_ASSIGN(RemoteDebuggingServer);
};
diff --git a/chromium/chromecast/browser/geolocation/cast_access_token_store.h b/chromium/chromecast/browser/geolocation/cast_access_token_store.h
index 02bbc7cbafb..27de8b3b2ed 100644
--- a/chromium/chromecast/browser/geolocation/cast_access_token_store.h
+++ b/chromium/chromecast/browser/geolocation/cast_access_token_store.h
@@ -22,12 +22,11 @@ class CastAccessTokenStore : public content::AccessTokenStore {
explicit CastAccessTokenStore(content::BrowserContext* browser_context);
private:
- virtual ~CastAccessTokenStore();
+ ~CastAccessTokenStore() override;
// AccessTokenStore implementation:
- virtual void LoadAccessTokens(
- const LoadAccessTokensCallbackType& callback) override;
- virtual void SaveAccessToken(
+ void LoadAccessTokens(const LoadAccessTokensCallbackType& callback) override;
+ void SaveAccessToken(
const GURL& server_url, const base::string16& access_token) override;
void GetRequestContextGetterOnUIThread();
diff --git a/chromium/chromecast/browser/media/cast_browser_cdm_factory.cc b/chromium/chromecast/browser/media/cast_browser_cdm_factory.cc
new file mode 100644
index 00000000000..61d80019090
--- /dev/null
+++ b/chromium/chromecast/browser/media/cast_browser_cdm_factory.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/media/cast_browser_cdm_factory.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chromecast/browser/media/cma_message_loop.h"
+#include "chromecast/media/cdm/browser_cdm_cast.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/cdm_key_information.h"
+
+namespace chromecast {
+namespace media {
+
+scoped_ptr<::media::BrowserCdm> CastBrowserCdmFactory::CreateBrowserCdm(
+ const std::string& key_system_name,
+ bool use_hw_secure_codecs,
+ const ::media::SessionMessageCB& session_message_cb,
+ const ::media::SessionClosedCB& session_closed_cb,
+ const ::media::LegacySessionErrorCB& legacy_session_error_cb,
+ const ::media::SessionKeysChangeCB& session_keys_change_cb,
+ const ::media::SessionExpirationUpdateCB& session_expiration_update_cb) {
+ DCHECK(!use_hw_secure_codecs)
+ << "Chromecast does not use |use_hw_secure_codecs|";
+
+ CastKeySystem key_system(GetKeySystemByName(key_system_name));
+
+ scoped_ptr<chromecast::media::BrowserCdmCast> browser_cdm;
+ if (key_system == chromecast::media::KEY_SYSTEM_CLEAR_KEY) {
+ // TODO(gunsch): handle ClearKey decryption. See crbug.com/441957
+ } else {
+ browser_cdm = CreatePlatformBrowserCdm(key_system);
+ }
+
+ if (browser_cdm) {
+ CmaMessageLoop::GetMessageLoopProxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserCdmCast::Initialize,
+ base::Unretained(browser_cdm.get()),
+ ::media::BindToCurrentLoop(session_message_cb),
+ ::media::BindToCurrentLoop(session_closed_cb),
+ ::media::BindToCurrentLoop(legacy_session_error_cb),
+ ::media::BindToCurrentLoop(session_keys_change_cb),
+ ::media::BindToCurrentLoop(session_expiration_update_cb)));
+ return make_scoped_ptr(
+ new BrowserCdmCastUi(browser_cdm.Pass(),
+ CmaMessageLoop::GetMessageLoopProxy()));
+ }
+
+ LOG(INFO) << "No matching key system found.";
+ return scoped_ptr< ::media::BrowserCdm>();
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/media/cast_browser_cdm_factory.h b/chromium/chromecast/browser/media/cast_browser_cdm_factory.h
new file mode 100644
index 00000000000..ad59bed81eb
--- /dev/null
+++ b/chromium/chromecast/browser/media/cast_browser_cdm_factory.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_MEDIA_CAST_BROWSER_CDM_FACTORY_H_
+#define CHROMECAST_BROWSER_MEDIA_CAST_BROWSER_CDM_FACTORY_H_
+
+#include "chromecast/media/base/key_systems_common.h"
+#include "media/base/browser_cdm.h"
+#include "media/base/browser_cdm_factory.h"
+
+namespace chromecast {
+namespace media {
+
+class BrowserCdmCast;
+
+class CastBrowserCdmFactory : public ::media::BrowserCdmFactory {
+ public:
+ CastBrowserCdmFactory() {}
+ ~CastBrowserCdmFactory() override {};
+
+ // ::media::BrowserCdmFactory implementation:
+ scoped_ptr<::media::BrowserCdm> CreateBrowserCdm(
+ const std::string& key_system,
+ bool use_hw_secure_codecs,
+ const ::media::SessionMessageCB& session_message_cb,
+ const ::media::SessionClosedCB& session_closed_cb,
+ const ::media::LegacySessionErrorCB& legacy_session_error_cb,
+ const ::media::SessionKeysChangeCB& session_keys_change_cb,
+ const ::media::SessionExpirationUpdateCB& session_expiration_update_cb)
+ override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CastBrowserCdmFactory);
+};
+
+// Allow platform-specific CDMs to be provided.
+scoped_ptr<BrowserCdmCast> CreatePlatformBrowserCdm(
+ const CastKeySystem& key_system);
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_MEDIA_CAST_BROWSER_CDM_FACTORY_H_
diff --git a/chromium/chromecast/browser/media/cast_browser_cdm_factory_simple.cc b/chromium/chromecast/browser/media/cast_browser_cdm_factory_simple.cc
new file mode 100644
index 00000000000..d9ebda176e1
--- /dev/null
+++ b/chromium/chromecast/browser/media/cast_browser_cdm_factory_simple.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/media/cast_browser_cdm_factory.h"
+
+#include "chromecast/media/cdm/browser_cdm_cast.h"
+
+namespace chromecast {
+namespace media {
+
+scoped_ptr<BrowserCdmCast> CreatePlatformBrowserCdm(
+ const CastKeySystem& key_system) {
+ return scoped_ptr<BrowserCdmCast>();
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/media/cast_media_client_android.cc b/chromium/chromecast/browser/media/cast_media_client_android.cc
new file mode 100644
index 00000000000..696471e6c0d
--- /dev/null
+++ b/chromium/chromecast/browser/media/cast_media_client_android.cc
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/media/cast_media_client_android.h"
+
+#include "chromecast/media/base/key_systems_common.h"
+
+namespace chromecast {
+namespace media {
+
+CastMediaClientAndroid::CastMediaClientAndroid() {
+}
+
+CastMediaClientAndroid::~CastMediaClientAndroid() {
+}
+
+void CastMediaClientAndroid::AddKeySystemUUIDMappings(KeySystemUuidMap* map) {
+ // Note: MediaDrmBridge adds the Widevine UUID mapping automatically.
+#if defined(PLAYREADY_CDM_AVAILABLE)
+ (*map)[kChromecastPlayreadyKeySystem] = playready_delegate_.GetUUID();
+#endif
+
+ auto platform_mappings = GetPlatformKeySystemUUIDMappings();
+ for (const auto& mapping : platform_mappings)
+ map->insert(mapping);
+}
+
+::media::MediaDrmBridgeDelegate*
+CastMediaClientAndroid::GetMediaDrmBridgeDelegate(
+ const ::media::UUID& scheme_uuid) {
+#if defined(PLAYREADY_CDM_AVAILABLE)
+ if (scheme_uuid == playready_delegate_.GetUUID())
+ return &playready_delegate_;
+#endif
+
+ if (scheme_uuid == widevine_delegate_.GetUUID())
+ return &widevine_delegate_;
+
+ return nullptr;
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/media/cast_media_client_android.h b/chromium/chromecast/browser/media/cast_media_client_android.h
new file mode 100644
index 00000000000..a7aaa1d9b2e
--- /dev/null
+++ b/chromium/chromecast/browser/media/cast_media_client_android.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_MEDIA_CAST_MEDIA_CLIENT_ANDROID_H_
+#define CHROMECAST_BROWSER_MEDIA_CAST_MEDIA_CLIENT_ANDROID_H_
+
+#include <map>
+
+#include "base/macros.h"
+#include "chromecast/media/cdm/playready_drm_delegate_android.h"
+#include "components/cdm/browser/widevine_drm_delegate_android.h"
+#include "media/base/android/media_client_android.h"
+
+namespace chromecast {
+namespace media {
+
+class CastMediaClientAndroid : public ::media::MediaClientAndroid {
+ public:
+ CastMediaClientAndroid();
+ ~CastMediaClientAndroid() override;
+
+ private:
+ // ::media::MediaClientAndroid implementation:
+ void AddKeySystemUUIDMappings(KeySystemUuidMap* map) override;
+ ::media::MediaDrmBridgeDelegate* GetMediaDrmBridgeDelegate(
+ const ::media::UUID& scheme_uuid) override;
+
+#if defined(PLAYREADY_CDM_AVAILABLE)
+ PlayreadyDrmDelegateAndroid playready_delegate_;
+#endif
+
+ cdm::WidevineDrmDelegateAndroid widevine_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(CastMediaClientAndroid);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_MEDIA_CAST_MEDIA_CLIENT_ANDROID_H_
diff --git a/chromium/chromecast/browser/media/cma_message_filter_host.cc b/chromium/chromecast/browser/media/cma_message_filter_host.cc
new file mode 100644
index 00000000000..d3664c915a6
--- /dev/null
+++ b/chromium/chromecast/browser/media/cma_message_filter_host.cc
@@ -0,0 +1,540 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/media/cma_message_filter_host.h"
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
+#include "chromecast/browser/media/cma_message_loop.h"
+#include "chromecast/browser/media/media_pipeline_host.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "chromecast/media/cdm/browser_cdm_cast.h"
+#include "chromecast/media/cma/backend/video_plane.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_client.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "media/base/bind_to_current_loop.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace chromecast {
+namespace media {
+
+#define FORWARD_CALL(arg_pipeline, arg_fn, ...) \
+ task_runner_->PostTask( \
+ FROM_HERE, \
+ base::Bind(&MediaPipelineHost::arg_fn, \
+ base::Unretained(arg_pipeline), __VA_ARGS__))
+
+namespace {
+
+const size_t kMaxSharedMem = 8 * 1024 * 1024;
+
+typedef std::map<uint64_t, MediaPipelineHost*> MediaPipelineCmaMap;
+
+// Map of MediaPipelineHost instances that is accessed only from the CMA thread.
+// The existence of a MediaPipelineHost* in this map implies that the instance
+// is still valid.
+base::LazyInstance<MediaPipelineCmaMap> g_pipeline_map_cma =
+ LAZY_INSTANCE_INITIALIZER;
+
+uint64_t GetPipelineCmaId(int process_id, int media_id) {
+ return (static_cast<uint64>(process_id) << 32) +
+ static_cast<uint64>(media_id);
+}
+
+MediaPipelineHost* GetMediaPipeline(int process_id, int media_id) {
+ DCHECK(CmaMessageLoop::GetTaskRunner()->BelongsToCurrentThread());
+ MediaPipelineCmaMap::iterator it =
+ g_pipeline_map_cma.Get().find(GetPipelineCmaId(process_id, media_id));
+ if (it == g_pipeline_map_cma.Get().end())
+ return nullptr;
+ return it->second;
+}
+
+void SetMediaPipeline(int process_id, int media_id, MediaPipelineHost* host) {
+ DCHECK(CmaMessageLoop::GetTaskRunner()->BelongsToCurrentThread());
+ std::pair<MediaPipelineCmaMap::iterator, bool> ret =
+ g_pipeline_map_cma.Get().insert(
+ std::make_pair(GetPipelineCmaId(process_id, media_id), host));
+
+ // Check there is no other entry with the same ID.
+ DCHECK(ret.second != false);
+}
+
+void DestroyMediaPipeline(int process_id,
+ int media_id,
+ scoped_ptr<MediaPipelineHost> media_pipeline) {
+ DCHECK(CmaMessageLoop::GetTaskRunner()->BelongsToCurrentThread());
+ MediaPipelineCmaMap::iterator it =
+ g_pipeline_map_cma.Get().find(GetPipelineCmaId(process_id, media_id));
+ if (it != g_pipeline_map_cma.Get().end())
+ g_pipeline_map_cma.Get().erase(it);
+}
+
+void SetCdmOnCmaThread(int render_process_id, int media_id,
+ BrowserCdmCast* cdm) {
+ MediaPipelineHost* pipeline = GetMediaPipeline(render_process_id, media_id);
+ if (!pipeline) {
+ LOG(WARNING) << "MediaPipelineHost not alive: " << render_process_id << ","
+ << media_id;
+ return;
+ }
+
+ pipeline->SetCdm(cdm);
+}
+
+// BrowserCdm instance must be retrieved/accessed on the UI thread, then
+// passed to MediaPipelineHost on CMA thread.
+void SetCdmOnUiThread(
+ int render_process_id,
+ int render_frame_id,
+ int media_id,
+ int cdm_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id);
+ if (!host) {
+ LOG(ERROR) << "RenderProcessHost not alive for ID: " << render_process_id;
+ return;
+ }
+
+ ::media::BrowserCdm* cdm = host->GetBrowserCdm(render_frame_id, cdm_id);
+ if (!cdm) {
+ LOG(WARNING) << "Could not find BrowserCdm (" << render_frame_id << ","
+ << cdm_id << ")";
+ return;
+ }
+
+ BrowserCdmCast* browser_cdm_cast =
+ static_cast<BrowserCdmCastUi*>(cdm)->browser_cdm_cast();
+ CmaMessageLoop::GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&SetCdmOnCmaThread,
+ render_process_id,
+ media_id,
+ browser_cdm_cast));
+}
+
+void UpdateVideoSurfaceHost(int surface_id, const gfx::QuadF& quad) {
+ // Currently supports only one video plane.
+ CHECK_EQ(surface_id, 0);
+
+ VideoPlane* video_plane = GetVideoPlane();
+ video_plane->SetGeometry(
+ quad,
+ VideoPlane::COORDINATE_TYPE_GRAPHICS_PLANE);
+}
+
+} // namespace
+
+CmaMessageFilterHost::CmaMessageFilterHost(int render_process_id)
+ : content::BrowserMessageFilter(CastMediaMsgStart),
+ process_id_(render_process_id),
+ task_runner_(CmaMessageLoop::GetMessageLoopProxy()),
+ weak_factory_(this) {
+ weak_this_ = weak_factory_.GetWeakPtr();
+}
+
+CmaMessageFilterHost::~CmaMessageFilterHost() {
+ DCHECK(media_pipelines_.empty());
+}
+
+void CmaMessageFilterHost::OnChannelClosing() {
+ content::BrowserMessageFilter::OnChannelClosing();
+ DeleteEntries();
+}
+
+void CmaMessageFilterHost::OnDestruct() const {
+ content::BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+bool CmaMessageFilterHost::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(CmaMessageFilterHost, message)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_CreateMedia, CreateMedia)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_DestroyMedia, DestroyMedia)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_SetCdm, SetCdm)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_CreateAvPipe, CreateAvPipe)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_AudioInitialize, AudioInitialize)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_VideoInitialize, VideoInitialize)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_StartPlayingFrom, StartPlayingFrom)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_Flush, Flush)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_Stop, Stop)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_SetPlaybackRate, SetPlaybackRate)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_SetVolume, SetVolume)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_NotifyPipeWrite, NotifyPipeWrite)
+ IPC_MESSAGE_HANDLER(CmaHostMsg_NotifyExternalSurface,
+ NotifyExternalSurface)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void CmaMessageFilterHost::DeleteEntries() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ for (MediaPipelineMap::iterator it = media_pipelines_.begin();
+ it != media_pipelines_.end(); ) {
+ scoped_ptr<MediaPipelineHost> media_pipeline(it->second);
+ media_pipelines_.erase(it++);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DestroyMediaPipeline, process_id_, it->first,
+ base::Passed(&media_pipeline)));
+ }
+}
+
+MediaPipelineHost* CmaMessageFilterHost::LookupById(int media_id) {
+ MediaPipelineMap::iterator it = media_pipelines_.find(media_id);
+ if (it == media_pipelines_.end())
+ return NULL;
+ return it->second;
+}
+
+
+// *** Handle incoming messages ***
+
+void CmaMessageFilterHost::CreateMedia(int media_id, LoadType load_type) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ scoped_ptr<MediaPipelineHost> media_pipeline_host(new MediaPipelineHost());
+ MediaPipelineClient client;
+ client.time_update_cb = ::media::BindToCurrentLoop(base::Bind(
+ &CmaMessageFilterHost::OnTimeUpdate, weak_this_, media_id));
+ client.buffering_state_cb = ::media::BindToCurrentLoop(base::Bind(
+ &CmaMessageFilterHost::OnBufferingNotification, weak_this_, media_id));
+ client.error_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnPlaybackError,
+ weak_this_, media_id, media::kNoTrackId));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&SetMediaPipeline,
+ process_id_, media_id, media_pipeline_host.get()));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineHost::Initialize,
+ base::Unretained(media_pipeline_host.get()),
+ load_type, client));
+ std::pair<MediaPipelineMap::iterator, bool> ret =
+ media_pipelines_.insert(
+ std::make_pair(media_id, media_pipeline_host.release()));
+
+ // Check there is no other entry with the same ID.
+ DCHECK(ret.second != false);
+}
+
+void CmaMessageFilterHost::DestroyMedia(int media_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ MediaPipelineMap::iterator it = media_pipelines_.find(media_id);
+ if (it == media_pipelines_.end())
+ return;
+
+ scoped_ptr<MediaPipelineHost> media_pipeline(it->second);
+ media_pipelines_.erase(it);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DestroyMediaPipeline, process_id_, media_id,
+ base::Passed(&media_pipeline)));
+}
+
+void CmaMessageFilterHost::SetCdm(int media_id,
+ int render_frame_id,
+ int cdm_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline)
+ return;
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&SetCdmOnUiThread,
+ process_id_, render_frame_id, media_id, cdm_id));
+}
+
+
+void CmaMessageFilterHost::CreateAvPipe(
+ int media_id, TrackId track_id, size_t shared_mem_size) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ base::FileDescriptor foreign_socket_handle;
+ base::SharedMemoryHandle foreign_memory_handle;
+
+ // A few sanity checks before allocating resources.
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline || !PeerHandle() || shared_mem_size > kMaxSharedMem) {
+ Send(new CmaMsg_AvPipeCreated(
+ media_id, track_id, false,
+ foreign_memory_handle, foreign_socket_handle));
+ return;
+ }
+
+ // Create the local/foreign sockets to signal media message
+ // consune/feed events.
+ // Use CancelableSyncSocket so that write is always non-blocking.
+ scoped_ptr<base::CancelableSyncSocket> local_socket(
+ new base::CancelableSyncSocket());
+ scoped_ptr<base::CancelableSyncSocket> foreign_socket(
+ new base::CancelableSyncSocket());
+ if (!base::CancelableSyncSocket::CreatePair(local_socket.get(),
+ foreign_socket.get()) ||
+ foreign_socket->handle() == -1) {
+ Send(new CmaMsg_AvPipeCreated(
+ media_id, track_id, false,
+ foreign_memory_handle, foreign_socket_handle));
+ return;
+ }
+
+ // Shared memory used to convey media messages.
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+ if (!shared_memory->CreateAndMapAnonymous(shared_mem_size) ||
+ !shared_memory->ShareToProcess(PeerHandle(), &foreign_memory_handle)) {
+ Send(new CmaMsg_AvPipeCreated(
+ media_id, track_id, false,
+ foreign_memory_handle, foreign_socket_handle));
+ return;
+ }
+
+ // Note: the IPC message can be sent only once the pipe has been fully
+ // configured. Part of this configuration is done in
+ // |MediaPipelineHost::SetAvPipe|.
+ // TODO(erickung): investigate possible memory leak here.
+ // If the weak pointer in |av_pipe_set_cb| gets invalidated,
+ // then |foreign_memory_handle| leaks.
+ base::Closure pipe_read_activity_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnPipeReadActivity, weak_this_,
+ media_id, track_id));
+ base::Closure av_pipe_set_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnAvPipeSet, weak_this_,
+ media_id, track_id,
+ foreign_memory_handle, base::Passed(&foreign_socket)));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineHost::SetAvPipe,
+ base::Unretained(media_pipeline),
+ track_id,
+ base::Passed(&shared_memory),
+ pipe_read_activity_cb,
+ av_pipe_set_cb));
+}
+
+void CmaMessageFilterHost::OnAvPipeSet(
+ int media_id,
+ TrackId track_id,
+ base::SharedMemoryHandle foreign_memory_handle,
+ scoped_ptr<base::CancelableSyncSocket> foreign_socket) {
+ base::FileDescriptor foreign_socket_handle;
+ foreign_socket_handle.fd = foreign_socket->handle();
+ foreign_socket_handle.auto_close = false;
+
+ // This message can only be set once the pipe has fully been configured
+ // by |MediaPipelineHost|.
+ Send(new CmaMsg_AvPipeCreated(
+ media_id, track_id, true, foreign_memory_handle, foreign_socket_handle));
+}
+
+void CmaMessageFilterHost::AudioInitialize(
+ int media_id, TrackId track_id, const ::media::AudioDecoderConfig& config) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline) {
+ Send(new CmaMsg_TrackStateChanged(
+ media_id, track_id, ::media::PIPELINE_ERROR_ABORT));
+ return;
+ }
+
+ AvPipelineClient client;
+ client.eos_cb = ::media::BindToCurrentLoop(base::Bind(
+ &CmaMessageFilterHost::OnEos, weak_this_, media_id, track_id));
+ client.playback_error_cb = ::media::BindToCurrentLoop(base::Bind(
+ &CmaMessageFilterHost::OnPlaybackError, weak_this_, media_id, track_id));
+ client.statistics_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnStatisticsUpdated, weak_this_,
+ media_id, track_id));
+
+ ::media::PipelineStatusCB pipeline_status_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnTrackStateChanged, weak_this_,
+ media_id, track_id));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineHost::AudioInitialize,
+ base::Unretained(media_pipeline),
+ track_id, client, config, pipeline_status_cb));
+}
+
+void CmaMessageFilterHost::VideoInitialize(
+ int media_id, TrackId track_id, const ::media::VideoDecoderConfig& config) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline) {
+ Send(new CmaMsg_TrackStateChanged(
+ media_id, track_id, ::media::PIPELINE_ERROR_ABORT));
+ return;
+ }
+
+ VideoPipelineClient client;
+ client.av_pipeline_client.eos_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnEos, weak_this_,
+ media_id, track_id));
+ client.av_pipeline_client.playback_error_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnPlaybackError, weak_this_,
+ media_id, track_id));
+ client.av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnStatisticsUpdated, weak_this_,
+ media_id, track_id));
+ client.natural_size_changed_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnNaturalSizeChanged, weak_this_,
+ media_id, track_id));
+
+ ::media::PipelineStatusCB pipeline_status_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnTrackStateChanged, weak_this_,
+ media_id, track_id));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineHost::VideoInitialize,
+ base::Unretained(media_pipeline),
+ track_id, client, config, pipeline_status_cb));
+}
+
+void CmaMessageFilterHost::StartPlayingFrom(
+ int media_id, base::TimeDelta time) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline)
+ return;
+ FORWARD_CALL(media_pipeline, StartPlayingFrom, time);
+}
+
+void CmaMessageFilterHost::Flush(int media_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline) {
+ Send(new CmaMsg_MediaStateChanged(
+ media_id, ::media::PIPELINE_ERROR_ABORT));
+ return;
+ }
+ ::media::PipelineStatusCB pipeline_status_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaMessageFilterHost::OnMediaStateChanged, weak_this_,
+ media_id));
+ FORWARD_CALL(media_pipeline, Flush, pipeline_status_cb);
+}
+
+void CmaMessageFilterHost::Stop(int media_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline)
+ return;
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineHost::Stop,
+ base::Unretained(media_pipeline)));
+}
+
+void CmaMessageFilterHost::SetPlaybackRate(
+ int media_id, double playback_rate) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline)
+ return;
+ FORWARD_CALL(media_pipeline, SetPlaybackRate, playback_rate);
+}
+
+void CmaMessageFilterHost::SetVolume(
+ int media_id, TrackId track_id, float volume) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline)
+ return;
+ FORWARD_CALL(media_pipeline, SetVolume, track_id, volume);
+}
+
+void CmaMessageFilterHost::NotifyPipeWrite(int media_id, TrackId track_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ MediaPipelineHost* media_pipeline = LookupById(media_id);
+ if (!media_pipeline)
+ return;
+ FORWARD_CALL(media_pipeline, NotifyPipeWrite, track_id);
+}
+
+void CmaMessageFilterHost::NotifyExternalSurface(
+ int surface_id,
+ const gfx::PointF& p0, const gfx::PointF& p1,
+ const gfx::PointF& p2, const gfx::PointF& p3) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&UpdateVideoSurfaceHost, surface_id,
+ gfx::QuadF(p0, p1, p2, p3)));
+}
+
+// *** Browser to renderer messages ***
+
+void CmaMessageFilterHost::OnMediaStateChanged(
+ int media_id, ::media::PipelineStatus status) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_MediaStateChanged(media_id, status));
+}
+
+void CmaMessageFilterHost::OnTrackStateChanged(
+ int media_id, TrackId track_id, ::media::PipelineStatus status) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_TrackStateChanged(media_id, track_id, status));
+}
+
+void CmaMessageFilterHost::OnPipeReadActivity(int media_id, TrackId track_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_NotifyPipeRead(media_id, track_id));
+}
+
+void CmaMessageFilterHost::OnTimeUpdate(
+ int media_id,
+ base::TimeDelta media_time,
+ base::TimeDelta max_media_time,
+ base::TimeTicks stc) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_TimeUpdate(media_id,
+ media_time, max_media_time, stc));
+}
+
+void CmaMessageFilterHost::OnBufferingNotification(
+ int media_id, ::media::BufferingState state) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_BufferingNotification(media_id, state));
+}
+
+void CmaMessageFilterHost::OnEos(int media_id, TrackId track_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_Eos(media_id, track_id));
+}
+
+void CmaMessageFilterHost::OnPlaybackError(
+ int media_id, TrackId track_id, ::media::PipelineStatus status) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_PlaybackError(media_id, track_id, status));
+}
+
+void CmaMessageFilterHost::OnStatisticsUpdated(
+ int media_id, TrackId track_id, const ::media::PipelineStatistics& stats) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_PlaybackStatistics(media_id, track_id, stats));
+}
+
+void CmaMessageFilterHost::OnNaturalSizeChanged(
+ int media_id, TrackId track_id, const gfx::Size& size) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ Send(new CmaMsg_NaturalSizeChanged(media_id, track_id, size));
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/media/cma_message_filter_host.h b/chromium/chromecast/browser/media/cma_message_filter_host.h
new file mode 100644
index 00000000000..e00057466f5
--- /dev/null
+++ b/chromium/chromecast/browser/media/cma_message_filter_host.h
@@ -0,0 +1,126 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_MEDIA_CMA_MESSAGE_FILTER_HOST_H_
+#define CHROMECAST_BROWSER_MEDIA_CMA_MESSAGE_FILTER_HOST_H_
+
+#include <map>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "base/memory/weak_ptr.h"
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_thread.h"
+#include "media/base/buffering_state.h"
+#include "media/base/pipeline_status.h"
+
+namespace base {
+class CancelableSyncSocket;
+class SingleThreadTaskRunner;
+}
+
+namespace gfx {
+class PointF;
+class Size;
+}
+
+namespace media {
+class AudioDecoderConfig;
+class BrowserCdm;
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+
+class MediaPipelineHost;
+
+class CmaMessageFilterHost
+ : public content::BrowserMessageFilter {
+ public:
+ explicit CmaMessageFilterHost(int render_process_id);
+
+ // content::BrowserMessageFilter implementation.
+ void OnChannelClosing() override;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ private:
+ typedef std::map<int, MediaPipelineHost*> MediaPipelineMap;
+
+ friend class content::BrowserThread;
+ friend class base::DeleteHelper<CmaMessageFilterHost>;
+ ~CmaMessageFilterHost() override;
+
+ void DeleteEntries();
+ MediaPipelineHost* LookupById(int media_id);
+
+ // Handling of incoming IPC messages.
+ void CreateMedia(int media_id, LoadType load_type);
+ void DestroyMedia(int media_id);
+ void SetCdm(int media_id, int render_frame_id, int cdm_id);
+ void CreateAvPipe(int media_id, TrackId track_id, size_t shared_mem_size);
+ void OnAvPipeSet(int media_id,
+ TrackId track_id,
+ base::SharedMemoryHandle foreign_memory_handle,
+ scoped_ptr<base::CancelableSyncSocket> foreign_socket);
+ void AudioInitialize(int media_id,
+ TrackId track_id,
+ const ::media::AudioDecoderConfig& config);
+ void VideoInitialize(int media_id,
+ TrackId track_id,
+ const ::media::VideoDecoderConfig& config);
+ void StartPlayingFrom(int media_id, base::TimeDelta time);
+ void Flush(int media_id);
+ void Stop(int media_id);
+ void SetPlaybackRate(int media_id, double playback_rate);
+ void SetVolume(int media_id, TrackId track_id, float volume);
+ void NotifyPipeWrite(int media_id, TrackId track_id);
+ void NotifyExternalSurface(int surface_id,
+ const gfx::PointF& p0, const gfx::PointF& p1,
+ const gfx::PointF& p2, const gfx::PointF& p3);
+
+ // Audio/Video callbacks.
+ void OnMediaStateChanged(int media_id,
+ ::media::PipelineStatus status);
+ void OnTrackStateChanged(int media_id,
+ TrackId track_id,
+ ::media::PipelineStatus status);
+ void OnPipeReadActivity(int media_id, TrackId track_id);
+ void OnTimeUpdate(int media_id,
+ base::TimeDelta media_time,
+ base::TimeDelta max_media_time,
+ base::TimeTicks stc);
+ void OnBufferingNotification(int media_id, ::media::BufferingState state);
+ void OnEos(int media_id, TrackId track_id);
+ void OnPlaybackError(int media_id, TrackId track_id,
+ ::media::PipelineStatus status);
+ void OnStatisticsUpdated(int media_id,
+ TrackId track_id,
+ const ::media::PipelineStatistics& stats);
+ void OnNaturalSizeChanged(int media_id,
+ TrackId track_id,
+ const gfx::Size& size);
+
+ // Render process ID correponding to this message filter.
+ const int process_id_;
+
+ // List of media pipeline and message loop media pipelines are running on.
+ MediaPipelineMap media_pipelines_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::WeakPtr<CmaMessageFilterHost> weak_this_;
+ base::WeakPtrFactory<CmaMessageFilterHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CmaMessageFilterHost);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_MEDIA_CMA_MESSAGE_FILTER_HOST_H_
+
diff --git a/chromium/chromecast/browser/media/cma_message_loop.cc b/chromium/chromecast/browser/media/cma_message_loop.cc
new file mode 100644
index 00000000000..8ba93e01c99
--- /dev/null
+++ b/chromium/chromecast/browser/media/cma_message_loop.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/media/cma_message_loop.h"
+
+#include "base/threading/thread.h"
+
+namespace chromecast {
+namespace media {
+
+// static
+scoped_refptr<base::MessageLoopProxy> CmaMessageLoop::GetMessageLoopProxy() {
+ return GetInstance()->thread_->message_loop_proxy();
+}
+
+// static
+scoped_refptr<base::SingleThreadTaskRunner> CmaMessageLoop::GetTaskRunner() {
+ return GetInstance()->thread_->task_runner();
+}
+
+// static
+CmaMessageLoop* CmaMessageLoop::GetInstance() {
+ return Singleton<CmaMessageLoop>::get();
+}
+
+CmaMessageLoop::CmaMessageLoop()
+ : thread_(new base::Thread("CmaThread")) {
+ thread_->Start();
+}
+
+CmaMessageLoop::~CmaMessageLoop() {
+ // This will automatically shutdown the thread.
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/media/cma_message_loop.h b/chromium/chromecast/browser/media/cma_message_loop.h
new file mode 100644
index 00000000000..5ce2cd40c83
--- /dev/null
+++ b/chromium/chromecast/browser/media/cma_message_loop.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_MEDIA_CMA_MESSAGE_LOOP_H_
+#define CHROMECAST_BROWSER_MEDIA_CMA_MESSAGE_LOOP_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+
+namespace base {
+class MessageLoopProxy;
+class SingleThreadTaskRunner;
+class Thread;
+}
+
+namespace chromecast {
+namespace media {
+
+class CmaMessageLoop {
+ public:
+ // TODO(gunsch): clean up references to deprecated Message*Loop*Proxy.
+ static scoped_refptr<base::MessageLoopProxy> GetMessageLoopProxy();
+ static scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner();
+
+ private:
+ friend struct DefaultSingletonTraits<CmaMessageLoop>;
+ friend class Singleton<CmaMessageLoop>;
+
+ static CmaMessageLoop* GetInstance();
+
+ CmaMessageLoop();
+ ~CmaMessageLoop();
+
+ scoped_ptr<base::Thread> thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(CmaMessageLoop);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_MEDIA_CMA_MESSAGE_LOOP_H_
diff --git a/chromium/chromecast/browser/media/media_pipeline_host.cc b/chromium/chromecast/browser/media/media_pipeline_host.cc
new file mode 100644
index 00000000000..ff3eb6926f9
--- /dev/null
+++ b/chromium/chromecast/browser/media/media_pipeline_host.cc
@@ -0,0 +1,174 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/media/media_pipeline_host.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/memory/shared_memory.h"
+#include "base/single_thread_task_runner.h"
+#include "chromecast/common/media/shared_memory_chunk.h"
+#include "chromecast/media/cma/backend/media_pipeline_device.h"
+#include "chromecast/media/cma/backend/media_pipeline_device_params.h"
+#include "chromecast/media/cma/ipc/media_message_fifo.h"
+#include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_impl.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
+
+namespace chromecast {
+namespace media {
+
+struct MediaPipelineHost::MediaTrackHost {
+ MediaTrackHost();
+ ~MediaTrackHost();
+
+ base::Closure pipe_write_cb;
+};
+
+MediaPipelineHost::MediaTrackHost::MediaTrackHost() {
+}
+
+MediaPipelineHost::MediaTrackHost::~MediaTrackHost() {
+}
+
+MediaPipelineHost::MediaPipelineHost() {
+ thread_checker_.DetachFromThread();
+}
+
+MediaPipelineHost::~MediaPipelineHost() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ for (MediaTrackMap::iterator it = media_track_map_.begin();
+ it != media_track_map_.end(); ++it) {
+ scoped_ptr<MediaTrackHost> media_track(it->second);
+ }
+ media_track_map_.clear();
+}
+
+void MediaPipelineHost::Initialize(
+ LoadType load_type,
+ const MediaPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_.reset(new MediaPipelineImpl());
+ MediaPipelineDeviceParams default_parameters;
+ if (load_type == kLoadTypeMediaStream)
+ default_parameters.sync_type = MediaPipelineDeviceParams::kModeIgnorePts;
+ media_pipeline_->Initialize(
+ load_type,
+ CreateMediaPipelineDevice(default_parameters).Pass());
+ media_pipeline_->SetClient(client);
+}
+
+void MediaPipelineHost::SetAvPipe(
+ TrackId track_id,
+ scoped_ptr<base::SharedMemory> shared_mem,
+ const base::Closure& pipe_read_activity_cb,
+ const base::Closure& av_pipe_set_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CHECK(track_id == kAudioTrackId || track_id == kVideoTrackId);
+
+ size_t shared_mem_size = shared_mem->requested_size();
+ scoped_ptr<MediaMemoryChunk> shared_memory_chunk(
+ new SharedMemoryChunk(shared_mem.Pass(), shared_mem_size));
+ scoped_ptr<MediaMessageFifo> media_message_fifo(
+ new MediaMessageFifo(shared_memory_chunk.Pass(), shared_mem_size));
+ media_message_fifo->ObserveReadActivity(pipe_read_activity_cb);
+ scoped_ptr<CodedFrameProviderHost> frame_provider_host(
+ new CodedFrameProviderHost(media_message_fifo.Pass()));
+
+ MediaTrackMap::iterator it = media_track_map_.find(track_id);
+ MediaTrackHost* media_track_host;
+ if (it == media_track_map_.end()) {
+ media_track_host = new MediaTrackHost();
+ media_track_map_.insert(
+ std::pair<TrackId, MediaTrackHost*>(track_id, media_track_host));
+ } else {
+ media_track_host = it->second;
+ }
+ media_track_host->pipe_write_cb = frame_provider_host->GetFifoWriteEventCb();
+
+ scoped_ptr<CodedFrameProvider> frame_provider(frame_provider_host.release());
+ if (track_id == kAudioTrackId) {
+ media_pipeline_->GetAudioPipelineImpl()->SetCodedFrameProvider(
+ frame_provider.Pass());
+ } else {
+ media_pipeline_->GetVideoPipelineImpl()->SetCodedFrameProvider(
+ frame_provider.Pass());
+ }
+ av_pipe_set_cb.Run();
+}
+
+void MediaPipelineHost::AudioInitialize(
+ TrackId track_id,
+ const AvPipelineClient& client,
+ const ::media::AudioDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CHECK(track_id == kAudioTrackId);
+ media_pipeline_->GetAudioPipeline()->SetClient(client);
+ media_pipeline_->InitializeAudio(
+ config, scoped_ptr<CodedFrameProvider>(), status_cb);
+}
+
+void MediaPipelineHost::VideoInitialize(
+ TrackId track_id,
+ const VideoPipelineClient& client,
+ const ::media::VideoDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CHECK(track_id == kVideoTrackId);
+ media_pipeline_->GetVideoPipeline()->SetClient(client);
+ media_pipeline_->InitializeVideo(
+ config, scoped_ptr<CodedFrameProvider>(), status_cb);
+}
+
+void MediaPipelineHost::StartPlayingFrom(base::TimeDelta time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_->StartPlayingFrom(time);
+}
+
+void MediaPipelineHost::Flush(const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_->Flush(status_cb);
+}
+
+void MediaPipelineHost::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_->Stop();
+}
+
+void MediaPipelineHost::SetPlaybackRate(double playback_rate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_->SetPlaybackRate(playback_rate);
+}
+
+void MediaPipelineHost::SetVolume(TrackId track_id, float volume) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CHECK(track_id == kAudioTrackId);
+ media_pipeline_->GetAudioPipeline()->SetVolume(volume);
+}
+
+void MediaPipelineHost::SetCdm(BrowserCdmCast* cdm) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_->SetCdm(cdm);
+}
+
+void MediaPipelineHost::NotifyPipeWrite(TrackId track_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ MediaTrackMap::iterator it = media_track_map_.find(track_id);
+ if (it == media_track_map_.end())
+ return;
+
+ MediaTrackHost* media_track_host = it->second;
+ if (!media_track_host->pipe_write_cb.is_null())
+ media_track_host->pipe_write_cb.Run();
+}
+
+} // namespace media
+} // namespace chromecast
+
diff --git a/chromium/chromecast/browser/media/media_pipeline_host.h b/chromium/chromecast/browser/media/media_pipeline_host.h
new file mode 100644
index 00000000000..dc15db94240
--- /dev/null
+++ b/chromium/chromecast/browser/media/media_pipeline_host.h
@@ -0,0 +1,86 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_MEDIA_MEDIA_PIPELINE_HOST_H_
+#define CHROMECAST_BROWSER_MEDIA_MEDIA_PIPELINE_HOST_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "media/base/pipeline_status.h"
+
+namespace base {
+class SharedMemory;
+class SingleThreadTaskRunner;
+}
+
+namespace media {
+class AudioDecoderConfig;
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+struct AvPipelineClient;
+class BrowserCdmCast;
+struct MediaPipelineClient;
+class MediaPipelineImpl;
+struct VideoPipelineClient;
+
+class MediaPipelineHost {
+ public:
+ MediaPipelineHost();
+ ~MediaPipelineHost();
+
+ void Initialize(LoadType load_type,
+ const MediaPipelineClient& client);
+
+ void SetAvPipe(TrackId track_id,
+ scoped_ptr<base::SharedMemory> shared_mem,
+ const base::Closure& pipe_read_activity_cb,
+ const base::Closure& av_pipe_set_cb);
+ void AudioInitialize(TrackId track_id,
+ const AvPipelineClient& client,
+ const ::media::AudioDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb);
+ void VideoInitialize(TrackId track_id,
+ const VideoPipelineClient& client,
+ const ::media::VideoDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb);
+ void StartPlayingFrom(base::TimeDelta time);
+ void Flush(const ::media::PipelineStatusCB& status_cb);
+ void Stop();
+
+ void SetPlaybackRate(double playback_rate);
+ void SetVolume(TrackId track_id, float playback_rate);
+ void SetCdm(BrowserCdmCast* cdm);
+
+ void NotifyPipeWrite(TrackId track_id);
+
+ private:
+ base::ThreadChecker thread_checker_;
+
+ scoped_ptr<MediaPipelineImpl> media_pipeline_;
+
+ // The shared memory for a track id must be valid until Stop is invoked on
+ // that track id.
+ struct MediaTrackHost;
+ typedef std::map<TrackId, MediaTrackHost*> MediaTrackMap;
+ MediaTrackMap media_track_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaPipelineHost);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_MEDIA_MEDIA_PIPELINE_HOST_H_
+
diff --git a/chromium/chromecast/browser/metrics/cast_metrics_service_client.cc b/chromium/chromecast/browser/metrics/cast_metrics_service_client.cc
index feb0fa6022c..a367322da4e 100644
--- a/chromium/chromecast/browser/metrics/cast_metrics_service_client.cc
+++ b/chromium/chromecast/browser/metrics/cast_metrics_service_client.cc
@@ -5,19 +5,24 @@
#include "chromecast/browser/metrics/cast_metrics_service_client.h"
#include "base/command_line.h"
+#include "base/guid.h"
#include "base/i18n/rtl.h"
+#include "base/prefs/pref_service.h"
#include "chromecast/browser/metrics/cast_stability_metrics_provider.h"
#include "chromecast/browser/metrics/platform_metrics_providers.h"
-#include "chromecast/common/chromecast_config.h"
#include "chromecast/common/chromecast_switches.h"
+#include "chromecast/common/pref_names.h"
#include "components/metrics/client_info.h"
#include "components/metrics/gpu/gpu_metrics_provider.h"
+#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_provider.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/metrics/net/net_metrics_log_uploader.h"
#include "components/metrics/net/network_metrics_provider.h"
#include "components/metrics/profiler/profiler_metrics_provider.h"
+#include "components/metrics/url_constants.h"
+#include "content/public/common/content_switches.h"
#if defined(OS_LINUX)
#include "chromecast/browser/metrics/external_metrics.h"
@@ -27,32 +32,72 @@ namespace chromecast {
namespace metrics {
namespace {
-
-void StoreClientInfo(const ::metrics::ClientInfo& client_info) {
-}
-
-scoped_ptr<::metrics::ClientInfo> LoadClientInfo() {
- return scoped_ptr<::metrics::ClientInfo>();
-}
-
+const int kStandardUploadIntervalMinutes = 5;
} // namespace
// static
-CastMetricsServiceClient* CastMetricsServiceClient::Create(
+scoped_ptr<CastMetricsServiceClient> CastMetricsServiceClient::Create(
base::TaskRunner* io_task_runner,
PrefService* pref_service,
net::URLRequestContextGetter* request_context) {
- return new CastMetricsServiceClient(io_task_runner,
- pref_service,
- request_context);
+ return make_scoped_ptr(new CastMetricsServiceClient(io_task_runner,
+ pref_service,
+ request_context));
}
void CastMetricsServiceClient::SetMetricsClientId(
const std::string& client_id) {
+ client_id_ = client_id;
LOG(INFO) << "Metrics client ID set: " << client_id;
- PlatformSetClientID(client_id);
+ PlatformSetClientID(cast_service_, client_id);
+}
+
+void CastMetricsServiceClient::OnRecordingDisabled() {
+}
+
+void CastMetricsServiceClient::StoreClientInfo(
+ const ::metrics::ClientInfo& client_info) {
+ const std::string& client_id = client_info.client_id;
+ DCHECK(client_id.empty() || base::IsValidGUID(client_id));
+ // backup client_id or reset to empty.
+ SetMetricsClientId(client_id);
}
+scoped_ptr< ::metrics::ClientInfo> CastMetricsServiceClient::LoadClientInfo() {
+ scoped_ptr< ::metrics::ClientInfo> client_info(new ::metrics::ClientInfo);
+
+ // kMetricsIsNewClientID would be missing if either the device was just
+ // FDR'ed, or it is on pre-v1.2 build.
+ if (!pref_service_->GetBoolean(prefs::kMetricsIsNewClientID)) {
+ // If the old client id exists, the device must be on pre-v1.2 build,
+ // instead of just being FDR'ed.
+ if (!pref_service_->GetString(::metrics::prefs::kMetricsOldClientID)
+ .empty()) {
+ // Force old client id to be regenerated. See b/9487011.
+ client_info->client_id = base::GenerateGUID();
+ pref_service_->SetBoolean(prefs::kMetricsIsNewClientID, true);
+ return client_info.Pass();
+ }
+ // else the device was just FDR'ed, pass through.
+ }
+
+ const std::string client_id(GetPlatformClientID(cast_service_));
+ if (!client_id.empty() && base::IsValidGUID(client_id)) {
+ client_info->client_id = client_id;
+ return client_info.Pass();
+ } else {
+ if (client_id.empty()) {
+ LOG(WARNING) << "Empty client id from platform,"
+ << " assuming this is the first boot up of a new device.";
+ } else {
+ LOG(ERROR) << "Invalid client id " << client_id << " from platform.";
+ }
+ return scoped_ptr< ::metrics::ClientInfo>();
+ }
+}
+
+
+
bool CastMetricsServiceClient::IsOffTheRecordSessionActive() {
// Chromecast behaves as "off the record" w/r/t recording browsing state,
// but this value is about not disabling metrics because of it.
@@ -73,15 +118,15 @@ bool CastMetricsServiceClient::GetBrand(std::string* brand_code) {
}
::metrics::SystemProfileProto::Channel CastMetricsServiceClient::GetChannel() {
- return GetPlatformReleaseChannel();
+ return GetPlatformReleaseChannel(cast_service_);
}
std::string CastMetricsServiceClient::GetVersionString() {
- return GetPlatformVersionString();
+ return GetPlatformVersionString(cast_service_);
}
void CastMetricsServiceClient::OnLogUploadComplete() {
- PlatformOnLogUploadComplete();
+ PlatformOnLogUploadComplete(cast_service_);
}
void CastMetricsServiceClient::StartGatheringMetrics(
@@ -96,10 +141,8 @@ void CastMetricsServiceClient::CollectFinalMetrics(
scoped_ptr< ::metrics::MetricsLogUploader>
CastMetricsServiceClient::CreateUploader(
- const std::string& server_url,
- const std::string& mime_type,
const base::Callback<void(int)>& on_upload_complete) {
- std::string uma_server_url(server_url);
+ std::string uma_server_url(::metrics::kDefaultMetricsServerUrl);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kOverrideMetricsUploadUrl)) {
uma_server_url.assign(
@@ -110,10 +153,14 @@ CastMetricsServiceClient::CreateUploader(
new ::metrics::NetMetricsLogUploader(
request_context_,
uma_server_url,
- mime_type,
+ ::metrics::kDefaultMetricsMimeType,
on_upload_complete));
}
+base::TimeDelta CastMetricsServiceClient::GetStandardUploadInterval() {
+ return base::TimeDelta::FromMinutes(kStandardUploadIntervalMinutes);
+}
+
void CastMetricsServiceClient::EnableMetricsService(bool enabled) {
if (!metrics_service_loop_->BelongsToCurrentThread()) {
metrics_service_loop_->PostTask(
@@ -135,18 +182,40 @@ CastMetricsServiceClient::CastMetricsServiceClient(
base::TaskRunner* io_task_runner,
PrefService* pref_service,
net::URLRequestContextGetter* request_context)
- : metrics_state_manager_(::metrics::MetricsStateManager::Create(
- pref_service,
- base::Bind(&CastMetricsServiceClient::IsReportingEnabled,
- base::Unretained(this)),
- base::Bind(&StoreClientInfo),
- base::Bind(&LoadClientInfo))),
- metrics_service_(new ::metrics::MetricsService(
- metrics_state_manager_.get(),
- this,
- pref_service)),
+ : io_task_runner_(io_task_runner),
+ pref_service_(pref_service),
+ cast_service_(NULL),
+#if !defined(OS_ANDROID)
+ external_metrics_(NULL),
+#endif // !defined(OS_ANDROID)
metrics_service_loop_(base::MessageLoopProxy::current()),
request_context_(request_context) {
+}
+
+CastMetricsServiceClient::~CastMetricsServiceClient() {
+#if !defined(OS_ANDROID)
+ DCHECK(!external_metrics_);
+#endif // !defined(OS_ANDROID)
+}
+
+void CastMetricsServiceClient::Initialize(CastService* cast_service) {
+ DCHECK(cast_service);
+ DCHECK(!cast_service_);
+ cast_service_ = cast_service;
+
+ metrics_state_manager_ = ::metrics::MetricsStateManager::Create(
+ pref_service_,
+ base::Bind(&CastMetricsServiceClient::IsReportingEnabled,
+ base::Unretained(this)),
+ base::Bind(&CastMetricsServiceClient::StoreClientInfo,
+ base::Unretained(this)),
+ base::Bind(&CastMetricsServiceClient::LoadClientInfo,
+ base::Unretained(this)));
+ metrics_service_.reset(new ::metrics::MetricsService(
+ metrics_state_manager_.get(),
+ this,
+ pref_service_));
+
// Always create a client id as it may also be used by crash reporting,
// (indirectly) included in feedback, and can be queried during setup.
// For UMA and crash reporting, associated opt-in settings will control
@@ -160,18 +229,26 @@ CastMetricsServiceClient::CastMetricsServiceClient(
new CastStabilityMetricsProvider(metrics_service_.get());
metrics_service_->RegisterMetricsProvider(
scoped_ptr< ::metrics::MetricsProvider>(stability_provider));
+
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (!command_line->HasSwitch(switches::kDisableGpu)) {
+ metrics_service_->RegisterMetricsProvider(
+ scoped_ptr< ::metrics::MetricsProvider>(
+ new ::metrics::GPUMetricsProvider));
+ }
metrics_service_->RegisterMetricsProvider(
scoped_ptr< ::metrics::MetricsProvider>(
- new ::metrics::GPUMetricsProvider));
- metrics_service_->RegisterMetricsProvider(
- scoped_ptr< ::metrics::MetricsProvider>(
- new ::metrics::NetworkMetricsProvider(io_task_runner)));
+ new ::metrics::NetworkMetricsProvider(io_task_runner_)));
metrics_service_->RegisterMetricsProvider(
scoped_ptr< ::metrics::MetricsProvider>(
new ::metrics::ProfilerMetricsProvider));
- RegisterPlatformMetricsProviders(metrics_service_.get());
+ RegisterPlatformMetricsProviders(metrics_service_.get(), cast_service_);
metrics_service_->InitializeMetricsRecordingState();
+#if !defined(OS_ANDROID)
+ // Reset clean_shutdown bit after InitializeMetricsRecordingState().
+ metrics_service_->LogNeedForCleanShutdown();
+#endif // !defined(OS_ANDROID)
if (IsReportingEnabled())
metrics_service_->Start();
@@ -179,16 +256,27 @@ CastMetricsServiceClient::CastMetricsServiceClient(
// Start external metrics collection, which feeds data from external
// processes into the main external metrics.
#if defined(OS_LINUX)
- external_metrics_.reset(new ExternalMetrics(stability_provider));
+ external_metrics_ = new ExternalMetrics(stability_provider);
external_metrics_->Start();
#endif // defined(OS_LINUX)
}
-CastMetricsServiceClient::~CastMetricsServiceClient() {
+void CastMetricsServiceClient::Finalize() {
+#if !defined(OS_ANDROID)
+ // Set clean_shutdown bit.
+ metrics_service_->RecordCompletedSessionEnd();
+#endif // !defined(OS_ANDROID)
+
+ // Stop metrics service cleanly before destructing CastMetricsServiceClient.
+#if defined(OS_LINUX)
+ external_metrics_->StopAndDestroy();
+ external_metrics_ = NULL;
+#endif // defined(OS_LINUX)
+ metrics_service_->Stop();
}
bool CastMetricsServiceClient::IsReportingEnabled() {
- return PlatformIsReportingEnabled();
+ return PlatformIsReportingEnabled(cast_service_);
}
} // namespace metrics
diff --git a/chromium/chromecast/browser/metrics/cast_metrics_service_client.h b/chromium/chromecast/browser/metrics/cast_metrics_service_client.h
index 5cba73c0d27..abc2b57311c 100644
--- a/chromium/chromecast/browser/metrics/cast_metrics_service_client.h
+++ b/chromium/chromecast/browser/metrics/cast_metrics_service_client.h
@@ -20,6 +20,7 @@ class TaskRunner;
}
namespace metrics {
+struct ClientInfo;
class MetricsService;
class MetricsStateManager;
} // namespace metrics
@@ -29,38 +30,48 @@ class URLRequestContextGetter;
} // namespace net
namespace chromecast {
+
+class CastService;
+
namespace metrics {
+
class ExternalMetrics;
class CastMetricsServiceClient : public ::metrics::MetricsServiceClient {
public:
- virtual ~CastMetricsServiceClient();
+ ~CastMetricsServiceClient() override;
- static CastMetricsServiceClient* Create(
+ static scoped_ptr<CastMetricsServiceClient> Create(
base::TaskRunner* io_task_runner,
PrefService* pref_service,
net::URLRequestContextGetter* request_context);
+ void Initialize(CastService* cast_service);
+ void Finalize();
+
// metrics::MetricsServiceClient implementation:
- virtual void SetMetricsClientId(const std::string& client_id) override;
- virtual bool IsOffTheRecordSessionActive() override;
- virtual int32_t GetProduct() override;
- virtual std::string GetApplicationLocale() override;
- virtual bool GetBrand(std::string* brand_code) override;
- virtual ::metrics::SystemProfileProto::Channel GetChannel() override;
- virtual std::string GetVersionString() override;
- virtual void OnLogUploadComplete() override;
- virtual void StartGatheringMetrics(
- const base::Closure& done_callback) override;
- virtual void CollectFinalMetrics(const base::Closure& done_callback) override;
- virtual scoped_ptr< ::metrics::MetricsLogUploader> CreateUploader(
- const std::string& server_url,
- const std::string& mime_type,
+ void SetMetricsClientId(const std::string& client_id) override;
+ void OnRecordingDisabled() override;
+ bool IsOffTheRecordSessionActive() override;
+ int32_t GetProduct() override;
+ std::string GetApplicationLocale() override;
+ bool GetBrand(std::string* brand_code) override;
+ ::metrics::SystemProfileProto::Channel GetChannel() override;
+ std::string GetVersionString() override;
+ void OnLogUploadComplete() override;
+ void StartGatheringMetrics(const base::Closure& done_callback) override;
+ void CollectFinalMetrics(const base::Closure& done_callback) override;
+ scoped_ptr< ::metrics::MetricsLogUploader> CreateUploader(
const base::Callback<void(int)>& on_upload_complete) override;
+ base::TimeDelta GetStandardUploadInterval() override;
// Starts/stops the metrics service.
void EnableMetricsService(bool enabled);
+ std::string client_id() const {
+ return client_id_;
+ }
+
private:
CastMetricsServiceClient(
base::TaskRunner* io_task_runner,
@@ -70,13 +81,21 @@ class CastMetricsServiceClient : public ::metrics::MetricsServiceClient {
// Returns whether or not metrics reporting is enabled.
bool IsReportingEnabled();
+ scoped_ptr< ::metrics::ClientInfo> LoadClientInfo();
+ void StoreClientInfo(const ::metrics::ClientInfo& client_info);
+
+ base::TaskRunner* const io_task_runner_;
+ PrefService* const pref_service_;
+ CastService* cast_service_;
+ std::string client_id_;
+
#if defined(OS_LINUX)
- scoped_ptr<ExternalMetrics> external_metrics_;
+ ExternalMetrics* external_metrics_;
#endif // defined(OS_LINUX)
+ const scoped_refptr<base::MessageLoopProxy> metrics_service_loop_;
scoped_ptr< ::metrics::MetricsStateManager> metrics_state_manager_;
scoped_ptr< ::metrics::MetricsService> metrics_service_;
- scoped_refptr<base::MessageLoopProxy> metrics_service_loop_;
- net::URLRequestContextGetter* request_context_;
+ net::URLRequestContextGetter* const request_context_;
DISALLOW_COPY_AND_ASSIGN(CastMetricsServiceClient);
};
diff --git a/chromium/chromecast/browser/metrics/cast_metrics_service_client_unittest.cc b/chromium/chromecast/browser/metrics/cast_metrics_service_client_unittest.cc
deleted file mode 100644
index 31537864d81..00000000000
--- a/chromium/chromecast/browser/metrics/cast_metrics_service_client_unittest.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromecast/browser/metrics/cast_metrics_service_client.h"
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/prefs/testing_pref_service.h"
-#include "components/metrics/metrics_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromecast {
-
-class CastMetricsTest : public testing::Test {
- public:
- CastMetricsTest() {}
- virtual ~CastMetricsTest() {}
-
- protected:
- virtual void SetUp() override {
- message_loop_.reset(new base::MessageLoop());
- prefs_.reset(new TestingPrefServiceSimple());
- ::metrics::MetricsService::RegisterPrefs(prefs_->registry());
- }
-
- base::TaskRunner* task_runner() {
- return message_loop_->task_runner().get();
- }
- TestingPrefServiceSimple* prefs() { return prefs_.get(); }
-
- private:
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<TestingPrefServiceSimple> prefs_;
-
- DISALLOW_COPY_AND_ASSIGN(CastMetricsTest);
-};
-
-TEST_F(CastMetricsTest, CreateMetricsServiceClient) {
- // Create and expect this to not crash.
- metrics::CastMetricsServiceClient::Create(task_runner(), prefs(), NULL);
-}
-
-} // namespace chromecast
diff --git a/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.cc b/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.cc
index b7ec5096327..62150a3af3f 100644
--- a/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.cc
+++ b/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.cc
@@ -11,8 +11,8 @@
#include "base/metrics/sparse_histogram.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
+#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/metrics/cast_metrics_service_client.h"
-#include "chromecast/common/chromecast_config.h"
#include "chromecast/common/pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/proto/system_profile.pb.h"
@@ -21,7 +21,6 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/user_metrics.h"
namespace chromecast {
namespace metrics {
@@ -29,7 +28,7 @@ namespace metrics {
namespace {
void IncrementPrefValue(const char* path) {
- PrefService* pref = ChromecastConfig::GetInstance()->pref_service();
+ PrefService* pref = shell::CastBrowserProcess::GetInstance()->pref_service();
DCHECK(pref);
int value = pref->GetInteger(path);
pref->SetInteger(path, value + 1);
@@ -75,7 +74,7 @@ void CastStabilityMetricsProvider::OnRecordingDisabled() {
void CastStabilityMetricsProvider::ProvideStabilityMetrics(
::metrics::SystemProfileProto* system_profile_proto) {
- PrefService* pref = ChromecastConfig::GetInstance()->pref_service();
+ PrefService* pref = shell::CastBrowserProcess::GetInstance()->pref_service();
::metrics::SystemProfileProto_Stability* stability_proto =
system_profile_proto->mutable_stability();
@@ -141,7 +140,8 @@ void CastStabilityMetricsProvider::Observe(
}
void CastStabilityMetricsProvider::BrowserChildProcessCrashed(
- const content::ChildProcessData& data) {
+ const content::ChildProcessData& data,
+ int exit_code) {
IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
}
diff --git a/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.h b/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.h
index eea85054057..b29d2a4dc35 100644
--- a/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.h
+++ b/chromium/chromecast/browser/metrics/cast_stability_metrics_provider.h
@@ -6,7 +6,6 @@
#define CHROMECAST_BROWSER_METRICS_CAST_STABILITY_METRICS_PROVIDER_H_
#include "base/basictypes.h"
-#include "base/metrics/user_metrics.h"
#include "base/process/kill.h"
#include "components/metrics/metrics_provider.h"
#include "content/public/browser/browser_child_process_observer.h"
@@ -39,12 +38,12 @@ class CastStabilityMetricsProvider
explicit CastStabilityMetricsProvider(
::metrics::MetricsService* metrics_service);
- virtual ~CastStabilityMetricsProvider();
+ ~CastStabilityMetricsProvider() override;
// metrics::MetricsDataProvider implementation:
- virtual void OnRecordingEnabled() override;
- virtual void OnRecordingDisabled() override;
- virtual void ProvideStabilityMetrics(
+ void OnRecordingEnabled() override;
+ void OnRecordingDisabled() override;
+ void ProvideStabilityMetrics(
::metrics::SystemProfileProto* system_profile_proto) override;
// Logs an external crash, presumably from the ExternalMetrics service.
@@ -52,13 +51,14 @@ class CastStabilityMetricsProvider
private:
// content::NotificationObserver implementation:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) override;
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) override;
// content::BrowserChildProcessObserver implementation:
- virtual void BrowserChildProcessCrashed(
- const content::ChildProcessData& data) override;
+ void BrowserChildProcessCrashed(
+ const content::ChildProcessData& data,
+ int exit_code) override;
// Records a renderer process crash.
void LogRendererCrash(content::RenderProcessHost* host,
diff --git a/chromium/chromecast/browser/metrics/external_metrics.cc b/chromium/chromecast/browser/metrics/external_metrics.cc
index 18e7ec0ff0f..f26e0ccd960 100644
--- a/chromium/chromecast/browser/metrics/external_metrics.cc
+++ b/chromium/chromecast/browser/metrics/external_metrics.cc
@@ -14,12 +14,12 @@
#include "base/metrics/statistics_recorder.h"
#include "base/timer/elapsed_timer.h"
#include "chromecast/base/metrics/cast_histograms.h"
+#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "chromecast/browser/metrics/cast_stability_metrics_provider.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/serialization/metric_sample.h"
#include "components/metrics/serialization/serialization_utils.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/user_metrics.h"
namespace chromecast {
namespace metrics {
@@ -58,17 +58,16 @@ ExternalMetrics::ExternalMetrics(
DCHECK(stability_provider);
}
-ExternalMetrics::~ExternalMetrics() {}
+ExternalMetrics::~ExternalMetrics() {
+}
-void ExternalMetrics::Start() {
- ScheduleCollector();
+void ExternalMetrics::StopAndDestroy() {
+ content::BrowserThread::DeleteSoon(
+ content::BrowserThread::FILE, FROM_HERE, this);
}
-void ExternalMetrics::RecordAction(const std::string& action) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(&content::RecordComputedAction, action));
+void ExternalMetrics::Start() {
+ ScheduleCollector();
}
void ExternalMetrics::RecordCrash(const std::string& crash_kind) {
@@ -102,7 +101,7 @@ int ExternalMetrics::CollectEvents() {
RecordCrash(sample.name());
break;
case ::metrics::MetricSample::USER_ACTION:
- RecordAction(sample.name());
+ CastMetricsHelper::GetInstance()->RecordSimpleAction(sample.name());
break;
case ::metrics::MetricSample::HISTOGRAM:
if (!CheckValues(sample.name(), sample.min(), sample.max(),
diff --git a/chromium/chromecast/browser/metrics/external_metrics.h b/chromium/chromecast/browser/metrics/external_metrics.h
index 2b4bc5381a5..dd125e211b6 100644
--- a/chromium/chromecast/browser/metrics/external_metrics.h
+++ b/chromium/chromecast/browser/metrics/external_metrics.h
@@ -24,19 +24,22 @@ class CastStabilityMetricsProvider;
class ExternalMetrics {
public:
explicit ExternalMetrics(CastStabilityMetricsProvider* stability_provider);
- ~ExternalMetrics();
// Begins external data collection. Calls to RecordAction originate in the
// File thread but are executed in the UI thread.
void Start();
+ // Destroys itself in appropriate thread.
+ void StopAndDestroy();
+
private:
+ friend class base::DeleteHelper<ExternalMetrics>;
+
+ ~ExternalMetrics();
+
// The max length of a message (name-value pair, plus header)
static const int kMetricsMessageMaxLength = 1024; // be generous
- // Passes an action event to the UMA service.
- void RecordAction(const std::string& action_name);
-
// Records an external crash of the given string description.
void RecordCrash(const std::string& crash_kind);
diff --git a/chromium/chromecast/browser/metrics/platform_metrics_providers.h b/chromium/chromecast/browser/metrics/platform_metrics_providers.h
index da1130bc5f4..ea28f679eac 100644
--- a/chromium/chromecast/browser/metrics/platform_metrics_providers.h
+++ b/chromium/chromecast/browser/metrics/platform_metrics_providers.h
@@ -12,26 +12,35 @@ class MetricsService;
}
namespace chromecast {
+
+class CastService;
+
namespace metrics {
// Build-level hook for different platforms to provide data to MetricsService.
void RegisterPlatformMetricsProviders(
- ::metrics::MetricsService* metrics_service);
+ ::metrics::MetricsService* metrics_service,
+ CastService* cast_servce);
+
+// Returns UMA client ID persisted in the platform.
+const std::string GetPlatformClientID(CastService* cast_servce);
// Returns the current release channel.
-::metrics::SystemProfileProto::Channel GetPlatformReleaseChannel();
+::metrics::SystemProfileProto::Channel GetPlatformReleaseChannel(
+ CastService* cast_servce);
// Returns a string representing this build's version.
-std::string GetPlatformVersionString();
+std::string GetPlatformVersionString(CastService* cast_servce);
// Returns whether or not metrics reporting should be on.
-bool PlatformIsReportingEnabled();
+bool PlatformIsReportingEnabled(CastService* cast_servce);
// Called when the UMA client ID has been set.
-void PlatformSetClientID(const std::string& client_id);
+void PlatformSetClientID(CastService* cast_servce,
+ const std::string& client_id);
// Called when an upload has completed.
-void PlatformOnLogUploadComplete();
+void PlatformOnLogUploadComplete(CastService* cast_servce);
} // namespace metrics
} // namespace chromecast
diff --git a/chromium/chromecast/browser/metrics/platform_metrics_providers_simple.cc b/chromium/chromecast/browser/metrics/platform_metrics_providers_simple.cc
index 7bc4c52b31c..f92a4790178 100644
--- a/chromium/chromecast/browser/metrics/platform_metrics_providers_simple.cc
+++ b/chromium/chromecast/browser/metrics/platform_metrics_providers_simple.cc
@@ -8,25 +8,32 @@ namespace chromecast {
namespace metrics {
void RegisterPlatformMetricsProviders(
- ::metrics::MetricsService* metrics_service) {
+ ::metrics::MetricsService* metrics_service,
+ CastService* cast_servce) {
}
-::metrics::SystemProfileProto::Channel GetPlatformReleaseChannel() {
+const std::string GetPlatformClientID(CastService* cast_servce) {
+ return "";
+}
+
+::metrics::SystemProfileProto::Channel GetPlatformReleaseChannel(
+ CastService* cast_servce) {
return ::metrics::SystemProfileProto::CHANNEL_STABLE;
}
-std::string GetPlatformVersionString() {
+std::string GetPlatformVersionString(CastService* cast_servce) {
return "";
}
-bool PlatformIsReportingEnabled() {
+bool PlatformIsReportingEnabled(CastService* cast_service) {
return false;
}
-void PlatformSetClientID(const std::string& client_id) {
+void PlatformSetClientID(CastService* cast_servce,
+ const std::string& client_id) {
}
-void PlatformOnLogUploadComplete() {
+void PlatformOnLogUploadComplete(CastService* cast_servce) {
}
} // namespace metrics
diff --git a/chromium/chromecast/browser/pref_service_helper.cc b/chromium/chromecast/browser/pref_service_helper.cc
new file mode 100644
index 00000000000..3f6f5c607c3
--- /dev/null
+++ b/chromium/chromecast/browser/pref_service_helper.cc
@@ -0,0 +1,76 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/pref_service_helper.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/prefs/json_pref_store.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service_factory.h"
+#include "base/prefs/pref_store.h"
+#include "chromecast/base/cast_paths.h"
+#include "chromecast/common/pref_names.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace chromecast {
+namespace shell {
+
+namespace {
+
+void UserPrefsLoadError(PersistentPrefStore::PrefReadError* error_val,
+ PersistentPrefStore::PrefReadError error) {
+ DCHECK(error_val);
+ *error_val = error;
+}
+
+base::FilePath GetConfigPath() {
+ base::FilePath config_path;
+ CHECK(PathService::Get(FILE_CAST_CONFIG, &config_path));
+ return config_path;
+}
+
+} // namespace
+
+// static
+scoped_ptr<PrefService> PrefServiceHelper::CreatePrefService(
+ PrefRegistrySimple* registry) {
+ const base::FilePath config_path(GetConfigPath());
+ VLOG(1) << "Loading config from " << config_path.value();
+
+ registry->RegisterBooleanPref(prefs::kMetricsIsNewClientID, false);
+ registry->RegisterIntegerPref(prefs::kRemoteDebuggingPort, 0);
+
+ RegisterPlatformPrefs(registry);
+
+ base::PrefServiceFactory prefServiceFactory;
+ scoped_refptr<base::SequencedTaskRunner> task_runner =
+ JsonPrefStore::GetTaskRunnerForFile(
+ config_path,
+ content::BrowserThread::GetBlockingPool());
+ prefServiceFactory.SetUserPrefsFile(config_path, task_runner.get());
+ prefServiceFactory.set_async(false);
+
+ PersistentPrefStore::PrefReadError prefs_read_error =
+ PersistentPrefStore::PREF_READ_ERROR_NONE;
+ prefServiceFactory.set_read_error_callback(
+ base::Bind(&UserPrefsLoadError, &prefs_read_error));
+
+ scoped_ptr<PrefService> pref_service(prefServiceFactory.Create(registry));
+ if (prefs_read_error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
+ LOG(ERROR) << "Cannot initialize chromecast config: "
+ << config_path.value()
+ << ", pref_error=" << prefs_read_error;
+ }
+
+ OnPrefsLoaded(pref_service.get());
+ return pref_service.Pass();
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/pref_service_helper.h b/chromium/chromecast/browser/pref_service_helper.h
new file mode 100644
index 00000000000..cf41a925f36
--- /dev/null
+++ b/chromium/chromecast/browser/pref_service_helper.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper to initialize PrefService for cast shell.
+
+#ifndef CHROMECAST_BROWSER_PREF_SERVICE_HELPER_H_
+#define CHROMECAST_BROWSER_PREF_SERVICE_HELPER_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_service.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/threading/thread_checker.h"
+
+class PrefRegistrySimple;
+
+namespace chromecast {
+namespace shell {
+
+// It uses JsonPrefStore internally and/so the format of config file is same to
+// that of JsonPrefStore.
+class PrefServiceHelper {
+ public:
+ // Loads configs from config file. Returns true if successful.
+ static scoped_ptr<PrefService> CreatePrefService(
+ PrefRegistrySimple* registry);
+
+ private:
+ // Registers any needed preferences for the current platform.
+ static void RegisterPlatformPrefs(PrefRegistrySimple* registry);
+
+ // Called after the pref file has been loaded.
+ static void OnPrefsLoaded(PrefService* pref_service);
+};
+
+} // namespace shell
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_PREF_SERVICE_HELPER_H_
diff --git a/chromium/chromecast/browser/pref_service_helper_simple.cc b/chromium/chromecast/browser/pref_service_helper_simple.cc
new file mode 100644
index 00000000000..0357ca79f11
--- /dev/null
+++ b/chromium/chromecast/browser/pref_service_helper_simple.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/pref_service_helper.h"
+
+namespace chromecast {
+namespace shell {
+
+void PrefServiceHelper::RegisterPlatformPrefs(PrefRegistrySimple* registry) {
+}
+
+void PrefServiceHelper::OnPrefsLoaded(PrefService* pref_service) {
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/browser/service/cast_service.cc b/chromium/chromecast/browser/service/cast_service.cc
index 87c9ee264e2..d725abe2397 100644
--- a/chromium/chromecast/browser/service/cast_service.cc
+++ b/chromium/chromecast/browser/service/cast_service.cc
@@ -5,15 +5,18 @@
#include "chromecast/browser/service/cast_service.h"
#include "base/logging.h"
+#include "base/run_loop.h"
#include "base/threading/thread_checker.h"
namespace chromecast {
CastService::CastService(
content::BrowserContext* browser_context,
- const OptInStatsChangedCallback& opt_in_stats_callback)
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client)
: browser_context_(browser_context),
- opt_in_stats_callback_(opt_in_stats_callback),
+ pref_service_(pref_service),
+ metrics_service_client_(metrics_service_client),
stopped_(true),
thread_checker_(new base::ThreadChecker()) {
}
@@ -23,10 +26,18 @@ CastService::~CastService() {
DCHECK(stopped_);
}
-void CastService::Start() {
+void CastService::Initialize() {
DCHECK(thread_checker_->CalledOnValidThread());
+ InitializeInternal();
+}
- Initialize();
+void CastService::Finalize() {
+ DCHECK(thread_checker_->CalledOnValidThread());
+ FinalizeInternal();
+}
+
+void CastService::Start() {
+ DCHECK(thread_checker_->CalledOnValidThread());
stopped_ = false;
StartInternal();
}
@@ -34,6 +45,9 @@ void CastService::Start() {
void CastService::Stop() {
DCHECK(thread_checker_->CalledOnValidThread());
StopInternal();
+ // Consume any pending tasks which should be done before destroying in-process
+ // renderer process, for example, destroying web_contents.
+ base::RunLoop().RunUntilIdle();
stopped_ = true;
}
diff --git a/chromium/chromecast/browser/service/cast_service.h b/chromium/chromecast/browser/service/cast_service.h
index 7e7d94c00b3..e10ac39f254 100644
--- a/chromium/chromecast/browser/service/cast_service.h
+++ b/chromium/chromecast/browser/service/cast_service.h
@@ -9,6 +9,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+class PrefService;
+
namespace base {
class ThreadChecker;
}
@@ -23,46 +25,68 @@ class URLRequestContextGetter;
namespace chromecast {
+namespace metrics {
+class CastMetricsServiceClient;
+}
+
class CastService {
public:
- // A callback that will be invoked when the user changes the opt-in stats
- // value.
- typedef base::Callback<void(bool)> OptInStatsChangedCallback;
-
// Create() takes a separate url request context getter because the request
// context getter obtained through the browser context might not be
// appropriate for the url requests made by the cast service/reciever.
// For example, on Chromecast, it is needed to pass in a system url request
// context getter that would set the request context for NSS, which the main
// getter doesn't do.
- static CastService* Create(
+ static scoped_ptr<CastService> Create(
content::BrowserContext* browser_context,
- net::URLRequestContextGetter* request_context_getter,
- const OptInStatsChangedCallback& opt_in_stats_callback);
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client,
+ net::URLRequestContextGetter* request_context_getter);
virtual ~CastService();
- // Start/stop the cast service.
+ // Initializes/finalizes the cast service.
+ void Initialize();
+ void Finalize();
+
+ // Starts/stops the cast service.
void Start();
void Stop();
protected:
CastService(content::BrowserContext* browser_context,
- const OptInStatsChangedCallback& opt_in_stats_callback);
- virtual void Initialize() = 0;
-
- // Implementation-specific start/stop behavior.
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client);
+
+ // Implementation-specific initialization. Initialization of cast service's
+ // sub-components, and anything that requires IO operations should go here.
+ // Anything that should happen before cast service is started but doesn't need
+ // the sub-components to finish initializing should also go here.
+ virtual void InitializeInternal() = 0;
+
+ // Implementation-specific finalization. Any initializations done by
+ // InitializeInternal() should be finalized here.
+ virtual void FinalizeInternal() = 0;
+
+ // Implementation-specific start behavior. It basically starts the
+ // sub-component services and does additional initialization that cannot be
+ // done in the InitializationInternal().
virtual void StartInternal() = 0;
+
+ // Implementation-specific stop behavior. Any initializations done by
+ // StartInternal() should be finalized here.
virtual void StopInternal() = 0;
content::BrowserContext* browser_context() const { return browser_context_; }
- const OptInStatsChangedCallback& opt_in_stats_callback() const {
- return opt_in_stats_callback_;
+ PrefService* pref_service() const { return pref_service_; }
+ metrics::CastMetricsServiceClient* metrics_service_client() const {
+ return metrics_service_client_;
}
private:
content::BrowserContext* const browser_context_;
- const OptInStatsChangedCallback opt_in_stats_callback_;
+ PrefService* const pref_service_;
+ metrics::CastMetricsServiceClient* const metrics_service_client_;
bool stopped_;
const scoped_ptr<base::ThreadChecker> thread_checker_;
diff --git a/chromium/chromecast/browser/service/cast_service_android.cc b/chromium/chromecast/browser/service/cast_service_android.cc
index 7a4b563c1b5..8822c83e7b8 100644
--- a/chromium/chromecast/browser/service/cast_service_android.cc
+++ b/chromium/chromecast/browser/service/cast_service_android.cc
@@ -4,30 +4,44 @@
#include "chromecast/browser/service/cast_service_android.h"
+#include "base/bind.h"
#include "chromecast/android/chromecast_config_android.h"
+#include "chromecast/browser/metrics/cast_metrics_service_client.h"
namespace chromecast {
// static
-CastService* CastService::Create(
+scoped_ptr<CastService> CastService::Create(
content::BrowserContext* browser_context,
- net::URLRequestContextGetter* request_context_getter,
- const OptInStatsChangedCallback& opt_in_stats_callback) {
- return new CastServiceAndroid(browser_context, opt_in_stats_callback);
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client,
+ net::URLRequestContextGetter* request_context_getter) {
+ return scoped_ptr<CastService>(
+ new CastServiceAndroid(browser_context,
+ pref_service,
+ metrics_service_client));
}
CastServiceAndroid::CastServiceAndroid(
content::BrowserContext* browser_context,
- const OptInStatsChangedCallback& opt_in_stats_callback)
- : CastService(browser_context, opt_in_stats_callback) {
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client)
+ : CastService(browser_context, pref_service, metrics_service_client) {
}
CastServiceAndroid::~CastServiceAndroid() {
}
-void CastServiceAndroid::Initialize() {
+void CastServiceAndroid::InitializeInternal() {
android::ChromecastConfigAndroid::GetInstance()->
- SetSendUsageStatsChangedCallback(opt_in_stats_callback());
+ SetSendUsageStatsChangedCallback(
+ base::Bind(&metrics::CastMetricsServiceClient::EnableMetricsService,
+ base::Unretained(metrics_service_client())));
+}
+
+void CastServiceAndroid::FinalizeInternal() {
+ android::ChromecastConfigAndroid::GetInstance()->
+ SetSendUsageStatsChangedCallback(base::Callback<void(bool)>());
}
void CastServiceAndroid::StartInternal() {
diff --git a/chromium/chromecast/browser/service/cast_service_android.h b/chromium/chromecast/browser/service/cast_service_android.h
index 22670c6f2bb..91baf349960 100644
--- a/chromium/chromecast/browser/service/cast_service_android.h
+++ b/chromium/chromecast/browser/service/cast_service_android.h
@@ -13,14 +13,16 @@ namespace chromecast {
class CastServiceAndroid : public CastService {
public:
CastServiceAndroid(content::BrowserContext* browser_context,
- const OptInStatsChangedCallback& opt_in_stats_callback);
- virtual ~CastServiceAndroid();
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client);
+ ~CastServiceAndroid() override;
protected:
// CastService implementation.
- virtual void Initialize() override;
- virtual void StartInternal() override;
- virtual void StopInternal() override;
+ void InitializeInternal() override;
+ void FinalizeInternal() override;
+ void StartInternal() override;
+ void StopInternal() override;
private:
DISALLOW_COPY_AND_ASSIGN(CastServiceAndroid);
diff --git a/chromium/chromecast/browser/service/cast_service_simple.cc b/chromium/chromecast/browser/service/cast_service_simple.cc
index 9ac90b040e7..2a40b3e16df 100644
--- a/chromium/chromecast/browser/service/cast_service_simple.cc
+++ b/chromium/chromecast/browser/service/cast_service_simple.cc
@@ -5,12 +5,12 @@
#include "chromecast/browser/service/cast_service_simple.h"
#include "base/command_line.h"
+#include "base/files/file_util.h"
#include "chromecast/browser/cast_content_window.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "net/base/filename_util.h"
#include "net/url_request/url_request_context_getter.h"
-#include "url/gurl.h"
namespace chromecast {
@@ -27,29 +27,38 @@ GURL GetStartupURL() {
if (url.is_valid() && url.has_scheme())
return url;
- return net::FilePathToFileURL(base::FilePath(args[0]));
+ return net::FilePathToFileURL(
+ base::MakeAbsoluteFilePath(base::FilePath(args[0])));
}
} // namespace
// static
-CastService* CastService::Create(
+scoped_ptr<CastService> CastService::Create(
content::BrowserContext* browser_context,
- net::URLRequestContextGetter* request_context_getter,
- const OptInStatsChangedCallback& opt_in_stats_callback) {
- return new CastServiceSimple(browser_context, opt_in_stats_callback);
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client,
+ net::URLRequestContextGetter* request_context_getter) {
+ return scoped_ptr<CastService>(new CastServiceSimple(browser_context,
+ pref_service,
+ metrics_service_client));
}
CastServiceSimple::CastServiceSimple(
content::BrowserContext* browser_context,
- const OptInStatsChangedCallback& opt_in_stats_callback)
- : CastService(browser_context, opt_in_stats_callback) {
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client)
+ : CastService(browser_context, pref_service, metrics_service_client) {
}
CastServiceSimple::~CastServiceSimple() {
}
-void CastServiceSimple::Initialize() {
+void CastServiceSimple::InitializeInternal() {
+ startup_url_ = GetStartupURL();
+}
+
+void CastServiceSimple::FinalizeInternal() {
}
void CastServiceSimple::StartInternal() {
@@ -57,16 +66,16 @@ void CastServiceSimple::StartInternal() {
gfx::Size initial_size(1280, 720);
window_.reset(new CastContentWindow);
- web_contents_ = window_->Create(initial_size, browser_context());
+ web_contents_ = window_->CreateWebContents(initial_size, browser_context());
+ window_->CreateWindowTree(initial_size, web_contents_.get());
- web_contents_->GetController().LoadURL(GetStartupURL(),
- content::Referrer(),
+ web_contents_->GetController().LoadURL(startup_url_, content::Referrer(),
ui::PAGE_TRANSITION_TYPED,
std::string());
}
void CastServiceSimple::StopInternal() {
- web_contents_->GetRenderViewHost()->ClosePage();
+ web_contents_->ClosePage();
web_contents_.reset();
window_.reset();
}
diff --git a/chromium/chromecast/browser/service/cast_service_simple.h b/chromium/chromecast/browser/service/cast_service_simple.h
index f1fb5c8a127..8ce5a13484a 100644
--- a/chromium/chromecast/browser/service/cast_service_simple.h
+++ b/chromium/chromecast/browser/service/cast_service_simple.h
@@ -7,6 +7,7 @@
#include "base/memory/scoped_ptr.h"
#include "chromecast/browser/service/cast_service.h"
+#include "url/gurl.h"
namespace content {
class WebContents;
@@ -18,18 +19,21 @@ class CastContentWindow;
class CastServiceSimple : public CastService {
public:
CastServiceSimple(content::BrowserContext* browser_context,
- const OptInStatsChangedCallback& opt_in_stats_callback);
- virtual ~CastServiceSimple();
+ PrefService* pref_service,
+ metrics::CastMetricsServiceClient* metrics_service_client);
+ ~CastServiceSimple() override;
protected:
// CastService implementation:
- virtual void Initialize() override;
- virtual void StartInternal() override;
- virtual void StopInternal() override;
+ void InitializeInternal() override;
+ void FinalizeInternal() override;
+ void StartInternal() override;
+ void StopInternal() override;
private:
scoped_ptr<CastContentWindow> window_;
scoped_ptr<content::WebContents> web_contents_;
+ GURL startup_url_;
DISALLOW_COPY_AND_ASSIGN(CastServiceSimple);
};
diff --git a/chromium/chromecast/browser/url_request_context_factory.cc b/chromium/chromecast/browser/url_request_context_factory.cc
index 339546c51e1..9143071fb8e 100644
--- a/chromium/chromecast/browser/url_request_context_factory.cc
+++ b/chromium/chromecast/browser/url_request_context_factory.cc
@@ -10,20 +10,20 @@
#include "base/threading/worker_pool.h"
#include "chromecast/browser/cast_http_user_agent_settings.h"
#include "chromecast/browser/cast_network_delegate.h"
+#include "chromecast/common/chromecast_switches.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert_net/nss_ocsp.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
-#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_stream_factory.h"
-#include "net/ocsp/nss_ocsp.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/next_proto.h"
#include "net/ssl/channel_id_service.h"
@@ -58,29 +58,29 @@ class URLRequestContextFactory::URLRequestContextGetter
factory_(factory) {
}
- virtual net::URLRequestContext* GetURLRequestContext() override {
+ net::URLRequestContext* GetURLRequestContext() override {
if (!request_context_) {
if (is_media_) {
request_context_.reset(factory_->CreateMediaRequestContext());
} else {
request_context_.reset(factory_->CreateSystemRequestContext());
-#if defined(USE_NSS)
+#if defined(USE_NSS_CERTS)
// Set request context used by NSS for Crl requests.
net::SetURLRequestContextForNSSHttpIO(request_context_.get());
-#endif // defined(USE_NSS)
+#endif // defined(USE_NSS_CERTS)
}
}
return request_context_.get();
}
- virtual scoped_refptr<base::SingleThreadTaskRunner>
+ scoped_refptr<base::SingleThreadTaskRunner>
GetNetworkTaskRunner() const override {
return content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO);
}
private:
- virtual ~URLRequestContextGetter() {}
+ ~URLRequestContextGetter() override {}
const bool is_media_;
URLRequestContextFactory* const factory_;
@@ -105,7 +105,7 @@ class URLRequestContextFactory::MainURLRequestContextGetter
std::swap(protocol_handlers_, *protocol_handlers);
}
- virtual net::URLRequestContext* GetURLRequestContext() override {
+ net::URLRequestContext* GetURLRequestContext() override {
if (!request_context_) {
request_context_.reset(factory_->CreateMainRequestContext(
browser_context_, &protocol_handlers_, request_interceptors_.Pass()));
@@ -114,14 +114,14 @@ class URLRequestContextFactory::MainURLRequestContextGetter
return request_context_.get();
}
- virtual scoped_refptr<base::SingleThreadTaskRunner>
+ scoped_refptr<base::SingleThreadTaskRunner>
GetNetworkTaskRunner() const override {
return content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO);
}
private:
- virtual ~MainURLRequestContextGetter() {}
+ ~MainURLRequestContextGetter() override {}
content::BrowserContext* const browser_context_;
URLRequestContextFactory* const factory_;
@@ -144,7 +144,7 @@ URLRequestContextFactory::~URLRequestContextFactory() {
}
void URLRequestContextFactory::InitializeOnUIThread() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Cast http user agent settings must be initialized in UI thread
// because it registers itself to pref notification observer which is not
// thread safe.
@@ -243,15 +243,17 @@ void URLRequestContextFactory::InitializeMainContextDependencies(
url::kDataScheme,
new net::DataProtocolHandler);
DCHECK(set_protocol);
-#if defined(OS_ANDROID)
- set_protocol = job_factory->SetProtocolHandler(
- url::kFileScheme,
- new net::FileProtocolHandler(
- content::BrowserThread::GetBlockingPool()->
- GetTaskRunnerWithShutdownBehavior(
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
- DCHECK(set_protocol);
-#endif // defined(OS_ANDROID)
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableLocalFileAccesses)) {
+ set_protocol = job_factory->SetProtocolHandler(
+ url::kFileScheme,
+ new net::FileProtocolHandler(
+ content::BrowserThread::GetBlockingPool()->
+ GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
+ DCHECK(set_protocol);
+ }
// Set up interceptors in the reverse order.
scoped_ptr<net::URLRequestJobFactory> top_job_factory = job_factory.Pass();
@@ -298,7 +300,7 @@ void URLRequestContextFactory::PopulateNetworkSessionParams(
}
net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
InitializeSystemContextDependencies();
net::HttpNetworkSession::Params system_params;
PopulateNetworkSessionParams(false, &system_params);
@@ -330,7 +332,7 @@ net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() {
}
net::URLRequestContext* URLRequestContextFactory::CreateMediaRequestContext() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(main_getter_.get())
<< "Getting MediaRequestContext before MainRequestContext";
net::URLRequestContext* main_context = main_getter_->GetURLRequestContext();
@@ -352,14 +354,11 @@ net::URLRequestContext* URLRequestContextFactory::CreateMainRequestContext(
content::BrowserContext* browser_context,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
InitializeSystemContextDependencies();
- net::HttpCache::BackendFactory* main_backend =
- net::HttpCache::DefaultBackend::InMemory(16 * 1024 * 1024);
-
bool ignore_certificate_errors = false;
- CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (cmd_line->HasSwitch(switches::kIgnoreCertificateErrors)) {
ignore_certificate_errors = true;
}
@@ -367,7 +366,8 @@ net::URLRequestContext* URLRequestContextFactory::CreateMainRequestContext(
PopulateNetworkSessionParams(ignore_certificate_errors,
&network_session_params);
InitializeMainContextDependencies(
- new net::HttpCache(network_session_params, main_backend),
+ new net::HttpNetworkLayer(
+ new net::HttpNetworkSession(network_session_params)),
protocol_handlers,
request_interceptors.Pass());
diff --git a/chromium/chromecast/browser/url_request_context_factory.h b/chromium/chromecast/browser/url_request_context_factory.h
index 0b9a4e955e0..5ae43cb7a4a 100644
--- a/chromium/chromecast/browser/url_request_context_factory.h
+++ b/chromium/chromecast/browser/url_request_context_factory.h
@@ -48,6 +48,10 @@ class URLRequestContextFactory {
return app_network_delegate_.get();
}
+ net::HostResolver* host_resolver() const {
+ return host_resolver_.get();
+ }
+
// Initialize the CastNetworkDelegate objects. This needs to be done
// after the CastService is created, but before any URL requests are made.
void InitializeNetworkDelegates();
diff --git a/chromium/chromecast/browser/webui/webui_cast.h b/chromium/chromecast/browser/webui/webui_cast.h
deleted file mode 100644
index 0172dc5420e..00000000000
--- a/chromium/chromecast/browser/webui/webui_cast.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMECAST_BROWSER_WEBUI_WEBUI_CAST_H_
-#define CHROMECAST_BROWSER_WEBUI_WEBUI_CAST_H_
-
-namespace chromecast {
-namespace shell {
-
-// Initializes all WebUIs needed for the Chromecast shell. This should be
-// implemented on a per-product basis.
-void InitializeWebUI();
-
-} // namespace shell
-} // namespace chromecast
-
-#endif // CHROMECAST_BROWSER_UI_WEBUI_CAST_H_
diff --git a/chromium/chromecast/build/args.gn b/chromium/chromecast/build/args.gn
new file mode 100644
index 00000000000..1624b0a9a6b
--- /dev/null
+++ b/chromium/chromecast/build/args.gn
@@ -0,0 +1,14 @@
+# Build arguments for Chromecast.
+# Copy the contents of this file to gn args.
+
+root_extra_deps = [ "//chromecast" ]
+
+# Flags set from build/common.gypi
+enable_mpeg2ts_stream_parser = true
+ffmpeg_branding = "ChromeOS"
+proprietary_codecs = true
+enable_browser_cdms = true
+# TODO(halliwell): look into supporting Cast Ozone with GN.
+# ozone_platform_cast = 1
+# TODO(gyp): Add support for blink_logging_always_on and enable it.
+# blink_logging_always_on = 1
diff --git a/chromium/chromecast/build/tests/test_list.gypi b/chromium/chromecast/build/tests/test_list.gypi
new file mode 100644
index 00000000000..93373898388
--- /dev/null
+++ b/chromium/chromecast/build/tests/test_list.gypi
@@ -0,0 +1,54 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'variables': {
+ 'variables': {
+ # Note: priority can be set from 1 to 9 to indicate precedence for
+ # filters (larger overrides smaller).
+ 'priority%': 1,
+ 'test_output_folder': '<(SHARED_INTERMEDIATE_DIR)/chromecast/tests',
+ },
+ # Copy from previous level.
+ 'test_output_folder': '<(test_output_folder)',
+
+ 'test_output_file_prefix':
+ '<(test_output_folder)/<(priority)-<(_target_name)',
+ },
+ # Copy from previous level.
+ 'test_output_folder': '<(test_output_folder)',
+
+ 'test_filters_output_file': '<(test_output_file_prefix).filters',
+ 'test_generator_py': '<(DEPTH)/chromecast/tools/build/generate_test_lists.py',
+ 'test_list_output_file': '<(test_output_file_prefix).tests',
+ 'filters%': [],
+ },
+ 'actions': [
+ {
+ 'action_name': 'generate_test_list',
+ 'inputs': ['<(test_generator_py)'],
+ 'outputs': ['<(test_list_output_file)'],
+ 'message': 'Generating test list from <(_target_name)',
+ 'action': [
+ 'python', '<@(_inputs)',
+ '-o', '<(test_list_output_file)',
+ 'create_list',
+ '<@(_dependencies)'
+ ],
+ },
+ {
+ 'action_name': 'generate_filter_list',
+ 'inputs': ['<(test_generator_py)'],
+ 'outputs': ['<(test_filters_output_file)'],
+ 'message': 'Generating filter list from <(_target_name)',
+ 'action': [
+ 'python', '<@(_inputs)',
+ '-o', '<(test_filters_output_file)',
+ 'create_list',
+ '<@(filters)'
+ ],
+ },
+ ],
+}
diff --git a/chromium/chromecast/chromecast.gni b/chromium/chromecast/chromecast.gni
new file mode 100644
index 00000000000..b6f7307bcce
--- /dev/null
+++ b/chromium/chromecast/chromecast.gni
@@ -0,0 +1,10 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+ # is_chromecast_chrome_branded is set to true for an official build
+ is_chromecast_chrome_branded = false
+
+ use_playready = false
+}
diff --git a/chromium/chromecast/chromecast.gyp b/chromium/chromecast/chromecast.gyp
index 22a8085c6aa..ed8261946da 100644
--- a/chromium/chromecast/chromecast.gyp
+++ b/chromium/chromecast/chromecast.gyp
@@ -6,15 +6,53 @@
'variables': {
'android_support_v13_target%':
'../third_party/android_tools/android_tools.gyp:android_support_v13_javalib',
+ 'cast_build_release': 'internal/build/cast_build_release',
+ 'cast_is_debug_build%': 0,
+ # Refers to enum CastProductType in components/metrics/proto/cast_logs.proto
+ 'cast_product_type%': 0, # CAST_PRODUCT_TYPE_UNKNOWN
'chromium_code': 1,
'chromecast_branding%': 'Chromium',
+ 'disable_display%': 0,
+ 'enable_default_cast_graphics%': 1,
+ 'ozone_platform_cast%': 0,
+ 'use_chromecast_webui%': 0,
},
+ 'includes': [
+ 'chromecast_tests.gypi',
+ ],
'target_defaults': {
'include_dirs': [
'..', # Root of Chromium checkout
],
+ 'conditions': [
+ ['disable_display==1', {
+ 'defines': ['DISABLE_DISPLAY'],
+ }],
+ ],
},
'targets': [
+ # Public API target for OEM partners to replace shlibs.
+ {
+ 'target_name': 'cast_public_api',
+ 'type': '<(component)',
+ 'sources': [
+ 'public/cast_egl_platform.h',
+ 'public/cast_egl_platform_shlib.h',
+ 'public/cast_media_shlib.h',
+ 'public/cast_sys_info.h',
+ 'public/chromecast_export.h',
+ 'public/graphics_properties_shlib.h',
+ 'public/graphics_types.h',
+ 'public/media/decoder_config.h',
+ 'public/osd_plane.h',
+ 'public/osd_plane_shlib.h',
+ 'public/osd_surface.h',
+ ],
+ },
+ # TODO(gunsch): Remove this fake target once it's either added or no
+ # longer referenced from internal code.
+ {'target_name': 'cast_media_audio', 'type': 'none'},
+
{
'target_name': 'cast_base',
'type': '<(component)',
@@ -22,19 +60,60 @@
'../base/base.gyp:base',
],
'sources': [
+ 'base/cast_paths.cc',
+ 'base/cast_paths.h',
'base/metrics/cast_histograms.h',
'base/metrics/cast_metrics_helper.cc',
'base/metrics/cast_metrics_helper.h',
+ 'base/metrics/grouped_histogram.cc',
+ 'base/metrics/grouped_histogram.h',
+ 'base/serializers.cc',
+ 'base/serializers.h'
],
}, # end of target 'cast_base'
{
+ 'target_name': 'cast_crash_client',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../breakpad/breakpad.gyp:breakpad_client',
+ '../components/components.gyp:crash_component',
+ ],
+ 'sources': [
+ 'crash/cast_crash_keys.cc',
+ 'crash/cast_crash_keys.h',
+ 'crash/cast_crash_reporter_client.cc',
+ 'crash/cast_crash_reporter_client.h',
+ ],
+ 'conditions': [
+ ['chromecast_branding=="Chrome"', {
+ 'dependencies': [
+ 'internal/chromecast_internal.gyp:crash_internal',
+ ],
+ }, {
+ 'sources': [
+ 'crash/cast_crash_reporter_client_simple.cc',
+ ],
+ }],
+ ]
+ }, # end of target 'cast_crash_client'
+ {
'target_name': 'cast_net',
'type': '<(component)',
'sources': [
- 'net/network_change_notifier_cast.cc',
- 'net/network_change_notifier_cast.h',
- 'net/network_change_notifier_factory_cast.cc',
- 'net/network_change_notifier_factory_cast.h',
+ 'net/connectivity_checker.cc',
+ 'net/connectivity_checker.h',
+ 'net/net_switches.cc',
+ 'net/net_switches.h',
+ 'net/net_util_cast.cc',
+ 'net/net_util_cast.h',
+ ],
+ 'conditions': [
+ ['OS!="android"', {
+ 'sources': [
+ 'net/network_change_notifier_factory_cast.cc',
+ 'net/network_change_notifier_factory_cast.h',
+ ],
+ }],
],
},
{
@@ -69,10 +148,11 @@
],
'actions': [
{
- 'action_name': 'repack_cast_shell_pack',
+ 'action_name': 'repack_cast_shell_pak',
'variables': {
'pak_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_image_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/chromecast/shell_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_100_percent.pak',
@@ -83,12 +163,28 @@
'<(SHARED_INTERMEDIATE_DIR)/ui/strings/app_locale_settings_en-US.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/strings/ui_strings_en-US.pak',
],
+ 'conditions': [
+ ['chromecast_branding=="Chrome" and use_chromecast_webui==1', {
+ 'pak_inputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/chromecast/app_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/chromecast/cast_webui_resources.pak',
+ ],
+ }],
+ ],
'pak_output': '<(PRODUCT_DIR)/assets/cast_shell.pak',
},
'includes': [ '../build/repack_action.gypi' ],
},
],
- },
+ 'conditions': [
+ ['chromecast_branding=="Chrome" and use_chromecast_webui==1', {
+ 'dependencies': [
+ 'internal/chromecast_resources.gyp:chromecast_app_resources',
+ 'internal/chromecast_resources.gyp:chromecast_webui_resources',
+ ],
+ }],
+ ],
+ }, # end of target 'cast_shell_pak'
# This target contains all content-embedder implementation that is
# non-platform-specific.
{
@@ -96,21 +192,31 @@
'type': '<(component)',
'dependencies': [
'cast_base',
+ 'cast_crash_client',
+ 'cast_net',
'cast_shell_pak',
'cast_shell_resources',
+ 'cast_sys_info',
'cast_version_header',
'chromecast_locales.gyp:chromecast_locales_pak',
'chromecast_locales.gyp:chromecast_settings',
'media/media.gyp:media_base',
+ 'media/media.gyp:media_cdm',
'../base/base.gyp:base',
+ '../components/components.gyp:breakpad_host',
'../components/components.gyp:cdm_renderer',
'../components/components.gyp:component_metrics_proto',
+ '../components/components.gyp:crash_component',
+ '../components/components.gyp:devtools_discovery',
+ '../components/components.gyp:devtools_http_handler',
+ '../components/components.gyp:network_hints_browser',
+ '../components/components.gyp:network_hints_renderer',
'../components/components.gyp:metrics',
'../components/components.gyp:metrics_gpu',
'../components/components.gyp:metrics_net',
'../components/components.gyp:metrics_profiler',
'../content/content.gyp:content',
- '../content/content.gyp:content_app_browser',
+ '../content/content.gyp:content_app_both',
'../skia/skia.gyp:skia',
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
@@ -134,12 +240,20 @@
'browser/cast_http_user_agent_settings.h',
'browser/cast_network_delegate.cc',
'browser/cast_network_delegate.h',
+ 'browser/cast_permission_manager.cc',
+ 'browser/cast_permission_manager.h',
+ 'browser/cast_quota_permission_context.cc',
+ 'browser/cast_quota_permission_context.h',
+ 'browser/cast_resource_dispatcher_host_delegate.cc',
+ 'browser/cast_resource_dispatcher_host_delegate.h',
'browser/devtools/cast_dev_tools_delegate.cc',
'browser/devtools/cast_dev_tools_delegate.h',
'browser/devtools/remote_debugging_server.cc',
'browser/devtools/remote_debugging_server.h',
'browser/geolocation/cast_access_token_store.cc',
'browser/geolocation/cast_access_token_store.h',
+ 'browser/media/cast_media_client_android.cc',
+ 'browser/media/cast_media_client_android.h',
'browser/metrics/cast_metrics_prefs.cc',
'browser/metrics/cast_metrics_prefs.h',
'browser/metrics/cast_metrics_service_client.cc',
@@ -147,42 +261,49 @@
'browser/metrics/cast_stability_metrics_provider.cc',
'browser/metrics/cast_stability_metrics_provider.h',
'browser/metrics/platform_metrics_providers.h',
+ 'browser/pref_service_helper.cc',
+ 'browser/pref_service_helper.h',
'browser/service/cast_service.cc',
'browser/service/cast_service.h',
'browser/url_request_context_factory.cc',
'browser/url_request_context_factory.h',
- 'browser/webui/webui_cast.h',
'common/cast_content_client.cc',
'common/cast_content_client.h',
- 'common/cast_paths.cc',
- 'common/cast_paths.h',
'common/cast_resource_delegate.cc',
'common/cast_resource_delegate.h',
- 'common/chromecast_config.cc',
- 'common/chromecast_config.h',
'common/chromecast_switches.cc',
'common/chromecast_switches.h',
+ 'common/media/cast_messages.h',
+ 'common/media/cast_message_generator.cc',
+ 'common/media/cast_message_generator.h',
'common/platform_client_auth.h',
'common/pref_names.cc',
'common/pref_names.h',
'renderer/cast_content_renderer_client.cc',
'renderer/cast_content_renderer_client.h',
+ 'renderer/cast_media_load_deferrer.cc',
+ 'renderer/cast_media_load_deferrer.h',
+ 'renderer/cast_render_process_observer.cc',
+ 'renderer/cast_render_process_observer.h',
'renderer/key_systems_cast.cc',
'renderer/key_systems_cast.h',
+ 'renderer/media/capabilities_message_filter.cc',
+ 'renderer/media/capabilities_message_filter.h',
],
'conditions': [
['chromecast_branding=="Chrome"', {
'dependencies': [
- '<(cast_internal_gyp):cast_shell_internal',
+ 'internal/chromecast_internal.gyp:cast_shell_internal',
],
}, {
'sources': [
+ 'browser/cast_content_browser_client_simple.cc',
'browser/cast_network_delegate_simple.cc',
'browser/devtools/remote_debugging_server_simple.cc',
'browser/metrics/platform_metrics_providers_simple.cc',
- 'browser/webui/webui_cast_simple.cc',
- 'common/chromecast_config_simple.cc',
+ 'browser/pref_service_helper_simple.cc',
'common/platform_client_auth_simple.cc',
+ 'renderer/cast_content_renderer_client_simple.cc',
'renderer/key_systems_cast_simple.cc',
],
'conditions': [
@@ -193,6 +314,7 @@
],
}, {
'sources': [
+ 'browser/media/cast_browser_cdm_factory_simple.cc',
'browser/service/cast_service_simple.cc',
'browser/service/cast_service_simple.h',
],
@@ -209,32 +331,36 @@
],
'dependencies': [
'../components/components.gyp:metrics_serialization',
+ '../ui/aura/aura.gyp:aura_test_support',
+ ],
+ }],
+ ['OS=="android"', {
+ 'dependencies': [
+ '../components/components.gyp:cdm_browser',
],
}],
],
},
{
- 'target_name': 'cast_shell_unittests',
- 'type': '<(gtest_target_type)',
+ 'target_name': 'cast_sys_info',
+ 'type': '<(component)',
'dependencies': [
- 'cast_shell_common',
- '../base/base.gyp:base_prefs_test_support',
- '../base/base.gyp:run_all_unittests',
- '../base/base.gyp:test_support_base',
- '../components/components.gyp:component_metrics_proto',
- '../testing/gtest.gyp:gtest',
+ 'cast_public_api',
+ '../base/base.gyp:base',
],
'sources': [
- 'browser/metrics/cast_metrics_service_client_unittest.cc',
+ 'base/cast_sys_info_util.h',
+ 'base/cast_sys_info_dummy.cc',
+ 'base/cast_sys_info_dummy.h',
],
'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
+ ['chromecast_branding!="Chrome"', {
+ 'sources': [
+ 'base/cast_sys_info_util_simple.cc',
],
}],
- ]
- }, # end of target 'cast_metrics_unittests'
+ ],
+ }, # end of target 'cast_sys_info'
{
'target_name': 'cast_version_header',
'type': 'none',
@@ -258,9 +384,14 @@
'python',
'<(version_py_path)',
'-e', 'VERSION_FULL="<(version_full)"',
- # Revision is taken from buildbot if available; otherwise, a dev string is used.
- '-e', 'CAST_BUILD_REVISION="<!(echo ${BUILD_NUMBER:="local.${USER}"})"',
- '-e', 'CAST_IS_DEBUG_BUILD=1 if "<(CONFIGURATION_NAME)" == "Debug" else 0',
+ # CAST_BUILD_INCREMENTAL is taken from buildbot if available;
+ # otherwise, a dev string is used.
+ '-e', 'CAST_BUILD_INCREMENTAL="<!(echo ${CAST_BUILD_INCREMENTAL:="<!(date +%Y%m%d.%H%M%S)"})"',
+ # CAST_BUILD_RELEASE is taken from cast_build_release file if exist;
+ # otherwise, a dev string is used.
+ '-e', 'CAST_BUILD_RELEASE="<!(if test -f <(cast_build_release); then cat <(cast_build_release); else echo eng.${USER}; fi)"',
+ '-e', 'CAST_IS_DEBUG_BUILD=1 if "<(CONFIGURATION_NAME)" == "Debug" or <(cast_is_debug_build) == 1 else 0',
+ '-e', 'CAST_PRODUCT_TYPE=<(cast_product_type)',
'common/version.h.in',
'<@(_outputs)',
],
@@ -270,24 +401,6 @@
},
],
},
- {
- 'target_name': 'cast_metrics_test_support',
- 'type': '<(component)',
- 'dependencies': [
- 'cast_base',
- ],
- 'sources': [
- 'base/metrics/cast_metrics_test_helper.cc',
- 'base/metrics/cast_metrics_test_helper.h',
- ],
- }, # end of target 'cast_metrics_test_support'
- {
- 'target_name': 'cast_tests',
- 'type': 'none',
- 'dependencies': [
- 'media/media.gyp:cast_media_unittests',
- ],
- },
], # end of targets
# Targets for Android receiver.
@@ -295,18 +408,35 @@
['OS=="android"', {
'targets': [
{
+ 'target_name': 'cast_shell_icudata',
+ 'type': 'none',
+ 'dependencies': [
+ '../third_party/icu/icu.gyp:icudata',
+ '../v8/tools/gyp/v8.gyp:v8_external_snapshot',
+ ],
+ 'copies': [{
+ 'destination': '<(PRODUCT_DIR)/assets',
+ 'files': [
+ '<(PRODUCT_DIR)/icudtl.dat',
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ }],
+ },
+ {
'target_name': 'libcast_shell_android',
'type': 'shared_library',
'dependencies': [
'cast_jni_headers',
'cast_shell_common',
+ 'cast_shell_icudata',
'cast_shell_pak',
'cast_version_header',
'../base/base.gyp:base',
'../breakpad/breakpad.gyp:breakpad_client',
'../components/components.gyp:breakpad_host',
'../components/components.gyp:crash_component',
- '../content/content.gyp:content_app_browser',
+ '../components/components.gyp:external_video_surface',
'../content/content.gyp:content',
'../skia/skia.gyp:skia',
'../ui/gfx/gfx.gyp:gfx',
@@ -326,8 +456,6 @@
'browser/android/cast_window_android.h',
'browser/android/cast_window_manager.cc',
'browser/android/cast_window_manager.h',
- 'browser/android/external_video_surface_container_impl.cc',
- 'browser/android/external_video_surface_container_impl.h',
'crash/android/cast_crash_reporter_client_android.cc',
'crash/android/cast_crash_reporter_client_android.h',
'crash/android/crash_handler.cc',
@@ -336,7 +464,7 @@
'conditions': [
['chromecast_branding=="Chrome"', {
'dependencies': [
- '<(cast_internal_gyp):cast_shell_android_internal'
+ 'internal/chromecast_internal.gyp:cast_shell_android_internal'
],
}, {
'sources': [
@@ -366,6 +494,15 @@
'includes': ['../build/java.gypi'],
}, # end of target 'cast_shell_java'
{
+ 'target_name': 'cast_shell_manifest',
+ 'type': 'none',
+ 'variables': {
+ 'jinja_inputs': ['browser/android/apk/AndroidManifest.xml.jinja2'],
+ 'jinja_output': '<(SHARED_INTERMEDIATE_DIR)/cast_shell_manifest/AndroidManifest.xml',
+ },
+ 'includes': [ '../build/android/jinja_template.gypi' ],
+ },
+ {
'target_name': 'cast_shell_apk',
'type': 'none',
'dependencies': [
@@ -382,7 +519,7 @@
# if the actual Java path is used.
# This will hopefully be removable after the great GN migration.
'java_in_dir': 'android',
- 'android_manifest_path': 'browser/android/apk/AndroidManifest.xml',
+ 'android_manifest_path': '<(SHARED_INTERMEDIATE_DIR)/cast_shell_manifest/AndroidManifest.xml',
'package_name': 'org.chromium.chromecast.shell',
'native_lib_target': 'libcast_shell_android',
'asset_location': '<(PRODUCT_DIR)/assets',
@@ -397,7 +534,6 @@
'browser/android/apk/src/org/chromium/chromecast/shell/CastCrashHandler.java',
'browser/android/apk/src/org/chromium/chromecast/shell/CastWindowAndroid.java',
'browser/android/apk/src/org/chromium/chromecast/shell/CastWindowManager.java',
- 'browser/android/apk/src/org/chromium/chromecast/shell/ExternalVideoSurfaceContainer.java',
],
'direct_dependent_settings': {
'include_dirs': [
@@ -412,6 +548,46 @@
], # end of targets
}, { # OS != "android"
'targets': [
+ {
+ 'target_name': 'cast_shell_media',
+ 'type': '<(component)',
+ 'dependencies': [
+ 'media/media.gyp:cast_media',
+ '../content/content.gyp:content',
+ '../ipc/ipc.gyp:ipc',
+ '../media/media.gyp:media',
+ ],
+ 'sources': [
+ 'browser/media/cast_browser_cdm_factory.cc',
+ 'browser/media/cast_browser_cdm_factory.h',
+ 'browser/media/cma_message_filter_host.cc',
+ 'browser/media/cma_message_filter_host.h',
+ 'browser/media/cma_message_loop.cc',
+ 'browser/media/cma_message_loop.h',
+ 'browser/media/media_pipeline_host.cc',
+ 'browser/media/media_pipeline_host.h',
+ 'common/media/cma_ipc_common.h',
+ 'common/media/cma_messages.h',
+ 'common/media/cma_message_generator.cc',
+ 'common/media/cma_message_generator.h',
+ 'common/media/cma_param_traits.cc',
+ 'common/media/cma_param_traits.h',
+ 'common/media/shared_memory_chunk.cc',
+ 'common/media/shared_memory_chunk.h',
+ 'renderer/media/audio_pipeline_proxy.cc',
+ 'renderer/media/audio_pipeline_proxy.h',
+ 'renderer/media/chromecast_media_renderer_factory.cc',
+ 'renderer/media/chromecast_media_renderer_factory.h',
+ 'renderer/media/cma_message_filter_proxy.cc',
+ 'renderer/media/cma_message_filter_proxy.h',
+ 'renderer/media/media_channel_proxy.cc',
+ 'renderer/media/media_channel_proxy.h',
+ 'renderer/media/media_pipeline_proxy.cc',
+ 'renderer/media/media_pipeline_proxy.h',
+ 'renderer/media/video_pipeline_proxy.cc',
+ 'renderer/media/video_pipeline_proxy.h',
+ ],
+ }, # end of target 'cast_shell_media'
# This target contains all of the primary code of |cast_shell|, except
# for |main|. This allows end-to-end tests using |cast_shell|.
# This also includes all targets that cannot be built on Android.
@@ -419,17 +595,12 @@
'target_name': 'cast_shell_core',
'type': '<(component)',
'dependencies': [
- 'cast_net',
+ 'cast_shell_media',
'cast_shell_common',
'media/media.gyp:cast_media',
- '../ui/aura/aura.gyp:aura_test_support',
],
'conditions': [
- ['chromecast_branding=="Chrome"', {
- 'dependencies': [
- '<(cast_internal_gyp):cast_gfx_internal',
- ],
- }, {
+ ['ozone_platform_egltest==1', {
'dependencies': [
'../ui/ozone/ozone.gyp:eglplatform_shim_x11',
],
@@ -445,39 +616,34 @@
'sources': [
'app/cast_main.cc',
],
- },
- {
- 'target_name': 'cast_shell_browser_test',
- 'type': '<(gtest_target_type)',
- 'dependencies': [
- 'cast_shell_test_support',
- '../testing/gtest.gyp:gtest',
- ],
- 'defines': [
- 'HAS_OUT_OF_PROC_TEST_RUNNER',
- ],
- 'sources': [
- 'browser/test/chromecast_shell_browser_test.cc',
+ 'ldflags': [
+ # Allow OEMs to override default libraries that are shipped with
+ # cast receiver package by installed OEM-specific libraries in
+ # /oem_cast_shlib.
+ '-Wl,-rpath=/oem_cast_shlib',
+ # TODO(dougsteed): remove when Chromecast moves to boringssl.
+ # Allow the cast shell to find the NSS module in the same
+ # directory.
+ '-Wl,-rpath=\$$ORIGIN'
],
},
+ ], # end of targets
+ }],
+ ['enable_default_cast_graphics==1', {
+ 'targets': [
{
- 'target_name': 'cast_shell_test_support',
- 'type': '<(component)',
- 'defines': [
- 'HAS_OUT_OF_PROC_TEST_RUNNER',
- ],
+ 'target_name': 'libcast_graphics_1.0',
+ 'type': 'shared_library',
'dependencies': [
- 'cast_shell_core',
- '../content/content_shell_and_tests.gyp:content_browser_test_support',
- '../testing/gtest.gyp:gtest',
+ 'cast_public_api'
],
'sources': [
- 'browser/test/chromecast_browser_test.cc',
- 'browser/test/chromecast_browser_test.h',
- 'browser/test/chromecast_browser_test_runner.cc',
+ 'graphics/cast_egl_platform_default.cc',
+ 'graphics/graphics_properties_default.cc',
+ 'graphics/osd_plane_default.cc'
],
- },
- ], # end of targets
+ }
+ ]
}],
], # end of conditions
}
diff --git a/chromium/chromecast/chromecast_tests.gypi b/chromium/chromecast/chromecast_tests.gypi
new file mode 100644
index 00000000000..a5a7204fcc4
--- /dev/null
+++ b/chromium/chromecast/chromecast_tests.gypi
@@ -0,0 +1,286 @@
+# Copyright (c) 2014 Google Inc. All Rights Reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1
+ },
+ 'targets': [
+ {
+ 'target_name': 'cast_base_unittests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'chromecast.gyp:cast_base',
+ '../base/base.gyp:run_all_unittests',
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'base/serializers_unittest.cc',
+ ],
+ },
+ {
+ 'target_name': 'cast_tests',
+ 'type': 'none',
+ 'dependencies': [
+ 'cast_test_generator',
+ ],
+ 'conditions': [
+ ['chromecast_branding=="Chrome"', {
+ 'dependencies': [
+ 'internal/chromecast_internal.gyp:cast_tests_internal',
+ ],
+ }],
+ ],
+ },
+ # This target only depends on targets that generate test binaries.
+ {
+ 'target_name': 'cast_test_generator',
+ 'type': 'none',
+ 'dependencies': [
+ 'cast_base_unittests',
+ '../base/base.gyp:base_unittests',
+ '../content/content_shell_and_tests.gyp:content_unittests',
+ '../crypto/crypto.gyp:crypto_unittests',
+ '../ipc/ipc.gyp:ipc_tests',
+ '../jingle/jingle.gyp:jingle_unittests',
+ '../media/media.gyp:media_unittests',
+ '../media/midi/midi.gyp:midi_unittests',
+ '../net/net.gyp:net_unittests',
+ '../sandbox/sandbox.gyp:sandbox_linux_unittests',
+ '../sql/sql.gyp:sql_unittests',
+ '../sync/sync.gyp:sync_unit_tests',
+ '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+ '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+ '../url/url.gyp:url_unittests',
+ ],
+ 'conditions': [
+ ['target_arch=="arm" and OS!="android"', {
+ 'variables': {
+ 'filters': [
+ # Run net_unittests first to avoid random failures due to slow python startup
+ # KeygenHandlerTest.SmokeTest and KeygenHandlerTest.ConcurrencyTest fail due to
+ # readonly certdb (b/8153161)
+ # URLRequestTestHTTP.GetTest_ManyCookies takes roughly 55s to run. Increase
+ # timeout to 75s from 45s to allow it to pass (b/19821476)
+ # ProxyScriptFetcherImplTest.HttpMimeType is flaking (b/19848784)
+ 'net_unittests --gtest_filter=-KeygenHandlerTest.SmokeTest:KeygenHandlerTest.ConcurrencyTest:ProxyScriptFetcherImplTest.HttpMimeType --test-launcher-timeout=75000',
+ # Disable ProcessMetricsTest.GetNumberOfThreads (b/15610509)
+ # Disable ProcessUtilTest.* (need to define OS_ANDROID)
+ # Disable StackContainer.BufferAlignment (don't support 16-byte alignment)
+ # Disable SystemMetrics2Test.GetSystemMemoryInfo (buffers>0 can't be guaranteed)
+ 'base_unittests --gtest_filter=-ProcessMetricsTest.GetNumberOfThreads:ProcessUtilTest.*:StackContainer.BufferAlignment:SystemMetrics2Test.GetSystemMemoryInfo',
+ # DesktopCaptureDeviceTest.*: No capture device on Eureka
+ # Disable PepperGamepadHostTest.WaitForReply (pepper not supported on Eureka)
+ # Disable GpuDataManagerImplPrivateTest.SetGLStrings and
+ # RenderWidgetHostTest.Background because we disable the blacklist to enable WebGL (b/16142554)
+ 'content_unittests --gtest_filter=-DOMStorageDatabaseTest.TestCanOpenAndReadWebCoreDatabase:DesktopCaptureDeviceTest.Capture:GamepadProviderTest.PollingAccess:GpuDataManagerImplPrivateTest.SetGLStrings:PepperGamepadHostTest.WaitForReply:RenderWidgetHostTest.Background',
+ # Disable VP9 related tests (b/18593324)
+ # PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM
+ # PipelineIntegrationTest.BasicPlayback_VideoOnly_VP9_WebM
+ # PipelineIntegrationTest.BasicPlayback_VP9*
+ # PipelineIntegrationTest.P444_VP9_WebM
+ # Disable VP8A tests (b/18593324)
+ # PipelineIntegrationTest.BasicPlayback_VP8A*
+ # Disable OpusAudioDecoderTest/AudioDecoderTest.ProduceAudioSamples/0 (unit
+ # test fails when Opus decoder uses fixed-point)
+ # Due to b/16456550, disable the following four test cases:
+ # AudioOutputControllerTest.PlayDivertSwitchDeviceRevertClose
+ # AudioOutputControllerTest.PlaySwitchDeviceClose
+ # AudioStreamHandlerTest.Play
+ # SoundsManagerTest.Play
+ # Disable AudioStreamHandlerTest.ConsecutivePlayRequests (b/16539293)
+ 'media_unittests --gtest_filter=-AudioOutputControllerTest.PlayDivertSwitchDeviceRevertClose:AudioOutputControllerTest.PlaySwitchDeviceClose:AudioStreamHandlerTest.Play:AudioStreamHandlerTest.ConsecutivePlayRequests:PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM:PipelineIntegrationTest.BasicPlayback_VideoOnly_VP9_WebM:PipelineIntegrationTest.BasicPlayback_VP9*:PipelineIntegrationTest.P444_VP9_WebM:PipelineIntegrationTest.BasicPlayback_VP8A*:OpusAudioDecoderTest/AudioDecoderTest.ProduceAudioSamples/0:SoundsManagerTest.Play',
+ 'sync_unit_tests --gtest_filter=-SyncHttpBridgeTest.*',
+ # DoAppendUTF8Invalid fails because of dcheck_always_on flag in Eng builds
+ 'url_unittests --gtest_filter=-URLCanonTest.DoAppendUTF8Invalid',
+ ],
+ },
+ }, { # else "x86" or "android"
+ 'variables': {
+ 'filters': [
+ # Disable PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM (not supported)
+ 'media_unittests --gtest_filter=-PipelineIntegrationTest.BasicPlayback_MediaSource_VP9_WebM',
+ ],
+ }
+ }],
+ ['disable_display==0', {
+ 'dependencies': [
+ '../gpu/gpu.gyp:gpu_unittests',
+ ],
+ }],
+ ['OS!="android"', {
+ 'dependencies': [
+ 'cast_shell_browser_test',
+ 'cast_shell_media_unittests',
+ 'media/media.gyp:cast_media_unittests',
+ ],
+ 'variables': {
+ 'filters': [
+ 'cast_shell_browser_test --no-sandbox --disable-gpu',
+ ],
+ },
+ }],
+ ],
+ 'includes': ['build/tests/test_list.gypi'],
+ },
+ # Builds all tests and the output lists of build/run targets for those tests.
+ # Note: producing a predetermined list of dependent inputs on which to
+ # regenerate this output is difficult with GYP. This file is not
+ # guaranteed to be regenerated outside of a clean build.
+ {
+ 'target_name': 'cast_test_lists',
+ 'type': 'none',
+ 'dependencies': [
+ 'cast_tests',
+ ],
+ 'variables': {
+ 'test_generator_py': '<(DEPTH)/chromecast/tools/build/generate_test_lists.py',
+ 'test_inputs_dir': '<(SHARED_INTERMEDIATE_DIR)/chromecast/tests',
+ 'test_additional_options': '--ozone-platform=test'
+ },
+ 'actions': [
+ {
+ 'action_name': 'generate_combined_test_build_list',
+ 'message': 'Generating combined test build list',
+ 'inputs': ['<(test_generator_py)'],
+ 'outputs': ['<(PRODUCT_DIR)/tests/build_test_list.txt'],
+ 'action': [
+ 'python', '<(test_generator_py)',
+ '-t', '<(test_inputs_dir)',
+ '-o', '<@(_outputs)',
+ 'pack_build',
+ ],
+ },
+ {
+ 'action_name': 'generate_combined_test_run_list',
+ 'message': 'Generating combined test run list',
+ 'inputs': ['<(test_generator_py)'],
+ 'outputs': ['<(PRODUCT_DIR)/tests/run_test_list.txt'],
+ 'action': [
+ 'python', '<(test_generator_py)',
+ '-t', '<(test_inputs_dir)',
+ '-o', '<@(_outputs)',
+ '-a', '<(test_additional_options)',
+ 'pack_run',
+ ],
+ }
+ ],
+ },
+ {
+ 'target_name': 'cast_metrics_test_support',
+ 'type': '<(component)',
+ 'dependencies': [
+ 'cast_base',
+ ],
+ 'sources': [
+ 'base/metrics/cast_metrics_test_helper.cc',
+ 'base/metrics/cast_metrics_test_helper.h',
+ ],
+ }, # end of target 'cast_metrics_test_support'
+ ], # end of targets
+ 'conditions': [
+ ['OS=="android"', {
+ 'targets': [
+ {
+ 'target_name': 'cast_android_tests',
+ 'type': 'none',
+ 'dependencies': [
+ '../base/base.gyp:base_unittests_apk',
+ '../cc/cc_tests.gyp:cc_unittests_apk',
+ '../ipc/ipc.gyp:ipc_tests_apk',
+ '../media/media.gyp:media_unittests_apk',
+ '../media/midi/midi.gyp:midi_unittests_apk',
+ '../net/net.gyp:net_unittests_apk',
+ '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests_apk',
+ '../sql/sql.gyp:sql_unittests_apk',
+ '../sync/sync.gyp:sync_unit_tests_apk',
+ '../ui/events/events.gyp:events_unittests_apk',
+ '../ui/gfx/gfx_tests.gyp:gfx_unittests_apk',
+ ],
+ 'includes': ['build/tests/test_list.gypi'],
+ },
+ {
+ 'target_name': 'cast_android_test_lists',
+ 'type': 'none',
+ 'dependencies': [
+ 'cast_android_tests',
+ ],
+ 'variables': {
+ 'test_generator_py': '<(DEPTH)/chromecast/tools/build/generate_test_lists.py',
+ 'test_inputs_dir': '<(SHARED_INTERMEDIATE_DIR)/chromecast/tests',
+ },
+ 'actions': [
+ {
+ 'action_name': 'generate_combined_test_build_list',
+ 'message': 'Generating combined test build list',
+ 'inputs': ['<(test_generator_py)'],
+ 'outputs': ['<(PRODUCT_DIR)/tests/build_test_list_android.txt'],
+ 'action': [
+ 'python', '<(test_generator_py)',
+ '-t', '<(test_inputs_dir)',
+ '-o', '<@(_outputs)',
+ 'pack_build',
+ ],
+ },
+ ],
+ },
+ ], # end of targets
+ }, { # OS!="android"
+ 'targets': [
+ {
+ 'target_name': 'cast_shell_media_unittests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'cast_metrics_test_support',
+ 'cast_shell_media',
+ 'media/media.gyp:cast_media',
+ '../base/base.gyp:base',
+ '../base/base.gyp:test_support_base',
+ '../ipc/ipc.gyp:test_support_ipc',
+ '../media/media.gyp:media_test_support',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../testing/gtest.gyp:gtest_main',
+ ],
+ 'sources': [
+ 'renderer/media/cma_renderer_unittest.cc',
+ 'media/cma/test/run_all_unittests.cc',
+ ],
+ },
+ {
+ 'target_name': 'cast_shell_test_support',
+ 'type': '<(component)',
+ 'defines': [
+ 'HAS_OUT_OF_PROC_TEST_RUNNER',
+ ],
+ 'dependencies': [
+ 'cast_shell_core',
+ '../content/content_shell_and_tests.gyp:content_browser_test_support',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ ],
+ 'sources': [
+ 'browser/test/chromecast_browser_test.cc',
+ 'browser/test/chromecast_browser_test.h',
+ 'browser/test/chromecast_browser_test_runner.cc',
+ ],
+ }, # end of target 'cast_shell_test_support'
+ {
+ 'target_name': 'cast_shell_browser_test',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'cast_shell_test_support',
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'defines': [
+ 'HAS_OUT_OF_PROC_TEST_RUNNER',
+ ],
+ 'sources': [
+ 'browser/test/chromecast_shell_browser_test.cc',
+ ],
+ },
+ ], # end of targets
+ }],
+ ], # end of conditions
+}
diff --git a/chromium/chromecast/common/cast_content_client.cc b/chromium/chromecast/common/cast_content_client.cc
index e93b7d2a51b..4772fdd5c06 100644
--- a/chromium/chromecast/common/cast_content_client.cc
+++ b/chromium/chromecast/common/cast_content_client.cc
@@ -4,6 +4,8 @@
#include "chromecast/common/cast_content_client.h"
+#include "base/strings/stringprintf.h"
+#include "base/sys_info.h"
#include "chromecast/common/version.h"
#include "content/public/common/user_agent.h"
#include "ui/base/l10n/l10n_util.h"
@@ -12,9 +14,56 @@
namespace chromecast {
namespace shell {
+namespace {
+
+#if defined(OS_ANDROID)
+std::string BuildAndroidOsInfo() {
+ int32 os_major_version = 0;
+ int32 os_minor_version = 0;
+ int32 os_bugfix_version = 0;
+ base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
+ &os_minor_version,
+ &os_bugfix_version);
+
+ std::string android_version_str;
+ base::StringAppendF(
+ &android_version_str, "%d.%d", os_major_version, os_minor_version);
+ if (os_bugfix_version != 0)
+ base::StringAppendF(&android_version_str, ".%d", os_bugfix_version);
+
+ std::string android_info_str;
+ // Append the build ID.
+ std::string android_build_id = base::SysInfo::GetAndroidBuildID();
+ if (android_build_id.size() > 0)
+ android_info_str += "; Build/" + android_build_id;
+
+ std::string os_info;
+ base::StringAppendF(
+ &os_info,
+ "Android %s%s",
+ android_version_str.c_str(),
+ android_info_str.c_str());
+ return os_info;
+}
+#endif
+
+} // namespace
+
std::string GetUserAgent() {
std::string product = "Chrome/" PRODUCT_VERSION;
- return content::BuildUserAgentFromProduct(product) +
+ std::string os_info;
+ base::StringAppendF(
+ &os_info,
+ "%s%s",
+#if defined(OS_ANDROID)
+ "Linux; ",
+ BuildAndroidOsInfo().c_str()
+#else
+ "X11; ",
+ content::BuildOSCpuInfo().c_str()
+#endif
+ );
+ return content::BuildUserAgentFromOSAndProduct(os_info, product) +
" CrKey/" CAST_BUILD_REVISION;
}
diff --git a/chromium/chromecast/common/cast_content_client.h b/chromium/chromecast/common/cast_content_client.h
index 3a4d61d71f7..8289f41b34f 100644
--- a/chromium/chromecast/common/cast_content_client.h
+++ b/chromium/chromecast/common/cast_content_client.h
@@ -14,17 +14,17 @@ std::string GetUserAgent();
class CastContentClient : public content::ContentClient {
public:
- virtual ~CastContentClient();
+ ~CastContentClient() override;
// content::ContentClient implementation:
- virtual std::string GetUserAgent() const override;
- virtual base::string16 GetLocalizedString(int message_id) const override;
- virtual base::StringPiece GetDataResource(
+ std::string GetUserAgent() const override;
+ base::string16 GetLocalizedString(int message_id) const override;
+ base::StringPiece GetDataResource(
int resource_id,
ui::ScaleFactor scale_factor) const override;
- virtual base::RefCountedStaticMemory* GetDataResourceBytes(
+ base::RefCountedStaticMemory* GetDataResourceBytes(
int resource_id) const override;
- virtual gfx::Image& GetNativeImageNamed(int resource_id) const override;
+ gfx::Image& GetNativeImageNamed(int resource_id) const override;
};
} // namespace shell
diff --git a/chromium/chromecast/common/cast_resource_delegate.h b/chromium/chromecast/common/cast_resource_delegate.h
index 8e248c3453a..3e4cac2e4cb 100644
--- a/chromium/chromecast/common/cast_resource_delegate.h
+++ b/chromium/chromecast/common/cast_resource_delegate.h
@@ -30,29 +30,27 @@ class CastResourceDelegate : public ui::ResourceBundle::Delegate {
static CastResourceDelegate* GetInstance();
CastResourceDelegate();
- virtual ~CastResourceDelegate();
+ ~CastResourceDelegate() override;
// ui:ResourceBundle::Delegate implementation:
- virtual base::FilePath GetPathForResourcePack(
+ base::FilePath GetPathForResourcePack(
const base::FilePath& pack_path,
ui::ScaleFactor scale_factor) override;
- virtual base::FilePath GetPathForLocalePack(
+ base::FilePath GetPathForLocalePack(
const base::FilePath& pack_path,
const std::string& locale) override;
- virtual gfx::Image GetImageNamed(int resource_id) override;
- virtual gfx::Image GetNativeImageNamed(
+ gfx::Image GetImageNamed(int resource_id) override;
+ gfx::Image GetNativeImageNamed(
int resource_id,
ui::ResourceBundle::ImageRTL rtl) override;
- virtual base::RefCountedStaticMemory* LoadDataResourceBytes(
+ base::RefCountedStaticMemory* LoadDataResourceBytes(
int resource_id,
ui::ScaleFactor scale_factor) override;
- virtual bool GetRawDataResource(int resource_id,
- ui::ScaleFactor scale_factor,
- base::StringPiece* value) override;
- virtual bool GetLocalizedString(int message_id,
- base::string16* value) override;
- virtual scoped_ptr<gfx::Font> GetFont(
- ui::ResourceBundle::FontStyle style) override;
+ bool GetRawDataResource(int resource_id,
+ ui::ScaleFactor scale_factor,
+ base::StringPiece* value) override;
+ bool GetLocalizedString(int message_id, base::string16* value) override;
+ scoped_ptr<gfx::Font> GetFont(ui::ResourceBundle::FontStyle style) override;
// Adds/removes/clears extra localized strings.
void AddExtraLocalizedString(int resource_id,
diff --git a/chromium/chromecast/common/chromecast_config.cc b/chromium/chromecast/common/chromecast_config.cc
deleted file mode 100644
index 4b5e6bf8053..00000000000
--- a/chromium/chromecast/common/chromecast_config.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromecast/common/chromecast_config.h"
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/prefs/json_pref_store.h"
-#include "base/prefs/pref_registry_simple.h"
-#include "base/prefs/pref_service_factory.h"
-#include "base/prefs/pref_store.h"
-#include "base/strings/string_number_conversions.h"
-#include "chromecast/common/cast_paths.h"
-#include "chromecast/common/pref_names.h"
-
-namespace chromecast {
-
-namespace {
-
-// Config file IO worker constants.
-const int kNumOfConfigFileIOWorkers = 1;
-const char kNameOfConfigFileIOWorkers[] = "ConfigFileIO";
-
-void UserPrefsLoadError(
- PersistentPrefStore::PrefReadError* error_val,
- PersistentPrefStore::PrefReadError error) {
- DCHECK(error_val);
- *error_val = error;
-}
-
-base::FilePath GetConfigPath() {
- base::FilePath config_path;
- CHECK(PathService::Get(FILE_CAST_CONFIG, &config_path));
- return config_path;
-}
-
-} // namespace
-
-// static
-ChromecastConfig* ChromecastConfig::g_instance_ = NULL;
-
-// static
-void ChromecastConfig::Create(PrefRegistrySimple* registry) {
- DCHECK(g_instance_ == NULL);
- g_instance_ = new ChromecastConfig();
- g_instance_->Load(registry);
-}
-
-// static
-ChromecastConfig* ChromecastConfig::GetInstance() {
- DCHECK(g_instance_ != NULL);
- return g_instance_;
-}
-
-ChromecastConfig::ChromecastConfig()
- : config_path_(GetConfigPath()),
- worker_pool_(new base::SequencedWorkerPool(kNumOfConfigFileIOWorkers,
- kNameOfConfigFileIOWorkers)) {
-}
-
-ChromecastConfig::~ChromecastConfig() {
- // Explict writing before worker_pool shutdown.
- pref_service_->CommitPendingWrite();
- worker_pool_->Shutdown();
-}
-
-bool ChromecastConfig::Load(PrefRegistrySimple* registry) {
- DCHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "Loading config from " << config_path_.value();
- registry->RegisterIntegerPref(prefs::kRemoteDebuggingPort, 0);
-
- RegisterPlatformPrefs(registry);
-
- PersistentPrefStore::PrefReadError prefs_read_error =
- PersistentPrefStore::PREF_READ_ERROR_NONE;
- base::PrefServiceFactory prefServiceFactory;
- scoped_refptr<base::SequencedTaskRunner> task_runner =
- JsonPrefStore::GetTaskRunnerForFile(config_path_, worker_pool_.get());
- prefServiceFactory.SetUserPrefsFile(config_path_, task_runner.get());
- prefServiceFactory.set_async(false);
- prefServiceFactory.set_read_error_callback(
- base::Bind(&UserPrefsLoadError, &prefs_read_error));
- pref_service_ = prefServiceFactory.Create(registry);
-
- if (prefs_read_error == PersistentPrefStore::PREF_READ_ERROR_NONE) {
- return true;
- } else {
- LOG(ERROR) << "Cannot initialize chromecast config: "
- << config_path_.value()
- << ", pref_error=" << prefs_read_error;
- return false;
- }
-}
-
-void ChromecastConfig::Save() const {
- DCHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "Saving config to: " << config_path_.value();
- pref_service_->CommitPendingWrite();
-}
-
-const std::string ChromecastConfig::GetValue(const std::string& key) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- return pref_service_->GetString(key.c_str());
-}
-
-const int ChromecastConfig::GetIntValue(const std::string& key) const {
- return pref_service_->GetInteger(key.c_str());
-}
-
-void ChromecastConfig::SetValue(
- const std::string& key,
- const std::string& value) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (pref_service_->IsUserModifiablePreference(key.c_str())) {
- VLOG(1) << "Set config: key=" << key << ", value=" << value;
- pref_service_->SetString(key.c_str(), value);
- } else {
- LOG(ERROR) << "Cannot set read-only config: key=" << key
- << ", value=" << value;
- }
-}
-
-void ChromecastConfig::SetIntValue(const std::string& key, int value) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (pref_service_->IsUserModifiablePreference(key.c_str())) {
- VLOG(1) << "Set config: key=" << key << ", value=" << value;
- pref_service_->SetInteger(key.c_str(), value);
- } else {
- LOG(ERROR) << "Cannot set read-only config: key=" << key
- << ", value=" << value;
- }
-}
-
-bool ChromecastConfig::HasValue(const std::string& key) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- return pref_service_->HasPrefPath(key.c_str());
-}
-
-} // namespace chromecast
diff --git a/chromium/chromecast/common/chromecast_config.h b/chromium/chromecast/common/chromecast_config.h
deleted file mode 100644
index 23482c6be4d..00000000000
--- a/chromium/chromecast/common/chromecast_config.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Chromecast-specific configurations retrieved from and stored into a given
-// configuration file.
-
-#ifndef CHROMECAST_COMMON_CHROMECAST_CONFIG_H_
-#define CHROMECAST_COMMON_CHROMECAST_CONFIG_H_
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/prefs/pref_service.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/threading/thread_checker.h"
-
-class PrefRegistrySimple;
-
-namespace chromecast {
-
-// Manages configuration for Chromecast via PrefService.
-// It uses JsonPrefStore internally and/so the format of config file is same to
-// that of JsonPrefStore.
-// It is NOT thread-safe; all functions must be run on the same thread as
-// the object is created.
-class ChromecastConfig {
- public:
- // Creates new singleton instance of ChromecastConfig.
- static void Create(PrefRegistrySimple* registry);
-
- // Returns the singleton instance of ChromecastConfig.
- static ChromecastConfig* GetInstance();
-
- // Saves configs into configuration file.
- void Save() const;
-
- // Returns string value for |key|, if present.
- const std::string GetValue(const std::string& key) const;
-
- // Returns integer value for |key|, if present.
- const int GetIntValue(const std::string& key) const;
-
- // Sets new string value for |key|.
- void SetValue(const std::string& key, const std::string& value) const;
-
- // Sets new int value for |key|.
- void SetIntValue(const std::string& key, int value) const;
-
- // Whether or not a value has been set for |key|.
- bool HasValue(const std::string& key) const;
-
- scoped_refptr<base::SequencedWorkerPool> worker_pool() const {
- return worker_pool_;
- }
-
- PrefService* pref_service() const { return pref_service_.get(); }
-
- private:
- ChromecastConfig();
- ~ChromecastConfig();
-
- // Loads configs from config file. Returns true if successful.
- bool Load(PrefRegistrySimple* registry);
-
- // Registers any needed preferences for the current platform.
- void RegisterPlatformPrefs(PrefRegistrySimple* registry);
-
- // Global singleton instance.
- static ChromecastConfig* g_instance_;
-
- const base::FilePath config_path_;
- const scoped_refptr<base::SequencedWorkerPool> worker_pool_;
- scoped_ptr<PrefService> pref_service_;
-
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(ChromecastConfig);
-};
-
-} // namespace chromecast
-
-#endif // CHROMECAST_COMMON_CHROMECAST_CONFIG_H_
diff --git a/chromium/chromecast/common/chromecast_switches.cc b/chromium/chromecast/common/chromecast_switches.cc
index 0ccbf7bc0cf..435a35abdf9 100644
--- a/chromium/chromecast/common/chromecast_switches.cc
+++ b/chromium/chromecast/common/chromecast_switches.cc
@@ -6,12 +6,27 @@
namespace switches {
-#if defined(OS_ANDROID)
-// Enable file accesses for debug.
+// Enable the CMA media pipeline.
+const char kEnableCmaMediaPipeline[] = "enable-cma-media-pipeline";
+
+// The bitmask of codecs (media_caps.h) supported by the current HDMI sink.
+const char kHdmiSinkSupportedCodecs[] = "hdmi-sink-supported-codecs";
+
+// Enable file accesses. It should not be enabled for most Cast devices.
const char kEnableLocalFileAccesses[] = "enable-local-file-accesses";
-#endif // defined(OS_ANDROID)
// Override the URL to which metrics logs are sent for debugging.
const char kOverrideMetricsUploadUrl[] = "override-metrics-upload-url";
+// Disable features that require WiFi management.
+const char kNoWifi[] = "no-wifi";
+
+// Pass the app id information to the renderer process, to be used for logging.
+// last-launched-app should be the app that just launched and is spawning the
+// renderer.
+const char kLastLaunchedApp[] = "last-launched-app";
+// previous-app should be the app that was running when last-launched-app
+// started.
+const char kPreviousApp[] = "previous-app";
+
} // namespace switches
diff --git a/chromium/chromecast/common/chromecast_switches.h b/chromium/chromecast/common/chromecast_switches.h
index 4fc0e715892..697a8a15763 100644
--- a/chromium/chromecast/common/chromecast_switches.h
+++ b/chromium/chromecast/common/chromecast_switches.h
@@ -9,14 +9,23 @@
namespace switches {
-#if defined(OS_ANDROID)
+// Media switches
+extern const char kEnableCmaMediaPipeline[];
+extern const char kHdmiSinkSupportedCodecs[];
+
// Content-implementation switches
extern const char kEnableLocalFileAccesses[];
-#endif // defined(OS_ANDROID)
// Metrics switches
extern const char kOverrideMetricsUploadUrl[];
+// Network switches
+extern const char kNoWifi[];
+
+// Switches to communicate app state information
+extern const char kLastLaunchedApp[];
+extern const char kPreviousApp[];
+
} // namespace switches
#endif // CHROMECAST_COMMON_CHROMECAST_SWITCHES_H_
diff --git a/chromium/chromecast/common/media/DEPS b/chromium/chromecast/common/media/DEPS
new file mode 100644
index 00000000000..b1e00c87d24
--- /dev/null
+++ b/chromium/chromecast/common/media/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+chromecast/media",
+ "+media/base",
+]
diff --git a/chromium/chromecast/common/media/OWNERS b/chromium/chromecast/common/media/OWNERS
new file mode 100644
index 00000000000..b4e262d45b4
--- /dev/null
+++ b/chromium/chromecast/common/media/OWNERS
@@ -0,0 +1,25 @@
+# Changes to IPC messages require a security review to avoid introducing
+# new sandbox escapes.
+per-file *_message*.h=set noparent
+per-file *_message*.h=dcheng@chromium.org
+per-file *_message*.h=inferno@chromium.org
+per-file *_message*.h=jln@chromium.org
+per-file *_message*.h=jschuh@chromium.org
+per-file *_message*.h=kenrb@chromium.org
+per-file *_message*.h=mkwst@chromium.org
+per-file *_message*.h=nasko@chromium.org
+per-file *_message*.h=palmer@chromium.org
+per-file *_message*.h=tsepez@chromium.org
+per-file *_message*.h=wfh@chromium.org
+
+per-file *_messages.cc=set noparent
+per-file *_messages.cc=dcheng@chromium.org
+per-file *_messages.cc=inferno@chromium.org
+per-file *_messages.cc=jln@chromium.org
+per-file *_messages.cc=jschuh@chromium.org
+per-file *_messages.cc=kenrb@chromium.org
+per-file *_messages.cc=mkwst@chromium.org
+per-file *_messages.cc=nasko@chromium.org
+per-file *_messages.cc=palmer@chromium.org
+per-file *_messages.cc=tsepez@chromium.org
+per-file *_messages.cc=wfh@chromium.org
diff --git a/chromium/chromecast/common/media/cast_message_generator.cc b/chromium/chromecast/common/media/cast_message_generator.cc
new file mode 100644
index 00000000000..ee6c73e2de9
--- /dev/null
+++ b/chromium/chromecast/common/media/cast_message_generator.cc
@@ -0,0 +1,15 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "chromecast/common/media/cast_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "chromecast/common/media/cast_message_generator.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "chromecast/common/media/cast_message_generator.h"
diff --git a/chromium/chromecast/common/media/cast_message_generator.h b/chromium/chromecast/common/media/cast_message_generator.h
new file mode 100644
index 00000000000..ac6c0041c50
--- /dev/null
+++ b/chromium/chromecast/common/media/cast_message_generator.h
@@ -0,0 +1,8 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included file, hence no include guard.
+
+#include "chromecast/common/media/cast_messages.h"
+
diff --git a/chromium/chromecast/common/media/cast_messages.h b/chromium/chromecast/common/media/cast_messages.h
new file mode 100644
index 00000000000..3d9cc2a88c4
--- /dev/null
+++ b/chromium/chromecast/common/media/cast_messages.h
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages related to media on Chromecast.
+// Multiply-included message file, hence no include guard.
+
+#include "ipc/ipc_message_macros.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_START CastMediaMsgStart
+
+// Messages sent from the browser to the renderer process.
+
+IPC_MESSAGE_CONTROL1(CmaMsg_UpdateSupportedHdmiSinkCodecs,
+ int /* Codec support, bitmask of media_caps.h values */)
diff --git a/chromium/chromecast/common/media/cma_ipc_common.h b/chromium/chromecast/common/media/cma_ipc_common.h
new file mode 100644
index 00000000000..343110451f2
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_ipc_common.h
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_COMMON_MEDIA_CMA_IPC_COMMON_H_
+#define CHROMECAST_COMMON_MEDIA_CMA_IPC_COMMON_H_
+
+namespace chromecast {
+namespace media {
+
+enum TrackId {
+ kNoTrackId = -1,
+ kAudioTrackId = 0,
+ kVideoTrackId = 1,
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_COMMON_MEDIA_CMA_IPC_COMMON_H_
+
diff --git a/chromium/chromecast/common/media/cma_message_generator.cc b/chromium/chromecast/common/media/cma_message_generator.cc
new file mode 100644
index 00000000000..c6dd826dbbf
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_message_generator.cc
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "chromecast/common/media/cma_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "chromecast/common/media/cma_message_generator.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "chromecast/common/media/cma_message_generator.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#undef CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_MACROS_H_
+#include "chromecast/common/media/cma_message_generator.h"
+#include "chromecast/common/media/cma_param_traits_macros.h"
+} // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#undef CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_MACROS_H_
+#include "chromecast/common/media/cma_message_generator.h"
+#include "chromecast/common/media/cma_param_traits_macros.h"
+} // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#undef CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_MACROS_H_
+#include "chromecast/common/media/cma_message_generator.h"
+#include "chromecast/common/media/cma_param_traits_macros.h"
+} // namespace IPC
diff --git a/chromium/chromecast/common/media/cma_message_generator.h b/chromium/chromecast/common/media/cma_message_generator.h
new file mode 100644
index 00000000000..805066dc36c
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_message_generator.h
@@ -0,0 +1,8 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included file, hence no include guard.
+
+#include "chromecast/common/media/cma_messages.h"
+
diff --git a/chromium/chromecast/common/media/cma_messages.h b/chromium/chromecast/common/media/cma_messages.h
new file mode 100644
index 00000000000..3fbed3dbad7
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_messages.h
@@ -0,0 +1,115 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for the Cast Media Acceleration (CMA) pipeline.
+// Multiply-included message file, hence no include guard.
+
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/common/media/cma_param_traits.h"
+#include "chromecast/common/media/cma_param_traits_macros.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "content/public/common/common_param_traits.h"
+#include "ipc/ipc_message_macros.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/buffering_state.h"
+#include "media/base/pipeline_status.h"
+#include "media/base/video_decoder_config.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_START CastMediaMsgStart
+
+// Messages sent from the renderer to the browser process.
+
+IPC_MESSAGE_CONTROL2(CmaHostMsg_CreateMedia,
+ int /* Media pipeline ID */,
+ chromecast::media::LoadType /* Load type */)
+IPC_MESSAGE_CONTROL1(CmaHostMsg_DestroyMedia,
+ int /* Media pipeline ID */)
+IPC_MESSAGE_CONTROL3(CmaHostMsg_SetCdm,
+ int /* Media pipeline ID */,
+ int /* render_frame_id */,
+ int /* cdm_id */)
+IPC_MESSAGE_CONTROL2(CmaHostMsg_StartPlayingFrom,
+ int /* Media pipeline ID */,
+ base::TimeDelta /* Timestamp */)
+IPC_MESSAGE_CONTROL1(CmaHostMsg_Flush,
+ int /* Media pipeline ID */)
+IPC_MESSAGE_CONTROL1(CmaHostMsg_Stop,
+ int /* Media pipeline ID */)
+IPC_MESSAGE_CONTROL2(CmaHostMsg_SetPlaybackRate,
+ int /* Media pipeline ID */,
+ double /* Playback rate */)
+
+IPC_MESSAGE_CONTROL3(CmaHostMsg_CreateAvPipe,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ size_t /* Fifo size */)
+IPC_MESSAGE_CONTROL3(CmaHostMsg_AudioInitialize,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ media::AudioDecoderConfig /* Audio config */)
+IPC_MESSAGE_CONTROL3(CmaHostMsg_VideoInitialize,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ media::VideoDecoderConfig /* Video config */)
+IPC_MESSAGE_CONTROL3(CmaHostMsg_SetVolume,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ float /* Volume */)
+IPC_MESSAGE_CONTROL2(CmaHostMsg_NotifyPipeWrite,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */)
+
+IPC_MESSAGE_CONTROL5(CmaHostMsg_NotifyExternalSurface,
+ int /* Surface ID */,
+ gfx::PointF /* Quad video top left */,
+ gfx::PointF /* Quad video top right */,
+ gfx::PointF /* Quad video bottim right */,
+ gfx::PointF /* Quad video bottom left */)
+
+// Messages from the browser to the renderer process.
+
+IPC_MESSAGE_CONTROL2(CmaMsg_MediaStateChanged,
+ int /* Media pipeline ID */,
+ media::PipelineStatus /* Status */)
+IPC_MESSAGE_CONTROL4(CmaMsg_TimeUpdate,
+ int /* Media pipeline ID */,
+ base::TimeDelta /* Media time */,
+ base::TimeDelta /* Max media time */,
+ base::TimeTicks /* STC */)
+IPC_MESSAGE_CONTROL2(CmaMsg_BufferingNotification,
+ int /* Media pipeline ID */,
+ media::BufferingState /* Buffering state */)
+
+IPC_MESSAGE_CONTROL5(CmaMsg_AvPipeCreated,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ bool /* Status */,
+ base::SharedMemoryHandle /* Shared memory */,
+ base::FileDescriptor /* socket handle */)
+IPC_MESSAGE_CONTROL3(CmaMsg_TrackStateChanged,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ media::PipelineStatus /* Status */)
+IPC_MESSAGE_CONTROL2(CmaMsg_NotifyPipeRead,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */)
+
+IPC_MESSAGE_CONTROL2(CmaMsg_Eos,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */)
+IPC_MESSAGE_CONTROL3(CmaMsg_PlaybackError,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ media::PipelineStatus /* status */)
+IPC_MESSAGE_CONTROL3(CmaMsg_PlaybackStatistics,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ media::PipelineStatistics /* status */)
+IPC_MESSAGE_CONTROL3(CmaMsg_NaturalSizeChanged,
+ int /* Media pipeline ID */,
+ chromecast::media::TrackId /* Track ID */,
+ gfx::Size /* Size */) \ No newline at end of file
diff --git a/chromium/chromecast/common/media/cma_param_traits.cc b/chromium/chromecast/common/media/cma_param_traits.cc
new file mode 100644
index 00000000000..33accb04672
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_param_traits.cc
@@ -0,0 +1,135 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/common/media/cma_param_traits.h"
+
+#include <vector>
+
+#include "chromecast/common/media/cma_param_traits_macros.h"
+#include "content/public/common/common_param_traits.h"
+#include "ipc/ipc_message_macros.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
+
+// Note(gunsch): these are currently defined in content/, but not declared in
+// content/public/. These headers need to be forward-declared for chromecast/,
+// but without new implementations linked in.
+// The correct long-term fix is to use Mojo instead of the content/ IPCs.
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::ChannelLayout,
+ media::ChannelLayout::CHANNEL_LAYOUT_NONE,
+ media::ChannelLayout::CHANNEL_LAYOUT_MAX)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::VideoCodecProfile,
+ media::VIDEO_CODEC_PROFILE_MIN,
+ media::VIDEO_CODEC_PROFILE_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(media::VideoFrame::Format,
+ media::VideoFrame::FORMAT_MAX)
+
+namespace IPC {
+
+void ParamTraits<media::AudioDecoderConfig>::Write(
+ Message* m, const media::AudioDecoderConfig& p) {
+ ParamTraits<media::AudioCodec>::Write(m, p.codec());
+ ParamTraits<media::SampleFormat>::Write(m, p.sample_format());
+ ParamTraits<media::ChannelLayout>::Write(m, p.channel_layout());
+ ParamTraits<int>::Write(m, p.samples_per_second());
+ ParamTraits<bool>::Write(m, p.is_encrypted());
+ std::vector<uint8> extra_data;
+ if (p.extra_data_size() > 0) {
+ extra_data =
+ std::vector<uint8>(p.extra_data(),
+ p.extra_data() + p.extra_data_size());
+ }
+ ParamTraits<std::vector<uint8> >::Write(m, extra_data);
+}
+
+bool ParamTraits<media::AudioDecoderConfig>::Read(
+ const Message* m, PickleIterator* iter,
+ media::AudioDecoderConfig* r) {
+ media::AudioCodec codec;
+ media::SampleFormat sample_format;
+ media::ChannelLayout channel_layout;
+ int samples_per_second;
+ bool is_encrypted;
+ if (!ParamTraits<media::AudioCodec>::Read(m, iter, &codec) ||
+ !ParamTraits<media::SampleFormat>::Read(m, iter, &sample_format) ||
+ !ParamTraits<media::ChannelLayout>::Read(m, iter, &channel_layout) ||
+ !ParamTraits<int>::Read(m, iter, &samples_per_second) ||
+ !ParamTraits<bool>::Read(m, iter, &is_encrypted)) {
+ return false;
+ }
+ std::vector<uint8> extra_data;
+ if (!ParamTraits<std::vector<uint8> >::Read(m, iter, &extra_data))
+ return false;
+ const uint8* extra_data_ptr = NULL;
+ if (extra_data.size() > 0)
+ extra_data_ptr = &extra_data[0];
+ *r = media::AudioDecoderConfig(codec, sample_format, channel_layout,
+ samples_per_second,
+ extra_data_ptr, extra_data.size(),
+ is_encrypted);
+ return true;
+}
+
+void ParamTraits<media::AudioDecoderConfig>::Log(
+ const media::AudioDecoderConfig& p, std::string* l) {
+ l->append(base::StringPrintf("<AudioDecoderConfig>"));
+}
+
+void ParamTraits<media::VideoDecoderConfig>::Write(
+ Message* m, const media::VideoDecoderConfig& p) {
+ ParamTraits<media::VideoCodec>::Write(m, p.codec());
+ ParamTraits<media::VideoCodecProfile>::Write(m, p.profile());
+ ParamTraits<media::VideoFrame::Format>::Write(m, p.format());
+ ParamTraits<gfx::Size>::Write(m, p.coded_size());
+ ParamTraits<gfx::Rect>::Write(m, p.visible_rect());
+ ParamTraits<gfx::Size>::Write(m, p.natural_size());
+ ParamTraits<bool>::Write(m, p.is_encrypted());
+ std::vector<uint8> extra_data;
+ if (p.extra_data_size() > 0) {
+ extra_data =
+ std::vector<uint8>(p.extra_data(),
+ p.extra_data() + p.extra_data_size());
+ }
+ ParamTraits<std::vector<uint8> >::Write(m, extra_data);
+}
+
+bool ParamTraits<media::VideoDecoderConfig>::Read(
+ const Message* m, PickleIterator* iter,
+ media::VideoDecoderConfig* r) {
+ media::VideoCodec codec;
+ media::VideoCodecProfile profile;
+ media::VideoFrame::Format format;
+ gfx::Size coded_size;
+ gfx::Rect visible_rect;
+ gfx::Size natural_size;
+ bool is_encrypted;
+ if (!ParamTraits<media::VideoCodec>::Read(m, iter, &codec) ||
+ !ParamTraits<media::VideoCodecProfile>::Read(m, iter, &profile) ||
+ !ParamTraits<media::VideoFrame::Format>::Read(m, iter, &format) ||
+ !ParamTraits<gfx::Size>::Read(m, iter, &coded_size) ||
+ !ParamTraits<gfx::Rect>::Read(m, iter, &visible_rect) ||
+ !ParamTraits<gfx::Size>::Read(m, iter, &natural_size) ||
+ !ParamTraits<bool>::Read(m, iter, &is_encrypted)) {
+ return false;
+ }
+ std::vector<uint8> extra_data;
+ if (!ParamTraits<std::vector<uint8> >::Read(m, iter, &extra_data))
+ return false;
+ const uint8* extra_data_ptr = NULL;
+ if (extra_data.size() > 0)
+ extra_data_ptr = &extra_data[0];
+ *r = media::VideoDecoderConfig(codec, profile, format,
+ coded_size, visible_rect, natural_size,
+ extra_data_ptr, extra_data.size(),
+ is_encrypted);
+ return true;
+}
+
+void ParamTraits<media::VideoDecoderConfig>::Log(
+ const media::VideoDecoderConfig& p, std::string* l) {
+ l->append(base::StringPrintf("<VideoDecoderConfig>"));
+}
+
+} // namespace IPC
diff --git a/chromium/chromecast/common/media/cma_param_traits.h b/chromium/chromecast/common/media/cma_param_traits.h
new file mode 100644
index 00000000000..0bebac35c2a
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_param_traits.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_H_
+#define CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_H_
+
+#include "ipc/ipc_message_utils.h"
+
+namespace media {
+class AudioDecoderConfig;
+class VideoDecoderConfig;
+}
+
+namespace IPC {
+
+template <>
+struct ParamTraits<media::AudioDecoderConfig> {
+ typedef media::AudioDecoderConfig param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<media::VideoDecoderConfig> {
+ typedef media::VideoDecoderConfig param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+} // namespace IPC
+
+#endif // CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_H_
diff --git a/chromium/chromecast/common/media/cma_param_traits_macros.h b/chromium/chromecast/common/media/cma_param_traits_macros.h
new file mode 100644
index 00000000000..72682000ef4
--- /dev/null
+++ b/chromium/chromecast/common/media/cma_param_traits_macros.h
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Singly or Multiply-included shared traits file depending on circumstances.
+// This allows the use of IPC serialization macros in more than one IPC message
+// file.
+#ifndef CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_MACROS_H_
+#define CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_MACROS_H_
+
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/param_traits_macros.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/buffering_state.h"
+#include "media/base/channel_layout.h"
+#include "media/base/pipeline_status.h"
+#include "media/base/sample_format.h"
+#include "media/base/video_decoder_config.h"
+#include "media/base/video_frame.h"
+
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(chromecast::media::LoadType,
+ chromecast::media::kLoadTypeURL,
+ chromecast::media::kLoadTypeMediaStream)
+
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(chromecast::media::TrackId,
+ chromecast::media::kNoTrackId,
+ chromecast::media::kVideoTrackId)
+
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::AudioCodec,
+ media::AudioCodec::kUnknownAudioCodec,
+ media::AudioCodec::kAudioCodecMax)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::BufferingState,
+ media::BUFFERING_HAVE_NOTHING,
+ media::BUFFERING_HAVE_ENOUGH)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::SampleFormat,
+ media::SampleFormat::kUnknownSampleFormat,
+ media::SampleFormat::kSampleFormatMax)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::PipelineStatus,
+ media::PIPELINE_OK,
+ media::PIPELINE_STATUS_MAX)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::VideoCodec,
+ media::VideoCodec::kUnknownVideoCodec,
+ media::VideoCodec::kVideoCodecMax)
+
+IPC_STRUCT_TRAITS_BEGIN(media::PipelineStatistics)
+ IPC_STRUCT_TRAITS_MEMBER(audio_bytes_decoded)
+ IPC_STRUCT_TRAITS_MEMBER(video_bytes_decoded)
+ IPC_STRUCT_TRAITS_MEMBER(video_frames_decoded)
+ IPC_STRUCT_TRAITS_MEMBER(video_frames_dropped)
+IPC_STRUCT_TRAITS_END()
+
+#endif // CHROMECAST_COMMON_MEDIA_CMA_PARAM_TRAITS_MACROS_H_ \ No newline at end of file
diff --git a/chromium/chromecast/common/media/shared_memory_chunk.cc b/chromium/chromecast/common/media/shared_memory_chunk.cc
new file mode 100644
index 00000000000..405339502c5
--- /dev/null
+++ b/chromium/chromecast/common/media/shared_memory_chunk.cc
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/common/media/shared_memory_chunk.h"
+
+#include "base/memory/shared_memory.h"
+
+namespace chromecast {
+namespace media {
+
+SharedMemoryChunk::SharedMemoryChunk(
+ scoped_ptr<base::SharedMemory> shared_mem,
+ size_t size)
+ : shared_mem_(shared_mem.Pass()),
+ size_(size) {
+}
+
+SharedMemoryChunk::~SharedMemoryChunk() {
+}
+
+void* SharedMemoryChunk::data() const {
+ return shared_mem_->memory();
+}
+
+size_t SharedMemoryChunk::size() const {
+ return size_;
+}
+
+bool SharedMemoryChunk::valid() const {
+ return true;
+}
+
+} // namespace media
+} // namespace chromecast
+
diff --git a/chromium/chromecast/common/media/shared_memory_chunk.h b/chromium/chromecast/common/media/shared_memory_chunk.h
new file mode 100644
index 00000000000..a8b71c2a12b
--- /dev/null
+++ b/chromium/chromecast/common/media/shared_memory_chunk.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_COMMON_MEDIA_SHARED_MEMORY_CHUNK_H_
+#define CHROMECAST_COMMON_MEDIA_SHARED_MEMORY_CHUNK_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromecast/media/cma/ipc/media_memory_chunk.h"
+
+namespace base {
+class SharedMemory;
+}
+
+namespace chromecast {
+namespace media {
+
+class SharedMemoryChunk : public MediaMemoryChunk {
+ public:
+ SharedMemoryChunk(scoped_ptr<base::SharedMemory> shared_mem,
+ size_t size);
+ ~SharedMemoryChunk() override;
+
+ // MediaMemoryChunk implementation.
+ void* data() const override;
+ size_t size() const override;
+ bool valid() const override;
+
+ private:
+ scoped_ptr<base::SharedMemory> shared_mem_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedMemoryChunk);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_COMMON_MEDIA_SHARED_MEMORY_CHUNK_H_ \ No newline at end of file
diff --git a/chromium/chromecast/common/pref_names.cc b/chromium/chromecast/common/pref_names.cc
index 45d0bc1780d..0b885f50080 100644
--- a/chromium/chromecast/common/pref_names.cc
+++ b/chromium/chromecast/common/pref_names.cc
@@ -6,6 +6,10 @@
namespace prefs {
+// Boolean that specifies whether or not the client_id has been regenerated
+// due to bug b/9487011.
+const char kMetricsIsNewClientID[] = "user_experience_metrics.is_new_client_id";
+
// Port on which to host the remote debugging server. A value of 0 indicates
// that remote debugging is disabled.
const char kRemoteDebuggingPort[] = "remote_debugging_port";
diff --git a/chromium/chromecast/common/pref_names.h b/chromium/chromecast/common/pref_names.h
index fe9f6ce1aec..6caa2cc6eea 100644
--- a/chromium/chromecast/common/pref_names.h
+++ b/chromium/chromecast/common/pref_names.h
@@ -7,6 +7,7 @@
namespace prefs {
+extern const char kMetricsIsNewClientID[];
extern const char kRemoteDebuggingPort[];
extern const char kStabilityChildProcessCrashCount[];
extern const char kStabilityKernelCrashCount[];
diff --git a/chromium/chromecast/common/version.h.in b/chromium/chromecast/common/version.h.in
index 628cb4c217f..918401f42ae 100644
--- a/chromium/chromecast/common/version.h.in
+++ b/chromium/chromecast/common/version.h.in
@@ -8,7 +8,9 @@
#define CHROMECAST_COMMON_VERSION_INFO_H_
#define PRODUCT_VERSION "@VERSION_FULL@"
-#define CAST_BUILD_REVISION "@CAST_BUILD_REVISION@"
-#define CAST_IS_DEBUG_BUILD @CAST_IS_DEBUG_BUILD@
+#define CAST_BUILD_INCREMENTAL "@CAST_BUILD_INCREMENTAL@"
+#define CAST_BUILD_REVISION "@CAST_BUILD_RELEASE@.@CAST_BUILD_INCREMENTAL@"
+#define CAST_IS_DEBUG_BUILD() @CAST_IS_DEBUG_BUILD@
+#define CAST_PRODUCT_TYPE @CAST_PRODUCT_TYPE@
#endif // CHROMECAST_COMMON_VERSION_INFO_H_
diff --git a/chromium/chromecast/crash/android/cast_crash_reporter_client_android.cc b/chromium/chromecast/crash/android/cast_crash_reporter_client_android.cc
index 2137faeea9b..ae4063745e5 100644
--- a/chromium/chromecast/crash/android/cast_crash_reporter_client_android.cc
+++ b/chromium/chromecast/crash/android/cast_crash_reporter_client_android.cc
@@ -11,6 +11,7 @@
#include "chromecast/android/chromecast_config_android.h"
#include "chromecast/common/global_descriptors.h"
#include "chromecast/common/version.h"
+#include "chromecast/crash/cast_crash_keys.h"
#include "content/public/common/content_switches.h"
namespace chromecast {
@@ -26,7 +27,7 @@ void CastCrashReporterClientAndroid::GetProductNameAndVersion(
const char** version) {
*product_name = "media_shell";
*version = PRODUCT_VERSION
-#if CAST_IS_DEBUG_BUILD
+#if CAST_IS_DEBUG_BUILD()
".debug"
#endif
"." CAST_BUILD_REVISION;
@@ -55,6 +56,10 @@ bool CastCrashReporterClientAndroid::GetCrashDumpLocation(
return true;
}
+size_t CastCrashReporterClientAndroid::RegisterCrashKeys() {
+ return crash_keys::RegisterCastCrashKeys();
+}
+
bool CastCrashReporterClientAndroid::GetCollectStatsConsent() {
return android::ChromecastConfigAndroid::GetInstance()->CanSendUsageStats();
}
diff --git a/chromium/chromecast/crash/android/cast_crash_reporter_client_android.h b/chromium/chromecast/crash/android/cast_crash_reporter_client_android.h
index 4524ae70a26..e98eef72605 100644
--- a/chromium/chromecast/crash/android/cast_crash_reporter_client_android.h
+++ b/chromium/chromecast/crash/android/cast_crash_reporter_client_android.h
@@ -14,17 +14,18 @@ class CastCrashReporterClientAndroid
: public crash_reporter::CrashReporterClient {
public:
CastCrashReporterClientAndroid();
- virtual ~CastCrashReporterClientAndroid();
+ ~CastCrashReporterClientAndroid() override;
// crash_reporter::CrashReporterClient implementation:
- virtual void GetProductNameAndVersion(const char** product_name,
- const char** version) override;
- virtual base::FilePath GetReporterLogFilename() override;
- virtual bool GetCrashDumpLocation(base::FilePath* crash_dir) override;
- virtual int GetAndroidMinidumpDescriptor() override;
- virtual bool GetCollectStatsConsent() override;
- virtual bool EnableBreakpadForProcess(
+ void GetProductNameAndVersion(const char** product_name,
+ const char** version) override;
+ base::FilePath GetReporterLogFilename() override;
+ bool GetCrashDumpLocation(base::FilePath* crash_dir) override;
+ int GetAndroidMinidumpDescriptor() override;
+ bool GetCollectStatsConsent() override;
+ bool EnableBreakpadForProcess(
const std::string& process_type) override;
+ size_t RegisterCrashKeys() override;
private:
DISALLOW_COPY_AND_ASSIGN(CastCrashReporterClientAndroid);
diff --git a/chromium/chromecast/crash/android/crash_handler.cc b/chromium/chromecast/crash/android/crash_handler.cc
index a73e31352b7..1c42dfa931a 100644
--- a/chromium/chromecast/crash/android/crash_handler.cc
+++ b/chromium/chromecast/crash/android/crash_handler.cc
@@ -5,12 +5,14 @@
#include "chromecast/crash/android/crash_handler.h"
#include <jni.h>
+#include <stdlib.h>
#include <string>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
#include "breakpad/src/client/linux/handler/exception_handler.h"
#include "breakpad/src/client/linux/handler/minidump_descriptor.h"
#include "chromecast/common/version.h"
@@ -24,22 +26,29 @@ namespace {
chromecast::CrashHandler* g_crash_handler = NULL;
-// ExceptionHandler requires a HandlerCallback as a function pointer. This
-// function exists to proxy into the global CrashHandler instance.
-bool HandleCrash(const void* /* crash_context */,
- size_t /* crash_context_size */,
- void* /* context */) {
+bool HandleCrash(void* /* crash_context */) {
DCHECK(g_crash_handler);
- if (g_crash_handler->CanUploadCrashDump()) {
- g_crash_handler->AttemptUploadCrashDump();
- } else {
- g_crash_handler->RemoveCrashDumps();
- }
+ g_crash_handler->UploadCrashDumps();
- // Let the exception continue to propagate up to the system.
+ // TODO(gunsch): clean up the ATV crash handling code.
+ // Don't write another minidump. Chrome's default ExceptionHandler has already
+ // written a minidump by this point in the crash handling sequence.
return false;
}
+// Debug builds: always to crash-staging
+// Release builds: only to crash-staging for local/invalid build numbers
+bool UploadCrashToStaging() {
+#if CAST_IS_DEBUG_BUILD()
+ return true;
+#else
+ int build_number;
+ if (base::StringToInt(CAST_BUILD_INCREMENTAL, &build_number))
+ return build_number == 0;
+ return true;
+#endif
+}
+
} // namespace
namespace chromecast {
@@ -79,67 +88,56 @@ CrashHandler::~CrashHandler() {
}
void CrashHandler::Initialize(const std::string& process_type) {
- if (process_type != switches::kZygoteProcess) {
- if (process_type.empty()) {
- // ExceptionHandlers are called on crash in reverse order of
- // instantiation. This ExceptionHandler will attempt to upload crashes
- // and the log file written out by the main process.
-
- // Dummy MinidumpDescriptor just to start up another ExceptionHandler.
- google_breakpad::MinidumpDescriptor dummy(crash_dump_path_.value());
- crash_uploader_.reset(new google_breakpad::ExceptionHandler(
- dummy, NULL, NULL, NULL, true, -1));
- crash_uploader_->set_crash_handler(&::HandleCrash);
-
- breakpad::InitCrashReporter(process_type);
- } else {
- breakpad::InitNonBrowserCrashReporterForAndroid(process_type);
- }
- }
+ if (process_type.empty()) {
+ InitializeUploader();
- UploadCrashDumpsAsync();
-}
+ // ExceptionHandlers are called on crash in reverse order of
+ // instantiation. This ExceptionHandler will attempt to upload crashes
+ // and the log file written out by the main process.
-bool CrashHandler::CanUploadCrashDump() {
- DCHECK(crash_reporter_client_);
- return crash_reporter_client_->GetCollectStatsConsent();
+ // Dummy MinidumpDescriptor just to start up another ExceptionHandler.
+ google_breakpad::MinidumpDescriptor dummy(crash_dump_path_.value());
+ crash_uploader_.reset(new google_breakpad::ExceptionHandler(
+ dummy, &HandleCrash, NULL, NULL, true, -1));
+
+ breakpad::InitCrashReporter(process_type);
+
+ return;
+ }
+
+ if (process_type != switches::kZygoteProcess) {
+ breakpad::InitNonBrowserCrashReporterForAndroid(process_type);
+ }
}
-void CrashHandler::AttemptUploadCrashDump() {
- VLOG(1) << "Attempting to upload current process crash";
+void CrashHandler::InitializeUploader() {
JNIEnv* env = base::android::AttachCurrentThread();
- // Crash dump location
base::android::ScopedJavaLocalRef<jstring> crash_dump_path_java =
base::android::ConvertUTF8ToJavaString(env,
crash_dump_path_.value());
- // Current log file location
- base::android::ScopedJavaLocalRef<jstring> log_file_path_java =
- base::android::ConvertUTF8ToJavaString(env, log_file_path_.value());
- Java_CastCrashHandler_uploadCurrentProcessDumpSync(
- env,
- crash_dump_path_java.obj(),
- log_file_path_java.obj(),
- CAST_IS_DEBUG_BUILD);
+ Java_CastCrashHandler_initializeUploader(
+ env, crash_dump_path_java.obj(), UploadCrashToStaging());
}
-void CrashHandler::UploadCrashDumpsAsync() {
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jstring> crash_dump_path_java =
- base::android::ConvertUTF8ToJavaString(env,
- crash_dump_path_.value());
- Java_CastCrashHandler_uploadCrashDumpsAsync(env,
- crash_dump_path_java.obj(),
- CAST_IS_DEBUG_BUILD);
+bool CrashHandler::CanUploadCrashDump() {
+ DCHECK(crash_reporter_client_);
+ return crash_reporter_client_->GetCollectStatsConsent();
}
-void CrashHandler::RemoveCrashDumps() {
- VLOG(1) << "Removing crash dumps instead of uploading";
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jstring> crash_dump_path_java =
- base::android::ConvertUTF8ToJavaString(env,
- crash_dump_path_.value());
- Java_CastCrashHandler_removeCrashDumpsSync(
- env, crash_dump_path_java.obj(), CAST_IS_DEBUG_BUILD);
+void CrashHandler::UploadCrashDumps() {
+ VLOG(1) << "Attempting to upload current process crash";
+
+ if (CanUploadCrashDump()) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ // Current log file location
+ base::android::ScopedJavaLocalRef<jstring> log_file_path_java =
+ base::android::ConvertUTF8ToJavaString(env, log_file_path_.value());
+ Java_CastCrashHandler_uploadCrashDumps(env, log_file_path_java.obj());
+ } else {
+ VLOG(1) << "Removing crash dumps instead of uploading";
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_CastCrashHandler_removeCrashDumps(env);
+ }
}
} // namespace chromecast
diff --git a/chromium/chromecast/crash/android/crash_handler.h b/chromium/chromecast/crash/android/crash_handler.h
index 246c5bb8c66..853e7f50973 100644
--- a/chromium/chromecast/crash/android/crash_handler.h
+++ b/chromium/chromecast/crash/android/crash_handler.h
@@ -36,14 +36,7 @@ class CrashHandler {
// Returns whether or not the user has allowed for uploading crash dumps.
bool CanUploadCrashDump();
- // Callback with which to create a breakpad::ExceptionHandler that will
- // attempt synchronously uploading crash dumps and logs at crash time.
- void AttemptUploadCrashDump();
-
- // Callback for breakpad::ExceptionHandler to delete crash dumps created by
- // the Chrome crash component. Chrome's crash component does not query
- // for user consent after initializing breakpad.
- void RemoveCrashDumps();
+ void UploadCrashDumps();
private:
CrashHandler(const base::FilePath& log_file_path);
@@ -51,9 +44,8 @@ class CrashHandler {
void Initialize(const std::string& process_type);
- // Starts a background thread to look for any past crash dumps and upload them
- // to the crash server.
- void UploadCrashDumpsAsync();
+ // Starts a thread to periodically check for uploads
+ void InitializeUploader();
// Path to the current process's log file.
base::FilePath log_file_path_;
diff --git a/chromium/chromecast/crash/cast_crash_keys.cc b/chromium/chromecast/crash/cast_crash_keys.cc
new file mode 100644
index 00000000000..a33a257b585
--- /dev/null
+++ b/chromium/chromecast/crash/cast_crash_keys.cc
@@ -0,0 +1,53 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/crash/cast_crash_keys.h"
+
+// TODO(kjoswiak): Potentially refactor chunk size info as well as non-cast
+// specific keys out and make shared with chrome/common/crash_keys.cc.
+namespace {
+
+// A small crash key, guaranteed to never be split into multiple pieces.
+const size_t kSmallSize = 63;
+
+// A medium crash key, which will be chunked on certain platforms but not
+// others. Guaranteed to never be more than four chunks.
+const size_t kMediumSize = kSmallSize * 4;
+
+// A large crash key, which will be chunked on all platforms. This should be
+// used sparingly.
+const size_t kLargeSize = kSmallSize * 16;
+
+// The maximum lengths specified by breakpad include the trailing NULL, so
+// the actual length of the string is one less.
+static const size_t kSingleChunkLength = 63;
+
+}
+
+namespace chromecast {
+namespace crash_keys {
+
+const char kLastApp[] = "last_app";
+const char kCurrentApp[] = "current_app";
+const char kPreviousApp[] = "previous_app";
+
+size_t RegisterCastCrashKeys() {
+ const base::debug::CrashKey fixed_keys[] = {
+ { kLastApp, kSmallSize },
+ { kCurrentApp, kSmallSize },
+ { kPreviousApp, kSmallSize },
+ // content/:
+ { "discardable-memory-allocated", kSmallSize },
+ { "discardable-memory-free", kSmallSize },
+ { "ppapi_path", kMediumSize },
+ { "subresource_url", kLargeSize },
+ { "total-discardable-memory-allocated", kSmallSize },
+ };
+
+ return base::debug::InitCrashKeys(fixed_keys, arraysize(fixed_keys),
+ kSingleChunkLength);
+}
+
+} // namespace chromecast
+} // namespace crash_keys
diff --git a/chromium/chromecast/crash/cast_crash_keys.h b/chromium/chromecast/crash/cast_crash_keys.h
new file mode 100644
index 00000000000..2f1af20ee8e
--- /dev/null
+++ b/chromium/chromecast/crash/cast_crash_keys.h
@@ -0,0 +1,22 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_CRASH_CAST_CRASH_KEYS_H_
+#define CHROMECAST_CRASH_CAST_CRASH_KEYS_H_
+
+#include "base/debug/crash_logging.h"
+
+namespace chromecast {
+namespace crash_keys {
+
+size_t RegisterCastCrashKeys();
+
+extern const char kCurrentApp[];
+extern const char kLastApp[];
+extern const char kPreviousApp[];
+
+} // namespace chromecast
+} // namespace crash_keys
+
+#endif // CHROMECAST_CRASH_CAST_CRASH_KEYS_H_
diff --git a/chromium/chromecast/crash/cast_crash_reporter_client.cc b/chromium/chromecast/crash/cast_crash_reporter_client.cc
new file mode 100644
index 00000000000..8edbfa6b7b2
--- /dev/null
+++ b/chromium/chromecast/crash/cast_crash_reporter_client.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/crash/cast_crash_reporter_client.h"
+
+#include "base/time/time.h"
+#include "components/crash/app/breakpad_linux.h"
+#include "content/public/common/content_switches.h"
+
+namespace chromecast {
+
+namespace {
+
+char* g_process_type = NULL;
+uint64_t g_process_start_time = 0;
+
+} // namespace
+
+// static
+void CastCrashReporterClient::InitCrashReporter(
+ const std::string& process_type) {
+ g_process_start_time = (base::TimeTicks::Now() -
+ base::TimeTicks()).InMilliseconds();
+
+ // Save the process type (leaked).
+ // Note: "browser" process is identified by empty process type string.
+ const std::string& named_process_type(
+ process_type.empty() ? "browser" : process_type);
+ const size_t process_type_len = named_process_type.size() + 1;
+ g_process_type = new char[process_type_len];
+ strncpy(g_process_type, named_process_type.c_str(), process_type_len);
+
+ // Start up breakpad for this process, if applicable.
+ breakpad::InitCrashReporter(process_type);
+}
+
+// static
+char* CastCrashReporterClient::GetProcessType() {
+ return g_process_type;
+}
+
+// static
+uint64_t CastCrashReporterClient::GetProcessStartTime() {
+ return g_process_start_time;
+}
+
+CastCrashReporterClient::CastCrashReporterClient() {}
+CastCrashReporterClient::~CastCrashReporterClient() {}
+
+bool CastCrashReporterClient::EnableBreakpadForProcess(
+ const std::string& process_type) {
+ return process_type == switches::kRendererProcess ||
+ process_type == switches::kZygoteProcess ||
+ process_type == switches::kGpuProcess;
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/crash/cast_crash_reporter_client.h b/chromium/chromecast/crash/cast_crash_reporter_client.h
new file mode 100644
index 00000000000..a0916a041ea
--- /dev/null
+++ b/chromium/chromecast/crash/cast_crash_reporter_client.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_CRASH_CAST_CRASH_REPORTER_CLIENT_H_
+#define CHROMECAST_CRASH_CAST_CRASH_REPORTER_CLIENT_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/crash/app/crash_reporter_client.h"
+
+namespace chromecast {
+
+class CastCrashReporterClient : public crash_reporter::CrashReporterClient {
+ public:
+ static void InitCrashReporter(const std::string& process_type);
+
+ CastCrashReporterClient();
+ ~CastCrashReporterClient() override;
+
+ // crash_reporter::CrashReporterClient implementation:
+ bool EnableBreakpadForProcess(
+ const std::string& process_type) override;
+ bool HandleCrashDump(const char* crashdump_filename) override;
+
+ private:
+ static char* GetProcessType();
+ static uint64_t GetProcessStartTime();
+
+ DISALLOW_COPY_AND_ASSIGN(CastCrashReporterClient);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_CRASH_CAST_CRASH_REPORTER_CLIENT_H_
diff --git a/chromium/chromecast/crash/cast_crash_reporter_client_simple.cc b/chromium/chromecast/crash/cast_crash_reporter_client_simple.cc
new file mode 100644
index 00000000000..aef4add13c0
--- /dev/null
+++ b/chromium/chromecast/crash/cast_crash_reporter_client_simple.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/crash/cast_crash_reporter_client.h"
+
+#include "base/logging.h"
+
+namespace chromecast {
+
+bool CastCrashReporterClient::HandleCrashDump(const char* crashdump_filename) {
+ LOG(INFO) << "Process " << GetProcessType() << " crashed; minidump in "
+ << crashdump_filename;
+ return true;
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/graphics/DEPS b/chromium/chromecast/graphics/DEPS
new file mode 100644
index 00000000000..ada2e660c17
--- /dev/null
+++ b/chromium/chromecast/graphics/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+chromecast/public",
+]
diff --git a/chromium/chromecast/graphics/cast_egl_platform_default.cc b/chromium/chromecast/graphics/cast_egl_platform_default.cc
new file mode 100644
index 00000000000..3cb9a1b8c32
--- /dev/null
+++ b/chromium/chromecast/graphics/cast_egl_platform_default.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "chromecast/public/cast_egl_platform.h"
+#include "chromecast/public/cast_egl_platform_shlib.h"
+
+namespace chromecast {
+namespace {
+
+// Default/stub CastEglPlatform implementation so that we can link
+// successfully.
+class EglPlatformDefault : public CastEglPlatform {
+ public:
+ ~EglPlatformDefault() override {}
+ const int* GetEGLSurfaceProperties(const int* desired) override {
+ return desired;
+ }
+ bool InitializeHardware() override { return true; }
+ void ShutdownHardware() override {}
+ void* GetEglLibrary() override { return nullptr; }
+ void* GetGles2Library() override { return nullptr; }
+ GLGetProcAddressProc GetGLProcAddressProc() override { return nullptr; }
+ NativeDisplayType CreateDisplayType(const Size& size) override {
+ return nullptr;
+ }
+ void DestroyDisplayType(NativeDisplayType display_type) override {}
+ NativeWindowType CreateWindow(NativeDisplayType display_type,
+ const Size& size) override {
+ return nullptr;
+ }
+ void DestroyWindow(NativeWindowType window) override {}
+};
+
+} // namespace
+
+CastEglPlatform* CastEglPlatformShlib::Create(
+ const std::vector<std::string>& argv) {
+ return new EglPlatformDefault();
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/graphics/graphics_properties_default.cc b/chromium/chromecast/graphics/graphics_properties_default.cc
new file mode 100644
index 00000000000..200c6cc4b3a
--- /dev/null
+++ b/chromium/chromecast/graphics/graphics_properties_default.cc
@@ -0,0 +1,15 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/public/graphics_properties_shlib.h"
+
+namespace chromecast {
+
+bool GraphicsPropertiesShlib::IsSupported(
+ Resolution resolution,
+ const std::vector<std::string>& argv) {
+ return true;
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/graphics/osd_plane_default.cc b/chromium/chromecast/graphics/osd_plane_default.cc
new file mode 100644
index 00000000000..2c73edc531a
--- /dev/null
+++ b/chromium/chromecast/graphics/osd_plane_default.cc
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "chromecast/public/graphics_types.h"
+#include "chromecast/public/osd_plane.h"
+#include "chromecast/public/osd_plane_shlib.h"
+#include "chromecast/public/osd_surface.h"
+
+namespace chromecast {
+namespace {
+
+// Default no-op OsdSurface implementation
+class OsdSurfaceDefault : public OsdSurface {
+ public:
+ OsdSurfaceDefault(const Size& size) : size_(size) {}
+
+ // OsdSurface implementation:
+ void Blit(OsdSurface* src_surface,
+ const Rect& src_rect,
+ const Point& dst_point) override {}
+ void Composite(OsdSurface* src_surface,
+ const Rect& src_rect,
+ const Point& dst_point) override {}
+ void CopyBitmap(char* src_bitmap,
+ const Rect& src_rect,
+ const Rect& damage_rect,
+ const Point& dst_point) override {}
+ void Fill(const Rect& rect, int argb) override {}
+
+ const Size& size() const override { return size_; }
+
+ private:
+ const Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(OsdSurfaceDefault);
+};
+
+// Default no-op OsdPlane implementation
+class OsdPlaneDefault : public OsdPlane {
+ public:
+ OsdPlaneDefault() : size_(0, 0) {}
+
+ // OsdPlane implementation:
+ OsdSurface* CreateSurface(const Size& size) override {
+ return new OsdSurfaceDefault(size);
+ }
+ void SetClipRectangle(const Rect& rect) override {
+ size_ = Size(rect.width, rect.height);
+ }
+ OsdSurface* GetBackBuffer() override {
+ if (!back_buffer_)
+ back_buffer_.reset(new OsdSurfaceDefault(size_));
+ return back_buffer_.get();
+ }
+
+ void Flip() override {}
+
+ private:
+ scoped_ptr<OsdSurface> back_buffer_;
+ Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(OsdPlaneDefault);
+};
+
+} // namespace
+
+OsdPlane* OsdPlaneShlib::Create(const std::vector<std::string>& argv) {
+ return new OsdPlaneDefault;
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/media/BUILD.gn b/chromium/chromecast/media/BUILD.gn
new file mode 100644
index 00000000000..6a8c6a6a3df
--- /dev/null
+++ b/chromium/chromecast/media/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//testing/test.gni")
+
+group("media") {
+ deps = [
+ "//chromecast/media/base",
+ "//chromecast/media/cdm",
+ "//chromecast/media/cma",
+ ]
+}
+
+test("unittests") {
+ sources = [
+ "//media/base",
+ "cma/backend/audio_video_pipeline_device_unittest.cc",
+ "cma/base/balanced_media_task_runner_unittest.cc",
+ "cma/base/buffering_controller_unittest.cc",
+ "cma/base/buffering_frame_provider_unittest.cc",
+ "cma/filters/demuxer_stream_adapter_unittest.cc",
+ "cma/ipc/media_message_fifo_unittest.cc",
+ "cma/ipc/media_message_unittest.cc",
+ "cma/ipc_streamer/av_streamer_unittest.cc",
+ "cma/pipeline/audio_video_pipeline_impl_unittest.cc",
+ "cma/test/frame_generator_for_test.cc",
+ "cma/test/frame_generator_for_test.h",
+ "cma/test/frame_segmenter_for_test.cc",
+ "cma/test/frame_segmenter_for_test.h",
+ "cma/test/media_component_device_feeder_for_test.cc",
+ "cma/test/media_component_device_feeder_for_test.h",
+ "cma/test/mock_frame_consumer.cc",
+ "cma/test/mock_frame_consumer.h",
+ "cma/test/mock_frame_provider.cc",
+ "cma/test/mock_frame_provider.h",
+ "cma/test/run_all_unittests.cc",
+ ]
+
+ deps = [
+ ":media",
+ "//base",
+ "//base:i18n",
+ "//base/test:test_support",
+ "//chromecast/base/metrics:test_support",
+ "//media",
+ "//media/base:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/DEPS b/chromium/chromecast/media/DEPS
index 1891d1afe50..f2506bb5ad6 100644
--- a/chromium/chromecast/media/DEPS
+++ b/chromium/chromecast/media/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+media/base",
"+media/cdm",
+ "+media/renderers",
]
diff --git a/chromium/chromecast/media/base/BUILD.gn b/chromium/chromecast/media/base/BUILD.gn
new file mode 100644
index 00000000000..64992f331f2
--- /dev/null
+++ b/chromium/chromecast/media/base/BUILD.gn
@@ -0,0 +1,38 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/crypto.gni")
+import("//chromecast/chromecast.gni")
+
+source_set("base") {
+ sources = [
+ "decrypt_context.cc",
+ "decrypt_context.h",
+ "decrypt_context_clearkey.cc",
+ "decrypt_context_clearkey.h",
+ "key_systems_common.cc",
+ "key_systems_common.h",
+ "media_caps.cc",
+ "media_caps.h",
+ "switching_media_renderer.cc",
+ "switching_media_renderer.h",
+ ]
+
+ deps = [
+ "//base",
+ "//crypto",
+ "//crypto:platform",
+ "//third_party/widevine/cdm:version_h",
+ ]
+
+ configs += [ "//chromecast:config" ]
+
+ if (is_chromecast_chrome_branded) {
+ deps += [
+ # TODO(gyp): add dependency on internal/chromecast_internal:media_base_internal
+ ]
+ } else {
+ sources += [ "key_systems_common_simple.cc" ]
+ }
+}
diff --git a/chromium/chromecast/media/base/cast_media_default.cc b/chromium/chromecast/media/base/cast_media_default.cc
new file mode 100644
index 00000000000..0cc03d38705
--- /dev/null
+++ b/chromium/chromecast/media/base/cast_media_default.cc
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/public/cast_media_shlib.h"
+
+namespace chromecast {
+namespace media {
+
+void CastMediaShlib::Initialize(const std::vector<std::string>& argv) {
+}
+
+void CastMediaShlib::Finalize() {
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/base/decrypt_context_clearkey.h b/chromium/chromecast/media/base/decrypt_context_clearkey.h
index 770cea08144..a4e56d0ba25 100644
--- a/chromium/chromecast/media/base/decrypt_context_clearkey.h
+++ b/chromium/chromecast/media/base/decrypt_context_clearkey.h
@@ -17,10 +17,10 @@ class DecryptContextClearKey : public DecryptContext {
explicit DecryptContextClearKey(crypto::SymmetricKey* key);
// DecryptContext implementation.
- virtual crypto::SymmetricKey* GetKey() const override;
+ crypto::SymmetricKey* GetKey() const override;
private:
- virtual ~DecryptContextClearKey();
+ ~DecryptContextClearKey() override;
crypto::SymmetricKey* const key_;
@@ -30,4 +30,4 @@ class DecryptContextClearKey : public DecryptContext {
} // namespace media
} // namespace chromecast
-#endif // CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_CLEARKEY_H_ \ No newline at end of file
+#endif // CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_CLEARKEY_H_
diff --git a/chromium/chromecast/media/base/key_systems_common.h b/chromium/chromecast/media/base/key_systems_common.h
index 4ab8ea75dec..1537afd36ab 100644
--- a/chromium/chromecast/media/base/key_systems_common.h
+++ b/chromium/chromecast/media/base/key_systems_common.h
@@ -6,6 +6,11 @@
#define CHROMECAST_MEDIA_BASE_KEY_SYSTEMS_COMMON_H_
#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "media/base/android/media_client_android.h"
namespace chromecast {
namespace media {
@@ -29,6 +34,13 @@ CastKeySystem GetKeySystemByName(const std::string& key_system_name);
// TODO(gunsch): Remove when prefixed EME is removed.
CastKeySystem GetPlatformKeySystemByName(const std::string& key_system_name);
+// Translates a platform-specific key system string into a CastKeySystem.
+// TODO(gunsch): Remove when prefixed EME is removed.
+#if defined(OS_ANDROID)
+std::vector<::media::MediaClientAndroid::KeySystemUuidMap::value_type>
+GetPlatformKeySystemUUIDMappings();
+#endif
+
} // namespace media
} // namespace chromecast
diff --git a/chromium/chromecast/media/base/key_systems_common_simple.cc b/chromium/chromecast/media/base/key_systems_common_simple.cc
index e6dbd028902..671ce037730 100644
--- a/chromium/chromecast/media/base/key_systems_common_simple.cc
+++ b/chromium/chromecast/media/base/key_systems_common_simple.cc
@@ -11,5 +11,13 @@ CastKeySystem GetPlatformKeySystemByName(const std::string& key_system_name) {
return KEY_SYSTEM_NONE;
}
+#if defined(OS_ANDROID)
+std::vector<::media::MediaClientAndroid::KeySystemUuidMap::value_type>
+GetPlatformKeySystemUUIDMappings() {
+ return std::vector<
+ ::media::MediaClientAndroid::KeySystemUuidMap::value_type>();
+}
+#endif
+
} // namespace media
} // namespace chromecast
diff --git a/chromium/chromecast/media/base/media_caps.cc b/chromium/chromecast/media/base/media_caps.cc
new file mode 100644
index 00000000000..29248828a03
--- /dev/null
+++ b/chromium/chromecast/media/base/media_caps.cc
@@ -0,0 +1,38 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/base/media_caps.h"
+
+namespace media {
+
+namespace {
+int g_hdmi_codecs = 0;
+} // namespace
+
+void SetHdmiSinkCodecs(int codecs_mask) {
+ g_hdmi_codecs = codecs_mask;
+}
+
+bool HdmiSinkSupportsAC3() {
+ return g_hdmi_codecs & HdmiSinkCodec::kSinkCodecAc3;
+}
+
+bool HdmiSinkSupportsDTS() {
+ return g_hdmi_codecs & HdmiSinkCodec::kSinkCodecDts;
+}
+
+bool HdmiSinkSupportsDTSHD() {
+ return g_hdmi_codecs & HdmiSinkCodec::kSinkCodecDtsHd;
+}
+
+bool HdmiSinkSupportsEAC3() {
+ return g_hdmi_codecs & HdmiSinkCodec::kSinkCodecEac3;
+}
+
+bool HdmiSinkSupportsPcmSurroundSound() {
+ return g_hdmi_codecs & HdmiSinkCodec::kSinkCodecPcmSurroundSound;
+}
+
+} // namespace media
+
diff --git a/chromium/chromecast/media/base/media_caps.h b/chromium/chromecast/media/base/media_caps.h
new file mode 100644
index 00000000000..8ae2c7bcec0
--- /dev/null
+++ b/chromium/chromecast/media/base/media_caps.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_BASE_MEDIA_CAPS_
+#define CHROMECAST_MEDIA_BASE_MEDIA_CAPS_
+
+namespace media {
+
+enum HdmiSinkCodec {
+ kSinkCodecAc3 = 1,
+ kSinkCodecDts = 1 << 1,
+ kSinkCodecDtsHd = 1 << 2,
+ kSinkCodecEac3 = 1 << 3,
+ kSinkCodecPcmSurroundSound = 1 << 4,
+};
+
+// Records the known supported codecs for the current HDMI sink, as a bit mask
+// of HdmiSinkCodec values.
+void SetHdmiSinkCodecs(int codecs_mask);
+
+bool HdmiSinkSupportsAC3();
+bool HdmiSinkSupportsDTS();
+bool HdmiSinkSupportsDTSHD();
+bool HdmiSinkSupportsEAC3();
+bool HdmiSinkSupportsPcmSurroundSound();
+
+} // namespace media
+
+#endif // CHROMECAST_MEDIA_BASE_MEDIA_CAPS_
diff --git a/chromium/chromecast/media/base/media_codec_support.cc b/chromium/chromecast/media/base/media_codec_support.cc
new file mode 100644
index 00000000000..b04a077961e
--- /dev/null
+++ b/chromium/chromecast/media/base/media_codec_support.cc
@@ -0,0 +1,16 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/base/media_codec_support.h"
+
+// TODO(gunsch/servolk): delete this file once a solution exists upstream.
+
+namespace net {
+
+bool DefaultIsCodecSupported(const std::string&) {
+ return true;
+}
+
+} // namespace net
+
diff --git a/chromium/chromecast/media/base/media_codec_support.h b/chromium/chromecast/media/base/media_codec_support.h
new file mode 100644
index 00000000000..e961177ecb0
--- /dev/null
+++ b/chromium/chromecast/media/base/media_codec_support.h
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_BASE_MEDIA_CODEC_SUPPORT_H_
+#define CHROMECAST_MEDIA_BASE_MEDIA_CODEC_SUPPORT_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "net/base/mime_util.h"
+
+// TODO(gunsch/servolk): remove when this definition exists upstream.
+
+namespace net {
+typedef base::Callback<bool(const std::string&)> IsCodecSupportedCB;
+bool DefaultIsCodecSupported(const std::string&);
+}
+
+namespace chromecast {
+namespace media {
+
+// This function should return a callback capable of deciding whether a given
+// codec (passed in as a string representation of the codec id conforming to
+// RFC 6381) is supported or not. The implementation of this function is
+// expected to be provided somewhere in the vendor platform-specific libraries
+// that will get linked with cast_shell_common target.
+net::IsCodecSupportedCB GetIsCodecSupportedOnChromecastCB();
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_BASE_MEDIA_CODEC_SUPPORT_H_
+
diff --git a/chromium/chromecast/media/base/media_codec_support_simple.cc b/chromium/chromecast/media/base/media_codec_support_simple.cc
new file mode 100644
index 00000000000..24e83be69dc
--- /dev/null
+++ b/chromium/chromecast/media/base/media_codec_support_simple.cc
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/base/media_codec_support.h"
+
+#include "base/bind.h"
+
+namespace chromecast {
+namespace media {
+
+// This is a default implementation of GetIsCodecSupportedOnChromecastCB that is
+// going to be used for brandings other than 'Chrome'. Most platforms will want
+// to use their own custom implementations of the IsCodecSupportedCB callback.
+net::IsCodecSupportedCB GetIsCodecSupportedOnChromecastCB() {
+ return base::Bind(&net::DefaultIsCodecSupported);
+}
+
+} // namespace media
+} // namespace chromecast
+
diff --git a/chromium/chromecast/media/base/switching_media_renderer.cc b/chromium/chromecast/media/base/switching_media_renderer.cc
new file mode 100644
index 00000000000..b0a12c3a040
--- /dev/null
+++ b/chromium/chromecast/media/base/switching_media_renderer.cc
@@ -0,0 +1,102 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/base/switching_media_renderer.h"
+
+#include "base/logging.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/demuxer_stream.h"
+#include "media/base/demuxer_stream_provider.h"
+
+namespace chromecast {
+namespace media {
+
+SwitchingMediaRenderer::SwitchingMediaRenderer(
+ scoped_ptr<::media::Renderer> default_renderer,
+ scoped_ptr<::media::Renderer> cma_renderer)
+ : default_renderer_(default_renderer.Pass()),
+ cma_renderer_(cma_renderer.Pass()) {
+ DCHECK(default_renderer_);
+ DCHECK(cma_renderer_);
+}
+
+SwitchingMediaRenderer::~SwitchingMediaRenderer() {
+}
+
+void SwitchingMediaRenderer::Initialize(
+ ::media::DemuxerStreamProvider* demuxer_stream_provider,
+ const ::media::PipelineStatusCB& init_cb,
+ const ::media::StatisticsCB& statistics_cb,
+ const ::media::BufferingStateCB& buffering_state_cb,
+ const base::Closure& ended_cb,
+ const ::media::PipelineStatusCB& error_cb,
+ const base::Closure& waiting_for_decryption_key_cb) {
+ // At this point the DemuxerStreamProvider should be fully initialized, so we
+ // have enough information to decide which renderer to use.
+ demuxer_stream_provider_ = demuxer_stream_provider;
+ DCHECK(demuxer_stream_provider_);
+ ::media::DemuxerStream* audio_stream =
+ demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO);
+ ::media::DemuxerStream* video_stream =
+ demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO);
+ if (audio_stream && !video_stream &&
+ (audio_stream->audio_decoder_config().codec() == ::media::kCodecFLAC ||
+ audio_stream->audio_decoder_config().codec() == ::media::kCodecOpus)) {
+ // We'll use the default Chrome media renderer with software audio decoding
+ cma_renderer_.reset();
+ } else {
+ // We'll use the CMA-based rendering with hardware decoding
+ default_renderer_.reset();
+ }
+
+ return GetRenderer()->Initialize(
+ demuxer_stream_provider, init_cb, statistics_cb, buffering_state_cb,
+ ended_cb, error_cb, waiting_for_decryption_key_cb);
+}
+
+::media::Renderer* SwitchingMediaRenderer::GetRenderer() const {
+ DCHECK(default_renderer_ || cma_renderer_);
+ if (cma_renderer_)
+ return cma_renderer_.get();
+
+ DCHECK(default_renderer_);
+ return default_renderer_.get();
+}
+
+void SwitchingMediaRenderer::SetCdm(
+ ::media::CdmContext* cdm_context,
+ const ::media::CdmAttachedCB& cdm_attached_cb) {
+ GetRenderer()->SetCdm(cdm_context, cdm_attached_cb);
+}
+
+void SwitchingMediaRenderer::Flush(const base::Closure& flush_cb) {
+ GetRenderer()->Flush(flush_cb);
+}
+
+void SwitchingMediaRenderer::StartPlayingFrom(base::TimeDelta time) {
+ GetRenderer()->StartPlayingFrom(time);
+}
+
+void SwitchingMediaRenderer::SetPlaybackRate(double playback_rate) {
+ GetRenderer()->SetPlaybackRate(playback_rate);
+}
+
+void SwitchingMediaRenderer::SetVolume(float volume) {
+ GetRenderer()->SetVolume(volume);
+}
+
+base::TimeDelta SwitchingMediaRenderer::GetMediaTime() {
+ return GetRenderer()->GetMediaTime();
+}
+
+bool SwitchingMediaRenderer::HasAudio() {
+ return GetRenderer()->HasAudio();
+}
+
+bool SwitchingMediaRenderer::HasVideo() {
+ return GetRenderer()->HasVideo();
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/base/switching_media_renderer.h b/chromium/chromecast/media/base/switching_media_renderer.h
new file mode 100644
index 00000000000..c32b1d438d5
--- /dev/null
+++ b/chromium/chromecast/media/base/switching_media_renderer.h
@@ -0,0 +1,66 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_BASE_SWITCHING_MEDIA_RENDERER_H_
+#define CHROMECAST_MEDIA_BASE_SWITCHING_MEDIA_RENDERER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "media/base/renderer.h"
+
+namespace media {
+class DemuxerStreamProvider;
+}
+
+namespace chromecast {
+namespace media {
+
+// Chromecast's custom media renderer which is capable of selecting an
+// appropriate media renderer at runtime depending on the content.
+// We'll look at media types of media streams present in DemuxerStreamProvider
+// and will use either CMA-based renderer (for media types that are supported by
+// our hardware decoder - H264 and VP8 video, AAC and Vorbis audio) or the
+// default Chrome media renderer (this will allow us to support audio codecs
+// like FLAC and Opus, which are decoded in software).
+class SwitchingMediaRenderer : public ::media::Renderer {
+ public:
+ SwitchingMediaRenderer(
+ scoped_ptr<::media::Renderer> default_renderer,
+ scoped_ptr<::media::Renderer> cma_renderer);
+ ~SwitchingMediaRenderer() override;
+
+ // ::media::Renderer implementation:
+ void Initialize(
+ ::media::DemuxerStreamProvider* demuxer_stream_provider,
+ const ::media::PipelineStatusCB& init_cb,
+ const ::media::StatisticsCB& statistics_cb,
+ const ::media::BufferingStateCB& buffering_state_cb,
+ const base::Closure& ended_cb,
+ const ::media::PipelineStatusCB& error_cb,
+ const base::Closure& waiting_for_decryption_key_cb) override;
+ void SetCdm(::media::CdmContext* cdm_context,
+ const ::media::CdmAttachedCB& cdm_attached_cb) override;
+ void Flush(const base::Closure& flush_cb) override;
+ void StartPlayingFrom(base::TimeDelta time) override;
+ void SetPlaybackRate(double playback_rate) override;
+ void SetVolume(float volume) override;
+ base::TimeDelta GetMediaTime() override;
+ bool HasAudio() override;
+ bool HasVideo() override;
+
+ private:
+ // Returns the pointer to the actual renderer being used
+ ::media::Renderer* GetRenderer() const;
+
+ ::media::DemuxerStreamProvider* demuxer_stream_provider_;
+ scoped_ptr<::media::Renderer> default_renderer_;
+ scoped_ptr<::media::Renderer> cma_renderer_;
+
+ DISALLOW_COPY_AND_ASSIGN(SwitchingMediaRenderer);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_BASE_SWITCHING_MEDIA_RENDERER_H_
diff --git a/chromium/chromecast/media/cdm/BUILD.gn b/chromium/chromecast/media/cdm/BUILD.gn
new file mode 100644
index 00000000000..1a929d07b33
--- /dev/null
+++ b/chromium/chromecast/media/cdm/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("cdm") {
+ sources = [
+ "browser_cdm_cast.cc",
+ "browser_cdm_cast.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chromecast/media/base",
+ "//media",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/cdm/browser_cdm_cast.cc b/chromium/chromecast/media/cdm/browser_cdm_cast.cc
new file mode 100644
index 00000000000..b62df02cb8b
--- /dev/null
+++ b/chromium/chromecast/media/cdm/browser_cdm_cast.cc
@@ -0,0 +1,209 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cdm/browser_cdm_cast.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "media/base/cdm_key_information.h"
+#include "media/base/cdm_promise.h"
+#include "media/cdm/player_tracker_impl.h"
+
+namespace chromecast {
+namespace media {
+
+BrowserCdmCast::BrowserCdmCast() {
+ thread_checker_.DetachFromThread();
+}
+
+BrowserCdmCast::~BrowserCdmCast() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(player_tracker_impl_.get());
+ player_tracker_impl_->NotifyCdmUnset();
+}
+
+void BrowserCdmCast::Initialize(
+ const ::media::SessionMessageCB& session_message_cb,
+ const ::media::SessionClosedCB& session_closed_cb,
+ const ::media::LegacySessionErrorCB& legacy_session_error_cb,
+ const ::media::SessionKeysChangeCB& session_keys_change_cb,
+ const ::media::SessionExpirationUpdateCB& session_expiration_update_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ player_tracker_impl_.reset(new ::media::PlayerTrackerImpl);
+
+ session_message_cb_ = session_message_cb;
+ session_closed_cb_ = session_closed_cb;
+ legacy_session_error_cb_ = legacy_session_error_cb;
+ session_keys_change_cb_ = session_keys_change_cb;
+ session_expiration_update_cb_ = session_expiration_update_cb;
+
+ InitializeInternal();
+}
+
+int BrowserCdmCast::RegisterPlayer(const base::Closure& new_key_cb,
+ const base::Closure& cdm_unset_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return player_tracker_impl_->RegisterPlayer(new_key_cb, cdm_unset_cb);
+}
+
+void BrowserCdmCast::UnregisterPlayer(int registration_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ player_tracker_impl_->UnregisterPlayer(registration_id);
+}
+
+void BrowserCdmCast::LoadSession(
+ ::media::MediaKeys::SessionType session_type,
+ const std::string& session_id,
+ scoped_ptr<::media::NewSessionCdmPromise> promise) {
+ NOTREACHED() << "LoadSession not supported";
+ legacy_session_error_cb_.Run(
+ session_id, ::media::MediaKeys::Exception::NOT_SUPPORTED_ERROR, 0,
+ std::string());
+}
+
+::media::CdmContext* BrowserCdmCast::GetCdmContext() {
+ NOTREACHED();
+ return nullptr;
+}
+
+void BrowserCdmCast::OnSessionMessage(const std::string& session_id,
+ const std::vector<uint8_t>& message,
+ const GURL& destination_url) {
+ // Note: Message type is not supported in Chromecast. Do our best guess here.
+ ::media::MediaKeys::MessageType message_type =
+ destination_url.is_empty() ? ::media::MediaKeys::LICENSE_REQUEST
+ : ::media::MediaKeys::LICENSE_RENEWAL;
+ session_message_cb_.Run(session_id,
+ message_type,
+ message,
+ destination_url);
+}
+
+void BrowserCdmCast::OnSessionClosed(const std::string& session_id) {
+ session_closed_cb_.Run(session_id);
+}
+
+void BrowserCdmCast::OnSessionKeysChange(
+ const std::string& session_id,
+ const ::media::KeyIdAndKeyPairs& keys) {
+ ::media::CdmKeysInfo cdm_keys_info;
+ for (const std::pair<std::string, std::string>& key : keys) {
+ scoped_ptr< ::media::CdmKeyInformation> cdm_key_information(
+ new ::media::CdmKeyInformation());
+ cdm_key_information->key_id.assign(key.first.begin(), key.first.end());
+ cdm_keys_info.push_back(cdm_key_information.release());
+ }
+ session_keys_change_cb_.Run(session_id, true, cdm_keys_info.Pass());
+
+ player_tracker_impl_->NotifyNewKey();
+}
+
+// A macro runs current member function on |cdm_loop_| thread.
+#define FORWARD_ON_CDM_THREAD(param_fn, ...) \
+ cdm_loop_->PostTask( \
+ FROM_HERE, \
+ base::Bind(&BrowserCdmCast::param_fn, \
+ base::Unretained(browser_cdm_cast_.get()), ##__VA_ARGS__))
+
+
+BrowserCdmCastUi::BrowserCdmCastUi(
+ scoped_ptr<BrowserCdmCast> browser_cdm_cast,
+ const scoped_refptr<base::MessageLoopProxy>& cdm_loop)
+ : browser_cdm_cast_(browser_cdm_cast.Pass()),
+ cdm_loop_(cdm_loop) {
+}
+
+BrowserCdmCastUi::~BrowserCdmCastUi() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ cdm_loop_->DeleteSoon(FROM_HERE, browser_cdm_cast_.release());
+}
+
+int BrowserCdmCastUi::RegisterPlayer(const base::Closure& new_key_cb,
+ const base::Closure& cdm_unset_cb) {
+ NOTREACHED() << "RegisterPlayer should be called on BrowserCdmCast";
+ return -1;
+}
+
+void BrowserCdmCastUi::UnregisterPlayer(int registration_id) {
+ NOTREACHED() << "UnregisterPlayer should be called on BrowserCdmCast";
+}
+
+BrowserCdmCast* BrowserCdmCastUi::browser_cdm_cast() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return browser_cdm_cast_.get();
+}
+
+void BrowserCdmCastUi::SetServerCertificate(
+ const std::vector<uint8_t>& certificate,
+ scoped_ptr<::media::SimpleCdmPromise> promise) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_CDM_THREAD(
+ SetServerCertificate,
+ certificate,
+ base::Passed(&promise));
+}
+
+void BrowserCdmCastUi::CreateSessionAndGenerateRequest(
+ ::media::MediaKeys::SessionType session_type,
+ ::media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ scoped_ptr<::media::NewSessionCdmPromise> promise) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_CDM_THREAD(
+ CreateSessionAndGenerateRequest,
+ session_type,
+ init_data_type,
+ init_data,
+ base::Passed(&promise));
+}
+
+void BrowserCdmCastUi::LoadSession(
+ ::media::MediaKeys::SessionType session_type,
+ const std::string& session_id,
+ scoped_ptr<::media::NewSessionCdmPromise> promise) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_CDM_THREAD(
+ LoadSession, session_type, session_id, base::Passed(&promise));
+}
+
+void BrowserCdmCastUi::UpdateSession(
+ const std::string& session_id,
+ const std::vector<uint8_t>& response,
+ scoped_ptr<::media::SimpleCdmPromise> promise) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_CDM_THREAD(
+ UpdateSession,
+ session_id,
+ response,
+ base::Passed(&promise));
+}
+
+void BrowserCdmCastUi::CloseSession(
+ const std::string& session_id,
+ scoped_ptr<::media::SimpleCdmPromise> promise) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_CDM_THREAD(CloseSession, session_id, base::Passed(&promise));
+}
+
+void BrowserCdmCastUi::RemoveSession(
+ const std::string& session_id,
+ scoped_ptr<::media::SimpleCdmPromise> promise) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_CDM_THREAD(RemoveSession, session_id, base::Passed(&promise));
+}
+
+::media::CdmContext* BrowserCdmCastUi::GetCdmContext() {
+ NOTREACHED();
+ return nullptr;
+}
+
+// A default empty implementation for subclasses that don't need to provide
+// any key system specific initialization.
+void BrowserCdmCast::InitializeInternal() {
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cdm/browser_cdm_cast.h b/chromium/chromecast/media/cdm/browser_cdm_cast.h
new file mode 100644
index 00000000000..7a83a08dcc8
--- /dev/null
+++ b/chromium/chromecast/media/cdm/browser_cdm_cast.h
@@ -0,0 +1,147 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CDM_BROWSER_CDM_CAST_H_
+#define CHROMECAST_MEDIA_CDM_BROWSER_CDM_CAST_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "media/base/browser_cdm.h"
+#include "media/cdm/json_web_key.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace media {
+class PlayerTrackerImpl;
+}
+
+namespace chromecast {
+namespace media {
+class DecryptContext;
+
+// BrowserCdmCast is an extension of BrowserCdm that provides common
+// functionality across CDM implementations.
+// All these additional functions are synchronous so:
+// - either both the CDM and the media pipeline must be running on the same
+// thread,
+// - or BrowserCdmCast implementations must use some locks.
+//
+class BrowserCdmCast : public ::media::BrowserCdm {
+ public:
+ BrowserCdmCast();
+ ~BrowserCdmCast() override;
+
+ void Initialize(
+ const ::media::SessionMessageCB& session_message_cb,
+ const ::media::SessionClosedCB& session_closed_cb,
+ const ::media::LegacySessionErrorCB& legacy_session_error_cb,
+ const ::media::SessionKeysChangeCB& session_keys_change_cb,
+ const ::media::SessionExpirationUpdateCB& session_expiration_update_cb);
+
+ // PlayerTracker implementation.
+ int RegisterPlayer(const base::Closure& new_key_cb,
+ const base::Closure& cdm_unset_cb) override;
+ void UnregisterPlayer(int registration_id) override;
+
+ // ::media::BrowserCdm implementation:
+ void LoadSession(::media::MediaKeys::SessionType session_type,
+ const std::string& session_id,
+ scoped_ptr<::media::NewSessionCdmPromise> promise) override;
+ ::media::CdmContext* GetCdmContext() override;
+
+ // Returns the decryption context needed to decrypt frames encrypted with
+ // |key_id|.
+ // Returns null if |key_id| is not available.
+ virtual scoped_refptr<DecryptContext> GetDecryptContext(
+ const std::string& key_id) const = 0;
+
+ protected:
+ void OnSessionMessage(const std::string& session_id,
+ const std::vector<uint8_t>& message,
+ const GURL& destination_url);
+ void OnSessionClosed(const std::string& session_id);
+ void OnSessionKeysChange(const std::string& session_id,
+ const ::media::KeyIdAndKeyPairs& keys);
+
+ private:
+ friend class BrowserCdmCastUi;
+
+ // Allow subclasses to override to provide key sysytem specific
+ // initialization.
+ virtual void InitializeInternal();
+
+ ::media::SessionMessageCB session_message_cb_;
+ ::media::SessionClosedCB session_closed_cb_;
+ ::media::LegacySessionErrorCB legacy_session_error_cb_;
+ ::media::SessionKeysChangeCB session_keys_change_cb_;
+ ::media::SessionExpirationUpdateCB session_expiration_update_cb_;
+
+ scoped_ptr<::media::PlayerTrackerImpl> player_tracker_impl_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserCdmCast);
+};
+
+// BrowserCdm implementation that lives on the UI thread and forwards all calls
+// to a BrowserCdmCast instance on the CMA thread. This is used to simplify the
+// UI-CMA threading interaction.
+class BrowserCdmCastUi : public ::media::BrowserCdm {
+ public:
+ BrowserCdmCastUi(
+ scoped_ptr<BrowserCdmCast> browser_cdm_cast,
+ const scoped_refptr<base::MessageLoopProxy>& cdm_loop);
+ ~BrowserCdmCastUi() override;
+
+ // PlayerTracker implementation:
+ int RegisterPlayer(const base::Closure& new_key_cb,
+ const base::Closure& cdm_unset_cb) override;
+ void UnregisterPlayer(int registration_id) override;
+
+ BrowserCdmCast* browser_cdm_cast() const;
+
+ private:
+ // ::media::MediaKeys implementation:
+ void SetServerCertificate(
+ const std::vector<uint8_t>& certificate,
+ scoped_ptr<::media::SimpleCdmPromise> promise) override;
+ void CreateSessionAndGenerateRequest(
+ ::media::MediaKeys::SessionType session_type,
+ ::media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ scoped_ptr<::media::NewSessionCdmPromise> promise) override;
+ void LoadSession(::media::MediaKeys::SessionType session_type,
+ const std::string& session_id,
+ scoped_ptr<::media::NewSessionCdmPromise> promise) override;
+ void UpdateSession(const std::string& session_id,
+ const std::vector<uint8_t>& response,
+ scoped_ptr<::media::SimpleCdmPromise> promise) override;
+ void CloseSession(const std::string& session_id,
+ scoped_ptr<::media::SimpleCdmPromise> promise) override;
+ void RemoveSession(const std::string& session_id,
+ scoped_ptr<::media::SimpleCdmPromise> promise) override;
+ ::media::CdmContext* GetCdmContext() override;
+
+ scoped_ptr<BrowserCdmCast> browser_cdm_cast_;
+ scoped_refptr<base::MessageLoopProxy> cdm_loop_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserCdmCastUi);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CDM_BROWSER_CDM_CAST_H_
diff --git a/chromium/chromecast/media/cdm/playready_drm_delegate_android.cc b/chromium/chromecast/media/cdm/playready_drm_delegate_android.cc
new file mode 100644
index 00000000000..135fc44bd52
--- /dev/null
+++ b/chromium/chromecast/media/cdm/playready_drm_delegate_android.cc
@@ -0,0 +1,85 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cdm/playready_drm_delegate_android.h"
+
+#include "base/logging.h"
+#include "media/base/bit_reader.h"
+
+namespace chromecast {
+namespace media {
+
+const uint8_t kPlayreadyUuid[16] = {
+ 0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86,
+ 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95};
+
+const uint8_t kPlayreadyCustomDataUuid[] = {
+ 0x2b, 0xf8, 0x66, 0x80, 0xc6, 0xe5, 0x4e, 0x24,
+ 0xbe, 0x23, 0x0f, 0x81, 0x5a, 0x60, 0x6e, 0xb2};
+
+// ASCII "uuid" as an 4-byte integer
+const uint32_t kBoxTypeUuid = 1970628964;
+
+PlayreadyDrmDelegateAndroid::PlayreadyDrmDelegateAndroid() {
+}
+
+PlayreadyDrmDelegateAndroid::~PlayreadyDrmDelegateAndroid() {
+}
+
+const ::media::UUID PlayreadyDrmDelegateAndroid::GetUUID() const {
+ return ::media::UUID(kPlayreadyUuid,
+ kPlayreadyUuid + arraysize(kPlayreadyUuid));
+}
+
+bool PlayreadyDrmDelegateAndroid::OnCreateSession(
+ const ::media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* /* init_data_out */,
+ std::vector<std::string>* optional_parameters_out) {
+ if (init_data_type == ::media::EmeInitDataType::CENC) {
+ ::media::BitReader reader(&init_data[0], init_data.size());
+ while (reader.bits_available() > 64) {
+ uint32_t box_size;
+ uint32_t box_type;
+ reader.ReadBits(32, &box_size);
+ reader.ReadBits(32, &box_type);
+ int bytes_read = 8;
+
+ if (box_type != kBoxTypeUuid) {
+ if (box_size < 8 + sizeof(kPlayreadyCustomDataUuid)) {
+ break;
+ }
+ // Box size includes the bytes already consumed
+ reader.SkipBits((box_size - bytes_read) * 8);
+ continue;
+ }
+
+ // "uuid" was found, look for custom data format as per b/10246367
+ reader.SkipBits(128);
+ bytes_read += 16;
+ if (!memcmp(&init_data[0] + reader.bits_read() / 8,
+ kPlayreadyCustomDataUuid, 16)) {
+ reader.SkipBits((box_size - bytes_read) * 8);
+ continue;
+ }
+
+ int custom_data_size = box_size - bytes_read;
+ DCHECK(reader.bits_read() % 8 == 0);
+ int total_bytes_read = reader.bits_read() / 8;
+
+ optional_parameters_out->clear();
+ optional_parameters_out->push_back("PRCustomData");
+ optional_parameters_out->push_back(
+ std::string(&init_data[0] + total_bytes_read,
+ &init_data[0] + total_bytes_read + custom_data_size));
+ reader.SkipBits(custom_data_size * 8);
+ LOG(INFO) << "Including " << custom_data_size
+ << " bytes of custom PlayReady data";
+ }
+ }
+ return true;
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cdm/playready_drm_delegate_android.h b/chromium/chromecast/media/cdm/playready_drm_delegate_android.h
new file mode 100644
index 00000000000..3a934c456d2
--- /dev/null
+++ b/chromium/chromecast/media/cdm/playready_drm_delegate_android.h
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CDM_PLAYREADY_DRM_DELEGATE_ANDROID_H_
+#define CHROMECAST_MEDIA_CDM_PLAYREADY_DRM_DELEGATE_ANDROID_H_
+
+#include "base/macros.h"
+#include "media/base/android/media_drm_bridge_delegate.h"
+
+namespace chromecast {
+namespace media {
+
+class PlayreadyDrmDelegateAndroid : public ::media::MediaDrmBridgeDelegate {
+ public:
+ PlayreadyDrmDelegateAndroid();
+ ~PlayreadyDrmDelegateAndroid() override;
+
+ // ::media::MediaDrmBridgeDelegate implementation:
+ const ::media::UUID GetUUID() const override;
+ bool OnCreateSession(
+ const ::media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* init_data_out,
+ std::vector<std::string>* optional_parameters_out) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PlayreadyDrmDelegateAndroid);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CDM_PLAYREADY_DRM_DELEGATE_ANDROID_H_
diff --git a/chromium/chromecast/media/cma/BUILD.gn b/chromium/chromecast/media/cma/BUILD.gn
new file mode 100644
index 00000000000..c9da6296f0e
--- /dev/null
+++ b/chromium/chromecast/media/cma/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+group("cma") {
+ deps = [
+ "//chromecast/media/cma/backend",
+ "//chromecast/media/cma/base",
+ "//chromecast/media/cma/filters",
+ "//chromecast/media/cma/ipc",
+ "//chromecast/media/cma/ipc_streamer",
+ "//chromecast/media/cma/pipeline",
+ ]
+}
diff --git a/chromium/chromecast/media/cma/backend/BUILD.gn b/chromium/chromecast/media/cma/backend/BUILD.gn
new file mode 100644
index 00000000000..6526a1f746b
--- /dev/null
+++ b/chromium/chromecast/media/cma/backend/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("backend") {
+ sources = [
+ "audio_pipeline_device.cc",
+ "audio_pipeline_device.h",
+ "media_clock_device.cc",
+ "media_clock_device.h",
+ "media_component_device.cc",
+ "media_component_device.h",
+ "media_pipeline_device.cc",
+ "media_pipeline_device.h",
+ "media_pipeline_device_fake.cc",
+ "media_pipeline_device_fake.h",
+ "media_pipeline_device_fake_factory.cc",
+ "media_pipeline_device_params.cc",
+ "media_pipeline_device_params.h",
+ "video_pipeline_device.cc",
+ "video_pipeline_device.h",
+ "video_plane.cc",
+ "video_plane.h",
+ "video_plane_fake.cc",
+ "video_plane_fake.h",
+ "video_plane_fake_factory.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//chromecast/media/base",
+ "//chromecast/media/cma/base",
+ "//media",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/cma/backend/audio_pipeline_device.h b/chromium/chromecast/media/cma/backend/audio_pipeline_device.h
index 3fbf5731dbe..84c1af1fe1d 100644
--- a/chromium/chromecast/media/cma/backend/audio_pipeline_device.h
+++ b/chromium/chromecast/media/cma/backend/audio_pipeline_device.h
@@ -8,24 +8,21 @@
#include "base/macros.h"
#include "chromecast/media/cma/backend/media_component_device.h"
-namespace media {
-class AudioDecoderConfig;
-}
-
namespace chromecast {
namespace media {
class AudioPipelineDeviceClient;
+struct AudioConfig;
class AudioPipelineDevice : public MediaComponentDevice {
public:
AudioPipelineDevice();
- virtual ~AudioPipelineDevice();
+ ~AudioPipelineDevice() override;
// Provide the audio configuration.
// Must be called before switching from |kStateUninitialized| to |kStateIdle|.
// Afterwards, this can be invoked any time the configuration changes.
// Returns true if the configuration is a supported configuration.
- virtual bool SetConfig(const ::media::AudioDecoderConfig& config) = 0;
+ virtual bool SetConfig(const AudioConfig& config) = 0;
// Sets the volume multiplier.
// The multiplier must be in the range [0.0, 1.0].
diff --git a/chromium/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromium/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
index cf1daca9ab0..972d20af679 100644
--- a/chromium/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
+++ b/chromium/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -6,6 +6,7 @@
#include "base/basictypes.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
@@ -25,8 +26,11 @@
#include "chromecast/media/cma/backend/video_pipeline_device.h"
#include "chromecast/media/cma/base/decoder_buffer_adapter.h"
#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/base/decoder_config_adapter.h"
#include "chromecast/media/cma/test/frame_segmenter_for_test.h"
#include "chromecast/media/cma/test/media_component_device_feeder_for_test.h"
+#include "chromecast/public/cast_media_shlib.h"
+#include "chromecast/public/media/decoder_config.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/buffers.h"
#include "media/base/decoder_buffer.h"
@@ -67,7 +71,16 @@ class AudioVideoPipelineDeviceTest : public testing::Test {
};
AudioVideoPipelineDeviceTest();
- virtual ~AudioVideoPipelineDeviceTest();
+ ~AudioVideoPipelineDeviceTest() override;
+
+ void SetUp() override {
+ CastMediaShlib::Initialize(
+ base::CommandLine::ForCurrentProcess()->argv());
+ }
+
+ void TearDown() override {
+ CastMediaShlib::Finalize();
+ }
void ConfigureForFile(std::string filename);
void ConfigureForAudioOnly(std::string filename);
@@ -154,7 +167,8 @@ void AudioVideoPipelineDeviceTest::LoadAudioStream(std::string filename) {
AudioPipelineDevice* audio_pipeline_device =
media_pipeline_device_->GetAudioPipelineDevice();
- bool success = audio_pipeline_device->SetConfig(demux_result.audio_config);
+ bool success = audio_pipeline_device->SetConfig(
+ DecoderConfigAdapter::ToCastAudioConfig(demux_result.audio_config));
ASSERT_TRUE(success);
VLOG(2) << "Got " << frames.size() << " audio input frames";
@@ -174,7 +188,7 @@ void AudioVideoPipelineDeviceTest::LoadAudioStream(std::string filename) {
void AudioVideoPipelineDeviceTest::LoadVideoStream(std::string filename,
bool raw_h264) {
BufferList frames;
- ::media::VideoDecoderConfig video_config;
+ VideoConfig video_config;
if (raw_h264) {
base::FilePath file_path = GetTestDataFilePath(filename);
@@ -183,26 +197,18 @@ void AudioVideoPipelineDeviceTest::LoadVideoStream(std::string filename,
<< "Couldn't open stream file: " << file_path.MaybeAsASCII();
frames = H264SegmenterForTest(video_stream.data(), video_stream.length());
- // Use arbitraty sizes.
- gfx::Size coded_size(320, 240);
- gfx::Rect visible_rect(0, 0, 320, 240);
- gfx::Size natural_size(320, 240);
-
- // TODO(kjoswiak): Either pull data from stream or make caller specify value
- video_config = ::media::VideoDecoderConfig(
- ::media::kCodecH264,
- ::media::H264PROFILE_MAIN,
- ::media::VideoFrame::I420,
- coded_size,
- visible_rect,
- natural_size,
- NULL, 0, false);
+ // TODO(erickung): Either pull data from stream or make caller specify value
+ video_config.codec = kCodecH264;
+ video_config.profile = kH264Main;
+ video_config.additional_config = NULL;
+ video_config.is_encrypted = false;
} else {
base::FilePath file_path = GetTestDataFilePath(filename);
DemuxResult demux_result = FFmpegDemuxForTest(file_path,
/*audio*/ false);
frames = demux_result.frames;
- video_config = demux_result.video_config;
+ video_config =
+ DecoderConfigAdapter::ToCastVideoConfig(demux_result.video_config);
}
VideoPipelineDevice* video_pipeline_device =
@@ -230,7 +236,7 @@ void AudioVideoPipelineDeviceTest::Start() {
pause_time_ = base::TimeDelta();
pause_pattern_idx_ = 0;
- for (int i = 0; i < component_device_feeders_.size(); i++) {
+ for (size_t i = 0; i < component_device_feeders_.size(); i++) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(&MediaComponentDeviceFeederForTest::Feed,
diff --git a/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.cc b/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.cc
index c075191e62f..60d9576764a 100644
--- a/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.cc
+++ b/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.cc
@@ -5,6 +5,7 @@
#include "chromecast/media/cma/backend/media_pipeline_device_fake.h"
#include <list>
+#include <vector>
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -17,9 +18,8 @@
#include "chromecast/media/cma/backend/media_component_device.h"
#include "chromecast/media/cma/backend/video_pipeline_device.h"
#include "chromecast/media/cma/base/decoder_buffer_base.h"
-#include "media/base/audio_decoder_config.h"
+#include "chromecast/public/media/decoder_config.h"
#include "media/base/buffers.h"
-#include "media/base/video_decoder_config.h"
namespace chromecast {
namespace media {
@@ -27,14 +27,14 @@ namespace media {
class MediaClockDeviceFake : public MediaClockDevice {
public:
MediaClockDeviceFake();
- virtual ~MediaClockDeviceFake();
+ ~MediaClockDeviceFake() override;
// MediaClockDevice implementation.
- virtual State GetState() const override;
- virtual bool SetState(State new_state) override;
- virtual bool ResetTimeline(base::TimeDelta time) override;
- virtual bool SetRate(float rate) override;
- virtual base::TimeDelta GetTime() override;
+ State GetState() const override;
+ bool SetState(State new_state) override;
+ bool ResetTimeline(base::TimeDelta time) override;
+ bool SetRate(float rate) override;
+ base::TimeDelta GetTime() override;
private:
State state_;
@@ -130,20 +130,20 @@ const size_t kMaxFrameCount = 20;
class MediaComponentDeviceFake : public MediaComponentDevice {
public:
explicit MediaComponentDeviceFake(MediaClockDeviceFake* media_clock_device);
- virtual ~MediaComponentDeviceFake();
+ ~MediaComponentDeviceFake() override;
// MediaComponentDevice implementation.
- virtual void SetClient(const Client& client) override;
- virtual State GetState() const override;
- virtual bool SetState(State new_state) override;
- virtual bool SetStartPts(base::TimeDelta time) override;
- virtual FrameStatus PushFrame(
+ void SetClient(const Client& client) override;
+ State GetState() const override;
+ bool SetState(State new_state) override;
+ bool SetStartPts(base::TimeDelta time) override;
+ FrameStatus PushFrame(
const scoped_refptr<DecryptContext>& decrypt_context,
const scoped_refptr<DecoderBufferBase>& buffer,
const FrameStatusCB& completion_cb) override;
- virtual base::TimeDelta GetRenderingTime() const override;
- virtual base::TimeDelta GetRenderingDelay() const override;
- virtual bool GetStatistics(Statistics* stats) const override;
+ base::TimeDelta GetRenderingTime() const override;
+ base::TimeDelta GetRenderingDelay() const override;
+ bool GetStatistics(Statistics* stats) const override;
private:
struct FakeDecoderBuffer {
@@ -358,27 +358,28 @@ bool MediaComponentDeviceFake::GetStatistics(Statistics* stats) const {
class AudioPipelineDeviceFake : public AudioPipelineDevice {
public:
explicit AudioPipelineDeviceFake(MediaClockDeviceFake* media_clock_device);
- virtual ~AudioPipelineDeviceFake();
+ ~AudioPipelineDeviceFake() override;
// AudioPipelineDevice implementation.
- virtual void SetClient(const Client& client) override;
- virtual State GetState() const override;
- virtual bool SetState(State new_state) override;
- virtual bool SetStartPts(base::TimeDelta time) override;
- virtual FrameStatus PushFrame(
+ void SetClient(const Client& client) override;
+ State GetState() const override;
+ bool SetState(State new_state) override;
+ bool SetStartPts(base::TimeDelta time) override;
+ FrameStatus PushFrame(
const scoped_refptr<DecryptContext>& decrypt_context,
const scoped_refptr<DecoderBufferBase>& buffer,
const FrameStatusCB& completion_cb) override;
- virtual base::TimeDelta GetRenderingTime() const override;
- virtual base::TimeDelta GetRenderingDelay() const override;
- virtual bool SetConfig(const ::media::AudioDecoderConfig& config) override;
- virtual void SetStreamVolumeMultiplier(float multiplier) override;
- virtual bool GetStatistics(Statistics* stats) const override;
+ base::TimeDelta GetRenderingTime() const override;
+ base::TimeDelta GetRenderingDelay() const override;
+ bool SetConfig(const AudioConfig& config) override;
+ void SetStreamVolumeMultiplier(float multiplier) override;
+ bool GetStatistics(Statistics* stats) const override;
private:
scoped_ptr<MediaComponentDeviceFake> fake_pipeline_;
- ::media::AudioDecoderConfig config_;
+ AudioConfig config_;
+ std::vector<uint8_t> config_extra_data_;
DISALLOW_COPY_AND_ASSIGN(AudioPipelineDeviceFake);
};
@@ -406,10 +407,10 @@ bool AudioPipelineDeviceFake::SetState(State new_state) {
return false;
if (new_state == kStateIdle) {
- DCHECK(config_.IsValidConfig());
+ DCHECK(IsValidConfig(config_));
}
if (new_state == kStateUninitialized) {
- config_ = ::media::AudioDecoderConfig();
+ config_ = AudioConfig();
}
return true;
}
@@ -433,12 +434,16 @@ base::TimeDelta AudioPipelineDeviceFake::GetRenderingDelay() const {
return fake_pipeline_->GetRenderingDelay();
}
-bool AudioPipelineDeviceFake::SetConfig(
- const ::media::AudioDecoderConfig& config) {
+bool AudioPipelineDeviceFake::SetConfig(const AudioConfig& config) {
DCHECK(CalledOnValidThread());
- if (!config.IsValidConfig())
+ if (!IsValidConfig(config))
return false;
config_ = config;
+ if (config.extra_data_size > 0)
+ config_extra_data_.assign(config.extra_data,
+ config.extra_data + config.extra_data_size);
+ else
+ config_extra_data_.clear();
return true;
}
@@ -454,27 +459,28 @@ bool AudioPipelineDeviceFake::GetStatistics(Statistics* stats) const {
class VideoPipelineDeviceFake : public VideoPipelineDevice {
public:
explicit VideoPipelineDeviceFake(MediaClockDeviceFake* media_clock_device);
- virtual ~VideoPipelineDeviceFake();
+ ~VideoPipelineDeviceFake() override;
// VideoPipelineDevice implementation.
- virtual void SetClient(const Client& client) override;
- virtual State GetState() const override;
- virtual bool SetState(State new_state) override;
- virtual bool SetStartPts(base::TimeDelta time) override;
- virtual FrameStatus PushFrame(
+ void SetClient(const Client& client) override;
+ State GetState() const override;
+ bool SetState(State new_state) override;
+ bool SetStartPts(base::TimeDelta time) override;
+ FrameStatus PushFrame(
const scoped_refptr<DecryptContext>& decrypt_context,
const scoped_refptr<DecoderBufferBase>& buffer,
const FrameStatusCB& completion_cb) override;
- virtual base::TimeDelta GetRenderingTime() const override;
- virtual base::TimeDelta GetRenderingDelay() const override;
- virtual void SetVideoClient(const VideoClient& client) override;
- virtual bool SetConfig(const ::media::VideoDecoderConfig& config) override;
- virtual bool GetStatistics(Statistics* stats) const override;
+ base::TimeDelta GetRenderingTime() const override;
+ base::TimeDelta GetRenderingDelay() const override;
+ void SetVideoClient(const VideoClient& client) override;
+ bool SetConfig(const VideoConfig& config) override;
+ bool GetStatistics(Statistics* stats) const override;
private:
scoped_ptr<MediaComponentDeviceFake> fake_pipeline_;
- ::media::VideoDecoderConfig config_;
+ VideoConfig config_;
+ std::vector<uint8_t> config_extra_data_;
DISALLOW_COPY_AND_ASSIGN(VideoPipelineDeviceFake);
};
@@ -502,10 +508,10 @@ bool VideoPipelineDeviceFake::SetState(State new_state) {
return false;
if (new_state == kStateIdle) {
- DCHECK(config_.IsValidConfig());
+ DCHECK(IsValidConfig(config_));
}
if (new_state == kStateUninitialized) {
- config_ = ::media::VideoDecoderConfig();
+ config_ = VideoConfig();
}
return true;
}
@@ -532,12 +538,16 @@ base::TimeDelta VideoPipelineDeviceFake::GetRenderingDelay() const {
void VideoPipelineDeviceFake::SetVideoClient(const VideoClient& client) {
}
-bool VideoPipelineDeviceFake::SetConfig(
- const ::media::VideoDecoderConfig& config) {
+bool VideoPipelineDeviceFake::SetConfig(const VideoConfig& config) {
DCHECK(CalledOnValidThread());
- if (!config.IsValidConfig())
+ if (!IsValidConfig(config))
return false;
config_ = config;
+ if (config.extra_data_size > 0)
+ config_extra_data_.assign(config.extra_data,
+ config.extra_data + config.extra_data_size);
+ else
+ config_extra_data_.clear();
return true;
}
diff --git a/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.h b/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.h
index 0534515bf9f..248c9a4322e 100644
--- a/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.h
+++ b/chromium/chromecast/media/cma/backend/media_pipeline_device_fake.h
@@ -19,12 +19,12 @@ class VideoPipelineDeviceFake;
class MediaPipelineDeviceFake : public MediaPipelineDevice {
public:
MediaPipelineDeviceFake();
- virtual ~MediaPipelineDeviceFake();
+ ~MediaPipelineDeviceFake() override;
// MediaPipelineDevice implementation.
- virtual AudioPipelineDevice* GetAudioPipelineDevice() const override;
- virtual VideoPipelineDevice* GetVideoPipelineDevice() const override;
- virtual MediaClockDevice* GetMediaClockDevice() const override;
+ AudioPipelineDevice* GetAudioPipelineDevice() const override;
+ VideoPipelineDevice* GetVideoPipelineDevice() const override;
+ MediaClockDevice* GetMediaClockDevice() const override;
private:
scoped_ptr<MediaClockDeviceFake> media_clock_device_;
diff --git a/chromium/chromecast/media/cma/backend/media_pipeline_device_params.cc b/chromium/chromecast/media/cma/backend/media_pipeline_device_params.cc
index 531c76884f9..1f4e2ebed58 100644
--- a/chromium/chromecast/media/cma/backend/media_pipeline_device_params.cc
+++ b/chromium/chromecast/media/cma/backend/media_pipeline_device_params.cc
@@ -8,7 +8,7 @@ namespace chromecast {
namespace media {
MediaPipelineDeviceParams::MediaPipelineDeviceParams()
- : disable_synchronization(false) {
+ : sync_type(kModeSyncPts) {
}
MediaPipelineDeviceParams::~MediaPipelineDeviceParams() {
diff --git a/chromium/chromecast/media/cma/backend/media_pipeline_device_params.h b/chromium/chromecast/media/cma/backend/media_pipeline_device_params.h
index 9bf9c044f16..d13e4e3a188 100644
--- a/chromium/chromecast/media/cma/backend/media_pipeline_device_params.h
+++ b/chromium/chromecast/media/cma/backend/media_pipeline_device_params.h
@@ -12,17 +12,25 @@ namespace media {
class MediaPipelineDeviceParams {
public:
+ enum MediaSyncType {
+ // Default operation, synchronize playback using PTS with higher latency.
+ kModeSyncPts = 0,
+ // With this mode, synchronization is disabled and audio/video frames are
+ // rendered "right away":
+ // - for audio, frames are still rendered based on the sampling frequency
+ // - for video, frames are rendered as soon as available at the output of
+ // the video decoder.
+ // The assumption is that no B frames are used when synchronization is
+ // disabled, otherwise B frames would always be skipped.
+ kModeIgnorePts = 1,
+ // In addition to the constraints above, also do not wait for vsync.
+ kModeIgnorePtsAndVSync = 2,
+ };
+
MediaPipelineDeviceParams();
~MediaPipelineDeviceParams();
- // When set to true, synchronization is disabled and audio/video frames are
- // rendered "right away":
- // - for audio, frames are still rendered based on the sampling frequency
- // - for video, frames are rendered as soon as available at the output of
- // the video decoder.
- // The assumption is that no B frames are used when synchronization is
- // disabled, otherwise B frames would always be skipped.
- bool disable_synchronization;
+ MediaSyncType sync_type;
};
} // namespace media
diff --git a/chromium/chromecast/media/cma/backend/video_pipeline_device.h b/chromium/chromecast/media/cma/backend/video_pipeline_device.h
index eda48e206f4..ee7dff4c0d1 100644
--- a/chromium/chromecast/media/cma/backend/video_pipeline_device.h
+++ b/chromium/chromecast/media/cma/backend/video_pipeline_device.h
@@ -13,13 +13,10 @@ namespace gfx {
class Size;
}
-namespace media {
-class VideoDecoderConfig;
-}
-
namespace chromecast {
namespace media {
class DecoderBufferBase;
+struct VideoConfig;
// VideoPipelineDevice -
//
@@ -42,7 +39,7 @@ class VideoPipelineDevice : public MediaComponentDevice {
};
VideoPipelineDevice();
- virtual ~VideoPipelineDevice();
+ ~VideoPipelineDevice() override;
// Registers |client| as the video specific event handler.
virtual void SetVideoClient(const VideoClient& client) = 0;
@@ -51,7 +48,7 @@ class VideoPipelineDevice : public MediaComponentDevice {
// Must be called before switching from |kStateUninitialized| to |kStateIdle|.
// Afterwards, this can be invoked any time the configuration changes.
// Returns true if the configuration is a supported configuration.
- virtual bool SetConfig(const ::media::VideoDecoderConfig& config) = 0;
+ virtual bool SetConfig(const VideoConfig& config) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(VideoPipelineDevice);
diff --git a/chromium/chromecast/media/cma/backend/video_plane.cc b/chromium/chromecast/media/cma/backend/video_plane.cc
new file mode 100644
index 00000000000..5d8097f2a62
--- /dev/null
+++ b/chromium/chromecast/media/cma/backend/video_plane.cc
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/backend/video_plane.h"
+
+#include "base/memory/singleton.h"
+
+namespace chromecast {
+namespace media {
+
+VideoPlane::VideoPlane() {
+}
+
+VideoPlane::~VideoPlane() {
+}
+
+class VideoPlaneRegistry {
+ public:
+ static VideoPlaneRegistry* GetInstance() {
+ return Singleton<VideoPlaneRegistry>::get();
+ }
+
+ VideoPlane* GetVideoPlane();
+
+ private:
+ friend struct DefaultSingletonTraits<VideoPlaneRegistry>;
+ friend class Singleton<VideoPlaneRegistry>;
+
+ VideoPlaneRegistry();
+ virtual ~VideoPlaneRegistry();
+
+ scoped_ptr<VideoPlane> video_plane_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoPlaneRegistry);
+};
+
+VideoPlaneRegistry::VideoPlaneRegistry() :
+ video_plane_(CreateVideoPlane()) {
+}
+
+VideoPlaneRegistry::~VideoPlaneRegistry() {
+}
+
+VideoPlane* VideoPlaneRegistry::GetVideoPlane() {
+ return video_plane_.get();
+}
+
+VideoPlane* GetVideoPlane() {
+ return VideoPlaneRegistry::GetInstance()->GetVideoPlane();
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/backend/video_plane.h b/chromium/chromecast/media/cma/backend/video_plane.h
new file mode 100644
index 00000000000..a5f864c6d50
--- /dev/null
+++ b/chromium/chromecast/media/cma/backend/video_plane.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PLANE_H_
+#define CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PLANE_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace gfx {
+class QuadF;
+class Size;
+}
+
+namespace chromecast {
+namespace media {
+
+class VideoPlane {
+ public:
+ enum CoordinateType {
+ // Graphics plane as coordinate type.
+ COORDINATE_TYPE_GRAPHICS_PLANE = 0,
+ // Output display screen as coordinate type.
+ COORDINATE_TYPE_SCREEN_RESOLUTION = 1,
+ };
+
+ VideoPlane();
+ virtual ~VideoPlane();
+
+ // Gets output screen resolution.
+ virtual gfx::Size GetScreenResolution() = 0;
+
+ // Updates the video plane geometry.
+ // |quad.p1()| corresponds to the top left of the original video,
+ // |quad.p2()| to the top right of the original video,
+ // and so on.
+ // Depending on the underlying hardware, the exact geometry
+ // might not be honored.
+ // |coordinate_type| indicates what coordinate type |quad| refers to.
+ virtual void SetGeometry(const gfx::QuadF& quad,
+ CoordinateType coordinate_type) = 0;
+
+ // Should be invoked whenever screen resolution changes (e.g. when a device is
+ // plugged into a new HDMI port and a new HDMI EDID is received).
+ // VideoPlane should reposition itself according to the new screen resolution.
+ virtual void OnScreenResolutionChanged(const gfx::Size& screen_res) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VideoPlane);
+};
+
+// Factory to create a VideoPlane.
+scoped_ptr<VideoPlane> CreateVideoPlane();
+
+// Global accessor to the video plane.
+VideoPlane* GetVideoPlane();
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PLANE_H_
diff --git a/chromium/chromecast/media/cma/backend/video_plane_fake.cc b/chromium/chromecast/media/cma/backend/video_plane_fake.cc
new file mode 100644
index 00000000000..73fa39ef5b6
--- /dev/null
+++ b/chromium/chromecast/media/cma/backend/video_plane_fake.cc
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/backend/video_plane_fake.h"
+
+#include "base/logging.h"
+#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace chromecast {
+namespace media {
+
+VideoPlaneFake::VideoPlaneFake() {
+}
+
+VideoPlaneFake::~VideoPlaneFake() {
+}
+
+gfx::Size VideoPlaneFake::GetScreenResolution() {
+ return gfx::Size(1920, 1080);
+}
+
+void VideoPlaneFake::SetGeometry(const gfx::QuadF& quad,
+ CoordinateType coordinate_type) {
+ // Nothing to be done.
+}
+
+void VideoPlaneFake::OnScreenResolutionChanged(const gfx::Size& screen_res) {
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/backend/video_plane_fake.h b/chromium/chromecast/media/cma/backend/video_plane_fake.h
new file mode 100644
index 00000000000..5fe04e6accb
--- /dev/null
+++ b/chromium/chromecast/media/cma/backend/video_plane_fake.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PLANE_FAKE_H_
+#define CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PLANE_FAKE_H_
+
+#include "base/macros.h"
+#include "chromecast/media/cma/backend/video_plane.h"
+
+namespace chromecast {
+namespace media {
+
+class VideoPlaneFake : public VideoPlane {
+ public:
+ VideoPlaneFake();
+ ~VideoPlaneFake() override;
+
+ // VideoPlane implementation.
+ gfx::Size GetScreenResolution() override;
+ void SetGeometry(const gfx::QuadF& quad,
+ CoordinateType coordinate_type) override;
+ void OnScreenResolutionChanged(const gfx::Size& screen_res) override;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoPlaneFake);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PLANE_FAKE_H_
diff --git a/chromium/chromecast/media/cma/backend/video_plane_fake_factory.cc b/chromium/chromecast/media/cma/backend/video_plane_fake_factory.cc
new file mode 100644
index 00000000000..310c8bc878a
--- /dev/null
+++ b/chromium/chromecast/media/cma/backend/video_plane_fake_factory.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/backend/video_plane_fake.h"
+
+namespace chromecast {
+namespace media {
+
+scoped_ptr<VideoPlane> CreateVideoPlane() {
+ return make_scoped_ptr(new VideoPlaneFake());
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/base/BUILD.gn b/chromium/chromecast/media/cma/base/BUILD.gn
new file mode 100644
index 00000000000..b919439cde6
--- /dev/null
+++ b/chromium/chromecast/media/cma/base/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("base") {
+ sources = [
+ "balanced_media_task_runner_factory.cc",
+ "balanced_media_task_runner_factory.h",
+ "buffering_controller.cc",
+ "buffering_controller.h",
+ "buffering_defs.cc",
+ "buffering_defs.h",
+ "buffering_frame_provider.cc",
+ "buffering_frame_provider.h",
+ "buffering_state.cc",
+ "buffering_state.h",
+ "cma_logging.h",
+ "coded_frame_provider.cc",
+ "coded_frame_provider.h",
+ "decoder_buffer_adapter.cc",
+ "decoder_buffer_adapter.h",
+ "decoder_buffer_base.cc",
+ "decoder_buffer_base.h",
+ "media_task_runner.cc",
+ "media_task_runner.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chromecast/base",
+ "//media",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/cma/base/balanced_media_task_runner_factory.cc b/chromium/chromecast/media/cma/base/balanced_media_task_runner_factory.cc
index 48413c0a9e2..f365534e457 100644
--- a/chromium/chromecast/media/cma/base/balanced_media_task_runner_factory.cc
+++ b/chromium/chromecast/media/cma/base/balanced_media_task_runner_factory.cc
@@ -32,13 +32,13 @@ class MediaTaskRunnerWithNotification : public MediaTaskRunner {
const base::Closure& shutdown_cb);
// MediaTaskRunner implementation.
- virtual bool PostMediaTask(
+ bool PostMediaTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta timestamp) override;
private:
- virtual ~MediaTaskRunnerWithNotification();
+ ~MediaTaskRunnerWithNotification() override;
scoped_refptr<MediaTaskRunner> const media_task_runner_;
@@ -93,13 +93,13 @@ class BalancedMediaTaskRunner
base::TimeDelta GetMediaTimestamp() const;
// MediaTaskRunner implementation.
- virtual bool PostMediaTask(
+ bool PostMediaTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta timestamp) override;
private:
- virtual ~BalancedMediaTaskRunner();
+ ~BalancedMediaTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> const task_runner_;
diff --git a/chromium/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc b/chromium/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
index e3448f67cac..b572e500247 100644
--- a/chromium/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
+++ b/chromium/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
@@ -45,7 +45,7 @@ MediaTaskRunnerTestContext::~MediaTaskRunnerTestContext() {
class BalancedMediaTaskRunnerTest : public testing::Test {
public:
BalancedMediaTaskRunnerTest();
- virtual ~BalancedMediaTaskRunnerTest();
+ ~BalancedMediaTaskRunnerTest() override;
void SetupTest(base::TimeDelta max_delta,
const std::vector<std::vector<int> >& timestamps_in_ms,
diff --git a/chromium/chromecast/media/cma/base/buffering_controller.cc b/chromium/chromecast/media/cma/base/buffering_controller.cc
index 183b12628d2..9e7cb6c9c01 100644
--- a/chromium/chromecast/media/cma/base/buffering_controller.cc
+++ b/chromium/chromecast/media/cma/base/buffering_controller.cc
@@ -63,11 +63,13 @@ void BufferingController::UpdateHighLevelThreshold(
OnBufferingStateChanged(false, false);
}
-scoped_refptr<BufferingState> BufferingController::AddStream() {
+scoped_refptr<BufferingState> BufferingController::AddStream(
+ const std::string& stream_id) {
DCHECK(thread_checker_.CalledOnValidThread());
// Add a new stream to the list of streams being monitored.
scoped_refptr<BufferingState> buffering_state(new BufferingState(
+ stream_id,
config_,
base::Bind(&BufferingController::OnBufferingStateChanged, weak_this_,
false, false),
@@ -195,7 +197,6 @@ bool BufferingController::IsLowBufferLevel() {
}
void BufferingController::DumpState() const {
- CMALOG(kLogControl) << __FUNCTION__;
for (StreamList::const_iterator it = stream_list_.begin();
it != stream_list_.end(); ++it) {
CMALOG(kLogControl) << (*it)->ToString();
diff --git a/chromium/chromecast/media/cma/base/buffering_controller.h b/chromium/chromecast/media/cma/base/buffering_controller.h
index bfc2c5cb9aa..b0ccecee1a1 100644
--- a/chromium/chromecast/media/cma/base/buffering_controller.h
+++ b/chromium/chromecast/media/cma/base/buffering_controller.h
@@ -6,6 +6,7 @@
#define CHROMECAST_MEDIA_CMA_BASE_BUFFERING_CONTROLLER_H
#include <list>
+#include <string>
#include "base/callback.h"
#include "base/macros.h"
@@ -36,7 +37,7 @@ class BufferingController {
// Creates a buffering state for one stream. This state is added to the list
// of streams monitored by the buffering controller.
- scoped_refptr<BufferingState> AddStream();
+ scoped_refptr<BufferingState> AddStream(const std::string& stream_id);
// Sets the playback time.
void SetMediaTime(base::TimeDelta time);
diff --git a/chromium/chromecast/media/cma/base/buffering_controller_unittest.cc b/chromium/chromecast/media/cma/base/buffering_controller_unittest.cc
index 75eaed9ce1a..e0b45c5b377 100644
--- a/chromium/chromecast/media/cma/base/buffering_controller_unittest.cc
+++ b/chromium/chromecast/media/cma/base/buffering_controller_unittest.cc
@@ -39,7 +39,7 @@ MockBufferingControllerClient::~MockBufferingControllerClient() {
class BufferingControllerTest : public testing::Test {
public:
BufferingControllerTest();
- virtual ~BufferingControllerTest();
+ ~BufferingControllerTest() override;
protected:
scoped_ptr<BufferingController> buffering_controller_;
@@ -83,7 +83,7 @@ BufferingControllerTest::~BufferingControllerTest() {
TEST_F(BufferingControllerTest, OneStream_Typical) {
EXPECT_CALL(client_, OnBufferingNotification(true)).Times(1);
scoped_refptr<BufferingState> buffering_state =
- buffering_controller_->AddStream();
+ buffering_controller_->AddStream("test");
buffering_state->SetMediaTime(base::TimeDelta());
// Simulate pre-buffering.
@@ -121,7 +121,7 @@ TEST_F(BufferingControllerTest, OneStream_Typical) {
TEST_F(BufferingControllerTest, OneStream_LeaveBufferingOnEos) {
EXPECT_CALL(client_, OnBufferingNotification(true)).Times(1);
scoped_refptr<BufferingState> buffering_state =
- buffering_controller_->AddStream();
+ buffering_controller_->AddStream("test");
buffering_state->SetMediaTime(base::TimeDelta());
EXPECT_CALL(client_, OnBufferingNotification(false)).Times(1);
diff --git a/chromium/chromecast/media/cma/base/buffering_defs.cc b/chromium/chromecast/media/cma/base/buffering_defs.cc
new file mode 100644
index 00000000000..3afd0f8087e
--- /dev/null
+++ b/chromium/chromecast/media/cma/base/buffering_defs.cc
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/base/buffering_defs.h"
+
+namespace chromecast {
+namespace media {
+
+const size_t kAppAudioBufferSize = 64 * 1024;
+const size_t kAppVideoBufferSize = 4 * 1024 * 1024;
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/base/buffering_defs.h b/chromium/chromecast/media/cma/base/buffering_defs.h
new file mode 100644
index 00000000000..a56a9a679e9
--- /dev/null
+++ b/chromium/chromecast/media/cma/base/buffering_defs.h
@@ -0,0 +1,19 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BASE_BUFFERING_DEFS_H_
+#define CHROMECAST_MEDIA_CMA_BASE_BUFFERING_DEFS_H_
+
+#include "base/basictypes.h"
+
+namespace chromecast {
+namespace media {
+
+extern const size_t kAppAudioBufferSize;
+extern const size_t kAppVideoBufferSize;
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BASE_BUFFERING_DEFS_H_
diff --git a/chromium/chromecast/media/cma/base/buffering_frame_provider.h b/chromium/chromecast/media/cma/base/buffering_frame_provider.h
index 0397676bca0..0cb99e2c591 100644
--- a/chromium/chromecast/media/cma/base/buffering_frame_provider.h
+++ b/chromium/chromecast/media/cma/base/buffering_frame_provider.h
@@ -40,11 +40,11 @@ class BufferingFrameProvider : public CodedFrameProvider {
size_t max_buffer_size,
size_t max_frame_size,
const FrameBufferedCB& frame_buffered_cb);
- virtual ~BufferingFrameProvider();
+ ~BufferingFrameProvider() override;
// CodedFrameProvider implementation.
- virtual void Read(const ReadCB& read_cb) override;
- virtual void Flush(const base::Closure& flush_cb) override;
+ void Read(const ReadCB& read_cb) override;
+ void Flush(const base::Closure& flush_cb) override;
private:
class BufferWithConfig {
diff --git a/chromium/chromecast/media/cma/base/buffering_frame_provider_unittest.cc b/chromium/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
index c24862f4932..8e027365ef7 100644
--- a/chromium/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
+++ b/chromium/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
@@ -27,7 +27,7 @@ namespace media {
class BufferingFrameProviderTest : public testing::Test {
public:
BufferingFrameProviderTest();
- virtual ~BufferingFrameProviderTest();
+ ~BufferingFrameProviderTest() override;
// Setup the test.
void Configure(
diff --git a/chromium/chromecast/media/cma/base/buffering_state.cc b/chromium/chromecast/media/cma/base/buffering_state.cc
index e1fc49fe188..dec0cb42095 100644
--- a/chromium/chromecast/media/cma/base/buffering_state.cc
+++ b/chromium/chromecast/media/cma/base/buffering_state.cc
@@ -24,10 +24,12 @@ BufferingConfig::~BufferingConfig() {
BufferingState::BufferingState(
+ const std::string& stream_id,
const scoped_refptr<BufferingConfig>& config,
const base::Closure& state_changed_cb,
const HighLevelBufferCB& high_level_buffer_cb)
- : config_(config),
+ : stream_id_(stream_id),
+ config_(config),
state_changed_cb_(state_changed_cb),
high_level_buffer_cb_(high_level_buffer_cb),
state_(kLowLevel),
@@ -94,7 +96,7 @@ void BufferingState::NotifyMaxCapacity(base::TimeDelta buffered_time) {
std::string BufferingState::ToString() const {
std::ostringstream s;
- s << "state=" << state_
+ s << stream_id_ << " state=" << state_
<< " media_time_ms=" << media_time_.InMilliseconds()
<< " buffered_time_ms=" << buffered_time_.InMilliseconds()
<< " low_level_ms=" << config_->low_level().InMilliseconds()
diff --git a/chromium/chromecast/media/cma/base/buffering_state.h b/chromium/chromecast/media/cma/base/buffering_state.h
index ced8206d8a1..3e1fe5d811c 100644
--- a/chromium/chromecast/media/cma/base/buffering_state.h
+++ b/chromium/chromecast/media/cma/base/buffering_state.h
@@ -57,7 +57,8 @@ class BufferingState
// |high_level_buffer_cb| is used to adjust the high buffer threshold
// when the underlying buffer is not large enough to accomodate
// the current high buffer level.
- BufferingState(const scoped_refptr<BufferingConfig>& config,
+ BufferingState(const std::string& stream_id,
+ const scoped_refptr<BufferingConfig>& config,
const base::Closure& state_changed_cb,
const HighLevelBufferCB& high_level_buffer_cb);
@@ -105,6 +106,7 @@ class BufferingState
// Updates the state to |new_state|.
void UpdateState(State new_state);
+ std::string const stream_id_;
scoped_refptr<BufferingConfig> const config_;
// Callback invoked each time there is a change of state.
diff --git a/chromium/chromecast/media/cma/base/decoder_buffer_adapter.cc b/chromium/chromecast/media/cma/base/decoder_buffer_adapter.cc
index 236505b9950..45095da169b 100644
--- a/chromium/chromecast/media/cma/base/decoder_buffer_adapter.cc
+++ b/chromium/chromecast/media/cma/base/decoder_buffer_adapter.cc
@@ -29,7 +29,7 @@ uint8* DecoderBufferAdapter::writable_data() const {
return buffer_->writable_data();
}
-int DecoderBufferAdapter::data_size() const {
+size_t DecoderBufferAdapter::data_size() const {
return buffer_->data_size();
}
diff --git a/chromium/chromecast/media/cma/base/decoder_buffer_adapter.h b/chromium/chromecast/media/cma/base/decoder_buffer_adapter.h
index 1967fbebd67..054e60ee59e 100644
--- a/chromium/chromecast/media/cma/base/decoder_buffer_adapter.h
+++ b/chromium/chromecast/media/cma/base/decoder_buffer_adapter.h
@@ -24,15 +24,15 @@ class DecoderBufferAdapter : public DecoderBufferBase {
const scoped_refptr< ::media::DecoderBuffer>& buffer);
// DecoderBufferBase implementation.
- virtual base::TimeDelta timestamp() const override;
- virtual const uint8* data() const override;
- virtual uint8* writable_data() const override;
- virtual int data_size() const override;
- virtual const ::media::DecryptConfig* decrypt_config() const override;
- virtual bool end_of_stream() const override;
+ base::TimeDelta timestamp() const override;
+ const uint8* data() const override;
+ uint8* writable_data() const override;
+ size_t data_size() const override;
+ const ::media::DecryptConfig* decrypt_config() const override;
+ bool end_of_stream() const override;
private:
- virtual ~DecoderBufferAdapter();
+ ~DecoderBufferAdapter() override;
scoped_refptr< ::media::DecoderBuffer> const buffer_;
diff --git a/chromium/chromecast/media/cma/base/decoder_buffer_base.h b/chromium/chromecast/media/cma/base/decoder_buffer_base.h
index 9143104f14a..099b44d7a9e 100644
--- a/chromium/chromecast/media/cma/base/decoder_buffer_base.h
+++ b/chromium/chromecast/media/cma/base/decoder_buffer_base.h
@@ -33,7 +33,7 @@ class DecoderBufferBase
virtual uint8* writable_data() const = 0;
// Returns the size of the frame in bytes.
- virtual int data_size() const = 0;
+ virtual size_t data_size() const = 0;
// Returns the decrypt configuration.
// Returns NULL if the buffer has no decrypt info.
diff --git a/chromium/chromecast/media/cma/base/decoder_config_adapter.cc b/chromium/chromecast/media/cma/base/decoder_config_adapter.cc
new file mode 100644
index 00000000000..793395c9c14
--- /dev/null
+++ b/chromium/chromecast/media/cma/base/decoder_config_adapter.cc
@@ -0,0 +1,126 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/base/decoder_config_adapter.h"
+
+#include "base/logging.h"
+#include "media/base/channel_layout.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+// Converts ::media::AudioCodec to chromecast::media::AudioCodec. Any unknown or
+// unsupported codec will be converted to chromecast::media::kCodecUnknown.
+AudioCodec ToAudioCodec(const ::media::AudioCodec audio_codec) {
+ switch (audio_codec) {
+ case ::media::kCodecAAC:
+ return kCodecAAC;
+ case ::media::kCodecMP3:
+ return kCodecMP3;
+ case ::media::kCodecPCM:
+ return kCodecPCM;
+ case ::media::kCodecPCM_S16BE:
+ return kCodecPCM_S16BE;
+ case ::media::kCodecVorbis:
+ return kCodecVorbis;
+ default:
+ LOG(ERROR) << "Unsupported audio codec " << audio_codec;
+ }
+ return kAudioCodecUnknown;
+}
+
+// Converts ::media::VideoCodec to chromecast::media::VideoCodec. Any unknown or
+// unsupported codec will be converted to chromecast::media::kCodecUnknown.
+VideoCodec ToVideoCodec(const ::media::VideoCodec video_codec) {
+ switch (video_codec) {
+ case ::media::kCodecH264:
+ return kCodecH264;
+ case ::media::kCodecVP8:
+ return kCodecVP8;
+ case ::media::kCodecVP9:
+ return kCodecVP9;
+ default:
+ LOG(ERROR) << "Unsupported video codec " << video_codec;
+ }
+ return kVideoCodecUnknown;
+}
+
+// Converts ::media::VideoCodecProfile to chromecast::media::VideoProfile.
+VideoProfile ToVideoProfile(const ::media::VideoCodecProfile codec_profile) {
+ switch(codec_profile) {
+ case ::media::H264PROFILE_BASELINE:
+ return kH264Baseline;
+ case ::media::H264PROFILE_MAIN:
+ return kH264Main;
+ case ::media::H264PROFILE_EXTENDED:
+ return kH264Extended;
+ case ::media::H264PROFILE_HIGH:
+ return kH264High;
+ case ::media::H264PROFILE_HIGH10PROFILE:
+ return kH264High10;
+ case ::media::H264PROFILE_HIGH422PROFILE:
+ return kH264High422;
+ case ::media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
+ return kH264High444Predictive;
+ case ::media::H264PROFILE_SCALABLEBASELINE:
+ return kH264ScalableBaseline;
+ case ::media::H264PROFILE_SCALABLEHIGH:
+ return kH264ScalableHigh;
+ case ::media::H264PROFILE_STEREOHIGH:
+ return kH264Stereohigh;
+ case ::media::H264PROFILE_MULTIVIEWHIGH:
+ return kH264MultiviewHigh;
+ case ::media::VP8PROFILE_ANY:
+ return kVP8ProfileAny;
+ case ::media::VP9PROFILE_ANY:
+ return kVP9ProfileAny;
+ default:
+ LOG(INFO) << "Unsupported video codec profile " << codec_profile;
+ }
+ return kVideoProfileUnknown;
+}
+
+} // namespace
+
+// static
+AudioConfig DecoderConfigAdapter::ToCastAudioConfig(
+ const ::media::AudioDecoderConfig& config) {
+ AudioConfig audio_config;
+ if (!config.IsValidConfig()) {
+ return audio_config;
+ }
+
+ audio_config.codec = ToAudioCodec(config.codec());
+ audio_config.bytes_per_channel = config.bytes_per_channel();
+ audio_config.channel_number =
+ ::media::ChannelLayoutToChannelCount(config.channel_layout()),
+ audio_config.samples_per_second = config.samples_per_second();
+ audio_config.extra_data = (config.extra_data_size() > 0) ?
+ config.extra_data() : nullptr;
+ audio_config.extra_data_size = config.extra_data_size();
+ audio_config.is_encrypted = config.is_encrypted();
+ return audio_config;
+}
+
+// static
+VideoConfig DecoderConfigAdapter::ToCastVideoConfig(
+ const ::media::VideoDecoderConfig& config) {
+ VideoConfig video_config;
+ if (!config.IsValidConfig()) {
+ return video_config;
+ }
+
+ video_config.codec = ToVideoCodec(config.codec());
+ video_config.profile = ToVideoProfile(config.profile());
+ video_config.extra_data = (config.extra_data_size() > 0) ?
+ config.extra_data() : nullptr;
+ video_config.extra_data_size = config.extra_data_size();
+ video_config.is_encrypted = config.is_encrypted();
+ return video_config;
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/base/decoder_config_adapter.h b/chromium/chromecast/media/cma/base/decoder_config_adapter.h
new file mode 100644
index 00000000000..f04c1c2f1d3
--- /dev/null
+++ b/chromium/chromecast/media/cma/base/decoder_config_adapter.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BASE_DECODER_CONFIG_ADAPTER_H_
+#define CHROMECAST_MEDIA_CMA_BASE_DECODER_CONFIG_ADAPTER_H_
+
+#include "chromecast/public/media/decoder_config.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+
+namespace chromecast {
+namespace media {
+
+class DecoderConfigAdapter {
+ public:
+ // Converts ::media::AudioDecoderConfig to chromecast::media::AudioConfig.
+ static AudioConfig ToCastAudioConfig(
+ const ::media::AudioDecoderConfig& config);
+
+ // Converts ::media::VideoDecoderConfig to chromecast::media::VideoConfig.
+ static VideoConfig ToCastVideoConfig(
+ const ::media::VideoDecoderConfig& config);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BASE_DECODER_CONFIG_ADAPTER_H_
diff --git a/chromium/chromecast/media/cma/filters/BUILD.gn b/chromium/chromecast/media/cma/filters/BUILD.gn
new file mode 100644
index 00000000000..605075533f9
--- /dev/null
+++ b/chromium/chromecast/media/cma/filters/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("filters") {
+ sources = [
+ "cma_renderer.cc",
+ "cma_renderer.h",
+ "demuxer_stream_adapter.cc",
+ "demuxer_stream_adapter.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chromecast/media/cma/base",
+ "//media",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/cma/filters/cma_renderer.cc b/chromium/chromecast/media/cma/filters/cma_renderer.cc
new file mode 100644
index 00000000000..b8e7b42ba9a
--- /dev/null
+++ b/chromium/chromecast/media/cma/filters/cma_renderer.cc
@@ -0,0 +1,472 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/filters/cma_renderer.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/filters/demuxer_stream_adapter.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/media_pipeline.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/video_pipeline.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_client.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/demuxer_stream_provider.h"
+#include "media/base/pipeline_status.h"
+#include "media/base/time_delta_interpolator.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_renderer_sink.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+// Maximum difference between audio frame PTS and video frame PTS
+// for frames read from the DemuxerStream.
+const base::TimeDelta kMaxDeltaFetcher(
+ base::TimeDelta::FromMilliseconds(2000));
+
+} // namespace
+
+CmaRenderer::CmaRenderer(scoped_ptr<MediaPipeline> media_pipeline,
+ ::media::VideoRendererSink* video_renderer_sink)
+ : media_task_runner_factory_(
+ new BalancedMediaTaskRunnerFactory(kMaxDeltaFetcher)),
+ media_pipeline_(media_pipeline.Pass()),
+ audio_pipeline_(media_pipeline_->GetAudioPipeline()),
+ video_pipeline_(media_pipeline_->GetVideoPipeline()),
+ video_renderer_sink_(video_renderer_sink),
+ state_(kUninitialized),
+ is_pending_transition_(false),
+ has_audio_(false),
+ has_video_(false),
+ received_audio_eos_(false),
+ received_video_eos_(false),
+ initial_natural_size_(gfx::Size()),
+ initial_video_hole_created_(false),
+ time_interpolator_(
+ new ::media::TimeDeltaInterpolator(&default_tick_clock_)),
+ playback_rate_(1.0),
+ weak_factory_(this) {
+ weak_this_ = weak_factory_.GetWeakPtr();
+ thread_checker_.DetachFromThread();
+
+ time_interpolator_->SetUpperBound(base::TimeDelta());
+}
+
+CmaRenderer::~CmaRenderer() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!init_cb_.is_null())
+ base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_ERROR_ABORT);
+ else if (!flush_cb_.is_null())
+ base::ResetAndReturn(&flush_cb_).Run();
+
+ if (has_audio_ || has_video_)
+ media_pipeline_->Stop();
+}
+
+void CmaRenderer::Initialize(
+ ::media::DemuxerStreamProvider* demuxer_stream_provider,
+ const ::media::PipelineStatusCB& init_cb,
+ const ::media::StatisticsCB& statistics_cb,
+ const ::media::BufferingStateCB& buffering_state_cb,
+ const base::Closure& ended_cb,
+ const ::media::PipelineStatusCB& error_cb,
+ const base::Closure& waiting_for_decryption_key_cb) {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kUninitialized) << state_;
+ DCHECK(!init_cb.is_null());
+ DCHECK(!statistics_cb.is_null());
+ DCHECK(!ended_cb.is_null());
+ DCHECK(!error_cb.is_null());
+ DCHECK(!buffering_state_cb.is_null());
+ DCHECK(!waiting_for_decryption_key_cb.is_null());
+ DCHECK(demuxer_stream_provider->GetStream(::media::DemuxerStream::AUDIO) ||
+ demuxer_stream_provider->GetStream(::media::DemuxerStream::VIDEO));
+
+ BeginStateTransition();
+
+ demuxer_stream_provider_ = demuxer_stream_provider;
+ statistics_cb_ = statistics_cb;
+ buffering_state_cb_ = buffering_state_cb;
+ ended_cb_ = ended_cb;
+ error_cb_ = error_cb;
+ // TODO(erickung): wire up waiting_for_decryption_key_cb.
+ waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
+
+ MediaPipelineClient media_pipeline_client;
+ media_pipeline_client.error_cb = error_cb_;
+ media_pipeline_client.buffering_state_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnBufferingNotification, weak_this_));
+ media_pipeline_client.time_update_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnPlaybackTimeUpdated, weak_this_));
+ media_pipeline_->SetClient(media_pipeline_client);
+
+ init_cb_ = init_cb;
+ InitializeAudioPipeline();
+}
+
+void CmaRenderer::Flush(const base::Closure& flush_cb) {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ BeginStateTransition();
+
+ DCHECK(flush_cb_.is_null());
+ flush_cb_ = flush_cb;
+
+ if (state_ == kError) {
+ OnError(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+
+ DCHECK_EQ(state_, kPlaying) << state_;
+ media_pipeline_->Flush(
+ ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnFlushDone, weak_this_)));
+
+ {
+ base::AutoLock auto_lock(time_interpolator_lock_);
+ time_interpolator_->StopInterpolating();
+ }
+}
+
+void CmaRenderer::StartPlayingFrom(base::TimeDelta time) {
+ CMALOG(kLogControl) << __FUNCTION__ << ": " << time.InMilliseconds();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ BeginStateTransition();
+
+ if (state_ == kError) {
+ error_cb_.Run(::media::PIPELINE_ERROR_ABORT);
+ CompleteStateTransition(kError);
+ return;
+ }
+
+#if defined(VIDEO_HOLE)
+ // Create a video hole frame just before starting playback.
+ // Note that instead of creating the video hole frame in Initialize(), we do
+ // it here because paint_cb_ (which eventually calls OnOpacityChanged)
+ // expects the current state to not be HaveNothing. And the place where
+ // the ready state is changed to HaveMetadata (OnPipelineMetadata) is
+ // right before the pipeline calls StartPlayingFrom (in
+ // Pipeline::StateTransitionTask).
+ if (!initial_video_hole_created_) {
+ initial_video_hole_created_ = true;
+ video_renderer_sink_->PaintFrameUsingOldRenderingPath(
+ ::media::VideoFrame::CreateHoleFrame(initial_natural_size_));
+ }
+#endif
+
+ {
+ base::AutoLock auto_lock(time_interpolator_lock_);
+ time_interpolator_.reset(
+ new ::media::TimeDeltaInterpolator(&default_tick_clock_));
+ time_interpolator_->SetPlaybackRate(playback_rate_);
+ time_interpolator_->SetBounds(time, time);
+ time_interpolator_->StartInterpolating();
+ }
+
+ received_audio_eos_ = false;
+ received_video_eos_ = false;
+
+ DCHECK_EQ(state_, kFlushed) << state_;
+ // Immediately update transition to playing.
+ // Error case will be handled on response from host.
+ media_pipeline_->StartPlayingFrom(time);
+ CompleteStateTransition(kPlaying);
+}
+
+void CmaRenderer::SetPlaybackRate(double playback_rate) {
+ CMALOG(kLogControl) << __FUNCTION__ << ": " << playback_rate;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_->SetPlaybackRate(playback_rate);
+ playback_rate_ = playback_rate;
+
+ {
+ base::AutoLock auto_lock(time_interpolator_lock_);
+ time_interpolator_->SetPlaybackRate(playback_rate);
+ }
+}
+
+void CmaRenderer::SetVolume(float volume) {
+ CMALOG(kLogControl) << __FUNCTION__ << ": " << volume;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ audio_pipeline_->SetVolume(volume);
+}
+
+base::TimeDelta CmaRenderer::GetMediaTime() {
+ base::AutoLock auto_lock(time_interpolator_lock_);
+ return time_interpolator_->GetInterpolatedTime();
+}
+
+bool CmaRenderer::HasAudio() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return has_audio_;
+}
+
+bool CmaRenderer::HasVideo() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return has_video_;
+}
+
+void CmaRenderer::SetCdm(::media::CdmContext* cdm_context,
+ const ::media::CdmAttachedCB& cdm_attached_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+#if defined(ENABLE_BROWSER_CDMS)
+ media_pipeline_->SetCdm(cdm_context->GetCdmId());
+#endif
+ cdm_attached_cb.Run(true);
+}
+
+void CmaRenderer::InitializeAudioPipeline() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kUninitialized) << state_;
+ DCHECK(!init_cb_.is_null());
+
+ ::media::PipelineStatusCB audio_initialization_done_cb =
+ ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnAudioPipelineInitializeDone, weak_this_));
+
+ ::media::DemuxerStream* stream =
+ demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO);
+ if (!stream) {
+ audio_initialization_done_cb.Run(::media::PIPELINE_OK);
+ return;
+ }
+
+ // Receive events from the audio pipeline.
+ AvPipelineClient av_pipeline_client;
+ av_pipeline_client.eos_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnEosReached, weak_this_, true));
+ av_pipeline_client.playback_error_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnError, weak_this_));
+ av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnStatisticsUpdated, weak_this_));
+ audio_pipeline_->SetClient(av_pipeline_client);
+
+ scoped_ptr<CodedFrameProvider> frame_provider(
+ new DemuxerStreamAdapter(
+ base::MessageLoopProxy::current(),
+ media_task_runner_factory_,
+ stream));
+
+ const ::media::AudioDecoderConfig& config = stream->audio_decoder_config();
+ if (config.codec() == ::media::kCodecAAC)
+ stream->EnableBitstreamConverter();
+
+ media_pipeline_->InitializeAudio(
+ config, frame_provider.Pass(), audio_initialization_done_cb);
+}
+
+void CmaRenderer::OnAudioPipelineInitializeDone(
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // OnError() may be fired at any time, even before initialization is complete.
+ if (state_ == kError)
+ return;
+
+ DCHECK_EQ(state_, kUninitialized) << state_;
+ DCHECK(!init_cb_.is_null());
+ if (status != ::media::PIPELINE_OK) {
+ base::ResetAndReturn(&init_cb_).Run(status);
+ return;
+ }
+ has_audio_ = true;
+
+ InitializeVideoPipeline();
+}
+
+void CmaRenderer::InitializeVideoPipeline() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kUninitialized) << state_;
+ DCHECK(!init_cb_.is_null());
+
+ ::media::PipelineStatusCB video_initialization_done_cb =
+ ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnVideoPipelineInitializeDone, weak_this_));
+
+ ::media::DemuxerStream* stream =
+ demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO);
+ if (!stream) {
+ video_initialization_done_cb.Run(::media::PIPELINE_OK);
+ return;
+ }
+
+ // Receive events from the video pipeline.
+ VideoPipelineClient client;
+ client.av_pipeline_client.eos_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnEosReached, weak_this_, false));
+ client.av_pipeline_client.playback_error_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnError, weak_this_));
+ client.av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnStatisticsUpdated, weak_this_));
+ client.natural_size_changed_cb = ::media::BindToCurrentLoop(
+ base::Bind(&CmaRenderer::OnNaturalSizeChanged, weak_this_));
+ video_pipeline_->SetClient(client);
+
+ scoped_ptr<CodedFrameProvider> frame_provider(
+ new DemuxerStreamAdapter(
+ base::MessageLoopProxy::current(),
+ media_task_runner_factory_,
+ stream));
+
+ const ::media::VideoDecoderConfig& config = stream->video_decoder_config();
+ if (config.codec() == ::media::kCodecH264)
+ stream->EnableBitstreamConverter();
+
+ initial_natural_size_ = config.natural_size();
+
+ media_pipeline_->InitializeVideo(
+ config,
+ frame_provider.Pass(),
+ video_initialization_done_cb);
+}
+
+void CmaRenderer::OnVideoPipelineInitializeDone(
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // OnError() may be fired at any time, even before initialization is complete.
+ if (state_ == kError)
+ return;
+
+ DCHECK_EQ(state_, kUninitialized) << state_;
+ DCHECK(!init_cb_.is_null());
+ if (status != ::media::PIPELINE_OK) {
+ base::ResetAndReturn(&init_cb_).Run(status);
+ return;
+ }
+ has_video_ = true;
+
+ CompleteStateTransition(kFlushed);
+ base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_OK);
+}
+
+void CmaRenderer::OnEosReached(bool is_audio) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CMALOG(kLogControl) << __FUNCTION__;
+ if (state_ != kPlaying) {
+ LOG(WARNING) << "Ignoring a late EOS event";
+ return;
+ }
+
+ if (is_audio) {
+ DCHECK(!received_audio_eos_);
+ received_audio_eos_ = true;
+ } else {
+ DCHECK(!received_video_eos_);
+ received_video_eos_ = true;
+ }
+
+ bool audio_finished = !has_audio_ || received_audio_eos_;
+ bool video_finished = !has_video_ || received_video_eos_;
+ if (audio_finished && video_finished)
+ ended_cb_.Run();
+}
+
+void CmaRenderer::OnStatisticsUpdated(
+ const ::media::PipelineStatistics& stats) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ statistics_cb_.Run(stats);
+}
+
+void CmaRenderer::OnNaturalSizeChanged(const gfx::Size& size) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+#if defined(VIDEO_HOLE)
+ video_renderer_sink_->PaintFrameUsingOldRenderingPath(
+ ::media::VideoFrame::CreateHoleFrame(size));
+#endif
+}
+
+void CmaRenderer::OnPlaybackTimeUpdated(
+ base::TimeDelta time,
+ base::TimeDelta max_time,
+ base::TimeTicks capture_time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (state_ != kPlaying) {
+ LOG(WARNING) << "Ignoring a late time update";
+ return;
+ }
+
+ // TODO(halliwell): arguably, TimeDeltaInterpolator::SetBounds should perform
+ // this calculation to avoid calling TimeTicks::Now twice (it's slower and has
+ // potential accuracy problems).
+ base::TimeDelta lower_bound =
+ std::min(max_time, time + base::TimeTicks::Now() - capture_time);
+
+ base::AutoLock auto_lock(time_interpolator_lock_);
+ time_interpolator_->SetBounds(lower_bound, max_time);
+}
+
+void CmaRenderer::OnBufferingNotification(
+ ::media::BufferingState buffering_state) {
+ CMALOG(kLogControl) << __FUNCTION__ << ": state=" << state_
+ << ", buffering=" << buffering_state;
+ // TODO(gunsch): WebMediaPlayerImpl currently only handles HAVE_ENOUGH while
+ // playing. See OnPipelineBufferingStateChanged, http://crbug.com/144683.
+ if (state_ != kPlaying) {
+ LOG(WARNING) << "Ignoring buffering notification in state: " << state_;
+ return;
+ }
+ if (buffering_state != ::media::BUFFERING_HAVE_ENOUGH) {
+ LOG(WARNING) << "Ignoring buffering notification during playing: "
+ << buffering_state;
+ return;
+ }
+ buffering_state_cb_.Run(buffering_state);
+}
+
+void CmaRenderer::OnFlushDone(::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (status != ::media::PIPELINE_OK) {
+ OnError(status);
+ return;
+ }
+
+ CompleteStateTransition(kFlushed);
+ base::ResetAndReturn(&flush_cb_).Run();
+}
+
+void CmaRenderer::OnError(::media::PipelineStatus error) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(::media::PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
+ LOG(ERROR) << "CMA error encountered: " << error;
+
+ State old_state = state_;
+ CompleteStateTransition(kError);
+
+ if (old_state != kError) {
+ if (!init_cb_.is_null()) {
+ base::ResetAndReturn(&init_cb_).Run(error);
+ return;
+ }
+ error_cb_.Run(error);
+ }
+
+ // After OnError() returns, the pipeline may destroy |this|.
+ if (!flush_cb_.is_null())
+ base::ResetAndReturn(&flush_cb_).Run();
+}
+
+void CmaRenderer::BeginStateTransition() {
+ DCHECK(!is_pending_transition_) << state_;
+ is_pending_transition_ = true;
+}
+
+void CmaRenderer::CompleteStateTransition(State new_state) {
+ state_ = new_state;
+ is_pending_transition_ = false;
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/filters/cma_renderer.h b/chromium/chromecast/media/cma/filters/cma_renderer.h
new file mode 100644
index 00000000000..d33699ea586
--- /dev/null
+++ b/chromium/chromecast/media/cma/filters/cma_renderer.h
@@ -0,0 +1,151 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_FILTERS_CMA_RENDERER_H_
+#define CHROMECAST_MEDIA_CMA_FILTERS_CMA_RENDERER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/default_tick_clock.h"
+#include "media/base/buffering_state.h"
+#include "media/base/renderer.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace media {
+class DemuxerStreamProvider;
+class TimeDeltaInterpolator;
+class VideoFrame;
+class VideoRendererSink;
+}
+
+namespace chromecast {
+namespace media {
+class AudioPipeline;
+class BalancedMediaTaskRunnerFactory;
+class MediaPipeline;
+class VideoPipeline;
+
+class CmaRenderer : public ::media::Renderer {
+ public:
+ CmaRenderer(scoped_ptr<MediaPipeline> media_pipeline,
+ ::media::VideoRendererSink* video_renderer_sink);
+ ~CmaRenderer() override;
+
+ // ::media::Renderer implementation:
+ void Initialize(
+ ::media::DemuxerStreamProvider* demuxer_stream_provider,
+ const ::media::PipelineStatusCB& init_cb,
+ const ::media::StatisticsCB& statistics_cb,
+ const ::media::BufferingStateCB& buffering_state_cb,
+ const base::Closure& ended_cb,
+ const ::media::PipelineStatusCB& error_cb,
+ const base::Closure& waiting_for_decryption_key_cb) override;
+ void Flush(const base::Closure& flush_cb) override;
+ void StartPlayingFrom(base::TimeDelta time) override;
+ void SetPlaybackRate(double playback_rate) override;
+ void SetVolume(float volume) override;
+ base::TimeDelta GetMediaTime() override;
+ bool HasAudio() override;
+ bool HasVideo() override;
+ void SetCdm(::media::CdmContext* cdm_context,
+ const ::media::CdmAttachedCB& cdm_attached_cb) override;
+
+ private:
+ enum State {
+ kUninitialized,
+ kPlaying,
+ kFlushed,
+ kError,
+ };
+
+ // Asynchronous initialization sequence. These four methods are invoked in
+ // the order below, with a successful initialization making it to
+ // OnVideoPipelineInitializeDone, regardless of which streams are present.
+ void InitializeAudioPipeline();
+ void OnAudioPipelineInitializeDone(::media::PipelineStatus status);
+ void InitializeVideoPipeline();
+ void OnVideoPipelineInitializeDone(::media::PipelineStatus status);
+
+ // Callbacks for AvPipelineClient.
+ void OnEosReached(bool is_audio);
+ void OnStatisticsUpdated(const ::media::PipelineStatistics& stats);
+ void OnNaturalSizeChanged(const gfx::Size& size);
+
+ // Callbacks for MediaPipelineClient.
+ void OnPlaybackTimeUpdated(base::TimeDelta time,
+ base::TimeDelta max_time,
+ base::TimeTicks capture_time);
+ void OnBufferingNotification(::media::BufferingState state);
+
+ void OnFlushDone(::media::PipelineStatus status);
+ void OnError(::media::PipelineStatus status);
+
+ // Begin a state transition.
+ // Return true if delayed because of a pending state transition.
+ void BeginStateTransition();
+ void CompleteStateTransition(State new_state);
+
+ base::ThreadChecker thread_checker_;
+
+ scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_;
+ scoped_ptr<MediaPipeline> media_pipeline_;
+ AudioPipeline* audio_pipeline_;
+ VideoPipeline* video_pipeline_;
+ ::media::VideoRendererSink* video_renderer_sink_;
+
+ ::media::DemuxerStreamProvider* demuxer_stream_provider_;
+
+ // Set of callbacks.
+ ::media::PipelineStatusCB init_cb_;
+ ::media::StatisticsCB statistics_cb_;
+ base::Closure ended_cb_;
+ ::media::PipelineStatusCB error_cb_;
+ ::media::BufferingStateCB buffering_state_cb_;
+ base::Closure flush_cb_;
+ base::Closure waiting_for_decryption_key_cb_;
+
+ // Renderer state.
+ // Used mostly for checking that transitions are correct.
+ State state_;
+ bool is_pending_transition_;
+
+ bool has_audio_;
+ bool has_video_;
+
+ bool received_audio_eos_;
+ bool received_video_eos_;
+
+ // Data members for helping the creation of the initial video hole frame.
+ gfx::Size initial_natural_size_;
+ bool initial_video_hole_created_;
+
+ // Lock protecting access to |time_interpolator_|.
+ base::Lock time_interpolator_lock_;
+
+ // base::TickClock used by |time_interpolator_|.
+ base::DefaultTickClock default_tick_clock_;
+
+ // Tracks the most recent media time update and provides interpolated values
+ // as playback progresses.
+ scoped_ptr< ::media::TimeDeltaInterpolator> time_interpolator_;
+
+ double playback_rate_;
+
+ base::WeakPtr<CmaRenderer> weak_this_;
+ base::WeakPtrFactory<CmaRenderer> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CmaRenderer);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_FILTERS_CMA_RENDERER_H_
diff --git a/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.cc b/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.cc
index db0d7b70ab2..c2fd5a47861 100644
--- a/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.cc
+++ b/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.cc
@@ -27,13 +27,13 @@ class DummyMediaTaskRunner : public MediaTaskRunner {
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
// MediaTaskRunner implementation.
- virtual bool PostMediaTask(
+ bool PostMediaTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta timestamp) override;
private:
- virtual ~DummyMediaTaskRunner();
+ ~DummyMediaTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> const task_runner_;
@@ -183,6 +183,13 @@ void DemuxerStreamAdapter::OnNewBuffer(
DCHECK_EQ(status, ::media::DemuxerStream::kOk);
+ if (input->end_of_stream()) {
+ // This stream has ended, its media time will stop increasing, but there
+ // might be other streams that are still playing. Remove the task runner of
+ // this stream to ensure other streams are not blocked waiting for this one.
+ ResetMediaTaskRunner();
+ }
+
// Updates the timestamp used for task scheduling.
if (!input->end_of_stream() &&
input->timestamp() != ::media::kNoTimestamp() &&
diff --git a/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.h b/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.h
index 7d8c8b33702..5e8d817b76c 100644
--- a/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.h
+++ b/chromium/chromecast/media/cma/filters/demuxer_stream_adapter.h
@@ -36,11 +36,11 @@ class DemuxerStreamAdapter : public CodedFrameProvider {
const scoped_refptr<BalancedMediaTaskRunnerFactory>&
media_task_runner_factory,
::media::DemuxerStream* demuxer_stream);
- virtual ~DemuxerStreamAdapter();
+ ~DemuxerStreamAdapter() override;
// CodedFrameProvider implementation.
- virtual void Read(const ReadCB& read_cb) override;
- virtual void Flush(const base::Closure& flush_cb) override;
+ void Read(const ReadCB& read_cb) override;
+ void Flush(const base::Closure& flush_cb) override;
private:
void ResetMediaTaskRunner();
diff --git a/chromium/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc b/chromium/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc
index bee63eb4d45..084acd7e3a4 100644
--- a/chromium/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc
+++ b/chromium/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc
@@ -41,15 +41,15 @@ class DummyDemuxerStream : public ::media::DemuxerStream {
DummyDemuxerStream(int cycle_count,
int delayed_frame_count,
const std::list<int>& config_idx);
- virtual ~DummyDemuxerStream();
+ ~DummyDemuxerStream() override;
// ::media::DemuxerStream implementation.
- virtual void Read(const ReadCB& read_cb) override;
- virtual ::media::AudioDecoderConfig audio_decoder_config() override;
- virtual ::media::VideoDecoderConfig video_decoder_config() override;
- virtual Type type() override;
- virtual bool SupportsConfigChanges() override;
- virtual ::media::VideoRotation video_rotation() override;
+ void Read(const ReadCB& read_cb) override;
+ ::media::AudioDecoderConfig audio_decoder_config() override;
+ ::media::VideoDecoderConfig video_decoder_config() override;
+ Type type() const override;
+ bool SupportsConfigChanges() override;
+ ::media::VideoRotation video_rotation() override;
bool has_pending_read() const {
return has_pending_read_;
@@ -127,7 +127,7 @@ void DummyDemuxerStream::Read(const ReadCB& read_cb) {
false);
}
-::media::DemuxerStream::Type DummyDemuxerStream::type() {
+::media::DemuxerStream::Type DummyDemuxerStream::type() const {
return VIDEO;
}
@@ -153,7 +153,7 @@ void DummyDemuxerStream::DoRead(const ReadCB& read_cb) {
class DemuxerStreamAdapterTest : public testing::Test {
public:
DemuxerStreamAdapterTest();
- virtual ~DemuxerStreamAdapterTest();
+ ~DemuxerStreamAdapterTest() override;
void Initialize(::media::DemuxerStream* demuxer_stream);
void Start();
@@ -232,7 +232,7 @@ void DemuxerStreamAdapterTest::OnNewFrame(
const ::media::AudioDecoderConfig& audio_config,
const ::media::VideoDecoderConfig& video_config) {
if (video_config.IsValidConfig()) {
- ASSERT_GT(config_idx_.size(), 0);
+ ASSERT_GT(config_idx_.size(), 0u);
ASSERT_EQ(frame_received_count_, config_idx_.front());
config_idx_.pop_front();
}
diff --git a/chromium/chromecast/media/cma/ipc/BUILD.gn b/chromium/chromecast/media/cma/ipc/BUILD.gn
new file mode 100644
index 00000000000..037b3bdd6a7
--- /dev/null
+++ b/chromium/chromecast/media/cma/ipc/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("ipc") {
+ sources = [
+ "media_memory_chunk.cc",
+ "media_memory_chunk.h",
+ "media_message.cc",
+ "media_message.h",
+ "media_message_fifo.cc",
+ "media_message_fifo.h",
+ "media_message_type.h",
+ ]
+
+ deps = [
+ "//base",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/cma/ipc/media_message_fifo.cc b/chromium/chromecast/media/cma/ipc/media_message_fifo.cc
index 9f8ad001dc8..5e4b239bc5d 100644
--- a/chromium/chromecast/media/cma/ipc/media_message_fifo.cc
+++ b/chromium/chromecast/media/cma/ipc/media_message_fifo.cc
@@ -60,12 +60,12 @@ class FifoOwnedMemory : public MediaMemoryChunk {
FifoOwnedMemory(void* data, size_t size,
const scoped_refptr<MediaMessageFlag>& flag,
const base::Closure& release_msg_cb);
- virtual ~FifoOwnedMemory();
+ ~FifoOwnedMemory() override;
// MediaMemoryChunk implementation.
- virtual void* data() const override { return data_; }
- virtual size_t size() const override { return size_; }
- virtual bool valid() const override { return flag_->IsValid(); }
+ void* data() const override { return data_; }
+ size_t size() const override { return size_; }
+ bool valid() const override { return flag_->IsValid(); }
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -133,7 +133,7 @@ MediaMessageFifo::MediaMessageFifo(
}
CMALOG(kLogControl)
<< "MediaMessageFifo:" << " init=" << init << " size=" << size_;
- CHECK_GT(size_, 0) << size_;
+ CHECK_GT(size_, 0u) << size_;
weak_this_ = weak_factory_.GetWeakPtr();
thread_checker_.DetachFromThread();
diff --git a/chromium/chromecast/media/cma/ipc/media_message_fifo.h b/chromium/chromecast/media/cma/ipc/media_message_fifo.h
index dcc60dbd60b..b20432b5b1f 100644
--- a/chromium/chromecast/media/cma/ipc/media_message_fifo.h
+++ b/chromium/chromecast/media/cma/ipc/media_message_fifo.h
@@ -82,7 +82,19 @@ class MediaMessageFlag;
//
//
class MediaMessageFifo {
+ private:
+ struct Descriptor {
+ size_t size;
+ size_t rd_offset;
+ size_t wr_offset;
+
+ // Ensure the first item has the same alignment as an int64.
+ int64 first_item;
+ };
+
public:
+ static const int kDescriptorSize = sizeof(Descriptor);
+
// Creates a media message fifo using |mem| as the underlying serialized
// structure.
// If |init| is true, the underlying fifo structure is initialized.
@@ -108,15 +120,6 @@ class MediaMessageFifo {
void Flush();
private:
- struct Descriptor {
- size_t size;
- size_t rd_offset;
- size_t wr_offset;
-
- // Ensure the first item has the same alignment as an int64.
- int64 first_item;
- };
-
// Add some accessors to ensure security on the browser process side.
size_t current_rd_offset() const;
size_t current_wr_offset() const;
@@ -174,7 +177,7 @@ class MediaMessageFifo {
typedef base::subtle::Atomic32 AtomicSize;
#elif SIZE_MAX == UINT64_MAX
typedef base::subtle::Atomic64 AtomicSize;
-#elif
+#else
#error "Unsupported size_t"
#endif
AtomicSize* rd_offset_;
diff --git a/chromium/chromecast/media/cma/ipc/media_message_fifo_unittest.cc b/chromium/chromecast/media/cma/ipc/media_message_fifo_unittest.cc
index bc04b70a0cc..ed758182ce4 100644
--- a/chromium/chromecast/media/cma/ipc/media_message_fifo_unittest.cc
+++ b/chromium/chromecast/media/cma/ipc/media_message_fifo_unittest.cc
@@ -22,11 +22,11 @@ class FifoMemoryChunk : public MediaMemoryChunk {
public:
FifoMemoryChunk(void* mem, size_t size)
: mem_(mem), size_(size) {}
- virtual ~FifoMemoryChunk() {}
+ ~FifoMemoryChunk() override {}
- virtual void* data() const override { return mem_; }
- virtual size_t size() const override { return size_; }
- virtual bool valid() const override { return true; }
+ void* data() const override { return mem_; }
+ size_t size() const override { return size_; }
+ bool valid() const override { return true; }
private:
void* mem_;
diff --git a/chromium/chromecast/media/cma/ipc/media_message_unittest.cc b/chromium/chromecast/media/cma/ipc/media_message_unittest.cc
index 6f34f3eaf89..cec0712cfaa 100644
--- a/chromium/chromecast/media/cma/ipc/media_message_unittest.cc
+++ b/chromium/chromecast/media/cma/ipc/media_message_unittest.cc
@@ -19,12 +19,12 @@ class ExternalMemoryBlock
public:
ExternalMemoryBlock(void* data, size_t size)
: data_(data), size_(size) {}
- virtual ~ExternalMemoryBlock() {}
+ ~ExternalMemoryBlock() override {}
// MediaMemoryChunk implementation.
- virtual void* data() const override { return data_; }
- virtual size_t size() const override { return size_; }
- virtual bool valid() const override { return true; }
+ void* data() const override { return data_; }
+ size_t size() const override { return size_; }
+ bool valid() const override { return true; }
private:
void* const data_;
diff --git a/chromium/chromecast/media/cma/ipc_streamer/BUILD.gn b/chromium/chromecast/media/cma/ipc_streamer/BUILD.gn
new file mode 100644
index 00000000000..aa87709333e
--- /dev/null
+++ b/chromium/chromecast/media/cma/ipc_streamer/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("ipc_streamer") {
+ sources = [
+ "audio_decoder_config_marshaller.cc",
+ "audio_decoder_config_marshaller.h",
+ "av_streamer_proxy.cc",
+ "av_streamer_proxy.h",
+ "coded_frame_provider_host.cc",
+ "coded_frame_provider_host.h",
+ "decoder_buffer_base_marshaller.cc",
+ "decoder_buffer_base_marshaller.h",
+ "decrypt_config_marshaller.cc",
+ "decrypt_config_marshaller.h",
+ "video_decoder_config_marshaller.cc",
+ "video_decoder_config_marshaller.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chromecast/media/cma/base",
+ "//media",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc b/chromium/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc
index 54a9e14ba07..c8720561c1a 100644
--- a/chromium/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc
+++ b/chromium/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc
@@ -33,11 +33,11 @@ class FifoMemoryChunk : public MediaMemoryChunk {
public:
FifoMemoryChunk(void* mem, size_t size)
: mem_(mem), size_(size) {}
- virtual ~FifoMemoryChunk() {}
+ ~FifoMemoryChunk() override {}
- virtual void* data() const override { return mem_; }
- virtual size_t size() const override { return size_; }
- virtual bool valid() const override { return true; }
+ void* data() const override { return mem_; }
+ size_t size() const override { return size_; }
+ bool valid() const override { return true; }
private:
void* mem_;
@@ -51,7 +51,7 @@ class FifoMemoryChunk : public MediaMemoryChunk {
class AvStreamerTest : public testing::Test {
public:
AvStreamerTest();
- virtual ~AvStreamerTest();
+ ~AvStreamerTest() override;
// Setups the test.
void Configure(
diff --git a/chromium/chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h b/chromium/chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h
index 9dc9471bc5b..738cc8bd769 100644
--- a/chromium/chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h
+++ b/chromium/chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h
@@ -25,11 +25,11 @@ class CodedFrameProviderHost : public CodedFrameProvider {
// during the whole lifetime of this object.
explicit CodedFrameProviderHost(
scoped_ptr<MediaMessageFifo> media_message_fifo);
- virtual ~CodedFrameProviderHost();
+ ~CodedFrameProviderHost() override;
// CodedFrameProvider implementation.
- virtual void Read(const ReadCB& read_cb) override;
- virtual void Flush(const base::Closure& flush_cb) override;
+ void Read(const ReadCB& read_cb) override;
+ void Flush(const base::Closure& flush_cb) override;
// Invoked when some data has been written into the fifo.
void OnFifoWriteEvent();
diff --git a/chromium/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc b/chromium/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc
index dc1f8f5714e..a377ae66337 100644
--- a/chromium/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc
+++ b/chromium/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc
@@ -24,15 +24,15 @@ class DecoderBufferFromMsg : public DecoderBufferBase {
void Initialize();
// DecoderBufferBase implementation.
- virtual base::TimeDelta timestamp() const override;
- virtual const uint8* data() const override;
- virtual uint8* writable_data() const override;
- virtual int data_size() const override;
- virtual const ::media::DecryptConfig* decrypt_config() const override;
- virtual bool end_of_stream() const override;
+ base::TimeDelta timestamp() const override;
+ const uint8* data() const override;
+ uint8* writable_data() const override;
+ size_t data_size() const override;
+ const ::media::DecryptConfig* decrypt_config() const override;
+ bool end_of_stream() const override;
private:
- virtual ~DecoderBufferFromMsg();
+ ~DecoderBufferFromMsg() override;
// Indicates whether this is an end of stream frame.
bool is_eos_;
@@ -44,7 +44,7 @@ class DecoderBufferFromMsg : public DecoderBufferBase {
scoped_ptr< ::media::DecryptConfig> decrypt_config_;
// Size of the frame.
- int data_size_;
+ size_t data_size_;
// Keeps the message since frame data is not copied.
scoped_ptr<MediaMessage> msg_;
@@ -55,8 +55,8 @@ class DecoderBufferFromMsg : public DecoderBufferBase {
DecoderBufferFromMsg::DecoderBufferFromMsg(
scoped_ptr<MediaMessage> msg)
- : msg_(msg.Pass()),
- is_eos_(true),
+ : is_eos_(true),
+ msg_(msg.Pass()),
data_(NULL) {
CHECK(msg_);
}
@@ -81,7 +81,7 @@ void DecoderBufferFromMsg::Initialize() {
decrypt_config_.reset(DecryptConfigMarshaller::Read(msg_.get()).release());
CHECK(msg_->ReadPod(&data_size_));
- CHECK_GT(data_size_, 0);
+ CHECK_GT(data_size_, 0u);
CHECK_LT(data_size_, kMaxFrameSize);
// Get a pointer to the frame data inside the message.
@@ -113,7 +113,7 @@ uint8* DecoderBufferFromMsg::writable_data() const {
return data_;
}
-int DecoderBufferFromMsg::data_size() const {
+size_t DecoderBufferFromMsg::data_size() const {
return data_size_;
}
diff --git a/chromium/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc b/chromium/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc
index 9e3de954ccb..72eacd6e9ce 100644
--- a/chromium/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc
+++ b/chromium/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc
@@ -20,9 +20,9 @@ const size_t kMaxSubsampleCount = 1024;
// static
void DecryptConfigMarshaller::Write(
const ::media::DecryptConfig& config, MediaMessage* msg) {
- CHECK_GT(config.key_id().size(), 0);
- CHECK_GT(config.iv().size(), 0);
- CHECK_GT(config.subsamples().size(), 0);
+ CHECK_GT(config.key_id().size(), 0u);
+ CHECK_GT(config.iv().size(), 0u);
+ CHECK_GT(config.subsamples().size(), 0u);
CHECK(msg->WritePod(config.key_id().size()));
CHECK(msg->WriteBuffer(config.key_id().data(), config.key_id().size()));
@@ -40,21 +40,21 @@ scoped_ptr< ::media::DecryptConfig> DecryptConfigMarshaller::Read(
MediaMessage* msg) {
size_t key_id_size = 0;
CHECK(msg->ReadPod(&key_id_size));
- CHECK_GT(key_id_size, 0);
+ CHECK_GT(key_id_size, 0u);
CHECK_LT(key_id_size, kMaxKeyIdSize);
scoped_ptr<char[]> key_id(new char[key_id_size]);
CHECK(msg->ReadBuffer(key_id.get(), key_id_size));
size_t iv_size = 0;
CHECK(msg->ReadPod(&iv_size));
- CHECK_GT(iv_size, 0);
+ CHECK_GT(iv_size, 0u);
CHECK_LT(iv_size, kMaxIvSize);
scoped_ptr<char[]> iv(new char[iv_size]);
CHECK(msg->ReadBuffer(iv.get(), iv_size));
size_t subsample_count = 0;
CHECK(msg->ReadPod(&subsample_count));
- CHECK_GT(subsample_count, 0);
+ CHECK_GT(subsample_count, 0u);
CHECK_LT(subsample_count, kMaxSubsampleCount);
std::vector< ::media::SubsampleEntry> subsamples(subsample_count);
for (size_t k = 0; k < subsample_count; k++) {
diff --git a/chromium/chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.cc b/chromium/chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.cc
index 645056ce22d..d6ec43e23b0 100644
--- a/chromium/chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.cc
+++ b/chromium/chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.cc
@@ -8,8 +8,8 @@
#include "base/logging.h"
#include "chromecast/media/cma/ipc/media_message.h"
#include "media/base/video_decoder_config.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
namespace chromecast {
namespace media {
diff --git a/chromium/chromecast/media/cma/pipeline/BUILD.gn b/chromium/chromecast/media/cma/pipeline/BUILD.gn
new file mode 100644
index 00000000000..f82a8d9a3f6
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/BUILD.gn
@@ -0,0 +1,44 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("pipeline") {
+ sources = [
+ "audio_pipeline.cc",
+ "audio_pipeline.h",
+ "audio_pipeline_impl.cc",
+ "audio_pipeline_impl.h",
+ "av_pipeline_client.cc",
+ "av_pipeline_client.h",
+ "av_pipeline_impl.cc",
+ "av_pipeline_impl.h",
+ "decrypt_util.cc",
+ "decrypt_util.h",
+ "load_type.h",
+ "media_pipeline.h",
+ "media_pipeline_client.cc",
+ "media_pipeline_client.h",
+ "media_pipeline_impl.cc",
+ "media_pipeline_impl.h",
+ "video_pipeline.cc",
+ "video_pipeline.h",
+ "video_pipeline_client.cc",
+ "video_pipeline_client.h",
+ "video_pipeline_impl.cc",
+ "video_pipeline_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chromecast/media/cma/backend",
+ "//chromecast/media/cma/base",
+ "//chromecast/media/base",
+ "//chromecast/media/cdm",
+ "//crypto",
+ "//crypto:platform",
+ "//media",
+ "//third_party/boringssl",
+ ]
+
+ configs += [ "//chromecast:config" ]
+}
diff --git a/chromium/chromecast/browser/webui/webui_cast_simple.cc b/chromium/chromecast/media/cma/pipeline/audio_pipeline.cc
index 255c1d8de26..7d98e09f2c4 100644
--- a/chromium/chromecast/browser/webui/webui_cast_simple.cc
+++ b/chromium/chromecast/media/cma/pipeline/audio_pipeline.cc
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chromecast/browser/webui/webui_cast.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline.h"
namespace chromecast {
-namespace shell {
+namespace media {
-void InitializeWebUI() {
- // Intentional no-op for public cast_shell build.
+AudioPipeline::AudioPipeline() {
}
-} // namespace shell
+AudioPipeline::~AudioPipeline() {
+}
+
+} // namespace media
} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/audio_pipeline.h b/chromium/chromecast/media/cma/pipeline/audio_pipeline.h
new file mode 100644
index 00000000000..d7284a10d7f
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/audio_pipeline.h
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_AUDIO_PIPELINE_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_AUDIO_PIPELINE_H_
+
+#include "base/macros.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+
+namespace chromecast {
+namespace media {
+
+class AudioPipeline {
+ public:
+ AudioPipeline();
+ virtual ~AudioPipeline();
+
+ // Set the audio client.
+ virtual void SetClient(const AvPipelineClient& client) = 0;
+
+ // Set the stream volume.
+ // - A value of 1.0 is the neutral value.
+ // - |volume|=0.0 mutes the stream.
+ virtual void SetVolume(float volume) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioPipeline);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_AUDIO_PIPELINE_H_
diff --git a/chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.cc b/chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
new file mode 100644
index 00000000000..3dbc028fc6c
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
@@ -0,0 +1,161 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
+
+#include "base/bind.h"
+#include "chromecast/media/cma/backend/audio_pipeline_device.h"
+#include "chromecast/media/cma/base/buffering_defs.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/media/cma/base/decoder_config_adapter.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
+#include "chromecast/public/media/decoder_config.h"
+#include "media/base/audio_decoder_config.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+const size_t kMaxAudioFrameSize = 32 * 1024;
+}
+
+AudioPipelineImpl::AudioPipelineImpl(AudioPipelineDevice* audio_device)
+ : audio_device_(audio_device),
+ weak_factory_(this) {
+ av_pipeline_impl_.reset(new AvPipelineImpl(
+ audio_device_,
+ base::Bind(&AudioPipelineImpl::OnUpdateConfig, base::Unretained(this))));
+ weak_this_ = weak_factory_.GetWeakPtr();
+}
+
+AudioPipelineImpl::~AudioPipelineImpl() {
+}
+
+void AudioPipelineImpl::SetCodedFrameProvider(
+ scoped_ptr<CodedFrameProvider> frame_provider) {
+ av_pipeline_impl_->SetCodedFrameProvider(
+ frame_provider.Pass(), kAppAudioBufferSize, kMaxAudioFrameSize);
+}
+
+void AudioPipelineImpl::SetClient(const AvPipelineClient& client) {
+ audio_client_ = client;
+ av_pipeline_impl_->SetClient(client);
+}
+
+bool AudioPipelineImpl::StartPlayingFrom(
+ base::TimeDelta time,
+ const scoped_refptr<BufferingState>& buffering_state) {
+ CMALOG(kLogControl) << "AudioPipelineImpl::StartPlayingFrom t0="
+ << time.InMilliseconds();
+
+ // Reset the pipeline statistics.
+ previous_stats_ = ::media::PipelineStatistics();
+
+ // Start playing.
+ if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError)
+ return false;
+ DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kFlushed);
+
+ if (!av_pipeline_impl_->StartPlayingFrom(time, buffering_state)) {
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError);
+ return false;
+ }
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kPlaying);
+
+ return true;
+}
+
+void AudioPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "AudioPipelineImpl::Flush";
+ if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kPlaying);
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushing);
+ av_pipeline_impl_->Flush(
+ base::Bind(&AudioPipelineImpl::OnFlushDone, weak_this_, status_cb));
+}
+
+void AudioPipelineImpl::OnFlushDone(
+ const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "AudioPipelineImpl::OnFlushDone";
+ if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
+ status_cb.Run(::media::PIPELINE_OK);
+}
+
+void AudioPipelineImpl::Stop() {
+ CMALOG(kLogControl) << "AudioPipelineImpl::Stop";
+ av_pipeline_impl_->Stop();
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kStopped);
+}
+
+void AudioPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
+ av_pipeline_impl_->SetCdm(media_keys);
+}
+
+void AudioPipelineImpl::Initialize(
+ const ::media::AudioDecoderConfig& audio_config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "AudioPipelineImpl::Initialize "
+ << audio_config.AsHumanReadableString();
+ if (frame_provider)
+ SetCodedFrameProvider(frame_provider.Pass());
+
+ if (!audio_device_->SetConfig(
+ DecoderConfigAdapter::ToCastAudioConfig(audio_config)) ||
+ !av_pipeline_impl_->Initialize()) {
+ status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
+ status_cb.Run(::media::PIPELINE_OK);
+}
+
+void AudioPipelineImpl::SetVolume(float volume) {
+ audio_device_->SetStreamVolumeMultiplier(volume);
+}
+
+void AudioPipelineImpl::OnUpdateConfig(
+ const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config) {
+ if (audio_config.IsValidConfig()) {
+ CMALOG(kLogControl) << "AudioPipelineImpl::OnUpdateConfig "
+ << audio_config.AsHumanReadableString();
+
+ bool success = audio_device_->SetConfig(
+ DecoderConfigAdapter::ToCastAudioConfig(audio_config));
+ if (!success && !audio_client_.playback_error_cb.is_null())
+ audio_client_.playback_error_cb.Run(::media::PIPELINE_ERROR_DECODE);
+ }
+}
+
+void AudioPipelineImpl::UpdateStatistics() {
+ if (audio_client_.statistics_cb.is_null())
+ return;
+
+ MediaComponentDevice::Statistics device_stats;
+ if (!audio_device_->GetStatistics(&device_stats))
+ return;
+
+ ::media::PipelineStatistics current_stats;
+ current_stats.audio_bytes_decoded = device_stats.decoded_bytes;
+
+ ::media::PipelineStatistics delta_stats;
+ delta_stats.audio_bytes_decoded =
+ current_stats.audio_bytes_decoded - previous_stats_.audio_bytes_decoded;
+
+ previous_stats_ = current_stats;
+
+ audio_client_.statistics_cb.Run(delta_stats);
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.h b/chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.h
new file mode 100644
index 00000000000..7d2e63a1314
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/audio_pipeline_impl.h
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BASE_AUDIO_PIPELINE_IMPL_H_
+#define CHROMECAST_MEDIA_CMA_BASE_AUDIO_PIPELINE_IMPL_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+
+namespace media {
+class AudioDecoderConfig;
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+class AudioPipelineDevice;
+class AvPipelineImpl;
+class BrowserCdmCast;
+class BufferingState;
+class CodedFrameProvider;
+
+class AudioPipelineImpl : public AudioPipeline {
+ public:
+ // |buffering_controller| can be NULL.
+ explicit AudioPipelineImpl(AudioPipelineDevice* audio_device);
+ ~AudioPipelineImpl() override;
+
+ // Input port of the pipeline.
+ void SetCodedFrameProvider(scoped_ptr<CodedFrameProvider> frame_provider);
+
+ // Provide the CDM to use to decrypt samples.
+ void SetCdm(BrowserCdmCast* media_keys);
+
+ // Functions to control the state of the audio pipeline.
+ void Initialize(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb);
+ bool StartPlayingFrom(base::TimeDelta time,
+ const scoped_refptr<BufferingState>& buffering_state);
+ void Flush(const ::media::PipelineStatusCB& status_cb);
+ void Stop();
+
+ // Update the playback statistics for this audio stream.
+ void UpdateStatistics();
+
+ // AudioPipeline implementation.
+ void SetClient(const AvPipelineClient& client) override;
+ void SetVolume(float volume) override;
+
+ private:
+ void OnFlushDone(const ::media::PipelineStatusCB& status_cb);
+ void OnUpdateConfig(const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config);
+
+ AudioPipelineDevice* audio_device_;
+
+ scoped_ptr<AvPipelineImpl> av_pipeline_impl_;
+ AvPipelineClient audio_client_;
+
+ ::media::PipelineStatistics previous_stats_;
+
+ base::WeakPtr<AudioPipelineImpl> weak_this_;
+ base::WeakPtrFactory<AudioPipelineImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioPipelineImpl);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BASE_AUDIO_PIPELINE_IMPL_H_
diff --git a/chromium/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc b/chromium/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
new file mode 100644
index 00000000000..9c17c7b2330
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
@@ -0,0 +1,211 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
+#include "chromecast/media/cma/backend/audio_pipeline_device.h"
+#include "chromecast/media/cma/backend/media_clock_device.h"
+#include "chromecast/media/cma/backend/media_pipeline_device.h"
+#include "chromecast/media/cma/backend/media_pipeline_device_fake.h"
+#include "chromecast/media/cma/base/buffering_controller.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_impl.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
+#include "chromecast/media/cma/test/frame_generator_for_test.h"
+#include "chromecast/media/cma/test/mock_frame_provider.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/buffers.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/video_decoder_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace media {
+
+class AudioVideoPipelineImplTest : public testing::Test {
+ public:
+ AudioVideoPipelineImplTest();
+ ~AudioVideoPipelineImplTest() override;
+
+ void Initialize(const base::Closure& done_cb,
+ ::media::PipelineStatus status,
+ bool is_audio);
+ void StartPlaying(const base::Closure& done_cb,
+ ::media::PipelineStatus status);
+
+ void Flush(const base::Closure& done_cb, ::media::PipelineStatus status);
+ void Stop(const base::Closure& done_cb, ::media::PipelineStatus status);
+
+ void OnEos();
+
+ base::Closure task_after_eos_cb_;
+
+ private:
+ scoped_ptr<MediaPipelineImpl> media_pipeline_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioVideoPipelineImplTest);
+};
+
+AudioVideoPipelineImplTest::AudioVideoPipelineImplTest()
+ : media_pipeline_(new MediaPipelineImpl()) {
+ scoped_ptr<MediaPipelineDevice> media_pipeline_device(
+ new MediaPipelineDeviceFake());
+ media_pipeline_->Initialize(kLoadTypeURL, media_pipeline_device.Pass());
+ media_pipeline_->SetPlaybackRate(1.0);
+}
+
+AudioVideoPipelineImplTest::~AudioVideoPipelineImplTest() {
+}
+
+void AudioVideoPipelineImplTest::Initialize(
+ const base::Closure& done_cb,
+ ::media::PipelineStatus status,
+ bool is_audio) {
+ if (is_audio) {
+ AvPipelineClient client;
+ client.eos_cb =
+ base::Bind(&AudioVideoPipelineImplTest::OnEos, base::Unretained(this));
+ media_pipeline_->GetAudioPipeline()->SetClient(client);
+ } else {
+ VideoPipelineClient client;
+ client.av_pipeline_client.eos_cb =
+ base::Bind(&AudioVideoPipelineImplTest::OnEos, base::Unretained(this));
+ media_pipeline_->GetVideoPipeline()->SetClient(client);
+ }
+
+ ::media::AudioDecoderConfig audio_config(
+ ::media::kCodecMP3,
+ ::media::kSampleFormatS16,
+ ::media::CHANNEL_LAYOUT_STEREO,
+ 44100,
+ NULL, 0, false);
+ ::media::VideoDecoderConfig video_config(
+ ::media::kCodecH264,
+ ::media::H264PROFILE_MAIN,
+ ::media::VideoFrame::I420,
+ gfx::Size(640, 480),
+ gfx::Rect(0, 0, 640, 480),
+ gfx::Size(640, 480),
+ NULL, 0, false);
+
+ // Frame generation on the producer side.
+ std::vector<FrameGeneratorForTest::FrameSpec> frame_specs;
+ frame_specs.resize(100);
+ for (size_t k = 0; k < frame_specs.size() - 1; k++) {
+ frame_specs[k].has_config = (k == 0);
+ frame_specs[k].timestamp = base::TimeDelta::FromMilliseconds(40) * k;
+ frame_specs[k].size = 512;
+ frame_specs[k].has_decrypt_config = false;
+ }
+ frame_specs[frame_specs.size() - 1].is_eos = true;
+
+ scoped_ptr<FrameGeneratorForTest> frame_generator_provider(
+ new FrameGeneratorForTest(frame_specs));
+ bool provider_delayed_pattern[] = { true, false };
+ scoped_ptr<MockFrameProvider> frame_provider(new MockFrameProvider());
+ frame_provider->Configure(
+ std::vector<bool>(
+ provider_delayed_pattern,
+ provider_delayed_pattern + arraysize(provider_delayed_pattern)),
+ frame_generator_provider.Pass());
+
+ ::media::PipelineStatusCB next_task =
+ base::Bind(&AudioVideoPipelineImplTest::StartPlaying,
+ base::Unretained(this),
+ done_cb);
+
+ scoped_ptr<CodedFrameProvider> frame_provider_base(frame_provider.release());
+ base::Closure task = is_audio ?
+ base::Bind(&MediaPipeline::InitializeAudio,
+ base::Unretained(media_pipeline_.get()),
+ audio_config,
+ base::Passed(&frame_provider_base),
+ next_task) :
+ base::Bind(&MediaPipeline::InitializeVideo,
+ base::Unretained(media_pipeline_.get()),
+ video_config,
+ base::Passed(&frame_provider_base),
+ next_task);
+
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, task);
+}
+
+void AudioVideoPipelineImplTest::StartPlaying(
+ const base::Closure& done_cb, ::media::PipelineStatus status) {
+ base::TimeDelta start_time = base::TimeDelta::FromMilliseconds(0);
+
+ media_pipeline_->StartPlayingFrom(start_time);
+ if (!done_cb.is_null())
+ done_cb.Run();
+}
+
+void AudioVideoPipelineImplTest::OnEos() {
+ task_after_eos_cb_.Run();
+}
+
+void AudioVideoPipelineImplTest::Flush(
+ const base::Closure& done_cb, ::media::PipelineStatus status) {
+ ::media::PipelineStatusCB next_task =
+ base::Bind(&AudioVideoPipelineImplTest::Stop, base::Unretained(this),
+ done_cb);
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipeline::Flush,
+ base::Unretained(media_pipeline_.get()),
+ next_task));
+}
+
+void AudioVideoPipelineImplTest::Stop(
+ const base::Closure& done_cb, ::media::PipelineStatus status) {
+ media_pipeline_->Stop();
+ if (!done_cb.is_null())
+ done_cb.Run();
+ base::MessageLoop::current()->QuitWhenIdle();
+}
+
+
+TEST_F(AudioVideoPipelineImplTest, AudioFullCycleInitToStop) {
+ bool is_audio = true;
+ task_after_eos_cb_ = base::Bind(
+ &AudioVideoPipelineImplTest::Flush, base::Unretained(this),
+ base::Closure(), ::media::PIPELINE_OK);
+
+ scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+ message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioVideoPipelineImplTest::Initialize,
+ base::Unretained(this),
+ base::Closure(),
+ ::media::PIPELINE_OK, is_audio));
+ message_loop->Run();
+};
+
+TEST_F(AudioVideoPipelineImplTest, VideoFullCycleInitToStop) {
+ bool is_audio = false;
+ task_after_eos_cb_ = base::Bind(
+ &AudioVideoPipelineImplTest::Flush, base::Unretained(this),
+ base::Closure(), ::media::PIPELINE_OK);
+
+ scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+ message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioVideoPipelineImplTest::Initialize,
+ base::Unretained(this),
+ base::Closure(),
+ ::media::PIPELINE_OK, is_audio));
+ message_loop->Run();
+};
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/av_pipeline_client.cc b/chromium/chromecast/media/cma/pipeline/av_pipeline_client.cc
new file mode 100644
index 00000000000..1845c6cc5c1
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/av_pipeline_client.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+
+namespace chromecast {
+namespace media {
+
+AvPipelineClient::AvPipelineClient() {
+}
+
+AvPipelineClient::~AvPipelineClient() {
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/av_pipeline_client.h b/chromium/chromecast/media/cma/pipeline/av_pipeline_client.h
new file mode 100644
index 00000000000..692871603d7
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/av_pipeline_client.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_AV_PIPELINE_CLIENT_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_AV_PIPELINE_CLIENT_H_
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "media/base/pipeline_status.h"
+
+namespace chromecast {
+namespace media {
+
+struct AvPipelineClient {
+ typedef base::Callback<void(
+ base::TimeDelta, base::TimeDelta, base::TimeTicks)> TimeUpdateCB;
+
+ AvPipelineClient();
+ ~AvPipelineClient();
+
+ // End of stream notification.
+ base::Closure eos_cb;
+
+ // Asynchronous playback error notification.
+ ::media::PipelineStatusCB playback_error_cb;
+
+ // Callback used to report the playback statistics.
+ ::media::StatisticsCB statistics_cb;
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_AV_PIPELINE_CLIENT_H_
diff --git a/chromium/chromecast/media/cma/pipeline/av_pipeline_impl.cc b/chromium/chromecast/media/cma/pipeline/av_pipeline_impl.cc
new file mode 100644
index 00000000000..9ff88e99225
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/av_pipeline_impl.cc
@@ -0,0 +1,387 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/string_number_conversions.h"
+#include "chromecast/media/base/decrypt_context.h"
+#include "chromecast/media/cdm/browser_cdm_cast.h"
+#include "chromecast/media/cma/backend/media_clock_device.h"
+#include "chromecast/media/cma/backend/media_component_device.h"
+#include "chromecast/media/cma/base/buffering_frame_provider.h"
+#include "chromecast/media/cma/base/buffering_state.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/pipeline/decrypt_util.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/decrypt_config.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+const int kNoCallbackId = -1;
+
+} // namespace
+
+AvPipelineImpl::AvPipelineImpl(
+ MediaComponentDevice* media_component_device,
+ const UpdateConfigCB& update_config_cb)
+ : update_config_cb_(update_config_cb),
+ media_component_device_(media_component_device),
+ state_(kUninitialized),
+ buffered_time_(::media::kNoTimestamp()),
+ playable_buffered_time_(::media::kNoTimestamp()),
+ enable_feeding_(false),
+ pending_read_(false),
+ pending_push_(false),
+ enable_time_update_(false),
+ pending_time_update_task_(false),
+ media_keys_(NULL),
+ media_keys_callback_id_(kNoCallbackId),
+ weak_factory_(this) {
+ DCHECK(media_component_device);
+ weak_this_ = weak_factory_.GetWeakPtr();
+ thread_checker_.DetachFromThread();
+}
+
+AvPipelineImpl::~AvPipelineImpl() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_component_device_->SetClient(MediaComponentDevice::Client());
+
+ if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
+ media_keys_->UnregisterPlayer(media_keys_callback_id_);
+}
+
+void AvPipelineImpl::TransitionToState(State state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ state_ = state;
+}
+
+void AvPipelineImpl::SetCodedFrameProvider(
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ size_t max_buffer_size,
+ size_t max_frame_size) {
+ DCHECK_EQ(state_, kUninitialized);
+ DCHECK(frame_provider);
+
+ // Wrap the incoming frame provider to add some buffering capabilities.
+ frame_provider_.reset(
+ new BufferingFrameProvider(
+ frame_provider.Pass(),
+ max_buffer_size,
+ max_frame_size,
+ base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_)));
+}
+
+void AvPipelineImpl::SetClient(const AvPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kUninitialized);
+ client_ = client;
+}
+
+bool AvPipelineImpl::Initialize() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kUninitialized);
+
+ MediaComponentDevice::Client client;
+ client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, weak_this_);
+ media_component_device_->SetClient(client);
+ if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle))
+ return false;
+
+ return true;
+}
+
+bool AvPipelineImpl::StartPlayingFrom(
+ base::TimeDelta time,
+ const scoped_refptr<BufferingState>& buffering_state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kFlushed);
+
+ // Media time where rendering should start
+ // and switch to a state where the audio device accepts incoming buffers.
+ if (!media_component_device_->SetStartPts(time) ||
+ !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) {
+ return false;
+ }
+
+ // Buffering related initialization.
+ DCHECK(frame_provider_);
+ buffering_state_ = buffering_state;
+ if (buffering_state_.get())
+ buffering_state_->SetMediaTime(time);
+
+ if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning))
+ return false;
+
+ // Start feeding the pipeline.
+ enable_feeding_ = true;
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
+
+ return true;
+}
+
+void AvPipelineImpl::Flush(const base::Closure& done_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, kFlushing);
+ DCHECK_EQ(
+ media_component_device_->GetState(), MediaComponentDevice::kStateRunning);
+ // Note: returning to idle state aborts any pending frame push.
+ media_component_device_->SetState(MediaComponentDevice::kStateIdle);
+ pending_push_ = false;
+
+ // Break the feeding loop.
+ enable_feeding_ = false;
+
+ // Remove any pending buffer.
+ pending_buffer_ = scoped_refptr<DecoderBufferBase>();
+
+ // Finally, remove any frames left in the frame provider.
+ pending_read_ = false;
+ buffered_time_ = ::media::kNoTimestamp();
+ playable_buffered_time_ = ::media::kNoTimestamp();
+ non_playable_frames_.clear();
+ frame_provider_->Flush(done_cb);
+}
+
+void AvPipelineImpl::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Stop can be called from any state.
+ if (state_ == kUninitialized || state_ == kStopped)
+ return;
+
+ // Stop feeding the pipeline.
+ enable_feeding_ = false;
+
+ // Release hardware resources on Stop.
+ if (media_component_device_->GetState() ==
+ MediaComponentDevice::kStatePaused ||
+ media_component_device_->GetState() ==
+ MediaComponentDevice::kStateRunning) {
+ media_component_device_->SetState(MediaComponentDevice::kStateIdle);
+ }
+ if (media_component_device_->GetState() == MediaComponentDevice::kStateIdle) {
+ media_component_device_->SetState(
+ MediaComponentDevice::kStateUninitialized);
+ }
+}
+
+void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(media_keys);
+
+ if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
+ media_keys_->UnregisterPlayer(media_keys_callback_id_);
+
+ media_keys_ = media_keys;
+ media_keys_callback_id_ = media_keys_->RegisterPlayer(
+ base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_),
+ base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_));
+}
+
+void AvPipelineImpl::OnEos() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CMALOG(kLogControl) << __FUNCTION__;
+ if (state_ != kPlaying)
+ return;
+
+ if (!client_.eos_cb.is_null())
+ client_.eos_cb.Run();
+}
+
+void AvPipelineImpl::FetchBufferIfNeeded() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!enable_feeding_)
+ return;
+
+ if (pending_read_ || pending_buffer_.get())
+ return;
+
+ pending_read_ = true;
+ frame_provider_->Read(
+ base::Bind(&AvPipelineImpl::OnNewFrame, weak_this_));
+}
+
+void AvPipelineImpl::OnNewFrame(
+ const scoped_refptr<DecoderBufferBase>& buffer,
+ const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ pending_read_ = false;
+
+ if (audio_config.IsValidConfig() || video_config.IsValidConfig())
+ update_config_cb_.Run(audio_config, video_config);
+
+ pending_buffer_ = buffer;
+ ProcessPendingBuffer();
+
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
+}
+
+void AvPipelineImpl::ProcessPendingBuffer() {
+ if (!enable_feeding_)
+ return;
+
+ // Initiate a read if there isn't already one.
+ if (!pending_buffer_.get() && !pending_read_) {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
+ return;
+ }
+
+ if (!pending_buffer_.get() || pending_push_)
+ return;
+
+ // Break the feeding loop when the end of stream is reached.
+ if (pending_buffer_->end_of_stream()) {
+ CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding";
+ enable_feeding_ = false;
+ }
+
+ scoped_refptr<DecryptContext> decrypt_context;
+ if (!pending_buffer_->end_of_stream() &&
+ pending_buffer_->decrypt_config()) {
+ // Verify that CDM has the key ID.
+ // Should not send the frame if the key ID is not available yet.
+ std::string key_id(pending_buffer_->decrypt_config()->key_id());
+ if (!media_keys_) {
+ CMALOG(kLogControl) << "No CDM for frame: pts="
+ << pending_buffer_->timestamp().InMilliseconds();
+ return;
+ }
+ decrypt_context = media_keys_->GetDecryptContext(key_id);
+ if (!decrypt_context.get()) {
+ CMALOG(kLogControl) << "frame(pts="
+ << pending_buffer_->timestamp().InMilliseconds()
+ << "): waiting for key id "
+ << base::HexEncode(&key_id[0], key_id.size());
+ return;
+ }
+
+ // If we do have the clear key, decrypt the pending buffer
+ // and reset the decryption context (not needed anymore).
+ crypto::SymmetricKey* key = decrypt_context->GetKey();
+ if (key != NULL) {
+ pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key);
+ decrypt_context = scoped_refptr<DecryptContext>();
+ }
+ }
+
+ if (!pending_buffer_->end_of_stream() && buffering_state_.get()) {
+ base::TimeDelta timestamp = pending_buffer_->timestamp();
+ if (timestamp != ::media::kNoTimestamp())
+ buffering_state_->SetMaxRenderingTime(timestamp);
+ }
+
+ MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame(
+ decrypt_context,
+ pending_buffer_,
+ base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_));
+ pending_buffer_ = scoped_refptr<DecoderBufferBase>();
+
+ pending_push_ = (status == MediaComponentDevice::kFramePending);
+ if (!pending_push_)
+ OnFramePushed(status);
+}
+
+void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ pending_push_ = false;
+ if (status == MediaComponentDevice::kFrameFailed) {
+ LOG(WARNING) << "AvPipelineImpl: PushFrame failed";
+ enable_feeding_ = false;
+ state_ = kError;
+ return;
+ }
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_));
+}
+
+void AvPipelineImpl::OnCdmStateChanged() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Update the buffering state if needed.
+ if (buffering_state_.get())
+ UpdatePlayableFrames();
+
+ // Process the pending buffer in case the CDM now has the frame key id.
+ ProcessPendingBuffer();
+}
+
+void AvPipelineImpl::OnCdmDestroyed() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_keys_ = NULL;
+}
+
+void AvPipelineImpl::OnFrameBuffered(
+ const scoped_refptr<DecoderBufferBase>& buffer,
+ bool is_at_max_capacity) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!buffering_state_.get())
+ return;
+
+ if (!buffer->end_of_stream() &&
+ (buffered_time_ == ::media::kNoTimestamp() ||
+ buffered_time_ < buffer->timestamp())) {
+ buffered_time_ = buffer->timestamp();
+ }
+
+ if (is_at_max_capacity)
+ buffering_state_->NotifyMaxCapacity(buffered_time_);
+
+ // No need to update the list of playable frames,
+ // if we are already blocking on a frame.
+ bool update_playable_frames = non_playable_frames_.empty();
+ non_playable_frames_.push_back(buffer);
+ if (update_playable_frames)
+ UpdatePlayableFrames();
+}
+
+void AvPipelineImpl::UpdatePlayableFrames() {
+ while (!non_playable_frames_.empty()) {
+ const scoped_refptr<DecoderBufferBase>& non_playable_frame =
+ non_playable_frames_.front();
+
+ if (non_playable_frame->end_of_stream()) {
+ buffering_state_->NotifyEos();
+ } else {
+ const ::media::DecryptConfig* decrypt_config =
+ non_playable_frame->decrypt_config();
+ if (decrypt_config &&
+ !(media_keys_ &&
+ media_keys_->GetDecryptContext(decrypt_config->key_id()).get())) {
+ // The frame is still not playable. All the following are thus not
+ // playable.
+ break;
+ }
+
+ if (playable_buffered_time_ == ::media::kNoTimestamp() ||
+ playable_buffered_time_ < non_playable_frame->timestamp()) {
+ playable_buffered_time_ = non_playable_frame->timestamp();
+ buffering_state_->SetBufferedTime(playable_buffered_time_);
+ }
+ }
+
+ // The frame is playable: remove it from the list of non playable frames.
+ non_playable_frames_.pop_front();
+ }
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/av_pipeline_impl.h b/chromium/chromecast/media/cma/pipeline/av_pipeline_impl.h
new file mode 100644
index 00000000000..20b3fc4feda
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/av_pipeline_impl.h
@@ -0,0 +1,172 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BASE_AV_PIPELINE_IMPL_H_
+#define CHROMECAST_MEDIA_CMA_BASE_AV_PIPELINE_IMPL_H_
+
+#include <list>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/media/cma/backend/media_component_device.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+
+namespace media {
+class AudioDecoderConfig;
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+class BrowserCdmCast;
+class BufferingFrameProvider;
+class BufferingState;
+class CodedFrameProvider;
+class DecoderBufferBase;
+class MediaComponentDevice;
+
+class AvPipelineImpl {
+ public:
+ // Pipeline states.
+ enum State {
+ kUninitialized,
+ kPlaying,
+ kFlushing,
+ kFlushed,
+ kStopped,
+ kError,
+ };
+
+ typedef base::Callback<
+ void(const ::media::AudioDecoderConfig&,
+ const ::media::VideoDecoderConfig&)> UpdateConfigCB;
+
+ AvPipelineImpl(
+ MediaComponentDevice* media_component_device,
+ const UpdateConfigCB& update_config_cb);
+ ~AvPipelineImpl();
+
+ // Setting the frame provider or the client must be done in the
+ // |kUninitialized| state.
+ void SetCodedFrameProvider(scoped_ptr<CodedFrameProvider> frame_provider,
+ size_t max_buffer_size,
+ size_t max_frame_size);
+ void SetClient(const AvPipelineClient& client);
+
+ // Initialize the pipeline.
+ bool Initialize();
+
+ // Setup the pipeline and ensure samples are available for the given media
+ // time, then start rendering samples.
+ bool StartPlayingFrom(base::TimeDelta time,
+ const scoped_refptr<BufferingState>& buffering_state);
+
+ // Flush any remaining samples in the pipeline.
+ // Invoke |done_cb| when flush is completed.
+ void Flush(const base::Closure& done_cb);
+
+ // Tear down the pipeline and release the hardware resources.
+ void Stop();
+
+ State GetState() const { return state_; }
+ void TransitionToState(State state);
+
+ void SetCdm(BrowserCdmCast* media_keys);
+
+ private:
+ // Callback invoked when the CDM state has changed in a way that might
+ // impact media playback.
+ void OnCdmStateChange();
+
+ // Callback invoked when playback has reached the end of stream.
+ void OnEos();
+
+ // Feed the pipeline, getting the frames from |frame_provider_|.
+ void FetchBufferIfNeeded();
+
+ // Callback invoked when receiving a new frame from |frame_provider_|.
+ void OnNewFrame(const scoped_refptr<DecoderBufferBase>& buffer,
+ const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config);
+
+ // Process a pending buffer.
+ void ProcessPendingBuffer();
+
+ void OnFramePushed(MediaComponentDevice::FrameStatus status);
+
+ // Callbacks:
+ // - when BrowserCdm updated its state.
+ // - when BrowserCdm has been destroyed.
+ void OnCdmStateChanged();
+ void OnCdmDestroyed();
+
+ // Callback invoked when a frame has been buffered by |frame_provider_|
+ // which is a BufferingFrameProvider.
+ void OnFrameBuffered(const scoped_refptr<DecoderBufferBase>& buffer,
+ bool is_at_max_capacity);
+ void UpdatePlayableFrames();
+
+ base::ThreadChecker thread_checker_;
+
+ UpdateConfigCB update_config_cb_;
+
+ AvPipelineClient client_;
+
+ // Backends.
+ MediaComponentDevice* media_component_device_;
+
+ // AV pipeline state.
+ State state_;
+
+ // Buffering state.
+ // Can be NULL if there is no buffering strategy.
+ scoped_refptr<BufferingState> buffering_state_;
+
+ // |buffered_time_| is the maximum timestamp of buffered frames.
+ // |playable_buffered_time_| is the maximum timestamp of buffered and
+ // playable frames (i.e. the key id is available for those frames).
+ base::TimeDelta buffered_time_;
+ base::TimeDelta playable_buffered_time_;
+
+ // List of frames buffered but not playable right away due to a missing
+ // key id.
+ std::list<scoped_refptr<DecoderBufferBase> > non_playable_frames_;
+
+ // Buffer provider.
+ scoped_ptr<BufferingFrameProvider> frame_provider_;
+
+ // Indicate whether the frame fetching process is active.
+ bool enable_feeding_;
+
+ // Indicate whether there is a pending buffer read.
+ bool pending_read_;
+
+ // Pending buffer.
+ scoped_refptr<DecoderBufferBase> pending_buffer_;
+
+ // Indicate if there is a frame being pushed to the audio device.
+ bool pending_push_;
+
+ // The media time is retrieved at regular intervals.
+ // Indicate whether time update is enabled.
+ bool enable_time_update_;
+ bool pending_time_update_task_;
+
+ // Decryption keys, if available.
+ BrowserCdmCast* media_keys_;
+ int media_keys_callback_id_;
+
+ base::WeakPtr<AvPipelineImpl> weak_this_;
+ base::WeakPtrFactory<AvPipelineImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AvPipelineImpl);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BASE_AV_PIPELINE_IMPL_H_
diff --git a/chromium/chromecast/media/cma/pipeline/decrypt_util.cc b/chromium/chromecast/media/cma/pipeline/decrypt_util.cc
new file mode 100644
index 00000000000..1f1fbe85c62
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/decrypt_util.cc
@@ -0,0 +1,128 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/decrypt_util.h"
+
+#include <openssl/aes.h>
+#include <string>
+
+#include "base/logging.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "crypto/symmetric_key.h"
+#include "media/base/decrypt_config.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+class DecoderBufferClear : public DecoderBufferBase {
+ public:
+ explicit DecoderBufferClear(const scoped_refptr<DecoderBufferBase>& buffer);
+
+ // DecoderBufferBase implementation.
+ base::TimeDelta timestamp() const override;
+ const uint8* data() const override;
+ uint8* writable_data() const override;
+ size_t data_size() const override;
+ const ::media::DecryptConfig* decrypt_config() const override;
+ bool end_of_stream() const override;
+
+ private:
+ ~DecoderBufferClear() override;
+
+ scoped_refptr<DecoderBufferBase> const buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecoderBufferClear);
+};
+
+DecoderBufferClear::DecoderBufferClear(
+ const scoped_refptr<DecoderBufferBase>& buffer)
+ : buffer_(buffer) {
+}
+
+DecoderBufferClear::~DecoderBufferClear() {
+}
+
+base::TimeDelta DecoderBufferClear::timestamp() const {
+ return buffer_->timestamp();
+}
+
+const uint8* DecoderBufferClear::data() const {
+ return buffer_->data();
+}
+
+uint8* DecoderBufferClear::writable_data() const {
+ return buffer_->writable_data();
+}
+
+size_t DecoderBufferClear::data_size() const {
+ return buffer_->data_size();
+}
+
+const ::media::DecryptConfig* DecoderBufferClear::decrypt_config() const {
+ // Buffer is clear so no decryption info.
+ return NULL;
+}
+
+bool DecoderBufferClear::end_of_stream() const {
+ return buffer_->end_of_stream();
+}
+
+} // namespace
+
+scoped_refptr<DecoderBufferBase> DecryptDecoderBuffer(
+ const scoped_refptr<DecoderBufferBase>& buffer,
+ crypto::SymmetricKey* key) {
+ if (buffer->end_of_stream())
+ return buffer;
+
+ const ::media::DecryptConfig* decrypt_config = buffer->decrypt_config();
+ if (!decrypt_config || decrypt_config->iv().size() == 0)
+ return buffer;
+
+ // Get the key.
+ std::string raw_key;
+ if (!key->GetRawKey(&raw_key)) {
+ LOG(ERROR) << "Failed to get the underlying AES key";
+ return buffer;
+ }
+ DCHECK_EQ(static_cast<int>(raw_key.length()), AES_BLOCK_SIZE);
+ const uint8* key_u8 = reinterpret_cast<const uint8*>(raw_key.data());
+ AES_KEY aes_key;
+ if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) {
+ LOG(ERROR) << "Failed to set the AES key";
+ return buffer;
+ }
+
+ // Get the IV.
+ uint8 aes_iv[AES_BLOCK_SIZE];
+ DCHECK_EQ(static_cast<int>(decrypt_config->iv().length()),
+ AES_BLOCK_SIZE);
+ memcpy(aes_iv, decrypt_config->iv().data(), AES_BLOCK_SIZE);
+
+ // Decryption state.
+ unsigned int encrypted_byte_offset = 0;
+ uint8 ecount_buf[AES_BLOCK_SIZE];
+
+ // Perform the decryption.
+ const std::vector< ::media::SubsampleEntry>& subsamples =
+ decrypt_config->subsamples();
+ uint8* data = buffer->writable_data();
+ uint32 offset = 0;
+ for (size_t k = 0; k < subsamples.size(); k++) {
+ offset += subsamples[k].clear_bytes;
+ uint32 cypher_bytes = subsamples[k].cypher_bytes;
+ CHECK_LE(static_cast<size_t>(offset + cypher_bytes), buffer->data_size());
+ AES_ctr128_encrypt(
+ data + offset, data + offset, cypher_bytes, &aes_key,
+ aes_iv, ecount_buf, &encrypted_byte_offset);
+ offset += cypher_bytes;
+ }
+
+ return scoped_refptr<DecoderBufferBase>(new DecoderBufferClear(buffer));
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/decrypt_util.h b/chromium/chromecast/media/cma/pipeline/decrypt_util.h
new file mode 100644
index 00000000000..5a59afc8648
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/decrypt_util.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_DECRYPT_UTIL_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_DECRYPT_UTIL_H_
+
+#include "base/memory/ref_counted.h"
+
+namespace crypto {
+class SymmetricKey;
+}
+
+namespace chromecast {
+namespace media {
+
+class DecoderBufferBase;
+
+// Create a new buffer which corresponds to the clear version of |buffer|.
+// Note: the memory area corresponding to the ES data of the new buffer
+// is the same as the ES data of |buffer| (for efficiency).
+// After the function is called, |buffer| is left in a inconsistent state
+// in the sense it has some decryption info but the ES data is now in clear.
+scoped_refptr<DecoderBufferBase> DecryptDecoderBuffer(
+ const scoped_refptr<DecoderBufferBase>& buffer,
+ crypto::SymmetricKey* key);
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_DECRYPT_UTIL_H_
diff --git a/chromium/chromecast/media/cma/pipeline/load_type.h b/chromium/chromecast/media/cma/pipeline/load_type.h
new file mode 100644
index 00000000000..569b2ef33f2
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/load_type.h
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_LOAD_TYPE_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_LOAD_TYPE_H_
+
+namespace chromecast {
+namespace media {
+
+enum LoadType {
+ kLoadTypeURL,
+ kLoadTypeMediaSource,
+ kLoadTypeMediaStream,
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_LOAD_TYPE_H_
diff --git a/chromium/chromecast/media/cma/pipeline/media_pipeline.h b/chromium/chromecast/media/cma/pipeline/media_pipeline.h
new file mode 100644
index 00000000000..6b127cb276b
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/media_pipeline.h
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_H_
+
+#include "base/basictypes.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "media/base/pipeline_status.h"
+
+namespace media {
+class AudioDecoderConfig;
+class BrowserCdm;
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+class AudioPipeline;
+class CodedFrameProvider;
+struct MediaPipelineClient;
+class VideoPipeline;
+
+class MediaPipeline {
+ public:
+ MediaPipeline() {}
+ virtual ~MediaPipeline() {}
+
+ // Set the media pipeline client.
+ virtual void SetClient(const MediaPipelineClient& client) = 0;
+
+ // Set the CDM to use for decryption.
+ // The CDM is refered by its id.
+ virtual void SetCdm(int cdm_id) = 0;
+
+ // Return the audio/video pipeline owned by the MediaPipeline.
+ virtual AudioPipeline* GetAudioPipeline() const = 0;
+ virtual VideoPipeline* GetVideoPipeline() const = 0;
+
+ // Create an audio/video pipeline.
+ // MediaPipeline owns the resulting audio/video pipeline.
+ // Only one audio and one video pipeline can be created.
+ virtual void InitializeAudio(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) = 0;
+ virtual void InitializeVideo(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) = 0;
+
+ // Control the media pipeline state machine.
+ virtual void StartPlayingFrom(base::TimeDelta time) = 0;
+ virtual void Flush(const ::media::PipelineStatusCB& status_cb) = 0;
+ virtual void Stop() = 0;
+
+ // Set the playback rate.
+ virtual void SetPlaybackRate(double playback_rate) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MediaPipeline);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_H_
diff --git a/chromium/chromecast/media/cma/pipeline/media_pipeline_client.cc b/chromium/chromecast/media/cma/pipeline/media_pipeline_client.cc
new file mode 100644
index 00000000000..8dbfc8db724
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/media_pipeline_client.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/media_pipeline_client.h"
+
+namespace chromecast {
+namespace media {
+
+MediaPipelineClient::MediaPipelineClient() {
+}
+
+MediaPipelineClient::~MediaPipelineClient() {
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/media_pipeline_client.h b/chromium/chromecast/media/cma/pipeline/media_pipeline_client.h
new file mode 100644
index 00000000000..692263c6e6a
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/media_pipeline_client.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_CLIENT_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_CLIENT_H_
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "media/base/buffering_state.h"
+#include "media/base/pipeline_status.h"
+
+namespace chromecast {
+namespace media {
+
+struct MediaPipelineClient {
+ typedef base::Callback<void(
+ base::TimeDelta, base::TimeDelta, base::TimeTicks)> TimeUpdateCB;
+
+ MediaPipelineClient();
+ ~MediaPipelineClient();
+
+ // Callback used to report a playback error as a ::media::PipelineStatus.
+ ::media::PipelineStatusCB error_cb;
+
+ // Callback used to report the latest playback time,
+ // as well as the maximum time available for rendering.
+ TimeUpdateCB time_update_cb;
+
+ // Callback used to report the buffering status.
+ ::media::BufferingStateCB buffering_state_cb;
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_CLIENT_H_
diff --git a/chromium/chromecast/media/cma/pipeline/media_pipeline_impl.cc b/chromium/chromecast/media/cma/pipeline/media_pipeline_impl.cc
new file mode 100644
index 00000000000..ced7df14cc0
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/media_pipeline_impl.cc
@@ -0,0 +1,373 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/media_pipeline_impl.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
+#include "chromecast/media/cdm/browser_cdm_cast.h"
+#include "chromecast/media/cma/backend/media_clock_device.h"
+#include "chromecast/media/cma/backend/media_pipeline_device.h"
+#include "chromecast/media/cma/base/buffering_controller.h"
+#include "chromecast/media/cma/base/buffering_state.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
+#include "media/base/buffers.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+// Buffering parameters when load_type is kLoadTypeUrl.
+const base::TimeDelta kLowBufferThresholdURL(
+ base::TimeDelta::FromMilliseconds(2000));
+const base::TimeDelta kHighBufferThresholdURL(
+ base::TimeDelta::FromMilliseconds(6000));
+
+// Buffering parameters when load_type is kLoadTypeMediaSource.
+const base::TimeDelta kLowBufferThresholdMediaSource(
+ base::TimeDelta::FromMilliseconds(0));
+const base::TimeDelta kHighBufferThresholdMediaSource(
+ base::TimeDelta::FromMilliseconds(300));
+
+// Interval between two updates of the media time.
+const base::TimeDelta kTimeUpdateInterval(
+ base::TimeDelta::FromMilliseconds(250));
+
+// Interval between two updates of the statistics is equal to:
+// kTimeUpdateInterval * kStatisticsUpdatePeriod.
+const int kStatisticsUpdatePeriod = 4;
+
+} // namespace
+
+MediaPipelineImpl::MediaPipelineImpl()
+ : has_audio_(false),
+ has_video_(false),
+ target_playback_rate_(0.0),
+ enable_time_update_(false),
+ pending_time_update_task_(false),
+ statistics_rolling_counter_(0),
+ weak_factory_(this) {
+ CMALOG(kLogControl) << __FUNCTION__;
+ weak_this_ = weak_factory_.GetWeakPtr();
+ thread_checker_.DetachFromThread();
+}
+
+MediaPipelineImpl::~MediaPipelineImpl() {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void MediaPipelineImpl::Initialize(
+ LoadType load_type,
+ scoped_ptr<MediaPipelineDevice> media_pipeline_device) {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_pipeline_device_.reset(media_pipeline_device.release());
+ clock_device_ = media_pipeline_device_->GetMediaClockDevice();
+
+ if (load_type == kLoadTypeURL || load_type == kLoadTypeMediaSource) {
+ base::TimeDelta low_threshold(kLowBufferThresholdURL);
+ base::TimeDelta high_threshold(kHighBufferThresholdURL);
+ if (load_type == kLoadTypeMediaSource) {
+ low_threshold = kLowBufferThresholdMediaSource;
+ high_threshold = kHighBufferThresholdMediaSource;
+ }
+ scoped_refptr<BufferingConfig> buffering_config(
+ new BufferingConfig(low_threshold, high_threshold));
+ buffering_controller_.reset(new BufferingController(
+ buffering_config,
+ base::Bind(&MediaPipelineImpl::OnBufferingNotification, weak_this_)));
+ }
+
+ audio_pipeline_.reset(new AudioPipelineImpl(
+ media_pipeline_device_->GetAudioPipelineDevice()));
+
+ video_pipeline_.reset(new VideoPipelineImpl(
+ media_pipeline_device_->GetVideoPipelineDevice()));
+}
+
+void MediaPipelineImpl::SetClient(const MediaPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!client.error_cb.is_null());
+ DCHECK(!client.time_update_cb.is_null());
+ DCHECK(!client.buffering_state_cb.is_null());
+ client_ = client;
+}
+
+void MediaPipelineImpl::SetCdm(int cdm_id) {
+ CMALOG(kLogControl) << __FUNCTION__ << " cdm_id=" << cdm_id;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ NOTIMPLEMENTED();
+ // TODO(gunsch): SetCdm(int) is not implemented.
+ // One possibility would be a GetCdmByIdCB that's passed in.
+}
+
+void MediaPipelineImpl::SetCdm(BrowserCdmCast* cdm) {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ audio_pipeline_->SetCdm(cdm);
+ video_pipeline_->SetCdm(cdm);
+}
+
+AudioPipeline* MediaPipelineImpl::GetAudioPipeline() const {
+ return audio_pipeline_.get();
+}
+
+VideoPipeline* MediaPipelineImpl::GetVideoPipeline() const {
+ return video_pipeline_.get();
+}
+
+void MediaPipelineImpl::InitializeAudio(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!has_audio_);
+ if (clock_device_->GetState() == MediaClockDevice::kStateUninitialized &&
+ !clock_device_->SetState(MediaClockDevice::kStateIdle)) {
+ status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ has_audio_ = true;
+ audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
+}
+
+void MediaPipelineImpl::InitializeVideo(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!has_video_);
+ if (clock_device_->GetState() == MediaClockDevice::kStateUninitialized &&
+ !clock_device_->SetState(MediaClockDevice::kStateIdle)) {
+ status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ has_video_ = true;
+ video_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
+}
+
+void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) {
+ CMALOG(kLogControl) << __FUNCTION__ << " t0=" << time.InMilliseconds();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+ DCHECK(!pending_callbacks_);
+
+ // Reset the start of the timeline.
+ DCHECK_EQ(clock_device_->GetState(), MediaClockDevice::kStateIdle);
+ clock_device_->ResetTimeline(time);
+
+ // Start the clock. If the playback rate is 0, then the clock is started
+ // but does not increase.
+ if (!clock_device_->SetState(MediaClockDevice::kStateRunning)) {
+ OnError(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+
+ // Enable time updates.
+ enable_time_update_ = true;
+ statistics_rolling_counter_ = 0;
+ if (!pending_time_update_task_) {
+ pending_time_update_task_ = true;
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_));
+ }
+
+ // Setup the audio and video pipeline for the new timeline.
+ if (has_audio_) {
+ scoped_refptr<BufferingState> buffering_state;
+ if (buffering_controller_)
+ buffering_state = buffering_controller_->AddStream("audio");
+ if (!audio_pipeline_->StartPlayingFrom(time, buffering_state)) {
+ OnError(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ }
+ if (has_video_) {
+ scoped_refptr<BufferingState> buffering_state;
+ if (buffering_controller_)
+ buffering_state = buffering_controller_->AddStream("video");
+ if (!video_pipeline_->StartPlayingFrom(time, buffering_state)) {
+ OnError(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ }
+}
+
+void MediaPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+ DCHECK(!pending_callbacks_);
+
+ // No need to update media time anymore.
+ enable_time_update_ = false;
+
+ buffering_controller_->Reset();
+
+ // The clock should return to idle.
+ if (!clock_device_->SetState(MediaClockDevice::kStateIdle)) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+
+ // Flush both the audio and video pipeline.
+ ::media::SerialRunner::Queue bound_fns;
+ if (has_audio_) {
+ bound_fns.Push(base::Bind(
+ &AudioPipelineImpl::Flush,
+ base::Unretained(audio_pipeline_.get())));
+ }
+ if (has_video_) {
+ bound_fns.Push(base::Bind(
+ &VideoPipelineImpl::Flush,
+ base::Unretained(video_pipeline_.get())));
+ }
+ ::media::PipelineStatusCB transition_cb =
+ base::Bind(&MediaPipelineImpl::StateTransition, weak_this_, status_cb);
+ pending_callbacks_ =
+ ::media::SerialRunner::Run(bound_fns, transition_cb);
+}
+
+void MediaPipelineImpl::Stop() {
+ CMALOG(kLogControl) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+ DCHECK(!pending_callbacks_);
+
+ // No need to update media time anymore.
+ enable_time_update_ = false;
+
+ // Release hardware resources on Stop.
+ // Note: Stop can be called from any state.
+ if (clock_device_->GetState() == MediaClockDevice::kStateRunning)
+ clock_device_->SetState(MediaClockDevice::kStateIdle);
+ if (clock_device_->GetState() == MediaClockDevice::kStateIdle)
+ clock_device_->SetState(MediaClockDevice::kStateUninitialized);
+
+ // Stop both the audio and video pipeline.
+ if (has_audio_)
+ audio_pipeline_->Stop();
+ if (has_video_)
+ video_pipeline_->Stop();
+}
+
+void MediaPipelineImpl::SetPlaybackRate(double rate) {
+ CMALOG(kLogControl) << __FUNCTION__ << " rate=" << rate;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ target_playback_rate_ = rate;
+ if (!buffering_controller_ || !buffering_controller_->IsBuffering())
+ media_pipeline_device_->GetMediaClockDevice()->SetRate(rate);
+}
+
+AudioPipelineImpl* MediaPipelineImpl::GetAudioPipelineImpl() const {
+ return audio_pipeline_.get();
+}
+
+VideoPipelineImpl* MediaPipelineImpl::GetVideoPipelineImpl() const {
+ return video_pipeline_.get();
+}
+
+void MediaPipelineImpl::StateTransition(
+ const ::media::PipelineStatusCB& status_cb,
+ ::media::PipelineStatus status) {
+ pending_callbacks_.reset();
+ status_cb.Run(status);
+}
+
+void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) {
+ CMALOG(kLogControl) << __FUNCTION__ << " is_buffering=" << is_buffering;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(buffering_controller_);
+
+ if (!client_.buffering_state_cb.is_null()) {
+ ::media::BufferingState buffering_state = is_buffering ?
+ ::media::BUFFERING_HAVE_NOTHING : ::media::BUFFERING_HAVE_ENOUGH;
+ client_.buffering_state_cb.Run(buffering_state);
+ }
+
+ if (media_pipeline_device_->GetMediaClockDevice()->GetState() ==
+ MediaClockDevice::kStateUninitialized) {
+ return;
+ }
+
+ if (is_buffering) {
+ // Do not consume data in a rebuffering phase.
+ media_pipeline_device_->GetMediaClockDevice()->SetRate(0.0);
+ } else {
+ media_pipeline_device_->GetMediaClockDevice()->SetRate(
+ target_playback_rate_);
+ }
+}
+
+void MediaPipelineImpl::UpdateMediaTime() {
+ pending_time_update_task_ = false;
+ if (!enable_time_update_)
+ return;
+
+ if (statistics_rolling_counter_ == 0) {
+ audio_pipeline_->UpdateStatistics();
+ video_pipeline_->UpdateStatistics();
+ }
+ statistics_rolling_counter_ =
+ (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod;
+
+ base::TimeDelta media_time(clock_device_->GetTime());
+ if (media_time == ::media::kNoTimestamp()) {
+ pending_time_update_task_ = true;
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_),
+ kTimeUpdateInterval);
+ return;
+ }
+ base::TimeTicks stc = base::TimeTicks::Now();
+
+ base::TimeDelta max_rendering_time = media_time;
+ if (buffering_controller_) {
+ buffering_controller_->SetMediaTime(media_time);
+
+ // Receiving the same time twice in a row means playback isn't moving,
+ // so don't interpolate ahead.
+ if (media_time != last_media_time_) {
+ max_rendering_time = buffering_controller_->GetMaxRenderingTime();
+ if (max_rendering_time == ::media::kNoTimestamp())
+ max_rendering_time = media_time;
+
+ // Cap interpolation time to avoid interpolating too far ahead.
+ max_rendering_time =
+ std::min(max_rendering_time, media_time + 2 * kTimeUpdateInterval);
+ }
+ }
+
+ last_media_time_ = media_time;
+ if (!client_.time_update_cb.is_null())
+ client_.time_update_cb.Run(media_time, max_rendering_time, stc);
+
+ pending_time_update_task_ = true;
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_),
+ kTimeUpdateInterval);
+}
+
+void MediaPipelineImpl::OnError(::media::PipelineStatus error) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!";
+ if (!client_.error_cb.is_null())
+ client_.error_cb.Run(error);
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/media_pipeline_impl.h b/chromium/chromecast/media/cma/pipeline/media_pipeline_impl.h
new file mode 100644
index 00000000000..eb14a555b98
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/media_pipeline_impl.h
@@ -0,0 +1,113 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_IMPL_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "chromecast/media/cma/pipeline/media_pipeline.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_client.h"
+#include "media/base/serial_runner.h"
+
+namespace chromecast {
+namespace media {
+class AudioPipelineImpl;
+class BrowserCdmCast;
+class BufferingController;
+class MediaClockDevice;
+class MediaPipelineDevice;
+class VideoPipelineImpl;
+
+class MediaPipelineImpl : public MediaPipeline {
+ public:
+ MediaPipelineImpl();
+ ~MediaPipelineImpl() override;
+
+ // Initialize the media pipeline: the pipeline is configured based on
+ // |load_type|.
+ void Initialize(LoadType load_type,
+ scoped_ptr<MediaPipelineDevice> media_pipeline_device);
+
+ // MediaPipeline implementation.
+ void SetClient(const MediaPipelineClient& client) override;
+ void SetCdm(int cdm_id) override;
+ AudioPipeline* GetAudioPipeline() const override;
+ VideoPipeline* GetVideoPipeline() const override;
+ void InitializeAudio(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) override;
+ void InitializeVideo(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) override;
+ void StartPlayingFrom(base::TimeDelta time) override;
+ void Flush(const ::media::PipelineStatusCB& status_cb) override;
+ void Stop() override;
+ void SetPlaybackRate(double playback_rate) override;
+
+ AudioPipelineImpl* GetAudioPipelineImpl() const;
+ VideoPipelineImpl* GetVideoPipelineImpl() const;
+
+ void SetCdm(BrowserCdmCast* cdm);
+
+ private:
+ void StateTransition(const ::media::PipelineStatusCB& status_cb,
+ ::media::PipelineStatus status);
+
+ // Invoked to notify about a change of buffering state.
+ void OnBufferingNotification(bool is_buffering);
+
+ void UpdateMediaTime();
+
+ void OnError(::media::PipelineStatus error);
+
+ base::ThreadChecker thread_checker_;
+
+ MediaPipelineClient client_;
+
+ scoped_ptr<BufferingController> buffering_controller_;
+
+ // Interface with the underlying hardware media pipeline.
+ scoped_ptr<MediaPipelineDevice> media_pipeline_device_;
+ MediaClockDevice* clock_device_;
+
+ bool has_audio_;
+ bool has_video_;
+ scoped_ptr<AudioPipelineImpl> audio_pipeline_;
+ scoped_ptr<VideoPipelineImpl> video_pipeline_;
+ scoped_ptr< ::media::SerialRunner> pending_callbacks_;
+
+ // Playback rate set by the upper layer.
+ float target_playback_rate_;
+
+ // Indicate a possible re-buffering phase.
+ bool is_buffering_;
+
+ // The media time is retrieved at regular intervals.
+ // Indicate whether time update is enabled.
+ bool enable_time_update_;
+ bool pending_time_update_task_;
+ base::TimeDelta last_media_time_;
+
+ // Used to make the statistics update period a multiplier of the time update
+ // period.
+ int statistics_rolling_counter_;
+
+ base::WeakPtr<MediaPipelineImpl> weak_this_;
+ base::WeakPtrFactory<MediaPipelineImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaPipelineImpl);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_PIPELINE_IMPL_H_
diff --git a/chromium/chromecast/common/chromecast_config_simple.cc b/chromium/chromecast/media/cma/pipeline/video_pipeline.cc
index f62efe524b8..6b428b5e6e2 100644
--- a/chromium/chromecast/common/chromecast_config_simple.cc
+++ b/chromium/chromecast/media/cma/pipeline/video_pipeline.cc
@@ -2,11 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chromecast/common/chromecast_config.h"
+#include "chromecast/media/cma/pipeline/video_pipeline.h"
namespace chromecast {
+namespace media {
-void ChromecastConfig::RegisterPlatformPrefs(PrefRegistrySimple* registry) {
+VideoPipeline::VideoPipeline() {
}
+VideoPipeline::~VideoPipeline() {
+}
+
+} // namespace media
} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/video_pipeline.h b/chromium/chromecast/media/cma/pipeline/video_pipeline.h
new file mode 100644
index 00000000000..68a9b8ccbce
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/video_pipeline.h
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_H_
+
+#include "base/macros.h"
+
+namespace chromecast {
+namespace media {
+struct VideoPipelineClient;
+
+class VideoPipeline {
+ public:
+ VideoPipeline();
+ virtual ~VideoPipeline();
+
+ virtual void SetClient(const VideoPipelineClient& client) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VideoPipeline);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_H_
diff --git a/chromium/chromecast/media/cma/pipeline/video_pipeline_client.cc b/chromium/chromecast/media/cma/pipeline/video_pipeline_client.cc
new file mode 100644
index 00000000000..bb7388e83c3
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/video_pipeline_client.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/video_pipeline_client.h"
+
+namespace chromecast {
+namespace media {
+
+VideoPipelineClient::VideoPipelineClient() {
+}
+
+VideoPipelineClient::~VideoPipelineClient() {
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/video_pipeline_client.h b/chromium/chromecast/media/cma/pipeline/video_pipeline_client.h
new file mode 100644
index 00000000000..105b8a2fe11
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/video_pipeline_client.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_CLIENT_H_
+#define CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_CLIENT_H_
+
+#include "base/callback.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace chromecast {
+namespace media {
+
+struct VideoPipelineClient {
+ typedef base::Callback<void(
+ const gfx::Size& natural_size)> NaturalSizeChangedCB;
+
+ VideoPipelineClient();
+ ~VideoPipelineClient();
+
+ // All the default callbacks.
+ AvPipelineClient av_pipeline_client;
+
+ // Video resolution change notification.
+ NaturalSizeChangedCB natural_size_changed_cb;
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_CLIENT_H_
diff --git a/chromium/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromium/chromecast/media/cma/pipeline/video_pipeline_impl.cc
new file mode 100644
index 00000000000..fda8b445ba4
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/video_pipeline_impl.cc
@@ -0,0 +1,178 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
+
+#include "base/bind.h"
+#include "chromecast/media/cma/backend/video_pipeline_device.h"
+#include "chromecast/media/cma/base/buffering_defs.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/media/cma/base/decoder_config_adapter.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
+#include "chromecast/public/media/decoder_config.h"
+#include "media/base/video_decoder_config.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+const size_t kMaxVideoFrameSize = 1024 * 1024;
+}
+
+VideoPipelineImpl::VideoPipelineImpl(VideoPipelineDevice* video_device)
+ : video_device_(video_device),
+ weak_factory_(this) {
+ weak_this_ = weak_factory_.GetWeakPtr();
+ av_pipeline_impl_.reset(new AvPipelineImpl(
+ video_device_,
+ base::Bind(&VideoPipelineImpl::OnUpdateConfig, base::Unretained(this))));
+}
+
+VideoPipelineImpl::~VideoPipelineImpl() {
+}
+
+void VideoPipelineImpl::SetCodedFrameProvider(
+ scoped_ptr<CodedFrameProvider> frame_provider) {
+ av_pipeline_impl_->SetCodedFrameProvider(
+ frame_provider.Pass(), kAppVideoBufferSize, kMaxVideoFrameSize);
+}
+
+bool VideoPipelineImpl::StartPlayingFrom(
+ base::TimeDelta time,
+ const scoped_refptr<BufferingState>& buffering_state) {
+ CMALOG(kLogControl) << "VideoPipelineImpl::StartPlayingFrom t0="
+ << time.InMilliseconds();
+
+ // Reset the pipeline statistics.
+ previous_stats_ = ::media::PipelineStatistics();
+
+ // Start playing.
+ if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError)
+ return false;
+ DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kFlushed);
+
+ if (!av_pipeline_impl_->StartPlayingFrom(time, buffering_state)) {
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError);
+ return false;
+ }
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kPlaying);
+
+ return true;
+}
+
+void VideoPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "VideoPipelineImpl::Flush";
+ if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kPlaying);
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushing);
+ av_pipeline_impl_->Flush(
+ base::Bind(&VideoPipelineImpl::OnFlushDone, weak_this_, status_cb));
+}
+
+void VideoPipelineImpl::OnFlushDone(
+ const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "VideoPipelineImpl::OnFlushDone";
+ if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
+ status_cb.Run(::media::PIPELINE_OK);
+}
+
+void VideoPipelineImpl::Stop() {
+ CMALOG(kLogControl) << "VideoPipelineImpl::Stop";
+ av_pipeline_impl_->Stop();
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kStopped);
+}
+
+void VideoPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
+ av_pipeline_impl_->SetCdm(media_keys);
+}
+
+void VideoPipelineImpl::SetClient(const VideoPipelineClient& client) {
+ video_client_ = client;
+ av_pipeline_impl_->SetClient(client.av_pipeline_client);
+}
+
+void VideoPipelineImpl::Initialize(
+ const ::media::VideoDecoderConfig& video_config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "VideoPipelineImpl::Initialize "
+ << video_config.AsHumanReadableString();
+ VideoPipelineDevice::VideoClient client;
+ client.natural_size_changed_cb =
+ base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_);
+ video_device_->SetVideoClient(client);
+ if (frame_provider)
+ SetCodedFrameProvider(frame_provider.Pass());
+
+ if (!video_device_->SetConfig(
+ DecoderConfigAdapter::ToCastVideoConfig(video_config)) ||
+ !av_pipeline_impl_->Initialize()) {
+ status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
+ status_cb.Run(::media::PIPELINE_OK);
+}
+
+void VideoPipelineImpl::OnUpdateConfig(
+ const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config) {
+ if (video_config.IsValidConfig()) {
+ CMALOG(kLogControl) << "VideoPipelineImpl::OnUpdateConfig "
+ << video_config.AsHumanReadableString();
+
+ bool success = video_device_->SetConfig(
+ DecoderConfigAdapter::ToCastVideoConfig(video_config));
+ if (!success &&
+ !video_client_.av_pipeline_client.playback_error_cb.is_null()) {
+ video_client_.av_pipeline_client.playback_error_cb.Run(
+ ::media::PIPELINE_ERROR_DECODE);
+ }
+ }
+}
+
+void VideoPipelineImpl::OnNaturalSizeChanged(const gfx::Size& size) {
+ if (av_pipeline_impl_->GetState() != AvPipelineImpl::kPlaying)
+ return;
+
+ if (!video_client_.natural_size_changed_cb.is_null())
+ video_client_.natural_size_changed_cb.Run(size);
+}
+
+void VideoPipelineImpl::UpdateStatistics() {
+ if (video_client_.av_pipeline_client.statistics_cb.is_null())
+ return;
+
+ MediaComponentDevice::Statistics device_stats;
+ if (!video_device_->GetStatistics(&device_stats))
+ return;
+
+ ::media::PipelineStatistics current_stats;
+ current_stats.video_bytes_decoded = device_stats.decoded_bytes;
+ current_stats.video_frames_decoded = device_stats.decoded_samples;
+ current_stats.video_frames_dropped = device_stats.dropped_samples;
+
+ ::media::PipelineStatistics delta_stats;
+ delta_stats.video_bytes_decoded =
+ current_stats.video_bytes_decoded - previous_stats_.video_bytes_decoded;
+ delta_stats.video_frames_decoded =
+ current_stats.video_frames_decoded - previous_stats_.video_frames_decoded;
+ delta_stats.video_frames_dropped =
+ current_stats.video_frames_dropped - previous_stats_.video_frames_dropped;
+
+ previous_stats_ = current_stats;
+
+ video_client_.av_pipeline_client.statistics_cb.Run(delta_stats);
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/media/cma/pipeline/video_pipeline_impl.h b/chromium/chromecast/media/cma/pipeline/video_pipeline_impl.h
new file mode 100644
index 00000000000..e065ac1df20
--- /dev/null
+++ b/chromium/chromecast/media/cma/pipeline/video_pipeline_impl.h
@@ -0,0 +1,82 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_CMA_BASE_VIDEO_PIPELINE_IMPL_H_
+#define CHROMECAST_MEDIA_CMA_BASE_VIDEO_PIPELINE_IMPL_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/media/cma/pipeline/video_pipeline.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_client.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace media {
+class AudioDecoderConfig;
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+class AvPipelineImpl;
+class BrowserCdmCast;
+class BufferingState;
+class CodedFrameProvider;
+class VideoPipelineDevice;
+
+class VideoPipelineImpl : public VideoPipeline {
+ public:
+ // |buffering_controller| can be NULL.
+ explicit VideoPipelineImpl(VideoPipelineDevice* video_device);
+ ~VideoPipelineImpl() override;
+
+ // Input port of the pipeline.
+ void SetCodedFrameProvider(scoped_ptr<CodedFrameProvider> frame_provider);
+
+ // Provide the CDM to use to decrypt samples.
+ void SetCdm(BrowserCdmCast* media_keys);
+
+ // Functions to control the state of the audio pipeline.
+ void Initialize(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb);
+ bool StartPlayingFrom(base::TimeDelta time,
+ const scoped_refptr<BufferingState>& buffering_state);
+ void Flush(const ::media::PipelineStatusCB& status_cb);
+ void Stop();
+
+ // Update the playback statistics for this video stream.
+ void UpdateStatistics();
+
+ // VideoPipeline implementation.
+ void SetClient(const VideoPipelineClient& client) override;
+
+ private:
+ void OnFlushDone(const ::media::PipelineStatusCB& status_cb);
+ void OnUpdateConfig(const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config);
+ void OnNaturalSizeChanged(const gfx::Size& size);
+
+ VideoPipelineDevice* video_device_;
+
+ scoped_ptr<AvPipelineImpl> av_pipeline_impl_;
+ VideoPipelineClient video_client_;
+
+ ::media::PipelineStatistics previous_stats_;
+
+ base::WeakPtr<VideoPipelineImpl> weak_this_;
+ base::WeakPtrFactory<VideoPipelineImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoPipelineImpl);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CMA_BASE_VIDEO_PIPELINE_IMPL_H_
diff --git a/chromium/chromecast/media/media.gyp b/chromium/chromecast/media/media.gyp
index 9eaf8d1be75..20b1dc0c134 100644
--- a/chromium/chromecast/media/media.gyp
+++ b/chromium/chromecast/media/media.gyp
@@ -4,7 +4,10 @@
{
'variables': {
+ 'chromium_code': 1,
'chromecast_branding%': 'Chromium',
+ 'libcast_media_gyp%': '',
+ 'use_default_libcast_media%': 1,
},
'targets': [
{
@@ -14,6 +17,7 @@
'../../base/base.gyp:base',
'../../crypto/crypto.gyp:crypto',
'../../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
+ '<(libcast_media_gyp):libcast_media_1.0',
],
'sources': [
'base/decrypt_context.cc',
@@ -22,11 +26,17 @@
'base/decrypt_context_clearkey.h',
'base/key_systems_common.cc',
'base/key_systems_common.h',
+ 'base/media_caps.cc',
+ 'base/media_caps.h',
+ 'base/media_codec_support.cc',
+ 'base/media_codec_support.h',
+ 'base/switching_media_renderer.cc',
+ 'base/switching_media_renderer.h',
],
'conditions': [
['chromecast_branding=="Chrome"', {
'dependencies': [
- '<(cast_internal_gyp):media_base_internal',
+ '../internal/chromecast_internal.gyp:media_base_internal',
],
}, {
'sources': [
@@ -36,6 +46,27 @@
],
},
{
+ 'target_name': 'media_cdm',
+ 'type': '<(component)',
+ 'dependencies': [
+ 'media_base',
+ '../../base/base.gyp:base',
+ '../../media/media.gyp:media',
+ ],
+ 'sources': [
+ 'cdm/browser_cdm_cast.cc',
+ 'cdm/browser_cdm_cast.h',
+ ],
+ 'conditions': [
+ ['use_playready==1', {
+ 'sources': [
+ 'cdm/playready_drm_delegate_android.cc',
+ 'cdm/playready_drm_delegate_android.h',
+ ],
+ }],
+ ],
+ },
+ {
'target_name': 'cma_base',
'type': '<(component)',
'dependencies': [
@@ -51,6 +82,8 @@
'cma/base/balanced_media_task_runner_factory.h',
'cma/base/buffering_controller.cc',
'cma/base/buffering_controller.h',
+ 'cma/base/buffering_defs.cc',
+ 'cma/base/buffering_defs.h',
'cma/base/buffering_frame_provider.cc',
'cma/base/buffering_frame_provider.h',
'cma/base/buffering_state.cc',
@@ -62,6 +95,8 @@
'cma/base/decoder_buffer_adapter.h',
'cma/base/decoder_buffer_base.cc',
'cma/base/decoder_buffer_base.h',
+ 'cma/base/decoder_config_adapter.cc',
+ 'cma/base/decoder_config_adapter.h',
'cma/base/media_task_runner.cc',
'cma/base/media_task_runner.h',
],
@@ -93,15 +128,20 @@
'cma/backend/media_pipeline_device_params.h',
'cma/backend/video_pipeline_device.cc',
'cma/backend/video_pipeline_device.h',
+ 'cma/backend/video_plane.cc',
+ 'cma/backend/video_plane.h',
+ 'cma/backend/video_plane_fake.cc',
+ 'cma/backend/video_plane_fake.h',
],
'conditions': [
['chromecast_branding=="Chrome"', {
'dependencies': [
- '<(cast_internal_gyp):cma_backend_internal',
+ '../internal/chromecast_internal.gyp:cma_backend_internal',
],
}, {
'sources': [
'cma/backend/media_pipeline_device_fake_factory.cc',
+ 'cma/backend/video_plane_fake_factory.cc',
],
}],
],
@@ -145,6 +185,54 @@
],
},
{
+ 'target_name': 'cma_pipeline',
+ 'type': '<(component)',
+ 'dependencies': [
+ 'cma_backend',
+ 'cma_base',
+ 'media_base',
+ 'media_cdm',
+ '../../base/base.gyp:base',
+ '../../crypto/crypto.gyp:crypto',
+ '../../media/media.gyp:media',
+ ],
+ 'conditions': [
+ ['chromecast_branding=="Chrome"', {
+ 'dependencies': [
+ '../internal/cast_system.gyp:openssl',
+ ],
+ }, {
+ 'dependencies': [
+ '../../third_party/boringssl/boringssl.gyp:boringssl',
+ ],
+ }],
+ ],
+ 'sources': [
+ 'cma/pipeline/audio_pipeline.cc',
+ 'cma/pipeline/audio_pipeline.h',
+ 'cma/pipeline/audio_pipeline_impl.cc',
+ 'cma/pipeline/audio_pipeline_impl.h',
+ 'cma/pipeline/av_pipeline_client.cc',
+ 'cma/pipeline/av_pipeline_client.h',
+ 'cma/pipeline/av_pipeline_impl.cc',
+ 'cma/pipeline/av_pipeline_impl.h',
+ 'cma/pipeline/decrypt_util.cc',
+ 'cma/pipeline/decrypt_util.h',
+ 'cma/pipeline/load_type.h',
+ 'cma/pipeline/media_pipeline.h',
+ 'cma/pipeline/media_pipeline_client.cc',
+ 'cma/pipeline/media_pipeline_client.h',
+ 'cma/pipeline/media_pipeline_impl.cc',
+ 'cma/pipeline/media_pipeline_impl.h',
+ 'cma/pipeline/video_pipeline.cc',
+ 'cma/pipeline/video_pipeline.h',
+ 'cma/pipeline/video_pipeline_client.cc',
+ 'cma/pipeline/video_pipeline_client.h',
+ 'cma/pipeline/video_pipeline_impl.cc',
+ 'cma/pipeline/video_pipeline_impl.h',
+ ],
+ },
+ {
'target_name': 'cma_filters',
'type': '<(component)',
'dependencies': [
@@ -153,6 +241,8 @@
'cma_base',
],
'sources': [
+ 'cma/filters/cma_renderer.cc',
+ 'cma/filters/cma_renderer.h',
'cma/filters/demuxer_stream_adapter.cc',
'cma/filters/demuxer_stream_adapter.h',
],
@@ -166,6 +256,8 @@
'cma_filters',
'cma_ipc',
'cma_ipc_streamer',
+ 'cma_pipeline',
+ 'media_cdm',
],
},
{
@@ -191,6 +283,7 @@
'cma/ipc/media_message_fifo_unittest.cc',
'cma/ipc/media_message_unittest.cc',
'cma/ipc_streamer/av_streamer_unittest.cc',
+ 'cma/pipeline/audio_video_pipeline_impl_unittest.cc',
'cma/test/frame_generator_for_test.cc',
'cma/test/frame_generator_for_test.h',
'cma/test/frame_segmenter_for_test.cc',
@@ -204,5 +297,24 @@
'cma/test/run_all_unittests.cc',
],
},
+ ], # end of targets
+ 'conditions': [
+ ['use_default_libcast_media==1', {
+ 'targets': [
+ {
+ 'target_name': 'libcast_media_1.0',
+ 'type': 'shared_library',
+ 'dependencies': [
+ '../../chromecast/chromecast.gyp:cast_public_api'
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'sources': [
+ 'base/cast_media_default.cc',
+ ],
+ }
+ ]
+ }],
],
}
diff --git a/chromium/chromecast/net/connectivity_checker.cc b/chromium/chromecast/net/connectivity_checker.cc
new file mode 100644
index 00000000000..de3081291f3
--- /dev/null
+++ b/chromium/chromecast/net/connectivity_checker.cc
@@ -0,0 +1,184 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/net/connectivity_checker.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "chromecast/net/net_switches.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
+#include "net/http/http_status_code.h"
+#include "net/proxy/proxy_config.h"
+#include "net/proxy/proxy_config_service_fixed.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_builder.h"
+
+namespace chromecast {
+
+namespace {
+
+// How often connectivity checks are performed in seconds
+const unsigned int kConnectivityPeriodSeconds = 1;
+
+// Number of consecutive bad responses received before connectivity status is
+// changed to offline
+const unsigned int kNumBadResponses = 3;
+
+// Default url for connectivity checking.
+const char kDefaultConnectivityCheckUrl[] =
+ "https://clients3.google.com/generate_204";
+
+} // namespace
+
+ConnectivityChecker::ConnectivityChecker(
+ const scoped_refptr<base::MessageLoopProxy>& loop_proxy)
+ : connectivity_observer_list_(
+ new ObserverListThreadSafe<ConnectivityObserver>()),
+ loop_proxy_(loop_proxy),
+ connected_(false),
+ bad_responses_(0) {
+ DCHECK(loop_proxy_.get());
+ loop_proxy->PostTask(FROM_HERE,
+ base::Bind(&ConnectivityChecker::Initialize, this));
+}
+
+void ConnectivityChecker::Initialize() {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringType check_url_str =
+ command_line->GetSwitchValueNative(switches::kConnectivityCheckUrl);
+ connectivity_check_url_.reset(new GURL(
+ check_url_str.empty() ? kDefaultConnectivityCheckUrl : check_url_str));
+
+ net::URLRequestContextBuilder builder;
+ builder.set_proxy_config_service(
+ new net::ProxyConfigServiceFixed(net::ProxyConfig::CreateDirect()));
+ builder.DisableHttpCache();
+ url_request_context_.reset(builder.Build());
+
+ net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+ net::NetworkChangeNotifier::AddIPAddressObserver(this);
+ loop_proxy_->PostTask(FROM_HERE,
+ base::Bind(&ConnectivityChecker::Check, this));
+}
+
+ConnectivityChecker::~ConnectivityChecker() {
+ DCHECK(loop_proxy_.get());
+ net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+ loop_proxy_->DeleteSoon(FROM_HERE, url_request_context_.release());
+ loop_proxy_->DeleteSoon(FROM_HERE, url_request_.release());
+}
+
+void ConnectivityChecker::AddConnectivityObserver(
+ ConnectivityObserver* observer) {
+ connectivity_observer_list_->AddObserver(observer);
+}
+
+void ConnectivityChecker::RemoveConnectivityObserver(
+ ConnectivityObserver* observer) {
+ connectivity_observer_list_->RemoveObserver(observer);
+}
+
+bool ConnectivityChecker::Connected() const {
+ return connected_;
+}
+
+void ConnectivityChecker::SetConnectivity(bool connected) {
+ if (connected_ == connected)
+ return;
+
+ connected_ = connected;
+ connectivity_observer_list_->Notify(
+ FROM_HERE, &ConnectivityObserver::OnConnectivityChanged, connected);
+ LOG(INFO) << "Global connection is: " << (connected ? "Up" : "Down");
+}
+
+void ConnectivityChecker::Check() {
+ if (!loop_proxy_->BelongsToCurrentThread()) {
+ loop_proxy_->PostTask(FROM_HERE,
+ base::Bind(&ConnectivityChecker::Check, this));
+ return;
+ }
+ DCHECK(url_request_context_.get());
+
+ // Don't check connectivity if network is offline, because internet could be
+ // accessible via netifs ignored.
+ if (net::NetworkChangeNotifier::IsOffline())
+ return;
+
+ // If url_request_ is non-null, there is already a check going on. Don't
+ // start another.
+ if (url_request_.get())
+ return;
+
+ VLOG(1) << "Connectivity check: url=" << *connectivity_check_url_;
+ url_request_ = url_request_context_->CreateRequest(
+ *connectivity_check_url_, net::MAXIMUM_PRIORITY, this);
+ url_request_->set_method("HEAD");
+ url_request_->Start();
+}
+
+void ConnectivityChecker::OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ VLOG(2) << "OnConnectionTypeChanged " << type;
+ if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
+ SetConnectivity(false);
+
+ Cancel();
+ Check();
+}
+
+void ConnectivityChecker::OnIPAddressChanged() {
+ VLOG(2) << "OnIPAddressChanged";
+
+ Cancel();
+ Check();
+}
+
+void ConnectivityChecker::OnResponseStarted(net::URLRequest* request) {
+ int http_response_code =
+ (request->status().is_success() &&
+ request->response_info().headers.get() != NULL)
+ ? request->response_info().headers->response_code()
+ : net::HTTP_BAD_REQUEST;
+
+ // Clears resources.
+ url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
+
+ if (http_response_code < 400) {
+ VLOG(1) << "Connectivity check succeeded";
+ bad_responses_ = 0;
+ SetConnectivity(true);
+ return;
+ }
+
+ VLOG(1) << "Connectivity check failed: " << http_response_code;
+ ++bad_responses_;
+ if (bad_responses_ > kNumBadResponses) {
+ bad_responses_ = kNumBadResponses;
+ SetConnectivity(false);
+ }
+
+ // Check again
+ loop_proxy_->PostDelayedTask(
+ FROM_HERE, base::Bind(&ConnectivityChecker::Check, this),
+ base::TimeDelta::FromSeconds(kConnectivityPeriodSeconds));
+}
+
+void ConnectivityChecker::OnReadCompleted(net::URLRequest* request,
+ int bytes_read) {
+ NOTREACHED();
+}
+
+void ConnectivityChecker::Cancel() {
+ if (url_request_.get()) {
+ VLOG(2) << "Cancel connectivity check in progress";
+ url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
+ }
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/net/connectivity_checker.h b/chromium/chromecast/net/connectivity_checker.h
new file mode 100644
index 00000000000..c52b8a624da
--- /dev/null
+++ b/chromium/chromecast/net/connectivity_checker.h
@@ -0,0 +1,99 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_NET_CONNECTIVITY_CHECKER_H_
+#define CHROMECAST_NET_CONNECTIVITY_CHECKER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "net/base/network_change_notifier.h"
+#include "net/url_request/url_request.h"
+
+class GURL;
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace net {
+class URLRequestContext;
+}
+
+namespace chromecast {
+
+// Simple class to check network connectivity by sending a HEAD http request
+// to given url.
+class ConnectivityChecker
+ : public base::RefCountedThreadSafe<ConnectivityChecker>,
+ public net::URLRequest::Delegate,
+ public net::NetworkChangeNotifier::ConnectionTypeObserver,
+ public net::NetworkChangeNotifier::IPAddressObserver {
+ public:
+ class ConnectivityObserver {
+ public:
+ // Will be called when internet connectivity changes
+ virtual void OnConnectivityChanged(bool connected) = 0;
+
+ protected:
+ ConnectivityObserver() {}
+ virtual ~ConnectivityObserver() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConnectivityObserver);
+ };
+
+ explicit ConnectivityChecker(
+ const scoped_refptr<base::MessageLoopProxy>& loop_proxy);
+
+ void AddConnectivityObserver(ConnectivityObserver* observer);
+ void RemoveConnectivityObserver(ConnectivityObserver* observer);
+
+ // Returns if there is internet connectivity
+ bool Connected() const;
+
+ // Checks for connectivity
+ void Check();
+
+ protected:
+ ~ConnectivityChecker() override;
+
+ private:
+ friend class base::RefCountedThreadSafe<ConnectivityChecker>;
+
+ // UrlRequest::Delegate implementation:
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
+
+ // Initializes ConnectivityChecker
+ void Initialize();
+
+ // NetworkChangeNotifier::ConnectionTypeObserver implementation:
+ void OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) override;
+
+ // net::NetworkChangeNotifier::IPAddressObserver implementation:
+ void OnIPAddressChanged() override;
+
+ // Cancels current connectivity checking in progress.
+ void Cancel();
+
+ // Sets connectivity and alerts observers if it has changed
+ void SetConnectivity(bool connected);
+
+ scoped_ptr<GURL> connectivity_check_url_;
+ scoped_ptr<net::URLRequestContext> url_request_context_;
+ scoped_ptr<net::URLRequest> url_request_;
+ const scoped_refptr<ObserverListThreadSafe<ConnectivityObserver> >
+ connectivity_observer_list_;
+ const scoped_refptr<base::MessageLoopProxy> loop_proxy_;
+ bool connected_;
+ unsigned int bad_responses_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectivityChecker);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_NET_CONNECTIVITY_CHECKER_H_
diff --git a/chromium/chromecast/net/net_switches.cc b/chromium/chromecast/net/net_switches.cc
new file mode 100644
index 00000000000..d50b1d88b64
--- /dev/null
+++ b/chromium/chromecast/net/net_switches.cc
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/net/net_switches.h"
+
+namespace switches {
+
+// Url for network connectivity checking. Default is
+// "https://clients3.google.com/generate_204".
+const char kConnectivityCheckUrl[] = "connectivity-check-url";
+
+// List of network interfaces to ignore. Ignored interfaces will not be used
+// for network connectivity.
+const char kNetifsToIgnore[] = "netifs-to-ignore";
+
+} // namespace switches
diff --git a/chromium/chromecast/net/net_switches.h b/chromium/chromecast/net/net_switches.h
new file mode 100644
index 00000000000..d8c71f34db5
--- /dev/null
+++ b/chromium/chromecast/net/net_switches.h
@@ -0,0 +1,15 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_NET_NET_SWITCHES_H_
+#define CHROMECAST_NET_NET_SWITCHES_H_
+
+namespace switches {
+
+extern const char kConnectivityCheckUrl[];
+extern const char kNetifsToIgnore[];
+
+} // namespace switches
+
+#endif // CHROMECAST_NET_NET_SWITCHES_H_
diff --git a/chromium/chromecast/net/net_util_cast.cc b/chromium/chromecast/net/net_util_cast.cc
new file mode 100644
index 00000000000..6e688316c8a
--- /dev/null
+++ b/chromium/chromecast/net/net_util_cast.cc
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/net/net_util_cast.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_split.h"
+#include "chromecast/base/cast_sys_info_util.h"
+#include "chromecast/net/net_switches.h"
+#include "chromecast/public/cast_sys_info.h"
+
+namespace chromecast {
+
+base::hash_set<std::string> GetIgnoredInterfaces() {
+ base::hash_set<std::string> ignored_interfaces;
+ scoped_ptr<CastSysInfo> sys_info = CreateSysInfo();
+ if (!sys_info->GetApInterface().empty())
+ ignored_interfaces.insert(sys_info->GetApInterface());
+
+ // Add interfaces from "netif-to-ignore" switch.
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringType netifs_to_ignore_str =
+ command_line->GetSwitchValueNative(switches::kNetifsToIgnore);
+ base::CommandLine::StringVector netifs_to_ignore_vector;
+ base::SplitString(netifs_to_ignore_str, ',', &netifs_to_ignore_vector);
+ for (const auto& netif : netifs_to_ignore_vector)
+ ignored_interfaces.insert(netif);
+
+ return ignored_interfaces;
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/net/net_util_cast.h b/chromium/chromecast/net/net_util_cast.h
new file mode 100644
index 00000000000..2ec95bbd985
--- /dev/null
+++ b/chromium/chromecast/net/net_util_cast.h
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_NET_NET_UTIL_H_
+#define CHROMECAST_NET_NET_UTIL_H_
+
+#include <string>
+
+#include "base/containers/hash_tables.h"
+
+namespace chromecast {
+
+// Gets the list of interfaces that should be ignored. The interfaces returned
+// by this function will not be used to connect to the internet.
+base::hash_set<std::string> GetIgnoredInterfaces();
+
+} // namespace chromecast
+
+#endif // CHROMECAST_NET_NET_UTIL_CAST_H_
diff --git a/chromium/chromecast/net/network_change_notifier_cast.cc b/chromium/chromecast/net/network_change_notifier_cast.cc
deleted file mode 100644
index ab6a218b189..00000000000
--- a/chromium/chromecast/net/network_change_notifier_cast.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromecast/net/network_change_notifier_cast.h"
-
-namespace chromecast {
-
-NetworkChangeNotifierCast::NetworkChangeNotifierCast() {
-}
-
-NetworkChangeNotifierCast::~NetworkChangeNotifierCast() {
-}
-
-net::NetworkChangeNotifier::ConnectionType
-NetworkChangeNotifierCast::GetCurrentConnectionType() const {
- return net::NetworkChangeNotifier::CONNECTION_NONE;
-}
-
-} // namespace chromecast
diff --git a/chromium/chromecast/net/network_change_notifier_cast.h b/chromium/chromecast/net/network_change_notifier_cast.h
deleted file mode 100644
index adf85607804..00000000000
--- a/chromium/chromecast/net/network_change_notifier_cast.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMECAST_NET_NETWORK_CHANGE_NOTIFIER_CAST_H_
-#define CHROMECAST_NET_NETWORK_CHANGE_NOTIFIER_CAST_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "net/base/network_change_notifier.h"
-
-namespace chromecast {
-
-// TODO(lcwu): http://crbug.com/391064. This is a place holder for
-// cast-specific NetworkChangeNotifier implementation. The actual
-// implementation of this class will come in later CLs.
-class NetworkChangeNotifierCast : public net::NetworkChangeNotifier {
- public:
- NetworkChangeNotifierCast();
- virtual ~NetworkChangeNotifierCast();
-
- // net::NetworkChangeNotifier implementation:
- virtual net::NetworkChangeNotifier::ConnectionType
- GetCurrentConnectionType() const override;
-
- private:
- friend class NetworkChangeNotifierCastTest;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierCast);
-};
-
-} // namespace chromecast
-
-#endif // CHROMECAST_NET_NETWORK_CHANGE_NOTIFIER_CAST_H_
diff --git a/chromium/chromecast/net/network_change_notifier_factory_cast.cc b/chromium/chromecast/net/network_change_notifier_factory_cast.cc
index c446b1e5768..4c1cd604d10 100644
--- a/chromium/chromecast/net/network_change_notifier_factory_cast.cc
+++ b/chromium/chromecast/net/network_change_notifier_factory_cast.cc
@@ -1,16 +1,17 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/net/network_change_notifier_factory_cast.h"
-#include "chromecast/net/network_change_notifier_cast.h"
+#include "chromecast/net/net_util_cast.h"
+#include "net/base/network_change_notifier_linux.h"
namespace chromecast {
net::NetworkChangeNotifier* NetworkChangeNotifierFactoryCast::CreateInstance() {
// Caller assumes ownership.
- return new NetworkChangeNotifierCast();
+ return new net::NetworkChangeNotifierLinux(GetIgnoredInterfaces());
}
NetworkChangeNotifierFactoryCast::~NetworkChangeNotifierFactoryCast() {
diff --git a/chromium/chromecast/net/network_change_notifier_factory_cast.h b/chromium/chromecast/net/network_change_notifier_factory_cast.h
index 281a18d060a..058d5b91c6b 100644
--- a/chromium/chromecast/net/network_change_notifier_factory_cast.h
+++ b/chromium/chromecast/net/network_change_notifier_factory_cast.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -17,12 +17,10 @@ class NetworkChangeNotifierFactoryCast
: public net::NetworkChangeNotifierFactory {
public:
NetworkChangeNotifierFactoryCast() {}
- virtual ~NetworkChangeNotifierFactoryCast();
+ ~NetworkChangeNotifierFactoryCast() override;
// net::NetworkChangeNotifierFactory implementation:
- virtual net::NetworkChangeNotifier* CreateInstance() override;
-
- static NetworkChangeNotifierCast* GetInstance();
+ net::NetworkChangeNotifier* CreateInstance() override;
private:
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierFactoryCast);
diff --git a/chromium/chromecast/public/DEPS b/chromium/chromecast/public/DEPS
new file mode 100644
index 00000000000..30d9ea2d336
--- /dev/null
+++ b/chromium/chromecast/public/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ # chromecast/public should not depend on anything Chromium specific
+ "-chromecast",
+ "-base",
+ "-content",
+ "-net",
+ "-ui",
+]
diff --git a/chromium/chromecast/public/cast_egl_platform.h b/chromium/chromecast/public/cast_egl_platform.h
new file mode 100644
index 00000000000..c1350f6964f
--- /dev/null
+++ b/chromium/chromecast/public/cast_egl_platform.h
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_CAST_EGL_PLATFORM_H_
+#define CHROMECAST_PUBLIC_CAST_EGL_PLATFORM_H_
+
+namespace chromecast {
+
+struct Size;
+
+// Interface representing all the hardware-specific elements of an Ozone
+// implementation for Cast. Supply an implementation of this interface
+// to OzonePlatformCast to create a complete Ozone implementation.
+class CastEglPlatform {
+ public:
+ typedef void* (*GLGetProcAddressProc)(const char* name);
+ typedef void* NativeDisplayType;
+ typedef void* NativeWindowType;
+
+ virtual ~CastEglPlatform() {}
+
+ // Returns an array of EGL properties, which can be used in any EGL function
+ // used to select a display configuration. Note that all properties should be
+ // immediately followed by the corresponding desired value and array should be
+ // terminated with EGL_NONE. Ownership of the array is not transferred to
+ // caller. desired_list contains list of desired EGL properties and values.
+ virtual const int* GetEGLSurfaceProperties(const int* desired_list) = 0;
+
+ // Initialize/ShutdownHardware are called at most once each over the object's
+ // lifetime. Initialize will be called before creating display type or
+ // window. If Initialize fails, return false (Shutdown will still be called).
+ virtual bool InitializeHardware() = 0;
+ virtual void ShutdownHardware() = 0;
+
+ // These three are called once after hardware is successfully initialized.
+ // The implementation must load the libraries containing EGL and GLES2
+ // bindings (return the pointer obtained from dlopen). It must also supply
+ // a function pointer to eglGetProcAddress or equivalent.
+ virtual void* GetEglLibrary() = 0;
+ virtual void* GetGles2Library() = 0;
+ virtual GLGetProcAddressProc GetGLProcAddressProc() = 0;
+
+ // Creates/destroys an EGLNativeDisplayType. These may be called multiple
+ // times over the object's lifetime, for example to release the display when
+ // switching to an external application. There will be at most one display
+ // type at a time.
+ virtual NativeDisplayType CreateDisplayType(const Size& size) = 0;
+ virtual void DestroyDisplayType(NativeDisplayType display_type) = 0;
+
+ // Creates/destroys an EGLNativeWindow. There will be at most one window at a
+ // time, created within a valid display type.
+ virtual NativeWindowType CreateWindow(NativeDisplayType display_type,
+ const Size& size) = 0;
+ virtual void DestroyWindow(NativeWindowType window) = 0;
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_CAST_EGL_PLATFORM_H_
diff --git a/chromium/chromecast/public/cast_egl_platform_shlib.h b/chromium/chromecast/public/cast_egl_platform_shlib.h
new file mode 100644
index 00000000000..4a091406f1a
--- /dev/null
+++ b/chromium/chromecast/public/cast_egl_platform_shlib.h
@@ -0,0 +1,25 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_CAST_EGL_PLATFORM_SHLIB_H_
+#define CHROMECAST_PUBLIC_CAST_EGL_PLATFORM_SHLIB_H_
+
+#include <string>
+#include <vector>
+
+#include "chromecast_export.h"
+
+namespace chromecast {
+
+class CastEglPlatform;
+
+// Entry point for loading CastEglPlatform from shared library.
+class CHROMECAST_EXPORT CastEglPlatformShlib {
+ public:
+ static CastEglPlatform* Create(const std::vector<std::string>& argv);
+};
+
+}
+
+#endif // CHROMECAST_PUBLIC_CAST_EGL_PLATFORM_SHLIB_H_
diff --git a/chromium/chromecast/public/cast_media_shlib.h b/chromium/chromecast/public/cast_media_shlib.h
new file mode 100644
index 00000000000..6f2d60d6cd1
--- /dev/null
+++ b/chromium/chromecast/public/cast_media_shlib.h
@@ -0,0 +1,40 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_CAST_MEDIA_SHLIB_H_
+#define CHROMECAST_PUBLIC_CAST_MEDIA_SHLIB_H_
+
+#include <string>
+#include <vector>
+
+#include "chromecast_export.h"
+
+namespace chromecast {
+namespace media {
+
+// Provides access to platform-specific media systems and hardware resources.
+// In cast_shell, all usage is from the browser process. An implementation is
+// assumed to be in an uninitialized state initially. When uninitialized, no
+// API calls will be made except for Initialize, which brings the implementation
+// into an initialized state. A call to Finalize returns the implementation to
+// its uninitialized state. The implementation must support multiple
+// transitions between these states, to support resource grant/revoke events and
+// also to allow multiple unit tests to bring up the media systems in isolation
+// from other tests.
+class CHROMECAST_EXPORT CastMediaShlib {
+ public:
+ // Initializes platform-specific media systems. Only called when in an
+ // uninitialized state.
+ static void Initialize(const std::vector<std::string>& argv);
+
+ // Tears down platform-specific media systems and returns to the uninitialized
+ // state. The implementation must release all media-related hardware
+ // resources.
+ static void Finalize();
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_CAST_MEDIA_SHLIB_H_
diff --git a/chromium/chromecast/public/cast_sys_info.h b/chromium/chromecast/public/cast_sys_info.h
new file mode 100644
index 00000000000..6297f5b3e2e
--- /dev/null
+++ b/chromium/chromecast/public/cast_sys_info.h
@@ -0,0 +1,75 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_CAST_SYS_INFO_H_
+#define CHROMECAST_PUBLIC_CAST_SYS_INFO_H_
+
+#include <string>
+#include <vector>
+
+namespace chromecast {
+
+// Pure abstract interface for system information which is accessed by other
+// processes as well as cast_shell browser process. All information should be
+// immutable.
+// It should be possible to instantiate multiple instances of CastSysInfo and
+// should be able to be instantiated at any point in the startup process. Other
+// processes must be able to create an instance of CastSysInfo.
+class CastSysInfo {
+ public:
+ enum BuildType {
+ BUILD_ENG,
+ BUILD_BETA,
+ BUILD_PRODUCTION,
+ };
+
+ virtual ~CastSysInfo() {}
+
+ // Returns the system build type.
+ virtual BuildType GetBuildType() = 0;
+ // Returns release channel of system.
+ virtual std::string GetSystemReleaseChannel() = 0;
+ // Returns serial number of the device.
+ virtual std::string GetSerialNumber() = 0;
+ // Returns product code name of the device.
+ virtual std::string GetProductName() = 0;
+ // Returns model name of device (eg: Chromecast, Nexus Player, ...).
+ virtual std::string GetDeviceModel() = 0;
+ // Returns the board's name.
+ virtual std::string GetBoardName() = 0;
+ // Returns the revision of board (eg: 514, ...).
+ virtual std::string GetBoardRevision() = 0;
+ // Returns device manufacturer (eg: Google, ...).
+ virtual std::string GetManufacturer() = 0;
+ // Returns the system's build number (eg: 100, 20000 ...).
+ // This describes system version which may be different with
+ // CAST_BUILD_NUMBER.
+ virtual std::string GetSystemBuildNumber() = 0;
+
+ // Returns default country and locale baked from the factory.
+ virtual std::string GetFactoryCountry() = 0;
+ virtual std::string GetFactoryLocale(std::string* second_locale) = 0;
+
+ // Returns the name of the wifi interface used to connect to the internet.
+ virtual std::string GetWifiInterface() = 0;
+ // Returns the name of the software AP interface.
+ virtual std::string GetApInterface() = 0;
+
+ // Returns the GL_VENDOR string of GPU driver. Must match the value that would
+ // be obtained from a GL context, but implementations must *not* create a GL
+ // context.
+ virtual std::string GetGlVendor() = 0;
+ // Returns the GL_RENDERER string of GPU driver. Must match the value that
+ // would be obtained from a GL context, but implementations must *not* create
+ // a GL context.
+ virtual std::string GetGlRenderer() = 0;
+ // Returns the GL_VERSION string of GPU driver. Must match the value that
+ // would be obtained from a GL context, but implementations must *not* create
+ // a GL context.
+ virtual std::string GetGlVersion() = 0;
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_CAST_SYS_INFO_H_
diff --git a/chromium/chromecast/public/chromecast_export.h b/chromium/chromecast/public/chromecast_export.h
new file mode 100644
index 00000000000..022ffc7843a
--- /dev/null
+++ b/chromium/chromecast/public/chromecast_export.h
@@ -0,0 +1,12 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_CHROMECAST_EXPORT_H_
+#define CHROMECAST_PUBLIC_CHROMECAST_EXPORT_H_
+
+// Export attribute for classes that are exposed in shared libraries,
+// allowing OEM partners to replace with their own implementations.
+#define CHROMECAST_EXPORT __attribute__((visibility("default")))
+
+#endif // CHROMECAST_PUBLIC_CHROMECAST_EXPORT_H_
diff --git a/chromium/chromecast/public/graphics_properties_shlib.h b/chromium/chromecast/public/graphics_properties_shlib.h
new file mode 100644
index 00000000000..693a7c1c52d
--- /dev/null
+++ b/chromium/chromecast/public/graphics_properties_shlib.h
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_GRAPHICS_PROPERTIES_SHLIB_H_
+#define CHROMECAST_PUBLIC_GRAPHICS_PROPERTIES_SHLIB_H_
+
+#include <string>
+#include <vector>
+
+#include "chromecast_export.h"
+
+namespace chromecast {
+
+class CHROMECAST_EXPORT GraphicsPropertiesShlib {
+ public:
+ // Optional resolutions that cast_shell queries for. 720p (1280x720) is
+ // assumed to be supported.
+ enum Resolution {
+ k1080p, // 1920x1080
+ kUHDTV // 3840x2160
+ };
+
+ // Returns whether or not the given display resolution is supported.
+ // Called in the browser process; command line args are provided.
+ static bool IsSupported(Resolution resolution,
+ const std::vector<std::string>& argv);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_GRAPHICS_PROPERTIES_SHLIB_H_
diff --git a/chromium/chromecast/public/graphics_types.h b/chromium/chromecast/public/graphics_types.h
new file mode 100644
index 00000000000..09ac12ba29b
--- /dev/null
+++ b/chromium/chromecast/public/graphics_types.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_GRAPHICS_TYPES_H_
+#define CHROMECAST_PUBLIC_GRAPHICS_TYPES_H_
+
+namespace chromecast {
+
+struct Rect {
+ Rect(int w, int h) : x(0), y(0), width(w), height(h) {}
+ Rect(int arg_x, int arg_y, int w, int h)
+ : x(arg_x), y(arg_y), width(w), height(h) {}
+
+ int x;
+ int y;
+ int width;
+ int height;
+};
+
+struct Size {
+ Size(int w, int h) : width(w), height(h) {}
+
+ int width;
+ int height;
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_GRAPHICS_TYPES_H_
diff --git a/chromium/chromecast/public/media/decoder_config.h b/chromium/chromecast/public/media/decoder_config.h
new file mode 100644
index 00000000000..b1077af5763
--- /dev/null
+++ b/chromium/chromecast/public/media/decoder_config.h
@@ -0,0 +1,157 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_MEDIA_DECODER_CONFIG_H_
+#define CHROMECAST_PUBLIC_MEDIA_DECODER_CONFIG_H_
+
+#include <stdint.h>
+#include <vector>
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+// Maximum audio bytes per sample.
+static const int kMaxBytesPerSample = 4;
+
+// Maximum audio sampling rate.
+static const int kMaxSampleRate = 192000;
+
+} // namespace
+
+enum AudioCodec {
+ kAudioCodecUnknown = -1,
+
+ kAudioCodecMin = 0,
+ kCodecAAC = kAudioCodecMin,
+ kCodecMP3,
+ kCodecPCM,
+ kCodecPCM_S16BE,
+ kCodecVorbis,
+ kCodecOpus,
+ kCodecEAC3,
+ kCodecAC3,
+ kCodecDTS,
+ kAudioCodecMax = kCodecDTS,
+};
+
+enum VideoCodec {
+ kVideoCodecUnknown = -1,
+
+ kVideoCodecMin = 0,
+ kCodecH264 = kVideoCodecMin,
+ kCodecVC1,
+ kCodecMPEG2,
+ kCodecMPEG4,
+ kCodecTheora,
+ kCodecVP8,
+ kCodecVP9,
+ kCodecHEVC,
+ kVideoCodecMax = kCodecHEVC,
+};
+
+// Profile for Video codec.
+enum VideoProfile {
+ kVideoProfileUnknown = -1,
+
+ kVideoProfileMin = 0,
+ kH264Baseline = kVideoProfileMin,
+ kH264Main,
+ kH264Extended,
+ kH264High,
+ kH264High10,
+ kH264High422,
+ kH264High444Predictive,
+ kH264ScalableBaseline,
+ kH264ScalableHigh,
+ kH264Stereohigh,
+ kH264MultiviewHigh,
+ kVP8ProfileAny,
+ kVP9ProfileAny,
+ kVideoProfileMax = kVP9ProfileAny,
+};
+
+// TODO(erickung): Remove constructor once CMA backend implementation does't
+// create a new object to reset the configuration and use IsValidConfig() to
+// determine if the configuration is still valid or not.
+struct AudioConfig {
+ AudioConfig()
+ : codec(kAudioCodecUnknown),
+ bytes_per_channel(0),
+ channel_number(0),
+ samples_per_second(0),
+ extra_data(nullptr),
+ extra_data_size(0),
+ is_encrypted(false) {}
+
+ // Audio codec.
+ AudioCodec codec;
+ // Number of bytes in each channel.
+ int bytes_per_channel;
+ // Number of channels in this audio stream.
+ int channel_number;
+ // Number of audio samples per second.
+ int samples_per_second;
+ // Pointer to extra data buffer for certain codec initialization. The memory
+ // is allocated outside this structure. Consumers of the structure should make
+ // a copy if it is expected to be used beyond the function ends.
+ const uint8_t* extra_data;
+ // Size of extra data in bytes.
+ int extra_data_size;
+ // content is encrypted or not.
+ bool is_encrypted;
+};
+
+// TODO(erickung): Remove constructor once CMA backend implementation does't
+// create a new object to reset the configuration and use IsValidConfig() to
+// determine if the configuration is still valid or not.
+struct VideoConfig {
+ VideoConfig()
+ : codec(kVideoCodecUnknown),
+ profile(kVideoProfileUnknown),
+ additional_config(nullptr),
+ extra_data(nullptr),
+ extra_data_size(0),
+ is_encrypted(false) {}
+
+ // Video codec.
+ VideoCodec codec;
+ // Video codec profile.
+ VideoProfile profile;
+ // Both |additional_config| and |extra_data| are the pointers to the object
+ // memory that are allocated outside this structure. Consumers of the
+ // structure should make a copy if it is expected to be used beyond the
+ // function ends.
+ // Additional video config for the video stream if available.
+ VideoConfig* additional_config;
+ // Pointer to extra data buffer for certain codec initialization.
+ const uint8_t* extra_data;
+ // Size of extra data in bytes.
+ int extra_data_size;
+ // content is encrypted or not.
+ bool is_encrypted;
+};
+
+// TODO(erickung): Remove following two inline IsValidConfig() functions. These
+// are to keep existing CMA backend implementation consistent until the clean up
+// is done. These SHOULD NOT be used in New CMA backend implementation.
+inline bool IsValidConfig(const AudioConfig& config) {
+ return config.codec >= kAudioCodecMin &&
+ config.codec <= kAudioCodecMax &&
+ config.channel_number > 0 &&
+ config.bytes_per_channel > 0 &&
+ config.bytes_per_channel <= kMaxBytesPerSample &&
+ config.samples_per_second > 0 &&
+ config.samples_per_second <= kMaxSampleRate;
+}
+
+inline bool IsValidConfig(const VideoConfig& config) {
+ return config.codec >= kVideoCodecMin && config.codec <= kVideoCodecMax;
+}
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_MEDIA_DECODER_CONFIG_H_
diff --git a/chromium/chromecast/public/osd_plane.h b/chromium/chromecast/public/osd_plane.h
new file mode 100644
index 00000000000..d689cba5440
--- /dev/null
+++ b/chromium/chromecast/public/osd_plane.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_OSD_PLANE_H_
+#define CHROMECAST_PUBLIC_OSD_PLANE_H_
+
+namespace chromecast {
+
+class OsdSurface;
+struct Rect;
+struct Size;
+
+// Abstract graphics plane for OSD, to be implemented in platform-specific way.
+// Platform must composite this plane on top of main (GL-based) graphics plane.
+class OsdPlane {
+ public:
+ virtual ~OsdPlane() {}
+
+ // Creates a surface for offscreen drawing.
+ virtual OsdSurface* CreateSurface(const Size& size) = 0;
+
+ // Sets a clip rectangle, client should call before drawing to back buffer
+ // to specify the area they intend to draw on. Platforms may reduce memory
+ // usage by only allocating back buffer to cover this area. Areas outside
+ // clip rectangle must display as fully transparent. In particular, setting
+ // an empty clip rectangle and calling Flip should clear the plane.
+ virtual void SetClipRectangle(const Rect& rect) = 0;
+
+ // Gets the current back buffer surface. Valid until next call to Flip or
+ // SetClipRectangle.
+ virtual OsdSurface* GetBackBuffer() = 0;
+
+ // Presents current back buffer to screen.
+ virtual void Flip() = 0;
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_OSD_PLANE_H
diff --git a/chromium/chromecast/public/osd_plane_shlib.h b/chromium/chromecast/public/osd_plane_shlib.h
new file mode 100644
index 00000000000..0ee170b019e
--- /dev/null
+++ b/chromium/chromecast/public/osd_plane_shlib.h
@@ -0,0 +1,25 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_OSD_PLANE_SHLIB_H_
+#define CHROMECAST_PUBLIC_OSD_PLANE_SHLIB_H_
+
+#include <string>
+#include <vector>
+
+#include "chromecast_export.h"
+
+namespace chromecast {
+
+class OsdPlane;
+
+// Entry point for loading OsdPlane from shared library.
+class CHROMECAST_EXPORT OsdPlaneShlib {
+ public:
+ static OsdPlane* Create(const std::vector<std::string>& argv);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_OSD_PLANE_SHLIB_H_
diff --git a/chromium/chromecast/public/osd_surface.h b/chromium/chromecast/public/osd_surface.h
new file mode 100644
index 00000000000..c83c0654993
--- /dev/null
+++ b/chromium/chromecast/public/osd_surface.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_PUBLIC_OSD_SURFACE_H_
+#define CHROMECAST_PUBLIC_OSD_SURFACE_H_
+
+namespace chromecast {
+
+struct Rect;
+struct Size;
+
+// Provides simple API (copy bitmap, blit, composite and fill) for drawing
+// OSD graphics on OsdPlane. Hardware-specific implementation should be
+// instantiated by OsdPlane.
+class OsdSurface {
+ public:
+ struct Point {
+ Point(int arg_x, int arg_y) : x(arg_x), y(arg_y) {}
+
+ const int x;
+ const int y;
+ };
+
+ virtual ~OsdSurface() {}
+
+ // Blits(fast copy) bitmap from a surface. Copies |src_rect| area of surface
+ // |dst_point| of this surface.
+ virtual void Blit(OsdSurface* src_surface,
+ const Rect& src_rect,
+ const Point& dst_point) = 0;
+
+ // Composites ARGB values of |src_surface| on top of this surface. It is NOT
+ // copy. Used when displaying OSD images on same plane.
+ virtual void Composite(OsdSurface* src_surface,
+ const Rect& src_rect,
+ const Point& dst_point) = 0;
+
+ // Copies |damage_rect| area of src bitmap into |dst_point| of this surface.
+ // It is similar to Blit() except that it accepts arbitrary bitmap pointer
+ // instead of surface.
+ virtual void CopyBitmap(char* src_bitmap,
+ const Rect& src_rect,
+ const Rect& damage_rect,
+ const Point& dst_point) = 0;
+
+ // Fills |rect| area of surface with |argb| value.
+ virtual void Fill(const Rect& rect, int argb) = 0;
+
+ // Returns the dimensions of the surface.
+ virtual const Size& size() const = 0;
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_PUBLIC_OSD_SURFACE_H_
diff --git a/chromium/chromecast/renderer/DEPS b/chromium/chromecast/renderer/DEPS
index 790b870ae3c..1015677bcbc 100644
--- a/chromium/chromecast/renderer/DEPS
+++ b/chromium/chromecast/renderer/DEPS
@@ -1,8 +1,12 @@
include_rules = [
+ "+chromecast/common",
+ "+chromecast/crash",
"+chromecast/media",
"+components/cdm/renderer",
+ "+components/network_hints/renderer",
"+content/public/renderer",
"+media/base",
+ "+media/renderers",
"+third_party/WebKit/public/platform",
"+third_party/WebKit/public/web",
]
diff --git a/chromium/chromecast/renderer/cast_content_renderer_client.cc b/chromium/chromecast/renderer/cast_content_renderer_client.cc
index 2a3c4d5bc77..cfce89371aa 100644
--- a/chromium/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromium/chromecast/renderer/cast_content_renderer_client.cc
@@ -8,10 +8,21 @@
#include "base/command_line.h"
#include "base/memory/memory_pressure_listener.h"
+#include "base/strings/string_number_conversions.h"
+#include "chromecast/common/chromecast_switches.h"
+#include "chromecast/crash/cast_crash_keys.h"
+#include "chromecast/media/base/media_caps.h"
+#include "chromecast/renderer/cast_media_load_deferrer.h"
+#include "chromecast/renderer/cast_render_process_observer.h"
#include "chromecast/renderer/key_systems_cast.h"
+#include "chromecast/renderer/media/chromecast_media_renderer_factory.h"
+#include "components/network_hints/renderer/prescient_networking_dispatcher.h"
#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/render_view_observer.h"
#include "crypto/nss_util.h"
+#include "ipc/message_filter.h"
#include "third_party/WebKit/public/platform/WebColor.h"
#include "third_party/WebKit/public/web/WebSettings.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -21,22 +32,108 @@ namespace shell {
namespace {
+#if defined(ARCH_CPU_ARM_FAMILY) && !defined(OS_ANDROID)
+// This memory threshold is set for Chromecast. See the UMA histogram
+// Platform.MeminfoMemFree when tuning.
+// TODO(gunsch): These should be platform/product-dependent. Look into a way
+// to move these to platform-specific repositories.
+const int kCriticalMinFreeMemMB = 24;
+const int kPollingIntervalMS = 5000;
+
+void PlatformPollFreemem(void) {
+ struct sysinfo sys;
+
+ if (sysinfo(&sys) == -1) {
+ LOG(ERROR) << "platform_poll_freemem(): sysinfo failed";
+ } else {
+ int free_mem_mb = static_cast<int64_t>(sys.freeram) *
+ sys.mem_unit / (1024 * 1024);
+
+ if (free_mem_mb <= kCriticalMinFreeMemMB) {
+ // Memory is getting really low, we need to do whatever we can to
+ // prevent deadlocks and interfering with other processes.
+ base::MemoryPressureListener::NotifyMemoryPressure(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
+ }
+ }
+
+ // Setup next poll.
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&PlatformPollFreemem),
+ base::TimeDelta::FromMilliseconds(kPollingIntervalMS));
+}
+#endif
+
// Default background color to set for WebViews. WebColor is in ARGB format
// though the comment of WebColor says it is in RGBA.
const blink::WebColor kColorBlack = 0xFF000000;
+class CastRenderViewObserver : content::RenderViewObserver {
+ public:
+ explicit CastRenderViewObserver(content::RenderView* render_view);
+ ~CastRenderViewObserver() override {}
+
+ void DidClearWindowObject(blink::WebLocalFrame* frame) override;
+};
+
+CastRenderViewObserver::CastRenderViewObserver(content::RenderView* render_view)
+ : content::RenderViewObserver(render_view) {
+}
+
+void CastRenderViewObserver::DidClearWindowObject(blink::WebLocalFrame* frame) {
+ PlatformAddRendererNativeBindings(frame);
+}
+
} // namespace
+CastContentRendererClient::CastContentRendererClient() {
+}
+
+CastContentRendererClient::~CastContentRendererClient() {
+}
+
void CastContentRendererClient::RenderThreadStarted() {
-#if defined(USE_NSS)
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+#if defined(USE_NSS_CERTS)
// Note: Copied from chrome_render_process_observer.cc to fix b/8676652.
//
// On platforms where the system NSS shared libraries are used,
// initialize NSS now because it won't be able to load the .so's
// after entering the sandbox.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
+ if (!command_line->HasSwitch(switches::kSingleProcess))
crypto::InitNSSSafely();
#endif
+
+#if defined(ARCH_CPU_ARM_FAMILY) && !defined(OS_ANDROID)
+ PlatformPollFreemem();
+#endif
+
+ // Set the initial known codecs mask.
+ if (command_line->HasSwitch(switches::kHdmiSinkSupportedCodecs)) {
+ int hdmi_codecs_mask;
+ if (base::StringToInt(command_line->GetSwitchValueASCII(
+ switches::kHdmiSinkSupportedCodecs),
+ &hdmi_codecs_mask)) {
+ ::media::SetHdmiSinkCodecs(hdmi_codecs_mask);
+ }
+ }
+
+ cast_observer_.reset(
+ new CastRenderProcessObserver(PlatformGetRendererMessageFilters()));
+
+ prescient_networking_dispatcher_.reset(
+ new network_hints::PrescientNetworkingDispatcher());
+
+ std::string last_launched_app =
+ command_line->GetSwitchValueNative(switches::kLastLaunchedApp);
+ if (!last_launched_app.empty())
+ base::debug::SetCrashKeyValue(crash_keys::kLastApp, last_launched_app);
+
+ std::string previous_app =
+ command_line->GetSwitchValueNative(switches::kPreviousApp);
+ if (!previous_app.empty())
+ base::debug::SetCrashKeyValue(crash_keys::kPreviousApp, previous_app);
}
void CastContentRendererClient::RenderViewCreated(
@@ -49,7 +146,21 @@ void CastContentRendererClient::RenderViewCreated(
// embedders, though Android has enabled by default for mobile browsers.
webview->settings()->setShrinksViewportContentToFit(false);
webview->settings()->setMediaControlsOverlayPlayButtonEnabled(false);
+
+ // Scale 1 ensures window.innerHeight/Width match application resolution.
+ // PageScaleOverride is the 'user agent' value which overrides page
+ // settings (from meta viewport tag) - thus preventing inconsistency
+ // between Android and non-Android cast_shell.
+ webview->setDefaultPageScaleLimits(1.f, 1.f);
+ webview->setInitialPageScaleOverride(1.f);
+
+ // Disable application cache as Chromecast doesn't support off-line
+ // application running.
+ webview->settings()->setOfflineWebApplicationCacheEnabled(false);
}
+
+ // Note: RenderView will own the lifetime of its observer.
+ new CastRenderViewObserver(render_view);
}
void CastContentRendererClient::AddKeySystems(
@@ -58,5 +169,37 @@ void CastContentRendererClient::AddKeySystems(
AddChromecastPlatformKeySystems(key_systems);
}
+#if !defined(OS_ANDROID)
+scoped_ptr<::media::RendererFactory>
+CastContentRendererClient::CreateMediaRendererFactory(
+ ::content::RenderFrame* render_frame,
+ const scoped_refptr<::media::MediaLog>& media_log) {
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ if (!cmd_line->HasSwitch(switches::kEnableCmaMediaPipeline))
+ return nullptr;
+
+ return scoped_ptr<::media::RendererFactory>(
+ new chromecast::media::ChromecastMediaRendererFactory(
+ media_log, render_frame->GetRoutingID()));
+}
+#endif
+
+blink::WebPrescientNetworking*
+CastContentRendererClient::GetPrescientNetworking() {
+ return prescient_networking_dispatcher_.get();
+}
+
+void CastContentRendererClient::DeferMediaLoad(
+ content::RenderFrame* render_frame,
+ const base::Closure& closure) {
+ if (!render_frame->IsHidden()) {
+ closure.Run();
+ return;
+ }
+
+ // Lifetime is tied to |render_frame| via content::RenderFrameObserver.
+ new CastMediaLoadDeferrer(render_frame, closure);
+}
+
} // namespace shell
} // namespace chromecast
diff --git a/chromium/chromecast/renderer/cast_content_renderer_client.h b/chromium/chromecast/renderer/cast_content_renderer_client.h
index e7d4654d5d0..efdc3a5a9f6 100644
--- a/chromium/chromecast/renderer/cast_content_renderer_client.h
+++ b/chromium/chromecast/renderer/cast_content_renderer_client.h
@@ -5,21 +5,56 @@
#ifndef CHROMECAST_RENDERER_CAST_CONTENT_RENDERER_CLIENT_H_
#define CHROMECAST_RENDERER_CAST_CONTENT_RENDERER_CLIENT_H_
+#include <vector>
+
+#include "base/macros.h"
#include "content/public/renderer/content_renderer_client.h"
+namespace IPC {
+class MessageFilter;
+}
+
+namespace network_hints {
+class PrescientNetworkingDispatcher;
+} // namespace network_hints
+
namespace chromecast {
namespace shell {
+class CastRenderProcessObserver;
+
+// Adds any platform-specific bindings to the current frame.
+void PlatformAddRendererNativeBindings(blink::WebLocalFrame* frame);
class CastContentRendererClient : public content::ContentRendererClient {
public:
- CastContentRendererClient() {}
- virtual ~CastContentRendererClient() {}
+ CastContentRendererClient();
+ ~CastContentRendererClient() override;
+
+ // Returns any MessageFilters from the platform implementation that should
+ // be added to the render process.
+ std::vector<scoped_refptr<IPC::MessageFilter>>
+ PlatformGetRendererMessageFilters();
// ContentRendererClient implementation:
- virtual void RenderThreadStarted() override;
- virtual void RenderViewCreated(content::RenderView* render_view) override;
- virtual void AddKeySystems(
+ void RenderThreadStarted() override;
+ void RenderViewCreated(content::RenderView* render_view) override;
+ void AddKeySystems(
std::vector< ::media::KeySystemInfo>* key_systems) override;
+#if !defined(OS_ANDROID)
+ scoped_ptr<media::RendererFactory> CreateMediaRendererFactory(
+ content::RenderFrame* render_frame,
+ const scoped_refptr<media::MediaLog>& media_log) override;
+#endif
+ blink::WebPrescientNetworking* GetPrescientNetworking() override;
+ void DeferMediaLoad(content::RenderFrame* render_frame,
+ const base::Closure& closure) override;
+
+ private:
+ scoped_ptr<network_hints::PrescientNetworkingDispatcher>
+ prescient_networking_dispatcher_;
+ scoped_ptr<CastRenderProcessObserver> cast_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(CastContentRendererClient);
};
} // namespace shell
diff --git a/chromium/chromecast/renderer/cast_content_renderer_client_simple.cc b/chromium/chromecast/renderer/cast_content_renderer_client_simple.cc
new file mode 100644
index 00000000000..5ad4fccb261
--- /dev/null
+++ b/chromium/chromecast/renderer/cast_content_renderer_client_simple.cc
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/cast_content_renderer_client.h"
+
+#include "ipc/message_filter.h"
+
+namespace chromecast {
+namespace shell {
+
+void PlatformAddRendererNativeBindings(blink::WebLocalFrame* frame) {
+}
+
+std::vector<scoped_refptr<IPC::MessageFilter>>
+CastContentRendererClient::PlatformGetRendererMessageFilters() {
+ return std::vector<scoped_refptr<IPC::MessageFilter>>();
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/renderer/cast_media_load_deferrer.cc b/chromium/chromecast/renderer/cast_media_load_deferrer.cc
new file mode 100644
index 00000000000..0f84657ce70
--- /dev/null
+++ b/chromium/chromecast/renderer/cast_media_load_deferrer.cc
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/cast_media_load_deferrer.h"
+
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+
+namespace chromecast {
+
+CastMediaLoadDeferrer::CastMediaLoadDeferrer(
+ content::RenderFrame* render_frame,
+ const base::Closure& continue_loading_cb)
+ : content::RenderFrameObserver(render_frame),
+ continue_loading_cb_(continue_loading_cb) {
+ DCHECK(!continue_loading_cb_.is_null());
+}
+
+CastMediaLoadDeferrer::~CastMediaLoadDeferrer() {}
+
+void CastMediaLoadDeferrer::WasShown() {
+ continue_loading_cb_.Run();
+ delete this;
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/renderer/cast_media_load_deferrer.h b/chromium/chromecast/renderer/cast_media_load_deferrer.h
new file mode 100644
index 00000000000..72a57ca9bec
--- /dev/null
+++ b/chromium/chromecast/renderer/cast_media_load_deferrer.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_CAST_MEDIA_LOAD_DEFERRER_H_
+#define CHROMECAST_RENDERER_CAST_MEDIA_LOAD_DEFERRER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/public/renderer/render_frame_observer.h"
+
+namespace chromecast {
+
+// Defers media player loading in background web apps until brought into
+// foreground.
+class CastMediaLoadDeferrer : public content::RenderFrameObserver {
+ public:
+ // Will run |closure| to continue loading the media resource once the page is
+ // swapped in.
+ CastMediaLoadDeferrer(content::RenderFrame* render_frame,
+ const base::Closure& continue_loading_cb);
+ ~CastMediaLoadDeferrer() override;
+
+ private:
+ // content::RenderFrameObserver implementation:
+ void WasShown() override;
+
+ base::Closure continue_loading_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(CastMediaLoadDeferrer);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_CAST_MEDIA_LOAD_DEFERRER_H_
diff --git a/chromium/chromecast/renderer/cast_render_process_observer.cc b/chromium/chromecast/renderer/cast_render_process_observer.cc
new file mode 100644
index 00000000000..caba2442a0c
--- /dev/null
+++ b/chromium/chromecast/renderer/cast_render_process_observer.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/cast_render_process_observer.h"
+
+#include "chromecast/renderer/media/capabilities_message_filter.h"
+#include "chromecast/renderer/media/cma_message_filter_proxy.h"
+#include "content/public/renderer/render_thread.h"
+
+namespace chromecast {
+namespace shell {
+
+CastRenderProcessObserver::CastRenderProcessObserver(
+ const std::vector<scoped_refptr<IPC::MessageFilter>>&
+ platform_message_filters)
+ : platform_message_filters_(platform_message_filters) {
+ content::RenderThread* thread = content::RenderThread::Get();
+ thread->AddObserver(this);
+ CreateCustomFilters();
+}
+
+CastRenderProcessObserver::~CastRenderProcessObserver() {
+ // CastRenderProcessObserver outlives content::RenderThread.
+ // No need to explicitly call RemoveObserver in teardown.
+}
+
+void CastRenderProcessObserver::CreateCustomFilters() {
+ content::RenderThread* thread = content::RenderThread::Get();
+#if !defined(OS_ANDROID)
+ cma_message_filter_proxy_ =
+ new media::CmaMessageFilterProxy(thread->GetIOMessageLoopProxy());
+ thread->AddFilter(cma_message_filter_proxy_.get());
+#endif // !defined(OS_ANDROID)
+ capabilities_message_filter_ = new CapabilitiesMessageFilter;
+ thread->AddFilter(capabilities_message_filter_.get());
+ for (const auto& filter : platform_message_filters_) {
+ thread->AddFilter(filter.get());
+ }
+}
+
+void CastRenderProcessObserver::OnRenderProcessShutdown() {
+ content::RenderThread* thread = content::RenderThread::Get();
+#if !defined(OS_ANDROID)
+ if (cma_message_filter_proxy_.get()) {
+ thread->RemoveFilter(cma_message_filter_proxy_.get());
+ cma_message_filter_proxy_ = nullptr;
+ }
+#endif // !defined(OS_ANDROID)
+ if (capabilities_message_filter_.get()) {
+ thread->RemoveFilter(capabilities_message_filter_.get());
+ capabilities_message_filter_ = nullptr;
+ }
+ for (auto& filter : platform_message_filters_) {
+ if (filter.get()) {
+ thread->RemoveFilter(filter.get());
+ filter = nullptr;
+ }
+ }
+ platform_message_filters_.clear();
+}
+
+} // namespace shell
+} // namespace chromecast
diff --git a/chromium/chromecast/renderer/cast_render_process_observer.h b/chromium/chromecast/renderer/cast_render_process_observer.h
new file mode 100644
index 00000000000..479026c5717
--- /dev/null
+++ b/chromium/chromecast/renderer/cast_render_process_observer.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_CAST_RENDER_PROCESS_OBSERVER_H_
+#define CHROMECAST_RENDERER_CAST_RENDER_PROCESS_OBSERVER_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/public/renderer/render_process_observer.h"
+
+namespace IPC {
+class MessageFilter;
+}
+
+namespace chromecast {
+class CapabilitiesMessageFilter;
+namespace media {
+class CmaMessageFilterProxy;
+}
+
+namespace shell {
+
+class CastRenderProcessObserver : public content::RenderProcessObserver {
+ public:
+ CastRenderProcessObserver(
+ const std::vector<scoped_refptr<IPC::MessageFilter>>&
+ platform_message_filters);
+ ~CastRenderProcessObserver() override;
+
+ private:
+ // content::RenderProcessObserver implementation:
+ void OnRenderProcessShutdown() override;
+
+ void CreateCustomFilters();
+
+#if !defined(OS_ANDROID)
+ scoped_refptr<media::CmaMessageFilterProxy> cma_message_filter_proxy_;
+#endif // !defined(OS_ANDROID)
+ scoped_refptr<CapabilitiesMessageFilter> capabilities_message_filter_;
+ std::vector<scoped_refptr<IPC::MessageFilter>> platform_message_filters_;
+
+ DISALLOW_COPY_AND_ASSIGN(CastRenderProcessObserver);
+};
+
+} // namespace shell
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_CAST_RENDER_PROCESS_OBSERVER_H_
diff --git a/chromium/chromecast/renderer/key_systems_cast.cc b/chromium/chromecast/renderer/key_systems_cast.cc
index 919ebbe8028..bede01890c5 100644
--- a/chromium/chromecast/renderer/key_systems_cast.cc
+++ b/chromium/chromecast/renderer/key_systems_cast.cc
@@ -14,29 +14,58 @@
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
+using ::media::EmeFeatureSupport;
+using ::media::EmeRobustness;
+using ::media::EmeSessionTypeSupport;
+
namespace chromecast {
namespace shell {
void AddKeySystemWithCodecs(
const std::string& key_system_name,
- std::vector< ::media::KeySystemInfo>* concrete_key_systems) {
- ::media::KeySystemInfo info(key_system_name);
- info.supported_codecs = ::media::EME_CODEC_MP4_ALL;
- concrete_key_systems->push_back(info);
+ std::vector<::media::KeySystemInfo>* key_systems_info) {
+ ::media::KeySystemInfo info;
+ info.key_system = key_system_name;
+ info.supported_init_data_types = ::media::kInitDataTypeMaskCenc;
+ info.supported_codecs =
+ ::media::EME_CODEC_MP4_AAC | ::media::EME_CODEC_MP4_AVC1;
+ info.max_audio_robustness = ::media::EmeRobustness::EMPTY;
+ info.max_video_robustness = ::media::EmeRobustness::EMPTY;
+ info.persistent_license_support =
+ ::media::EmeSessionTypeSupport::NOT_SUPPORTED;
+ info.persistent_release_message_support =
+ ::media::EmeSessionTypeSupport::NOT_SUPPORTED;
+ info.persistent_state_support = ::media::EmeFeatureSupport::ALWAYS_ENABLED;
+ info.distinctive_identifier_support =
+ ::media::EmeFeatureSupport::ALWAYS_ENABLED;
+ key_systems_info->push_back(info);
}
void AddChromecastKeySystems(
- std::vector< ::media::KeySystemInfo>* key_systems_info) {
+ std::vector<::media::KeySystemInfo>* key_systems_info) {
#if defined(WIDEVINE_CDM_AVAILABLE)
- AddWidevineWithCodecs(cdm::WIDEVINE,
- ::media::EME_CODEC_MP4_ALL,
- key_systems_info);
-#endif
+ ::media::SupportedCodecs codecs =
+ ::media::EME_CODEC_MP4_AAC | ::media::EME_CODEC_MP4_AVC1;
+ AddWidevineWithCodecs(
+ cdm::WIDEVINE,
+ codecs, // Regular codecs.
+#if defined(OS_ANDROID)
+ codecs, // Hardware-secure codecs.
+#endif // defined(OS_ANDROID)
+ EmeRobustness::HW_SECURE_ALL, // Max audio robustness.
+ EmeRobustness::HW_SECURE_ALL, // Max video robustness.
+ EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-license.
+ EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-release-message.
+ // Note: On Chromecast, all CDMs may have persistent state.
+ EmeFeatureSupport::ALWAYS_ENABLED, // Persistent state.
+ EmeFeatureSupport::ALWAYS_ENABLED, // Distinctive identifier.
+ key_systems_info);
+#endif // defined(WIDEVINE_CDM_AVAILABLE)
#if defined(PLAYREADY_CDM_AVAILABLE)
AddKeySystemWithCodecs(media::kChromecastPlayreadyKeySystem,
key_systems_info);
-#endif
+#endif // defined(PLAYREADY_CDM_AVAILABLE)
}
} // namespace shell
diff --git a/chromium/chromecast/renderer/key_systems_cast.h b/chromium/chromecast/renderer/key_systems_cast.h
index 36b21d5d045..c64eb1db708 100644
--- a/chromium/chromecast/renderer/key_systems_cast.h
+++ b/chromium/chromecast/renderer/key_systems_cast.h
@@ -13,16 +13,18 @@ namespace chromecast {
namespace shell {
// Adds a single key system by name.
+// TODO(gunsch): modify this API to accept specifying different supported
+// features, and/or APIs per key system type.
void AddKeySystemWithCodecs(
const std::string& key_system_name,
- std::vector< ::media::KeySystemInfo>* concrete_key_systems);
+ std::vector<::media::KeySystemInfo>* concrete_key_systems);
void AddChromecastKeySystems(
- std::vector< ::media::KeySystemInfo>* key_systems_info);
+ std::vector<::media::KeySystemInfo>* key_systems_info);
// TODO(gunsch): Remove when prefixed EME is removed.
void AddChromecastPlatformKeySystems(
- std::vector< ::media::KeySystemInfo>* key_systems_info);
+ std::vector<::media::KeySystemInfo>* key_systems_info);
} // namespace shell
} // namespace chromecast
diff --git a/chromium/chromecast/renderer/media/audio_pipeline_proxy.cc b/chromium/chromecast/renderer/media/audio_pipeline_proxy.cc
new file mode 100644
index 00000000000..30297a8a549
--- /dev/null
+++ b/chromium/chromecast/renderer/media/audio_pipeline_proxy.cc
@@ -0,0 +1,311 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/audio_pipeline_proxy.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "chromecast/common/media/shared_memory_chunk.h"
+#include "chromecast/media/cma/base/buffering_defs.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/media/cma/ipc/media_message_fifo.h"
+#include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+#include "chromecast/renderer/media/cma_message_filter_proxy.h"
+#include "chromecast/renderer/media/media_channel_proxy.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/pipeline_status.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+void IgnoreResult() {
+}
+
+} // namespace
+
+// AudioPipelineProxyInternal -
+// This class is not thread safe and should run on the same thread
+// as the media channel proxy.
+class AudioPipelineProxyInternal {
+ public:
+ typedef base::Callback<void(scoped_ptr<base::SharedMemory>)> SharedMemCB;
+
+ static void Release(scoped_ptr<AudioPipelineProxyInternal> proxy);
+
+ explicit AudioPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy);
+ virtual ~AudioPipelineProxyInternal();
+
+ // Notify the other side (browser process) of some activity on the audio pipe.
+ // TODO(erickung): either send an IPC message or write a byte on the
+ // SyncSocket.
+ void NotifyPipeWrite();
+
+ // These functions are almost a one to one correspondence with AudioPipeline
+ // but this is an internal class and there is no reason to derive from
+ // AudioPipeline.
+ void SetClient(const base::Closure& pipe_read_cb,
+ const AvPipelineClient& client);
+ void CreateAvPipe(const SharedMemCB& shared_mem_cb);
+ void Initialize(const ::media::AudioDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb);
+ void SetVolume(float volume);
+
+ private:
+ void Shutdown();
+
+ // Callbacks for CmaMessageFilterHost::AudioDelegate.
+ void OnAvPipeCreated(bool status,
+ base::SharedMemoryHandle shared_mem_handle,
+ base::FileDescriptor socket);
+ void OnStateChanged(::media::PipelineStatus status);
+
+ base::ThreadChecker thread_checker_;
+
+ scoped_refptr<MediaChannelProxy> media_channel_proxy_;
+
+ // Store the callback for a pending state transition.
+ ::media::PipelineStatusCB status_cb_;
+
+ SharedMemCB shared_mem_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioPipelineProxyInternal);
+};
+
+// static
+void AudioPipelineProxyInternal::Release(
+ scoped_ptr<AudioPipelineProxyInternal> proxy) {
+ proxy->Shutdown();
+}
+
+AudioPipelineProxyInternal::AudioPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy)
+ : media_channel_proxy_(media_channel_proxy) {
+ DCHECK(media_channel_proxy.get());
+
+ // Creation can be done on a different thread.
+ thread_checker_.DetachFromThread();
+}
+
+AudioPipelineProxyInternal::~AudioPipelineProxyInternal() {
+}
+
+void AudioPipelineProxyInternal::Shutdown() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Remove any callback on AudioPipelineProxyInternal.
+ media_channel_proxy_->SetAudioDelegate(
+ CmaMessageFilterProxy::AudioDelegate());
+}
+
+void AudioPipelineProxyInternal::NotifyPipeWrite() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // TODO(erickung): An alternative way would be to use a dedicated socket for
+ // this event.
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_NotifyPipeWrite(
+ media_channel_proxy_->GetId(), kAudioTrackId)));
+ VLOG_IF(4, !success) << "Sending msg failed";
+}
+
+void AudioPipelineProxyInternal::SetClient(
+ const base::Closure& pipe_read_cb,
+ const AvPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ CmaMessageFilterProxy::AudioDelegate delegate;
+ delegate.av_pipe_cb =
+ base::Bind(&AudioPipelineProxyInternal::OnAvPipeCreated,
+ base::Unretained(this));
+ delegate.state_changed_cb =
+ base::Bind(&AudioPipelineProxyInternal::OnStateChanged,
+ base::Unretained(this));
+ delegate.pipe_read_cb = pipe_read_cb;
+ delegate.client = client;
+ bool success = media_channel_proxy_->SetAudioDelegate(delegate);
+ CHECK(success);
+}
+
+void AudioPipelineProxyInternal::CreateAvPipe(
+ const SharedMemCB& shared_mem_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(shared_mem_cb_.is_null());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_CreateAvPipe(
+ media_channel_proxy_->GetId(), kAudioTrackId, kAppAudioBufferSize)));
+ if (!success) {
+ shared_mem_cb.Run(scoped_ptr<base::SharedMemory>());
+ return;
+ }
+ shared_mem_cb_ = shared_mem_cb;
+}
+
+void AudioPipelineProxyInternal::OnAvPipeCreated(
+ bool success,
+ base::SharedMemoryHandle shared_mem_handle,
+ base::FileDescriptor socket) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!shared_mem_cb_.is_null());
+ if (!success) {
+ shared_mem_cb_.Run(scoped_ptr<base::SharedMemory>());
+ return;
+ }
+
+ CHECK(base::SharedMemory::IsHandleValid(shared_mem_handle));
+ shared_mem_cb_.Run(scoped_ptr<base::SharedMemory>(
+ new base::SharedMemory(shared_mem_handle, false)));
+}
+
+void AudioPipelineProxyInternal::Initialize(
+ const ::media::AudioDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_AudioInitialize(
+ media_channel_proxy_->GetId(), kAudioTrackId, config)));
+ if (!success) {
+ status_cb.Run( ::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ DCHECK(status_cb_.is_null());
+ status_cb_ = status_cb;
+}
+
+void AudioPipelineProxyInternal::SetVolume(float volume) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_SetVolume(media_channel_proxy_->GetId(),
+ kAudioTrackId, volume)));
+}
+
+void AudioPipelineProxyInternal::OnStateChanged(
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!status_cb_.is_null());
+ base::ResetAndReturn(&status_cb_).Run(status);
+}
+
+
+// A macro runs current member function on |io_message_loop_proxy_| thread.
+#define FORWARD_ON_IO_THREAD(param_fn, ...) \
+ io_message_loop_proxy_->PostTask( \
+ FROM_HERE, \
+ base::Bind(&AudioPipelineProxyInternal::param_fn, \
+ base::Unretained(proxy_.get()), ##__VA_ARGS__))
+
+AudioPipelineProxy::AudioPipelineProxy(
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
+ scoped_refptr<MediaChannelProxy> media_channel_proxy)
+ : io_message_loop_proxy_(io_message_loop_proxy),
+ proxy_(new AudioPipelineProxyInternal(media_channel_proxy)),
+ audio_streamer_(new AvStreamerProxy()),
+ weak_factory_(this) {
+ DCHECK(io_message_loop_proxy_.get());
+ weak_this_ = weak_factory_.GetWeakPtr();
+ thread_checker_.DetachFromThread();
+}
+
+AudioPipelineProxy::~AudioPipelineProxy() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Release the underlying object on the right thread.
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioPipelineProxyInternal::Release, base::Passed(&proxy_)));
+}
+
+void AudioPipelineProxy::SetClient(
+ const AvPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ base::Closure pipe_read_cb = ::media::BindToCurrentLoop(
+ base::Bind(&AudioPipelineProxy::OnPipeRead, weak_this_));
+ FORWARD_ON_IO_THREAD(SetClient, pipe_read_cb, client);
+}
+
+void AudioPipelineProxy::Initialize(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "AudioPipelineProxy::Initialize";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ audio_streamer_->SetCodedFrameProvider(frame_provider.Pass());
+
+ AudioPipelineProxyInternal::SharedMemCB shared_mem_cb =
+ ::media::BindToCurrentLoop(base::Bind(
+ &AudioPipelineProxy::OnAvPipeCreated, weak_this_,
+ config, status_cb));
+ FORWARD_ON_IO_THREAD(CreateAvPipe, shared_mem_cb);
+}
+
+void AudioPipelineProxy::OnAvPipeCreated(
+ const ::media::AudioDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb,
+ scoped_ptr<base::SharedMemory> shared_memory) {
+ CMALOG(kLogControl) << "AudioPipelineProxy::OnAvPipeCreated";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!shared_memory ||
+ !shared_memory->Map(kAppAudioBufferSize)) {
+ status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ CHECK(shared_memory->memory());
+
+ scoped_ptr<MediaMemoryChunk> shared_memory_chunk(
+ new SharedMemoryChunk(shared_memory.Pass(), kAppAudioBufferSize));
+ scoped_ptr<MediaMessageFifo> audio_pipe(
+ new MediaMessageFifo(shared_memory_chunk.Pass(), false));
+ audio_pipe->ObserveWriteActivity(
+ base::Bind(&AudioPipelineProxy::OnPipeWrite, weak_this_));
+
+ audio_streamer_->SetMediaMessageFifo(audio_pipe.Pass());
+
+ // Now proceed to the decoder/renderer initialization.
+ FORWARD_ON_IO_THREAD(Initialize, config, status_cb);
+}
+
+void AudioPipelineProxy::StartFeeding() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(audio_streamer_);
+ audio_streamer_->Start();
+}
+
+void AudioPipelineProxy::Flush(const base::Closure& done_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(audio_streamer_);
+ audio_streamer_->StopAndFlush(done_cb);
+}
+
+void AudioPipelineProxy::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!audio_streamer_)
+ return;
+ audio_streamer_->StopAndFlush(base::Bind(&IgnoreResult));
+}
+
+void AudioPipelineProxy::SetVolume(float volume) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetVolume, volume);
+}
+
+void AudioPipelineProxy::OnPipeWrite() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(NotifyPipeWrite);
+}
+
+void AudioPipelineProxy::OnPipeRead() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (audio_streamer_)
+ audio_streamer_->OnFifoReadEvent();
+}
+
+} // namespace cma
+} // namespace chromecast \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/audio_pipeline_proxy.h b/chromium/chromecast/renderer/media/audio_pipeline_proxy.h
new file mode 100644
index 00000000000..b319ee1b8a7
--- /dev/null
+++ b/chromium/chromecast/renderer/media/audio_pipeline_proxy.h
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_AUDIO_PIPELINE_PROXY_H_
+#define CHROMECAST_RENDERER_MEDIA_AUDIO_PIPELINE_PROXY_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/media/cma/pipeline/audio_pipeline.h"
+#include "media/base/pipeline_status.h"
+
+namespace base {
+class MessageLoopProxy;
+class SharedMemory;
+}
+
+namespace media {
+class AudioDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+class AudioPipelineProxyInternal;
+struct AvPipelineClient;
+class AvStreamerProxy;
+class CodedFrameProvider;
+class MediaChannelProxy;
+
+class AudioPipelineProxy : public AudioPipeline {
+ public:
+ AudioPipelineProxy(
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
+ scoped_refptr<MediaChannelProxy> media_channel_proxy);
+ ~AudioPipelineProxy() override;
+
+ void Initialize(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb);
+ void StartFeeding();
+ void Flush(const base::Closure& done_cb);
+ void Stop();
+
+ // AudioPipeline implementation.
+ void SetClient(const AvPipelineClient& client) override;
+ void SetVolume(float volume) override;
+
+ private:
+ base::ThreadChecker thread_checker_;
+
+ void OnAvPipeCreated(
+ const ::media::AudioDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb,
+ scoped_ptr<base::SharedMemory> shared_memory);
+ void OnPipeWrite();
+ void OnPipeRead();
+
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+
+ // |proxy_| main goal is to convert function calls to IPC messages.
+ scoped_ptr<AudioPipelineProxyInternal> proxy_;
+
+ scoped_ptr<AvStreamerProxy> audio_streamer_;
+
+ base::WeakPtr<AudioPipelineProxy> weak_this_;
+ base::WeakPtrFactory<AudioPipelineProxy> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioPipelineProxy);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_AUDIO_PIPELINE_PROXY_H_ \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/capabilities_message_filter.cc b/chromium/chromecast/renderer/media/capabilities_message_filter.cc
new file mode 100644
index 00000000000..fb10972192d
--- /dev/null
+++ b/chromium/chromecast/renderer/media/capabilities_message_filter.cc
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/capabilities_message_filter.h"
+
+#include "chromecast/common/media/cast_messages.h"
+#include "chromecast/media/base/media_caps.h"
+
+namespace chromecast {
+
+CapabilitiesMessageFilter::CapabilitiesMessageFilter() {
+}
+
+CapabilitiesMessageFilter::~CapabilitiesMessageFilter() {
+}
+
+bool CapabilitiesMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(CapabilitiesMessageFilter, message)
+ IPC_MESSAGE_HANDLER(CmaMsg_UpdateSupportedHdmiSinkCodecs,
+ OnUpdateSupportedHdmiSinkCodecs)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void CapabilitiesMessageFilter::OnUpdateSupportedHdmiSinkCodecs(int codecs) {
+ ::media::SetHdmiSinkCodecs(codecs);
+}
+
+} // namespace chromecast
diff --git a/chromium/chromecast/renderer/media/capabilities_message_filter.h b/chromium/chromecast/renderer/media/capabilities_message_filter.h
new file mode 100644
index 00000000000..6c9c1deecd4
--- /dev/null
+++ b/chromium/chromecast/renderer/media/capabilities_message_filter.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_CAPABILITIES_MESSAGE_FILTER_H_
+#define CHROMECAST_RENDERER_MEDIA_CAPABILITIES_MESSAGE_FILTER_H_
+
+#include "ipc/message_filter.h"
+
+namespace chromecast {
+
+class CapabilitiesMessageFilter : public IPC::MessageFilter {
+ public:
+ CapabilitiesMessageFilter();
+
+ // IPC::ChannelProxy::MessageFilter implementation:
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ private:
+ ~CapabilitiesMessageFilter() override;
+
+ void OnUpdateSupportedHdmiSinkCodecs(int codecs);
+
+ DISALLOW_COPY_AND_ASSIGN(CapabilitiesMessageFilter);
+};
+
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_CAPABILITIES_MESSAGE_FILTER_H_
diff --git a/chromium/chromecast/renderer/media/chromecast_media_renderer_factory.cc b/chromium/chromecast/renderer/media/chromecast_media_renderer_factory.cc
new file mode 100644
index 00000000000..62fe7716a3d
--- /dev/null
+++ b/chromium/chromecast/renderer/media/chromecast_media_renderer_factory.cc
@@ -0,0 +1,76 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/chromecast_media_renderer_factory.h"
+
+#include "base/command_line.h"
+#include "chromecast/media/base/switching_media_renderer.h"
+#include "chromecast/media/cma/filters/cma_renderer.h"
+#include "chromecast/renderer/media/media_pipeline_proxy.h"
+#include "content/public/renderer/render_thread.h"
+#include "media/base/audio_hardware_config.h"
+#include "media/base/media_log.h"
+#include "media/renderers/default_renderer_factory.h"
+#include "media/renderers/gpu_video_accelerator_factories.h"
+
+namespace chromecast {
+namespace media {
+
+ChromecastMediaRendererFactory::ChromecastMediaRendererFactory(
+ const scoped_refptr<::media::MediaLog>& media_log,
+ int render_frame_id)
+ : render_frame_id_(render_frame_id),
+ media_log_(media_log) {
+}
+
+ChromecastMediaRendererFactory::~ChromecastMediaRendererFactory() {
+}
+
+scoped_ptr<::media::Renderer> ChromecastMediaRendererFactory::CreateRenderer(
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ ::media::AudioRendererSink* audio_renderer_sink,
+ ::media::VideoRendererSink* video_renderer_sink) {
+ if (!default_render_factory_) {
+ // Chromecast doesn't have input audio devices, so leave this uninitialized
+ ::media::AudioParameters input_audio_params;
+ // TODO(servolk): Audio parameters are hardcoded for now, but in the future
+ // either we need to obtain AudioHardwareConfig from RenderThreadImpl,
+ // or media renderer needs to figure out optimal audio parameters itself.
+ const int kDefaultSamplingRate = 48000;
+ const int kDefaultBitsPerSample = 16;
+ // About 20ms of stereo (2 channels) 16bit (2 byte) audio
+ int buffer_size = kDefaultSamplingRate * 20 * 2 * 2 / 1000;
+ ::media::AudioParameters output_audio_params(
+ ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ ::media::CHANNEL_LAYOUT_STEREO,
+ kDefaultSamplingRate, kDefaultBitsPerSample,
+ buffer_size, ::media::AudioParameters::NO_EFFECTS);
+ ::media::AudioHardwareConfig audio_config(input_audio_params,
+ output_audio_params);
+
+ default_render_factory_.reset(new ::media::DefaultRendererFactory(
+ media_log_, /*gpu_factories*/ nullptr, audio_config));
+ }
+
+ DCHECK(default_render_factory_);
+ // TODO(erickung): crbug.com/443956. Need to provide right LoadType.
+ LoadType cma_load_type = kLoadTypeMediaSource;
+ scoped_ptr<MediaPipeline> cma_media_pipeline(
+ new MediaPipelineProxy(
+ render_frame_id_,
+ content::RenderThread::Get()->GetIOMessageLoopProxy(),
+ cma_load_type));
+ scoped_ptr<CmaRenderer> cma_renderer(
+ new CmaRenderer(cma_media_pipeline.Pass(), video_renderer_sink));
+ scoped_ptr<::media::Renderer> default_media_render(
+ default_render_factory_->CreateRenderer(media_task_runner,
+ audio_renderer_sink,
+ video_renderer_sink));
+ scoped_ptr<SwitchingMediaRenderer> media_renderer(new SwitchingMediaRenderer(
+ default_media_render.Pass(), cma_renderer.Pass()));
+ return media_renderer.Pass();
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/renderer/media/chromecast_media_renderer_factory.h b/chromium/chromecast/renderer/media/chromecast_media_renderer_factory.h
new file mode 100644
index 00000000000..820609478fa
--- /dev/null
+++ b/chromium/chromecast/renderer/media/chromecast_media_renderer_factory.h
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_CHROMECAST_MEDIA_RENDERER_FACTORY_H_
+#define CHROMECAST_RENDERER_MEDIA_CHROMECAST_MEDIA_RENDERER_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "media/base/renderer_factory.h"
+
+namespace media {
+class MediaLog;
+class DefaultRendererFactory;
+}
+
+namespace chromecast {
+namespace media {
+
+class ChromecastMediaRendererFactory : public ::media::RendererFactory {
+ public:
+ ChromecastMediaRendererFactory(
+ const scoped_refptr<::media::MediaLog>& media_log,
+ int render_frame_id);
+ ~ChromecastMediaRendererFactory() final;
+
+ // ::media::RendererFactory implementation.
+ scoped_ptr<::media::Renderer> CreateRenderer(
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ ::media::AudioRendererSink* audio_renderer_sink,
+ ::media::VideoRendererSink* video_renderer_sink) final;
+
+ private:
+ int render_frame_id_;
+ scoped_refptr<::media::MediaLog> media_log_;
+ scoped_ptr<::media::DefaultRendererFactory> default_render_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromecastMediaRendererFactory);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_CHROMECAST_MEDIA_RENDERER_FACTORY_H_
diff --git a/chromium/chromecast/renderer/media/cma_message_filter_proxy.cc b/chromium/chromecast/renderer/media/cma_message_filter_proxy.cc
new file mode 100644
index 00000000000..f2701a98725
--- /dev/null
+++ b/chromium/chromecast/renderer/media/cma_message_filter_proxy.cc
@@ -0,0 +1,272 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/cma_message_filter_proxy.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_sender.h"
+
+namespace chromecast {
+namespace media {
+
+CmaMessageFilterProxy::MediaDelegate::MediaDelegate() {
+}
+
+CmaMessageFilterProxy::MediaDelegate::~MediaDelegate() {
+}
+
+CmaMessageFilterProxy::AudioDelegate::AudioDelegate() {
+}
+
+CmaMessageFilterProxy::AudioDelegate::~AudioDelegate() {
+}
+
+CmaMessageFilterProxy::VideoDelegate::VideoDelegate() {
+}
+
+CmaMessageFilterProxy::VideoDelegate::~VideoDelegate() {
+}
+
+CmaMessageFilterProxy::DelegateEntry::DelegateEntry() {
+}
+
+CmaMessageFilterProxy::DelegateEntry::~DelegateEntry() {
+}
+
+CmaMessageFilterProxy* CmaMessageFilterProxy::filter_ = NULL;
+
+// static
+CmaMessageFilterProxy* CmaMessageFilterProxy::Get() {
+ return filter_;
+}
+
+CmaMessageFilterProxy::CmaMessageFilterProxy(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
+ : sender_(NULL),
+ io_message_loop_(io_message_loop) {
+ DCHECK(!filter_);
+ filter_ = this;
+}
+
+int CmaMessageFilterProxy::CreateChannel() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ DelegateEntry* entry = new DelegateEntry();
+ int id = delegates_.Add(entry);
+ return id;
+}
+
+void CmaMessageFilterProxy::DestroyChannel(int id) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ delegates_.Remove(id);
+ delete entry;
+}
+
+bool CmaMessageFilterProxy::SetMediaDelegate(
+ int id, const MediaDelegate& media_delegate) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return false;
+ entry->media_delegate = media_delegate;
+ return true;
+}
+
+bool CmaMessageFilterProxy::SetAudioDelegate(
+ int id, const AudioDelegate& audio_delegate) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return false;
+ entry->audio_delegate = audio_delegate;
+ return true;
+}
+
+bool CmaMessageFilterProxy::SetVideoDelegate(
+ int id, const VideoDelegate& video_delegate) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return false;
+ entry->video_delegate = video_delegate;
+ return true;
+}
+
+bool CmaMessageFilterProxy::Send(scoped_ptr<IPC::Message> message) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ if (!sender_)
+ return false;
+ bool status = sender_->Send(message.release());
+ return status;
+}
+
+bool CmaMessageFilterProxy::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(CmaMessageFilterProxy, message)
+ IPC_MESSAGE_HANDLER(CmaMsg_AvPipeCreated, OnAvPipeCreated)
+ IPC_MESSAGE_HANDLER(CmaMsg_NotifyPipeRead, OnPipeRead)
+ IPC_MESSAGE_HANDLER(CmaMsg_MediaStateChanged, OnMediaStateChanged)
+ IPC_MESSAGE_HANDLER(CmaMsg_TrackStateChanged, OnTrackStateChanged)
+ IPC_MESSAGE_HANDLER(CmaMsg_Eos, OnEos)
+ IPC_MESSAGE_HANDLER(CmaMsg_TimeUpdate, OnTimeUpdate)
+ IPC_MESSAGE_HANDLER(CmaMsg_BufferingNotification, OnBufferingNotification)
+ IPC_MESSAGE_HANDLER(CmaMsg_PlaybackError, OnPlaybackError)
+ IPC_MESSAGE_HANDLER(CmaMsg_PlaybackStatistics, OnStatisticsUpdated)
+ IPC_MESSAGE_HANDLER(CmaMsg_NaturalSizeChanged, OnNaturalSizeChanged)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void CmaMessageFilterProxy::OnFilterAdded(IPC::Sender* sender) {
+ sender_ = sender;
+}
+
+void CmaMessageFilterProxy::OnFilterRemoved() {
+ sender_ = NULL;
+}
+
+void CmaMessageFilterProxy::OnChannelClosing() {
+ sender_ = NULL;
+}
+
+CmaMessageFilterProxy::~CmaMessageFilterProxy() {
+ DCHECK(filter_);
+ filter_ = NULL;
+}
+
+void CmaMessageFilterProxy::OnAvPipeCreated(
+ int id,
+ TrackId track_id,
+ bool status,
+ base::SharedMemoryHandle shared_memory_handle,
+ base::FileDescriptor socket_handle) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const AvPipeCB& cb = (track_id == kAudioTrackId) ?
+ entry->audio_delegate.av_pipe_cb :
+ entry->video_delegate.av_pipe_cb;
+ if (!cb.is_null())
+ cb.Run(status, shared_memory_handle, socket_handle);
+}
+
+void CmaMessageFilterProxy::OnPipeRead(
+ int id, TrackId track_id) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const base::Closure& cb = (track_id == kAudioTrackId) ?
+ entry->audio_delegate.pipe_read_cb :
+ entry->video_delegate.pipe_read_cb;
+ if (!cb.is_null())
+ cb.Run();
+}
+
+void CmaMessageFilterProxy::OnMediaStateChanged(
+ int id, ::media::PipelineStatus status) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const ::media::PipelineStatusCB& cb =
+ entry->media_delegate.state_changed_cb;
+ if (!cb.is_null())
+ cb.Run(status);
+}
+
+void CmaMessageFilterProxy::OnTrackStateChanged(
+ int id, TrackId track_id, ::media::PipelineStatus status) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const ::media::PipelineStatusCB& cb = (track_id == kAudioTrackId) ?
+ entry->audio_delegate.state_changed_cb :
+ entry->video_delegate.state_changed_cb;
+ if (!cb.is_null())
+ cb.Run(status);
+}
+
+void CmaMessageFilterProxy::OnEos(int id, TrackId track_id) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const base::Closure& cb = (track_id == kAudioTrackId) ?
+ entry->audio_delegate.client.eos_cb :
+ entry->video_delegate.client.av_pipeline_client.eos_cb;
+ if (!cb.is_null())
+ cb.Run();
+}
+
+void CmaMessageFilterProxy::OnTimeUpdate(
+ int id,
+ base::TimeDelta time,
+ base::TimeDelta max_time,
+ base::TimeTicks stc) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const MediaPipelineClient::TimeUpdateCB& cb =
+ entry->media_delegate.client.time_update_cb;
+ if (!cb.is_null())
+ cb.Run(time, max_time, stc);
+}
+
+void CmaMessageFilterProxy::OnBufferingNotification(
+ int id, ::media::BufferingState buffering_state) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const ::media::BufferingStateCB& cb =
+ entry->media_delegate.client.buffering_state_cb;
+ if (!cb.is_null())
+ cb.Run(buffering_state);
+}
+
+void CmaMessageFilterProxy::OnPlaybackError(
+ int id, TrackId track_id, ::media::PipelineStatus status) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const ::media::PipelineStatusCB& cb =
+ (track_id == kNoTrackId) ? entry->media_delegate.client.error_cb :
+ (track_id == kAudioTrackId) ?
+ entry->audio_delegate.client.playback_error_cb :
+ entry->video_delegate.client.av_pipeline_client.playback_error_cb;
+ if (!cb.is_null())
+ cb.Run(status);
+}
+
+void CmaMessageFilterProxy::OnStatisticsUpdated(
+ int id, TrackId track_id, const ::media::PipelineStatistics& stats) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ const ::media::StatisticsCB& cb = (track_id == kAudioTrackId) ?
+ entry->audio_delegate.client.statistics_cb :
+ entry->video_delegate.client.av_pipeline_client.statistics_cb;
+ if (!cb.is_null())
+ cb.Run(stats);
+}
+
+void CmaMessageFilterProxy::OnNaturalSizeChanged(
+ int id, TrackId track_id, const gfx::Size& size) {
+ DelegateEntry* entry = delegates_.Lookup(id);
+ if (!entry)
+ return;
+ if (track_id == kAudioTrackId)
+ return;
+ const VideoPipelineClient::NaturalSizeChangedCB& cb =
+ entry->video_delegate.client.natural_size_changed_cb;
+ if (!cb.is_null())
+ cb.Run(size);
+}
+
+} // namespace media
+} // namespace chromecast \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/cma_message_filter_proxy.h b/chromium/chromecast/renderer/media/cma_message_filter_proxy.h
new file mode 100644
index 00000000000..0930f19938e
--- /dev/null
+++ b/chromium/chromecast/renderer/media/cma_message_filter_proxy.h
@@ -0,0 +1,135 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_CMA_MESSAGE_FILTER_PROXY_H_
+#define CHROMECAST_RENDERER_MEDIA_CMA_MESSAGE_FILTER_PROXY_H_
+
+#include "base/id_map.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/media/cma/pipeline/av_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_client.h"
+#include "chromecast/media/cma/pipeline/video_pipeline_client.h"
+#include "ipc/message_filter.h"
+#include "media/base/buffering_state.h"
+#include "media/base/pipeline_status.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace chromecast {
+namespace media {
+
+typedef base::Callback<void(
+ bool, base::SharedMemoryHandle, base::FileDescriptor)> AvPipeCB;
+
+class CmaMessageFilterProxy : public IPC::MessageFilter {
+ public:
+ struct MediaDelegate {
+ MediaDelegate();
+ ~MediaDelegate();
+
+ ::media::PipelineStatusCB state_changed_cb;
+ MediaPipelineClient client;
+ };
+
+ struct AudioDelegate {
+ AudioDelegate();
+ ~AudioDelegate();
+
+ AvPipeCB av_pipe_cb;
+ base::Closure pipe_read_cb;
+ ::media::PipelineStatusCB state_changed_cb;
+ AvPipelineClient client;
+ };
+
+ struct VideoDelegate {
+ VideoDelegate();
+ ~VideoDelegate();
+
+ AvPipeCB av_pipe_cb;
+ base::Closure pipe_read_cb;
+ ::media::PipelineStatusCB state_changed_cb;
+ VideoPipelineClient client;
+ };
+
+ explicit CmaMessageFilterProxy(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
+
+ // Getter for the one CmaMessageFilterHost object.
+ static CmaMessageFilterProxy* Get();
+
+ int CreateChannel();
+ void DestroyChannel(int id);
+
+ // For adding/removing delegates.
+ bool SetMediaDelegate(int id, const MediaDelegate& media_delegate);
+ bool SetAudioDelegate(int id, const AudioDelegate& audio_delegate);
+ bool SetVideoDelegate(int id, const VideoDelegate& video_delegate);
+
+ // Sends an IPC message using |channel_|.
+ bool Send(scoped_ptr<IPC::Message> message);
+
+ // IPC::ChannelProxy::MessageFilter implementation. Called on IO thread.
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
+
+ protected:
+ ~CmaMessageFilterProxy() override;
+
+ private:
+ struct DelegateEntry {
+ DelegateEntry();
+ ~DelegateEntry();
+
+ MediaDelegate media_delegate;
+ AudioDelegate audio_delegate;
+ VideoDelegate video_delegate;
+ };
+
+ void OnAvPipeCreated(int id,
+ TrackId track_id,
+ bool status,
+ base::SharedMemoryHandle shared_memory_handle,
+ base::FileDescriptor socket_handle);
+ void OnPipeRead(int id, TrackId track_id);
+ void OnMediaStateChanged(int id, ::media::PipelineStatus status);
+ void OnTrackStateChanged(int id, TrackId track_id,
+ ::media::PipelineStatus status);
+ void OnEos(int id, TrackId track_id);
+ void OnTimeUpdate(int id,
+ base::TimeDelta time,
+ base::TimeDelta max_time,
+ base::TimeTicks stc);
+ void OnBufferingNotification(int id, ::media::BufferingState state);
+ void OnPlaybackError(int id, TrackId track_id,
+ ::media::PipelineStatus status);
+ void OnStatisticsUpdated(int id, TrackId track_id,
+ const ::media::PipelineStatistics& stats);
+ void OnNaturalSizeChanged(int id, TrackId track_id,
+ const gfx::Size& natural_size);
+
+ // The singleton instance for this filter.
+ static CmaMessageFilterProxy* filter_;
+
+ // A map of media ids to delegates.
+ IDMap<DelegateEntry> delegates_;
+
+ IPC::Sender* sender_;
+
+ scoped_refptr<base::MessageLoopProxy> const io_message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(CmaMessageFilterProxy);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_CMA_MESSAGE_FILTER_PROXY_H_
diff --git a/chromium/chromecast/renderer/media/cma_renderer_unittest.cc b/chromium/chromecast/renderer/media/cma_renderer_unittest.cc
new file mode 100644
index 00000000000..19ff6ecec62
--- /dev/null
+++ b/chromium/chromecast/renderer/media/cma_renderer_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "chromecast/common/media/shared_memory_chunk.h"
+#include "chromecast/media/cma/base/buffering_defs.h"
+#include "chromecast/media/cma/filters/cma_renderer.h"
+#include "chromecast/media/cma/ipc/media_memory_chunk.h"
+#include "chromecast/media/cma/ipc/media_message_fifo.h"
+#include "chromecast/media/cma/pipeline/media_pipeline.h"
+#include "chromecast/renderer/media/cma_message_filter_proxy.h"
+#include "chromecast/renderer/media/media_pipeline_proxy.h"
+#include "ipc/ipc_test_sink.h"
+#include "media/base/demuxer_stream_provider.h"
+#include "media/base/fake_demuxer_stream.h"
+#include "media/base/null_video_sink.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+class CmaRendererTest : public testing::Test {
+ public:
+ CmaRendererTest() {
+ demuxer_stream_provider_.reset(
+ new ::media::FakeDemuxerStreamProvider(1, 1, false));
+ null_sink_.reset(new ::media::NullVideoSink(
+ false,
+ base::TimeDelta::FromSecondsD(1.0 / 60),
+ base::Bind(&MockCB::OnFrameReceived, base::Unretained(&mock_)),
+ message_loop_.task_runner()));
+
+ cma_proxy_ = new CmaMessageFilterProxy(message_loop_.message_loop_proxy());
+ cma_proxy_->OnFilterAdded(&ipc_sink_);
+
+ renderer_.reset(new CmaRenderer(
+ scoped_ptr<MediaPipelineProxy>(
+ new MediaPipelineProxy(0, message_loop_.message_loop_proxy(),
+ LoadType::kLoadTypeMediaSource)),
+ null_sink_.get()));
+ }
+
+ ~CmaRendererTest() override {
+ cma_proxy_->OnFilterRemoved();
+ }
+
+ protected:
+ base::MessageLoop message_loop_;
+ scoped_ptr<::media::FakeDemuxerStreamProvider> demuxer_stream_provider_;
+ IPC::TestSink ipc_sink_;
+ scoped_refptr<CmaMessageFilterProxy> cma_proxy_;
+ scoped_ptr<CmaRenderer> renderer_;
+
+ class MockCB {
+ public:
+ MOCK_METHOD1(OnInitialized, void(::media::PipelineStatus));
+ MOCK_METHOD1(OnFrameReceived,
+ void(const scoped_refptr<::media::VideoFrame>&));
+ MOCK_METHOD1(OnStatistics, void(const ::media::PipelineStatistics&));
+ MOCK_METHOD1(OnBufferingState, void(::media::BufferingState));
+ MOCK_METHOD0(OnEnded, void());
+ MOCK_METHOD1(OnError, void(::media::PipelineStatus));
+ MOCK_METHOD0(OnWaitingForDecryptionKey, void());
+ };
+ MockCB mock_;
+
+ private:
+ scoped_ptr<::media::NullVideoSink> null_sink_;
+
+ DISALLOW_COPY_AND_ASSIGN(CmaRendererTest);
+};
+
+} // namespace
+
+TEST_F(CmaRendererTest, TestInitialization) {
+ renderer_->Initialize(
+ demuxer_stream_provider_.get(),
+ base::Bind(&MockCB::OnInitialized, base::Unretained(&mock_)),
+ base::Bind(&MockCB::OnStatistics, base::Unretained(&mock_)),
+ base::Bind(&MockCB::OnBufferingState, base::Unretained(&mock_)),
+ base::Bind(&MockCB::OnEnded, base::Unretained(&mock_)),
+ base::Bind(&MockCB::OnError, base::Unretained(&mock_)),
+ base::Bind(&MockCB::OnWaitingForDecryptionKey, base::Unretained(&mock_)));
+ message_loop_.RunUntilIdle();
+
+ EXPECT_TRUE(ipc_sink_.GetUniqueMessageMatching(CmaHostMsg_CreateAvPipe::ID));
+ base::SharedMemory* shared_memory = new base::SharedMemory();
+ EXPECT_TRUE(shared_memory->CreateAndMapAnonymous(kAppVideoBufferSize));
+
+ // Renderer MediaMessageFifo instance expects the first bytes of the shared
+ // memory blob to describe how much space is available for writing.
+ *(static_cast<size_t*>(shared_memory->memory())) =
+ shared_memory->requested_size() - MediaMessageFifo::kDescriptorSize;
+
+ base::FileDescriptor foreign_socket_handle;
+ cma_proxy_->OnMessageReceived(CmaMsg_AvPipeCreated(
+ 1, kVideoTrackId, true,
+ shared_memory->handle(), foreign_socket_handle));
+ message_loop_.RunUntilIdle();
+
+ EXPECT_FALSE(
+ ipc_sink_.GetUniqueMessageMatching(CmaHostMsg_AudioInitialize::ID));
+ EXPECT_TRUE(
+ ipc_sink_.GetUniqueMessageMatching(CmaHostMsg_VideoInitialize::ID));
+
+ EXPECT_CALL(mock_, OnInitialized(::media::PIPELINE_OK));
+ cma_proxy_->OnMessageReceived(
+ CmaMsg_TrackStateChanged(1, kVideoTrackId, ::media::PIPELINE_OK));
+ message_loop_.RunUntilIdle();
+}
+
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromium/chromecast/renderer/media/media_channel_proxy.cc b/chromium/chromecast/renderer/media/media_channel_proxy.cc
new file mode 100644
index 00000000000..2ef1d251d92
--- /dev/null
+++ b/chromium/chromecast/renderer/media/media_channel_proxy.cc
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/media_channel_proxy.h"
+
+#include "base/logging.h"
+#include "chromecast/common/media/cma_messages.h"
+
+namespace chromecast {
+namespace media {
+
+MediaChannelProxy::MediaChannelProxy()
+ : is_open_(false),
+ id_(0) {
+ filter_ = CmaMessageFilterProxy::Get();
+ DCHECK(filter_.get());
+}
+
+MediaChannelProxy::~MediaChannelProxy() {
+}
+
+void MediaChannelProxy::Open(LoadType load_type) {
+ CHECK(!is_open_);
+ // Renderer side.
+ id_ = filter_->CreateChannel();
+ is_open_ = true;
+
+ // Browser side.
+ bool success = Send(
+ scoped_ptr<IPC::Message>(new CmaHostMsg_CreateMedia(id_, load_type)));
+ if (!success) {
+ is_open_ = false;
+ id_ = 0;
+ }
+}
+
+void MediaChannelProxy::Close() {
+ if (!is_open_)
+ return;
+
+ // Browser side.
+ Send(scoped_ptr<IPC::Message>(new CmaHostMsg_DestroyMedia(id_)));
+
+ // Renderer side.
+ is_open_ = false;
+ filter_->DestroyChannel(id_);
+ id_ = 0;
+}
+
+bool MediaChannelProxy::SetMediaDelegate(
+ const CmaMessageFilterProxy::MediaDelegate& media_delegate) {
+ if (!is_open_)
+ return false;
+ return filter_->SetMediaDelegate(id_, media_delegate);
+}
+
+bool MediaChannelProxy::SetAudioDelegate(
+ const CmaMessageFilterProxy::AudioDelegate& audio_delegate) {
+ if (!is_open_)
+ return false;
+ return filter_->SetAudioDelegate(id_, audio_delegate);
+}
+
+bool MediaChannelProxy::SetVideoDelegate(
+ const CmaMessageFilterProxy::VideoDelegate& video_delegate) {
+ if (!is_open_)
+ return false;
+ return filter_->SetVideoDelegate(id_, video_delegate);
+}
+
+bool MediaChannelProxy::Send(scoped_ptr<IPC::Message> message) {
+ if (!is_open_)
+ return false;
+ return filter_->Send(message.Pass());
+}
+
+} // namespace media
+} // namespace chromecast \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/media_channel_proxy.h b/chromium/chromecast/renderer/media/media_channel_proxy.h
new file mode 100644
index 00000000000..c7c46965bf6
--- /dev/null
+++ b/chromium/chromecast/renderer/media/media_channel_proxy.h
@@ -0,0 +1,68 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_MEDIA_CHANNEL_PROXY_H_
+#define CHROMECAST_RENDERER_MEDIA_MEDIA_CHANNEL_PROXY_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "chromecast/renderer/media/cma_message_filter_proxy.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace chromecast {
+namespace media {
+
+// MediaChannelProxy - Manage the lifetime of a CMA ipc channel.
+// Must be invoked from the IO thread of the renderer process.
+class MediaChannelProxy
+ : public base::RefCountedThreadSafe<MediaChannelProxy> {
+ public:
+ MediaChannelProxy();
+
+ // Opens a CMA ipc channel.
+ void Open(LoadType load_type);
+
+ // Closes the ipc channel.
+ void Close();
+
+ // Returns the ID of the CMA ipc channel.
+ // Returns 0 or negative ID if no channel has been opened.
+ int GetId() { return id_; }
+
+ // Manages delegates.
+ bool SetMediaDelegate(
+ const CmaMessageFilterProxy::MediaDelegate& media_delegate);
+ bool SetAudioDelegate(
+ const CmaMessageFilterProxy::AudioDelegate& audio_delegate);
+ bool SetVideoDelegate(
+ const CmaMessageFilterProxy::VideoDelegate& video_delegate);
+
+ // Sends an IPC message over this CMA ipc channel.
+ bool Send(scoped_ptr<IPC::Message> message);
+
+ private:
+ friend class base::RefCountedThreadSafe<MediaChannelProxy>;
+ virtual ~MediaChannelProxy();
+
+ // Message filter running on the renderer side.
+ scoped_refptr<CmaMessageFilterProxy> filter_;
+
+ // Indicates whether the CMA channel is open.
+ bool is_open_;
+
+ // Unique identifier per media pipeline.
+ int id_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaChannelProxy);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_MEDIA_CHANNEL_PROXY_H_ \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/media_pipeline_proxy.cc b/chromium/chromecast/renderer/media/media_pipeline_proxy.cc
new file mode 100644
index 00000000000..830ac0fe134
--- /dev/null
+++ b/chromium/chromecast/renderer/media/media_pipeline_proxy.cc
@@ -0,0 +1,283 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/media_pipeline_proxy.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/renderer/media/audio_pipeline_proxy.h"
+#include "chromecast/renderer/media/media_channel_proxy.h"
+#include "chromecast/renderer/media/video_pipeline_proxy.h"
+
+namespace chromecast {
+namespace media {
+
+// MediaPipelineProxyInternal -
+// This class is not thread safe and should run on the same thread
+// as the media channel proxy.
+class MediaPipelineProxyInternal {
+ public:
+ static void Release(scoped_ptr<MediaPipelineProxyInternal> proxy);
+
+ explicit MediaPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy);
+ virtual ~MediaPipelineProxyInternal();
+
+ void SetClient(const MediaPipelineClient& client);
+ void SetCdm(int render_frame_id, int cdm_id);
+ void StartPlayingFrom(const base::TimeDelta& time);
+ void Flush(const ::media::PipelineStatusCB& status_cb);
+ void Stop();
+ void SetPlaybackRate(double playback_rate);
+
+ private:
+ void Shutdown();
+
+ // Callbacks for CmaMessageFilterHost::MediaDelegate.
+ void OnStateChanged(::media::PipelineStatus status);
+
+ base::ThreadChecker thread_checker_;
+
+ scoped_refptr<MediaChannelProxy> media_channel_proxy_;
+
+ MediaPipelineClient client_;
+
+ // Store the callback for a pending state transition.
+ ::media::PipelineStatusCB status_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaPipelineProxyInternal);
+};
+
+// static
+void MediaPipelineProxyInternal::Release(
+ scoped_ptr<MediaPipelineProxyInternal> proxy) {
+ proxy->Shutdown();
+}
+
+MediaPipelineProxyInternal::MediaPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy)
+ : media_channel_proxy_(media_channel_proxy) {
+ DCHECK(media_channel_proxy.get());
+
+ // Creation can be done on a different thread.
+ thread_checker_.DetachFromThread();
+}
+
+MediaPipelineProxyInternal::~MediaPipelineProxyInternal() {
+}
+
+void MediaPipelineProxyInternal::Shutdown() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Remove any callback on VideoPipelineProxyInternal.
+ media_channel_proxy_->SetMediaDelegate(
+ CmaMessageFilterProxy::MediaDelegate());
+}
+
+void MediaPipelineProxyInternal::SetClient(
+ const MediaPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!client.error_cb.is_null());
+ DCHECK(!client.buffering_state_cb.is_null());
+ client_ = client;
+
+ CmaMessageFilterProxy::MediaDelegate delegate;
+ delegate.state_changed_cb =
+ base::Bind(&MediaPipelineProxyInternal::OnStateChanged,
+ base::Unretained(this));
+ delegate.client = client;
+ bool success = media_channel_proxy_->SetMediaDelegate(delegate);
+ CHECK(success);
+}
+
+void MediaPipelineProxyInternal::SetCdm(int render_frame_id, int cdm_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_SetCdm(media_channel_proxy_->GetId(),
+ render_frame_id,
+ cdm_id)));
+ LOG_IF(ERROR, !success) << "Failed to send SetCdm=" << cdm_id;
+}
+
+void MediaPipelineProxyInternal::Flush(
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_Flush(media_channel_proxy_->GetId())));
+ if (!success) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ DCHECK(status_cb_.is_null());
+ status_cb_ = status_cb;
+}
+
+void MediaPipelineProxyInternal::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_Stop(media_channel_proxy_->GetId())));
+ if (!success)
+ client_.error_cb.Run(::media::PIPELINE_ERROR_ABORT);
+}
+
+void MediaPipelineProxyInternal::StartPlayingFrom(const base::TimeDelta& time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_StartPlayingFrom(
+ media_channel_proxy_->GetId(), time)));
+ if (!success)
+ client_.error_cb.Run(::media::PIPELINE_ERROR_ABORT);
+}
+
+void MediaPipelineProxyInternal::SetPlaybackRate(double playback_rate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_SetPlaybackRate(
+ media_channel_proxy_->GetId(), playback_rate)));
+}
+
+void MediaPipelineProxyInternal::OnStateChanged(
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!status_cb_.is_null());
+ base::ResetAndReturn(&status_cb_).Run(status);
+}
+
+
+// A macro runs current member function on |io_message_loop_proxy_| thread.
+#define FORWARD_ON_IO_THREAD(param_fn, ...) \
+ io_message_loop_proxy_->PostTask( \
+ FROM_HERE, \
+ base::Bind(&MediaPipelineProxyInternal::param_fn, \
+ base::Unretained(proxy_.get()), ##__VA_ARGS__))
+
+MediaPipelineProxy::MediaPipelineProxy(
+ int render_frame_id,
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
+ LoadType load_type)
+ : io_message_loop_proxy_(io_message_loop_proxy),
+ render_frame_id_(render_frame_id),
+ media_channel_proxy_(new MediaChannelProxy),
+ proxy_(new MediaPipelineProxyInternal(media_channel_proxy_)),
+ has_audio_(false),
+ has_video_(false),
+ audio_pipeline_(new AudioPipelineProxy(
+ io_message_loop_proxy, media_channel_proxy_)),
+ video_pipeline_(new VideoPipelineProxy(
+ io_message_loop_proxy, media_channel_proxy_)),
+ weak_factory_(this) {
+ weak_this_ = weak_factory_.GetWeakPtr();
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaChannelProxy::Open, media_channel_proxy_,
+ load_type));
+ thread_checker_.DetachFromThread();
+}
+
+MediaPipelineProxy::~MediaPipelineProxy() {
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineProxyInternal::Release, base::Passed(&proxy_)));
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaChannelProxy::Close, media_channel_proxy_));
+}
+
+void MediaPipelineProxy::SetClient(
+ const MediaPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetClient, client);
+}
+
+void MediaPipelineProxy::SetCdm(int cdm_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetCdm, render_frame_id_, cdm_id);
+}
+
+AudioPipeline* MediaPipelineProxy::GetAudioPipeline() const {
+ return audio_pipeline_.get();
+}
+
+VideoPipeline* MediaPipelineProxy::GetVideoPipeline() const {
+ return video_pipeline_.get();
+}
+
+void MediaPipelineProxy::InitializeAudio(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ has_audio_ = true;
+ audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
+}
+
+void MediaPipelineProxy::InitializeVideo(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ has_video_ = true;
+ video_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
+}
+
+void MediaPipelineProxy::StartPlayingFrom(base::TimeDelta time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (has_audio_)
+ audio_pipeline_->StartFeeding();
+ if (has_video_)
+ video_pipeline_->StartFeeding();
+ FORWARD_ON_IO_THREAD(StartPlayingFrom, time);
+}
+
+void MediaPipelineProxy::Flush(const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+
+ ::media::SerialRunner::Queue bound_fns;
+ if (has_audio_) {
+ bound_fns.Push(base::Bind(&AudioPipelineProxy::Flush,
+ base::Unretained(audio_pipeline_.get())));
+ }
+ if (has_video_) {
+ bound_fns.Push(base::Bind(&VideoPipelineProxy::Flush,
+ base::Unretained(video_pipeline_.get())));
+ }
+ ::media::PipelineStatusCB cb =
+ base::Bind(&MediaPipelineProxy::OnProxyFlushDone, weak_this_, status_cb);
+ pending_callbacks_ = ::media::SerialRunner::Run(bound_fns, cb);
+}
+
+void MediaPipelineProxy::OnProxyFlushDone(
+ const ::media::PipelineStatusCB& status_cb,
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(status, ::media::PIPELINE_OK);
+ pending_callbacks_.reset();
+ FORWARD_ON_IO_THREAD(Flush, status_cb);
+}
+
+void MediaPipelineProxy::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+
+ if (has_audio_)
+ audio_pipeline_->Stop();
+ if (has_video_)
+ video_pipeline_->Stop();
+
+ FORWARD_ON_IO_THREAD(Stop);
+}
+
+void MediaPipelineProxy::SetPlaybackRate(double playback_rate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetPlaybackRate, playback_rate);
+}
+
+} // namespace cma
+} // namespace chromecast \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/media_pipeline_proxy.h b/chromium/chromecast/renderer/media/media_pipeline_proxy.h
new file mode 100644
index 00000000000..decec653b86
--- /dev/null
+++ b/chromium/chromecast/renderer/media/media_pipeline_proxy.h
@@ -0,0 +1,85 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_MEDIA_PIPELINE_PROXY_H_
+#define CHROMECAST_RENDERER_MEDIA_MEDIA_PIPELINE_PROXY_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/media/cma/pipeline/load_type.h"
+#include "chromecast/media/cma/pipeline/media_pipeline.h"
+#include "chromecast/media/cma/pipeline/media_pipeline_client.h"
+#include "media/base/serial_runner.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace chromecast {
+namespace media {
+class AudioPipelineProxy;
+class MediaChannelProxy;
+class MediaPipelineProxyInternal;
+class VideoPipelineProxy;
+
+class MediaPipelineProxy : public MediaPipeline {
+ public:
+ MediaPipelineProxy(
+ int render_frame_id,
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
+ LoadType load_type);
+ ~MediaPipelineProxy() override;
+
+ // MediaPipeline implementation.
+ void SetClient(const MediaPipelineClient& client) override;
+ void SetCdm(int cdm_id) override;
+ AudioPipeline* GetAudioPipeline() const override;
+ VideoPipeline* GetVideoPipeline() const override;
+ void InitializeAudio(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) override;
+ void InitializeVideo(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) override;
+ void StartPlayingFrom(base::TimeDelta time) override;
+ void Flush(const ::media::PipelineStatusCB& status_cb) override;
+ void Stop() override;
+ void SetPlaybackRate(double playback_rate) override;
+
+ private:
+ void OnProxyFlushDone(const ::media::PipelineStatusCB& status_cb,
+ ::media::PipelineStatus status);
+
+ base::ThreadChecker thread_checker_;
+
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+
+ const int render_frame_id_;
+
+ // CMA channel to convey IPC messages.
+ scoped_refptr<MediaChannelProxy> const media_channel_proxy_;
+
+ scoped_ptr<MediaPipelineProxyInternal> proxy_;
+
+ bool has_audio_;
+ bool has_video_;
+ scoped_ptr<AudioPipelineProxy> audio_pipeline_;
+ scoped_ptr<VideoPipelineProxy> video_pipeline_;
+ scoped_ptr< ::media::SerialRunner> pending_callbacks_;
+
+ base::WeakPtr<MediaPipelineProxy> weak_this_;
+ base::WeakPtrFactory<MediaPipelineProxy> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaPipelineProxy);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_MEDIA_PIPELINE_PROXY_H_ \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/video_pipeline_proxy.cc b/chromium/chromecast/renderer/media/video_pipeline_proxy.cc
new file mode 100644
index 00000000000..6c924cd4e2e
--- /dev/null
+++ b/chromium/chromecast/renderer/media/video_pipeline_proxy.cc
@@ -0,0 +1,299 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/renderer/media/video_pipeline_proxy.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "chromecast/common/media/shared_memory_chunk.h"
+#include "chromecast/media/cma/base/buffering_defs.h"
+#include "chromecast/media/cma/base/cma_logging.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/media/cma/ipc/media_message_fifo.h"
+#include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h"
+#include "chromecast/renderer/media/cma_message_filter_proxy.h"
+#include "chromecast/renderer/media/media_channel_proxy.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/pipeline_status.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+void IgnoreResult() {
+}
+
+} // namespace
+
+// VideoPipelineProxyInternal -
+// This class is not thread safe and should run on the same thread
+// as the media channel proxy.
+class VideoPipelineProxyInternal {
+ public:
+ typedef base::Callback<void(scoped_ptr<base::SharedMemory>)> SharedMemCB;
+
+ static void Release(scoped_ptr<VideoPipelineProxyInternal> proxy);
+
+ explicit VideoPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy);
+ virtual ~VideoPipelineProxyInternal();
+
+ // Notify the other side (browser process) of some activity on the video pipe.
+ // TODO(erickung): either send an IPC message or write a byte on the
+ // SyncSocket.
+ void NotifyPipeWrite();
+
+ // These functions are almost a one to one correspondence with VideoPipeline
+ // but this is an internal class and there is no reason to derive from
+ // VideoPipeline.
+ void SetClient(const base::Closure& pipe_read_cb,
+ const VideoPipelineClient& client);
+ void CreateAvPipe(const SharedMemCB& shared_mem_cb);
+ void Initialize(const ::media::VideoDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb);
+
+ private:
+ void Shutdown();
+
+ // Callbacks for CmaMessageFilterHost::VideoDelegate.
+ void OnAvPipeCreated(bool status,
+ base::SharedMemoryHandle shared_mem_handle,
+ base::FileDescriptor socket);
+ void OnStateChanged(::media::PipelineStatus status);
+
+ base::ThreadChecker thread_checker_;
+
+ scoped_refptr<MediaChannelProxy> media_channel_proxy_;
+
+ // Store the callback for a pending state transition.
+ ::media::PipelineStatusCB status_cb_;
+
+ SharedMemCB shared_mem_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoPipelineProxyInternal);
+};
+
+// static
+void VideoPipelineProxyInternal::Release(
+ scoped_ptr<VideoPipelineProxyInternal> proxy) {
+ proxy->Shutdown();
+}
+
+VideoPipelineProxyInternal::VideoPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy)
+ : media_channel_proxy_(media_channel_proxy) {
+ DCHECK(media_channel_proxy.get());
+
+ // Creation can be done on a different thread.
+ thread_checker_.DetachFromThread();
+}
+
+VideoPipelineProxyInternal::~VideoPipelineProxyInternal() {
+}
+
+void VideoPipelineProxyInternal::Shutdown() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Remove any callback on VideoPipelineProxyInternal.
+ media_channel_proxy_->SetVideoDelegate(
+ CmaMessageFilterProxy::VideoDelegate());
+}
+
+void VideoPipelineProxyInternal::NotifyPipeWrite() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // TODO(damienv): An alternative way would be to use a dedicated socket for
+ // this event.
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_NotifyPipeWrite(media_channel_proxy_->GetId(),
+ kVideoTrackId)));
+ VLOG_IF(4, !success) << "Sending msg failed";
+}
+
+void VideoPipelineProxyInternal::SetClient(
+ const base::Closure& pipe_read_cb,
+ const VideoPipelineClient& video_client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ CmaMessageFilterProxy::VideoDelegate delegate;
+ delegate.av_pipe_cb =
+ base::Bind(&VideoPipelineProxyInternal::OnAvPipeCreated,
+ base::Unretained(this));
+ delegate.state_changed_cb =
+ base::Bind(&VideoPipelineProxyInternal::OnStateChanged,
+ base::Unretained(this));
+ delegate.pipe_read_cb = pipe_read_cb;
+ delegate.client = video_client;
+ bool success = media_channel_proxy_->SetVideoDelegate(delegate);
+ CHECK(success);
+}
+
+void VideoPipelineProxyInternal::CreateAvPipe(
+ const SharedMemCB& shared_mem_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(shared_mem_cb_.is_null());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_CreateAvPipe(
+ media_channel_proxy_->GetId(), kVideoTrackId, kAppVideoBufferSize)));
+ if (!success) {
+ shared_mem_cb.Run(scoped_ptr<base::SharedMemory>());
+ return;
+ }
+ shared_mem_cb_ = shared_mem_cb;
+}
+
+void VideoPipelineProxyInternal::OnAvPipeCreated(
+ bool success,
+ base::SharedMemoryHandle shared_mem_handle,
+ base::FileDescriptor socket) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!shared_mem_cb_.is_null());
+ if (!success) {
+ shared_mem_cb_.Run(scoped_ptr<base::SharedMemory>());
+ return;
+ }
+
+ CHECK(base::SharedMemory::IsHandleValid(shared_mem_handle));
+ shared_mem_cb_.Run(scoped_ptr<base::SharedMemory>(
+ new base::SharedMemory(shared_mem_handle, false)));
+}
+
+void VideoPipelineProxyInternal::Initialize(
+ const ::media::VideoDecoderConfig& arg1,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_VideoInitialize(media_channel_proxy_->GetId(),
+ kVideoTrackId, arg1)));
+ if (!success) {
+ status_cb.Run( ::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ DCHECK(status_cb_.is_null());
+ status_cb_ = status_cb;
+}
+
+void VideoPipelineProxyInternal::OnStateChanged(
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!status_cb_.is_null());
+ base::ResetAndReturn(&status_cb_).Run(status);
+}
+
+
+// A macro runs current member function on |io_message_loop_proxy_| thread.
+#define FORWARD_ON_IO_THREAD(param_fn, ...) \
+ io_message_loop_proxy_->PostTask( \
+ FROM_HERE, \
+ base::Bind(&VideoPipelineProxyInternal::param_fn, \
+ base::Unretained(proxy_.get()), ##__VA_ARGS__))
+
+VideoPipelineProxy::VideoPipelineProxy(
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
+ scoped_refptr<MediaChannelProxy> media_channel_proxy)
+ : io_message_loop_proxy_(io_message_loop_proxy),
+ proxy_(new VideoPipelineProxyInternal(media_channel_proxy)),
+ video_streamer_(new AvStreamerProxy()),
+ weak_factory_(this) {
+ DCHECK(io_message_loop_proxy_.get());
+ weak_this_ = weak_factory_.GetWeakPtr();
+ thread_checker_.DetachFromThread();
+}
+
+VideoPipelineProxy::~VideoPipelineProxy() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Release the underlying object on the right thread.
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoPipelineProxyInternal::Release, base::Passed(&proxy_)));
+}
+
+void VideoPipelineProxy::SetClient(
+ const VideoPipelineClient& video_client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ base::Closure pipe_read_cb =
+ ::media::BindToCurrentLoop(
+ base::Bind(&VideoPipelineProxy::OnPipeRead, weak_this_));
+ FORWARD_ON_IO_THREAD(SetClient, pipe_read_cb, video_client);
+}
+
+void VideoPipelineProxy::Initialize(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ CMALOG(kLogControl) << "VideoPipelineProxy::Initialize";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ video_streamer_->SetCodedFrameProvider(frame_provider.Pass());
+
+ VideoPipelineProxyInternal::SharedMemCB shared_mem_cb =
+ ::media::BindToCurrentLoop(base::Bind(
+ &VideoPipelineProxy::OnAvPipeCreated, weak_this_,
+ config, status_cb));
+ FORWARD_ON_IO_THREAD(CreateAvPipe, shared_mem_cb);
+}
+
+void VideoPipelineProxy::OnAvPipeCreated(
+ const ::media::VideoDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb,
+ scoped_ptr<base::SharedMemory> shared_memory) {
+ CMALOG(kLogControl) << "VideoPipelineProxy::OnAvPipeCreated";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!shared_memory ||
+ !shared_memory->Map(kAppVideoBufferSize)) {
+ status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+ CHECK(shared_memory->memory());
+
+ scoped_ptr<MediaMemoryChunk> shared_memory_chunk(
+ new SharedMemoryChunk(shared_memory.Pass(), kAppVideoBufferSize));
+ scoped_ptr<MediaMessageFifo> video_pipe(
+ new MediaMessageFifo(shared_memory_chunk.Pass(), false));
+ video_pipe->ObserveWriteActivity(
+ base::Bind(&VideoPipelineProxy::OnPipeWrite, weak_this_));
+
+ video_streamer_->SetMediaMessageFifo(video_pipe.Pass());
+
+ // Now proceed to the decoder/renderer initialization.
+ FORWARD_ON_IO_THREAD(Initialize, config, status_cb);
+}
+
+void VideoPipelineProxy::StartFeeding() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(video_streamer_);
+ video_streamer_->Start();
+}
+
+void VideoPipelineProxy::Flush(const base::Closure& done_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(video_streamer_);
+ video_streamer_->StopAndFlush(done_cb);
+}
+
+void VideoPipelineProxy::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!video_streamer_)
+ return;
+ video_streamer_->StopAndFlush(base::Bind(&IgnoreResult));
+}
+
+void VideoPipelineProxy::OnPipeWrite() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(NotifyPipeWrite);
+}
+
+void VideoPipelineProxy::OnPipeRead() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (video_streamer_)
+ video_streamer_->OnFifoReadEvent();
+}
+
+} // namespace media
+} // namespace chromecast \ No newline at end of file
diff --git a/chromium/chromecast/renderer/media/video_pipeline_proxy.h b/chromium/chromecast/renderer/media/video_pipeline_proxy.h
new file mode 100644
index 00000000000..88745525091
--- /dev/null
+++ b/chromium/chromecast/renderer/media/video_pipeline_proxy.h
@@ -0,0 +1,76 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_RENDERER_MEDIA_VIDEO_PIPELINE_PROXY_H_
+#define CHROMECAST_RENDERER_MEDIA_VIDEO_PIPELINE_PROXY_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/media/cma/pipeline/video_pipeline.h"
+#include "media/base/pipeline_status.h"
+
+namespace base {
+class MessageLoopProxy;
+class SharedMemory;
+}
+
+namespace media {
+class VideoDecoderConfig;
+}
+
+namespace chromecast {
+namespace media {
+struct AvPipelineClient;
+class AvStreamerProxy;
+class CodedFrameProvider;
+class VideoPipelineProxyInternal;
+class MediaChannelProxy;
+
+class VideoPipelineProxy : public VideoPipeline {
+ public:
+ VideoPipelineProxy(
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
+ scoped_refptr<MediaChannelProxy> media_channel_proxy);
+ ~VideoPipelineProxy() override;
+
+ void Initialize(const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb);
+ void StartFeeding();
+ void Flush(const base::Closure& done_cb);
+ void Stop();
+
+ // VideoPipeline implementation.
+ void SetClient(const VideoPipelineClient& video_client) override;
+
+ private:
+ base::ThreadChecker thread_checker_;
+
+ void OnAvPipeCreated(
+ const ::media::VideoDecoderConfig& config,
+ const ::media::PipelineStatusCB& status_cb,
+ scoped_ptr<base::SharedMemory> shared_memory);
+ void OnPipeWrite();
+ void OnPipeRead();
+
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
+
+ // |proxy_| main goal is to convert function calls to IPC messages.
+ scoped_ptr<VideoPipelineProxyInternal> proxy_;
+
+ scoped_ptr<AvStreamerProxy> video_streamer_;
+
+ base::WeakPtr<VideoPipelineProxy> weak_this_;
+ base::WeakPtrFactory<VideoPipelineProxy> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoPipelineProxy);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_RENDERER_MEDIA_VIDEO_PIPELINE_PROXY_H_ \ No newline at end of file
diff --git a/chromium/chromecast/tools/build/generate_test_lists.py b/chromium/chromecast/tools/build/generate_test_lists.py
new file mode 100755
index 00000000000..46e8b3d293d
--- /dev/null
+++ b/chromium/chromecast/tools/build/generate_test_lists.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Helper script to generate unit test lists for the Chromecast build scripts.
+"""
+
+import glob
+import optparse
+import sys
+
+
+def CombineList(test_files_dir, list_output_file, include_filters,
+ additional_runtime_options):
+ """Writes a unit test file in a format compatible for Chromecast scripts.
+
+ If include_filters is True, uses filters to create a test runner list
+ and also include additional options, if any.
+ Otherwise, creates a list only of the tests to build.
+
+ Args:
+ test_files_dir: Path to the intermediate directory containing tests/filters.
+ list_output_file: Path to write the unit test file out to.
+ include_filters: Whether or not to include the filters when generating
+ the test list.
+ """
+
+ # GYP targets may provide a numbered priority for the filename. Sort to
+ # use that priority.
+ test_files = sorted(glob.glob(test_files_dir + "/*.tests"))
+ filter_files = sorted(glob.glob(test_files_dir + "/*.filters"))
+
+ test_bin_set = set()
+ for test_filename in test_files:
+ with open(test_filename, "r") as test_file:
+ for test_file_line in test_file:
+ # Binary name may be a simple test target (cast_net_unittests) or be a
+ # qualified gyp path (../base.gyp:base_unittests).
+ test_binary_name = test_file_line.split(":")[-1].strip()
+ test_bin_set.add(test_binary_name)
+
+ test_filters = {}
+ if include_filters:
+ for filter_filename in filter_files:
+ with open(filter_filename, "r") as filter_file:
+ for filter_line in filter_file:
+ filter = filter_line.strip()
+ test_binary_name = filter.split(" ", 1)[0]
+
+ if test_binary_name not in test_bin_set:
+ raise Exception("Filter found for unknown target: " +
+ test_binary_name)
+
+ # Note: This may overwrite a previous rule. This is okay, since higher
+ # priority files are evaluated after lower priority files.
+ test_filters[test_binary_name] = filter
+
+ test_binaries = (
+ list(test_bin_set - set(test_filters.keys())) +
+ test_filters.values())
+
+ if additional_runtime_options:
+ lines = [
+ binary + " " + additional_runtime_options
+ for binary in test_binaries
+ ]
+ else:
+ lines = test_binaries
+ with open(list_output_file, "w") as f:
+ f.write("\n".join(sorted(lines)))
+
+
+def CreateList(inputs, list_output_file):
+ with open(list_output_file, "w") as f:
+ f.write("\n".join(inputs))
+
+
+def DoMain(argv):
+ """Main method. Runs helper commands for generating unit test lists."""
+ parser = optparse.OptionParser(
+ """usage: %prog [<options>] <command> [<test names>]
+
+ Valid commands:
+ create_list prints all given test names/args to a file, one line
+ per string
+ pack_build packs all test files from the given output directory
+ into a single test list file
+ pack_run packs all test and filter files from the given
+ output directory into a single test list file
+ """)
+ parser.add_option("-o", action="store", dest="list_output_file",
+ help="Output path in which to write the test list.")
+ parser.add_option("-t", action="store", dest="test_files_dir",
+ help="Intermediate test list directory.")
+ parser.add_option("-a", action="store", dest="additional_runtime_options",
+ help="Additional options applied to all tests.")
+ options, inputs = parser.parse_args(argv)
+
+ list_output_file = options.list_output_file
+ test_files_dir = options.test_files_dir
+ additional_runtime_options = options.additional_runtime_options
+
+ if len(inputs) < 1:
+ parser.error("No command given.\n")
+ command = inputs[0]
+ test_names = inputs[1:]
+
+ if not list_output_file:
+ parser.error("Output path (-o) is required.\n")
+
+ if command == "create_list":
+ return CreateList(test_names, list_output_file)
+
+ if command == "pack_build":
+ if not test_files_dir:
+ parser.error("pack_build require a test files directory (-t).\n")
+ return CombineList(test_files_dir, list_output_file, False, None)
+
+ if command == "pack_run":
+ if not test_files_dir:
+ parser.error("pack_run require a test files directory (-t).\n")
+ return CombineList(test_files_dir, list_output_file, True,
+ additional_runtime_options)
+
+ parser.error("Invalid command specified.")
+
+
+if __name__ == "__main__":
+ DoMain(sys.argv[1:])
diff --git a/chromium/chromecast/tools/trace.py b/chromium/chromecast/tools/trace.py
new file mode 100755
index 00000000000..bf93611e0ba
--- /dev/null
+++ b/chromium/chromecast/tools/trace.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script was originally written by Alok Priyadarshi (alokp@)
+# with some minor local modifications.
+
+import contextlib
+import json
+import logging
+import math
+import optparse
+import os
+import sys
+import websocket
+
+
+class TracingClient(object):
+ def BufferUsage(self, buffer_usage):
+ percent = int(math.floor(buffer_usage * 100))
+ logging.debug('Buffer Usage: %i', percent)
+
+
+class TracingBackend(object):
+ def __init__(self, devtools_port):
+ self._socket = None
+ self._next_request_id = 0
+ self._tracing_client = None
+ self._tracing_data = []
+
+ def Connect(self, device_ip, devtools_port, timeout=10):
+ assert not self._socket
+ url = 'ws://%s:%i/devtools/browser' % (device_ip, devtools_port)
+ print('Connect to %s ...' % url)
+ self._socket = websocket.create_connection(url, timeout=timeout)
+ self._next_request_id = 0
+
+ def Disconnect(self):
+ if self._socket:
+ self._socket.close()
+ self._socket = None
+
+ def StartTracing(self,
+ tracing_client=None,
+ custom_categories=None,
+ record_continuously=False,
+ buffer_usage_reporting_interval=0,
+ timeout=10):
+ self._tracing_client = tracing_client
+ self._socket.settimeout(timeout)
+ req = {
+ 'method': 'Tracing.start',
+ 'params': {
+ 'categories': custom_categories,
+ 'bufferUsageReportingInterval': buffer_usage_reporting_interval,
+ 'options': 'record-continuously' if record_continuously else
+ 'record-until-full'
+ }
+ }
+ self._SendRequest(req)
+
+ def StopTracing(self, timeout=30):
+ self._socket.settimeout(timeout)
+ req = {'method': 'Tracing.end'}
+ self._SendRequest(req)
+ while self._socket:
+ res = self._ReceiveResponse()
+ if 'method' in res and self._HandleResponse(res):
+ self._tracing_client = None
+ result = self._tracing_data
+ self._tracing_data = []
+ return result
+
+ def _SendRequest(self, req):
+ req['id'] = self._next_request_id
+ self._next_request_id += 1
+ data = json.dumps(req)
+ self._socket.send(data)
+
+ def _ReceiveResponse(self):
+ while self._socket:
+ data = self._socket.recv()
+ res = json.loads(data)
+ return res
+
+ def _HandleResponse(self, res):
+ method = res.get('method')
+ value = res.get('params', {}).get('value')
+ if 'Tracing.dataCollected' == method:
+ if type(value) in [str, unicode]:
+ self._tracing_data.append(value)
+ elif type(value) is list:
+ self._tracing_data.extend(value)
+ else:
+ logging.warning('Unexpected type in tracing data')
+ elif 'Tracing.bufferUsage' == method and self._tracing_client:
+ self._tracing_client.BufferUsage(value)
+ elif 'Tracing.tracingComplete' == method:
+ return True
+
+
+@contextlib.contextmanager
+def Connect(device_ip, devtools_port):
+ backend = TracingBackend(devtools_port)
+ try:
+ backend.Connect(device_ip, devtools_port)
+ yield backend
+ finally:
+ backend.Disconnect()
+
+
+def DumpTrace(trace, options):
+ filepath = os.path.expanduser(options.output) if options.output \
+ else os.path.join(os.getcwd(), 'trace.json')
+
+ dirname = os.path.dirname(filepath)
+ if dirname:
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ else:
+ filepath = os.path.join(os.getcwd(), filepath)
+
+ with open(filepath, "w") as f:
+ json.dump(trace, f)
+ return filepath
+
+
+def _CreateOptionParser():
+ parser = optparse.OptionParser(description='Record about://tracing profiles '
+ 'from any running instance of Chrome.')
+ parser.add_option(
+ '-v', '--verbose', help='Verbose logging.', action='store_true')
+ parser.add_option(
+ '-p', '--port', help='Remote debugging port.', type="int", default=9222)
+ parser.add_option(
+ '-d', '--device', help='Device ip address.', type='string',
+ default='127.0.0.1')
+
+ tracing_opts = optparse.OptionGroup(parser, 'Tracing options')
+ tracing_opts.add_option(
+ '-c', '--category-filter',
+ help='Apply filter to control what category groups should be traced.',
+ type='string')
+ tracing_opts.add_option(
+ '--record-continuously',
+ help='Keep recording until stopped. The trace buffer is of fixed size '
+ 'and used as a ring buffer. If this option is omitted then '
+ 'recording stops when the trace buffer is full.',
+ action='store_true')
+ parser.add_option_group(tracing_opts)
+
+ output_options = optparse.OptionGroup(parser, 'Output options')
+ output_options.add_option(
+ '-o', '--output',
+ help='Save trace output to file.')
+ parser.add_option_group(output_options)
+
+ return parser
+
+
+def _ProcessOptions(options):
+ websocket.enableTrace(options.verbose)
+
+
+def main():
+ parser = _CreateOptionParser()
+ options, _args = parser.parse_args()
+ _ProcessOptions(options)
+
+ with Connect(options.device, options.port) as tracing_backend:
+ tracing_backend.StartTracing(TracingClient(),
+ options.category_filter,
+ options.record_continuously)
+ raw_input('Capturing trace. Press Enter to stop...')
+ trace = tracing_backend.StopTracing()
+
+ filepath = DumpTrace(trace, options)
+ print('Done')
+ print('Trace written to file://%s' % filepath)
+
+
+if __name__ == '__main__':
+ sys.exit(main())