Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
#include <stdlib.h> // for free, malloc
|
||||
#include <string.h> // for memcpy
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
// Reference on memory alignment:
|
||||
// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
|
||||
namespace webrtc {
|
||||
|
||||
uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
|
||||
// The pointer should be aligned with `alignment` bytes. The - 1 guarantees
|
||||
// that it is aligned towards the closest higher (right) address.
|
||||
return (start_pos + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Alignment must be an integer power of two.
|
||||
bool ValidAlignment(size_t alignment) {
|
||||
if (!alignment) {
|
||||
return false;
|
||||
}
|
||||
return (alignment & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
void* GetRightAlign(const void* pointer, size_t alignment) {
|
||||
if (!pointer) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer);
|
||||
return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
|
||||
}
|
||||
|
||||
void* AlignedMalloc(size_t size, size_t alignment) {
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The memory is aligned towards the lowest address that so only
|
||||
// alignment - 1 bytes needs to be allocated.
|
||||
// A pointer to the start of the memory must be stored so that it can be
|
||||
// retreived for deletion, ergo the sizeof(uintptr_t).
|
||||
void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
|
||||
RTC_CHECK(memory_pointer) << "Couldn't allocate memory in AlignedMalloc";
|
||||
|
||||
// Aligning after the sizeof(uintptr_t) bytes will leave room for the header
|
||||
// in the same memory block.
|
||||
uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
align_start_pos += sizeof(uintptr_t);
|
||||
uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
|
||||
void* aligned_pointer = reinterpret_cast<void*>(aligned_pos);
|
||||
|
||||
// Store the address to the beginning of the memory just before the aligned
|
||||
// memory.
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
void* header_pointer = reinterpret_cast<void*>(header_pos);
|
||||
uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
|
||||
|
||||
return aligned_pointer;
|
||||
}
|
||||
|
||||
void AlignedFree(void* mem_block) {
|
||||
if (mem_block == NULL) {
|
||||
return;
|
||||
}
|
||||
uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
|
||||
// Read out the address of the AlignedMemory struct from the header.
|
||||
uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos);
|
||||
void* memory_start = reinterpret_cast<void*>(memory_start_pos);
|
||||
free(memory_start);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef RTC_BASE_MEMORY_ALIGNED_MALLOC_H_
|
||||
#define RTC_BASE_MEMORY_ALIGNED_MALLOC_H_
|
||||
|
||||
// The functions declared here
|
||||
// 1) Allocates block of aligned memory.
|
||||
// 2) Re-calculates a pointer such that it is aligned to a higher or equal
|
||||
// address.
|
||||
// Note: alignment must be a power of two. The alignment is in bytes.
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Returns a pointer to the first boundry of `alignment` bytes following the
|
||||
// address of `ptr`.
|
||||
// Note that there is no guarantee that the memory in question is available.
|
||||
// `ptr` has no requirements other than it can't be NULL.
|
||||
void* GetRightAlign(const void* ptr, size_t alignment);
|
||||
|
||||
// Allocates memory of `size` bytes aligned on an `alignment` boundry.
|
||||
// The return value is a pointer to the memory. Note that the memory must
|
||||
// be de-allocated using AlignedFree.
|
||||
void* AlignedMalloc(size_t size, size_t alignment);
|
||||
// De-allocates memory created using the AlignedMalloc() API.
|
||||
void AlignedFree(void* mem_block);
|
||||
|
||||
// Templated versions to facilitate usage of aligned malloc without casting
|
||||
// to and from void*.
|
||||
template <typename T>
|
||||
T* GetRightAlign(const T* ptr, size_t alignment) {
|
||||
return reinterpret_cast<T*>(
|
||||
GetRightAlign(reinterpret_cast<const void*>(ptr), alignment));
|
||||
}
|
||||
template <typename T>
|
||||
T* AlignedMalloc(size_t size, size_t alignment) {
|
||||
return reinterpret_cast<T*>(AlignedMalloc(size, alignment));
|
||||
}
|
||||
|
||||
// Deleter for use with unique_ptr. E.g., use as
|
||||
// std::unique_ptr<Foo, AlignedFreeDeleter> foo;
|
||||
struct AlignedFreeDeleter {
|
||||
inline void operator()(void* ptr) const { AlignedFree(ptr); }
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // RTC_BASE_MEMORY_ALIGNED_MALLOC_H_
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright 2022 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef RTC_BASE_MEMORY_ALWAYS_VALID_POINTER_H_
|
||||
#define RTC_BASE_MEMORY_ALWAYS_VALID_POINTER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This template allows the instantiation of a pointer to Interface in such a
|
||||
// way that if it is passed a null pointer, an object of class Default will be
|
||||
// created, which will be deallocated when the pointer is deleted.
|
||||
template <typename Interface, typename Default = Interface>
|
||||
class AlwaysValidPointer {
|
||||
public:
|
||||
explicit AlwaysValidPointer(Interface* pointer)
|
||||
: owned_instance_(pointer ? nullptr : std::make_unique<Default>()),
|
||||
pointer_(pointer ? pointer : owned_instance_.get()) {
|
||||
RTC_DCHECK(pointer_);
|
||||
}
|
||||
|
||||
template <typename Arg,
|
||||
typename std::enable_if<!(std::is_invocable<Arg>::value),
|
||||
bool>::type = true>
|
||||
AlwaysValidPointer(Interface* pointer, Arg arg)
|
||||
: owned_instance_(pointer ? nullptr
|
||||
: std::make_unique<Default>(std::move(arg))),
|
||||
pointer_(pointer ? pointer : owned_instance_.get()) {
|
||||
RTC_DCHECK(pointer_);
|
||||
}
|
||||
|
||||
// Multiple arguments
|
||||
template <typename Arg1, typename... Args>
|
||||
AlwaysValidPointer(Interface* pointer, Arg1 arg1, Args... args)
|
||||
: owned_instance_(pointer
|
||||
? nullptr
|
||||
: std::make_unique<Default>(std::move(arg1),
|
||||
std::move(args...))),
|
||||
pointer_(pointer ? pointer : owned_instance_.get()) {
|
||||
RTC_DCHECK(pointer_);
|
||||
}
|
||||
|
||||
// Create a pointer by
|
||||
// a) using |pointer|, without taking ownership
|
||||
// b) calling |function| and taking ownership of the result
|
||||
template <typename Func,
|
||||
typename std::enable_if<std::is_invocable<Func>::value,
|
||||
bool>::type = true>
|
||||
AlwaysValidPointer(Interface* pointer, Func function)
|
||||
: owned_instance_(pointer ? nullptr : function()),
|
||||
pointer_(owned_instance_ ? owned_instance_.get() : pointer) {
|
||||
RTC_DCHECK(pointer_);
|
||||
}
|
||||
|
||||
// Create a pointer by
|
||||
// a) taking over ownership of |instance|
|
||||
// b) or fallback to |pointer|, without taking ownership.
|
||||
// c) or Default.
|
||||
AlwaysValidPointer(std::unique_ptr<Interface>&& instance, Interface* pointer)
|
||||
: owned_instance_(
|
||||
instance
|
||||
? std::move(instance)
|
||||
: (pointer == nullptr ? std::make_unique<Default>() : nullptr)),
|
||||
pointer_(owned_instance_ ? owned_instance_.get() : pointer) {
|
||||
RTC_DCHECK(pointer_);
|
||||
}
|
||||
|
||||
// Create a pointer by
|
||||
// a) taking over ownership of |instance|
|
||||
// b) or fallback to |pointer|, without taking ownership.
|
||||
// c) or Default (with forwarded args).
|
||||
template <typename... Args>
|
||||
AlwaysValidPointer(std::unique_ptr<Interface>&& instance,
|
||||
Interface* pointer,
|
||||
Args... args)
|
||||
: owned_instance_(
|
||||
instance ? std::move(instance)
|
||||
: (pointer == nullptr
|
||||
? std::make_unique<Default>(std::move(args...))
|
||||
: nullptr)),
|
||||
pointer_(owned_instance_ ? owned_instance_.get() : pointer) {
|
||||
RTC_DCHECK(pointer_);
|
||||
}
|
||||
|
||||
Interface* get() { return pointer_; }
|
||||
Interface* operator->() { return pointer_; }
|
||||
Interface& operator*() { return *pointer_; }
|
||||
|
||||
Interface* get() const { return pointer_; }
|
||||
Interface* operator->() const { return pointer_; }
|
||||
Interface& operator*() const { return *pointer_; }
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Interface> owned_instance_;
|
||||
Interface* const pointer_;
|
||||
};
|
||||
|
||||
// This class is similar to AlwaysValidPointer, but it does not create
|
||||
// a default object and crashes if none of the input pointers are non-null.
|
||||
template <typename Interface>
|
||||
class AlwaysValidPointerNoDefault {
|
||||
public:
|
||||
explicit AlwaysValidPointerNoDefault(Interface* pointer) : pointer_(pointer) {
|
||||
RTC_CHECK(pointer_);
|
||||
}
|
||||
|
||||
// Create a pointer by
|
||||
// a) taking over ownership of |instance|
|
||||
// b) or fallback to |pointer|, without taking ownership.
|
||||
// At least one of the arguments must be non-null.
|
||||
explicit AlwaysValidPointerNoDefault(std::unique_ptr<Interface> instance,
|
||||
Interface* pointer = nullptr)
|
||||
: owned_instance_(std::move(instance)),
|
||||
pointer_(owned_instance_ ? owned_instance_.get() : pointer) {
|
||||
RTC_CHECK(pointer_);
|
||||
}
|
||||
|
||||
Interface* get() { return pointer_; }
|
||||
Interface* operator->() { return pointer_; }
|
||||
Interface& operator*() { return *pointer_; }
|
||||
|
||||
Interface* get() const { return pointer_; }
|
||||
Interface* operator->() const { return pointer_; }
|
||||
Interface& operator*() const { return *pointer_; }
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Interface> owned_instance_;
|
||||
Interface* const pointer_;
|
||||
};
|
||||
|
||||
template <typename T, typename U, typename V, typename W>
|
||||
bool operator==(const AlwaysValidPointer<T, U>& a,
|
||||
const AlwaysValidPointer<V, W>& b) {
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename V, typename W>
|
||||
bool operator!=(const AlwaysValidPointer<T, U>& a,
|
||||
const AlwaysValidPointer<V, W>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const AlwaysValidPointer<T, U>& a, std::nullptr_t) {
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const AlwaysValidPointer<T, U>& a, std::nullptr_t) {
|
||||
return !(a == nullptr);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(std::nullptr_t, const AlwaysValidPointer<T, U>& a) {
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(std::nullptr_t, const AlwaysValidPointer<T, U>& a) {
|
||||
return !(a == nullptr);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const AlwaysValidPointerNoDefault<T>& a,
|
||||
const AlwaysValidPointerNoDefault<U>& b) {
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const AlwaysValidPointerNoDefault<T>& a,
|
||||
const AlwaysValidPointerNoDefault<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const AlwaysValidPointerNoDefault<T>& a, std::nullptr_t) {
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const AlwaysValidPointerNoDefault<T>& a, std::nullptr_t) {
|
||||
return !(a == nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(std::nullptr_t, const AlwaysValidPointerNoDefault<T>& a) {
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(std::nullptr_t, const AlwaysValidPointerNoDefault<T>& a) {
|
||||
return !(a == nullptr);
|
||||
}
|
||||
|
||||
// Comparison with raw pointer.
|
||||
template <typename T, typename U, typename V>
|
||||
bool operator==(const AlwaysValidPointer<T, U>& a, const V* b) {
|
||||
return a.get() == b;
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename V>
|
||||
bool operator!=(const AlwaysValidPointer<T, U>& a, const V* b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename V>
|
||||
bool operator==(const T* a, const AlwaysValidPointer<U, V>& b) {
|
||||
return a == b.get();
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename V>
|
||||
bool operator!=(const T* a, const AlwaysValidPointer<U, V>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const AlwaysValidPointerNoDefault<T>& a, const U* b) {
|
||||
return a.get() == b;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const AlwaysValidPointerNoDefault<T>& a, const U* b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const T* a, const AlwaysValidPointerNoDefault<U>& b) {
|
||||
return a == b.get();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const T* a, const AlwaysValidPointerNoDefault<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // RTC_BASE_MEMORY_ALWAYS_VALID_POINTER_H_
|
||||
197
TMessagesProj/jni/voip/webrtc/rtc_base/memory/fifo_buffer.cc
Normal file
197
TMessagesProj/jni/voip/webrtc/rtc_base/memory/fifo_buffer.cc
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "rtc_base/memory/fifo_buffer.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rtc_base/thread.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
FifoBuffer::FifoBuffer(size_t size)
|
||||
: state_(SS_OPEN),
|
||||
buffer_(new char[size]),
|
||||
buffer_length_(size),
|
||||
data_length_(0),
|
||||
read_position_(0),
|
||||
owner_(Thread::Current()) {
|
||||
// all events are done on the owner_ thread
|
||||
}
|
||||
|
||||
FifoBuffer::FifoBuffer(size_t size, Thread* owner)
|
||||
: state_(SS_OPEN),
|
||||
buffer_(new char[size]),
|
||||
buffer_length_(size),
|
||||
data_length_(0),
|
||||
read_position_(0),
|
||||
owner_(owner) {
|
||||
// all events are done on the owner_ thread
|
||||
}
|
||||
|
||||
FifoBuffer::~FifoBuffer() {}
|
||||
|
||||
bool FifoBuffer::GetBuffered(size_t* size) const {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
*size = data_length_;
|
||||
return true;
|
||||
}
|
||||
|
||||
StreamState FifoBuffer::GetState() const {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
return state_;
|
||||
}
|
||||
|
||||
StreamResult FifoBuffer::Read(rtc::ArrayView<uint8_t> buffer,
|
||||
size_t& bytes_read,
|
||||
int& error) {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
const bool was_writable = data_length_ < buffer_length_;
|
||||
size_t copy = 0;
|
||||
StreamResult result = ReadLocked(buffer.data(), buffer.size(), ©);
|
||||
|
||||
if (result == SR_SUCCESS) {
|
||||
// If read was successful then adjust the read position and number of
|
||||
// bytes buffered.
|
||||
read_position_ = (read_position_ + copy) % buffer_length_;
|
||||
data_length_ -= copy;
|
||||
bytes_read = copy;
|
||||
|
||||
// if we were full before, and now we're not, post an event
|
||||
if (!was_writable && copy > 0) {
|
||||
PostEvent(SE_WRITE, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
StreamResult FifoBuffer::Write(rtc::ArrayView<const uint8_t> buffer,
|
||||
size_t& bytes_written,
|
||||
int& error) {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
|
||||
const bool was_readable = (data_length_ > 0);
|
||||
size_t copy = 0;
|
||||
StreamResult result = WriteLocked(buffer.data(), buffer.size(), ©);
|
||||
|
||||
if (result == SR_SUCCESS) {
|
||||
// If write was successful then adjust the number of readable bytes.
|
||||
data_length_ += copy;
|
||||
bytes_written = copy;
|
||||
// if we didn't have any data to read before, and now we do, post an event
|
||||
if (!was_readable && copy > 0) {
|
||||
PostEvent(SE_READ, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FifoBuffer::Close() {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
state_ = SS_CLOSED;
|
||||
}
|
||||
|
||||
const void* FifoBuffer::GetReadData(size_t* size) {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
*size = (read_position_ + data_length_ <= buffer_length_)
|
||||
? data_length_
|
||||
: buffer_length_ - read_position_;
|
||||
return &buffer_[read_position_];
|
||||
}
|
||||
|
||||
void FifoBuffer::ConsumeReadData(size_t size) {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
RTC_DCHECK(size <= data_length_);
|
||||
const bool was_writable = data_length_ < buffer_length_;
|
||||
read_position_ = (read_position_ + size) % buffer_length_;
|
||||
data_length_ -= size;
|
||||
if (!was_writable && size > 0) {
|
||||
PostEvent(SE_WRITE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void* FifoBuffer::GetWriteBuffer(size_t* size) {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
if (state_ == SS_CLOSED) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if empty, reset the write position to the beginning, so we can get
|
||||
// the biggest possible block
|
||||
if (data_length_ == 0) {
|
||||
read_position_ = 0;
|
||||
}
|
||||
|
||||
const size_t write_position =
|
||||
(read_position_ + data_length_) % buffer_length_;
|
||||
*size = (write_position > read_position_ || data_length_ == 0)
|
||||
? buffer_length_ - write_position
|
||||
: read_position_ - write_position;
|
||||
return &buffer_[write_position];
|
||||
}
|
||||
|
||||
void FifoBuffer::ConsumeWriteBuffer(size_t size) {
|
||||
webrtc::MutexLock lock(&mutex_);
|
||||
RTC_DCHECK(size <= buffer_length_ - data_length_);
|
||||
const bool was_readable = (data_length_ > 0);
|
||||
data_length_ += size;
|
||||
if (!was_readable && size > 0) {
|
||||
PostEvent(SE_READ, 0);
|
||||
}
|
||||
}
|
||||
|
||||
StreamResult FifoBuffer::ReadLocked(void* buffer,
|
||||
size_t bytes,
|
||||
size_t* bytes_read) {
|
||||
if (data_length_ == 0) {
|
||||
return (state_ != SS_CLOSED) ? SR_BLOCK : SR_EOS;
|
||||
}
|
||||
|
||||
const size_t available = data_length_;
|
||||
const size_t read_position = read_position_ % buffer_length_;
|
||||
const size_t copy = std::min(bytes, available);
|
||||
const size_t tail_copy = std::min(copy, buffer_length_ - read_position);
|
||||
char* const p = static_cast<char*>(buffer);
|
||||
memcpy(p, &buffer_[read_position], tail_copy);
|
||||
memcpy(p + tail_copy, &buffer_[0], copy - tail_copy);
|
||||
|
||||
if (bytes_read) {
|
||||
*bytes_read = copy;
|
||||
}
|
||||
return SR_SUCCESS;
|
||||
}
|
||||
|
||||
StreamResult FifoBuffer::WriteLocked(const void* buffer,
|
||||
size_t bytes,
|
||||
size_t* bytes_written) {
|
||||
if (state_ == SS_CLOSED) {
|
||||
return SR_EOS;
|
||||
}
|
||||
|
||||
if (data_length_ >= buffer_length_) {
|
||||
return SR_BLOCK;
|
||||
}
|
||||
|
||||
const size_t available = buffer_length_ - data_length_;
|
||||
const size_t write_position =
|
||||
(read_position_ + data_length_) % buffer_length_;
|
||||
const size_t copy = std::min(bytes, available);
|
||||
const size_t tail_copy = std::min(copy, buffer_length_ - write_position);
|
||||
const char* const p = static_cast<const char*>(buffer);
|
||||
memcpy(&buffer_[write_position], p, tail_copy);
|
||||
memcpy(&buffer_[0], p + tail_copy, copy - tail_copy);
|
||||
|
||||
if (bytes_written) {
|
||||
*bytes_written = copy;
|
||||
}
|
||||
return SR_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
118
TMessagesProj/jni/voip/webrtc/rtc_base/memory/fifo_buffer.h
Normal file
118
TMessagesProj/jni/voip/webrtc/rtc_base/memory/fifo_buffer.h
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef RTC_BASE_MEMORY_FIFO_BUFFER_H_
|
||||
#define RTC_BASE_MEMORY_FIFO_BUFFER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "api/task_queue/pending_task_safety_flag.h"
|
||||
#include "rtc_base/stream.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// FifoBuffer allows for efficient, thread-safe buffering of data between
|
||||
// writer and reader.
|
||||
class FifoBuffer final : public StreamInterface {
|
||||
public:
|
||||
// Creates a FIFO buffer with the specified capacity.
|
||||
explicit FifoBuffer(size_t length);
|
||||
// Creates a FIFO buffer with the specified capacity and owner
|
||||
FifoBuffer(size_t length, Thread* owner);
|
||||
~FifoBuffer() override;
|
||||
|
||||
FifoBuffer(const FifoBuffer&) = delete;
|
||||
FifoBuffer& operator=(const FifoBuffer&) = delete;
|
||||
|
||||
// Gets the amount of data currently readable from the buffer.
|
||||
bool GetBuffered(size_t* data_len) const;
|
||||
|
||||
// StreamInterface methods
|
||||
StreamState GetState() const override;
|
||||
StreamResult Read(rtc::ArrayView<uint8_t> buffer,
|
||||
size_t& bytes_read,
|
||||
int& error) override;
|
||||
StreamResult Write(rtc::ArrayView<const uint8_t> buffer,
|
||||
size_t& bytes_written,
|
||||
int& error) override;
|
||||
void Close() override;
|
||||
|
||||
// Seek to a byte offset from the beginning of the stream. Returns false if
|
||||
// the stream does not support seeking, or cannot seek to the specified
|
||||
// position.
|
||||
bool SetPosition(size_t position);
|
||||
|
||||
// Get the byte offset of the current position from the start of the stream.
|
||||
// Returns false if the position is not known.
|
||||
bool GetPosition(size_t* position) const;
|
||||
|
||||
// Seek to the start of the stream.
|
||||
bool Rewind() { return SetPosition(0); }
|
||||
|
||||
// GetReadData returns a pointer to a buffer which is owned by the stream.
|
||||
// The buffer contains data_len bytes. null is returned if no data is
|
||||
// available, or if the method fails. If the caller processes the data, it
|
||||
// must call ConsumeReadData with the number of processed bytes. GetReadData
|
||||
// does not require a matching call to ConsumeReadData if the data is not
|
||||
// processed. Read and ConsumeReadData invalidate the buffer returned by
|
||||
// GetReadData.
|
||||
const void* GetReadData(size_t* data_len);
|
||||
void ConsumeReadData(size_t used);
|
||||
// GetWriteBuffer returns a pointer to a buffer which is owned by the stream.
|
||||
// The buffer has a capacity of buf_len bytes. null is returned if there is
|
||||
// no buffer available, or if the method fails. The call may write data to
|
||||
// the buffer, and then call ConsumeWriteBuffer with the number of bytes
|
||||
// written. GetWriteBuffer does not require a matching call to
|
||||
// ConsumeWriteData if no data is written. Write and
|
||||
// ConsumeWriteData invalidate the buffer returned by GetWriteBuffer.
|
||||
void* GetWriteBuffer(size_t* buf_len);
|
||||
void ConsumeWriteBuffer(size_t used);
|
||||
|
||||
private:
|
||||
void PostEvent(int events, int err) {
|
||||
owner_->PostTask(webrtc::SafeTask(
|
||||
task_safety_.flag(),
|
||||
[this, events, err]() { SignalEvent(this, events, err); }));
|
||||
}
|
||||
|
||||
// Helper method that implements Read. Caller must acquire a lock
|
||||
// when calling this method.
|
||||
StreamResult ReadLocked(void* buffer, size_t bytes, size_t* bytes_read)
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Helper method that implements Write. Caller must acquire a lock
|
||||
// when calling this method.
|
||||
StreamResult WriteLocked(const void* buffer,
|
||||
size_t bytes,
|
||||
size_t* bytes_written)
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
webrtc::ScopedTaskSafety task_safety_;
|
||||
|
||||
// keeps the opened/closed state of the stream
|
||||
StreamState state_ RTC_GUARDED_BY(mutex_);
|
||||
// the allocated buffer
|
||||
std::unique_ptr<char[]> buffer_ RTC_GUARDED_BY(mutex_);
|
||||
// size of the allocated buffer
|
||||
const size_t buffer_length_;
|
||||
// amount of readable data in the buffer
|
||||
size_t data_length_ RTC_GUARDED_BY(mutex_);
|
||||
// offset to the readable data
|
||||
size_t read_position_ RTC_GUARDED_BY(mutex_);
|
||||
// stream callbacks are dispatched on this thread
|
||||
Thread* const owner_;
|
||||
// object lock
|
||||
mutable webrtc::Mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // RTC_BASE_MEMORY_FIFO_BUFFER_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue