blob: ada08610836b6e1f2cd7050407b0ee6028e38fed [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "in_stream.h"
#include <fbl/auto_lock.h>
#include "src/media/codec/examples/use_media_decoder/util.h"
#include "util.h"
InStream::InStream(async::Loop* fidl_loop, thrd_t fidl_thread,
sys::ComponentContext* component_context)
: fidl_loop_(fidl_loop),
fidl_dispatcher_(fidl_loop_->dispatcher()),
fidl_thread_(fidl_thread),
component_context_(component_context) {
ZX_DEBUG_ASSERT(fidl_loop_);
// Not necessarily portable, but should be valid on Zircon:
ZX_DEBUG_ASSERT(fidl_thread_ != thrd_t{});
ZX_DEBUG_ASSERT(component_context_);
// For now, we don't allow construction on the fidl_thread.
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
}
InStream::~InStream() {
// Sub-classes probably also want to check this at the start of their
// destructor before blocking on the fidl_thread_ for anything. That way we
// get an assert failure instead of just getting stuck.
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
}
uint64_t InStream::cursor_position() const {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
return cursor_position_;
}
bool InStream::eos_position_known() {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
return eos_position_known_;
}
uint64_t InStream::eos_position() {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
ZX_ASSERT(eos_position_known_);
return eos_position_;
}
zx_status_t InStream::ReadBytesShort(uint32_t max_bytes_to_read, uint32_t* bytes_read_out,
uint8_t* buffer_out, zx::time just_fail_deadline) {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
ZX_DEBUG_ASSERT(!failure_seen_);
zx_status_t status =
ReadBytesInternal(max_bytes_to_read, bytes_read_out, buffer_out, just_fail_deadline);
if (status != ZX_OK) {
LOGF("ReadBytesInternal failed - status: %u", status);
failure_seen_ = true;
return status;
}
cursor_position_ += *bytes_read_out;
if (*bytes_read_out == 0) {
bool eos_position_known_before = eos_position_known_;
uint64_t eos_position_before = eos_position_;
if (!eos_position_known_before) {
eos_position_ = cursor_position_;
eos_position_known_ = true;
} else {
ZX_DEBUG_ASSERT(eos_position_before == cursor_position_);
}
}
return ZX_OK;
}
zx_status_t InStream::ReadBytesComplete(uint32_t max_bytes_to_read, uint32_t* bytes_read_out,
uint8_t* buffer_out, zx::time just_fail_deadline) {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
ZX_DEBUG_ASSERT(!failure_seen_);
uint32_t bytes_remaining = max_bytes_to_read;
uint8_t* buffer_iter = buffer_out;
while (bytes_remaining != 0) {
uint32_t actual_bytes_read;
zx_status_t status =
ReadBytesShort(bytes_remaining, &actual_bytes_read, buffer_iter, just_fail_deadline);
if (status != ZX_OK) {
ZX_DEBUG_ASSERT(failure_seen_);
return status;
}
buffer_iter += actual_bytes_read;
bytes_remaining -= actual_bytes_read;
if (actual_bytes_read == 0) {
// ReadBytesShort() took care of these already.
ZX_DEBUG_ASSERT(eos_position_known_);
ZX_DEBUG_ASSERT(cursor_position_ == eos_position_);
break;
}
}
*bytes_read_out = buffer_iter - buffer_out;
return ZX_OK;
}
void InStream::PostToFidlSerial(fit::closure to_run) {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
PostSerial(fidl_dispatcher_, std::move(to_run));
}
void InStream::FencePostToFidlSerial() {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
FencePostSerial(fidl_dispatcher_);
}
zx_status_t InStream::ResetToStart(zx::time just_fail_deadline) {
ZX_DEBUG_ASSERT(thrd_current() != fidl_thread_);
if (cursor_position_ == 0) {
return ZX_OK;
}
return ResetToStartInternal(just_fail_deadline);
}
zx_status_t InStream::ResetToStartInternal(zx::time just_fail_deadline) {
return ZX_ERR_NOT_SUPPORTED;
};