Home | History | Annotate | Download | only in base
      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 
     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 
     28 TransformAdapter::~TransformAdapter() {
     29   TransformAdapter::Close();
     30   delete transform_;
     31 }
     32 
     33 StreamResult
     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
    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
    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 
    185 bool TransformAdapter::GetAvailable(size_t* size) const {
    186   return false;
    187 }
    188 
    189 bool TransformAdapter::ReserveSize(size_t size) {
    190   return true;
    191 }
    192 
    193 bool TransformAdapter::Rewind() {
    194   return false;
    195 }
    196 
    197 } // namespace rtc
    198