Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 // Iterate through all packets in |packet_list|. | 225 // Iterate through all packets in |packet_list|. |
| 226 while (it != packet_list->end()) { | 226 while (it != packet_list->end()) { |
| 227 Packet* packet = (*it); // Just to make the notation more intuitive. | 227 Packet* packet = (*it); // Just to make the notation more intuitive. |
| 228 // Get codec type for this payload. | 228 // Get codec type for this payload. |
| 229 const DecoderDatabase::DecoderInfo* info = | 229 const DecoderDatabase::DecoderInfo* info = |
| 230 decoder_database.GetDecoderInfo(packet->header.payloadType); | 230 decoder_database.GetDecoderInfo(packet->header.payloadType); |
| 231 if (!info) { | 231 if (!info) { |
| 232 LOG(LS_WARNING) << "SplitAudio unknown payload type"; | 232 LOG(LS_WARNING) << "SplitAudio unknown payload type"; |
| 233 return kUnknownPayloadType; | 233 return kUnknownPayloadType; |
| 234 } | 234 } |
| 235 // No splitting for a sync-packet. | 235 // No splitting for a sync-packet nor for any format handled internally. |
| 236 if (packet->sync_packet) { | 236 if (packet->sync_packet || |
| 237 info->IsComfortNoise() || info->IsDtmf() || info->IsRed()) { | |
| 237 ++it; | 238 ++it; |
| 238 continue; | 239 continue; |
| 239 } | 240 } |
| 240 PacketList new_packets; | 241 const AudioDecoder* decoder = info->GetDecoder(); |
| 241 switch (info->codec_type) { | 242 RTC_DCHECK(decoder); |
| 242 case NetEqDecoder::kDecoderPCMu: | 243 AudioDecoder::PacketSplits splits = |
| 243 case NetEqDecoder::kDecoderPCMa: { | 244 decoder->SplitPacket(packet->payload, packet->payload_length); |
| 244 // 8 bytes per ms; 8 timestamps per ms. | 245 if (splits.empty()) { |
| 245 SplitBySamples(packet, 8, 8, &new_packets); | 246 return kFrameSplitError; |
| 246 break; | 247 } else if (splits.size() == 1 && |
| 248 splits[0].byte_offset == 0 && | |
| 249 splits[0].num_bytes == packet->payload_length && | |
| 250 splits[0].timestamp_offset == 0) { | |
| 251 // No splitting necessary; move on to the next packet | |
|
kwiberg-webrtc
2016/08/26 12:39:25
Hmm. Wouldn't it be better to test just the first
ossu
2016/08/26 13:05:30
Nah, I think it's fine if you can figure out that
| |
| 252 ++it; | |
| 253 } else { | |
| 254 PacketList new_packets; | |
| 255 for (const auto& split : splits) { | |
| 256 Packet* new_packet = new Packet; | |
|
kwiberg-webrtc
2016/08/26 12:39:25
Ew. Consider using unique_ptr in this block, and u
ossu
2016/08/26 13:05:30
Hello. I'm the messenger. Please don't shoot me! :
| |
| 257 const uint8_t* payload_ptr = packet->payload + split.byte_offset; | |
| 258 new_packet->payload_length = split.num_bytes; | |
| 259 new_packet->header = packet->header; | |
| 260 new_packet->header.timestamp += split.timestamp_offset; | |
| 261 new_packet->primary = packet->primary; | |
| 262 new_packet->payload = new uint8_t[split.num_bytes]; | |
| 263 memcpy(new_packet->payload, payload_ptr, split.num_bytes); | |
| 264 new_packets.push_back(new_packet); | |
| 247 } | 265 } |
| 248 case NetEqDecoder::kDecoderPCMu_2ch: | 266 |
| 249 case NetEqDecoder::kDecoderPCMa_2ch: { | 267 // Insert new packets into original list, before the element pointed to by |
| 250 // 2 * 8 bytes per ms; 8 timestamps per ms. | 268 // iterator |it|. |
| 251 SplitBySamples(packet, 2 * 8, 8, &new_packets); | 269 packet_list->splice(it, new_packets, new_packets.begin(), |
| 252 break; | 270 new_packets.end()); |
| 253 } | 271 // Delete old packet payload. |
| 254 case NetEqDecoder::kDecoderG722: { | 272 delete [] (*it)->payload; |
| 255 // 8 bytes per ms; 16 timestamps per ms. | 273 delete (*it); |
| 256 SplitBySamples(packet, 8, 16, &new_packets); | 274 // Remove |it| from the packet list. This operation effectively moves the |
| 257 break; | 275 // iterator |it| to the next packet in the list. Thus, we do not have to |
| 258 } | 276 // increment it manually. |
| 259 case NetEqDecoder::kDecoderPCM16B: { | 277 it = packet_list->erase(it); |
| 260 // 16 bytes per ms; 8 timestamps per ms. | |
| 261 SplitBySamples(packet, 16, 8, &new_packets); | |
| 262 break; | |
| 263 } | |
| 264 case NetEqDecoder::kDecoderPCM16Bwb: { | |
| 265 // 32 bytes per ms; 16 timestamps per ms. | |
| 266 SplitBySamples(packet, 32, 16, &new_packets); | |
| 267 break; | |
| 268 } | |
| 269 case NetEqDecoder::kDecoderPCM16Bswb32kHz: { | |
| 270 // 64 bytes per ms; 32 timestamps per ms. | |
| 271 SplitBySamples(packet, 64, 32, &new_packets); | |
| 272 break; | |
| 273 } | |
| 274 case NetEqDecoder::kDecoderPCM16Bswb48kHz: { | |
| 275 // 96 bytes per ms; 48 timestamps per ms. | |
| 276 SplitBySamples(packet, 96, 48, &new_packets); | |
| 277 break; | |
| 278 } | |
| 279 case NetEqDecoder::kDecoderPCM16B_2ch: { | |
| 280 // 2 * 16 bytes per ms; 8 timestamps per ms. | |
| 281 SplitBySamples(packet, 2 * 16, 8, &new_packets); | |
| 282 break; | |
| 283 } | |
| 284 case NetEqDecoder::kDecoderPCM16Bwb_2ch: { | |
| 285 // 2 * 32 bytes per ms; 16 timestamps per ms. | |
| 286 SplitBySamples(packet, 2 * 32, 16, &new_packets); | |
| 287 break; | |
| 288 } | |
| 289 case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch: { | |
| 290 // 2 * 64 bytes per ms; 32 timestamps per ms. | |
| 291 SplitBySamples(packet, 2 * 64, 32, &new_packets); | |
| 292 break; | |
| 293 } | |
| 294 case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch: { | |
| 295 // 2 * 96 bytes per ms; 48 timestamps per ms. | |
| 296 SplitBySamples(packet, 2 * 96, 48, &new_packets); | |
| 297 break; | |
| 298 } | |
| 299 case NetEqDecoder::kDecoderPCM16B_5ch: { | |
| 300 // 5 * 16 bytes per ms; 8 timestamps per ms. | |
| 301 SplitBySamples(packet, 5 * 16, 8, &new_packets); | |
| 302 break; | |
| 303 } | |
| 304 case NetEqDecoder::kDecoderILBC: { | |
| 305 size_t bytes_per_frame; | |
| 306 int timestamps_per_frame; | |
| 307 if (packet->payload_length >= 950) { | |
| 308 LOG(LS_WARNING) << "SplitAudio too large iLBC payload"; | |
| 309 return kTooLargePayload; | |
| 310 } | |
| 311 if (packet->payload_length % 38 == 0) { | |
| 312 // 20 ms frames. | |
| 313 bytes_per_frame = 38; | |
| 314 timestamps_per_frame = 160; | |
| 315 } else if (packet->payload_length % 50 == 0) { | |
| 316 // 30 ms frames. | |
| 317 bytes_per_frame = 50; | |
| 318 timestamps_per_frame = 240; | |
| 319 } else { | |
| 320 LOG(LS_WARNING) << "SplitAudio invalid iLBC payload"; | |
| 321 return kFrameSplitError; | |
| 322 } | |
| 323 int ret = SplitByFrames(packet, bytes_per_frame, timestamps_per_frame, | |
| 324 &new_packets); | |
| 325 if (ret < 0) { | |
| 326 return ret; | |
| 327 } else if (ret == kNoSplit) { | |
| 328 // Do not split at all. Simply advance to the next packet in the list. | |
| 329 ++it; | |
| 330 // We do not have any new packets to insert, and should not delete the | |
| 331 // old one. Skip the code after the switch case, and jump straight to | |
| 332 // the next packet in the while loop. | |
| 333 continue; | |
| 334 } | |
| 335 break; | |
| 336 } | |
| 337 default: { | |
| 338 // Do not split at all. Simply advance to the next packet in the list. | |
| 339 ++it; | |
| 340 // We do not have any new packets to insert, and should not delete the | |
| 341 // old one. Skip the code after the switch case, and jump straight to | |
| 342 // the next packet in the while loop. | |
| 343 continue; | |
| 344 } | |
| 345 } | 278 } |
| 346 // Insert new packets into original list, before the element pointed to by | |
| 347 // iterator |it|. | |
| 348 packet_list->splice(it, new_packets, new_packets.begin(), | |
| 349 new_packets.end()); | |
| 350 // Delete old packet payload. | |
| 351 delete [] (*it)->payload; | |
| 352 delete (*it); | |
| 353 // Remove |it| from the packet list. This operation effectively moves the | |
| 354 // iterator |it| to the next packet in the list. Thus, we do not have to | |
| 355 // increment it manually. | |
| 356 it = packet_list->erase(it); | |
| 357 } | 279 } |
| 358 return kOK; | 280 return kOK; |
| 359 } | 281 } |
| 360 | |
| 361 void PayloadSplitter::SplitBySamples(const Packet* packet, | |
| 362 size_t bytes_per_ms, | |
| 363 uint32_t timestamps_per_ms, | |
| 364 PacketList* new_packets) { | |
| 365 assert(packet); | |
| 366 assert(new_packets); | |
| 367 | |
| 368 size_t split_size_bytes = packet->payload_length; | |
| 369 | |
| 370 // Find a "chunk size" >= 20 ms and < 40 ms. | |
| 371 size_t min_chunk_size = bytes_per_ms * 20; | |
| 372 // Reduce the split size by half as long as |split_size_bytes| is at least | |
| 373 // twice the minimum chunk size (so that the resulting size is at least as | |
| 374 // large as the minimum chunk size). | |
| 375 while (split_size_bytes >= 2 * min_chunk_size) { | |
| 376 split_size_bytes >>= 1; | |
| 377 } | |
| 378 uint32_t timestamps_per_chunk = static_cast<uint32_t>( | |
| 379 split_size_bytes * timestamps_per_ms / bytes_per_ms); | |
| 380 uint32_t timestamp = packet->header.timestamp; | |
| 381 | |
| 382 uint8_t* payload_ptr = packet->payload; | |
| 383 size_t len = packet->payload_length; | |
| 384 while (len >= (2 * split_size_bytes)) { | |
| 385 Packet* new_packet = new Packet; | |
| 386 new_packet->payload_length = split_size_bytes; | |
| 387 new_packet->header = packet->header; | |
| 388 new_packet->header.timestamp = timestamp; | |
| 389 timestamp += timestamps_per_chunk; | |
| 390 new_packet->primary = packet->primary; | |
| 391 new_packet->payload = new uint8_t[split_size_bytes]; | |
| 392 memcpy(new_packet->payload, payload_ptr, split_size_bytes); | |
| 393 payload_ptr += split_size_bytes; | |
| 394 new_packets->push_back(new_packet); | |
| 395 len -= split_size_bytes; | |
| 396 } | |
| 397 | |
| 398 if (len > 0) { | |
| 399 Packet* new_packet = new Packet; | |
| 400 new_packet->payload_length = len; | |
| 401 new_packet->header = packet->header; | |
| 402 new_packet->header.timestamp = timestamp; | |
| 403 new_packet->primary = packet->primary; | |
| 404 new_packet->payload = new uint8_t[len]; | |
| 405 memcpy(new_packet->payload, payload_ptr, len); | |
| 406 new_packets->push_back(new_packet); | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 int PayloadSplitter::SplitByFrames(const Packet* packet, | |
| 411 size_t bytes_per_frame, | |
| 412 uint32_t timestamps_per_frame, | |
| 413 PacketList* new_packets) { | |
| 414 if (packet->payload_length % bytes_per_frame != 0) { | |
| 415 LOG(LS_WARNING) << "SplitByFrames length mismatch"; | |
| 416 return kFrameSplitError; | |
| 417 } | |
| 418 | |
| 419 if (packet->payload_length == bytes_per_frame) { | |
| 420 // Special case. Do not split the payload. | |
| 421 return kNoSplit; | |
| 422 } | |
| 423 | |
| 424 uint32_t timestamp = packet->header.timestamp; | |
| 425 uint8_t* payload_ptr = packet->payload; | |
| 426 size_t len = packet->payload_length; | |
| 427 while (len > 0) { | |
| 428 assert(len >= bytes_per_frame); | |
| 429 Packet* new_packet = new Packet; | |
| 430 new_packet->payload_length = bytes_per_frame; | |
| 431 new_packet->header = packet->header; | |
| 432 new_packet->header.timestamp = timestamp; | |
| 433 timestamp += timestamps_per_frame; | |
| 434 new_packet->primary = packet->primary; | |
| 435 new_packet->payload = new uint8_t[bytes_per_frame]; | |
| 436 memcpy(new_packet->payload, payload_ptr, bytes_per_frame); | |
| 437 payload_ptr += bytes_per_frame; | |
| 438 new_packets->push_back(new_packet); | |
| 439 len -= bytes_per_frame; | |
| 440 } | |
| 441 return kOK; | |
| 442 } | |
| 443 | 282 |
| 444 } // namespace webrtc | 283 } // namespace webrtc |
| OLD | NEW |