| // Copyright 2019 The Chromium OS 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 "arc/vm/libvda/event_pipe.h" |
| |
| #include <utility> |
| |
| #include <fcntl.h> |
| |
| #include <base/bind.h> |
| #include <base/files/file_util.h> |
| #include <base/logging.h> |
| |
| #include "arc/vm/libvda/libvda_decode.h" |
| #include "arc/vm/libvda/libvda_encode.h" |
| |
| namespace arc { |
| |
| namespace { |
| // This method should only be called on the |event_write_thread| in order to |
| // write |event|. This is done so that all events are sent in sequence |
| // (important for PICTURE_READY events), and to ensure that a full write of |
| // |event| is always done as a single operation. Using the IPC thread was |
| // considered, but then in cases where the pipe buffer is close to being full, |
| // write() could block, which would not be acceptable to the IPC thread. |
| // Setting the pipe to non-blocking mode was also considered, but then |
| // we would have to re-post a new task to complete the write which could |
| // cause ordering issues. |
| template <class T> |
| void WriteToFd(int fd, const T event) { |
| CHECK(base::WriteFileDescriptor(fd, reinterpret_cast<const char*>(&event), |
| sizeof(T))); |
| } |
| } // namespace |
| |
| EventPipe::EventPipe() : event_write_thread_("EventWriteThread") { |
| int pipe_fds[2]; |
| CHECK_EQ(pipe2(pipe_fds, O_CLOEXEC), 0); |
| |
| event_read_fd_.reset(pipe_fds[0]); |
| event_write_fd_.reset(pipe_fds[1]); |
| |
| // Start the dedicated event write thread for this session context. |
| CHECK(event_write_thread_.Start()); |
| } |
| |
| EventPipe::~EventPipe() = default; |
| |
| int EventPipe::GetReadFd() const { |
| return event_read_fd_.get(); |
| } |
| |
| void EventPipe::WriteVdaEvent(const vda_event_t& event) { |
| event_write_thread_.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&WriteToFd<vda_event_t>, event_write_fd_.get(), event)); |
| } |
| |
| void EventPipe::WriteVeaEvent(const vea_event_t& event) { |
| event_write_thread_.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&WriteToFd<vea_event_t>, event_write_fd_.get(), event)); |
| } |
| |
| } // namespace arc |