147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/transformadapter.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <string.h>
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTransformAdapter::TransformAdapter(StreamInterface * stream,
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                   TransformInterface * transform,
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                   bool direction_read)
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : StreamAdapterInterface(stream), transform_(transform),
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      direction_read_(direction_read), state_(ST_PROCESSING), len_(0) {
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTransformAdapter::~TransformAdapter() {
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  TransformAdapter::Close();
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  delete transform_;
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamResult
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTransformAdapter::Read(void * buffer, size_t buffer_len,
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                       size_t * read, int * error) {
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!direction_read_)
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SR_EOS;
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (state_ != ST_ERROR) {
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (state_ == ST_COMPLETE)
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SR_EOS;
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Buffer more data
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((state_ == ST_PROCESSING) && (len_ < sizeof(buffer_))) {
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      size_t subread;
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      StreamResult result = StreamAdapterInterface::Read(
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              buffer_ + len_,
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              sizeof(buffer_) - len_,
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              &subread,
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              &error_);
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (result == SR_BLOCK) {
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return SR_BLOCK;
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (result == SR_ERROR) {
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        state_ = ST_ERROR;
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (result == SR_EOS) {
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        state_ = ST_FLUSHING;
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        len_ += subread;
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Process buffered data
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t in_len = len_;
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t out_len = buffer_len;
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    StreamResult result = transform_->Transform(buffer_, &in_len,
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                buffer, &out_len,
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                (state_ == ST_FLUSHING));
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(result != SR_BLOCK);
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (result == SR_EOS) {
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Note: Don't signal SR_EOS this iteration, unless out_len is zero
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = ST_COMPLETE;
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (result == SR_ERROR) {
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = ST_ERROR;
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      error_ = -1; // TODO: propagate error
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if ((out_len == 0) && (state_ == ST_FLUSHING)) {
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // If there is no output AND no more input, then something is wrong
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = ST_ERROR;
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      error_ = -1; // TODO: better error code?
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    len_ -= in_len;
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (len_ > 0)
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      memmove(buffer_, buffer_ + in_len, len_);
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (out_len == 0)
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      continue;
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (read)
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *read = out_len;
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SR_SUCCESS;
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (error)
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *error = error_;
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return SR_ERROR;
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamResult
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTransformAdapter::Write(const void * data, size_t data_len,
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        size_t * written, int * error) {
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (direction_read_)
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SR_EOS;
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t bytes_written = 0;
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (state_ != ST_ERROR) {
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (state_ == ST_COMPLETE)
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SR_EOS;
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (len_ < sizeof(buffer_)) {
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Process buffered data
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      size_t in_len = data_len;
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      size_t out_len = sizeof(buffer_) - len_;
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      StreamResult result = transform_->Transform(data, &in_len,
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                  buffer_ + len_, &out_len,
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                  (state_ == ST_FLUSHING));
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ASSERT(result != SR_BLOCK);
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (result == SR_EOS) {
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Note: Don't signal SR_EOS this iteration, unless no data written
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        state_ = ST_COMPLETE;
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (result == SR_ERROR) {
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASSERT(false); // When this happens, think about what should be done
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        state_ = ST_ERROR;
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        error_ = -1; // TODO: propagate error
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      len_ = out_len;
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bytes_written = in_len;
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t pos = 0;
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    while (pos < len_) {
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      size_t subwritten;
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      StreamResult result = StreamAdapterInterface::Write(buffer_ + pos,
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                          len_ - pos,
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                          &subwritten,
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                          &error_);
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (result == SR_BLOCK) {
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASSERT(false); // TODO: we should handle this
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return SR_BLOCK;
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (result == SR_ERROR) {
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        state_ = ST_ERROR;
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (result == SR_EOS) {
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        state_ = ST_COMPLETE;
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      pos += subwritten;
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    len_ -= pos;
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (len_ > 0)
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      memmove(buffer_, buffer_ + pos, len_);
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (bytes_written == 0)
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      continue;
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (written)
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *written = bytes_written;
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SR_SUCCESS;
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (error)
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *error = error_;
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return SR_ERROR;
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgTransformAdapter::Close() {
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!direction_read_ && (state_ == ST_PROCESSING)) {
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_ = ST_FLUSHING;
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    do {
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Write(0, 0, NULL, NULL);
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } while (state_ == ST_FLUSHING);
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = ST_COMPLETE;
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  StreamAdapterInterface::Close();
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc
186