Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
composer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Roc authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_fec/composer.h
10 //! @brief FECFRAME packet composer.
11 
12 #ifndef ROC_FEC_COMPOSER_H_
13 #define ROC_FEC_COMPOSER_H_
14 
15 #include "roc_core/alignment.h"
16 #include "roc_core/log.h"
17 #include "roc_core/noncopyable.h"
18 #include "roc_fec/headers.h"
19 #include "roc_packet/icomposer.h"
20 
21 namespace roc {
22 namespace fec {
23 
24 //! FECFRAME packet composer.
25 template <class PayloadID, PayloadID_Type Type, PayloadID_Pos Pos>
26 class Composer : public packet::IComposer, public core::NonCopyable<> {
27 public:
28  //! Initialization.
29  //! @remarks
30  //! Composes FECFRAME header or footer and passes the rest to
31  //! @p inner_composer if it's not null.
32  Composer(packet::IComposer* inner_composer)
33  : inner_composer_(inner_composer) {
34  }
35 
36  //! Adjust buffer to align payload.
37  virtual bool
38  align(core::Slice<uint8_t>& buffer, size_t header_size, size_t payload_alignment) {
39  if ((unsigned long)buffer.data() % payload_alignment != 0) {
40  roc_panic("fec composer: unexpected non-aligned buffer");
41  }
42 
43  if (Pos == Header) {
44  header_size += sizeof(PayloadID);
45  }
46 
47  if (inner_composer_ == NULL) {
48  const size_t padding = core::padding(header_size, payload_alignment);
49 
50  if (buffer.capacity() < padding) {
51  roc_log(
52  LogDebug,
53  "fec composer: not enough space for alignment: padding=%lu cap=%lu",
54  (unsigned long)padding, (unsigned long)buffer.capacity());
55  return false;
56  }
57 
58  buffer.resize(padding);
59  buffer = buffer.range(buffer.size(), buffer.size());
60 
61  return true;
62  } else {
63  return inner_composer_->align(buffer, header_size, payload_alignment);
64  }
65  }
66 
67  //! Prepare buffer for composing a packet.
68  virtual bool
69  prepare(packet::Packet& packet, core::Slice<uint8_t>& buffer, size_t payload_size) {
70  core::Slice<uint8_t> payload_id = buffer.range(0, 0);
71 
72  if (Pos == Header) {
73  if (payload_id.capacity() < sizeof(PayloadID)) {
75  "fec composer: not enough space for fec header: size=%lu cap=%lu",
76  (unsigned long)sizeof(PayloadID),
77  (unsigned long)payload_id.capacity());
78  return false;
79  }
80  payload_id.resize(sizeof(PayloadID));
81  }
82 
83  core::Slice<uint8_t> payload =
84  payload_id.range(payload_id.size(), payload_id.size());
85 
86  if (inner_composer_) {
87  if (!inner_composer_->prepare(packet, payload, payload_size)) {
88  return false;
89  }
90  } else {
91  payload.resize(payload_size);
92  }
93 
94  if (Pos == Footer) {
95  payload_id = payload.range(payload.size(), payload.size());
96 
97  if (payload_id.capacity() < sizeof(PayloadID)) {
99  "fec composer: not enough space for fec header: size=%lu cap=%lu",
100  (unsigned long)sizeof(PayloadID),
101  (unsigned long)payload_id.capacity());
102  return false;
103  }
104  payload_id.resize(sizeof(PayloadID));
105  }
106 
107  if (Type == Repair) {
109  }
110 
112 
113  packet::FEC& fec = *packet.fec();
114 
115  fec.fec_scheme = PayloadID::fec_scheme();
116  fec.payload_id = payload_id;
117  fec.payload = payload;
118 
119  buffer.resize(payload_id.size() + payload.size());
120 
121  return true;
122  }
123 
124  //! Pad packet.
125  virtual bool pad(packet::Packet& packet, size_t padding_size) {
126  if (inner_composer_) {
127  return inner_composer_->pad(packet, padding_size);
128  }
129 
130  // padding not supported
131  return false;
132  }
133 
134  //! Compose packet to buffer.
135  virtual bool compose(packet::Packet& packet) {
136  if (!packet.fec()) {
137  roc_panic("fec composer: unexpected non-fec packet");
138  }
139 
140  if (packet.fec()->payload_id.size() != sizeof(PayloadID)) {
141  roc_panic("fec composer: unexpected payload id size");
142  }
143 
144  packet::FEC& fec = *packet.fec();
145 
146  PayloadID& payload_id = *(PayloadID*)fec.payload_id.data();
147 
148  payload_id.clear();
149 
150  roc_panic_if((fec.encoding_symbol_id >> 16) != 0);
151  payload_id.set_esi((uint16_t)fec.encoding_symbol_id);
152 
153  payload_id.set_sbn(fec.source_block_number);
154 
155  roc_panic_if((fec.source_block_length >> 16) != 0);
156  payload_id.set_k((uint16_t)fec.source_block_length);
157 
158  roc_panic_if((fec.block_length >> 16) != 0);
159  payload_id.set_n((uint16_t)fec.block_length);
160 
161  if (inner_composer_) {
162  return inner_composer_->compose(packet);
163  }
164 
165  return true;
166  }
167 
168 private:
169  packet::IComposer* inner_composer_;
170 };
171 
172 } // namespace fec
173 } // namespace roc
174 
175 #endif // ROC_FEC_COMPOSER_H_
FECFRAME packet composer.
Definition: composer.h:26
Packet contains repair FEC symbols.
Definition: packet.h:46
Slice range(size_t from, size_t to) const
Construct a slice pointing to a part of this slice.
Definition: slice.h:93
Packet contains FEC header.
Definition: packet.h:44
Source packet header of footer.
Definition: headers.h:27
virtual bool compose(Packet &packet)=0
Compose packet to buffer.
#define roc_panic_if(x)
Panic if condition is true.
Definition: panic.h:26
virtual bool pad(Packet &packet, size_t padding_size)=0
Pad packet.
size_t padding(size_t size, size_t alignment)
Calculate padding required for given alignment.
Definition: alignment.h:36
void resize(size_t new_size)
Change slice size, up to the available capacity.
Definition: slice.h:83
Root namespace.
PayloadID comes before payload.
Definition: headers.h:32
size_t size() const
Get number of elements in slice.
Definition: slice.h:69
Alignment.
Composer(packet::IComposer *inner_composer)
Initialization.
Definition: composer.h:32
const FEC * fec() const
FEC packet.
FECFRAME packet.
Definition: fec.h:35
void add_flags(unsigned flags)
Add flags.
Packet composer interface.
Definition: icomposer.h:22
Packet composer interface.
size_t source_block_length
Number of source packets in the block to which this packet belongs to.
Definition: fec.h:63
#define roc_panic(...)
Print error message and terminate program gracefully.
Definition: panic.h:42
Base class for non-copyable objects.
Definition: noncopyable.h:23
Packet.
Definition: packet.h:35
virtual bool pad(packet::Packet &packet, size_t padding_size)
Pad packet.
Definition: composer.h:125
virtual bool compose(packet::Packet &packet)
Compose packet to buffer.
Definition: composer.h:135
T * data() const
Get slice data.
Definition: slice.h:61
#define roc_log(...)
Print message to log.
Definition: log.h:25
size_t encoding_symbol_id
The index number of packet in a block.
Definition: fec.h:49
FECScheme fec_scheme
The FEC scheme to which the packet belongs to.
Definition: fec.h:40
Debug message.
Definition: log.h:35
virtual bool prepare(Packet &packet, core::Slice< uint8_t > &buffer, size_t payload_size)=0
Prepare buffer for composing a packet.
core::Slice< uint8_t > payload_id
FECFRAME header or footer.
Definition: fec.h:74
core::Slice< uint8_t > payload
FECFRAME payload.
Definition: fec.h:79
Non-copyable object.
FECFRAME headers.
virtual bool align(core::Slice< uint8_t > &buffer, size_t header_size, size_t payload_alignment)=0
Adjust buffer to align payload.
PayloadID comes after payload.
Definition: headers.h:33
size_t capacity() const
Get maximum possible number of elements in slice.
Definition: slice.h:74
Logging.
virtual bool prepare(packet::Packet &packet, core::Slice< uint8_t > &buffer, size_t payload_size)
Prepare buffer for composing a packet.
Definition: composer.h:69
size_t block_length
Number of source packets and repair in the block to which this packet belongs to. ...
Definition: fec.h:71
blknum_t source_block_number
Number of a source block in a packet stream.
Definition: fec.h:57
virtual bool align(core::Slice< uint8_t > &buffer, size_t header_size, size_t payload_alignment)
Adjust buffer to align payload.
Definition: composer.h:38