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