VT: SFR: H264: CVO implementation for Tx side.
CVO(Coordination of Video Orientation) implemented for H264.
Support Coordination of Video Orientation (CVO) feature that carried in RTP Header extension.
it updates a device degrees(orientation) on RTP extension when device is rotated.
(6.2.3 of 3GPP Release 12 TS 26.114)
- rtp-param-ext-cvo-degrees: updates how much degress should be rotated.
- rtp-param-ext-cvo-extmap: updates what extmap CVO mapped in SDP negoration.
Merged-in: I49ab063d549b033aef06eadf39fd189384a5f724
Change-Id: I49ab063d549b033aef06eadf39fd189384a5f724
Signed-off-by: Byeongjo Park <bjo.park@samsung.com>
Signed-off-by: Kim Sungyeon <sy85.kim@samsung.com>
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 31238bc..4581889 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -117,6 +117,8 @@
mAudioSource((audio_source_t)AUDIO_SOURCE_CNT), // initialize with invalid value
mPrivacySensitive(PRIVACY_SENSITIVE_DEFAULT),
mVideoSource(VIDEO_SOURCE_LIST_END),
+ mRTPCVOExtMap(-1),
+ mRTPCVODegrees(0),
mStarted(false),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
mDeviceCallbackEnabled(false),
@@ -832,6 +834,26 @@
return OK;
}
+status_t StagefrightRecorder::setRTPCVOExtMap(int32_t extmap) {
+ ALOGV("setRtpCvoExtMap: %d", extmap);
+
+ mRTPCVOExtMap = extmap;
+ return OK;
+}
+
+status_t StagefrightRecorder::setRTPCVODegrees(int32_t cvoDegrees) {
+ Mutex::Autolock autolock(mLock);
+ ALOGV("setRtpCvoDegrees: %d", cvoDegrees);
+
+ mRTPCVODegrees = cvoDegrees;
+
+ if (mStarted && mOutputFormat == OUTPUT_FORMAT_RTP_AVP) {
+ mWriter->updateCVODegrees(mRTPCVODegrees);
+ }
+
+ return OK;
+}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -966,6 +988,16 @@
if (safe_strtoi32(value.string(), &payloadType)) {
return setParamPayloadType(payloadType);
}
+ } else if (key == "rtp-param-ext-cvo-extmap") {
+ int32_t extmap;
+ if (safe_strtoi32(value.string(), &extmap)) {
+ return setRTPCVOExtMap(extmap);
+ }
+ } else if (key == "rtp-param-ext-cvo-degrees") {
+ int32_t degrees;
+ if (safe_strtoi32(value.string(), °rees)) {
+ return setRTPCVODegrees(degrees);
+ }
} else {
ALOGE("setParameter: failed to find key %s", key.string());
}
@@ -1134,6 +1166,10 @@
meta->setInt64(kKeyTime, startTimeUs);
meta->setInt32(kKeySelfID, mSelfID);
meta->setInt32(kKeyPayloadType, mPayloadType);
+ if (mRTPCVOExtMap > 0) {
+ meta->setInt32(kKeyRtpExtMap, mRTPCVOExtMap);
+ meta->setInt32(kKeyRtpCvoDegrees, mRTPCVODegrees);
+ }
status = mWriter->start(meta.get());
break;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 99b0584..9114702 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -144,6 +144,8 @@
int32_t mRemotePort;
int32_t mSelfID;
int32_t mPayloadType;
+ int32_t mRTPCVOExtMap;
+ int32_t mRTPCVODegrees;
int64_t mDurationRecordedUs;
int64_t mStartedRecordingUs;
@@ -231,6 +233,8 @@
status_t setParamRtpRemotePort(int32_t remotePort);
status_t setParamSelfID(int32_t selfID);
status_t setParamPayloadType(int32_t payloadType);
+ status_t setRTPCVOExtMap(int32_t extmap);
+ status_t setRTPCVODegrees(int32_t cvoDegrees);
void clipVideoBitRate();
void clipVideoFrameRate();
void clipVideoFrameWidth();
diff --git a/media/libstagefright/include/media/stagefright/MediaWriter.h b/media/libstagefright/include/media/stagefright/MediaWriter.h
index 1f4fbcb..a71a474 100644
--- a/media/libstagefright/include/media/stagefright/MediaWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaWriter.h
@@ -54,7 +54,7 @@
virtual void setStartTimeOffsetMs(int /*ms*/) {}
virtual int32_t getStartTimeOffsetMs() const { return 0; }
virtual status_t setNextFd(int /*fd*/) { return INVALID_OPERATION; }
-
+ virtual void updateCVODegrees(int32_t /*cvoDegrees*/) {}
protected:
virtual ~MediaWriter() {}
int64_t mMaxFileSizeLimitBytes;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 53079cf..b0591b9 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -251,6 +251,8 @@
kKeyPps = 'sPps', // int32_t, indicates that a buffer is pps.
kKeySelfID = 'sfid', // int32_t, source ID to identify itself on RTP protocol.
kKeyPayloadType = 'pTyp', // int32_t, SDP negotiated payload type.
+ kKeyRtpExtMap = 'extm', // int32_t, rtp extension ID for cvo on RTP protocol.
+ kKeyRtpCvoDegrees = 'cvod', // int32_t, rtp cvo degrees as per 3GPP 26.114.
};
enum {
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 9111560..ce304e3 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -198,6 +198,8 @@
mLastRTPTime = 0;
mLastNTPTime = 0;
mNumSRsSent = 0;
+ mRTPCVOExtMap = -1;
+ mRTPCVODegrees = 0;
const char *mime;
CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
@@ -206,13 +208,18 @@
if(params->findInt32(kKeySelfID, &selfID))
mSourceID = selfID;
- if (mPayloadType == 0)
- mPayloadType = PT;
-
int32_t payloadType = 0;
if(params->findInt32(kKeyPayloadType, &payloadType))
mPayloadType = payloadType;
+ int32_t rtpExtMap = 0;
+ if(params->findInt32(kKeyRtpExtMap, &rtpExtMap))
+ mRTPCVOExtMap = rtpExtMap;
+
+ int32_t rtpCVODegrees = 0;
+ if(params->findInt32(kKeyRtpCvoDegrees, &rtpCVODegrees))
+ mRTPCVODegrees = rtpCVODegrees;
+
mMode = INVALID;
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
mMode = H264;
@@ -898,6 +905,8 @@
// The data fits into a single packet
uint8_t *data = buffer->data();
data[0] = 0x80;
+ if (mRTPCVOExtMap > 0)
+ data[0] |= 0x10;
if (isSpsPps)
data[1] = mPayloadType; // Marker bit should not be set in case of sps/pps
else
@@ -913,16 +922,51 @@
data[10] = (mSourceID >> 8) & 0xff;
data[11] = mSourceID & 0xff;
- memcpy(&data[12],
+ int rtpExtIndex = 0;
+ if (mRTPCVOExtMap > 0) {
+ /*
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xBE | 0xDE | length=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | ID | L=0 | data | ID | L=1 | data...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ...data | 0 (pad) | 0 (pad) | ID | L=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | data |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ In the one-byte header form of extensions, the 16-bit value required
+ by the RTP specification for a header extension, labeled in the RTP
+ specification as "defined by profile", takes the fixed bit pattern
+ 0xBEDE (the first version of this specification was written on the
+ feast day of the Venerable Bede).
+ */
+ data[12] = 0xBE;
+ data[13] = 0xDE;
+ // put a length of RTP Extension.
+ data[14] = 0x00;
+ data[15] = 0x01;
+ // put extmap of RTP assigned for CVO.
+ data[16] = (mRTPCVOExtMap << 4) | 0x0;
+ // put image degrees as per CVO specification.
+ data[17] = mRTPCVODegrees;
+ data[18] = 0x0;
+ data[19] = 0x0;
+ rtpExtIndex = 8;
+ }
+
+ memcpy(&data[12 + rtpExtIndex],
mediaData, mediaBuf->range_length());
- buffer->setRange(0, mediaBuf->range_length() + 12);
+ buffer->setRange(0, mediaBuf->range_length() + (12 + rtpExtIndex));
send(buffer, false /* isRTCP */);
++mSeqNo;
++mNumRTPSent;
- mNumRTPOctetsSent += buffer->size() - 12;
+ mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
} else {
// FU-A
@@ -942,6 +986,8 @@
uint8_t *data = buffer->data();
data[0] = 0x80;
+ if (lastPacket && mRTPCVOExtMap > 0)
+ data[0] |= 0x10;
data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType; // M-bit
data[2] = (mSeqNo >> 8) & 0xff;
data[3] = mSeqNo & 0xff;
@@ -954,24 +1000,37 @@
data[10] = (mSourceID >> 8) & 0xff;
data[11] = mSourceID & 0xff;
- data[12] = 28 | (nalType & 0xe0);
+ int rtpExtIndex = 0;
+ if (lastPacket && mRTPCVOExtMap > 0) {
+ data[12] = 0xBE;
+ data[13] = 0xDE;
+ data[14] = 0x00;
+ data[15] = 0x01;
+ data[16] = (mRTPCVOExtMap << 4) | 0x0;
+ data[17] = mRTPCVODegrees;
+ data[18] = 0x0;
+ data[19] = 0x0;
+ rtpExtIndex = 8;
+ }
+
+ data[12 + rtpExtIndex] = 28 | (nalType & 0xe0);
CHECK(!firstPacket || !lastPacket);
- data[13] =
+ data[13 + rtpExtIndex] =
(firstPacket ? 0x80 : 0x00)
| (lastPacket ? 0x40 : 0x00)
| (nalType & 0x1f);
- memcpy(&data[14], &mediaData[offset], size);
+ memcpy(&data[14 + rtpExtIndex], &mediaData[offset], size);
- buffer->setRange(0, 14 + size);
+ buffer->setRange(0, 14 + rtpExtIndex + size);
send(buffer, false /* isRTCP */);
++mSeqNo;
++mNumRTPSent;
- mNumRTPOctetsSent += buffer->size() - 12;
+ mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
firstPacket = false;
offset += size;
@@ -1044,6 +1103,11 @@
mLastNTPTime = GetNowNTP();
}
+void ARTPWriter::updateCVODegrees(int32_t cvoDegrees) {
+ Mutex::Autolock autoLock(mLock);
+ mRTPCVODegrees = cvoDegrees;
+}
+
static size_t getFrameSize(bool isWide, unsigned FT) {
static const size_t kFrameSizeNB[8] = {
95, 103, 118, 134, 148, 159, 204, 244
diff --git a/media/libstagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/ARTPWriter.h
index c2268e0..50922e4 100644
--- a/media/libstagefright/rtsp/ARTPWriter.h
+++ b/media/libstagefright/rtsp/ARTPWriter.h
@@ -44,6 +44,7 @@
virtual status_t start(MetaData *params);
virtual status_t stop();
virtual status_t pause();
+ void updateCVODegrees(int32_t cvoDegrees);
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -104,6 +105,8 @@
uint64_t mLastNTPTime;
int32_t mNumSRsSent;
+ int32_t mRTPCVOExtMap;
+ int32_t mRTPCVODegrees;
enum {
INVALID,