2011-07-07 08:21:25 +00:00
|
|
|
/*
|
2012-01-24 17:16:59 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2011-07-07 08:21:25 +00:00
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-02-05 15:12:39 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h"
|
2011-09-20 13:52:04 +00:00
|
|
|
|
2013-09-06 13:40:11 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <string.h>
|
2013-02-05 15:12:39 +00:00
|
|
|
|
2013-08-15 23:38:54 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
|
2014-07-31 14:59:24 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
|
2013-03-18 16:39:03 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
|
2013-02-05 15:12:39 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
|
|
|
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
2014-04-08 11:06:12 +00:00
|
|
|
#include "webrtc/system_wrappers/interface/logging.h"
|
2013-04-04 19:43:34 +00:00
|
|
|
#include "webrtc/system_wrappers/interface/trace_event.h"
|
2011-07-07 08:21:25 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2013-08-15 23:38:54 +00:00
|
|
|
RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy(
|
2014-04-08 11:06:12 +00:00
|
|
|
RtpData* data_callback) {
|
|
|
|
|
return new RTPReceiverVideo(data_callback);
|
2013-08-15 23:38:54 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-08 11:06:12 +00:00
|
|
|
RTPReceiverVideo::RTPReceiverVideo(RtpData* data_callback)
|
2014-09-12 11:05:55 +00:00
|
|
|
: RTPReceiverStrategy(data_callback) {
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-04-27 05:25:53 +00:00
|
|
|
RTPReceiverVideo::~RTPReceiverVideo() {
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-12 11:05:55 +00:00
|
|
|
bool RTPReceiverVideo::ShouldReportCsrcChanges(uint8_t payload_type) const {
|
2013-01-22 12:31:01 +00:00
|
|
|
// Always do this for video packets.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-08 11:08:41 +00:00
|
|
|
int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
|
2013-02-05 15:12:39 +00:00
|
|
|
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
2013-08-15 23:38:54 +00:00
|
|
|
int8_t payload_type,
|
|
|
|
|
uint32_t frequency) {
|
2013-02-04 13:23:07 +00:00
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-12 11:05:55 +00:00
|
|
|
int32_t RTPReceiverVideo::ParseRtpPacket(WebRtcRTPHeader* rtp_header,
|
|
|
|
|
const PayloadUnion& specific_payload,
|
|
|
|
|
bool is_red,
|
|
|
|
|
const uint8_t* payload,
|
|
|
|
|
uint16_t payload_length,
|
|
|
|
|
int64_t timestamp_ms,
|
|
|
|
|
bool is_first_packet) {
|
|
|
|
|
TRACE_EVENT2("webrtc_rtp",
|
|
|
|
|
"Video::ParseRtp",
|
|
|
|
|
"seqnum",
|
|
|
|
|
rtp_header->header.sequenceNumber,
|
|
|
|
|
"timestamp",
|
|
|
|
|
rtp_header->header.timestamp);
|
2013-08-15 23:38:54 +00:00
|
|
|
rtp_header->type.Video.codec = specific_payload.Video.videoCodecType;
|
2013-09-08 11:15:00 +00:00
|
|
|
|
|
|
|
|
const uint16_t payload_data_length =
|
|
|
|
|
payload_length - rtp_header->header.paddingLength;
|
|
|
|
|
|
2014-09-29 08:00:22 +00:00
|
|
|
if (payload == NULL || payload_data_length == 0) {
|
2013-09-08 11:15:00 +00:00
|
|
|
return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
|
|
|
|
|
: -1;
|
2014-09-29 08:00:22 +00:00
|
|
|
}
|
2013-09-08 11:15:00 +00:00
|
|
|
|
2014-09-12 11:05:55 +00:00
|
|
|
// We are not allowed to hold a critical section when calling below functions.
|
|
|
|
|
scoped_ptr<RtpDepacketizer> depacketizer(
|
2014-09-29 08:00:22 +00:00
|
|
|
RtpDepacketizer::Create(rtp_header->type.Video.codec));
|
2014-09-12 11:05:55 +00:00
|
|
|
if (depacketizer.get() == NULL) {
|
|
|
|
|
LOG(LS_ERROR) << "Failed to create depacketizer.";
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtp_header->type.Video.isFirstPacket = is_first_packet;
|
2014-09-29 08:00:22 +00:00
|
|
|
RtpDepacketizer::ParsedPayload parsed_payload(rtp_header);
|
|
|
|
|
if (!depacketizer->Parse(&parsed_payload, payload, payload_data_length))
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return data_callback_->OnReceivedPayloadData(parsed_payload.payload,
|
|
|
|
|
parsed_payload.payload_length,
|
|
|
|
|
parsed_payload.header) == 0
|
|
|
|
|
? 0
|
|
|
|
|
: -1;
|
2012-12-18 15:40:53 +00:00
|
|
|
}
|
|
|
|
|
|
2013-08-15 23:38:54 +00:00
|
|
|
int RTPReceiverVideo::GetPayloadTypeFrequency() const {
|
|
|
|
|
return kVideoPayloadTypeFrequency;
|
2012-12-18 15:40:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
|
2013-04-08 11:08:41 +00:00
|
|
|
uint16_t last_payload_length) const {
|
2012-12-18 15:40:53 +00:00
|
|
|
return kRtpDead;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-08 11:08:41 +00:00
|
|
|
int32_t RTPReceiverVideo::InvokeOnInitializeDecoder(
|
2012-12-18 15:40:53 +00:00
|
|
|
RtpFeedback* callback,
|
2013-08-15 23:38:54 +00:00
|
|
|
int32_t id,
|
|
|
|
|
int8_t payload_type,
|
2013-02-05 15:12:39 +00:00
|
|
|
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
2013-08-15 23:38:54 +00:00
|
|
|
const PayloadUnion& specific_payload) const {
|
2012-12-18 15:40:53 +00:00
|
|
|
// For video we just go with default values.
|
2014-09-12 11:05:55 +00:00
|
|
|
if (-1 ==
|
|
|
|
|
callback->OnInitializeDecoder(
|
|
|
|
|
id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) {
|
2014-04-08 11:06:12 +00:00
|
|
|
LOG(LS_ERROR) << "Failed to created decoder for payload type: "
|
|
|
|
|
<< payload_type;
|
2012-12-18 15:40:53 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-12 11:05:55 +00:00
|
|
|
int32_t RTPReceiverVideo::BuildRTPheader(const WebRtcRTPHeader* rtp_header,
|
|
|
|
|
uint8_t* data_buffer) const {
|
2013-04-08 11:08:41 +00:00
|
|
|
data_buffer[0] = static_cast<uint8_t>(0x80); // version 2
|
|
|
|
|
data_buffer[1] = static_cast<uint8_t>(rtp_header->header.payloadType);
|
2013-02-05 15:12:39 +00:00
|
|
|
if (rtp_header->header.markerBit) {
|
|
|
|
|
data_buffer[1] |= kRtpMarkerBitMask; // MarkerBit is 1
|
2012-04-27 05:25:53 +00:00
|
|
|
}
|
2014-07-08 12:10:51 +00:00
|
|
|
RtpUtility::AssignUWord16ToBuffer(data_buffer + 2,
|
|
|
|
|
rtp_header->header.sequenceNumber);
|
|
|
|
|
RtpUtility::AssignUWord32ToBuffer(data_buffer + 4,
|
|
|
|
|
rtp_header->header.timestamp);
|
|
|
|
|
RtpUtility::AssignUWord32ToBuffer(data_buffer + 8, rtp_header->header.ssrc);
|
2012-04-27 05:25:53 +00:00
|
|
|
|
2013-04-08 11:08:41 +00:00
|
|
|
int32_t rtp_header_length = 12;
|
2012-04-27 05:25:53 +00:00
|
|
|
|
|
|
|
|
// Add the CSRCs if any
|
2013-02-05 15:12:39 +00:00
|
|
|
if (rtp_header->header.numCSRCs > 0) {
|
|
|
|
|
if (rtp_header->header.numCSRCs > 16) {
|
2012-04-27 05:25:53 +00:00
|
|
|
// error
|
|
|
|
|
assert(false);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2013-04-08 11:08:41 +00:00
|
|
|
uint8_t* ptr = &data_buffer[rtp_header_length];
|
|
|
|
|
for (uint32_t i = 0; i < rtp_header->header.numCSRCs; ++i) {
|
2014-07-08 12:10:51 +00:00
|
|
|
RtpUtility::AssignUWord32ToBuffer(ptr, rtp_header->header.arrOfCSRCs[i]);
|
2013-02-05 15:12:39 +00:00
|
|
|
ptr += 4;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2013-02-05 15:12:39 +00:00
|
|
|
data_buffer[0] = (data_buffer[0] & 0xf0) | rtp_header->header.numCSRCs;
|
2012-04-27 05:25:53 +00:00
|
|
|
// Update length of header
|
2013-04-08 11:08:41 +00:00
|
|
|
rtp_header_length += sizeof(uint32_t) * rtp_header->header.numCSRCs;
|
2012-04-27 05:25:53 +00:00
|
|
|
}
|
2013-02-05 15:12:39 +00:00
|
|
|
return rtp_header_length;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-05 15:12:39 +00:00
|
|
|
} // namespace webrtc
|