blob: 943a5b967279fcac03eb72774923fceed34b6bc9 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/transformadapter.h"
nisse8e7577c2016-10-06 01:37:37 -070012
13#include <string.h>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/checks.h"
nisse8e7577c2016-10-06 01:37:37 -070016
17namespace rtc {
18
19///////////////////////////////////////////////////////////////////////////////
20
21TransformAdapter::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
28TransformAdapter::~TransformAdapter() {
29 TransformAdapter::Close();
30 delete transform_;
31}
32
33StreamResult
34TransformAdapter::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));
nisseede5da42017-01-12 05:15:36 -080069 RTC_DCHECK(result != SR_BLOCK);
nisse8e7577c2016-10-06 01:37:37 -070070 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
101StreamResult
102TransformAdapter::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
nisseede5da42017-01-12 05:15:36 -0800120 RTC_DCHECK(result != SR_BLOCK);
nisse8e7577c2016-10-06 01:37:37 -0700121 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) {
nissec80e7412017-01-11 05:56:46 -0800125 RTC_NOTREACHED(); // When this happens, think about what should be done
nisse8e7577c2016-10-06 01:37:37 -0700126 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) {
nissec80e7412017-01-11 05:56:46 -0800143 RTC_NOTREACHED(); // We should handle this
nisse8e7577c2016-10-06 01:37:37 -0700144 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
173void
174TransformAdapter::Close() {
175 if (!direction_read_ && (state_ == ST_PROCESSING)) {
176 state_ = ST_FLUSHING;
177 do {
deadbeef37f5ecf2017-02-27 14:06:41 -0800178 Write(0, 0, nullptr, nullptr);
nisse8e7577c2016-10-06 01:37:37 -0700179 } while (state_ == ST_FLUSHING);
180 }
181 state_ = ST_COMPLETE;
182 StreamAdapterInterface::Close();
183}
184
185bool TransformAdapter::GetAvailable(size_t* size) const {
186 return false;
187}
188
189bool TransformAdapter::ReserveSize(size_t size) {
190 return true;
191}
192
193bool TransformAdapter::Rewind() {
194 return false;
195}
196
197} // namespace rtc