blob: f140dab33416772f9e1e8ed5c608345e00111a9b [file] [log] [blame]
nisse8e7577c2016-10-06 01:37:37 -07001/*
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
nissec80e7412017-01-11 05:56:46 -080015#include "webrtc/base/checks.h"
nisse8e7577c2016-10-06 01:37:37 -070016#include "webrtc/base/common.h"
17
18namespace rtc {
19
20///////////////////////////////////////////////////////////////////////////////
21
22TransformAdapter::TransformAdapter(StreamInterface * stream,
23 TransformInterface * transform,
24 bool direction_read)
25 : StreamAdapterInterface(stream), transform_(transform),
26 direction_read_(direction_read), state_(ST_PROCESSING), len_(0) {
27}
28
29TransformAdapter::~TransformAdapter() {
30 TransformAdapter::Close();
31 delete transform_;
32}
33
34StreamResult
35TransformAdapter::Read(void * buffer, size_t buffer_len,
36 size_t * read, int * error) {
37 if (!direction_read_)
38 return SR_EOS;
39
40 while (state_ != ST_ERROR) {
41 if (state_ == ST_COMPLETE)
42 return SR_EOS;
43
44 // Buffer more data
45 if ((state_ == ST_PROCESSING) && (len_ < sizeof(buffer_))) {
46 size_t subread;
47 StreamResult result = StreamAdapterInterface::Read(
48 buffer_ + len_,
49 sizeof(buffer_) - len_,
50 &subread,
51 &error_);
52 if (result == SR_BLOCK) {
53 return SR_BLOCK;
54 } else if (result == SR_ERROR) {
55 state_ = ST_ERROR;
56 break;
57 } else if (result == SR_EOS) {
58 state_ = ST_FLUSHING;
59 } else {
60 len_ += subread;
61 }
62 }
63
64 // Process buffered data
65 size_t in_len = len_;
66 size_t out_len = buffer_len;
67 StreamResult result = transform_->Transform(buffer_, &in_len,
68 buffer, &out_len,
69 (state_ == ST_FLUSHING));
nisseede5da42017-01-12 05:15:36 -080070 RTC_DCHECK(result != SR_BLOCK);
nisse8e7577c2016-10-06 01:37:37 -070071 if (result == SR_EOS) {
72 // Note: Don't signal SR_EOS this iteration, unless out_len is zero
73 state_ = ST_COMPLETE;
74 } else if (result == SR_ERROR) {
75 state_ = ST_ERROR;
76 error_ = -1; // TODO: propagate error
77 break;
78 } else if ((out_len == 0) && (state_ == ST_FLUSHING)) {
79 // If there is no output AND no more input, then something is wrong
80 state_ = ST_ERROR;
81 error_ = -1; // TODO: better error code?
82 break;
83 }
84
85 len_ -= in_len;
86 if (len_ > 0)
87 memmove(buffer_, buffer_ + in_len, len_);
88
89 if (out_len == 0)
90 continue;
91
92 if (read)
93 *read = out_len;
94 return SR_SUCCESS;
95 }
96
97 if (error)
98 *error = error_;
99 return SR_ERROR;
100}
101
102StreamResult
103TransformAdapter::Write(const void * data, size_t data_len,
104 size_t * written, int * error) {
105 if (direction_read_)
106 return SR_EOS;
107
108 size_t bytes_written = 0;
109 while (state_ != ST_ERROR) {
110 if (state_ == ST_COMPLETE)
111 return SR_EOS;
112
113 if (len_ < sizeof(buffer_)) {
114 // Process buffered data
115 size_t in_len = data_len;
116 size_t out_len = sizeof(buffer_) - len_;
117 StreamResult result = transform_->Transform(data, &in_len,
118 buffer_ + len_, &out_len,
119 (state_ == ST_FLUSHING));
120
nisseede5da42017-01-12 05:15:36 -0800121 RTC_DCHECK(result != SR_BLOCK);
nisse8e7577c2016-10-06 01:37:37 -0700122 if (result == SR_EOS) {
123 // Note: Don't signal SR_EOS this iteration, unless no data written
124 state_ = ST_COMPLETE;
125 } else if (result == SR_ERROR) {
nissec80e7412017-01-11 05:56:46 -0800126 RTC_NOTREACHED(); // When this happens, think about what should be done
nisse8e7577c2016-10-06 01:37:37 -0700127 state_ = ST_ERROR;
128 error_ = -1; // TODO: propagate error
129 break;
130 }
131
132 len_ = out_len;
133 bytes_written = in_len;
134 }
135
136 size_t pos = 0;
137 while (pos < len_) {
138 size_t subwritten;
139 StreamResult result = StreamAdapterInterface::Write(buffer_ + pos,
140 len_ - pos,
141 &subwritten,
142 &error_);
143 if (result == SR_BLOCK) {
nissec80e7412017-01-11 05:56:46 -0800144 RTC_NOTREACHED(); // We should handle this
nisse8e7577c2016-10-06 01:37:37 -0700145 return SR_BLOCK;
146 } else if (result == SR_ERROR) {
147 state_ = ST_ERROR;
148 break;
149 } else if (result == SR_EOS) {
150 state_ = ST_COMPLETE;
151 break;
152 }
153
154 pos += subwritten;
155 }
156
157 len_ -= pos;
158 if (len_ > 0)
159 memmove(buffer_, buffer_ + pos, len_);
160
161 if (bytes_written == 0)
162 continue;
163
164 if (written)
165 *written = bytes_written;
166 return SR_SUCCESS;
167 }
168
169 if (error)
170 *error = error_;
171 return SR_ERROR;
172}
173
174void
175TransformAdapter::Close() {
176 if (!direction_read_ && (state_ == ST_PROCESSING)) {
177 state_ = ST_FLUSHING;
178 do {
179 Write(0, 0, NULL, NULL);
180 } while (state_ == ST_FLUSHING);
181 }
182 state_ = ST_COMPLETE;
183 StreamAdapterInterface::Close();
184}
185
186bool TransformAdapter::GetAvailable(size_t* size) const {
187 return false;
188}
189
190bool TransformAdapter::ReserveSize(size_t size) {
191 return true;
192}
193
194bool TransformAdapter::Rewind() {
195 return false;
196}
197
198} // namespace rtc