1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "init_webrtc.h"
6
7#include "base/command_line.h"
8#include "base/debug/trace_event.h"
9#include "base/files/file_path.h"
10#include "base/native_library.h"
11#include "base/path_service.h"
12#include "talk/base/basictypes.h"
13#include "third_party/libjingle/overrides/talk/base/logging.h"
14
15const unsigned char* GetCategoryGroupEnabled(const char* category_group) {
16  return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
17}
18
19void AddTraceEvent(char phase,
20                   const unsigned char* category_group_enabled,
21                   const char* name,
22                   unsigned long long id,
23                   int num_args,
24                   const char** arg_names,
25                   const unsigned char* arg_types,
26                   const unsigned long long* arg_values,
27                   unsigned char flags) {
28  TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name, id,
29                                  num_args, arg_names, arg_types, arg_values,
30                                  NULL, flags);
31}
32
33#if defined(LIBPEERCONNECTION_LIB)
34
35// libpeerconnection is being compiled as a static lib.  In this case
36// we don't need to do any initializing but to keep things simple we
37// provide an empty intialization routine so that this #ifdef doesn't
38// have to be in other places.
39bool InitializeWebRtcModule() {
40  webrtc::SetupEventTracer(&GetCategoryGroupEnabled, &AddTraceEvent);
41  return true;
42}
43
44#else  // !LIBPEERCONNECTION_LIB
45
46// When being compiled as a shared library, we need to bridge the gap between
47// the current module and the libpeerconnection module, so things get a tad
48// more complicated.
49
50// Global function pointers to the factory functions in the shared library.
51CreateWebRtcMediaEngineFunction g_create_webrtc_media_engine = NULL;
52DestroyWebRtcMediaEngineFunction g_destroy_webrtc_media_engine = NULL;
53
54// Returns the full or relative path to the libpeerconnection module depending
55// on what platform we're on.
56static base::FilePath GetLibPeerConnectionPath() {
57  base::FilePath path;
58  CHECK(PathService::Get(base::DIR_MODULE, &path));
59#if defined(OS_WIN)
60  path = path.Append(FILE_PATH_LITERAL("libpeerconnection.dll"));
61#elif defined(OS_MACOSX)
62  // Simulate '@loader_path/Libraries'.
63  path = path.Append(FILE_PATH_LITERAL("Libraries"))
64             .Append(FILE_PATH_LITERAL("libpeerconnection.so"));
65#elif defined(OS_ANDROID)
66  path = path.Append(FILE_PATH_LITERAL("libpeerconnection.so"));
67#else
68  path = path.Append(FILE_PATH_LITERAL("lib"))
69             .Append(FILE_PATH_LITERAL("libpeerconnection.so"));
70#endif
71  return path;
72}
73
74bool InitializeWebRtcModule() {
75  TRACE_EVENT0("webrtc", "InitializeWebRtcModule");
76
77  if (g_create_webrtc_media_engine)
78    return true;  // InitializeWebRtcModule has already been called.
79
80  base::FilePath path(GetLibPeerConnectionPath());
81  DVLOG(1) << "Loading WebRTC module: " << path.value();
82
83  std::string error;
84  static base::NativeLibrary lib =
85      base::LoadNativeLibrary(path, &error);
86  CHECK(lib) << error;
87
88  InitializeModuleFunction initialize_module =
89      reinterpret_cast<InitializeModuleFunction>(
90          base::GetFunctionPointerFromNativeLibrary(
91              lib, "InitializeModule"));
92
93  // Initialize the proxy by supplying it with a pointer to our
94  // allocator/deallocator routines.
95  // On mac we use malloc zones, which are global, so we provide NULLs for
96  // the alloc/dealloc functions.
97  // PS: This function is actually implemented in allocator_proxy.cc with the
98  // new/delete overrides.
99  InitDiagnosticLoggingDelegateFunctionFunction init_diagnostic_logging = NULL;
100  bool init_ok = initialize_module(*CommandLine::ForCurrentProcess(),
101#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
102      &Allocate, &Dellocate,
103#endif
104      logging::GetLogMessageHandler(),
105      &GetCategoryGroupEnabled, &AddTraceEvent,
106      &g_create_webrtc_media_engine, &g_destroy_webrtc_media_engine,
107      &init_diagnostic_logging);
108
109  if (init_ok)
110    talk_base::SetExtraLoggingInit(init_diagnostic_logging);
111  return init_ok;
112}
113
114cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
115    webrtc::AudioDeviceModule* adm,
116    webrtc::AudioDeviceModule* adm_sc,
117    cricket::WebRtcVideoEncoderFactory* encoder_factory,
118    cricket::WebRtcVideoDecoderFactory* decoder_factory) {
119  // For convenience of tests etc, we call InitializeWebRtcModule here.
120  // For Chrome however, InitializeWebRtcModule must be called
121  // explicitly before the sandbox is initialized.  In that case, this call is
122  // effectively a noop.
123  InitializeWebRtcModule();
124  return g_create_webrtc_media_engine(adm, adm_sc, encoder_factory,
125      decoder_factory);
126}
127
128void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
129  g_destroy_webrtc_media_engine(media_engine);
130}
131
132#endif  // LIBPEERCONNECTION_LIB
133