DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
io_cache.cc
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/file/io_cache.h"
8 
9 #include <string.h>
10 
11 #include <algorithm>
12 
13 #include "packager/base/logging.h"
14 
15 namespace shaka {
16 
17 using base::AutoLock;
18 using base::AutoUnlock;
19 
20 namespace media {
21 
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),
28  // Make the buffer one byte larger than the cache so that when the
29  // condition r_ptr == w_ptr is unambiguous (buffer empty).
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()),
34  closed_(false) {}
35 
36 IoCache::~IoCache() {
37  Close();
38 }
39 
40 uint64_t IoCache::Read(void* buffer, uint64_t size) {
41  DCHECK(buffer);
42 
43  AutoLock lock(lock_);
44  while (!closed_ && (BytesCachedInternal() == 0)) {
45  AutoUnlock unlock(lock_);
46  write_event_.Wait();
47  }
48 
49  size = std::min(size, BytesCachedInternal());
50  uint64_t first_chunk_size(std::min(size, static_cast<uint64_t>(
51  end_ptr_ - r_ptr_)));
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_,
60  second_chunk_size);
61  r_ptr_ += second_chunk_size;
62  DCHECK_GT(end_ptr_, r_ptr_);
63  }
64  read_event_.Signal();
65  return size;
66 }
67 
68 uint64_t IoCache::Write(const void* buffer, uint64_t size) {
69  DCHECK(buffer);
70 
71  const uint8_t* r_ptr(static_cast<const uint8_t*>(buffer));
72  uint64_t bytes_left(size);
73  while (bytes_left) {
74  AutoLock lock(lock_);
75  while (!closed_ && (BytesFreeInternal() == 0)) {
76  AutoUnlock unlock(lock_);
77  read_event_.Wait();
78  }
79  if (closed_)
80  return 0;
81 
82  uint64_t write_size(std::min(bytes_left, BytesFreeInternal()));
83  uint64_t first_chunk_size(std::min(write_size, static_cast<uint64_t>(
84  end_ptr_ - w_ptr_)));
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;
97  }
98  bytes_left -= write_size;
99  write_event_.Signal();
100  }
101  return size;
102 }
103 
105  AutoLock lock(lock_);
106  r_ptr_ = w_ptr_ = circular_buffer_.data();
107  // Let any writers know that there is room in the cache.
108  read_event_.Signal();
109 }
110 
112  AutoLock lock(lock_);
113  closed_ = true;
114  read_event_.Signal();
115  write_event_.Signal();
116 }
117 
119  AutoLock lock(lock_);
120  CHECK(closed_);
121  r_ptr_ = w_ptr_ = circular_buffer_.data();
122  closed_ = false;
123  read_event_.Reset();
124  write_event_.Reset();
125 }
126 
128  AutoLock lock(lock_);
129  return BytesCachedInternal();
130 }
131 
132 uint64_t IoCache::BytesFree() {
133  AutoLock lock(lock_);
134  return BytesFreeInternal();
135 }
136 
137 uint64_t IoCache::BytesCachedInternal() {
138  return (r_ptr_ <= w_ptr_)
139  ? w_ptr_ - r_ptr_
140  : (end_ptr_ - r_ptr_) + (w_ptr_ - circular_buffer_.data());
141 }
142 
143 uint64_t IoCache::BytesFreeInternal() {
144  return cache_size_ - BytesCachedInternal();
145 }
146 
148  AutoLock lock(lock_);
149  while (!closed_ && BytesCachedInternal()) {
150  AutoUnlock unlock(lock_);
151  read_event_.Wait();
152  }
153 }
154 
155 } // namespace media
156 } // namespace shaka
void Clear()
Empties the cache.
Definition: io_cache.cc:104
void WaitUntilEmptyOrClosed()
Waits until the cache is empty or has been closed.
Definition: io_cache.cc:147
uint64_t BytesFree()
Definition: io_cache.cc:132
void Reopen()
Reopens the cache. Any data still in the cache will be lost.
Definition: io_cache.cc:118
uint64_t Read(void *buffer, uint64_t size)
Definition: io_cache.cc:40
uint64_t BytesCached()
Definition: io_cache.cc:127
uint64_t Write(const void *buffer, uint64_t size)
Definition: io_cache.cc:68