Add CVO support to Vie layer.
1. standard plumbing CVO through vie layer.
2. added a rtp_cvo.h which has both conversion functions from rtp header byte to/from VideoRotation.
WebRTCVideoEngine will later pass the rotation info in SendFrame() through VieVideoFrameI420.
BUG=4145
R=mflodman@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/46429007
Cr-Commit-Position: refs/heads/master@{#8703}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8703 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/media/base/constants.cc b/talk/media/base/constants.cc
index 46f29bf..6e1c460 100644
--- a/talk/media/base/constants.cc
+++ b/talk/media/base/constants.cc
@@ -109,6 +109,11 @@
const char kRtpAbsoluteSenderTimeHeaderExtension[] =
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
+const int kRtpVideoRotationHeaderExtensionDefaultId = 4;
+const char kRtpVideoRotationHeaderExtension[] = "urn:3gpp:video-orientation";
+const char kRtpVideoRotation6BitsHeaderExtensionForTesting[] =
+ "urn:3gpp:video-orientation:6";
+
const int kNumDefaultUnsignalledVideoRecvStreams = 0;
diff --git a/talk/media/base/constants.h b/talk/media/base/constants.h
index ce2748c..2fb4fdc 100644
--- a/talk/media/base/constants.h
+++ b/talk/media/base/constants.h
@@ -121,21 +121,29 @@
extern const char kComfortNoiseCodecName[];
-// Extension header for audio levels, as defined in
+// Header extension for audio levels, as defined in
// http://tools.ietf.org/html/draft-ietf-avtext-client-to-mixer-audio-level-03
extern const int kRtpAudioLevelHeaderExtensionDefaultId;
extern const char kRtpAudioLevelHeaderExtension[];
-// Extension header for RTP timestamp offset, see RFC 5450 for details:
+// Header extension for RTP timestamp offset, see RFC 5450 for details:
// http://tools.ietf.org/html/rfc5450
extern const int kRtpTimestampOffsetHeaderExtensionDefaultId;
extern const char kRtpTimestampOffsetHeaderExtension[];
-// Extension header for absolute send time, see url for details:
+// Header extension for absolute send time, see url for details:
// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
extern const int kRtpAbsoluteSenderTimeHeaderExtensionDefaultId;
extern const char kRtpAbsoluteSenderTimeHeaderExtension[];
+// Header extension for coordination of video orientation, see url for details:
+// http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
+// ts_126114v120700p.pdf
+extern const int kRtpVideoRotationHeaderExtensionDefaultId;
+extern const char kRtpVideoRotationHeaderExtension[];
+// We don't support 6 bit CVO. Added here for testing purpose.
+extern const char kRtpVideoRotation6BitsHeaderExtensionForTesting[];
+
extern const int kNumDefaultUnsignalledVideoRecvStreams;
} // namespace cricket
diff --git a/talk/media/webrtc/fakewebrtcvideoengine.h b/talk/media/webrtc/fakewebrtcvideoengine.h
index f64cd40..16c7f8b 100644
--- a/talk/media/webrtc/fakewebrtcvideoengine.h
+++ b/talk/media/webrtc/fakewebrtcvideoengine.h
@@ -285,6 +285,8 @@
rtp_offset_receive_id_(-1),
rtp_absolute_send_time_send_id_(-1),
rtp_absolute_send_time_receive_id_(-1),
+ rtp_video_rotation_send_id_(-1),
+ rtp_video_rotation_receive_id_(-1),
sender_target_delay_(0),
receiver_target_delay_(0),
transmission_smoothing_(false),
@@ -325,6 +327,8 @@
int rtp_offset_receive_id_;
int rtp_absolute_send_time_send_id_;
int rtp_absolute_send_time_receive_id_;
+ int rtp_video_rotation_send_id_;
+ int rtp_video_rotation_receive_id_;
int sender_target_delay_;
int receiver_target_delay_;
bool transmission_smoothing_;
@@ -503,6 +507,8 @@
return channels_.find(channel)->second->rtp_offset_send_id_;
} else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) {
return channels_.find(channel)->second->rtp_absolute_send_time_send_id_;
+ } else if (extension == kRtpVideoRotationHeaderExtension) {
+ return channels_.find(channel)->second->rtp_video_rotation_send_id_;
}
return -1;
}
@@ -513,6 +519,8 @@
} else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) {
return
channels_.find(channel)->second->rtp_absolute_send_time_receive_id_;
+ } else if (extension == kRtpVideoRotationHeaderExtension) {
+ return channels_.find(channel)->second->rtp_video_rotation_receive_id_;
}
return -1;
}
@@ -1107,25 +1115,36 @@
WEBRTC_FUNC(SetSendTimestampOffsetStatus, (int channel, bool enable,
int id)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->rtp_offset_send_id_ = (enable) ? id : -1;
+ channels_[channel]->rtp_offset_send_id_ = enable? id : -1;
return 0;
}
WEBRTC_FUNC(SetReceiveTimestampOffsetStatus, (int channel, bool enable,
int id)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->rtp_offset_receive_id_ = (enable) ? id : -1;
+ channels_[channel]->rtp_offset_receive_id_ = enable? id : -1;
return 0;
}
WEBRTC_FUNC(SetSendAbsoluteSendTimeStatus, (int channel, bool enable,
int id)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->rtp_absolute_send_time_send_id_ = (enable) ? id : -1;
+ channels_[channel]->rtp_absolute_send_time_send_id_ = enable? id : -1;
return 0;
}
WEBRTC_FUNC(SetReceiveAbsoluteSendTimeStatus, (int channel, bool enable,
int id)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->rtp_absolute_send_time_receive_id_ = (enable) ? id : -1;
+ channels_[channel]->rtp_absolute_send_time_receive_id_ = enable? id : -1;
+ return 0;
+ }
+ WEBRTC_FUNC(SetSendVideoRotationStatus, (int channel, bool enable, int id)) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ channels_[channel]->rtp_video_rotation_send_id_ = enable? id : -1;
+ return 0;
+ }
+ WEBRTC_FUNC(SetReceiveVideoRotationStatus,
+ (int channel, bool enable, int id)) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ channels_[channel]->rtp_video_rotation_receive_id_ = enable? id : -1;
return 0;
}
WEBRTC_STUB(SetRtcpXrRrtrStatus, (int, bool));
diff --git a/webrtc/config.h b/webrtc/config.h
index 1777937..e43a588 100644
--- a/webrtc/config.h
+++ b/webrtc/config.h
@@ -51,6 +51,7 @@
static const char* kTOffset;
static const char* kAbsSendTime;
+ static const char* kVideoRotation;
std::string name;
int id;
};
diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_cvo.h b/webrtc/modules/rtp_rtcp/interface/rtp_cvo.h
new file mode 100644
index 0000000..c7a0268
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/interface/rtp_cvo.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * 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.
+ */
+#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_CVO__H_
+#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_CVO__H_
+
+#include "webrtc/common_video/rotation.h"
+
+namespace webrtc {
+
+// Please refer to http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/
+// 12.07.00_60/ts_126114v120700p.pdf Section 7.4.5. The rotation of a frame is
+// the clockwise angle the frames must be rotated in order to display the frames
+// correctly if the display is rotated in its natural orientation.
+inline uint8_t ConvertVideoRotationToCVOByte(VideoRotation rotation) {
+ switch (rotation) {
+ case kVideoRotation_0:
+ return 0;
+ case kVideoRotation_90:
+ return 1;
+ case kVideoRotation_180:
+ return 2;
+ case kVideoRotation_270:
+ return 3;
+ }
+ assert(false);
+ return 0;
+}
+
+inline VideoRotation ConvertCVOByteToVideoRotation(uint8_t rotation) {
+ switch (rotation) {
+ case 0:
+ return kVideoRotation_0;
+ case 1:
+ return kVideoRotation_90;
+ case 2:
+ return kVideoRotation_180;
+ break;
+ case 3:
+ return kVideoRotation_270;
+ default:
+ assert(false);
+ return kVideoRotation_0;
+ }
+}
+
+} // namespace webrtc
+#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_CVO__H_
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
index fd3b7af..2823868 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc
@@ -13,6 +13,7 @@
#include <assert.h>
#include <string.h>
+#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
@@ -62,6 +63,13 @@
const size_t payload_data_length =
payload_length - rtp_header->header.paddingLength;
+ // Retrieve the video rotation information.
+ rtp_header->type.Video.rotation = kVideoRotation_0;
+ if (rtp_header->header.extension.hasVideoRotation) {
+ rtp_header->type.Video.rotation = ConvertCVOByteToVideoRotation(
+ rtp_header->header.extension.videoRotation);
+ }
+
if (payload == NULL || payload_data_length == 0) {
return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0
: -1;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
index 28c458d..c01cb36 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -12,6 +12,7 @@
#include <stdlib.h> // srand
+#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
@@ -453,25 +454,6 @@
return 0;
}
-// Please refer to http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/
-// 12.07.00_60/ts_126114v120700p.pdf Section 7.4.5. The rotation of a frame is
-// the clockwise angle the frames must be rotated in order to display the frames
-// correctly if the display is rotated in its natural orientation.
-uint8_t RTPSender::ConvertToCVOByte(VideoRotation rotation) {
- switch (rotation) {
- case kVideoRotation_0:
- return 0;
- case kVideoRotation_90:
- return 1;
- case kVideoRotation_180:
- return 2;
- case kVideoRotation_270:
- return 3;
- }
- assert(false);
- return 0;
-}
-
int32_t RTPSender::SendOutgoingData(FrameType frame_type,
int8_t payload_type,
uint32_t capture_timestamp,
@@ -1367,7 +1349,7 @@
size_t pos = 0;
const uint8_t len = 0;
data_buffer[pos++] = (id << 4) + len;
- data_buffer[pos++] = ConvertToCVOByte(rotation_);
+ data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_);
data_buffer[pos++] = 0; // padding
data_buffer[pos++] = 0; // padding
assert(pos == kVideoRotationLength);
@@ -1508,7 +1490,7 @@
LOG(LS_WARNING) << "Failed to update CVO.";
return false;
}
- rtp_packet[block_pos + 1] = ConvertToCVOByte(rotation);
+ rtp_packet[block_pos + 1] = ConvertVideoRotationToCVOByte(rotation);
return true;
}
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
index 67fb1fe..72763ed 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
@@ -284,8 +284,6 @@
void SetRtxRtpState(const RtpState& rtp_state);
RtpState GetRtxRtpState() const;
- static uint8_t ConvertToCVOByte(VideoRotation rotation);
-
protected:
int32_t CheckPayloadType(int8_t payload_type, RtpVideoCodecTypes* video_type);
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index c6e8398..e5c3b6f 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -17,6 +17,7 @@
#include "webrtc/base/buffer.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/pacing/include/mock/mock_paced_sender.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
@@ -189,7 +190,7 @@
EXPECT_EQ(rtp_sender_->SSRC(), rtp_header.ssrc);
EXPECT_EQ(0, rtp_header.numCSRCs);
EXPECT_EQ(0U, rtp_header.paddingLength);
- EXPECT_EQ(RTPSender::ConvertToCVOByte(rotation),
+ EXPECT_EQ(ConvertVideoRotationToCVOByte(rotation),
rtp_header.extension.videoRotation);
}
};
@@ -427,7 +428,7 @@
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_TRUE(rtp_header.extension.hasVideoRotation);
- EXPECT_EQ(RTPSender::ConvertToCVOByte(kRotation),
+ EXPECT_EQ(ConvertVideoRotationToCVOByte(kRotation),
rtp_header.extension.videoRotation);
}
diff --git a/webrtc/video/call.cc b/webrtc/video/call.cc
index bf80ee5..21a78da 100644
--- a/webrtc/video/call.cc
+++ b/webrtc/video/call.cc
@@ -41,10 +41,12 @@
const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
const char* RtpExtension::kAbsSendTime =
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
+const char* RtpExtension::kVideoRotation = "urn:3gpp:video-orientation";
bool RtpExtension::IsSupported(const std::string& name) {
return name == webrtc::RtpExtension::kTOffset ||
- name == webrtc::RtpExtension::kAbsSendTime;
+ name == webrtc::RtpExtension::kAbsSendTime ||
+ name == webrtc::RtpExtension::kVideoRotation;
}
VideoEncoder* VideoEncoder::Create(VideoEncoder::EncoderType codec_type) {
diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc
index 8665c11..ce65bcd 100644
--- a/webrtc/video/video_receive_stream.cc
+++ b/webrtc/video/video_receive_stream.cc
@@ -181,6 +181,9 @@
} else if (extension == RtpExtension::kAbsSendTime) {
if (rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id) != 0)
abort();
+ } else if (extension == RtpExtension::kVideoRotation) {
+ if (rtp_rtcp_->SetReceiveVideoRotationStatus(channel_, true, id) != 0)
+ abort();
} else {
abort(); // Unsupported extension.
}
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index 881802a..65e45e6 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -144,6 +144,9 @@
} else if (extension == RtpExtension::kAbsSendTime) {
if (rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id) != 0)
abort();
+ } else if (extension == RtpExtension::kVideoRotation) {
+ if (rtp_rtcp_->SetSendVideoRotationStatus(channel_, true, id) != 0)
+ abort();
} else {
abort(); // Unsupported extension.
}
diff --git a/webrtc/video_engine/include/vie_capture.h b/webrtc/video_engine/include/vie_capture.h
index caaeace..35c8469 100644
--- a/webrtc/video_engine/include/vie_capture.h
+++ b/webrtc/video_engine/include/vie_capture.h
@@ -71,6 +71,7 @@
v_pitch = 0;
width = 0;
height = 0;
+ rotation = kVideoRotation_0;
}
unsigned char* y_plane;
@@ -83,6 +84,7 @@
unsigned short width;
unsigned short height;
+ VideoRotation rotation;
};
// This class declares an abstract interface to be used when implementing
diff --git a/webrtc/video_engine/include/vie_rtp_rtcp.h b/webrtc/video_engine/include/vie_rtp_rtcp.h
index 7446e5f..d9a6a1f 100644
--- a/webrtc/video_engine/include/vie_rtp_rtcp.h
+++ b/webrtc/video_engine/include/vie_rtp_rtcp.h
@@ -245,6 +245,14 @@
bool enable,
int id) = 0;
+ virtual int SetSendVideoRotationStatus(int video_channel,
+ bool enable,
+ int id) = 0;
+
+ virtual int SetReceiveVideoRotationStatus(int video_channel,
+ bool enable,
+ int id) = 0;
+
// Enables/disables RTCP Receiver Reference Time Report Block extension/
// DLRR Report Block extension (RFC 3611).
virtual int SetRtcpXrRrtrStatus(int video_channel, bool enable) = 0;
diff --git a/webrtc/video_engine/vie_capturer.cc b/webrtc/video_engine/vie_capturer.cc
index bc96425..b35be3e 100644
--- a/webrtc/video_engine/vie_capturer.cc
+++ b/webrtc/video_engine/vie_capturer.cc
@@ -325,7 +325,8 @@
video_frame.height,
video_frame.y_pitch,
video_frame.u_pitch,
- video_frame.v_pitch);
+ video_frame.v_pitch,
+ video_frame.rotation);
if (ret < 0) {
LOG_F(LS_ERROR) << "Could not create I420Frame.";
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index eb16b1f..1101213 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -118,6 +118,7 @@
bandwidth_observer_(bandwidth_observer),
send_timestamp_extension_id_(kInvalidRtpExtensionId),
absolute_send_time_extension_id_(kInvalidRtpExtensionId),
+ video_rotation_extension_id_(kInvalidRtpExtensionId),
external_transport_(NULL),
decoder_reset_(true),
wait_for_key_frame_(false),
@@ -459,6 +460,7 @@
if (rtp_rtcp->RegisterSendRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset,
send_timestamp_extension_id_) != 0) {
+ LOG(LS_WARNING) << "Register Transmission Time Offset failed";
}
} else {
rtp_rtcp->DeregisterSendRtpHeaderExtension(
@@ -471,11 +473,23 @@
if (rtp_rtcp->RegisterSendRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime,
absolute_send_time_extension_id_) != 0) {
+ LOG(LS_WARNING) << "Register Absolute Send Time failed";
}
} else {
rtp_rtcp->DeregisterSendRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime);
}
+ if (video_rotation_extension_id_ != kInvalidRtpExtensionId) {
+ // Deregister in case the extension was previously enabled.
+ rtp_rtcp->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation);
+ if (rtp_rtcp->RegisterSendRtpHeaderExtension(
+ kRtpExtensionVideoRotation, video_rotation_extension_id_) !=
+ 0) {
+ LOG(LS_WARNING) << "Register VideoRotation extension failed";
+ }
+ } else {
+ rtp_rtcp->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation);
+ }
rtp_rtcp->RegisterRtcpStatisticsCallback(
rtp_rtcp_->GetRtcpStatisticsCallback());
rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
@@ -899,6 +913,37 @@
return vie_receiver_.SetReceiveAbsoluteSendTimeStatus(enable, id) ? 0 : -1;
}
+int ViEChannel::SetSendVideoRotationStatus(bool enable, int id) {
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ int error = 0;
+ if (enable) {
+ // Enable the extension, but disable possible old id to avoid errors.
+ video_rotation_extension_id_ = id;
+ rtp_rtcp_->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation);
+ error = rtp_rtcp_->RegisterSendRtpHeaderExtension(
+ kRtpExtensionVideoRotation, id);
+ for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end(); it++) {
+ (*it)->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation);
+ error |=
+ (*it)->RegisterSendRtpHeaderExtension(kRtpExtensionVideoRotation, id);
+ }
+ } else {
+ // Disable the extension.
+ video_rotation_extension_id_ = kInvalidRtpExtensionId;
+ rtp_rtcp_->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation);
+ for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end(); it++) {
+ (*it)->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation);
+ }
+ }
+ return error;
+}
+
+int ViEChannel::SetReceiveVideoRotationStatus(bool enable, int id) {
+ return vie_receiver_.SetReceiveVideoRotationStatus(enable, id) ? 0 : -1;
+}
+
void ViEChannel::SetRtcpXrRrtrStatus(bool enable) {
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
rtp_rtcp_->SetRtcpXrRrtrStatus(enable);
diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h
index 3744d88..1bf95f8 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -131,6 +131,8 @@
int SetSendAbsoluteSendTimeStatus(bool enable, int id);
int SetReceiveAbsoluteSendTimeStatus(bool enable, int id);
bool GetReceiveAbsoluteSendTimeStatus() const;
+ int SetSendVideoRotationStatus(bool enable, int id);
+ int SetReceiveVideoRotationStatus(bool enable, int id);
void SetRtcpXrRrtrStatus(bool enable);
void SetTransmissionSmoothingStatus(bool enable);
void EnableTMMBR(bool enable);
@@ -526,6 +528,7 @@
rtc::scoped_ptr<RtcpBandwidthObserver> bandwidth_observer_;
int send_timestamp_extension_id_;
int absolute_send_time_extension_id_;
+ int video_rotation_extension_id_;
Transport* external_transport_;
diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc
index 0d1f1ad..e61c82b 100644
--- a/webrtc/video_engine/vie_receiver.cc
+++ b/webrtc/video_engine/vie_receiver.cc
@@ -16,6 +16,7 @@
#include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h"
#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
#include "webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
@@ -58,6 +59,7 @@
receiving_(false),
restored_packet_in_use_(false),
receiving_ast_enabled_(false),
+ receiving_cvo_enabled_(false),
last_packet_log_ms_(-1) {
assert(remote_bitrate_estimator);
}
@@ -187,6 +189,22 @@
}
}
+bool ViEReceiver::SetReceiveVideoRotationStatus(bool enable, int id) {
+ if (enable) {
+ if (rtp_header_parser_->RegisterRtpHeaderExtension(
+ kRtpExtensionVideoRotation, id)) {
+ receiving_cvo_enabled_ = true;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ receiving_cvo_enabled_ = false;
+ return rtp_header_parser_->DeregisterRtpHeaderExtension(
+ kRtpExtensionVideoRotation);
+ }
+}
+
int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
size_t rtp_packet_length,
const PacketTime& packet_time) {
@@ -382,6 +400,11 @@
return;
}
rtp_header.type.Video.codec = payload_specific.Video.videoCodecType;
+ rtp_header.type.Video.rotation = kVideoRotation_0;
+ if (header.extension.hasVideoRotation) {
+ rtp_header.type.Video.rotation =
+ ConvertCVOByteToVideoRotation(header.extension.videoRotation);
+ }
OnReceivedPayloadData(NULL, 0, &rtp_header);
}
diff --git a/webrtc/video_engine/vie_receiver.h b/webrtc/video_engine/vie_receiver.h
index e2e3daf..5c09a3e 100644
--- a/webrtc/video_engine/vie_receiver.h
+++ b/webrtc/video_engine/vie_receiver.h
@@ -64,6 +64,7 @@
bool SetReceiveTimestampOffsetStatus(bool enable, int id);
bool SetReceiveAbsoluteSendTimeStatus(bool enable, int id);
+ bool SetReceiveVideoRotationStatus(bool enable, int id);
void StartReceive();
void StopReceive();
@@ -123,6 +124,7 @@
uint8_t restored_packet_[kViEMaxMtu];
bool restored_packet_in_use_;
bool receiving_ast_enabled_;
+ bool receiving_cvo_enabled_;
int64_t last_packet_log_ms_;
};
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
index 58e750d..38e7e97 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
@@ -615,6 +615,43 @@
return 0;
}
+int ViERTP_RTCPImpl::SetSendVideoRotationStatus(int video_channel,
+ bool enable,
+ int id) {
+ LOG_F(LS_INFO) << "channel: " << video_channel
+ << " enable: " << (enable ? "on" : "off") << " id: " << id;
+
+ ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
+ ViEChannel* vie_channel = cs.Channel(video_channel);
+ if (!vie_channel) {
+ shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
+ return -1;
+ }
+ if (vie_channel->SetSendVideoRotationStatus(enable, id) != 0) {
+ shared_data_->SetLastError(kViERtpRtcpUnknownError);
+ return -1;
+ }
+ return 0;
+}
+
+int ViERTP_RTCPImpl::SetReceiveVideoRotationStatus(int video_channel,
+ bool enable,
+ int id) {
+ LOG_F(LS_INFO) << "channel: " << video_channel
+ << " enable: " << (enable ? "on" : "off") << " id: " << id;
+ ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
+ ViEChannel* vie_channel = cs.Channel(video_channel);
+ if (!vie_channel) {
+ shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
+ return -1;
+ }
+ if (vie_channel->SetReceiveVideoRotationStatus(enable, id) != 0) {
+ shared_data_->SetLastError(kViERtpRtcpUnknownError);
+ return -1;
+ }
+ return 0;
+}
+
int ViERTP_RTCPImpl::SetRtcpXrRrtrStatus(int video_channel, bool enable) {
LOG_F(LS_INFO) << "channel: " << video_channel
<< " enable: " << (enable ? "on" : "off");
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.h b/webrtc/video_engine/vie_rtp_rtcp_impl.h
index 7512222..b6f3a23 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.h
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.h
@@ -90,6 +90,12 @@
virtual int SetReceiveAbsoluteSendTimeStatus(int video_channel,
bool enable,
int id);
+ virtual int SetSendVideoRotationStatus(int video_channel,
+ bool enable,
+ int id);
+ virtual int SetReceiveVideoRotationStatus(int video_channel,
+ bool enable,
+ int id);
virtual int SetRtcpXrRrtrStatus(int video_channel, bool enable);
virtual int SetTransmissionSmoothingStatus(int video_channel, bool enable);
virtual int SetMinTransmitBitrate(int video_channel,