1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// CompoundBuffer implements a data buffer that is composed of several pieces,
6// each stored in a refcounted IOBuffer. It is needed for encoding/decoding
7// video pipeline to represent data packet and minimize data copying.
8// It is particularly useful for splitting data between multiple RTP packets
9// and assembling them into one buffer on the receiving side.
10//
11// CompoundBufferInputStream implements ZeroCopyInputStream interface
12// to be used by protobuf to decode data stored in CompoundBuffer into
13// a protocol buffer message.
14//
15// Mutations to the buffer are not thread-safe. Immutability can be ensured
16// with the Lock() method.
17
18#ifndef REMOTING_BASE_COMPOUND_BUFFER_H_
19#define REMOTING_BASE_COMPOUND_BUFFER_H_
20
21#include <deque>
22
23#include "base/basictypes.h"
24#include "base/memory/ref_counted.h"
25#include "google/protobuf/io/zero_copy_stream.h"
26
27namespace net {
28class IOBuffer;
29class IOBufferWithSize;
30}  // namespace net
31
32namespace remoting {
33
34class CompoundBuffer {
35 public:
36  CompoundBuffer();
37  ~CompoundBuffer();
38
39  void Clear();
40
41  // Adds new chunk to the buffer. |start| defines position of the chunk
42  // within the |buffer|. |size| is the size of the chunk that is being
43  // added, not size of the |buffer|.
44  void Append(net::IOBuffer* buffer, int size);
45  void Append(net::IOBuffer* buffer, const char* start, int size);
46  void Append(const CompoundBuffer& buffer);
47  void Prepend(net::IOBuffer* buffer, int size);
48  void Prepend(net::IOBuffer* buffer, const char* start, int size);
49  void Prepend(const CompoundBuffer& buffer);
50
51  // Same as above, but creates new IOBuffer and copies the data.
52  void AppendCopyOf(const char* data, int data_size);
53  void PrependCopyOf(const char* data, int data_size);
54
55  // Drop |bytes| bytes from the beginning or the end of the buffer.
56  void CropFront(int bytes);
57  void CropBack(int bytes);
58
59  // Current size of the buffer.
60  int total_bytes() const { return total_bytes_; }
61
62  // Locks the buffer. After the buffer is locked, no data can be
63  // added or removed (content can still be changed if some other
64  // object holds reference to the IOBuffer objects).
65  void Lock();
66
67  // Returns true if content is locked.
68  bool locked() const { return locked_; }
69
70  // Creates new IOBufferWithSize object and copies all data into it.
71  // Ownership of the result is given to the caller.
72  net::IOBufferWithSize* ToIOBufferWithSize() const;
73
74  // Copies all data into given location.
75  void CopyTo(char* data, int data_size) const;
76
77  // Clears the buffer, and initializes it with the interval from |buffer|
78  // starting at |start| and ending at |end|. The data itself isn't copied.
79  void CopyFrom(const CompoundBuffer& source, int start, int end);
80
81 private:
82  friend class CompoundBufferInputStream;
83
84  struct DataChunk {
85    DataChunk(net::IOBuffer* buffer, const char* start, int size);
86    ~DataChunk();
87
88    scoped_refptr<net::IOBuffer> buffer;
89    const char* start;
90    int size;
91  };
92  typedef std::deque<DataChunk> DataChunkList;
93
94  DataChunkList chunks_;
95  int total_bytes_;
96  bool locked_;
97
98  DISALLOW_COPY_AND_ASSIGN(CompoundBuffer);
99};
100
101class CompoundBufferInputStream
102    : public google::protobuf::io::ZeroCopyInputStream  {
103 public:
104  // Caller keeps ownership of |buffer|. |buffer| must be locked.
105  explicit CompoundBufferInputStream(const CompoundBuffer* buffer);
106  virtual ~CompoundBufferInputStream();
107
108  int position() const { return position_; }
109
110  // google::protobuf::io::ZeroCopyInputStream interface.
111  virtual bool Next(const void** data, int* size) OVERRIDE;
112  virtual void BackUp(int count) OVERRIDE;
113  virtual bool Skip(int count) OVERRIDE;
114  virtual int64 ByteCount() const OVERRIDE;
115
116 private:
117  const CompoundBuffer* buffer_;
118
119  size_t current_chunk_;
120  int current_chunk_position_;
121  int position_;
122  int last_returned_size_;
123};
124
125}  // namespace remoting
126
127#endif  // REMOTING_BASE_COMPOUND_BUFFER_H_
128