Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: webrtc/modules/audio_coding/neteq/payload_splitter.cc

Issue 2326003002: Moved codec-specific audio packet splitting into decoders. (Closed)
Patch Set: Fixed types in packet splitting (size_t vs. uint32_t) Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 ++num_deleted_packets; 205 ++num_deleted_packets;
206 continue; 206 continue;
207 } 207 }
208 } 208 }
209 } 209 }
210 ++it; 210 ++it;
211 } 211 }
212 return num_deleted_packets; 212 return num_deleted_packets;
213 } 213 }
214 214
215 int PayloadSplitter::SplitAudio(PacketList* packet_list,
216 const DecoderDatabase& decoder_database) {
217 PacketList::iterator it = packet_list->begin();
218 // Iterate through all packets in |packet_list|.
219 while (it != packet_list->end()) {
220 Packet* packet = (*it); // Just to make the notation more intuitive.
221 // Get codec type for this payload.
222 const DecoderDatabase::DecoderInfo* info =
223 decoder_database.GetDecoderInfo(packet->header.payloadType);
224 if (!info) {
225 LOG(LS_WARNING) << "SplitAudio unknown payload type";
226 return kUnknownPayloadType;
227 }
228 PacketList new_packets;
229 switch (info->codec_type) {
230 case NetEqDecoder::kDecoderPCMu:
231 case NetEqDecoder::kDecoderPCMa: {
232 // 8 bytes per ms; 8 timestamps per ms.
233 SplitBySamples(packet, 8, 8, &new_packets);
234 break;
235 }
236 case NetEqDecoder::kDecoderPCMu_2ch:
237 case NetEqDecoder::kDecoderPCMa_2ch: {
238 // 2 * 8 bytes per ms; 8 timestamps per ms.
239 SplitBySamples(packet, 2 * 8, 8, &new_packets);
240 break;
241 }
242 case NetEqDecoder::kDecoderG722: {
243 // 8 bytes per ms; 16 timestamps per ms.
244 SplitBySamples(packet, 8, 16, &new_packets);
245 break;
246 }
247 case NetEqDecoder::kDecoderPCM16B: {
248 // 16 bytes per ms; 8 timestamps per ms.
249 SplitBySamples(packet, 16, 8, &new_packets);
250 break;
251 }
252 case NetEqDecoder::kDecoderPCM16Bwb: {
253 // 32 bytes per ms; 16 timestamps per ms.
254 SplitBySamples(packet, 32, 16, &new_packets);
255 break;
256 }
257 case NetEqDecoder::kDecoderPCM16Bswb32kHz: {
258 // 64 bytes per ms; 32 timestamps per ms.
259 SplitBySamples(packet, 64, 32, &new_packets);
260 break;
261 }
262 case NetEqDecoder::kDecoderPCM16Bswb48kHz: {
263 // 96 bytes per ms; 48 timestamps per ms.
264 SplitBySamples(packet, 96, 48, &new_packets);
265 break;
266 }
267 case NetEqDecoder::kDecoderPCM16B_2ch: {
268 // 2 * 16 bytes per ms; 8 timestamps per ms.
269 SplitBySamples(packet, 2 * 16, 8, &new_packets);
270 break;
271 }
272 case NetEqDecoder::kDecoderPCM16Bwb_2ch: {
273 // 2 * 32 bytes per ms; 16 timestamps per ms.
274 SplitBySamples(packet, 2 * 32, 16, &new_packets);
275 break;
276 }
277 case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch: {
278 // 2 * 64 bytes per ms; 32 timestamps per ms.
279 SplitBySamples(packet, 2 * 64, 32, &new_packets);
280 break;
281 }
282 case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch: {
283 // 2 * 96 bytes per ms; 48 timestamps per ms.
284 SplitBySamples(packet, 2 * 96, 48, &new_packets);
285 break;
286 }
287 case NetEqDecoder::kDecoderPCM16B_5ch: {
288 // 5 * 16 bytes per ms; 8 timestamps per ms.
289 SplitBySamples(packet, 5 * 16, 8, &new_packets);
290 break;
291 }
292 case NetEqDecoder::kDecoderILBC: {
293 size_t bytes_per_frame;
294 int timestamps_per_frame;
295 if (packet->payload.size() >= 950) {
296 LOG(LS_WARNING) << "SplitAudio too large iLBC payload";
297 return kTooLargePayload;
298 }
299 if (packet->payload.size() % 38 == 0) {
300 // 20 ms frames.
301 bytes_per_frame = 38;
302 timestamps_per_frame = 160;
303 } else if (packet->payload.size() % 50 == 0) {
304 // 30 ms frames.
305 bytes_per_frame = 50;
306 timestamps_per_frame = 240;
307 } else {
308 LOG(LS_WARNING) << "SplitAudio invalid iLBC payload";
309 return kFrameSplitError;
310 }
311 int ret = SplitByFrames(packet, bytes_per_frame, timestamps_per_frame,
312 &new_packets);
313 if (ret < 0) {
314 return ret;
315 } else if (ret == kNoSplit) {
316 // Do not split at all. Simply advance to the next packet in the list.
317 ++it;
318 // We do not have any new packets to insert, and should not delete the
319 // old one. Skip the code after the switch case, and jump straight to
320 // the next packet in the while loop.
321 continue;
322 }
323 break;
324 }
325 default: {
326 // Do not split at all. Simply advance to the next packet in the list.
327 ++it;
328 // We do not have any new packets to insert, and should not delete the
329 // old one. Skip the code after the switch case, and jump straight to
330 // the next packet in the while loop.
331 continue;
332 }
333 }
334 // Insert new packets into original list, before the element pointed to by
335 // iterator |it|.
336 packet_list->splice(it, new_packets, new_packets.begin(),
337 new_packets.end());
338 // Delete old packet 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 }
345 return kOK;
346 }
347
348 void PayloadSplitter::SplitBySamples(const Packet* packet,
349 size_t bytes_per_ms,
350 uint32_t timestamps_per_ms,
351 PacketList* new_packets) {
352 assert(packet);
353 assert(new_packets);
354
355 size_t split_size_bytes = packet->payload.size();
356
357 // Find a "chunk size" >= 20 ms and < 40 ms.
358 size_t min_chunk_size = bytes_per_ms * 20;
359 // 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 }
365 uint32_t timestamps_per_chunk = static_cast<uint32_t>(
366 split_size_bytes * timestamps_per_ms / bytes_per_ms);
367 uint32_t timestamp = packet->header.timestamp;
368
369 const uint8_t* payload_ptr = packet->payload.data();
370 size_t len = packet->payload.size();
371 while (len >= (2 * split_size_bytes)) {
372 Packet* new_packet = new Packet;
373 new_packet->header = packet->header;
374 new_packet->header.timestamp = timestamp;
375 timestamp += timestamps_per_chunk;
376 new_packet->primary = packet->primary;
377 new_packet->payload.SetData(payload_ptr, split_size_bytes);
378 payload_ptr += split_size_bytes;
379 new_packets->push_back(new_packet);
380 len -= split_size_bytes;
381 }
382
383 if (len > 0) {
384 Packet* new_packet = new Packet;
385 new_packet->header = packet->header;
386 new_packet->header.timestamp = timestamp;
387 new_packet->primary = packet->primary;
388 new_packet->payload.SetData(payload_ptr, len);
389 new_packets->push_back(new_packet);
390 }
391 }
392
393 int PayloadSplitter::SplitByFrames(const Packet* packet,
394 size_t bytes_per_frame,
395 uint32_t timestamps_per_frame,
396 PacketList* new_packets) {
397 if (packet->payload.size() % bytes_per_frame != 0) {
398 LOG(LS_WARNING) << "SplitByFrames length mismatch";
399 return kFrameSplitError;
400 }
401
402 if (packet->payload.size() == bytes_per_frame) {
403 // Special case. Do not split the payload.
404 return kNoSplit;
405 }
406
407 uint32_t timestamp = packet->header.timestamp;
408 const uint8_t* payload_ptr = packet->payload.data();
409 size_t len = packet->payload.size();
410 while (len > 0) {
411 assert(len >= bytes_per_frame);
412 Packet* new_packet = new Packet;
413 new_packet->header = packet->header;
414 new_packet->header.timestamp = timestamp;
415 timestamp += timestamps_per_frame;
416 new_packet->primary = packet->primary;
417 new_packet->payload.SetData(payload_ptr, bytes_per_frame);
418 payload_ptr += bytes_per_frame;
419 new_packets->push_back(new_packet);
420 len -= bytes_per_frame;
421 }
422 return kOK;
423 }
424
425 } // namespace webrtc 215 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_coding/neteq/payload_splitter.h ('k') | webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698