diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java index 91efb6654702ca8733f43ba558a3e6ae53299d5c..556a56f9c4c530a7486ed834376d8425224871c4 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java @@ -62,6 +62,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; +import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -74,6 +75,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.ProgressBar; import android.widget.TextView; @@ -116,6 +119,8 @@ import com.huawei.cloudphone.api.ICloudPhone; import java.util.HashMap; import java.util.List; +import java.util.Timer; +import java.util.TimerTask; public class CasCloudPhoneActivity extends FragmentActivity implements IHandleData { private static final String TAG = "CasCloudPhoneActivity"; @@ -164,9 +169,15 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa private boolean mIsStopCloudPhoneCalled = false; private ICloudPhone mCloudPhone; private TextView mNavigationTextView; + private TextView mStatisticsTextView; + + private CheckBox mStatisticsCheckBox; private boolean isReadyToExit; private Toast mToast; + private Timer mTimer = new Timer(); + + private Handler handler = new Handler() { @SuppressLint("RestrictedApi") @Override @@ -214,6 +225,10 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa } }; + public void onUpdateStatisticInfo(String string) { + mStatisticsTextView.setText(string); + } + /** * set screen long light */ @@ -244,6 +259,28 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa mFrameLayout = (FrameLayout) findViewById(R.id.frame_layout); mNavigationTextView = findViewById(R.id.cas_navigaiton); + mStatisticsTextView = findViewById(R.id.cas_statistic_view); + mStatisticsTextView.setTextColor(Color.GREEN); + + mStatisticsCheckBox = findViewById(R.id.cas_stats_checkBox); + mStatisticsCheckBox.setTextColor(Color.GREEN); + mStatisticsCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (isChecked) { + mStatisticsTextView.setVisibility(View.VISIBLE); + // 不加这句显示不出来,后续需要分析 + float density = getResources().getDisplayMetrics().density; + mStatisticsTextView.setHeight((int) (50 * density)); + } else { + mStatisticsTextView.setVisibility(View.INVISIBLE); + } + }); + mTimer.schedule(new TimerTask() { + @Override + public void run() { + runOnUiThread(() -> onUpdateStatisticInfo(mCloudPhone.getVideoStatisticInfo())); + } + }, 1000, 1000); // 1000 毫秒后执行,之后每隔 1000 毫秒执行一次 + mNavigationTextView.setOnTouchListener(new View.OnTouchListener() { @SuppressLint({"RestrictedApi", "ClickableViewAccessibility"}) @Override diff --git a/app/src/main/res/drawable/rounded_corner.xml b/app/src/main/res/drawable/rounded_corner.xml new file mode 100644 index 0000000000000000000000000000000000000000..57eef4f29c874a82d2e38d6d9cd59c3bb334271b --- /dev/null +++ b/app/src/main/res/drawable/rounded_corner.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/cas_activity_fullscreen.xml b/app/src/main/res/layout/cas_activity_fullscreen.xml index 50d47614d940212ac1ff458378fdaad3cd6ff891..7b8e58e603e471cf28a3ef95227043c8cf9d2e3a 100644 --- a/app/src/main/res/layout/cas_activity_fullscreen.xml +++ b/app/src/main/res/layout/cas_activity_fullscreen.xml @@ -11,13 +11,31 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/cas_black" - android:focusable="true"> + android:focusable="true"> + + - + + + #include #include +#include +#include "opus.h" #include "CasJniBridge.h" #include "CasController.h" #include "CasConf.h" #include "CasTcpSocket.h" #include "CasMsgCode.h" #include "CasExtVideoDataPipe.h" +#include "CasDecodeController.h" using namespace std; @@ -37,8 +40,10 @@ const std::string CLIENT_TYPE = "1"; int32_t OnRecvVideoStreamData(uint8_t* data, uint32_t length); int32_t OnRecvAudioStreamData(uint8_t* data, uint32_t length); +int32_t OnRecvAudioDecodeCallback(int32_t streamId, AudioJbDecode* audioJbDecode); int32_t OnRecvCmdData(uint8_t* data, uint32_t length); void OnNeedKeyFrameCallback(); +OpusDecoder *g_opusDecoder = nullptr; CasController *CasController::g_instance = nullptr; CasController *CasController::GetInstance() @@ -87,7 +92,9 @@ CasController::CasController() m_orientation = 0; m_frameType = FrameType::H264; m_rotationDegrees = 0; +#if MTRANS_ENABLED m_mtrans = nullptr; +#endif m_isMTransValid = false; } @@ -113,7 +120,9 @@ CasController::~CasController() m_touch = nullptr; cmdCallBack = nullptr; m_orientation = 0; +#if MTRANS_ENABLED m_mtrans = nullptr; +#endif m_isMTransValid = false; } @@ -437,10 +446,14 @@ bool CasController::CreateWorkers() OnRecvAudioStreamData, nullptr, OnNeedKeyFrameCallback, - nullptr); + nullptr, + OnRecvAudioDecodeCallback); } #endif + int err = 0; + g_opusDecoder = opus_decoder_create(48000, 2, &err); + return true; } @@ -1075,6 +1088,7 @@ void CasController::RecvdVideoData(uint8_t *data, int length) uint8_t *videoData = new uint8_t[length]; memcpy(videoData, data, length); m_videoPacketStream->Handle(videoData); + m_videoDataCount++; } m_isMTransValid = true; } @@ -1097,7 +1111,48 @@ int32_t OnRecvVideoStreamData(uint8_t* data, uint32_t length) int32_t OnRecvAudioStreamData(uint8_t* data, uint32_t length) { int headerLen = 36; - CasController::GetInstance()->RecvdAudioData(data + headerLen, length - headerLen); + INFO("PLCTest audio stream data size=%d", length); + + stream_msg_head_t msgHead; + msgHead.size = length; + msgHead.checksum = CAS_MSG_CHECKSUM_AUDIO; + msgHead.magicword = CAS_STREAM_DELIMITER_MAGICWORD; + msgHead.type = Audio; + msgHead.SetPayloadSize(length); + + size_t dataLen = sizeof(stream_msg_head_t) + length; + char *outBuffer = (char *)malloc(dataLen); + if (outBuffer == nullptr) { + ERR("Failed to malloc out buffer."); + return 0; + } + if (EOK != memcpy_s(outBuffer, dataLen, &msgHead, sizeof(stream_msg_head_t))) { + ERR("Copy msg head failed."); + free(outBuffer); + return 0; + } + if (EOK != memcpy_s(outBuffer + sizeof(stream_msg_head_t), dataLen - sizeof(stream_msg_head_t), data, length)) { + ERR("Copy msg data failed."); + free(outBuffer); + return 0; + } + + CasController::GetInstance()->RecvdAudioData(reinterpret_cast(outBuffer), dataLen); + return 0; +} + +int32_t OnRecvAudioDecodeCallback(int32_t streamId, AudioJbDecode* audioJbDecode) +{ + if (audioJbDecode->inputLength > 0) { + int opusSize = 240; + int pcmlen = opus_decode(g_opusDecoder, audioJbDecode->payload + 8, opusSize, audioJbDecode->outputData, 480, 0); + audioJbDecode->frameType = 1; + audioJbDecode->outputLength = pcmlen * 2; + } else { + int pcmLen = opus_decode(g_opusDecoder, audioJbDecode->payload, 0, audioJbDecode->outputData, 480, 1); + audioJbDecode->frameType = 1; + audioJbDecode->outputLength = pcmLen * 2; + } return 0; } @@ -1105,4 +1160,39 @@ void OnNeedKeyFrameCallback() { INFO("Need key frame callback.."); CasController::GetInstance()->NotifyCommand(CAS_REQUEST_CAMERA_KEY_FRAME, "camera need key frame"); +} + +std::string CasController::GetVideoRecvStats() { + std::string statsString; + std::stringstream stream; +#if MTRANS_ENABLED + if (m_mtrans != nullptr && m_isMTransValid) { + + int rtt = m_mtrans->GetRtt(); + stream << "网络时延 : "; + if (rtt != -1) { + stream << rtt << "ms"; + } + stream << std::endl; + + StreamRecvStats stats{}; + if (0 != m_mtrans->GetVideoRecvStats(&stats)) { + WARN("GetVideoRecvStats failed"); + } else { + stream << "下行视频丢包 : " << stats.lostRate << std::endl; + stream << "视频接收码率 : " << stats.recvBitrate << "kbps" << std::endl; + } + StreamRecvStats audioStats{}; + if (0 != m_mtrans->GetAudioRecvStats(&audioStats)) { + WARN("GetAudioRecvStats failed"); + } else { + stream << "音频接收码率 : " << audioStats.recvBitrate << "kbps" << std::endl; + } + } +#endif + stream << "帧率 : " << m_videoDataCount << "fps" << std::endl; + m_videoDataCount = 0; + + statsString = stream.str(); + return statsString; } \ No newline at end of file diff --git a/cloudphone/src/main/cpp/CasController.h b/cloudphone/src/main/cpp/CasController.h index 400c0e12468392d4fb2b73a09368304ad6564b97..f6607af7d9ac5d709302c82310b0b4b9fd93b2e6 100644 --- a/cloudphone/src/main/cpp/CasController.h +++ b/cloudphone/src/main/cpp/CasController.h @@ -85,6 +85,8 @@ public: void RecvdAudioData(uint8_t *data, int length); + std::string GetVideoRecvStats(); + private: bool Release(); @@ -177,6 +179,7 @@ private: int m_orientation = 0; int m_rotationDegrees = 0; bool m_isMTransValid = false; + int m_videoDataCount = 0; }; #endif // CLOUDAPPSDK_CASCONTROLLRT_H \ No newline at end of file diff --git a/cloudphone/src/main/cpp/CasJniBridge.cpp b/cloudphone/src/main/cpp/CasJniBridge.cpp index 939c953e78119bf7ee5ad4d0566acaa51b9bcfb8..3f803080d91b4d182e624b1fb8091ea98ca3c843 100644 --- a/cloudphone/src/main/cpp/CasJniBridge.cpp +++ b/cloudphone/src/main/cpp/CasJniBridge.cpp @@ -214,6 +214,12 @@ extern "C" JNIEXPORT jint JNICALL JNI(getLag)(JNIEnv *env, jclass) return lag; } +extern "C" JNIEXPORT jstring JNICALL JNI(getVideoStreamStats)(JNIEnv *env, jclass) +{ + string statsString = gJniApiCtrl->GetVideoRecvStats(); + return env->NewStringUTF(statsString.c_str()); +} + extern "C" JNIEXPORT void JNICALL JNI(setAssetsData)(JNIEnv *env, jclass, jstring jFilename, jbyteArray jData, jint length) { diff --git a/cloudphone/src/main/cpp/CasJniBridge.h b/cloudphone/src/main/cpp/CasJniBridge.h index 47a4c8d78b5e081bef95cf070e2e09c6e05125f7..2ea0713c604800c43a62f54e80d100a61c1dc0a9 100644 --- a/cloudphone/src/main/cpp/CasJniBridge.h +++ b/cloudphone/src/main/cpp/CasJniBridge.h @@ -51,5 +51,7 @@ JNIEXPORT jboolean JNICALL JNI(sendMotionEvent)(JNIEnv *env, jclass, jint master JNIEXPORT jboolean JNICALL JNI(setRotation)(JNIEnv *, jclass, int h); JNIEXPORT jboolean JNICALL JNI(getConnectStatus)(JNIEnv *env, jclass); + +JNIEXPORT jstring JNICALL JNI(getVideoStreamStats)(JNIEnv *env, jclass); } #endif // CLOUDAPPSDK_JNIRENDER_H \ No newline at end of file diff --git a/cloudphone/src/main/cpp/libs/Arm64/libmtrans.a b/cloudphone/src/main/cpp/libs/Arm64/libmtrans.a index 4410512a4914f657f2fa4035c68fc872cd122a3f..e348b4fdad61de87f14a3572294c688b2fbf12f8 100644 Binary files a/cloudphone/src/main/cpp/libs/Arm64/libmtrans.a and b/cloudphone/src/main/cpp/libs/Arm64/libmtrans.a differ diff --git a/cloudphone/src/main/cpp/libs/mtrans/include/net_trans.h b/cloudphone/src/main/cpp/libs/mtrans/include/net_trans.h index 5b3c0b6bf20b2accafc6a5f0e4d4c29d637e4555..1b0c7ad4bd44eb4c7210bd10c05865154a2f8960 100644 --- a/cloudphone/src/main/cpp/libs/mtrans/include/net_trans.h +++ b/cloudphone/src/main/cpp/libs/mtrans/include/net_trans.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef HUAWEICLOUD_CLOUDPHONEACCESS_ENGINE_NET_TRANS_H -#define HUAWEICLOUD_CLOUDPHONEACCESS_ENGINE_NET_TRANS_H +#ifndef UDP_TRANS_NET_TRANS_H +#define UDP_TRANS_NET_TRANS_H #include #include @@ -23,7 +23,7 @@ class NetTrans { public: NetTrans(); - virtual ~NetTrans(); + void EnableLog(const std::string& logPath, NET_TRANS_LOG_LEVEL logLevel); int Init(NET_TRANS_PEER_TYPE peerType, char const *ip, int port, @@ -32,7 +32,10 @@ public: RecvAudioDataCallback audioCallback, UpdataBitrateCallback bitrateCallback, RequestKeyFrameCallback keyFrameCallback, - RecvCmdDataCallback cmdCallback); + RecvCmdDataCallback cmdCallback, + RecvAudioDecodeCallback audioDecodeCallback); + + virtual ~NetTrans(); int Start(); int Stop(); @@ -40,10 +43,13 @@ public: int SendVideoData(uint8_t *data, int len, std::string encodeType); int SendAudioData(uint8_t *data, int len); int SendCmdData(uint8_t *data, int len); + int GetVideoRecvStats(StreamRecvStats* stats); + int GetAudioRecvStats(StreamRecvStats* stats); + int GetRtt(); private: class NetTransPri; class NetTransPri *m_netTransPri; }; -#endif //HUAWEICLOUD_CLOUDPHONEACCESS_ENGINE_NET_TRANS_H +#endif //UDP_TRANS_NET_TRANS_H diff --git a/cloudphone/src/main/cpp/libs/mtrans/include/net_trans_def.h b/cloudphone/src/main/cpp/libs/mtrans/include/net_trans_def.h index dc8903ba5ef9a5f0fe6a75e2bb9debc3949a45e0..737e668828abfc9da61a9a58a5dc67b7e9b94110 100644 --- a/cloudphone/src/main/cpp/libs/mtrans/include/net_trans_def.h +++ b/cloudphone/src/main/cpp/libs/mtrans/include/net_trans_def.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef HUAWEICLOUD_CLOUDPHONEACCESS_ENGINE_NET_TRANS_DEF_H -#define HUAWEICLOUD_CLOUDPHONEACCESS_ENGINE_NET_TRANS_DEF_H +#ifndef UDP_TRANS_NET_TRANS_DEF_H +#define UDP_TRANS_NET_TRANS_DEF_H enum NET_TRANS_PEER_TYPE { PEER_CLIENT, @@ -27,10 +27,75 @@ struct TransConfigParam { uint32_t maxVideoSendBitrate; }; +enum NET_TRANS_LOG_LEVEL { + LOG_LEVEL_OFF, + LOG_LEVEL_ERROR, + LOG_LEVEL_WARN, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG +}; + +struct AudioJbDecode { + int32_t bfi; + uint8_t* payload; + uint32_t inputLength; + int16_t* outputData; + uint32_t outputLength; + uint32_t outputBufSize; + int32_t frameType; + uint32_t metaDataOffset; +}; + +struct VideoRecvStats { + uint32_t recvFrameRate; + uint32_t redRate; + uint32_t recoverRate; + uint32_t jbListpacketNum; + uint32_t sendKeyRequestCnt; + int32_t jbJitter; + uint32_t refFrameErrorCnt; + uint64_t aveJbDelayAfterBuild; + uint64_t recvAveDelay; + uint64_t recvMaxDelay; +}; + +struct AudioRecvStats { + uint32_t receiveTotalTime; + uint32_t plcCount; + uint32_t tsmCompressCount; + uint32_t tsmStretchCount; + int32_t totalDelay; + int32_t estTotalDelay; + uint64_t noVoiceFrameCnt; + uint32_t getFrameCount; +}; + +struct StreamRecvStats { + uint32_t recvBitrate; + uint32_t lostRate; + uint32_t jitter; + uint32_t lostPktCnt; + uint32_t maxContLostPktCnt; + uint32_t recvTotalFrameCnt; + uint32_t jbDepth; + uint32_t jbTotalFrameCnt; + uint32_t packetRate; + uint32_t periodNotRecvPktCnt; + uint32_t periodNotRecvPktTime; + uint32_t periodFreezeFrameCnt; + uint32_t periodFreezeTime; + uint32_t sendNackRequestCnt; + union { + VideoRecvStats videoStats; + AudioRecvStats audioStats; + }; +}; + typedef int32_t (*RecvVideoDataCallback)(uint8_t* data, uint32_t length); typedef int32_t (*RecvAudioDataCallback)(uint8_t* data, uint32_t length); +typedef int32_t (*RecvAudioDecodeCallback)(int32_t streamId, AudioJbDecode* audioJbDecode); typedef int32_t (*RecvCmdDataCallback)(uint8_t* data, uint32_t length); typedef void (*UpdataBitrateCallback)(uint32_t encBitrate, uint32_t totalBitrate); typedef void (*RequestKeyFrameCallback)(); -#endif //HUAWEICLOUD_CLOUDPHONEACCESS_ENGINE_NET_TRANS_DEF_H +#endif //UDP_TRANS_NET_TRANS_DEF_H diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java b/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java index a08203106075477d969deb2890828c44d792736a..401aaa6da6ab1832c21d495d1db3d003cf0dab5b 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java @@ -146,6 +146,8 @@ public interface ICloudPhone { */ int getRtt(); + String getVideoStatisticInfo(); + /** * 获取当前状态 * diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java b/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java index a17ba5f57d88fdbab196ef15c78e1e65d791fbad..9bb37b154759d9e12890350975b242afd98d715f 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java @@ -16,17 +16,23 @@ package com.huawei.cloudphone.apiimpl; +import static android.view.KeyEvent.KEYCODE_BACK; +import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN; +import static android.view.KeyEvent.KEYCODE_VOLUME_UP; +import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_CAMERA; +import static com.huawei.cloudphone.api.CloudPhoneParas.DisplayMode.DISPLAY_MODE_FILL; +import static com.huawei.cloudphone.common.CasState.CAS_CONNECT_EXCEPTION; +import static com.huawei.cloudphone.utils.CasMediaUtils.isValidMediaConfig; + import android.app.Activity; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.PixelFormat; - import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RemoteException; - import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceHolder; @@ -63,14 +69,6 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; -import static android.view.KeyEvent.KEYCODE_BACK; -import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN; -import static android.view.KeyEvent.KEYCODE_VOLUME_UP; -import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_CAMERA; -import static com.huawei.cloudphone.api.CloudPhoneParas.DisplayMode.DISPLAY_MODE_FILL; -import static com.huawei.cloudphone.common.CasState.CAS_CONNECT_EXCEPTION; -import static com.huawei.cloudphone.utils.CasMediaUtils.isValidMediaConfig; - public class CloudPhoneImpl implements ICloudPhone { private static final String TAG = "CloudPhoneImpl"; private static final int STATE_INIT = 0; @@ -106,7 +104,6 @@ public class CloudPhoneImpl implements ICloudPhone { private int mDisplayHeight = 0; private int mCurrentState; private DisplayMode mDisplayMode = DISPLAY_MODE_FILL; - private boolean mIsSurfaceDestroyed = true; private Timer mBackGroundTimer = null; private int mAutoReconnectCount = 0; private Timer mAutoReconnectTimer = null; @@ -243,7 +240,6 @@ public class CloudPhoneImpl implements ICloudPhone { mSurfaceView.setOnTouchListener(null); mSurfaceView.setOnKeyListener(null); mSurfaceView = null; - mIsSurfaceDestroyed = false; mActivity = null; mViewGroup = null; mAutoReconnectCount = 0; @@ -346,6 +342,15 @@ public class CloudPhoneImpl implements ICloudPhone { } } + @Override + public String getVideoStatisticInfo() { + if (mProccessor != null) { + return mProccessor.getVideoStreamStats(); + } else { + return null; + } + } + @Override public int getState() { return mCurrentState; @@ -363,19 +368,11 @@ public class CloudPhoneImpl implements ICloudPhone { CASLog.i(TAG, "handleStartCmd start"); mCurrentState = STATE_STARTING; //创建SurfaceView - while (!mIsSurfaceDestroyed) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - CASLog.i(TAG, "sleep has been interrupt"); - } - } if (mDisplayMode == DISPLAY_MODE_FILL) { mSurfaceView = new PhoneView(activity, true); } else { mSurfaceView = new PhoneView(activity, false); } - mIsSurfaceDestroyed = false; mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { @@ -423,7 +420,6 @@ public class CloudPhoneImpl implements ICloudPhone { msg.what = CMD_SURFACE_DESTROY; mCmdHandler.sendMessage(msg); } - mIsSurfaceDestroyed = true; } catch (Exception e) { CASLog.e(TAG, "surfaceDestroyed failed. " + e.getMessage()); } finally { diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/audio/AudioTrackerCallback.java b/cloudphone/src/main/java/com/huawei/cloudphone/audio/AudioTrackerCallback.java index 7664cb6784b5bfa950992e2f1c510c4bd02601d5..501a68ae5c3731aab704582d2b7243075c8a617f 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/audio/AudioTrackerCallback.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/audio/AudioTrackerCallback.java @@ -221,14 +221,14 @@ public class AudioTrackerCallback implements NewPacketCallback { byte[] buffer = msg.readBytes(userSize); // decode and play - short[] data = new short[bufferSizeInBytes]; - int dataLen = OpusJNIWrapper.opusDecode(mDecoder, buffer, userSize, data, bufferSizeInBytes * 2); - if (dataLen < 0) { - CASLog.e(TAG, "OPUS decode fail" + "userSize : " + userSize + "inputBuffer : " + Arrays.toString(buffer) - + "outputBuffer :" + Arrays.toString(data)); - return; - } - mTrackPlayer.write(data, 0, dataLen, AudioTrack.WRITE_NON_BLOCKING); +// short[] data = new short[bufferSizeInBytes]; +// int dataLen = OpusJNIWrapper.opusDecode(mDecoder, buffer, userSize, data, bufferSizeInBytes * 2); +// if (dataLen < 0) { +// CASLog.e(TAG, "OPUS decode fail" + "userSize : " + userSize + "inputBuffer : " + Arrays.toString(buffer) +// + "outputBuffer :" + Arrays.toString(data)); +// return; +// } + mTrackPlayer.write(buffer, 0, userSize, AudioTrack.WRITE_NON_BLOCKING); } private void handleStop(CasRemoteMessage msg) { diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JNIWrapper.java b/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JNIWrapper.java index cb49f18bd67b2bc445bbd35db391341ad89b65be..4f789a948c2936005cdcb7cfda7e17b7b8150ee4 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JNIWrapper.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JNIWrapper.java @@ -90,6 +90,8 @@ public class JNIWrapper { public static native int getLag(); + public static native String getVideoStreamStats(); + public static native boolean setMediaConfig(HashMap mediaConfigMap); public static native boolean setRotation(int rotation); diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JniBridge.java b/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JniBridge.java index 566e030f3f8f1bfb0f3ab03231f147e34be8fb1b..0a41f1951f2e5402d7030186282c023b8de70b51 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JniBridge.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/jniwrapper/JniBridge.java @@ -85,6 +85,10 @@ public class JniBridge { return JNIWrapper.getLag(); } + public String getVideoStreamStats() { + return JNIWrapper.getVideoStreamStats(); + } + public boolean setMediaConfig(HashMap mediaConfigMap) { if (mediaConfigMap != null) { return JNIWrapper.setMediaConfig(mediaConfigMap); diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/service/CasProcessor.java b/cloudphone/src/main/java/com/huawei/cloudphone/service/CasProcessor.java index 18608524e86989e37c96352046b71439c3cbc573..afdf63b06a7b26d33917c9b84861a15915d95073 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/service/CasProcessor.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/service/CasProcessor.java @@ -190,6 +190,10 @@ public class CasProcessor { return JniBridge.getInstance().getLag(); } + public String getVideoStreamStats() { + return JniBridge.getInstance().getVideoStreamStats(); + } + public boolean startJniRecv() { CASLog.i(TAG, "startJniRecv... "); mUpstreamReceiveDispatcher = new CasRecvPktDispatcher();