| 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 // For G.723 G.729, AMR etc we can have inband VAD | 138 // For G.723 G.729, AMR etc we can have inband VAD |
| 139 if (frame_type == kAudioFrameCN) { | 139 if (frame_type == kAudioFrameCN) { |
| 140 inband_vad_active_ = true; | 140 inband_vad_active_ = true; |
| 141 } else if (inband_vad_active_) { | 141 } else if (inband_vad_active_) { |
| 142 inband_vad_active_ = false; | 142 inband_vad_active_ = false; |
| 143 marker_bit = true; | 143 marker_bit = true; |
| 144 } | 144 } |
| 145 return marker_bit; | 145 return marker_bit; |
| 146 } | 146 } |
| 147 | 147 |
| 148 bool RTPSenderAudio::SendAudio(FrameType frame_type, | 148 int32_t RTPSenderAudio::SendAudio(FrameType frame_type, |
| 149 int8_t payload_type, | 149 int8_t payload_type, |
| 150 uint32_t capture_timestamp, | 150 uint32_t capture_timestamp, |
| 151 const uint8_t* payload_data, | 151 const uint8_t* payload_data, |
| 152 size_t data_size, | 152 size_t data_size, |
| 153 const RTPFragmentationHeader* fragmentation) { | 153 const RTPFragmentationHeader* fragmentation) { |
| 154 // TODO(pwestin) Breakup function in smaller functions. | 154 // TODO(pwestin) Breakup function in smaller functions. |
| 155 size_t payload_size = data_size; | 155 size_t payload_size = data_size; |
| 156 size_t max_payload_length = rtp_sender_->MaxPayloadLength(); | 156 size_t max_payload_length = rtp_sender_->MaxPayloadLength(); |
| 157 uint16_t dtmf_length_ms = 0; | 157 uint16_t dtmf_length_ms = 0; |
| 158 uint8_t key = 0; | 158 uint8_t key = 0; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 188 // A source MAY send events and coded audio packets for the same time | 188 // A source MAY send events and coded audio packets for the same time |
| 189 // but we don't support it | 189 // but we don't support it |
| 190 if (dtmf_event_is_on_) { | 190 if (dtmf_event_is_on_) { |
| 191 if (frame_type == kEmptyFrame) { | 191 if (frame_type == kEmptyFrame) { |
| 192 // kEmptyFrame is used to drive the DTMF when in CN mode | 192 // kEmptyFrame is used to drive the DTMF when in CN mode |
| 193 // it can be triggered more frequently than we want to send the | 193 // it can be triggered more frequently than we want to send the |
| 194 // DTMF packets. | 194 // DTMF packets. |
| 195 if (packet_size_samples > | 195 if (packet_size_samples > |
| 196 (capture_timestamp - dtmf_timestamp_last_sent_)) { | 196 (capture_timestamp - dtmf_timestamp_last_sent_)) { |
| 197 // not time to send yet | 197 // not time to send yet |
| 198 return true; | 198 return 0; |
| 199 } | 199 } |
| 200 } | 200 } |
| 201 dtmf_timestamp_last_sent_ = capture_timestamp; | 201 dtmf_timestamp_last_sent_ = capture_timestamp; |
| 202 uint32_t dtmf_duration_samples = capture_timestamp - dtmf_timestamp_; | 202 uint32_t dtmf_duration_samples = capture_timestamp - dtmf_timestamp_; |
| 203 bool ended = false; | 203 bool ended = false; |
| 204 bool send = true; | 204 bool send = true; |
| 205 | 205 |
| 206 if (dtmf_length_samples_ > dtmf_duration_samples) { | 206 if (dtmf_length_samples_ > dtmf_duration_samples) { |
| 207 if (dtmf_duration_samples <= 0) { | 207 if (dtmf_duration_samples <= 0) { |
| 208 // Skip send packet at start, since we shouldn't use duration 0 | 208 // Skip send packet at start, since we shouldn't use duration 0 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 221 | 221 |
| 222 // set new timestap for this segment | 222 // set new timestap for this segment |
| 223 dtmf_timestamp_ = capture_timestamp; | 223 dtmf_timestamp_ = capture_timestamp; |
| 224 dtmf_duration_samples -= 0xffff; | 224 dtmf_duration_samples -= 0xffff; |
| 225 dtmf_length_samples_ -= 0xffff; | 225 dtmf_length_samples_ -= 0xffff; |
| 226 | 226 |
| 227 return SendTelephoneEventPacket( | 227 return SendTelephoneEventPacket( |
| 228 ended, dtmf_payload_type, dtmf_timestamp_, | 228 ended, dtmf_payload_type, dtmf_timestamp_, |
| 229 static_cast<uint16_t>(dtmf_duration_samples), false); | 229 static_cast<uint16_t>(dtmf_duration_samples), false); |
| 230 } else { | 230 } else { |
| 231 if (!SendTelephoneEventPacket(ended, dtmf_payload_type, dtmf_timestamp_, | 231 if (SendTelephoneEventPacket(ended, dtmf_payload_type, dtmf_timestamp_, |
| 232 dtmf_duration_samples, | 232 dtmf_duration_samples, |
| 233 !dtmf_event_first_packet_sent_)) { | 233 !dtmf_event_first_packet_sent_) != 0) { |
| 234 return false; | 234 return -1; |
| 235 } | 235 } |
| 236 dtmf_event_first_packet_sent_ = true; | 236 dtmf_event_first_packet_sent_ = true; |
| 237 return true; | 237 return 0; |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 return true; | 240 return 0; |
| 241 } | 241 } |
| 242 if (payload_size == 0 || payload_data == NULL) { | 242 if (payload_size == 0 || payload_data == NULL) { |
| 243 if (frame_type == kEmptyFrame) { | 243 if (frame_type == kEmptyFrame) { |
| 244 // we don't send empty audio RTP packets | 244 // we don't send empty audio RTP packets |
| 245 // no error since we use it to drive DTMF when we use VAD | 245 // no error since we use it to drive DTMF when we use VAD |
| 246 return true; | 246 return 0; |
| 247 } | 247 } |
| 248 return false; | 248 return -1; |
| 249 } | 249 } |
| 250 uint8_t data_buffer[IP_PACKET_SIZE]; | 250 uint8_t data_buffer[IP_PACKET_SIZE]; |
| 251 bool marker_bit = MarkerBit(frame_type, payload_type); | 251 bool marker_bit = MarkerBit(frame_type, payload_type); |
| 252 | 252 |
| 253 int32_t rtpHeaderLength = 0; | 253 int32_t rtpHeaderLength = 0; |
| 254 uint16_t timestampOffset = 0; | 254 uint16_t timestampOffset = 0; |
| 255 | 255 |
| 256 if (red_payload_type >= 0 && fragmentation && !marker_bit && | 256 if (red_payload_type >= 0 && fragmentation && !marker_bit && |
| 257 fragmentation->fragmentationVectorSize > 1) { | 257 fragmentation->fragmentationVectorSize > 1) { |
| 258 // have we configured RED? use its payload type | 258 // have we configured RED? use its payload type |
| 259 // we need to get the current timestamp to calc the diff | 259 // we need to get the current timestamp to calc the diff |
| 260 uint32_t old_timestamp = rtp_sender_->Timestamp(); | 260 uint32_t old_timestamp = rtp_sender_->Timestamp(); |
| 261 rtpHeaderLength = rtp_sender_->BuildRtpHeader(data_buffer, red_payload_type, | 261 rtpHeaderLength = rtp_sender_->BuildRtpHeader(data_buffer, red_payload_type, |
| 262 marker_bit, capture_timestamp, | 262 marker_bit, capture_timestamp, |
| 263 clock_->TimeInMilliseconds()); | 263 clock_->TimeInMilliseconds()); |
| 264 | 264 |
| 265 timestampOffset = uint16_t(rtp_sender_->Timestamp() - old_timestamp); | 265 timestampOffset = uint16_t(rtp_sender_->Timestamp() - old_timestamp); |
| 266 } else { | 266 } else { |
| 267 rtpHeaderLength = rtp_sender_->BuildRtpHeader(data_buffer, payload_type, | 267 rtpHeaderLength = rtp_sender_->BuildRtpHeader(data_buffer, payload_type, |
| 268 marker_bit, capture_timestamp, | 268 marker_bit, capture_timestamp, |
| 269 clock_->TimeInMilliseconds()); | 269 clock_->TimeInMilliseconds()); |
| 270 } | 270 } |
| 271 if (rtpHeaderLength <= 0) { | 271 if (rtpHeaderLength <= 0) { |
| 272 return false; | 272 return -1; |
| 273 } | 273 } |
| 274 if (max_payload_length < (rtpHeaderLength + payload_size)) { | 274 if (max_payload_length < (rtpHeaderLength + payload_size)) { |
| 275 // Too large payload buffer. | 275 // Too large payload buffer. |
| 276 return false; | 276 return -1; |
| 277 } | 277 } |
| 278 if (red_payload_type >= 0 && // Have we configured RED? | 278 if (red_payload_type >= 0 && // Have we configured RED? |
| 279 fragmentation && fragmentation->fragmentationVectorSize > 1 && | 279 fragmentation && fragmentation->fragmentationVectorSize > 1 && |
| 280 !marker_bit) { | 280 !marker_bit) { |
| 281 if (timestampOffset <= 0x3fff) { | 281 if (timestampOffset <= 0x3fff) { |
| 282 if (fragmentation->fragmentationVectorSize != 2) { | 282 if (fragmentation->fragmentationVectorSize != 2) { |
| 283 // we only support 2 codecs when using RED | 283 // we only support 2 codecs when using RED |
| 284 return false; | 284 return -1; |
| 285 } | 285 } |
| 286 // only 0x80 if we have multiple blocks | 286 // only 0x80 if we have multiple blocks |
| 287 data_buffer[rtpHeaderLength++] = | 287 data_buffer[rtpHeaderLength++] = |
| 288 0x80 + fragmentation->fragmentationPlType[1]; | 288 0x80 + fragmentation->fragmentationPlType[1]; |
| 289 size_t blockLength = fragmentation->fragmentationLength[1]; | 289 size_t blockLength = fragmentation->fragmentationLength[1]; |
| 290 | 290 |
| 291 // sanity blockLength | 291 // sanity blockLength |
| 292 if (blockLength > 0x3ff) { // block length 10 bits 1023 bytes | 292 if (blockLength > 0x3ff) { // block length 10 bits 1023 bytes |
| 293 return false; | 293 return -1; |
| 294 } | 294 } |
| 295 uint32_t REDheader = (timestampOffset << 10) + blockLength; | 295 uint32_t REDheader = (timestampOffset << 10) + blockLength; |
| 296 ByteWriter<uint32_t>::WriteBigEndian(data_buffer + rtpHeaderLength, | 296 ByteWriter<uint32_t>::WriteBigEndian(data_buffer + rtpHeaderLength, |
| 297 REDheader); | 297 REDheader); |
| 298 rtpHeaderLength += 3; | 298 rtpHeaderLength += 3; |
| 299 | 299 |
| 300 data_buffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; | 300 data_buffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; |
| 301 // copy the RED data | 301 // copy the RED data |
| 302 memcpy(data_buffer + rtpHeaderLength, | 302 memcpy(data_buffer + rtpHeaderLength, |
| 303 payload_data + fragmentation->fragmentationOffset[1], | 303 payload_data + fragmentation->fragmentationOffset[1], |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 size_t packetSize = payload_size + rtpHeaderLength; | 342 size_t packetSize = payload_size + rtpHeaderLength; |
| 343 RtpUtility::RtpHeaderParser rtp_parser(data_buffer, packetSize); | 343 RtpUtility::RtpHeaderParser rtp_parser(data_buffer, packetSize); |
| 344 RTPHeader rtp_header; | 344 RTPHeader rtp_header; |
| 345 rtp_parser.Parse(&rtp_header); | 345 rtp_parser.Parse(&rtp_header); |
| 346 rtp_sender_->UpdateAudioLevel(data_buffer, packetSize, rtp_header, | 346 rtp_sender_->UpdateAudioLevel(data_buffer, packetSize, rtp_header, |
| 347 (frame_type == kAudioFrameSpeech), | 347 (frame_type == kAudioFrameSpeech), |
| 348 audio_level_dbov); | 348 audio_level_dbov); |
| 349 TRACE_EVENT_ASYNC_END2("webrtc", "Audio", capture_timestamp, "timestamp", | 349 TRACE_EVENT_ASYNC_END2("webrtc", "Audio", capture_timestamp, "timestamp", |
| 350 rtp_sender_->Timestamp(), "seqnum", | 350 rtp_sender_->Timestamp(), "seqnum", |
| 351 rtp_sender_->SequenceNumber()); | 351 rtp_sender_->SequenceNumber()); |
| 352 bool send_result = rtp_sender_->SendToNetwork( | 352 int32_t send_result = rtp_sender_->SendToNetwork( |
| 353 data_buffer, payload_size, rtpHeaderLength, rtc::TimeMillis(), | 353 data_buffer, payload_size, rtpHeaderLength, rtc::TimeMillis(), |
| 354 kAllowRetransmission, RtpPacketSender::kHighPriority); | 354 kAllowRetransmission, RtpPacketSender::kHighPriority); |
| 355 if (first_packet_sent_()) { | 355 if (first_packet_sent_()) { |
| 356 LOG(LS_INFO) << "First audio RTP packet sent to pacer"; | 356 LOG(LS_INFO) << "First audio RTP packet sent to pacer"; |
| 357 } | 357 } |
| 358 return send_result; | 358 return send_result; |
| 359 } | 359 } |
| 360 | 360 |
| 361 // Audio level magnitude and voice activity flag are set for each RTP packet | 361 // Audio level magnitude and voice activity flag are set for each RTP packet |
| 362 int32_t RTPSenderAudio::SetAudioLevel(uint8_t level_dbov) { | 362 int32_t RTPSenderAudio::SetAudioLevel(uint8_t level_dbov) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 { | 396 { |
| 397 rtc::CritScope lock(&send_audio_critsect_); | 397 rtc::CritScope lock(&send_audio_critsect_); |
| 398 if (dtmf_payload_type_ < 0) { | 398 if (dtmf_payload_type_ < 0) { |
| 399 // TelephoneEvent payloadtype not configured | 399 // TelephoneEvent payloadtype not configured |
| 400 return -1; | 400 return -1; |
| 401 } | 401 } |
| 402 } | 402 } |
| 403 return AddDTMF(key, time_ms, level); | 403 return AddDTMF(key, time_ms, level); |
| 404 } | 404 } |
| 405 | 405 |
| 406 bool RTPSenderAudio::SendTelephoneEventPacket(bool ended, | 406 int32_t RTPSenderAudio::SendTelephoneEventPacket(bool ended, |
| 407 int8_t dtmf_payload_type, | 407 int8_t dtmf_payload_type, |
| 408 uint32_t dtmf_timestamp, | 408 uint32_t dtmf_timestamp, |
| 409 uint16_t duration, | 409 uint16_t duration, |
| 410 bool marker_bit) { | 410 bool marker_bit) { |
| 411 uint8_t dtmfbuffer[IP_PACKET_SIZE]; | 411 uint8_t dtmfbuffer[IP_PACKET_SIZE]; |
| 412 uint8_t send_count = 1; | 412 uint8_t sendCount = 1; |
| 413 bool result = true; | 413 int32_t retVal = 0; |
| 414 | 414 |
| 415 if (ended) { | 415 if (ended) { |
| 416 // resend last packet in an event 3 times | 416 // resend last packet in an event 3 times |
| 417 send_count = 3; | 417 sendCount = 3; |
| 418 } | 418 } |
| 419 do { | 419 do { |
| 420 // Send DTMF data | 420 // Send DTMF data |
| 421 int32_t header_length = rtp_sender_->BuildRtpHeader( | 421 int32_t header_length = rtp_sender_->BuildRtpHeader( |
| 422 dtmfbuffer, dtmf_payload_type, marker_bit, dtmf_timestamp, | 422 dtmfbuffer, dtmf_payload_type, marker_bit, dtmf_timestamp, |
| 423 clock_->TimeInMilliseconds()); | 423 clock_->TimeInMilliseconds()); |
| 424 if (header_length <= 0) | 424 if (header_length <= 0) |
| 425 return false; | 425 return -1; |
| 426 | 426 |
| 427 // reset CSRC and X bit | 427 // reset CSRC and X bit |
| 428 dtmfbuffer[0] &= 0xe0; | 428 dtmfbuffer[0] &= 0xe0; |
| 429 | 429 |
| 430 // Create DTMF data | 430 // Create DTMF data |
| 431 /* From RFC 2833: | 431 /* From RFC 2833: |
| 432 | 432 |
| 433 0 1 2 3 | 433 0 1 2 3 |
| 434 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 | 434 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 |
| 435 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 435 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 436 | event |E|R| volume | duration | | 436 | event |E|R| volume | duration | |
| 437 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 437 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 438 */ | 438 */ |
| 439 // R bit always cleared | 439 // R bit always cleared |
| 440 uint8_t R = 0x00; | 440 uint8_t R = 0x00; |
| 441 uint8_t volume = dtmf_level_; | 441 uint8_t volume = dtmf_level_; |
| 442 | 442 |
| 443 // First packet un-ended | 443 // First packet un-ended |
| 444 uint8_t E = ended ? 0x80 : 0x00; | 444 uint8_t E = ended ? 0x80 : 0x00; |
| 445 | 445 |
| 446 // First byte is Event number, equals key number | 446 // First byte is Event number, equals key number |
| 447 dtmfbuffer[12] = dtmf_key_; | 447 dtmfbuffer[12] = dtmf_key_; |
| 448 dtmfbuffer[13] = E | R | volume; | 448 dtmfbuffer[13] = E | R | volume; |
| 449 ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 14, duration); | 449 ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 14, duration); |
| 450 | 450 |
| 451 TRACE_EVENT_INSTANT2( | 451 TRACE_EVENT_INSTANT2( |
| 452 TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Audio::SendTelephoneEvent", | 452 TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Audio::SendTelephoneEvent", |
| 453 "timestamp", dtmf_timestamp, "seqnum", rtp_sender_->SequenceNumber()); | 453 "timestamp", dtmf_timestamp, "seqnum", rtp_sender_->SequenceNumber()); |
| 454 result = rtp_sender_->SendToNetwork(dtmfbuffer, 4, 12, rtc::TimeMillis(), | 454 retVal = rtp_sender_->SendToNetwork(dtmfbuffer, 4, 12, rtc::TimeMillis(), |
| 455 kAllowRetransmission, | 455 kAllowRetransmission, |
| 456 RtpPacketSender::kHighPriority); | 456 RtpPacketSender::kHighPriority); |
| 457 send_count--; | 457 sendCount--; |
| 458 } while (send_count > 0 && result); | 458 } while (sendCount > 0 && retVal == 0); |
| 459 | 459 |
| 460 return result; | 460 return retVal; |
| 461 } | 461 } |
| 462 } // namespace webrtc | 462 } // namespace webrtc |
| OLD | NEW |