7 #include "packager/media/file/io_cache.h"
13 #include "packager/base/logging.h"
18 using base::AutoUnlock;
22 IoCache::IoCache(uint64_t cache_size)
23 : cache_size_(cache_size),
24 read_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
25 base::WaitableEvent::InitialState::NOT_SIGNALED),
26 write_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
27 base::WaitableEvent::InitialState::NOT_SIGNALED),
30 circular_buffer_(cache_size + 1),
31 end_ptr_(&circular_buffer_[0] + cache_size + 1),
32 r_ptr_(circular_buffer_.data()),
33 w_ptr_(circular_buffer_.data()),
40 uint64_t IoCache::Read(
void* buffer, uint64_t size) {
44 while (!closed_ && (BytesCachedInternal() == 0)) {
45 AutoUnlock unlock(lock_);
49 size = std::min(size, BytesCachedInternal());
50 uint64_t first_chunk_size(std::min(size, static_cast<uint64_t>(
52 memcpy(buffer, r_ptr_, first_chunk_size);
53 r_ptr_ += first_chunk_size;
54 DCHECK_GE(end_ptr_, r_ptr_);
55 if (r_ptr_ == end_ptr_)
56 r_ptr_ = &circular_buffer_[0];
57 uint64_t second_chunk_size(size - first_chunk_size);
58 if (second_chunk_size) {
59 memcpy(static_cast<uint8_t*>(buffer) + first_chunk_size, r_ptr_,
61 r_ptr_ += second_chunk_size;
62 DCHECK_GT(end_ptr_, r_ptr_);
68 uint64_t IoCache::Write(
const void* buffer, uint64_t size) {
71 const uint8_t* r_ptr(static_cast<const uint8_t*>(buffer));
72 uint64_t bytes_left(size);
75 while (!closed_ && (BytesFreeInternal() == 0)) {
76 AutoUnlock unlock(lock_);
82 uint64_t write_size(std::min(bytes_left, BytesFreeInternal()));
83 uint64_t first_chunk_size(std::min(write_size, static_cast<uint64_t>(
85 memcpy(w_ptr_, r_ptr, first_chunk_size);
86 w_ptr_ += first_chunk_size;
87 DCHECK_GE(end_ptr_, w_ptr_);
88 if (w_ptr_ == end_ptr_)
89 w_ptr_ = &circular_buffer_[0];
90 r_ptr += first_chunk_size;
91 uint64_t second_chunk_size(write_size - first_chunk_size);
92 if (second_chunk_size) {
93 memcpy(w_ptr_, r_ptr, second_chunk_size);
94 w_ptr_ += second_chunk_size;
95 DCHECK_GT(end_ptr_, w_ptr_);
96 r_ptr += second_chunk_size;
98 bytes_left -= write_size;
99 write_event_.Signal();
104 void IoCache::Clear() {
105 AutoLock lock(lock_);
106 r_ptr_ = w_ptr_ = circular_buffer_.data();
108 read_event_.Signal();
111 void IoCache::Close() {
112 AutoLock lock(lock_);
114 read_event_.Signal();
115 write_event_.Signal();
118 void IoCache::Reopen() {
119 AutoLock lock(lock_);
121 r_ptr_ = w_ptr_ = circular_buffer_.data();
124 write_event_.Reset();
127 uint64_t IoCache::BytesCached() {
128 AutoLock lock(lock_);
129 return BytesCachedInternal();
132 uint64_t IoCache::BytesFree() {
133 AutoLock lock(lock_);
134 return BytesFreeInternal();
137 uint64_t IoCache::BytesCachedInternal() {
138 return (r_ptr_ <= w_ptr_)
140 : (end_ptr_ - r_ptr_) + (w_ptr_ - circular_buffer_.data());
143 uint64_t IoCache::BytesFreeInternal() {
144 return cache_size_ - BytesCachedInternal();
147 void IoCache::WaitUntilEmptyOrClosed() {
148 AutoLock lock(lock_);
149 while (!closed_ && BytesCachedInternal()) {
150 AutoUnlock unlock(lock_);