blob: 118556b17266b7cadaf1716048002eae638fc3d2 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000011#include "webrtc/modules/audio_coding/neteq/payload_splitter.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
13#include <assert.h>
14
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000015#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000016
17namespace webrtc {
18
19// The method loops through a list of packets {A, B, C, ...}. Each packet is
20// split into its corresponding RED payloads, {A1, A2, ...}, which is
21// temporarily held in the list |new_packets|.
22// When the first packet in |packet_list| has been processed, the orignal packet
23// is replaced by the new ones in |new_packets|, so that |packet_list| becomes:
24// {A1, A2, ..., B, C, ...}. The method then continues with B, and C, until all
25// the original packets have been replaced by their split payloads.
26int PayloadSplitter::SplitRed(PacketList* packet_list) {
27 int ret = kOK;
28 PacketList::iterator it = packet_list->begin();
29 while (it != packet_list->end()) {
30 PacketList new_packets; // An empty list to store the split packets in.
31 Packet* red_packet = (*it);
32 assert(red_packet->payload);
33 uint8_t* payload_ptr = red_packet->payload;
34
35 // Read RED headers (according to RFC 2198):
36 //
37 // 0 1 2 3
38 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
39 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 // |F| block PT | timestamp offset | block length |
41 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 // Last RED header:
43 // 0 1 2 3 4 5 6 7
44 // +-+-+-+-+-+-+-+-+
45 // |0| Block PT |
46 // +-+-+-+-+-+-+-+-+
47
48 bool last_block = false;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000049 size_t sum_length = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000050 while (!last_block) {
51 Packet* new_packet = new Packet;
52 new_packet->header = red_packet->header;
53 // Check the F bit. If F == 0, this was the last block.
54 last_block = ((*payload_ptr & 0x80) == 0);
55 // Bits 1 through 7 are payload type.
56 new_packet->header.payloadType = payload_ptr[0] & 0x7F;
57 if (last_block) {
58 // No more header data to read.
59 ++sum_length; // Account for RED header size of 1 byte.
60 new_packet->payload_length = red_packet->payload_length - sum_length;
61 new_packet->primary = true; // Last block is always primary.
62 payload_ptr += 1; // Advance to first payload byte.
63 } else {
64 // Bits 8 through 21 are timestamp offset.
65 int timestamp_offset = (payload_ptr[1] << 6) +
66 ((payload_ptr[2] & 0xFC) >> 2);
67 new_packet->header.timestamp = red_packet->header.timestamp -
68 timestamp_offset;
69 // Bits 22 through 31 are payload length.
70 new_packet->payload_length = ((payload_ptr[2] & 0x03) << 8) +
71 payload_ptr[3];
72 new_packet->primary = false;
73 payload_ptr += 4; // Advance to next RED header.
74 }
75 sum_length += new_packet->payload_length;
76 sum_length += 4; // Account for RED header size of 4 bytes.
77 // Store in new list of packets.
78 new_packets.push_back(new_packet);
79 }
80
81 // Populate the new packets with payload data.
82 // |payload_ptr| now points at the first payload byte.
83 PacketList::iterator new_it;
84 for (new_it = new_packets.begin(); new_it != new_packets.end(); ++new_it) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000085 size_t payload_length = (*new_it)->payload_length;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000086 if (payload_ptr + payload_length >
87 red_packet->payload + red_packet->payload_length) {
88 // The block lengths in the RED headers do not match the overall packet
89 // length. Something is corrupt. Discard this and the remaining
90 // payloads from this packet.
91 while (new_it != new_packets.end()) {
92 // Payload should not have been allocated yet.
93 assert(!(*new_it)->payload);
94 delete (*new_it);
95 new_it = new_packets.erase(new_it);
96 }
97 ret = kRedLengthMismatch;
98 break;
99 }
100 (*new_it)->payload = new uint8_t[payload_length];
101 memcpy((*new_it)->payload, payload_ptr, payload_length);
102 payload_ptr += payload_length;
103 }
104 // Reverse the order of the new packets, so that the primary payload is
105 // always first.
106 new_packets.reverse();
107 // Insert new packets into original list, before the element pointed to by
108 // iterator |it|.
109 packet_list->splice(it, new_packets, new_packets.begin(),
110 new_packets.end());
111 // Delete old packet payload.
112 delete [] (*it)->payload;
113 delete (*it);
114 // Remove |it| from the packet list. This operation effectively moves the
115 // iterator |it| to the next packet in the list. Thus, we do not have to
116 // increment it manually.
117 it = packet_list->erase(it);
118 }
119 return ret;
120}
121
minyue@webrtc.orgb28bfa72014-03-21 12:07:40 +0000122int PayloadSplitter::SplitFec(PacketList* packet_list,
123 DecoderDatabase* decoder_database) {
124 PacketList::iterator it = packet_list->begin();
125 // Iterate through all packets in |packet_list|.
126 while (it != packet_list->end()) {
127 Packet* packet = (*it); // Just to make the notation more intuitive.
128 // Get codec type for this payload.
129 uint8_t payload_type = packet->header.payloadType;
130 const DecoderDatabase::DecoderInfo* info =
131 decoder_database->GetDecoderInfo(payload_type);
132 if (!info) {
133 return kUnknownPayloadType;
134 }
135 // No splitting for a sync-packet.
136 if (packet->sync_packet) {
137 ++it;
138 continue;
139 }
140
141 // Not an FEC packet.
142 AudioDecoder* decoder = decoder_database->GetDecoder(payload_type);
minyue@webrtc.org7549ff42014-04-02 15:03:01 +0000143 // decoder should not return NULL.
144 assert(decoder != NULL);
145 if (!decoder ||
146 !decoder->PacketHasFec(packet->payload, packet->payload_length)) {
minyue@webrtc.orgb28bfa72014-03-21 12:07:40 +0000147 ++it;
148 continue;
149 }
150
151 switch (info->codec_type) {
152 case kDecoderOpus:
153 case kDecoderOpus_2ch: {
154 Packet* new_packet = new Packet;
155
156 new_packet->header = packet->header;
157 int duration = decoder->
minyue@webrtc.org7549ff42014-04-02 15:03:01 +0000158 PacketDurationRedundant(packet->payload, packet->payload_length);
minyue@webrtc.orgb28bfa72014-03-21 12:07:40 +0000159 new_packet->header.timestamp -= duration;
160 new_packet->payload = new uint8_t[packet->payload_length];
161 memcpy(new_packet->payload, packet->payload, packet->payload_length);
162 new_packet->payload_length = packet->payload_length;
163 new_packet->primary = false;
164 new_packet->waiting_time = packet->waiting_time;
165 new_packet->sync_packet = packet->sync_packet;
166
167 packet_list->insert(it, new_packet);
168 break;
169 }
170 default: {
171 return kFecSplitError;
172 }
173 }
174
175 ++it;
176 }
177 return kOK;
178}
179
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000180int PayloadSplitter::CheckRedPayloads(PacketList* packet_list,
181 const DecoderDatabase& decoder_database) {
182 PacketList::iterator it = packet_list->begin();
183 int main_payload_type = -1;
184 int num_deleted_packets = 0;
185 while (it != packet_list->end()) {
186 uint8_t this_payload_type = (*it)->header.payloadType;
187 if (!decoder_database.IsDtmf(this_payload_type) &&
188 !decoder_database.IsComfortNoise(this_payload_type)) {
189 if (main_payload_type == -1) {
190 // This is the first packet in the list which is non-DTMF non-CNG.
191 main_payload_type = this_payload_type;
192 } else {
193 if (this_payload_type != main_payload_type) {
194 // We do not allow redundant payloads of a different type.
195 // Discard this payload.
196 delete [] (*it)->payload;
197 delete (*it);
198 // Remove |it| from the packet list. This operation effectively
199 // moves the iterator |it| to the next packet in the list. Thus, we
200 // do not have to increment it manually.
201 it = packet_list->erase(it);
202 ++num_deleted_packets;
203 continue;
204 }
205 }
206 }
207 ++it;
208 }
209 return num_deleted_packets;
210}
211
212int PayloadSplitter::SplitAudio(PacketList* packet_list,
213 const DecoderDatabase& decoder_database) {
214 PacketList::iterator it = packet_list->begin();
215 // Iterate through all packets in |packet_list|.
216 while (it != packet_list->end()) {
217 Packet* packet = (*it); // Just to make the notation more intuitive.
218 // Get codec type for this payload.
219 const DecoderDatabase::DecoderInfo* info =
220 decoder_database.GetDecoderInfo(packet->header.payloadType);
221 if (!info) {
222 return kUnknownPayloadType;
223 }
turaj@webrtc.org7b75ac62013-09-26 00:27:56 +0000224 // No splitting for a sync-packet.
225 if (packet->sync_packet) {
226 ++it;
227 continue;
228 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000229 PacketList new_packets;
230 switch (info->codec_type) {
231 case kDecoderPCMu:
232 case kDecoderPCMa: {
233 // 8 bytes per ms; 8 timestamps per ms.
234 SplitBySamples(packet, 8, 8, &new_packets);
235 break;
236 }
237 case kDecoderPCMu_2ch:
238 case kDecoderPCMa_2ch: {
239 // 2 * 8 bytes per ms; 8 timestamps per ms.
240 SplitBySamples(packet, 2 * 8, 8, &new_packets);
241 break;
242 }
243 case kDecoderG722: {
244 // 8 bytes per ms; 16 timestamps per ms.
245 SplitBySamples(packet, 8, 16, &new_packets);
246 break;
247 }
248 case kDecoderPCM16B: {
249 // 16 bytes per ms; 8 timestamps per ms.
250 SplitBySamples(packet, 16, 8, &new_packets);
251 break;
252 }
253 case kDecoderPCM16Bwb: {
254 // 32 bytes per ms; 16 timestamps per ms.
255 SplitBySamples(packet, 32, 16, &new_packets);
256 break;
257 }
258 case kDecoderPCM16Bswb32kHz: {
259 // 64 bytes per ms; 32 timestamps per ms.
260 SplitBySamples(packet, 64, 32, &new_packets);
261 break;
262 }
263 case kDecoderPCM16Bswb48kHz: {
264 // 96 bytes per ms; 48 timestamps per ms.
265 SplitBySamples(packet, 96, 48, &new_packets);
266 break;
267 }
268 case kDecoderPCM16B_2ch: {
269 // 2 * 16 bytes per ms; 8 timestamps per ms.
270 SplitBySamples(packet, 2 * 16, 8, &new_packets);
271 break;
272 }
273 case kDecoderPCM16Bwb_2ch: {
274 // 2 * 32 bytes per ms; 16 timestamps per ms.
275 SplitBySamples(packet, 2 * 32, 16, &new_packets);
276 break;
277 }
278 case kDecoderPCM16Bswb32kHz_2ch: {
279 // 2 * 64 bytes per ms; 32 timestamps per ms.
280 SplitBySamples(packet, 2 * 64, 32, &new_packets);
281 break;
282 }
283 case kDecoderPCM16Bswb48kHz_2ch: {
284 // 2 * 96 bytes per ms; 48 timestamps per ms.
285 SplitBySamples(packet, 2 * 96, 48, &new_packets);
286 break;
287 }
288 case kDecoderPCM16B_5ch: {
289 // 5 * 16 bytes per ms; 8 timestamps per ms.
290 SplitBySamples(packet, 5 * 16, 8, &new_packets);
291 break;
292 }
293 case kDecoderILBC: {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000294 size_t bytes_per_frame;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000295 int timestamps_per_frame;
296 if (packet->payload_length >= 950) {
297 return kTooLargePayload;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000298 }
299 if (packet->payload_length % 38 == 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000300 // 20 ms frames.
301 bytes_per_frame = 38;
302 timestamps_per_frame = 160;
303 } else if (packet->payload_length % 50 == 0) {
304 // 30 ms frames.
305 bytes_per_frame = 50;
306 timestamps_per_frame = 240;
307 } else {
308 return kFrameSplitError;
309 }
310 int ret = SplitByFrames(packet, bytes_per_frame, timestamps_per_frame,
311 &new_packets);
312 if (ret < 0) {
313 return ret;
314 } else if (ret == kNoSplit) {
315 // Do not split at all. Simply advance to the next packet in the list.
316 ++it;
317 // We do not have any new packets to insert, and should not delete the
318 // old one. Skip the code after the switch case, and jump straight to
319 // the next packet in the while loop.
320 continue;
321 }
322 break;
323 }
324 default: {
325 // Do not split at all. Simply advance to the next packet in the list.
326 ++it;
327 // We do not have any new packets to insert, and should not delete the
328 // old one. Skip the code after the switch case, and jump straight to
329 // the next packet in the while loop.
330 continue;
331 }
332 }
333 // Insert new packets into original list, before the element pointed to by
334 // iterator |it|.
335 packet_list->splice(it, new_packets, new_packets.begin(),
336 new_packets.end());
337 // Delete old packet payload.
338 delete [] (*it)->payload;
339 delete (*it);
340 // Remove |it| from the packet list. This operation effectively moves the
341 // iterator |it| to the next packet in the list. Thus, we do not have to
342 // increment it manually.
343 it = packet_list->erase(it);
344 }
minyue@webrtc.orgb28bfa72014-03-21 12:07:40 +0000345 return kOK;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000346}
347
348void PayloadSplitter::SplitBySamples(const Packet* packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000349 size_t bytes_per_ms,
350 uint32_t timestamps_per_ms,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000351 PacketList* new_packets) {
352 assert(packet);
353 assert(new_packets);
354
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000355 size_t split_size_bytes = packet->payload_length;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000356
357 // Find a "chunk size" >= 20 ms and < 40 ms.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000358 size_t min_chunk_size = bytes_per_ms * 20;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000359 // Reduce the split size by half as long as |split_size_bytes| is at least
360 // twice the minimum chunk size (so that the resulting size is at least as
361 // large as the minimum chunk size).
362 while (split_size_bytes >= 2 * min_chunk_size) {
363 split_size_bytes >>= 1;
364 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000365 uint32_t timestamps_per_chunk = static_cast<uint32_t>(
366 split_size_bytes * timestamps_per_ms / bytes_per_ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000367 uint32_t timestamp = packet->header.timestamp;
368
369 uint8_t* payload_ptr = packet->payload;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000370 size_t len = packet->payload_length;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000371 while (len >= (2 * split_size_bytes)) {
372 Packet* new_packet = new Packet;
373 new_packet->payload_length = split_size_bytes;
374 new_packet->header = packet->header;
375 new_packet->header.timestamp = timestamp;
376 timestamp += timestamps_per_chunk;
377 new_packet->primary = packet->primary;
378 new_packet->payload = new uint8_t[split_size_bytes];
379 memcpy(new_packet->payload, payload_ptr, split_size_bytes);
380 payload_ptr += split_size_bytes;
381 new_packets->push_back(new_packet);
382 len -= split_size_bytes;
383 }
384
385 if (len > 0) {
386 Packet* new_packet = new Packet;
387 new_packet->payload_length = len;
388 new_packet->header = packet->header;
389 new_packet->header.timestamp = timestamp;
390 new_packet->primary = packet->primary;
391 new_packet->payload = new uint8_t[len];
392 memcpy(new_packet->payload, payload_ptr, len);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000393 new_packets->push_back(new_packet);
394 }
395}
396
397int PayloadSplitter::SplitByFrames(const Packet* packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000398 size_t bytes_per_frame,
399 uint32_t timestamps_per_frame,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000400 PacketList* new_packets) {
401 if (packet->payload_length % bytes_per_frame != 0) {
402 return kFrameSplitError;
403 }
404
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000405 if (packet->payload_length == bytes_per_frame) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000406 // Special case. Do not split the payload.
407 return kNoSplit;
408 }
409
410 uint32_t timestamp = packet->header.timestamp;
411 uint8_t* payload_ptr = packet->payload;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000412 size_t len = packet->payload_length;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000413 while (len > 0) {
414 assert(len >= bytes_per_frame);
415 Packet* new_packet = new Packet;
416 new_packet->payload_length = bytes_per_frame;
417 new_packet->header = packet->header;
418 new_packet->header.timestamp = timestamp;
419 timestamp += timestamps_per_frame;
420 new_packet->primary = packet->primary;
421 new_packet->payload = new uint8_t[bytes_per_frame];
422 memcpy(new_packet->payload, payload_ptr, bytes_per_frame);
423 payload_ptr += bytes_per_frame;
424 new_packets->push_back(new_packet);
425 len -= bytes_per_frame;
426 }
427 return kOK;
428}
429
430} // namespace webrtc