summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbodamnam <bodamnam@google.com>2023-02-22 10:25:14 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-02-22 10:25:14 +0000
commitdf138e15d38f53901f2a79d9ebff24cafce034e5 (patch)
tree2995612be064e9ade68d8eaed067758a1b9d7396
parent042d9aac09e69904208833a6af8d31d977d611ef (diff)
parent0e6c7d339c5feac51992f7c5204ded40d873fd32 (diff)
downloadImsMedia-df138e15d38f53901f2a79d9ebff24cafce034e5.tar.gz
Implementation of RtpHeaderExtension am: 0e6c7d339c
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/ImsMedia/+/21515131 Change-Id: I578cc114a7bf924e4d12f6dbf63153e36d8a96aa Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--service/src/com/android/telephony/imsmedia/AudioListener.java13
-rw-r--r--service/src/com/android/telephony/imsmedia/AudioLocalSession.java10
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/RtpHeaderExtension.h71
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/VideoConfig.h4
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/RtpHeaderExtension.cpp199
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/IRtpSession.cpp56
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp79
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp17
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp10
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/IRtpSession.h11
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h78
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h3
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h8
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h8
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpDecoderNode.h9
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h12
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h1
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp156
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp108
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp4
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpService.h2
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpServiceTypes.h21
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/RtpService.cpp56
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacket.cpp24
-rw-r--r--test/app/ImsMediaTestingApp/app/src/main/java/com/example/imsmediatestingapp/MainActivity.java23
-rw-r--r--test/app/ImsMediaTestingApp/app/src/main/res/layout/activity_main.xml15
-rw-r--r--test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml2
-rw-r--r--test/imsmediahal/src/com/android/telephony/testimsmediahal/AudioListenerProxy.java9
-rw-r--r--test/imsmediahal/src/com/android/telephony/testimsmediahal/IImsMediaSessionImpl.java5
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/RtpHeaderExtensionTest.cpp100
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNodeTests.cpp62
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacketTest.cpp2
-rw-r--r--tests/unit/src/com/android/telephony/imsmedia/AudioListenerTest.java22
33 files changed, 1001 insertions, 199 deletions
diff --git a/service/src/com/android/telephony/imsmedia/AudioListener.java b/service/src/com/android/telephony/imsmedia/AudioListener.java
index 738f4083..f1afc46b 100644
--- a/service/src/com/android/telephony/imsmedia/AudioListener.java
+++ b/service/src/com/android/telephony/imsmedia/AudioListener.java
@@ -19,10 +19,14 @@ package com.android.telephony.imsmedia;
import android.os.Handler;
import android.os.Parcel;
import android.telephony.CallQuality;
+import android.telephony.ims.RtpHeaderExtension;
import android.telephony.imsmedia.AudioConfig;
import android.telephony.imsmedia.MediaQualityStatus;
import android.util.Log;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Audio listener to process JNI messages from local AP based RTP stack
*/
@@ -91,7 +95,14 @@ public class AudioListener implements JNIImsMediaListener {
}
break;
case AudioSession.EVENT_RTP_HEADER_EXTENSION_IND:
- Utils.sendMessage(mHandler, event);
+ {
+ final List<RtpHeaderExtension> extensions = new ArrayList<RtpHeaderExtension>();
+ final int listSize = parcel.readInt();
+ for (int i = 0; i < listSize; i++) {
+ extensions.add(RtpHeaderExtension.CREATOR.createFromParcel(parcel));
+ }
+ Utils.sendMessage(mHandler, event, extensions);
+ }
break;
case AudioSession.EVENT_MEDIA_QUALITY_STATUS_IND:
{
diff --git a/service/src/com/android/telephony/imsmedia/AudioLocalSession.java b/service/src/com/android/telephony/imsmedia/AudioLocalSession.java
index fc5f1927..2955f952 100644
--- a/service/src/com/android/telephony/imsmedia/AudioLocalSession.java
+++ b/service/src/com/android/telephony/imsmedia/AudioLocalSession.java
@@ -158,8 +158,14 @@ public class AudioLocalSession {
* @param extensions List of RTP header extensions to be transmitted
*/
public void sendHeaderExtension(final List<RtpHeaderExtension> extensions) {
- Log.d(TAG, "sendHeaderExtension");
- // TODO: add implementation
+ Log.d(TAG, "sendHeaderExtension, extension=" + extensions);
+ Parcel parcel = Parcel.obtain();
+ parcel.writeInt(AudioSession.CMD_SEND_RTP_HDR_EXTN);
+ parcel.writeInt(extensions.size());
+ for (RtpHeaderExtension item : extensions) {
+ item.writeToParcel(parcel, 0);
+ }
+ sendRequest(mSessionId, parcel);
}
/**
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/RtpHeaderExtension.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/RtpHeaderExtension.h
new file mode 100644
index 00000000..f3c52272
--- /dev/null
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/RtpHeaderExtension.h
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RTPEXTENSION_H
+#define RTPEXTENSION_H
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/Status.h>
+#include <stdint.h>
+
+namespace android
+{
+
+namespace telephony
+{
+
+namespace imsmedia
+{
+
+/** Native representation of android.telephony.imsmedia.RtpHeaderExtension */
+
+/**
+ * The class to encapsulate RTP header extension.
+ * Per RFC8285, an RTP header extension consists of both a local identifier in the range 1-14, an
+ * 8-bit length indicator and a number of extension data bytes equivalent to the stated length.
+ */
+class RtpHeaderExtension : public Parcelable
+{
+public:
+ RtpHeaderExtension();
+ RtpHeaderExtension(const RtpHeaderExtension& extension);
+ virtual ~RtpHeaderExtension();
+ RtpHeaderExtension& operator=(const RtpHeaderExtension& extension);
+ bool operator==(const RtpHeaderExtension& extension) const;
+ bool operator!=(const RtpHeaderExtension& extension) const;
+ virtual status_t writeToParcel(Parcel* parcel) const;
+ virtual status_t readFromParcel(const Parcel* in);
+ int32_t getLocalIdentifier();
+ void setLocalIdentifier(int32_t id);
+ uint8_t* getExtensionData() const;
+ void setExtensionData(const uint8_t* data, const int32_t size);
+ int32_t getExtensionDataSize();
+ void setExtensionDataSize(int32_t size);
+
+protected:
+ // The local identifier for this RTP header extension.
+ int32_t mLocalIdentifier;
+ // The data for this RTP header extension.
+ uint8_t* mExtensionData;
+ // The length of the mExtensionData
+ int32_t mExtensionDataSize;
+};
+} // namespace imsmedia
+} // namespace telephony
+} // namespace android
+
+#endif \ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/VideoConfig.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/VideoConfig.h
index eff588ff..8a6f1f57 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/VideoConfig.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/VideoConfig.h
@@ -252,8 +252,8 @@ protected:
int32_t deviceOrientationDegree;
/* The value to identify CVO RTP header extension features is enabled by the SDP negotiation.
* When the flag is set, MediaStack sends CVO RTP extension byte in the RTP header when the
- * sendHeaderExtension is invoked and the Video IDR frame is sent. if this value is -1,
- * CVO is disabled, and non zero means CVO enabled with specified offset. Check RFC 5285 */
+ * Video IDR frame is sent. if this value is -1, CVO is disabled, and non zero means CVO enabled
+ * with specified offset. Check RFC 5285 */
int32_t cvoValue;
/* The RTPFB, PSFB configuration with RTCP Protocol */
int32_t rtcpFbTypes;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/RtpHeaderExtension.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/RtpHeaderExtension.cpp
new file mode 100644
index 00000000..e65bd752
--- /dev/null
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/RtpHeaderExtension.cpp
@@ -0,0 +1,199 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <RtpHeaderExtension.h>
+
+namespace android
+{
+
+namespace telephony
+{
+
+namespace imsmedia
+{
+
+RtpHeaderExtension::RtpHeaderExtension() :
+ mLocalIdentifier(0),
+ mExtensionData(nullptr),
+ mExtensionDataSize(0)
+{
+}
+
+RtpHeaderExtension::RtpHeaderExtension(const RtpHeaderExtension& extension) :
+ mLocalIdentifier(extension.mLocalIdentifier),
+ mExtensionData(nullptr),
+ mExtensionDataSize(extension.mExtensionDataSize)
+{
+ if (mExtensionDataSize > 0)
+ {
+ mExtensionData = new uint8_t[mExtensionDataSize];
+ memcpy(mExtensionData, extension.mExtensionData, mExtensionDataSize);
+ }
+}
+
+RtpHeaderExtension::~RtpHeaderExtension()
+{
+ if (mExtensionData != nullptr)
+ {
+ delete[] mExtensionData;
+ mExtensionData = nullptr;
+ }
+}
+
+RtpHeaderExtension& RtpHeaderExtension::operator=(const RtpHeaderExtension& extension)
+{
+ if (this != &extension)
+ {
+ mLocalIdentifier = extension.mLocalIdentifier;
+ this->setExtensionData(extension.mExtensionData, extension.mExtensionDataSize);
+ }
+
+ return *this;
+}
+
+bool RtpHeaderExtension::operator==(const RtpHeaderExtension& extension) const
+{
+ return (mLocalIdentifier == extension.mLocalIdentifier &&
+ memcmp(mExtensionData, extension.mExtensionData, mExtensionDataSize) == 0);
+}
+
+bool RtpHeaderExtension::operator!=(const RtpHeaderExtension& extension) const
+{
+ return (mLocalIdentifier != extension.mLocalIdentifier ||
+ memcmp(mExtensionData, extension.mExtensionData, mExtensionDataSize) != 0);
+}
+
+status_t RtpHeaderExtension::writeToParcel(Parcel* parcel) const
+{
+ status_t err;
+
+ if (parcel == nullptr)
+ {
+ return BAD_VALUE;
+ }
+
+ err = parcel->writeInt32(mLocalIdentifier);
+
+ if (err != NO_ERROR)
+ {
+ return err;
+ }
+
+ err = parcel->writeInt32(mExtensionDataSize);
+
+ if (err != NO_ERROR)
+ {
+ return err;
+ }
+
+ void* dest = parcel->writeInplace(mExtensionDataSize);
+
+ if (dest == nullptr)
+ {
+ return NO_MEMORY;
+ }
+
+ memcpy(dest, mExtensionData, mExtensionDataSize);
+ return NO_ERROR;
+}
+
+status_t RtpHeaderExtension::readFromParcel(const Parcel* parcel)
+{
+ status_t err;
+
+ if (parcel == nullptr)
+ {
+ return BAD_VALUE;
+ }
+
+ err = parcel->readInt32(&mLocalIdentifier);
+
+ if (err != NO_ERROR)
+ {
+ return err;
+ }
+
+ err = parcel->readInt32(&mExtensionDataSize);
+
+ if (err != NO_ERROR)
+ {
+ return err;
+ }
+
+ if (mExtensionDataSize != 0)
+ {
+ if (mExtensionData != nullptr)
+ {
+ delete[] mExtensionData;
+ mExtensionData = nullptr;
+ }
+
+ mExtensionData = new uint8_t[mExtensionDataSize];
+ const void* data = parcel->readInplace(mExtensionDataSize);
+
+ if (data != nullptr)
+ {
+ memcpy(mExtensionData, data, mExtensionDataSize);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+int32_t RtpHeaderExtension::getLocalIdentifier()
+{
+ return mLocalIdentifier;
+}
+
+void RtpHeaderExtension::setLocalIdentifier(const int32_t id)
+{
+ mLocalIdentifier = id;
+}
+
+uint8_t* RtpHeaderExtension::getExtensionData() const
+{
+ return mExtensionData;
+}
+
+void RtpHeaderExtension::setExtensionData(const uint8_t* data, const int32_t size)
+{
+ if (mExtensionData != nullptr)
+ {
+ delete[] mExtensionData;
+ mExtensionData = nullptr;
+ mExtensionDataSize = 0;
+ }
+
+ if (data != nullptr)
+ {
+ mExtensionDataSize = size;
+ mExtensionData = new uint8_t[mExtensionDataSize];
+ memcpy(mExtensionData, data, mExtensionDataSize);
+ }
+}
+
+int32_t RtpHeaderExtension::getExtensionDataSize()
+{
+ return mExtensionDataSize;
+}
+void RtpHeaderExtension::setExtensionDataSize(int32_t size)
+{
+ mExtensionDataSize = size;
+}
+
+} // namespace imsmedia
+} // namespace telephony
+} // namespace android \ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/IRtpSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/IRtpSession.cpp
index f2a97fc4..11647e48 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/IRtpSession.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/IRtpSession.cpp
@@ -298,40 +298,40 @@ void IRtpSession::StopRtcp()
}
}
-bool IRtpSession::SendRtpPacket(uint32_t nPayloadType, uint8_t* pData, uint32_t nDataSize,
- uint32_t nTimestamp, bool bMark, uint32_t nTimeDiff, bool bExtension,
- tRtpHeaderExtensionInfo* pExtensionInfo)
+bool IRtpSession::SendRtpPacket(uint32_t payloadType, uint8_t* data, uint32_t dataSize,
+ uint32_t timestamp, bool mark, uint32_t timeDiff, RtpHeaderExtensionInfo* extensionInfo)
{
- tRtpSvc_SendRtpPacketParm stRtpPacketParam;
- memset(&stRtpPacketParam, 0, sizeof(tRtpSvc_SendRtpPacketParm));
+ tRtpSvc_SendRtpPacketParam stRtpPacketParam;
+ memset(&stRtpPacketParam, 0, sizeof(tRtpSvc_SendRtpPacketParam));
IMLOGD_PACKET5(IM_PACKET_LOG_RTP,
- "SendRtpPacket, payloadType[%u], size[%u], nTS[%u], bMark[%d], bExtension[%d]",
- nPayloadType, nDataSize, nTimestamp, bMark, bExtension);
- stRtpPacketParam.bMbit = bMark ? eRTP_TRUE : eRTP_FALSE;
- stRtpPacketParam.byPayLoadType = nPayloadType;
- stRtpPacketParam.diffFromLastRtpTimestamp = nTimeDiff;
- stRtpPacketParam.bXbit = bExtension ? eRTP_TRUE : eRTP_FALSE;
-
- if (bExtension && pExtensionInfo != nullptr)
+ "SendRtpPacket, payloadType[%u], size[%u], TS[%u], mark[%d], extension[%d]",
+ payloadType, dataSize, timestamp, mark, extensionInfo != nullptr);
+ stRtpPacketParam.bMbit = mark ? eRTP_TRUE : eRTP_FALSE;
+ stRtpPacketParam.byPayLoadType = payloadType;
+ stRtpPacketParam.diffFromLastRtpTimestamp = timeDiff;
+ stRtpPacketParam.bXbit = extensionInfo != nullptr ? eRTP_TRUE : eRTP_FALSE;
+
+ if (extensionInfo != nullptr)
{
- stRtpPacketParam.nDefinedByProfile = pExtensionInfo->nDefinedByProfile;
- stRtpPacketParam.nLength = pExtensionInfo->nLength;
- stRtpPacketParam.nExtensionData = pExtensionInfo->nExtensionData;
+ stRtpPacketParam.wDefinedByProfile = extensionInfo->definedByProfile;
+ stRtpPacketParam.wExtLen = extensionInfo->length;
+ stRtpPacketParam.pExtData = extensionInfo->extensionData;
+ stRtpPacketParam.nExtDataSize = extensionInfo->extensionDataSize;
}
- if (mPrevTimestamp == nTimestamp)
+ if (mPrevTimestamp == timestamp)
{
stRtpPacketParam.bUseLastTimestamp = eRTP_TRUE;
}
else
{
stRtpPacketParam.bUseLastTimestamp = eRTP_FALSE;
- mPrevTimestamp = nTimestamp;
+ mPrevTimestamp = timestamp;
}
mNumRtpDataToSend++;
IMS_RtpSvc_SendRtpPacket(
- this, mRtpSessionId, reinterpret_cast<char*>(pData), nDataSize, &stRtpPacketParam);
+ this, mRtpSessionId, reinterpret_cast<char*>(data), dataSize, &stRtpPacketParam);
return true;
}
@@ -421,26 +421,16 @@ void IRtpSession::OnPeerInd(tRtpSvc_IndicationFromStack type, void* pMsg)
{
tRtpSvcIndSt_ReceiveRtpInd* pstRtp =
reinterpret_cast<tRtpSvcIndSt_ReceiveRtpInd*>(pMsg);
- uint32_t nSSRC = 0;
-
- if (pstRtp->wMsgHdrLen >= 12)
- {
- nSSRC = pstRtp->pMsgHdr[8];
- nSSRC <<= 8;
- nSSRC += pstRtp->pMsgHdr[9];
- nSSRC <<= 8;
- nSSRC += pstRtp->pMsgHdr[10];
- nSSRC <<= 8;
- nSSRC += pstRtp->pMsgHdr[11];
- }
if ((mEnableDTMF == false || mRtpDtmfPayloadType != pstRtp->dwPayloadType) &&
pstRtp->dwPayloadType != 20)
{
+ RtpHeaderExtensionInfo extensionInfo(pstRtp->wDefinedByProfile, pstRtp->wExtLen,
+ reinterpret_cast<int8_t*>(pstRtp->pExtData), pstRtp->wExtDataSize);
+
mRtpDecoderListener->OnMediaDataInd(pstRtp->pMsgBody, pstRtp->wMsgBodyLen,
pstRtp->dwTimestamp, pstRtp->bMbit, pstRtp->dwSeqNum,
- pstRtp->dwPayloadType, nSSRC, pstRtp->bExtension,
- pstRtp->extensionData);
+ pstRtp->dwPayloadType, pstRtp->dwSsrc, extensionInfo);
}
}
break;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp
index 357a1d71..49efef54 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp
@@ -174,10 +174,20 @@ void AudioManager::sendDtmf(int sessionId, char dtmfDigit, int duration)
}
}
-/*void AudioManager::sendHeaderExtension(int sessionId, RtpHeaderExtension* data) {
- (void)sessionId;
- (void)data;
-}*/
+void AudioManager::sendRtpHeaderExtension(
+ int sessionId, std::list<RtpHeaderExtension>* listExtension)
+{
+ auto session = mSessions.find(sessionId);
+ IMLOGI1("[sendRtpHeaderExtension] sessionId[%d]", sessionId);
+ if (session != mSessions.end())
+ {
+ (session->second)->sendRtpHeaderExtension(listExtension);
+ }
+ else
+ {
+ IMLOGE1("[sendRtpHeaderExtension] no session id[%d]", sessionId);
+ }
+}
void AudioManager::setMediaQualityThreshold(int sessionId, MediaQualityThreshold* threshold)
{
@@ -225,7 +235,7 @@ void AudioManager::sendMessage(const int sessionId, const android::Parcel& parce
case kAudioDeleteConfig:
{
AudioConfig* config = new AudioConfig();
- config->readFromParcel(&parcel);
+ err = config->readFromParcel(&parcel);
if (err != NO_ERROR)
{
IMLOGE1("[sendMessage] error readFromParcel[%d]", err);
@@ -241,9 +251,25 @@ void AudioManager::sendMessage(const int sessionId, const android::Parcel& parce
"AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(param));
}
break;
- case kAudioSendHeaderExtension:
- // TO DO
- break;
+ case kAudioSendRtpHeaderExtension:
+ {
+ std::list<RtpHeaderExtension>* listExtension = new std::list<RtpHeaderExtension>();
+ int listSize = parcel.readInt32();
+
+ for (int32_t i = 0; i < listSize; i++)
+ {
+ RtpHeaderExtension extension;
+
+ if (extension.readFromParcel(&parcel) == NO_ERROR)
+ {
+ listExtension->push_back(extension);
+ }
+ }
+
+ ImsMediaEventHandler::SendEvent("AUDIO_REQUEST_EVENT", nMsg, sessionId,
+ reinterpret_cast<uint64_t>(listExtension));
+ }
+ break;
case kAudioSetMediaQualityThreshold:
{
MediaQualityThreshold* threshold = new MediaQualityThreshold();
@@ -377,9 +403,19 @@ void AudioManager::RequestHandler::processEvent(
}
}
break;
- case kAudioSendHeaderExtension:
- // TO DO : add implementation
- break;
+ case kAudioSendRtpHeaderExtension:
+ {
+ std::list<RtpHeaderExtension>* listExtension =
+ reinterpret_cast<std::list<RtpHeaderExtension>*>(paramA);
+
+ if (listExtension != nullptr)
+ {
+ AudioManager::getInstance()->sendRtpHeaderExtension(
+ static_cast<int>(sessionId), listExtension);
+ delete listExtension;
+ }
+ }
+ break;
case kAudioSetMediaQualityThreshold:
{
MediaQualityThreshold* threshold = reinterpret_cast<MediaQualityThreshold*>(paramA);
@@ -455,8 +491,25 @@ void AudioManager::ResponseHandler::processEvent(
}
break;
case kAudioRtpHeaderExtensionInd:
- // TODO : add implementation
- break;
+ {
+ parcel.writeInt32(event);
+ std::list<RtpHeaderExtension>* listExtension =
+ reinterpret_cast<std::list<RtpHeaderExtension>*>(paramA);
+
+ if (listExtension != nullptr)
+ {
+ parcel.writeInt32(listExtension->size());
+
+ for (auto& extension : *listExtension)
+ {
+ extension.writeToParcel(&parcel);
+ }
+
+ AudioManager::getInstance()->sendResponse(sessionId, parcel);
+ delete listExtension;
+ }
+ }
+ break;
case kAudioMediaQualityStatusInd:
{
parcel.writeInt32(event);
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
index e17112f6..5262cd15 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
@@ -478,8 +478,8 @@ void AudioSession::onEvent(int32_t type, uint64_t param1, uint64_t param2)
"AUDIO_RESPONSE_EVENT", kAudioFirstMediaPacketInd, mSessionId, param1, param2);
break;
case kImsMediaEventHeaderExtensionReceived:
- ImsMediaEventHandler::SendEvent(
- "AUDIO_RESPONSE_EVENT", kAudioRtpHeaderExtensionInd, 0, 0);
+ ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioRtpHeaderExtensionInd,
+ mSessionId, param1, param2);
break;
case kImsMediaEventMediaQualityStatus:
ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioMediaQualityStatusInd,
@@ -578,10 +578,19 @@ uint32_t AudioSession::getGraphSize(ImsMediaStreamType type)
return 0;
}
-void AudioSession::SendInternalEvent(int32_t type, uint64_t param1, uint64_t param2)
+void AudioSession::sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension)
{
- (void)param2;
+ for (auto& graph : mListGraphRtpTx)
+ {
+ if (graph != nullptr)
+ {
+ graph->sendRtpHeaderExtension(listExtension);
+ }
+ }
+}
+void AudioSession::SendInternalEvent(int32_t type, uint64_t param1, uint64_t param2)
+{
switch (type)
{
case kRequestAudioCmr:
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp
index 4a991320..ae8624a5 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp
@@ -244,3 +244,13 @@ void AudioStreamGraphRtpTx::processCmr(const uint32_t cmr)
(reinterpret_cast<IAudioSourceNode*>(node))->ProcessCmr(cmr);
}
}
+
+void AudioStreamGraphRtpTx::sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension)
+{
+ BaseNode* node = findNode(kNodeIdRtpEncoder);
+
+ if (node != nullptr)
+ {
+ (reinterpret_cast<RtpEncoderNode*>(node))->SetRtpHeaderExtension(listExtension);
+ }
+} \ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/IRtpSession.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/IRtpSession.h
index bb667867..3075dd4d 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/IRtpSession.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/IRtpSession.h
@@ -55,9 +55,9 @@ class IRtpDecoderListener
public:
IRtpDecoderListener() {}
virtual ~IRtpDecoderListener() {}
- virtual void OnMediaDataInd(unsigned char* pData, uint32_t nDataSize, uint32_t nTimestamp,
- bool bMark, uint16_t nSeqNum, uint32_t nPayloadType, uint32_t nSSRC, bool bExtension,
- uint16_t nExtensionData) = 0;
+ virtual void OnMediaDataInd(unsigned char* data, uint32_t dataSize, uint32_t timestamp,
+ bool mark, uint16_t seqNum, uint32_t payloadType, uint32_t ssrc,
+ const RtpHeaderExtensionInfo& extensionInfo) = 0;
virtual void OnNumReceivedPacket(uint32_t nNumRtpPacket) = 0;
};
@@ -103,9 +103,8 @@ public:
void StopRtp();
void StartRtcp(bool bSendRtcpBye = false);
void StopRtcp();
- bool SendRtpPacket(uint32_t nPayloadType, uint8_t* pData, uint32_t nDataSize,
- uint32_t timestamp, bool mark, uint32_t nTimeDiff, bool bExtension = false,
- tRtpHeaderExtensionInfo* pExtensionInfo = nullptr);
+ bool SendRtpPacket(uint32_t payloadType, uint8_t* data, uint32_t dataSize, uint32_t timestamp,
+ bool mark, uint32_t nTimeDiff, RtpHeaderExtensionInfo* extensionInfo = nullptr);
bool ProcRtpPacket(uint8_t* pData, uint32_t nDataSize);
bool ProcRtcpPacket(uint8_t* pData, uint32_t nDataSize);
void OnTimer();
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
index 9006f64d..a445059e 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
@@ -30,6 +30,7 @@
#define USHORT_TS_ROUND_COMPARE(a, b) \
(((a) >= (b) && (b) >= TS_ROUND_QUARD) || ((a) <= 0xffff - TS_ROUND_QUARD) || \
((a) <= TS_ROUND_QUARD && (b) >= 0xffff - TS_ROUND_QUARD))
+#define IMS_MEDIA_WORD_SIZE 4
using namespace android::telephony::imsmedia;
@@ -293,7 +294,7 @@ enum ImsMediaAudioMsgRequest
kAudioDeleteConfig,
kAudioConfirmConfig,
kAudioSendDtmf,
- kAudioSendHeaderExtension,
+ kAudioSendRtpHeaderExtension,
kAudioSetMediaQualityThreshold,
};
@@ -320,7 +321,7 @@ enum ImsMediaVideoMsgRequest
kVideoModifySession,
kVideoSetPreviewSurface,
kVideoSetDisplaySurface,
- kVideoSendHeaderExtension,
+ kVideoSendRtpHeaderExtension,
kVideoSetMediaQualityThreshold,
kVideoRequestDataUsage,
};
@@ -550,28 +551,77 @@ public:
uint32_t option;
};
-struct tRtpHeaderExtensionInfo
+struct RtpHeaderExtensionInfo
{
- uint16_t nDefinedByProfile;
- uint16_t nLength;
- uint16_t nExtensionData;
- tRtpHeaderExtensionInfo(uint16_t profile = 0, uint16_t length = 0, uint16_t data = 0)
+public:
+ enum
+ {
+ // RFC 8285#section-4.2, The bit pattern for one byte header
+ kBitPatternForOneByteHeader = 0xBEDE,
+ // RFC 8285#section-4.3, The bit pattern for two byte header
+ kBitPatternForTwoByteHeader = 0x1000,
+ };
+
+ uint16_t definedByProfile;
+ uint16_t length; // length in word unit
+ int8_t* extensionData;
+ uint16_t extensionDataSize;
+
+ RtpHeaderExtensionInfo(
+ uint16_t profile = 0, uint16_t len = 0, int8_t* data = nullptr, uint16_t size = 0)
+ {
+ definedByProfile = profile;
+ length = len;
+ extensionData = nullptr;
+ extensionDataSize = 0;
+ setExtensionData(data, size);
+ }
+
+ RtpHeaderExtensionInfo(const RtpHeaderExtensionInfo& extension)
{
- nDefinedByProfile = profile;
- nLength = length;
- nExtensionData = data;
+ definedByProfile = extension.definedByProfile;
+ extensionData = nullptr;
+ length = extension.length;
+ setExtensionData(extension.extensionData, extension.extensionDataSize);
}
- tRtpHeaderExtensionInfo& operator=(const tRtpHeaderExtensionInfo& extension)
+
+ ~RtpHeaderExtensionInfo()
+ {
+ if (extensionData != nullptr)
+ {
+ delete[] extensionData;
+ extensionData = nullptr;
+ }
+ }
+
+ RtpHeaderExtensionInfo& operator=(const RtpHeaderExtensionInfo& extension)
{
if (this != &extension)
{
- nDefinedByProfile = extension.nDefinedByProfile;
- nLength = extension.nLength;
- nExtensionData = extension.nExtensionData;
+ definedByProfile = extension.definedByProfile;
+ length = extension.length;
+ setExtensionData(extension.extensionData, extension.extensionDataSize);
}
return *this;
}
+
+ void setExtensionData(int8_t* data, uint16_t dataSize)
+ {
+ if (extensionData != nullptr)
+ {
+ delete[] extensionData;
+ extensionData = nullptr;
+ extensionDataSize = 0;
+ }
+
+ if (data != nullptr)
+ {
+ extensionDataSize = dataSize;
+ extensionData = new int8_t[extensionDataSize];
+ memcpy(extensionData, data, extensionDataSize);
+ }
+ }
};
#define MAX_IP_LEN 128
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h
index a7b69c63..231b4141 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioManager.h
@@ -23,6 +23,7 @@
#include <AudioSession.h>
#include <AudioConfig.h>
#include <MediaQualityThreshold.h>
+#include <RtpHeaderExtension.h>
#include <unordered_map>
using namespace std;
@@ -74,7 +75,7 @@ private:
ImsMediaResult deleteConfig(int sessionId, AudioConfig* config);
ImsMediaResult confirmConfig(int sessionId, AudioConfig* config);
void sendDtmf(int sessionId, char dtmfDigit, int duration);
- // void sendHeaderExtension(int sessionId, RtpHeaderExtension* data);
+ void sendRtpHeaderExtension(int sessionId, std::list<RtpHeaderExtension>* listExtension);
void setMediaQualityThreshold(int sessionId, MediaQualityThreshold* threshold);
static AudioManager* sManager;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h
index 10d8b916..ac29bfde 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h
@@ -24,6 +24,7 @@
#include <AudioStreamGraphRtcp.h>
#include <RtpConfig.h>
#include <MediaQualityAnalyzer.h>
+#include <RtpHeaderExtension.h>
#include <list>
class AudioSession : public BaseSession
@@ -103,6 +104,13 @@ public:
*/
uint32_t getGraphSize(ImsMediaStreamType type);
+ /**
+ * @brief Send rtp header extension to the audio rtp
+ *
+ * @param listExtension The list of rtp header extension data
+ */
+ void sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension);
+
private:
std::list<AudioStreamGraphRtpTx*> mListGraphRtpTx;
std::list<AudioStreamGraphRtpRx*> mListGraphRtpRx;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h
index 753774f1..0e9f00d6 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h
@@ -19,6 +19,7 @@
#include <ImsMediaDefine.h>
#include <AudioStreamGraph.h>
+#include <RtpHeaderExtension.h>
class AudioStreamGraphRtpTx : public AudioStreamGraph
{
@@ -57,6 +58,13 @@ public:
*/
void processCmr(const uint32_t cmr);
+ /**
+ * @brief Send rtp header extension to the audio rtp
+ *
+ * @param listExtension The list of rtp header extension data
+ */
+ void sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension);
+
private:
std::list<BaseNode*> mListDtmfNodes;
};
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpDecoderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpDecoderNode.h
index cf285891..efa933e6 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpDecoderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpDecoderNode.h
@@ -19,6 +19,7 @@
#include <BaseNode.h>
#include <IRtpSession.h>
+#include <RtpHeaderExtension.h>
// #define DEBUG_JITTER_GEN_SIMULATION_DELAY
// #define DEBUG_JITTER_GEN_SIMULATION_REORDER
@@ -46,9 +47,9 @@ public:
virtual void OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* pData, uint32_t nDataSize,
uint32_t timestamp, bool mark, uint32_t nSeqNum, ImsMediaSubType nDataType,
uint32_t arrivalTime = 0);
- virtual void OnMediaDataInd(unsigned char* pData, uint32_t nDataSize, uint32_t timestamp,
- bool mark, uint16_t nSeqNum, uint32_t nPayloadType, uint32_t nSSRC, bool bExtension,
- uint16_t nExtensionData);
+ virtual void OnMediaDataInd(unsigned char* data, uint32_t dataSize, uint32_t timestamp,
+ bool mark, uint16_t seqNum, uint32_t payloadType, uint32_t ssrc,
+ const RtpHeaderExtensionInfo& extensionInfo);
// IRtpDecoderListener
virtual void OnNumReceivedPacket(uint32_t nNumRtpPacket);
@@ -69,6 +70,8 @@ public:
private:
void processDtmf(uint8_t* data);
+ std::list<RtpHeaderExtension>* DecodeRtpHeaderExtension(
+ const RtpHeaderExtensionInfo& extensionInfo);
IRtpSession* mRtpSession;
RtpAddress mLocalAddress;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h
index 788f227e..54253073 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/RtpEncoderNode.h
@@ -19,6 +19,7 @@
#include <BaseNode.h>
#include <IRtpSession.h>
+#include <RtpHeaderExtension.h>
#include <mutex>
class RtpEncoderNode : public BaseNode, public IRtpEncoderListener
@@ -49,13 +50,18 @@ public:
/**
* @brief Set the camera facing and device orientation parameter for cvo extension in rtp header
+ *
+ * @param facing The facing of camera define in kCameraFacing in ImsMediaVideoUtil.h
+ * @param orientation The orientation value to send in degree unit
+ * @return true Return true when the extension data set properly
+ * @return false Return false when the cvo configuration is disabled
*/
bool SetCvoExtension(const int64_t facing, const int64_t orientation);
/**
- * @brief Set the rtp header extension parameter
+ * @brief Convert list of the RtpHeaderExtension to Rtp header extension payload
*/
- void SetRtpHeaderExtension(tRtpHeaderExtensionInfo& tExtension);
+ void SetRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension);
private:
bool ProcessAudioData(ImsMediaSubType subtype, uint8_t* pData, uint32_t nDataSize);
@@ -80,7 +86,7 @@ private:
int32_t mCvoValue;
int8_t mRedundantPayload;
int8_t mRedundantLevel;
- tRtpHeaderExtensionInfo mRtpExtension;
+ std::list<RtpHeaderExtensionInfo> mListRtpExtension;
};
#endif
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h
index 6095335c..7c780fd0 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoManager.h
@@ -98,7 +98,6 @@ private:
ImsMediaResult setPreviewSurfaceToSession(const int sessionId, ANativeWindow* surface);
ImsMediaResult setDisplaySurfaceToSession(const int sessionId, ANativeWindow* surface);
ImsMediaResult modifySession(const int sessionId, VideoConfig* config);
- // void sendHeaderExtension(int sessionId, RtpHeaderExtension* data);
void setMediaQualityThreshold(const int sessionId, MediaQualityThreshold* threshold);
static VideoManager* manager;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp
index 66e06141..a163d6ad 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNode.cpp
@@ -386,13 +386,14 @@ bool RtpDecoderNode::IsSameConfig(void* config)
}
void RtpDecoderNode::OnMediaDataInd(unsigned char* data, uint32_t datasize, uint32_t timestamp,
- bool mark, uint16_t seq, uint32_t payloadType, uint32_t ssrc, bool extension,
- uint16_t nExtensionData)
+ bool mark, uint16_t seq, uint32_t payloadType, uint32_t ssrc,
+ const RtpHeaderExtensionInfo& extensionInfo)
{
IMLOGD_PACKET8(IM_PACKET_LOG_RTP,
"[OnMediaDataInd] media[%d] size[%d], TS[%d], mark[%d], seq[%d], payloadType[%d] "
- "sampling[%d], ext[%d]",
- mMediaType, datasize, timestamp, mark, seq, payloadType, mSamplingRate, extension);
+ "sampling[%d], extensionSize[%d]",
+ mMediaType, datasize, timestamp, mark, seq, payloadType, mSamplingRate,
+ extensionInfo.length);
if (mMediaType == IMS_MEDIA_AUDIO && mRtpPayloadRx != payloadType &&
mRtpPayloadTx != payloadType && payloadType != mRtpRxDtmfPayload &&
@@ -423,46 +424,53 @@ void RtpDecoderNode::OnMediaDataInd(unsigned char* data, uint32_t datasize, uint
return;
}
- if (extension && mMediaType == IMS_MEDIA_VIDEO && mCvoValue != CVO_DEFINE_NONE)
+ if (extensionInfo.length > 0 && mMediaType == IMS_MEDIA_AUDIO)
{
- uint16_t nExtensionID;
- uint16_t nCamID;
- uint16_t nRotation;
- nExtensionID = nExtensionData;
- nExtensionID = nExtensionID >> 12;
+ std::list<RtpHeaderExtension>* extensions = DecodeRtpHeaderExtension(extensionInfo);
- nCamID = nExtensionData; // 0: Front-facing camera, 1: Back-facing camera
- nCamID = nCamID << 12;
- nCamID = nCamID >> 15;
+ if (mCallback != nullptr && extensions != nullptr)
+ {
+ mCallback->SendEvent(
+ kImsMediaEventHeaderExtensionReceived, reinterpret_cast<uint64_t>(extensions));
+ }
+ }
- nRotation = nExtensionData;
- nRotation = nRotation << 13;
- nRotation = nRotation >> 13;
+ if (extensionInfo.extensionData != nullptr && extensionInfo.extensionDataSize >= 2 &&
+ mMediaType == IMS_MEDIA_VIDEO && mCvoValue != CVO_DEFINE_NONE)
+ {
+ uint16_t extensionId = extensionInfo.extensionData[0] >> 4;
- switch (nRotation)
+ if (extensionId == mCvoValue)
{
- case 0: // No rotation (Rotated 0CW/CCW = To rotate 0CW/CCW)
- case 4: // + Horizontal Flip, but it's treated as same as above
- mSubtype = MEDIASUBTYPE_ROT0;
- break;
- case 1: // Rotated 270CW(90CCW) = To rotate 90CW(270CCW)
- case 5: // + Horizontal Flip, but it's treated as same as above
- mSubtype = MEDIASUBTYPE_ROT90;
- break;
- case 2: // Rotated 180CW = To rotate 180CW
- case 6: // + Horizontal Flip, but it's treated as same as above
- mSubtype = MEDIASUBTYPE_ROT180;
- break;
- case 3: // Rotated 90CW(270CCW) = To rotate 270CW(90CCW)
- case 7: // + Horizontal Flip, but it's treated as same as above
- mSubtype = MEDIASUBTYPE_ROT270;
- break;
- default:
- break;
- }
+ // 0: Front-facing camera, 1: Back-facing camera
+ uint16_t cameraId = extensionInfo.extensionData[1] >> 3;
+ uint16_t rotation = extensionInfo.extensionData[1] & 0x07;
- IMLOGD4("[OnMediaDataInd] extensionId[%d], camId[%d], rot[%d], subtype[%d]", nExtensionID,
- nCamID, nRotation, mSubtype);
+ switch (rotation)
+ {
+ case 0: // No rotation (Rotated 0CW/CCW = To rotate 0CW/CCW)
+ case 4: // + Horizontal Flip, but it's treated as same as above
+ mSubtype = MEDIASUBTYPE_ROT0;
+ break;
+ case 1: // Rotated 270CW(90CCW) = To rotate 90CW(270CCW)
+ case 5: // + Horizontal Flip, but it's treated as same as above
+ mSubtype = MEDIASUBTYPE_ROT90;
+ break;
+ case 2: // Rotated 180CW = To rotate 180CW
+ case 6: // + Horizontal Flip, but it's treated as same as above
+ mSubtype = MEDIASUBTYPE_ROT180;
+ break;
+ case 3: // Rotated 90CW(270CCW) = To rotate 270CW(90CCW)
+ case 7: // + Horizontal Flip, but it's treated as same as above
+ mSubtype = MEDIASUBTYPE_ROT270;
+ break;
+ default:
+ break;
+ }
+
+ IMLOGD4("[OnMediaDataInd] extensionId[%d], cameraId[%d], rotation[%d], subtype[%d]",
+ extensionId, cameraId, rotation, mSubtype);
+ }
}
if (mMediaType == IMS_MEDIA_TEXT)
@@ -564,4 +572,76 @@ void RtpDecoderNode::processDtmf(uint8_t* data)
// mark true when the new event started
mDtmfEndBit = true;
}
+}
+
+std::list<RtpHeaderExtension>* RtpDecoderNode::DecodeRtpHeaderExtension(
+ const RtpHeaderExtensionInfo& extensionInfo)
+{
+ if (extensionInfo.length == 0 || extensionInfo.extensionData == nullptr ||
+ extensionInfo.extensionDataSize == 0)
+ {
+ return nullptr;
+ }
+
+ std::list<RtpHeaderExtension>* extensions = new std::list<RtpHeaderExtension>();
+
+ // header
+ bool useTwoByteHeader =
+ (extensionInfo.definedByProfile == RtpHeaderExtensionInfo::kBitPatternForTwoByteHeader);
+ uint32_t length = extensionInfo.length; // word size
+ IMLOGD2("[DecodeRtpHeaderExtension] twoByteHeader[%d], len[%d]", useTwoByteHeader, length);
+
+ uint32_t offset = 0;
+ int32_t remainingSize = extensionInfo.extensionDataSize;
+
+ while (remainingSize > 0)
+ {
+ RtpHeaderExtension extension;
+
+ if (useTwoByteHeader)
+ {
+ // header
+ extension.setLocalIdentifier(extensionInfo.extensionData[offset++]);
+ int8_t dataSize = extensionInfo.extensionData[offset++]; // add header
+
+ // payload
+ if (dataSize > 0)
+ {
+ extension.setExtensionData(
+ reinterpret_cast<const uint8_t*>(extensionInfo.extensionData + offset),
+ dataSize);
+ }
+
+ offset += dataSize;
+ remainingSize -= (dataSize + 2); // remove two byte header too
+ }
+ else // one byte header
+ {
+ // header
+ extension.setLocalIdentifier(extensionInfo.extensionData[offset] >> 4);
+ int8_t dataSize = (extensionInfo.extensionData[offset] & 0x0F) + 1; // data + header
+ offset++;
+
+ // payload
+ if (dataSize > 0)
+ {
+ extension.setExtensionData(
+ reinterpret_cast<const uint8_t*>(extensionInfo.extensionData + offset),
+ dataSize);
+ }
+
+ offset += dataSize;
+ remainingSize -= (dataSize + 1); // remove one byte header too
+ }
+
+ extensions->push_back(extension);
+
+ while (remainingSize > 0 && extensionInfo.extensionData[offset] == 0x00) // ignore padding
+ {
+ offset++;
+ remainingSize--;
+ }
+ }
+
+ return extensions;
} \ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp
index d89d5bed..bcd35a6d 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpEncoderNode.cpp
@@ -328,24 +328,91 @@ bool RtpEncoderNode::SetCvoExtension(const int64_t facing, const int64_t orienta
}
}
- uint16_t extensionData;
+ int8_t extensionData[4]; // 32bit
IMLOGD3("[SetCvoExtension] cvoValue[%d], facing[%d], orientation[%d]", mCvoValue, cameraId,
rotation);
- extensionData = ((mCvoValue << 12) | (1 << 8)) | ((cameraId << 3) | rotation);
- mRtpExtension.nDefinedByProfile = 0xBEDE;
- mRtpExtension.nLength = 1;
- mRtpExtension.nExtensionData = extensionData;
+ extensionData[0] = (mCvoValue << 4) | 1; // local identifier and data length
+ extensionData[1] = (cameraId << 3) | rotation;
+ extensionData[2] = 0; // padding
+ extensionData[3] = 0; // padding
+ mListRtpExtension.push_back(RtpHeaderExtensionInfo(
+ RtpHeaderExtensionInfo::kBitPatternForOneByteHeader, 1, extensionData, 4));
return true;
}
return false;
}
-void RtpEncoderNode::SetRtpHeaderExtension(tRtpHeaderExtensionInfo& tExtension)
+void RtpEncoderNode::SetRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension)
{
- mRtpExtension = tExtension;
+ if (listExtension == nullptr || listExtension->empty())
+ {
+ return;
+ }
+
+ /**
+ * Check number of byte of the header. Based on RFC8285 4.2, one byte header has a local
+ * identifier in range of 1 to 14. Two byte header has is a range of 1 to 255.
+ */
+ bool useTwoByteHeader = false;
+ int32_t totalPayloadLength = 0; // accumulate payload length except the header size
+
+ for (auto extension : *listExtension)
+ {
+ if (extension.getLocalIdentifier() > 15)
+ {
+ useTwoByteHeader = true;
+ }
+
+ totalPayloadLength += extension.getExtensionDataSize();
+ }
+
+ // accumulate header size
+ useTwoByteHeader ? totalPayloadLength += 2 * listExtension->size()
+ : totalPayloadLength += listExtension->size();
+
+ // padding size
+ int32_t paddingSize = totalPayloadLength % IMS_MEDIA_WORD_SIZE == 0
+ ? 0
+ : IMS_MEDIA_WORD_SIZE - totalPayloadLength % IMS_MEDIA_WORD_SIZE;
+ totalPayloadLength += paddingSize;
+
+ int8_t* extensionData = new int8_t[totalPayloadLength];
+ int offset = 0;
+
+ for (auto extension : *listExtension)
+ {
+ if (useTwoByteHeader)
+ {
+ extensionData[offset++] = extension.getLocalIdentifier();
+ extensionData[offset++] = extension.getExtensionDataSize();
+ }
+ else
+ {
+ extensionData[offset++] =
+ extension.getLocalIdentifier() << 4 | (extension.getExtensionDataSize() - 1);
+ }
+
+ memcpy(extensionData + offset, extension.getExtensionData(),
+ extension.getExtensionDataSize());
+ offset += extension.getExtensionDataSize();
+ }
+
+ // add padding
+ memset(extensionData + offset, 0, paddingSize);
+
+ IMLOGD3("[SetRtpHeaderExtension] twoByte[%d], size[%d], list size[%d]", useTwoByteHeader,
+ totalPayloadLength, listExtension->size());
+
+ int16_t defineByProfile = useTwoByteHeader
+ ? RtpHeaderExtensionInfo::kBitPatternForTwoByteHeader
+ : RtpHeaderExtensionInfo::kBitPatternForOneByteHeader;
+ mListRtpExtension.push_back(RtpHeaderExtensionInfo(
+ defineByProfile, totalPayloadLength / 4, extensionData, totalPayloadLength));
+
+ delete[] extensionData;
}
bool RtpEncoderNode::ProcessAudioData(ImsMediaSubType subtype, uint8_t* data, uint32_t size)
@@ -431,8 +498,18 @@ bool RtpEncoderNode::ProcessAudioData(ImsMediaSubType subtype, uint8_t* data, ui
timestampDiff = timeDiff * mSamplingRate;
IMLOGD_PACKET3(IM_PACKET_LOG_RTP, "[ProcessAudioData] PayloadTx[%d], Size[%d], TS[%d]",
mRtpPayloadTx, size, currentTimestamp);
- mRtpSession->SendRtpPacket(
- mRtpPayloadTx, data, size, currentTimestamp, mMark, timestampDiff);
+
+ if (!mListRtpExtension.empty())
+ {
+ mRtpSession->SendRtpPacket(mRtpPayloadTx, data, size, currentTimestamp, mMark,
+ timestampDiff, &mListRtpExtension.front());
+ mListRtpExtension.pop_front();
+ }
+ else
+ {
+ mRtpSession->SendRtpPacket(
+ mRtpPayloadTx, data, size, currentTimestamp, mMark, timestampDiff);
+ }
if (mMark)
{
@@ -453,11 +530,11 @@ void RtpEncoderNode::ProcessVideoData(
if (mCvoValue > 0 && mark && subtype == MEDIASUBTYPE_VIDEO_IDR_FRAME)
{
mRtpSession->SendRtpPacket(
- mRtpPayloadTx, data, size, timestamp, mark, 0, true, &mRtpExtension);
+ mRtpPayloadTx, data, size, timestamp, mark, 0, &mListRtpExtension.front());
}
else
{
- mRtpSession->SendRtpPacket(mRtpPayloadTx, data, size, timestamp, mark, 0, false, nullptr);
+ mRtpSession->SendRtpPacket(mRtpPayloadTx, data, size, timestamp, mark, 0);
}
}
@@ -483,19 +560,16 @@ void RtpEncoderNode::ProcessTextData(
{
if (mRedundantLevel > 1 && mRedundantPayload > 0)
{
- mRtpSession->SendRtpPacket(
- mRedundantPayload, data, size, timestamp, mark, timeDiff, 0, nullptr);
+ mRtpSession->SendRtpPacket(mRedundantPayload, data, size, timestamp, mark, timeDiff);
}
else
{
- mRtpSession->SendRtpPacket(
- mRtpPayloadRx, data, size, timestamp, mark, timeDiff, 0, nullptr);
+ mRtpSession->SendRtpPacket(mRtpPayloadRx, data, size, timestamp, mark, timeDiff);
}
}
else if (subtype == MEDIASUBTYPE_BITSTREAM_T140_RED)
{
- mRtpSession->SendRtpPacket(
- mRtpPayloadTx, data, size, timestamp, mark, timeDiff, 0, nullptr);
+ mRtpSession->SendRtpPacket(mRtpPayloadTx, data, size, timestamp, mark, timeDiff);
}
mMark = false;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp
index bec6234f..9d98be37 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoManager.cpp
@@ -199,7 +199,7 @@ void VideoManager::sendMessage(const int sessionId, const android::Parcel& parce
"VIDEO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(config));
}
break;
- case kVideoSendHeaderExtension:
+ case kVideoSendRtpHeaderExtension:
// TO DO
break;
case kVideoSetMediaQualityThreshold:
@@ -321,7 +321,7 @@ void VideoManager::RequestHandler::processEvent(
"VIDEO_RESPONSE_EVENT", kVideoModifySessionResponse, sessionId, result, paramA);
}
break;
- case kVideoSendHeaderExtension:
+ case kVideoSendRtpHeaderExtension:
/** TODO: add implementation */
break;
case kVideoSetMediaQualityThreshold:
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpService.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpService.h
index f4b62bc7..bf5e0025 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpService.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpService.h
@@ -128,7 +128,7 @@ GLOBAL eRtp_Bool IMS_RtpSvc_DeleteSession(IN RTPSESSIONID hRtpSession);
*/
GLOBAL eRtp_Bool IMS_RtpSvc_SendRtpPacket(IN RtpServiceListener* pobjRtpServiceListener,
IN RTPSESSIONID hRtpSession, IN RtpDt_Char* pBuffer, IN RtpDt_UInt16 wBufferLength,
- IN tRtpSvc_SendRtpPacketParm* pstRtpParam);
+ IN tRtpSvc_SendRtpPacketParam* pstRtpParam);
/**
* This API processes the received RTP packet. Processed information is sent using
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpServiceTypes.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpServiceTypes.h
index ea3796be..9c4c119e 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpServiceTypes.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/interface/rtp/RtpServiceTypes.h
@@ -72,12 +72,13 @@ typedef struct
eRtp_Bool bUseLastTimestamp;
RtpDt_UInt32 diffFromLastRtpTimestamp;
- // [CVO] for extension header
+ // Rtp extension header
eRtp_Bool bXbit;
- RtpDt_UInt16 nDefinedByProfile;
- RtpDt_UInt16 nLength;
- RtpDt_UInt16 nExtensionData;
-} tRtpSvc_SendRtpPacketParm;
+ RtpDt_UInt16 wDefinedByProfile;
+ RtpDt_UInt16 wExtLen;
+ RtpDt_Int8* pExtData;
+ RtpDt_Int32 nExtDataSize;
+} tRtpSvc_SendRtpPacketParam;
/*
typedef struct
@@ -94,6 +95,7 @@ typedef struct
RtpDt_UInt32 dwTimestamp;
RtpDt_UInt32 dwPayloadType;
RtpDt_UInt16 dwSeqNum;
+ RtpDt_UInt32 dwSsrc;
RtpDt_UInt16 wMsgHdrLen;
RtpDt_UChar* pMsgHdr;
@@ -101,10 +103,11 @@ typedef struct
RtpDt_UInt16 wMsgBodyLen;
RtpDt_UChar* pMsgBody;
- /* [CVO] for RTP Header Extension, seokhwan.chung@, 2013.05.22 */
- RtpDt_UInt16 extensionData;
- eRtp_Bool bExtension;
-
+ /* RTP Header extension */
+ RtpDt_UInt16 wDefinedByProfile;
+ RtpDt_UInt16 wExtLen;
+ RtpDt_UChar* pExtData;
+ RtpDt_UInt16 wExtDataSize;
} tRtpSvcIndSt_ReceiveRtpInd;
typedef struct
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/RtpService.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/RtpService.cpp
index 0b502bc1..16599644 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/RtpService.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/RtpService.cpp
@@ -44,21 +44,29 @@ RtpDt_Void populateReceiveRtpIndInfo(
pstRtpIndMsg->dwTimestamp = pobjRtpHeader->getRtpTimestamp();
pstRtpIndMsg->dwPayloadType = pobjRtpHeader->getPayloadType();
pstRtpIndMsg->dwSeqNum = pobjRtpHeader->getSequenceNumber();
+ pstRtpIndMsg->dwSsrc = pobjRtpHeader->getRtpSsrc();
// Header length
pstRtpIndMsg->wMsgHdrLen = RTP_FIXED_HDR_LEN;
pstRtpIndMsg->wMsgHdrLen += RTP_WORD_SIZE * pobjRtpHeader->getCsrcCount();
+
if (pobjRtpPkt->getExtHeader())
{
pstRtpIndMsg->wMsgHdrLen += pobjRtpPkt->getExtHeader()->getLength();
- pstRtpIndMsg->bExtension = eRTP_TRUE;
- RtpDt_UChar* pbuf = pobjRtpPkt->getExtHeader()->getBuffer();
- pstRtpIndMsg->extensionData = ((((unsigned)*pbuf) << 8) & 0xff00) | ((pbuf[1] & 0x00ff));
+ RtpDt_UChar* pExtHdrBuffer = pobjRtpPkt->getExtHeader()->getBuffer();
+ RtpDt_Int32 uiByte4Data =
+ RtpOsUtil::Ntohl(*(reinterpret_cast<RtpDt_UInt32*>(pExtHdrBuffer)));
+ pstRtpIndMsg->wDefinedByProfile = uiByte4Data >> 16;
+ pstRtpIndMsg->wExtLen = uiByte4Data & 0x00FF;
+ pstRtpIndMsg->pExtData = pExtHdrBuffer + 4;
+ pstRtpIndMsg->wExtDataSize = pobjRtpPkt->getExtHeader()->getLength() - 4;
}
else
{
- pstRtpIndMsg->bExtension = eRTP_FALSE;
- pstRtpIndMsg->extensionData = 0;
+ pstRtpIndMsg->wDefinedByProfile = 0;
+ pstRtpIndMsg->wExtLen = 0;
+ pstRtpIndMsg->pExtData = nullptr;
+ pstRtpIndMsg->wExtDataSize = 0;
}
// End Header length
// play the payload
@@ -204,27 +212,33 @@ RtpDt_Void populateRtpProfile(OUT RtpStackProfile* pobjStackProfile)
pobjStackProfile->setTermNumber(RTP_CONF_SSRC_SEED);
}
-RtpBuffer* GetCVOXHdr(IN tRtpSvc_SendRtpPacketParm* pstRtpParam)
+RtpBuffer* SetRtpHeaderExtension(IN tRtpSvc_SendRtpPacketParam* pstRtpParam)
{
RtpBuffer* pobjXHdr = new RtpBuffer();
// HDR extension
if (pstRtpParam->bXbit)
{
- RtpDt_UChar* pBuf = new RtpDt_UChar[8];
- pBuf[0] = (((unsigned)pstRtpParam->nDefinedByProfile) >> 8) & 0x00ff;
- pBuf[1] = pstRtpParam->nDefinedByProfile & 0x00ff;
+ const RtpDt_Int32 headerSize = 4;
+ RtpDt_Int32 nBufferSize = headerSize + pstRtpParam->wExtLen * sizeof(int32_t);
+ RtpDt_UChar* pBuf = new RtpDt_UChar[nBufferSize];
- pBuf[2] = (((unsigned)pstRtpParam->nLength) >> 8) & 0x00ff;
- pBuf[3] = (pstRtpParam->nLength) & 0x00ff;
+ if (pstRtpParam->wExtLen * sizeof(int32_t) != pstRtpParam->nExtDataSize)
+ {
+ RTP_TRACE_WARNING("SetRtpHeaderExtension invalid data size len[%d], size[%d]",
+ pstRtpParam->wExtLen, pstRtpParam->nExtDataSize);
+ }
- pBuf[4] = (((unsigned)pstRtpParam->nExtensionData) >> 8) & 0x00ff;
- pBuf[5] = (pstRtpParam->nExtensionData) & 0x00ff;
+ // define by profile
+ pBuf[0] = (((unsigned)pstRtpParam->wDefinedByProfile) >> 8) & 0x00ff;
+ pBuf[1] = pstRtpParam->wDefinedByProfile & 0x00ff;
- pBuf[6] = 0;
- pBuf[7] = 0;
+ // number of the extension data set
+ pBuf[2] = (((unsigned)pstRtpParam->wExtLen) >> 8) & 0x00ff;
+ pBuf[3] = (pstRtpParam->wExtLen) & 0x00ff;
- pobjXHdr->setBufferInfo(8, pBuf);
+ memcpy(pBuf + 4, pstRtpParam->pExtData, pstRtpParam->nExtDataSize);
+ pobjXHdr->setBufferInfo(nBufferSize, pBuf);
}
else
{
@@ -234,7 +248,7 @@ RtpBuffer* GetCVOXHdr(IN tRtpSvc_SendRtpPacketParm* pstRtpParam)
return pobjXHdr;
}
-RtpDt_UInt16 GetCVOXHdrLen(eRtp_Bool bEnableCVO)
+RtpDt_UInt16 GetRtpHeaderExtensionSize(eRtp_Bool bEnableCVO)
{
if (bEnableCVO)
return RTP_CVO_XHDR_LEN;
@@ -351,7 +365,7 @@ GLOBAL eRtp_Bool IMS_RtpSvc_SetPayload(IN RTPSESSIONID hRtpSession,
}
eRTP_STATUS_CODE eInitSta =
- pobjRtpSession->setPayload(pobjlPayloadInfo, GetCVOXHdrLen(bEnableXHdr));
+ pobjRtpSession->setPayload(pobjlPayloadInfo, GetRtpHeaderExtensionSize(bEnableXHdr));
delete pobjlPayloadInfo;
if (eInitSta != RTP_SUCCESS)
{
@@ -392,7 +406,7 @@ GLOBAL eRtp_Bool IMS_RtpSvc_DeleteSession(IN RTPSESSIONID hRtpSession)
GLOBAL eRtp_Bool IMS_RtpSvc_SendRtpPacket(IN RtpServiceListener* pobjRtpServiceListener,
IN RTPSESSIONID hRtpSession, IN RtpDt_Char* pBuffer, IN RtpDt_UInt16 wBufferLength,
- IN tRtpSvc_SendRtpPacketParm* pstRtpParam)
+ IN tRtpSvc_SendRtpPacketParam* pstRtpParam)
{
RtpSession* pobjRtpSession = reinterpret_cast<RtpSession*>(hRtpSession);
@@ -425,6 +439,7 @@ GLOBAL eRtp_Bool IMS_RtpSvc_SendRtpPacket(IN RtpServiceListener* pobjRtpServiceL
// Create RTP packet
// 1. Set Marker bit
eRtp_Bool bMbit = eRTP_FALSE;
+
if (pstRtpParam->bMbit == eRTP_TRUE)
{
bMbit = eRTP_TRUE;
@@ -435,7 +450,7 @@ GLOBAL eRtp_Bool IMS_RtpSvc_SendRtpPacket(IN RtpServiceListener* pobjRtpServiceL
eRtp_Bool bUseLastTimestamp = pstRtpParam->bUseLastTimestamp ? eRTP_TRUE : eRTP_FALSE;
eRTP_STATUS_CODE eRtpCreateStat = pobjRtpSession->createRtpPacket(pobjRtpPayload, bMbit,
pstRtpParam->byPayLoadType, bUseLastTimestamp, pstRtpParam->diffFromLastRtpTimestamp,
- GetCVOXHdr(pstRtpParam), pobjRtpBuf);
+ SetRtpHeaderExtension(pstRtpParam), pobjRtpBuf);
// 3. de-init and free the temp variable both in success and failure case
pobjRtpPayload->setBufferInfo(RTP_ZERO, nullptr);
@@ -498,6 +513,7 @@ GLOBAL eRtp_Bool IMS_RtpSvc_ProcRtpPacket(IN RtpServiceListener* pvIRtpSession,
RtpBuffer objRtpBuf;
objRtpBuf.setBufferInfo(uiMsgLength, pMsg);
+
RtpDt_UInt32 uiTransLen = strlen(reinterpret_cast<const RtpDt_Char*>(pPeerIp));
RtpBuffer objRmtAddr;
objRmtAddr.setBufferInfo(uiTransLen + 1, reinterpret_cast<RtpDt_UChar*>(pPeerIp));
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacket.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacket.cpp
index 7ee0e408..23fa9378 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacket.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacket.cpp
@@ -149,34 +149,24 @@ eRtp_Bool RtpPacket::decodePacket(IN RtpBuffer* pobjRtpPktBuf)
// extension header
if (m_objRtpHeader.getExtension())
{
- RTP_TRACE_MESSAGE("[XHdr] Extension Header detected", 0, 0);
m_pobjExt = new RtpBuffer();
- if (m_pobjExt == nullptr)
- {
- return eRTP_FAILURE;
- }
// Get XHdr type and length
RtpDt_UInt32 uiByte4Data = RtpOsUtil::Ntohl(*(reinterpret_cast<RtpDt_UInt32*>(pcRtpBuf)));
- pcRtpBuf = pcRtpBuf + RTP_WORD_SIZE;
- uiRtpBufPos = uiRtpBufPos + RTP_WORD_SIZE;
- RtpDt_UInt16 uXHdrLen = (RtpDt_UInt16)(uiByte4Data & RTP_HEX_16_BIT_MAX);
- // RtpDt_UInt16 uXHdrType = (RtpDt_UInt16)(uiByte4Data >> RTP_SIXTEEN);
+ RtpDt_UInt16 uXHdrLen =
+ (RtpDt_UInt16)(uiByte4Data & RTP_HEX_16_BIT_MAX); // add header size
+
+ uXHdrLen += 1; // add a word for header type info
+ uXHdrLen *= RTP_WORD_SIZE; // convert word to byte
- uXHdrLen += RTP_WORD_SIZE - (uXHdrLen % RTP_WORD_SIZE); // word align
if ((uXHdrLen <= 0) || ((uiRtpBufPos + uXHdrLen) > uiRtpUtlBufLen))
{
- RTP_TRACE_ERROR("[XHdr]Invalid Header Extension.Xbit-1 but XHdr len <= 0 OR xhdr len "
- "> rtp buffer len",
- 0, 0);
+ RTP_TRACE_ERROR("[decodePacket] Invalid Header Extension len[%d]", uXHdrLen, 0);
return eRTP_FAILURE;
}
RtpDt_UChar* pRtpExtData = new RtpDt_UChar[uXHdrLen];
- if (pRtpExtData == nullptr)
- {
- return eRTP_FAILURE;
- }
+
memcpy(pRtpExtData, pcRtpBuf, uXHdrLen);
m_pobjExt->setBufferInfo(uXHdrLen, pRtpExtData);
diff --git a/test/app/ImsMediaTestingApp/app/src/main/java/com/example/imsmediatestingapp/MainActivity.java b/test/app/ImsMediaTestingApp/app/src/main/java/com/example/imsmediatestingapp/MainActivity.java
index e6800b57..f68076d5 100644
--- a/test/app/ImsMediaTestingApp/app/src/main/java/com/example/imsmediatestingapp/MainActivity.java
+++ b/test/app/ImsMediaTestingApp/app/src/main/java/com/example/imsmediatestingapp/MainActivity.java
@@ -17,6 +17,7 @@ import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CallQuality;
+import android.telephony.ims.RtpHeaderExtension;
import android.telephony.imsmedia.AmrParams;
import android.telephony.imsmedia.AudioConfig;
import android.telephony.imsmedia.AudioSessionCallback;
@@ -752,6 +753,12 @@ public class MainActivity extends AppCompatActivity {
}
@Override
+ public void onHeaderExtensionReceived(final List<RtpHeaderExtension> extensions) {
+ Log.d(TAG, "onHeaderExtensionReceived, list size=" + extensions.size()
+ + "list=" + extensions);
+ }
+
+ @Override
public void triggerAnbrQuery(AudioConfig config) {
Log.d(TAG, "triggerAnbrQuery");
}
@@ -2627,4 +2634,20 @@ public class MainActivity extends AppCompatActivity {
Log.d(TAG, e.toString());
}
}
+
+ public void sendHeaderExtension(View btn) {
+ if (mAudioSession != null) {
+ List<RtpHeaderExtension> extensions = new ArrayList<>();
+ byte[] testBytes1 = new byte[1];
+ byte[] testBytes2 = new byte[1];
+ testBytes1[0] = 5;
+ testBytes2[0] = 10;
+ RtpHeaderExtension extension1 = new RtpHeaderExtension(1, testBytes1);
+ RtpHeaderExtension extension2 = new RtpHeaderExtension(2, testBytes2);
+ extensions.add(extension1);
+ extensions.add(extension2);
+ Log.d(TAG, "[sendHeaderExtension] extension size=" + extensions.size());
+ mAudioSession.sendHeaderExtension(extensions);
+ }
+ }
}
diff --git a/test/app/ImsMediaTestingApp/app/src/main/res/layout/activity_main.xml b/test/app/ImsMediaTestingApp/app/src/main/res/layout/activity_main.xml
index 28189c98..fb2025a7 100644
--- a/test/app/ImsMediaTestingApp/app/src/main/res/layout/activity_main.xml
+++ b/test/app/ImsMediaTestingApp/app/src/main/res/layout/activity_main.xml
@@ -171,6 +171,7 @@
android:textColor="@color/black" />
<Button
+ android:id="@+id/getSpropButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
@@ -184,6 +185,20 @@
android:autoSizeTextType="uniform"
android:textColor="@color/black" />
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:layout_marginEnd="15dp"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@+id/getSpropButton"
+ android:backgroundTint="@drawable/selected_green"
+ android:enabled="true"
+ android:onClick="sendHeaderExtension"
+ android:text="@string/send_header_extension_button_text"
+ android:autoSizeTextType="uniform"
+ android:textColor="@color/black" />
+
<Spinner
android:id="@+id/spinnerAdditionalMedia"
android:layout_width="150dp"
diff --git a/test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml b/test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml
index efdc710c..37d6b5a7 100644
--- a/test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml
+++ b/test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml
@@ -40,6 +40,8 @@
<string name="connected_call_toast_text">Connected!</string>
<string name="connection_failed_toast_text">Connection failed!</string>
+ <!-- Send Header extension button text -->
+ <string name="send_header_extension_button_text">Send RtpHdrExt</string>
<!-- Settings page Strings -->
<string name="settings_remote_device_title">Remote Device</string>
diff --git a/test/imsmediahal/src/com/android/telephony/testimsmediahal/AudioListenerProxy.java b/test/imsmediahal/src/com/android/telephony/testimsmediahal/AudioListenerProxy.java
index 4917c3cc..2832c4d2 100644
--- a/test/imsmediahal/src/com/android/telephony/testimsmediahal/AudioListenerProxy.java
+++ b/test/imsmediahal/src/com/android/telephony/testimsmediahal/AudioListenerProxy.java
@@ -129,11 +129,14 @@ class AudioListenerProxy implements JNIImsMediaListener {
}
break;
case AudioSession.EVENT_RTP_HEADER_EXTENSION_IND:
- final List<RtpHeaderExtension> rtpHeaderExt = new ArrayList<RtpHeaderExtension>();
- parcel.readList(rtpHeaderExt, RtpHeaderExtension.class.getClassLoader());
+ final List<RtpHeaderExtension> extensions = new ArrayList<RtpHeaderExtension>();
+ final int listSize = parcel.readInt();
+ for (int i = 0; i < listSize; i++) {
+ extensions.add(RtpHeaderExtension.CREATOR.createFromParcel(parcel));
+ }
try {
- mMediaSessionListener.onHeaderExtensionReceived(rtpHeaderExt);
+ mMediaSessionListener.onHeaderExtensionReceived(extensions);
} catch(RemoteException e) {
Log.e(TAG, "Failed to notify rtp header extension: " + e);
}
diff --git a/test/imsmediahal/src/com/android/telephony/testimsmediahal/IImsMediaSessionImpl.java b/test/imsmediahal/src/com/android/telephony/testimsmediahal/IImsMediaSessionImpl.java
index 1ea35ad9..8d84c325 100644
--- a/test/imsmediahal/src/com/android/telephony/testimsmediahal/IImsMediaSessionImpl.java
+++ b/test/imsmediahal/src/com/android/telephony/testimsmediahal/IImsMediaSessionImpl.java
@@ -118,8 +118,9 @@ public class IImsMediaSessionImpl extends IImsMediaSession.Stub {
Log.d(TAG, "sendHeaderExtension: " + data);
Parcel parcel = Parcel.obtain();
parcel.writeInt(AudioSession.CMD_SEND_RTP_HDR_EXTN);
- if (data != null) {
- parcel.writeList(data);
+ parcel.writeInt(data.size());
+ for (RtpHeaderExtension item : data) {
+ item.writeToParcel(parcel, 0);
}
connector.sendRequest(mSessionId, parcel);
}
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/RtpHeaderExtensionTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/RtpHeaderExtensionTest.cpp
new file mode 100644
index 00000000..926e917f
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/RtpHeaderExtensionTest.cpp
@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <RtpHeaderExtension.h>
+#include <gtest/gtest.h>
+
+using namespace android::telephony::imsmedia;
+
+const int32_t kIdentifier = 15;
+const uint8_t kExtensionData[] = {0x01, 0x02};
+const int32_t kExtensionDataSize = 2;
+
+class RtpHeaderExtensionTest : public ::testing::Test
+{
+public:
+ RtpHeaderExtensionTest() { extension = nullptr; }
+ virtual ~RtpHeaderExtensionTest() {}
+
+protected:
+ RtpHeaderExtension* extension;
+
+ virtual void SetUp() override
+ {
+ extension = new RtpHeaderExtension();
+ extension->setExtensionData(kExtensionData, kExtensionDataSize);
+ extension->setLocalIdentifier(kIdentifier);
+ extension->setExtensionDataSize(kExtensionDataSize);
+ }
+
+ virtual void TearDown() override { delete extension; }
+};
+
+TEST_F(RtpHeaderExtensionTest, TestGetterSetter)
+{
+ EXPECT_EQ(memcmp(extension->getExtensionData(), kExtensionData, kExtensionDataSize), 0);
+ EXPECT_EQ(extension->getLocalIdentifier(), kIdentifier);
+ EXPECT_EQ(extension->getExtensionDataSize(), kExtensionDataSize);
+}
+
+TEST_F(RtpHeaderExtensionTest, TestParcel)
+{
+ android::Parcel parcel;
+ extension->writeToParcel(&parcel);
+ parcel.setDataPosition(0);
+
+ RtpHeaderExtension* extension2 = new RtpHeaderExtension();
+ extension2->readFromParcel(&parcel);
+ EXPECT_EQ(*extension2, *extension);
+ delete extension2;
+}
+
+TEST_F(RtpHeaderExtensionTest, TestAssign)
+{
+ RtpHeaderExtension extension2;
+ extension2 = *extension;
+ EXPECT_EQ(*extension, extension2);
+}
+
+TEST_F(RtpHeaderExtensionTest, TestEqual)
+{
+ RtpHeaderExtension* extension2 = new RtpHeaderExtension();
+ extension2->setExtensionData(kExtensionData, kExtensionDataSize);
+ extension2->setLocalIdentifier(kIdentifier);
+ extension2->setExtensionDataSize(kExtensionDataSize);
+ EXPECT_EQ(*extension, *extension2);
+ delete extension2;
+}
+
+TEST_F(RtpHeaderExtensionTest, TestNotEqual)
+{
+ RtpHeaderExtension* extension2 = new RtpHeaderExtension();
+ const uint8_t data[] = {0x03, 0x04};
+ extension2->setExtensionData(data, 2);
+ extension2->setLocalIdentifier(kIdentifier);
+ extension2->setExtensionDataSize(kExtensionDataSize);
+
+ RtpHeaderExtension* extension3 = new RtpHeaderExtension();
+ extension3->setExtensionData(kExtensionData, kExtensionDataSize);
+ extension3->setLocalIdentifier(9999);
+ extension3->setExtensionDataSize(kExtensionDataSize);
+
+ EXPECT_NE(*extension, *extension2);
+ EXPECT_NE(*extension, *extension3);
+
+ delete extension2;
+ delete extension3;
+} \ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNodeTests.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNodeTests.cpp
index dfa293e7..90c23056 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNodeTests.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtpDecoderNodeTests.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,8 +89,15 @@ public:
{
dtmfDigit = 0;
dtmfDuration = 0;
+ listExtensions = nullptr;
+ }
+ virtual ~FakeRtpDecoderCallback()
+ {
+ if (listExtensions != nullptr)
+ {
+ delete listExtensions;
+ }
}
- virtual ~FakeRtpDecoderCallback() {}
virtual void onEvent(int32_t type, uint64_t param1, uint64_t param2)
{
if (type == kAudioDtmfReceivedInd)
@@ -98,13 +105,24 @@ public:
dtmfDigit = static_cast<uint8_t>(param1);
dtmfDuration = static_cast<uint32_t>(param2);
}
+ else if (type == kImsMediaEventHeaderExtensionReceived)
+ {
+ if (listExtensions != nullptr)
+ {
+ delete listExtensions;
+ }
+
+ listExtensions = reinterpret_cast<std::list<RtpHeaderExtension>*>(param1);
+ }
}
uint8_t GetDtmfDigit() { return dtmfDigit; }
uint32_t GetDtmfDuration() { return dtmfDuration; }
+ std::list<RtpHeaderExtension>* GetListExtension() { return listExtensions; }
private:
uint8_t dtmfDigit;
uint32_t dtmfDuration;
+ std::list<RtpHeaderExtension>* listExtensions;
};
class FakeRtpDecoderNode : public BaseNode
@@ -370,6 +388,46 @@ TEST_F(RtpDecoderNodeTest, testAudioDtmfDataProcess)
EXPECT_EQ(callback.GetDtmfDuration(), 100);
}
+TEST_F(RtpDecoderNodeTest, testAudioRtpExtension)
+{
+ setupAudioConfig();
+ EXPECT_EQ(encoder->Start(), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->Start(), RESULT_SUCCESS);
+
+ // AMR mode 6 payload frame
+ uint8_t testFrame[] = {0x1c, 0x51, 0x06, 0x40, 0x32, 0xba, 0x8e, 0xc1, 0x25, 0x42, 0x2f, 0xc7,
+ 0xaf, 0x6e, 0xe0, 0xbb, 0xb2, 0x91, 0x09, 0xa5, 0xa6, 0x08, 0x18, 0x6f, 0x08, 0x1c,
+ 0x1c, 0x44, 0xd8, 0xe0, 0x48, 0x8c, 0x7c, 0xf8, 0x4c, 0x22, 0xd0};
+
+ const uint8_t testExtension1[] = {0xFF, 0xF2};
+ const uint8_t testExtension2[] = {0xFF, 0xF2};
+
+ std::list<RtpHeaderExtension> listExtension;
+
+ RtpHeaderExtension extension1;
+ extension1.setLocalIdentifier(1);
+ extension1.setExtensionData(testExtension1, 2);
+ listExtension.push_back(extension1);
+
+ RtpHeaderExtension extension2;
+ extension2.setLocalIdentifier(2);
+ extension2.setExtensionData(testExtension2, 2);
+ listExtension.push_back(extension2);
+
+ encoder->SetRtpHeaderExtension(&listExtension);
+ encoder->OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, testFrame, sizeof(testFrame), 0, false, 0);
+ encoder->ProcessData();
+
+ std::list<RtpHeaderExtension>* receivedExtension = callback.GetListExtension();
+ ASSERT_TRUE(receivedExtension != nullptr);
+
+ for (auto& extension : *receivedExtension)
+ {
+ EXPECT_EQ(extension, listExtension.front());
+ listExtension.pop_front();
+ }
+}
+
TEST_F(RtpDecoderNodeTest, startVideoAndUpdate)
{
setupVideoConfig();
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacketTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacketTest.cpp
index 17c758cb..319a2fe0 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacketTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/protocol/rtp/core/RtpPacketTest.cpp
@@ -90,7 +90,7 @@ TEST(RtpPacketTest, TestDecodePacket)
RtpBuffer* pobjRtpExtHdr = rtpPacket.getExtHeader();
ASSERT_TRUE(pobjRtpExtHdr != nullptr);
- uint8_t pRtpExtHdr[] = {0x41, 0x78, 0x42, 0x00};
+ uint8_t pRtpExtHdr[] = {0xbe, 0xde, 0x00, 0x01, 0x41, 0x78, 0x42, 0x00};
EXPECT_EQ(memcmp(pRtpExtHdr, pobjRtpExtHdr->getBuffer(), sizeof(pRtpExtHdr)), 0);
EXPECT_EQ(pobjRtpExtHdr->getLength(), sizeof(pRtpExtHdr));
diff --git a/tests/unit/src/com/android/telephony/imsmedia/AudioListenerTest.java b/tests/unit/src/com/android/telephony/imsmedia/AudioListenerTest.java
index a59a1646..353b6f7c 100644
--- a/tests/unit/src/com/android/telephony/imsmedia/AudioListenerTest.java
+++ b/tests/unit/src/com/android/telephony/imsmedia/AudioListenerTest.java
@@ -1,4 +1,4 @@
-/*
+/**
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
import android.os.Parcel;
import android.os.RemoteException;
import android.telephony.CallQuality;
+import android.telephony.ims.RtpHeaderExtension;
import android.telephony.imsmedia.AudioConfig;
import android.telephony.imsmedia.IImsAudioSessionCallback;
import android.telephony.imsmedia.ImsMediaSession;
@@ -39,6 +40,9 @@ import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(JUnit4.class)
public class AudioListenerTest {
private static final int SESSION_ID = 1;
@@ -160,11 +164,21 @@ public class AudioListenerTest {
@Test
public void testEventRtpHeaderExtensionInd() throws RemoteException {
- mAudioListener.onMessage(createParcel(AudioSession.EVENT_RTP_HEADER_EXTENSION_IND,
- SESSION_ID, mAudioConfig));
+ List<RtpHeaderExtension> extensions = new ArrayList<>();
+ extensions.add(new RtpHeaderExtension(1, new byte[]{5}));
+ extensions.add(new RtpHeaderExtension(2, new byte[]{10}));
+ Parcel parcel = Parcel.obtain();
+ parcel.writeInt(AudioSession.EVENT_RTP_HEADER_EXTENSION_IND);
+ parcel.writeInt(extensions.size());
+ for (RtpHeaderExtension item : extensions) {
+ item.writeToParcel(parcel, 0);
+ }
+ parcel.setDataPosition(0);
+ mAudioListener.onMessage(parcel);
+ parcel.recycle();
processAllMessages();
verify(mMockIImsAudioSessionCallback,
- times(1)).onHeaderExtensionReceived(any());
+ times(1)).onHeaderExtensionReceived(eq(extensions));
}
@Test