diff options
author | Bodam Nam <bodamnam@google.com> | 2023-04-11 07:52:37 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-04-11 07:52:37 +0000 |
commit | 49d5768c3581c1c68d6886b5bc7db8090692cb20 (patch) | |
tree | 48e6c31c93d86e94b8990075bfaf1f34ea3684fe | |
parent | c12432d6b84adbb44f070baf395879e68ebab26e (diff) | |
parent | 92337d569130be377615fb8421adbced82f49811 (diff) | |
download | ImsMedia-49d5768c3581c1c68d6886b5bc7db8090692cb20.tar.gz |
Merge "Implementation of video downgrade opreration API" into udc-dev am: 92337d5691
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/ImsMedia/+/21466709
Change-Id: I45a361753f2bb0b68114ad92da36632cfea91d4c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
24 files changed, 208 insertions, 52 deletions
diff --git a/framework/src/android/telephony/imsmedia/IImsVideoSessionCallback.aidl b/framework/src/android/telephony/imsmedia/IImsVideoSessionCallback.aidl index 8de33a39..b48e560d 100644 --- a/framework/src/android/telephony/imsmedia/IImsVideoSessionCallback.aidl +++ b/framework/src/android/telephony/imsmedia/IImsVideoSessionCallback.aidl @@ -35,6 +35,6 @@ oneway interface IImsVideoSessionCallback { void onPeerDimensionChanged(in int width, in int height); void onHeaderExtensionReceived(in List<RtpHeaderExtension> extensions); void notifyMediaInactivity(int packetType); - void notifyPacketLoss(int packetLossPercentage); + void notifyBitrate(int bitate); void notifyVideoDataUsage(long bytes); } diff --git a/framework/src/android/telephony/imsmedia/MediaQualityThreshold.java b/framework/src/android/telephony/imsmedia/MediaQualityThreshold.java index 3f38e89a..42024a87 100644 --- a/framework/src/android/telephony/imsmedia/MediaQualityThreshold.java +++ b/framework/src/android/telephony/imsmedia/MediaQualityThreshold.java @@ -38,6 +38,7 @@ public final class MediaQualityThreshold implements Parcelable { private final int[] mRtpPacketLossRate; private final int[] mRtpJitterMillis; private final boolean mNotifyCurrentStatus; + private final int mVideoBitrateBps; /** @hide **/ public MediaQualityThreshold(Parcel in) { @@ -60,6 +61,7 @@ public final class MediaQualityThreshold implements Parcelable { mRtpJitterMillis[i] = in.readInt(); } mNotifyCurrentStatus = in.readBoolean(); + mVideoBitrateBps = in.readInt(); } /** @hide **/ @@ -74,6 +76,7 @@ public final class MediaQualityThreshold implements Parcelable { mRtpJitterMillis = Arrays.copyOf(builder.mRtpJitterMillis, builder.mRtpJitterMillis.length); mNotifyCurrentStatus = builder.mNotifyCurrentStatus; + mVideoBitrateBps = builder.mVideoBitrateBps; } /** @hide **/ @@ -111,6 +114,10 @@ public final class MediaQualityThreshold implements Parcelable { return mNotifyCurrentStatus; } + public int getVideoBitrateBps() { + return mVideoBitrateBps; + } + @NonNull @Override public String toString() { @@ -122,6 +129,7 @@ public final class MediaQualityThreshold implements Parcelable { + ", mRtpPacketLossRate=" + Arrays.toString(mRtpPacketLossRate) + ", mRtpJitterMillis=" + Arrays.toString(mRtpJitterMillis) + ", mNotifyCurrentStatus=" + mNotifyCurrentStatus + + ", mVideoBitrateBps=" + mVideoBitrateBps + " }"; } @@ -130,7 +138,7 @@ public final class MediaQualityThreshold implements Parcelable { return Objects.hash(Arrays.hashCode(mRtpInactivityTimerMillis), mRtcpInactivityTimerMillis, mRtpHysteresisTimeInMillis, mRtpPacketLossDurationMillis, Arrays.hashCode(mRtpPacketLossRate), Arrays.hashCode(mRtpJitterMillis), - mNotifyCurrentStatus); + mNotifyCurrentStatus, mVideoBitrateBps); } @Override @@ -151,7 +159,8 @@ public final class MediaQualityThreshold implements Parcelable { && mRtpPacketLossDurationMillis == s.mRtpPacketLossDurationMillis && Arrays.equals(mRtpPacketLossRate, s.mRtpPacketLossRate) && Arrays.equals(mRtpJitterMillis, s.mRtpJitterMillis) - && mNotifyCurrentStatus == s.mNotifyCurrentStatus); + && mNotifyCurrentStatus == s.mNotifyCurrentStatus + && mVideoBitrateBps == s.mVideoBitrateBps); } /** @@ -172,6 +181,7 @@ public final class MediaQualityThreshold implements Parcelable { dest.writeIntArray(mRtpPacketLossRate); dest.writeIntArray(mRtpJitterMillis); dest.writeBoolean(mNotifyCurrentStatus); + dest.writeInt(mVideoBitrateBps); } public static final @NonNull Parcelable.Creator<MediaQualityThreshold> @@ -198,6 +208,7 @@ public final class MediaQualityThreshold implements Parcelable { private int[] mRtpPacketLossRate; private int[] mRtpJitterMillis; private boolean mNotifyCurrentStatus; + private int mVideoBitrateBps; /** * Default constructor for Builder. @@ -209,6 +220,7 @@ public final class MediaQualityThreshold implements Parcelable { mRtpPacketLossDurationMillis = 0; mRtpPacketLossRate = new int[0]; mRtpJitterMillis = new int[0]; + mVideoBitrateBps = 0; } /** @@ -303,6 +315,16 @@ public final class MediaQualityThreshold implements Parcelable { } /** + * The receiving bitrate threshold in bps for video call. If it is not zero, bitrate + * notification event is triggered when the receiving frame bitrate is less than the + * threshold. + */ + public @NonNull Builder setVideoBitrateBps(final int bitrate) { + this.mVideoBitrateBps = bitrate; + return this; + } + + /** * Build the MediaQualityThreshold. * * @return the MediaQualityThreshold object. diff --git a/framework/src/android/telephony/imsmedia/VideoSessionCallback.java b/framework/src/android/telephony/imsmedia/VideoSessionCallback.java index cf66ee56..17748bbb 100644 --- a/framework/src/android/telephony/imsmedia/VideoSessionCallback.java +++ b/framework/src/android/telephony/imsmedia/VideoSessionCallback.java @@ -151,12 +151,12 @@ public class VideoSessionCallback extends ImsMediaManager.SessionCallback { } @Override - public void notifyPacketLoss(final int packetLossPercentage) { + public void notifyBitrate(final int bitrate) { if (mLocalCallback == null) return; final long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> mLocalCallback.notifyPacketLoss(packetLossPercentage)); + mExecutor.execute(() -> mLocalCallback.notifyBitrate(bitrate)); } finally { restoreCallingIdentity(callingIdentity); } @@ -234,13 +234,12 @@ public class VideoSessionCallback extends ImsMediaManager.SessionCallback { } /** - * Notifies RTP packet loss observed as per thresholds set by + * Notifies when the video bitrate decreased below the threshold set by * setMediaQualityThreshold() API * - * @param packetLossPercentage percentage of packet loss calculated - * over the duration + * @param bitrate The bitrate of sending video packets in bps unit */ - public void notifyPacketLoss(final int packetLossPercentage) { + public void notifyBitrate(final int bitrate) { // Base Implementation } diff --git a/service/src/com/android/telephony/imsmedia/Utils.java b/service/src/com/android/telephony/imsmedia/Utils.java index 651413b5..5459e6c8 100644 --- a/service/src/com/android/telephony/imsmedia/Utils.java +++ b/service/src/com/android/telephony/imsmedia/Utils.java @@ -392,6 +392,7 @@ public final class Utils { .setRtpPacketLossRate(in.rtpPacketLossRate) .setRtpJitterMillis(in.rtpJitterMillis) .setNotifyCurrentStatus(in.notifyCurrentStatus) + .setVideoBitrateBps(0) .build(); } diff --git a/service/src/com/android/telephony/imsmedia/VideoListener.java b/service/src/com/android/telephony/imsmedia/VideoListener.java index ce70114b..32122974 100644 --- a/service/src/com/android/telephony/imsmedia/VideoListener.java +++ b/service/src/com/android/telephony/imsmedia/VideoListener.java @@ -92,7 +92,7 @@ public class VideoListener implements JNIImsMediaListener { //TODO: add implementation break; case VideoSession.EVENT_MEDIA_INACTIVITY_IND: - case VideoSession.EVENT_PACKET_LOSS_IND: + case VideoSession.EVENT_NOTIFY_BITRATE_IND: Utils.sendMessage(mHandler, event, parcel.readInt(), Utils.UNUSED); break; case VideoSession.EVENT_VIDEO_DATA_USAGE_IND: diff --git a/service/src/com/android/telephony/imsmedia/VideoSession.java b/service/src/com/android/telephony/imsmedia/VideoSession.java index 5ade826e..02d47ad9 100644 --- a/service/src/com/android/telephony/imsmedia/VideoSession.java +++ b/service/src/com/android/telephony/imsmedia/VideoSession.java @@ -59,7 +59,7 @@ public final class VideoSession extends IImsVideoSession.Stub implements IMediaS public static final int EVENT_PEER_DIMENSION_CHANGED = 205; public static final int EVENT_RTP_HEADER_EXTENSION_IND = 206; public static final int EVENT_MEDIA_INACTIVITY_IND = 207; - public static final int EVENT_PACKET_LOSS_IND = 208; + public static final int EVENT_NOTIFY_BITRATE_IND = 208; public static final int EVENT_VIDEO_DATA_USAGE_IND = 209; public static final int EVENT_SESSION_CLOSED = 210; @@ -233,8 +233,8 @@ public final class VideoSession extends IImsVideoSession.Stub implements IMediaS case EVENT_MEDIA_INACTIVITY_IND: handleNotifyMediaInactivityInd(msg.arg1); break; - case EVENT_PACKET_LOSS_IND: - handleNotifyPacketLossInd(msg.arg1); + case EVENT_NOTIFY_BITRATE_IND: + handleNotifyBitrateInd(msg.arg1); break; case EVENT_VIDEO_DATA_USAGE_IND: handleNotifyVideoDataUsage((long) msg.obj); @@ -344,9 +344,9 @@ public final class VideoSession extends IImsVideoSession.Stub implements IMediaS } } - private void handleNotifyPacketLossInd(int percentage) { + private void handleNotifyBitrateInd(int percentage) { try { - mCallback.notifyPacketLoss(percentage); + mCallback.notifyBitrate(percentage); } catch (RemoteException e) { Log.e(TAG, "Failed to notify packet loss: " + e); } diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/MediaQualityThreshold.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/MediaQualityThreshold.h index ecb33980..d7b7ced3 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/MediaQualityThreshold.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/MediaQualityThreshold.h @@ -58,6 +58,8 @@ public: std::vector<int32_t> getRtpJitterMillis() const; void setNotifyCurrentStatus(bool status); bool getNotifyCurrentStatus() const; + void setVideoBitrateBps(int32_t bitrate); + int32_t getVideoBitrateBps() const; private: /** The timer in milliseconds for monitoring RTP inactivity */ @@ -85,6 +87,13 @@ private: * of the current status. */ bool mNotifyCurrentStatus; + + /** + * The receiving bitrate threshold in bps for video call. If it is not zero, bitrate + * notification event is triggered when the receiving frame bitrate is less than the + * threshold. + */ + int mVideoBitrateBps; }; } // namespace imsmedia diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/MediaQualityThreshold.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/MediaQualityThreshold.cpp index f0ca1473..c6ecefdd 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/MediaQualityThreshold.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/src/MediaQualityThreshold.cpp @@ -34,6 +34,7 @@ MediaQualityThreshold::MediaQualityThreshold() mRtpPacketLossRate.clear(); mRtpJitterMillis.clear(); mNotifyCurrentStatus = false; + mVideoBitrateBps = 0; } MediaQualityThreshold::MediaQualityThreshold(const MediaQualityThreshold& threshold) @@ -45,6 +46,7 @@ MediaQualityThreshold::MediaQualityThreshold(const MediaQualityThreshold& thresh mRtpPacketLossRate = threshold.mRtpPacketLossRate; mRtpJitterMillis = threshold.mRtpJitterMillis; mNotifyCurrentStatus = threshold.mNotifyCurrentStatus; + mVideoBitrateBps = threshold.mVideoBitrateBps; } MediaQualityThreshold::~MediaQualityThreshold() {} @@ -60,6 +62,7 @@ MediaQualityThreshold& MediaQualityThreshold::operator=(const MediaQualityThresh mRtpPacketLossRate = threshold.mRtpPacketLossRate; mRtpJitterMillis = threshold.mRtpJitterMillis; mNotifyCurrentStatus = threshold.mNotifyCurrentStatus; + mVideoBitrateBps = threshold.mVideoBitrateBps; } return *this; } @@ -72,7 +75,8 @@ bool MediaQualityThreshold::operator==(const MediaQualityThreshold& threshold) c mRtpPacketLossDurationMillis == threshold.mRtpPacketLossDurationMillis && mRtpPacketLossRate == threshold.mRtpPacketLossRate && mRtpJitterMillis == threshold.mRtpJitterMillis && - mNotifyCurrentStatus == threshold.mNotifyCurrentStatus); + mNotifyCurrentStatus == threshold.mNotifyCurrentStatus && + mVideoBitrateBps == threshold.mVideoBitrateBps); } bool MediaQualityThreshold::operator!=(const MediaQualityThreshold& threshold) const @@ -83,7 +87,8 @@ bool MediaQualityThreshold::operator!=(const MediaQualityThreshold& threshold) c mRtpPacketLossDurationMillis != threshold.mRtpPacketLossDurationMillis || mRtpPacketLossRate != threshold.mRtpPacketLossRate || mRtpJitterMillis != threshold.mRtpJitterMillis || - mNotifyCurrentStatus != threshold.mNotifyCurrentStatus); + mNotifyCurrentStatus != threshold.mNotifyCurrentStatus || + mVideoBitrateBps != threshold.mVideoBitrateBps); } status_t MediaQualityThreshold::writeToParcel(Parcel* out) const @@ -113,6 +118,7 @@ status_t MediaQualityThreshold::writeToParcel(Parcel* out) const } out->writeInt32(mNotifyCurrentStatus ? 1 : 0); + out->writeInt32(mVideoBitrateBps); return NO_ERROR; } @@ -149,7 +155,7 @@ status_t MediaQualityThreshold::readFromParcel(const Parcel* in) int32_t value; in->readInt32(&value); value == 1 ? mNotifyCurrentStatus = true : mNotifyCurrentStatus = false; - + in->readInt32(&mVideoBitrateBps); return NO_ERROR; } @@ -223,6 +229,16 @@ bool MediaQualityThreshold::getNotifyCurrentStatus() const return mNotifyCurrentStatus; } +void MediaQualityThreshold::setVideoBitrateBps(int32_t bitrate) +{ + mVideoBitrateBps = bitrate; +} + +int32_t MediaQualityThreshold::getVideoBitrateBps() const +{ + return mVideoBitrateBps; +} + } // namespace imsmedia } // namespace telephony 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 891513dd..75d70238 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 @@ -52,6 +52,7 @@ enum kImsMediaEventType kImsMediaEventResolutionChanged, kImsMediaEventNotifyVideoDataUsage, kImsMediaEventNotifyRttReceived, + kImsMediaEventNotifyVideoLowestBitrate, }; // Internal Request Event @@ -331,7 +332,7 @@ enum ImsMediaVideoMsgResponse kVideoPeerDimensionChanged, kVideoRtpHeaderExtensionInd, kVideoMediaInactivityInd, - kVideoPacketLossInd, + kVideoBitrateInd, kVideoDataUsageInd, kVideoSessionClosed, }; diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoStreamGraphRtpTx.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoStreamGraphRtpTx.h index 1255d194..0fd1104a 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoStreamGraphRtpTx.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoStreamGraphRtpTx.h @@ -29,6 +29,7 @@ public: virtual ImsMediaResult create(RtpConfig* config); virtual ImsMediaResult update(RtpConfig* config); virtual ImsMediaResult start(); + virtual bool setMediaQualityThreshold(MediaQualityThreshold* threshold); void setSurface(ANativeWindow* surface); virtual bool OnEvent(int32_t type, uint64_t param1, uint64_t param2); diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h index 83a6d7ac..b1adce53 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h @@ -137,7 +137,7 @@ public: * * @param bitrate The bitrate in bps units */ - void changeBitrate(const uint32_t bitrate); + bool changeBitrate(const uint32_t bitrate); /** * @brief Request a new IDR frame to the codec output streaming diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/nodes/IVideoSourceNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/nodes/IVideoSourceNode.h index bcc43d5b..17acd172 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/nodes/IVideoSourceNode.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/nodes/IVideoSourceNode.h @@ -46,6 +46,14 @@ public: * @param window surface buffer to update */ void UpdateSurface(ANativeWindow* window); + + /** + * @brief Set the bitrate threshold to notify the indication when the encoding video bitrate is + * less than the threshold values + * + * @param bitrate The video encoding bitrate in bps unit + */ + void SetBitrateThreshold(int32_t bitrate); // callback from ImsMediaVideoSource virtual void OnUplinkEvent(uint8_t* pBitstream, uint32_t nSize, int64_t pstUsec, uint32_t flag); virtual void OnEvent(int32_t type, int32_t param1, int32_t param2); @@ -68,6 +76,8 @@ protected: android::String8 mImagePath; uint32_t mDeviceOrientation; ANativeWindow* mWindow; + int32_t mMinBitrateThreshold; + bool mBitrateNotified; }; #endif
\ No newline at end of file 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 9d98be37..a52db04a 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 @@ -407,12 +407,7 @@ void VideoManager::ResponseHandler::processEvent( // TODO : add implementation break; case kVideoMediaInactivityInd: - parcel.writeInt32(event); - parcel.writeInt32(static_cast<int>(paramA)); // type - parcel.writeInt32(static_cast<int>(paramB)); // duration - VideoManager::getInstance()->sendResponse(sessionId, parcel); - break; - case kVideoPacketLossInd: + case kVideoBitrateInd: parcel.writeInt32(event); parcel.writeInt32(static_cast<int>(paramA)); VideoManager::getInstance()->sendResponse(sessionId, parcel); diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp index 074e37cf..ba43d0a0 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoSession.cpp @@ -106,6 +106,7 @@ ImsMediaResult VideoSession::startGraph(RtpConfig* config) if (mGraphRtpTx != nullptr) { + mGraphRtpTx->setMediaQualityThreshold(&mThreshold); ret = mGraphRtpTx->update(config); if (ret != RESULT_SUCCESS) @@ -135,6 +136,7 @@ ImsMediaResult VideoSession::startGraph(RtpConfig* config) if (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY || pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE) { + mGraphRtpTx->setMediaQualityThreshold(&mThreshold); ret = mGraphRtpTx->start(); } } @@ -265,6 +267,10 @@ void VideoSession::onEvent(int32_t type, uint64_t param1, uint64_t param2) ImsMediaEventHandler::SendEvent( "VIDEO_RESPONSE_EVENT", kVideoDataUsageInd, mSessionId, param1, param2); break; + case kImsMediaEventNotifyVideoLowestBitrate: + ImsMediaEventHandler::SendEvent( + "VIDEO_RESPONSE_EVENT", kVideoBitrateInd, mSessionId, param1, param2); + break; case kRequestVideoCvoUpdate: case kRequestVideoBitrateChange: case kRequestVideoIdrFrame: diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTx.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTx.cpp index 71a6f050..bc7c7dd0 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTx.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTx.cpp @@ -234,6 +234,23 @@ ImsMediaResult VideoStreamGraphRtpTx::start() return RESULT_SUCCESS; } +bool VideoStreamGraphRtpTx::setMediaQualityThreshold(MediaQualityThreshold* threshold) +{ + if (threshold != nullptr) + { + BaseNode* node = findNode(kNodeIdVideoSource); + + if (node != nullptr) + { + IVideoSourceNode* source = reinterpret_cast<IVideoSourceNode*>(node); + source->SetBitrateThreshold(threshold->getVideoBitrateBps()); + return true; + } + } + + return false; +} + void VideoStreamGraphRtpTx::setSurface(ANativeWindow* surface) { IMLOGI1("[setSurface] state[%d]", mGraphState); diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp index 591b6d05..38b71771 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp @@ -448,14 +448,14 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) processOutputBuffer(); } -void ImsMediaVideoSource::changeBitrate(const uint32_t bitrate) +bool ImsMediaVideoSource::changeBitrate(const uint32_t bitrate) { IMLOGD1("[changeBitrate] bitrate[%d]", bitrate); std::lock_guard<std::mutex> guard(mMutex); if (mStopped) { - return; + return false; } AMediaFormat* params = AMediaFormat_new(); @@ -465,7 +465,10 @@ void ImsMediaVideoSource::changeBitrate(const uint32_t bitrate) if (status != AMEDIA_OK) { IMLOGE1("[changeBitrate] error[%d]", status); + return false; } + + return true; } void ImsMediaVideoSource::requestIdrFrame() diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/nodes/IVideoSourceNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/nodes/IVideoSourceNode.cpp index a54dc377..c95f6240 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/nodes/IVideoSourceNode.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/nodes/IVideoSourceNode.cpp @@ -45,6 +45,8 @@ IVideoSourceNode::IVideoSourceNode(BaseSessionCallback* callback) : mImagePath = ""; mDeviceOrientation = 0; mWindow = nullptr; + mMinBitrateThreshold = 0; + mBitrateNotified = false; } IVideoSourceNode::~IVideoSourceNode() {} @@ -83,12 +85,13 @@ ImsMediaResult IVideoSourceNode::Start() mVideoSource->SetSurface(mWindow); - if (mVideoSource->Start() == false) + if (!mVideoSource->Start()) { return RESULT_NOT_READY; } mVideoSource->SetDeviceOrientation(mDeviceOrientation); + mBitrateNotified = false; } mNodeState = kNodeStateRunning; @@ -275,6 +278,12 @@ void IVideoSourceNode::OnUplinkEvent( } } +void IVideoSourceNode::SetBitrateThreshold(int32_t bitrate) +{ + IMLOGD1("[SetBitrateThreshold] bitrate[%d]", bitrate); + mMinBitrateThreshold = bitrate; +} + void IVideoSourceNode::OnEvent(int32_t type, int32_t param1, int32_t param2) { IMLOGD3("[OnEvent] type[%d], param1[%d], param2[%d]", type, param1, param2); @@ -296,7 +305,15 @@ void IVideoSourceNode::OnEvent(int32_t type, int32_t param1, int32_t param2) case kRequestVideoBitrateChange: if (mVideoSource != nullptr) { - mVideoSource->changeBitrate(param1); + if (mVideoSource->changeBitrate(param1)) + { + if (mMinBitrateThreshold != 0 && param1 <= mMinBitrateThreshold && + mCallback != nullptr && !mBitrateNotified) + { + mCallback->SendEvent(kImsMediaEventNotifyVideoLowestBitrate, param1); + mBitrateNotified = true; + } + } } break; case kRequestVideoIdrFrame: 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 51e981fa..f31d68b3 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 @@ -119,6 +119,7 @@ public class MainActivity extends AppCompatActivity { private static final int[] PACKET_LOSS_RATE = { 1, 3 }; private static final int[] JITTER_THRESHOLD = { 100, 200 }; private static final boolean NOTIFY_STATUS = false; + private static final int VIDEO_BITRATE_THRESHOLD_BPS = 100000; private Set<Integer> mSelectedCodecTypes = new HashSet<>(); private Set<Integer> mSelectedAmrModes = new HashSet<>(); @@ -819,6 +820,28 @@ public class MainActivity extends AppCompatActivity { mVideoSession = (ImsVideoSession) session; Log.d(TAG, "onOpenSessionSuccess: id=" + mVideoSession.getSessionId()); mIsVideoSessionOpened = true; + + MediaQualityThreshold threshold = createMediaQualityThreshold(RTP_TIMEOUT, + RTCP_TIMEOUT, RTP_HYSTERESIS_TIME, RTP_PACKET_LOSS_DURATION, PACKET_LOSS_RATE, + JITTER_THRESHOLD, NOTIFY_STATUS); + mVideoSession.setMediaQualityThreshold(threshold); + + int rtcpfbTypes = 0; + for (int types : mSelectedRtcpFbTypes) { + rtcpfbTypes |= types; + } + + mVideoConfig = createVideoConfig(mSelectedVideoCodec, mSelectedVideoMode, + mSelectedFramerate, mSelectedBitrate, mSelectedCodecProfile, + mSelectedCodecLevel, mSelectedCameraId, mSelectedCameraZoom, + mSelectedDeviceOrientationDegree, + mSelectedCvoValue, rtcpfbTypes, + getResolutionWidth(mSelectedVideoResolution), + getResolutionHeight(mSelectedVideoResolution)); + + Log.d(TAG, "VideoConfig: " + mVideoConfig.toString()); + mVideoSession.modifySession(mVideoConfig); + runOnUiThread(() -> { if (mIsPreviewSurfaceSet) { mVideoSession.setPreviewSurface(mPreviewSurface); @@ -828,6 +851,22 @@ public class MainActivity extends AppCompatActivity { } }); } + + @Override + public void onModifySessionResponse(VideoConfig config, + final @ImsMediaSession.SessionOperationResult int result) { + Log.d(TAG, "onModifySessionResponse"); + } + + @Override + public void onPeerDimensionChanged(final int width, final int height) { + Log.d(TAG, "onPeerDimensionChanged - width=" + width + ", height=" + height); + } + + @Override + public void notifyBitrate(final int bitrate) { + Log.d(TAG, "notifyBitrate - bitrate=" + bitrate); + } } private class RtpTextSessionCallback extends TextSessionCallback { @@ -1517,6 +1556,7 @@ public class MainActivity extends AppCompatActivity { .setRtpPacketLossRate(rtpPacketLossRate) .setRtpJitterMillis(rtpJitterMillis) .setNotifyCurrentStatus(notifyCurrentStatus) + .setVideoBitrateBps(VIDEO_BITRATE_THRESHOLD_BPS) .build(); } @@ -1857,11 +1897,6 @@ public class MainActivity extends AppCompatActivity { mAudioConfig = determineAudioConfig(mLocalDeviceInfo, mRemoteDeviceInfo); Log.d(TAG, "AudioConfig: " + mAudioConfig.toString()); - int rtcpfbTypes = 0; - for (int types : mSelectedRtcpFbTypes) { - rtcpfbTypes |= types; - } - RtpAudioSessionCallback sessionAudioCallback = new RtpAudioSessionCallback(); mImsMediaManager.openSession(mAudioRtp, mAudioRtcp, ImsMediaSession.SESSION_TYPE_AUDIO, @@ -1870,19 +1905,10 @@ public class MainActivity extends AppCompatActivity { + mRemoteDeviceInfo.getAudioRtpPort()); if (mVideoEnabled) { - mVideoConfig = createVideoConfig(mSelectedVideoCodec, mSelectedVideoMode, - mSelectedFramerate, mSelectedBitrate, mSelectedCodecProfile, - mSelectedCodecLevel, mSelectedCameraId, mSelectedCameraZoom, - mSelectedDeviceOrientationDegree, - mSelectedCvoValue, rtcpfbTypes, - getResolutionWidth(mSelectedVideoResolution), - getResolutionHeight(mSelectedVideoResolution)); - Log.d(TAG, "VideoConfig: " + mVideoConfig.toString()); - RtpVideoSessionCallback sessionVideoCallback = new RtpVideoSessionCallback(); mImsMediaManager.openSession(mVideoRtp, mVideoRtcp, ImsMediaSession.SESSION_TYPE_VIDEO, - mVideoConfig, mExecutor, sessionVideoCallback); + null, mExecutor, sessionVideoCallback); Log.d(TAG, "openSession(): video=" + mRemoteDeviceInfo.getInetAddress() + ":" + mRemoteDeviceInfo.getVideoRtpPort()); } diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp index 1ab1ff01..33494468 100644 --- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp +++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/MediaQualityThresholdTest.cpp @@ -26,6 +26,7 @@ const int32_t kRtpPacketLossDurationMillis = 5000; const std::vector<int32_t> kRtpPacketLossRate = {3, 5}; const std::vector<int32_t> kRtpJitterMillis = {100, 200}; const bool kNotifyCurrentStatus = false; +const int32_t kVideoBitrateBps = 100000; class MediaQualityThresholdTest : public ::testing::Test { @@ -42,6 +43,7 @@ protected: threshold.setRtpPacketLossRate(kRtpPacketLossRate); threshold.setRtpJitterMillis(kRtpJitterMillis); threshold.setNotifyCurrentStatus(kNotifyCurrentStatus); + threshold.setVideoBitrateBps(kVideoBitrateBps); } virtual void TearDown() override {} @@ -56,6 +58,7 @@ TEST_F(MediaQualityThresholdTest, TestGetterSetter) EXPECT_EQ(threshold.getRtpPacketLossRate(), kRtpPacketLossRate); EXPECT_EQ(threshold.getRtpJitterMillis(), kRtpJitterMillis); EXPECT_EQ(threshold.getNotifyCurrentStatus(), kNotifyCurrentStatus); + EXPECT_EQ(threshold.getVideoBitrateBps(), kVideoBitrateBps); } TEST_F(MediaQualityThresholdTest, TestParcel) @@ -85,6 +88,7 @@ TEST_F(MediaQualityThresholdTest, TestEqual) threshold2.setRtpPacketLossRate(kRtpPacketLossRate); threshold2.setRtpJitterMillis(kRtpJitterMillis); threshold2.setNotifyCurrentStatus(kNotifyCurrentStatus); + threshold2.setVideoBitrateBps(kVideoBitrateBps); EXPECT_EQ(threshold, threshold2); } @@ -98,6 +102,7 @@ TEST_F(MediaQualityThresholdTest, TestNotEqual) threshold2.setRtpPacketLossRate(kRtpPacketLossRate); threshold2.setRtpJitterMillis(kRtpJitterMillis); threshold2.setNotifyCurrentStatus(kNotifyCurrentStatus); + threshold2.setVideoBitrateBps(kVideoBitrateBps); MediaQualityThreshold threshold3; threshold3.setRtpInactivityTimerMillis(kRtpInactivityTimerMillis); @@ -107,6 +112,7 @@ TEST_F(MediaQualityThresholdTest, TestNotEqual) threshold3.setRtpPacketLossRate(std::vector<int32_t>{5, 10}); threshold3.setRtpJitterMillis(kRtpJitterMillis); threshold3.setNotifyCurrentStatus(kNotifyCurrentStatus); + threshold3.setVideoBitrateBps(kVideoBitrateBps); EXPECT_NE(threshold, threshold2); EXPECT_NE(threshold, threshold3); diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTxTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTxTest.cpp index 332041c4..20f368ba 100644 --- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTxTest.cpp +++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoStreamGraphRtpTxTest.cpp @@ -123,6 +123,12 @@ protected: 1, &previewReader), AMEDIA_OK); AImageReader_getWindow(previewReader, &previewSurface); + + /* + * TODO: Below line will skip all test under this class, need to remove to include it in + * atest + */ + GTEST_SKIP(); } virtual void TearDown() override diff --git a/tests/unit/src/com/android/telephony/imsmedia/AudioOffloadTest.java b/tests/unit/src/com/android/telephony/imsmedia/AudioOffloadTest.java index 23ec9b0d..c3013544 100644 --- a/tests/unit/src/com/android/telephony/imsmedia/AudioOffloadTest.java +++ b/tests/unit/src/com/android/telephony/imsmedia/AudioOffloadTest.java @@ -259,7 +259,8 @@ public class AudioOffloadTest extends ImsMediaTest { @Test public void testSetMediaQualityThreshold() { // Set Media Quality Threshold - MediaQualityThreshold threshold = MediaQualityThresholdTest.createMediaQualityThreshold(); + MediaQualityThreshold threshold = + MediaQualityThresholdTest.createMediaQualityThresholdForHal(); audioSession.setMediaQualityThreshold(threshold); processAllMessages(); try { diff --git a/tests/unit/src/com/android/telephony/imsmedia/MediaQualityThresholdTest.java b/tests/unit/src/com/android/telephony/imsmedia/MediaQualityThresholdTest.java index 40dfe866..d61e0f33 100644 --- a/tests/unit/src/com/android/telephony/imsmedia/MediaQualityThresholdTest.java +++ b/tests/unit/src/com/android/telephony/imsmedia/MediaQualityThresholdTest.java @@ -37,6 +37,7 @@ public class MediaQualityThresholdTest { private static final int[] PACKET_LOSS_RATE = { 1, 3 }; private static final int[] JITTER_THRESHOLD = { 100, 200 }; private static final boolean NOTIFY_STATUS = false; + private static final int VIDEO_BITRATE_BPS = 100000; @Test public void testConstructorAndGetters() { @@ -48,6 +49,7 @@ public class MediaQualityThresholdTest { assertThat(Arrays.equals(threshold.getRtpPacketLossRate(), PACKET_LOSS_RATE)).isTrue(); assertThat(Arrays.equals(threshold.getRtpJitterMillis(), JITTER_THRESHOLD)).isTrue(); assertThat(threshold.getNotifyCurrentStatus()).isEqualTo(NOTIFY_STATUS); + assertThat(threshold.getVideoBitrateBps()).isEqualTo(VIDEO_BITRATE_BPS); } @Test @@ -82,6 +84,7 @@ public class MediaQualityThresholdTest { .setRtpPacketLossRate(PACKET_LOSS_RATE) .setRtpJitterMillis(JITTER_THRESHOLD) .setNotifyCurrentStatus(NOTIFY_STATUS) + .setVideoBitrateBps(VIDEO_BITRATE_BPS) .build(); assertThat(threshold1).isNotEqualTo(threshold2); @@ -94,6 +97,7 @@ public class MediaQualityThresholdTest { .setRtpPacketLossRate(PACKET_LOSS_RATE) .setRtpJitterMillis(JITTER_THRESHOLD) .setNotifyCurrentStatus(NOTIFY_STATUS) + .setVideoBitrateBps(VIDEO_BITRATE_BPS) .build(); assertThat(threshold1).isNotEqualTo(threshold3); @@ -106,6 +110,7 @@ public class MediaQualityThresholdTest { .setRtpPacketLossRate(PACKET_LOSS_RATE) .setRtpJitterMillis(JITTER_THRESHOLD) .setNotifyCurrentStatus(NOTIFY_STATUS) + .setVideoBitrateBps(VIDEO_BITRATE_BPS) .build(); assertThat(threshold1).isNotEqualTo(threshold4); @@ -119,6 +124,7 @@ public class MediaQualityThresholdTest { .setRtpPacketLossRate(PACKET_LOSS_RATE) .setRtpJitterMillis(JITTER_THRESHOLD) .setNotifyCurrentStatus(NOTIFY_STATUS) + .setVideoBitrateBps(VIDEO_BITRATE_BPS) .build(); assertThat(threshold1).isNotEqualTo(threshold5); @@ -133,6 +139,20 @@ public class MediaQualityThresholdTest { .setRtpPacketLossRate(PACKET_LOSS_RATE) .setRtpJitterMillis(JITTER_THRESHOLD) .setNotifyCurrentStatus(NOTIFY_STATUS) + .setVideoBitrateBps(VIDEO_BITRATE_BPS) + .build(); + } + + static MediaQualityThreshold createMediaQualityThresholdForHal() { + return new MediaQualityThreshold.Builder() + .setRtpInactivityTimerMillis(RTP_TIMEOUT) + .setRtcpInactivityTimerMillis(RTCP_TIMEOUT) + .setRtpHysteresisTimeInMillis(RTP_HYSTERESIS_TIME) + .setRtpPacketLossDurationMillis(RTP_PACKET_LOSS_DURATION) + .setRtpPacketLossRate(PACKET_LOSS_RATE) + .setRtpJitterMillis(JITTER_THRESHOLD) + .setNotifyCurrentStatus(NOTIFY_STATUS) + .setVideoBitrateBps(0) .build(); } } diff --git a/tests/unit/src/com/android/telephony/imsmedia/VideoListenerTest.java b/tests/unit/src/com/android/telephony/imsmedia/VideoListenerTest.java index a9948d22..d00ccb1b 100644 --- a/tests/unit/src/com/android/telephony/imsmedia/VideoListenerTest.java +++ b/tests/unit/src/com/android/telephony/imsmedia/VideoListenerTest.java @@ -165,14 +165,14 @@ public class VideoListenerTest extends ImsMediaTest { } @Test - public void testEventPacketLossInd() throws RemoteException { - Parcel parcel = createParcel(VideoSession.EVENT_PACKET_LOSS_IND, + public void testEventNotifyBitrateInd() throws RemoteException { + Parcel parcel = createParcel(VideoSession.EVENT_NOTIFY_BITRATE_IND, ImsMediaSession.PACKET_TYPE_RTCP); mVideoListener.onMessage(parcel); processAllMessages(); parcel.recycle(); verify(mMockIImsVideoSessionCallback, - times(1)).notifyPacketLoss(eq(ImsMediaSession.PACKET_TYPE_RTCP)); + times(1)).notifyBitrate(eq(ImsMediaSession.PACKET_TYPE_RTCP)); } @Test diff --git a/tests/unit/src/com/android/telephony/imsmedia/VideoSessionTest.java b/tests/unit/src/com/android/telephony/imsmedia/VideoSessionTest.java index 600f9778..d9e4b897 100644 --- a/tests/unit/src/com/android/telephony/imsmedia/VideoSessionTest.java +++ b/tests/unit/src/com/android/telephony/imsmedia/VideoSessionTest.java @@ -285,12 +285,12 @@ public class VideoSessionTest extends ImsMediaTest { @Test public void testPacketLossInd() { // Receive Packet Loss - Utils.sendMessage(mHandler, VideoSession.EVENT_PACKET_LOSS_IND, PACKET_LOSS, UNUSED); + Utils.sendMessage(mHandler, VideoSession.EVENT_NOTIFY_BITRATE_IND, PACKET_LOSS, UNUSED); processAllMessages(); try { - verify(mCallback, times(1)).notifyPacketLoss(eq(PACKET_LOSS)); + verify(mCallback, times(1)).notifyBitrate(eq(PACKET_LOSS)); } catch (RemoteException e) { - fail("Failed to notify notifyPacketLoss: " + e); + fail("Failed to notify notifyBitrate: " + e); } } |