Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
Loading...
Searching...
No Matches
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"
18#include "roc_fec/headers.h"
20
21namespace roc {
22namespace fec {
23
24//! FECFRAME packet composer.
25template <class PayloadID, PayloadID_Type Type, PayloadID_Pos Pos>
27public:
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(
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
168private:
169 packet::IComposer* inner_composer_;
170};
171
172} // namespace fec
173} // namespace roc
174
175#endif // ROC_FEC_COMPOSER_H_
Alignment.
Base class for non-copyable objects.
Definition: noncopyable.h:23
Slice.
Definition: slice.h:23
void resize(size_t new_size)
Change slice size, up to the available capacity.
Definition: slice.h:83
size_t capacity() const
Get maximum possible number of elements in slice.
Definition: slice.h:74
Slice range(size_t from, size_t to) const
Construct a slice pointing to a part of this slice.
Definition: slice.h:93
T * data() const
Get slice data.
Definition: slice.h:61
size_t size() const
Get number of elements in slice.
Definition: slice.h:69
FECFRAME packet composer.
Definition: composer.h:26
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
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:69
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.
@ FlagRepair
Packet contains repair FEC symbols.
Definition: packet.h:46
@ FlagFEC
Packet contains FEC header.
Definition: packet.h:44
const FEC * fec() const
FEC packet.
void add_flags(unsigned flags)
Add flags.
Packet composer interface.
Logging.
#define roc_log(...)
Print message to log.
Definition: log.h:25
size_t padding(size_t size, size_t alignment)
Calculate padding required for given alignment.
Definition: alignment.h:36
@ 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:35
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:42
FECFRAME headers.
FECFRAME packet.
Definition: fec.h:35
core::Slice< uint8_t > payload
FECFRAME payload.
Definition: fec.h:79
size_t encoding_symbol_id
The index number of packet in a block.
Definition: fec.h:49
size_t source_block_length
Number of source packets in the block to which this packet belongs to.
Definition: fec.h:63
FECScheme fec_scheme
The FEC scheme to which the packet belongs to.
Definition: fec.h:40
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
core::Slice< uint8_t > payload_id
FECFRAME header or footer.
Definition: fec.h:74