• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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