• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/modules/audio_device/android/low_latency_event.h"
12 
13 #include <assert.h>
14 
15 #define HANDLE_EINTR(x) ({                \
16       typeof(x) eintr_wrapper_result;     \
17       do {                                                        \
18         eintr_wrapper_result = (x);                               \
19       } while (eintr_wrapper_result == -1 && errno == EINTR);     \
20       eintr_wrapper_result;                                       \
21     })
22 
23 #define IGNORE_EINTR(x) ({                \
24       typeof(x) eintr_wrapper_result;     \
25       do {                                                        \
26         eintr_wrapper_result = (x);                               \
27         if (eintr_wrapper_result == -1 && errno == EINTR) {       \
28           eintr_wrapper_result = 0;                               \
29         }                                                         \
30       } while (0);                                                \
31       eintr_wrapper_result;                                       \
32     })
33 
34 namespace webrtc {
35 
36 const LowLatencyEvent::Handle LowLatencyEvent::kInvalidHandle = -1;
37 const int LowLatencyEvent::kReadHandle = 0;
38 const int LowLatencyEvent::kWriteHandle = 1;
39 
LowLatencyEvent()40 LowLatencyEvent::LowLatencyEvent() {
41   handles_[kReadHandle] = kInvalidHandle;
42   handles_[kWriteHandle] = kInvalidHandle;
43 }
44 
~LowLatencyEvent()45 LowLatencyEvent::~LowLatencyEvent() {
46   Stop();
47 }
48 
Start()49 bool LowLatencyEvent::Start() {
50   assert(handles_[kReadHandle] == kInvalidHandle);
51   assert(handles_[kWriteHandle] == kInvalidHandle);
52 
53   return socketpair(AF_UNIX, SOCK_STREAM, 0, handles_) == 0;
54 }
55 
Stop()56 bool LowLatencyEvent::Stop() {
57   bool ret = Close(&handles_[kReadHandle]) && Close(&handles_[kWriteHandle]);
58   handles_[kReadHandle] = kInvalidHandle;
59   handles_[kWriteHandle] = kInvalidHandle;
60   return ret;
61 }
62 
SignalEvent(int event_id,int event_msg)63 void LowLatencyEvent::SignalEvent(int event_id, int event_msg) {
64   WriteFd(event_id, event_msg);
65 }
66 
WaitOnEvent(int * event_id,int * event_msg)67 void LowLatencyEvent::WaitOnEvent(int* event_id, int* event_msg) {
68   ReadFd(event_id, event_msg);
69 }
70 
Close(Handle * handle)71 bool LowLatencyEvent::Close(Handle* handle) {
72   if (*handle == kInvalidHandle) {
73     return false;
74   }
75   int retval = IGNORE_EINTR(close(*handle));
76   *handle = kInvalidHandle;
77   return retval == 0;
78 }
79 
WriteFd(int message_id,int message)80 void LowLatencyEvent::WriteFd(int message_id, int message) {
81   char buffer[sizeof(message_id) + sizeof(message)];
82   size_t bytes = sizeof(buffer);
83   memcpy(buffer, &message_id, sizeof(message_id));
84   memcpy(&buffer[sizeof(message_id)], &message, sizeof(message));
85   ssize_t bytes_written = HANDLE_EINTR(write(handles_[kWriteHandle], buffer,
86                                              bytes));
87   if (bytes_written != static_cast<ssize_t>(bytes)) {
88     assert(false);
89   }
90 }
91 
ReadFd(int * message_id,int * message)92 void LowLatencyEvent::ReadFd(int* message_id, int* message) {
93   char buffer[sizeof(message_id) + sizeof(message)];
94   size_t bytes = sizeof(buffer);
95   ssize_t bytes_read = HANDLE_EINTR(read(handles_[kReadHandle], buffer, bytes));
96   if (bytes_read == 0) {
97     *message_id = 0;
98     *message = 0;
99     return;
100   } else if (bytes_read == static_cast<ssize_t>(bytes)) {
101     memcpy(message_id, buffer, sizeof(*message_id));
102     memcpy(message, &buffer[sizeof(*message_id)], sizeof(*message));
103   } else {
104     assert(false);
105   }
106 }
107 
108 }  // namespace webrtc
109