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 Streaming 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/align_ops.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::AlignOps::pad_as(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.reslice(padding, padding);
59  return true;
60  } else {
61  return inner_composer_->align(buffer, header_size, payload_alignment);
62  }
63  }
64 
65  //! Prepare buffer for composing a packet.
66  virtual bool
67  prepare(packet::Packet& packet, core::Slice<uint8_t>& buffer, size_t payload_size) {
68  core::Slice<uint8_t> payload_id = buffer.subslice(0, 0);
69 
70  if (Pos == Header) {
71  if (payload_id.capacity() < sizeof(PayloadID)) {
73  "fec composer: not enough space for fec header: size=%lu cap=%lu",
74  (unsigned long)sizeof(PayloadID),
75  (unsigned long)payload_id.capacity());
76  return false;
77  }
78  payload_id.reslice(0, sizeof(PayloadID));
79  }
80 
81  core::Slice<uint8_t> payload =
82  payload_id.subslice(payload_id.size(), payload_id.size());
83 
84  if (inner_composer_) {
85  if (!inner_composer_->prepare(packet, payload, payload_size)) {
86  return false;
87  }
88  } else {
89  payload.reslice(0, payload_size);
90  }
91 
92  if (Pos == Footer) {
93  payload_id = payload.subslice(payload.size(), payload.size());
94 
95  if (payload_id.capacity() < sizeof(PayloadID)) {
97  "fec composer: not enough space for fec header: size=%lu cap=%lu",
98  (unsigned long)sizeof(PayloadID),
99  (unsigned long)payload_id.capacity());
100  return false;
101  }
102  payload_id.reslice(0, sizeof(PayloadID));
103  }
104 
105  if (Type == Repair) {
107  }
108 
110 
111  packet::FEC& fec = *packet.fec();
112 
113  fec.fec_scheme = PayloadID::fec_scheme();
114  fec.payload_id = payload_id;
115  fec.payload = payload;
116 
117  buffer.reslice(0, payload_id.size() + payload.size());
118 
119  return true;
120  }
121 
122  //! Pad packet.
123  virtual bool pad(packet::Packet& packet, size_t padding_size) {
124  if (inner_composer_) {
125  return inner_composer_->pad(packet, padding_size);
126  }
127 
128  // padding not supported
129  return false;
130  }
131 
132  //! Compose packet to buffer.
133  virtual bool compose(packet::Packet& packet) {
134  if (!packet.fec()) {
135  roc_panic("fec composer: unexpected non-fec packet");
136  }
137 
138  if (packet.fec()->payload_id.size() != sizeof(PayloadID)) {
139  roc_panic("fec composer: unexpected payload id size");
140  }
141 
142  packet::FEC& fec = *packet.fec();
143 
144  PayloadID& payload_id = *(PayloadID*)fec.payload_id.data();
145 
146  payload_id.clear();
147 
148  roc_panic_if((fec.encoding_symbol_id >> 16) != 0);
149  payload_id.set_esi((uint16_t)fec.encoding_symbol_id);
150 
151  payload_id.set_sbn(fec.source_block_number);
152 
153  roc_panic_if((fec.source_block_length >> 16) != 0);
154  payload_id.set_k((uint16_t)fec.source_block_length);
155 
156  roc_panic_if((fec.block_length >> 16) != 0);
157  payload_id.set_n((uint16_t)fec.block_length);
158 
159  if (inner_composer_) {
160  return inner_composer_->compose(packet);
161  }
162 
163  return true;
164  }
165 
166 private:
167  packet::IComposer* inner_composer_;
168 };
169 
170 } // namespace fec
171 } // namespace roc
172 
173 #endif // ROC_FEC_COMPOSER_H_
Alignment operations.
static size_t pad_as(size_t size, size_t alignment)
Return padding needed for given alignment.
Base class for non-copyable objects.
Definition: noncopyable.h:23
Slice subslice(size_t from, size_t to) const
Construct a slice pointing to a part of this slice.
Definition: slice.h:161
size_t capacity() const
Get maximum possible number of elements in slice.
Definition: slice.h:113
T * data() const
Get slice data.
Definition: slice.h:92
void reslice(size_t from, size_t to)
Change slice beginning and ending inside the buffer.
Definition: slice.h:125
size_t size() const
Get number of elements in slice.
Definition: slice.h:108
FECFRAME packet composer.
Definition: composer.h:26
virtual bool pad(packet::Packet &packet, size_t padding_size)
Pad packet.
Definition: composer.h:123
virtual bool compose(packet::Packet &packet)
Compose packet to buffer.
Definition: composer.h:133
Composer(packet::IComposer *inner_composer)
Initialization.
Definition: composer.h:32
virtual bool prepare(packet::Packet &packet, core::Slice< uint8_t > &buffer, size_t payload_size)
Prepare buffer for composing a packet.
Definition: composer.h:67
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
Packet composer interface.
Definition: icomposer.h:22
virtual bool align(core::Slice< uint8_t > &buffer, size_t header_size, size_t payload_alignment)=0
Adjust buffer to align payload.
virtual bool pad(Packet &packet, size_t padding_size)=0
Pad packet.
virtual bool prepare(Packet &packet, core::Slice< uint8_t > &buffer, size_t payload_size)=0
Prepare buffer for composing a packet.
virtual bool compose(Packet &packet)=0
Compose packet to buffer.
const FEC * fec() const
FEC packet.
@ FlagRepair
Packet contains repair FEC symbols.
Definition: packet.h:50
@ FlagFEC
Packet contains FEC header.
Definition: packet.h:47
void add_flags(unsigned flags)
Add flags.
Packet composer interface.
Logging.
#define roc_log(level,...)
Print message to log.
Definition: log.h:31
@ Header
PayloadID comes before payload.
Definition: headers.h:32
@ Footer
PayloadID comes after payload.
Definition: headers.h:33
@ Repair
Source packet header of footer.
Definition: headers.h:27
Root namespace.
@ LogDebug
Debug message.
Definition: log.h:47
Non-copyable object.
#define roc_panic_if(x)
Panic if condition is true.
Definition: panic.h:26
#define roc_panic(...)
Print error message and terminate program gracefully.
Definition: panic.h:50
FECFRAME headers.
FECFRAME packet.
Definition: fec.h:35
core::Slice< uint8_t > payload
FECFRAME payload.
Definition: fec.h:74
size_t encoding_symbol_id
The index number of packet in a block ("esi").
Definition: fec.h:47
size_t source_block_length
Number of source packets in block to which this packet belongs ("sblen").
Definition: fec.h:59
FecScheme fec_scheme
The FEC scheme to which the packet belongs to.
Definition: fec.h:39
size_t block_length
Number of source + repair packets in block to which this packet belongs ("blen").
Definition: fec.h:66
blknum_t source_block_number
Number of a source block in a packet stream ("sbn").
Definition: fec.h:54
core::Slice< uint8_t > payload_id
FECFRAME header or footer.
Definition: fec.h:69