1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/base/transformadapter.h"
12
13 #include <string.h>
14
15 #include "webrtc/base/common.h"
16
17 namespace rtc {
18
19 ///////////////////////////////////////////////////////////////////////////////
20
TransformAdapter(StreamInterface * stream,TransformInterface * transform,bool direction_read)21 TransformAdapter::TransformAdapter(StreamInterface * stream,
22 TransformInterface * transform,
23 bool direction_read)
24 : StreamAdapterInterface(stream), transform_(transform),
25 direction_read_(direction_read), state_(ST_PROCESSING), len_(0) {
26 }
27
~TransformAdapter()28 TransformAdapter::~TransformAdapter() {
29 TransformAdapter::Close();
30 delete transform_;
31 }
32
33 StreamResult
Read(void * buffer,size_t buffer_len,size_t * read,int * error)34 TransformAdapter::Read(void * buffer, size_t buffer_len,
35 size_t * read, int * error) {
36 if (!direction_read_)
37 return SR_EOS;
38
39 while (state_ != ST_ERROR) {
40 if (state_ == ST_COMPLETE)
41 return SR_EOS;
42
43 // Buffer more data
44 if ((state_ == ST_PROCESSING) && (len_ < sizeof(buffer_))) {
45 size_t subread;
46 StreamResult result = StreamAdapterInterface::Read(
47 buffer_ + len_,
48 sizeof(buffer_) - len_,
49 &subread,
50 &error_);
51 if (result == SR_BLOCK) {
52 return SR_BLOCK;
53 } else if (result == SR_ERROR) {
54 state_ = ST_ERROR;
55 break;
56 } else if (result == SR_EOS) {
57 state_ = ST_FLUSHING;
58 } else {
59 len_ += subread;
60 }
61 }
62
63 // Process buffered data
64 size_t in_len = len_;
65 size_t out_len = buffer_len;
66 StreamResult result = transform_->Transform(buffer_, &in_len,
67 buffer, &out_len,
68 (state_ == ST_FLUSHING));
69 ASSERT(result != SR_BLOCK);
70 if (result == SR_EOS) {
71 // Note: Don't signal SR_EOS this iteration, unless out_len is zero
72 state_ = ST_COMPLETE;
73 } else if (result == SR_ERROR) {
74 state_ = ST_ERROR;
75 error_ = -1; // TODO: propagate error
76 break;
77 } else if ((out_len == 0) && (state_ == ST_FLUSHING)) {
78 // If there is no output AND no more input, then something is wrong
79 state_ = ST_ERROR;
80 error_ = -1; // TODO: better error code?
81 break;
82 }
83
84 len_ -= in_len;
85 if (len_ > 0)
86 memmove(buffer_, buffer_ + in_len, len_);
87
88 if (out_len == 0)
89 continue;
90
91 if (read)
92 *read = out_len;
93 return SR_SUCCESS;
94 }
95
96 if (error)
97 *error = error_;
98 return SR_ERROR;
99 }
100
101 StreamResult
Write(const void * data,size_t data_len,size_t * written,int * error)102 TransformAdapter::Write(const void * data, size_t data_len,
103 size_t * written, int * error) {
104 if (direction_read_)
105 return SR_EOS;
106
107 size_t bytes_written = 0;
108 while (state_ != ST_ERROR) {
109 if (state_ == ST_COMPLETE)
110 return SR_EOS;
111
112 if (len_ < sizeof(buffer_)) {
113 // Process buffered data
114 size_t in_len = data_len;
115 size_t out_len = sizeof(buffer_) - len_;
116 StreamResult result = transform_->Transform(data, &in_len,
117 buffer_ + len_, &out_len,
118 (state_ == ST_FLUSHING));
119
120 ASSERT(result != SR_BLOCK);
121 if (result == SR_EOS) {
122 // Note: Don't signal SR_EOS this iteration, unless no data written
123 state_ = ST_COMPLETE;
124 } else if (result == SR_ERROR) {
125 ASSERT(false); // When this happens, think about what should be done
126 state_ = ST_ERROR;
127 error_ = -1; // TODO: propagate error
128 break;
129 }
130
131 len_ = out_len;
132 bytes_written = in_len;
133 }
134
135 size_t pos = 0;
136 while (pos < len_) {
137 size_t subwritten;
138 StreamResult result = StreamAdapterInterface::Write(buffer_ + pos,
139 len_ - pos,
140 &subwritten,
141 &error_);
142 if (result == SR_BLOCK) {
143 ASSERT(false); // TODO: we should handle this
144 return SR_BLOCK;
145 } else if (result == SR_ERROR) {
146 state_ = ST_ERROR;
147 break;
148 } else if (result == SR_EOS) {
149 state_ = ST_COMPLETE;
150 break;
151 }
152
153 pos += subwritten;
154 }
155
156 len_ -= pos;
157 if (len_ > 0)
158 memmove(buffer_, buffer_ + pos, len_);
159
160 if (bytes_written == 0)
161 continue;
162
163 if (written)
164 *written = bytes_written;
165 return SR_SUCCESS;
166 }
167
168 if (error)
169 *error = error_;
170 return SR_ERROR;
171 }
172
173 void
Close()174 TransformAdapter::Close() {
175 if (!direction_read_ && (state_ == ST_PROCESSING)) {
176 state_ = ST_FLUSHING;
177 do {
178 Write(0, 0, NULL, NULL);
179 } while (state_ == ST_FLUSHING);
180 }
181 state_ = ST_COMPLETE;
182 StreamAdapterInterface::Close();
183 }
184
GetAvailable(size_t * size) const185 bool TransformAdapter::GetAvailable(size_t* size) const {
186 return false;
187 }
188
ReserveSize(size_t size)189 bool TransformAdapter::ReserveSize(size_t size) {
190 return true;
191 }
192
Rewind()193 bool TransformAdapter::Rewind() {
194 return false;
195 }
196
197 } // namespace rtc
198