diff options
7 files changed, 214 insertions, 190 deletions
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp index 64890329..98bf8014 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp @@ -608,19 +608,15 @@ bool AudioJitterBuffer::Resync(uint32_t currentTime) } else { - if (!IsSID(entry->nBufferSize)) - { - // the first voice frame - mCurrPlayingTS = entry->nTimestamp; - IMLOGD2("[Resync] currTs[%d], delay[%d]", mCurrPlayingTS, timeDiff); - return true; - } - else if (timeDiff > (mCurrJitterBufferSize - 1) * FRAME_INTERVAL) + if (!IsSID(entry->nBufferSize) || + timeDiff > (mCurrJitterBufferSize - 1) * FRAME_INTERVAL) { mCurrPlayingTS = entry->nTimestamp; IMLOGD2("[Resync] currTs[%d], delay[%d]", mCurrPlayingTS, timeDiff); return true; } + + break; } } 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 3bc63092..f74a9caf 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 @@ -153,11 +153,10 @@ private: ANativeWindow* mWindow; AMediaCodec* mCodec; AMediaFormat* mFormat; - ANativeWindow* mRecordingSurface; ANativeWindow* mImageReaderSurface; AImageReader* mImageReader; std::mutex mMutex; - std::mutex mImageReaderMutex; + ImsMediaCondition mConditionExit; IVideoSourceCallback* mListener; ImsMediaPauseImageSource mPauseImageSource; int32_t mCodecType; 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 b8d69951..a035443f 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 @@ -30,7 +30,6 @@ ImsMediaVideoSource::ImsMediaVideoSource() mWindow = nullptr; mCodec = nullptr; mFormat = nullptr; - mRecordingSurface = nullptr; mImageReaderSurface = nullptr; mImageReader = nullptr; mCodecType = -1; @@ -164,7 +163,6 @@ void ImsMediaVideoSource::SetDeviceOrientation(const uint32_t degree) bool ImsMediaVideoSource::Start() { IMLOGD1("[Start], VideoMode[%d]", mVideoMode); - mRecordingSurface = nullptr; if (mVideoMode == kVideoModeRecording || mVideoMode == kVideoModePauseImage) { @@ -214,29 +212,12 @@ bool ImsMediaVideoSource::Start() return false; } - if (mWidth > mHeight) // Is Landscape Mode - { - err = AMediaCodec_createInputSurface(mCodec, &mRecordingSurface); + mImageReaderSurface = CreateImageReader(mWidth, mHeight); - if (err != AMEDIA_OK) - { - IMLOGE1("[Start] create input surface error[%d]", err); - AMediaCodec_delete(mCodec); - mCodec = nullptr; - AMediaFormat_delete(mFormat); - mFormat = nullptr; - return false; - } - } - else + if (mImageReaderSurface == nullptr) { - mImageReaderSurface = CreateImageReader(mWidth, mHeight); - - if (mImageReaderSurface == nullptr) - { - IMLOGE0("[Start] create image reader failed"); - return false; - } + IMLOGE0("[Start] create image reader failed"); + return false; } err = AMediaCodec_start(mCodec); @@ -268,9 +249,7 @@ bool ImsMediaVideoSource::Start() return false; } - ANativeWindow* recording = mRecordingSurface ? mRecordingSurface : mImageReaderSurface; - - if (mCamera->CreateSession(mWindow, recording) == false) + if (mCamera->CreateSession(mWindow, mImageReaderSurface) == false) { IMLOGE0("[Start] error create camera session"); AMediaCodec_delete(mCodec); @@ -295,14 +274,13 @@ bool ImsMediaVideoSource::Start() else if (mVideoMode == kVideoModePauseImage) { mPauseImageSource.Initialize(mWidth, mHeight); - } - - // start encoder output thread - if (mCodec != nullptr) - { - mStopped = false; - std::thread t1(&ImsMediaVideoSource::processOutputBuffer, this); - t1.detach(); + // start encoder output thread + if (mCodec != nullptr) + { + mStopped = false; + std::thread t1(&ImsMediaVideoSource::EncodePauseImage, this); + t1.detach(); + } } mDeviceOrientation = -1; @@ -314,19 +292,19 @@ void ImsMediaVideoSource::Stop() { IMLOGD0("[Stop]"); - mMutex.lock(); + std::lock_guard<std::mutex> guard(mMutex); mStopped = true; - mMutex.unlock(); - if (mCamera != nullptr) + if (mImageReader != nullptr) { - mCamera->StopSession(); + AImageReader_delete(mImageReader); + mImageReader = nullptr; + mImageReaderSurface = nullptr; } - IMLOGD0("[Stop] deinitialize camera"); - if (mCamera != nullptr) { + mCamera->StopSession(); mCamera->DeleteSession(); mCamera->DeInitialize(); mCamera = nullptr; @@ -334,19 +312,12 @@ void ImsMediaVideoSource::Stop() if (mCodec != nullptr) { - if (mRecordingSurface != nullptr) + if (mVideoMode == kVideoModePauseImage) { - AMediaCodec_signalEndOfInputStream(mCodec); + mConditionExit.wait_timeout(mFramerate != 0 ? 1000 / mFramerate : 66); } AMediaCodec_stop(mCodec); - - if (mRecordingSurface != nullptr) - { - ANativeWindow_release(mRecordingSurface); - mRecordingSurface = nullptr; - } - AMediaCodec_delete(mCodec); mCodec = nullptr; } @@ -357,15 +328,10 @@ void ImsMediaVideoSource::Stop() mFormat = nullptr; } - if (mImageReader != nullptr) + if (mVideoMode == kVideoModePauseImage) { - std::lock_guard<std::mutex> guard(mImageReaderMutex); - AImageReader_delete(mImageReader); - mImageReader = nullptr; - mImageReaderSurface = nullptr; + mPauseImageSource.Uninitialize(); } - - mPauseImageSource.Uninitialize(); } bool ImsMediaVideoSource::IsStopped() @@ -376,7 +342,7 @@ bool ImsMediaVideoSource::IsStopped() void ImsMediaVideoSource::onCameraFrame(AImage* pImage) { - std::lock_guard<std::mutex> guard(mImageReaderMutex); + std::lock_guard<std::mutex> guard(mMutex); if (mImageReader == nullptr || pImage == nullptr) { @@ -404,31 +370,40 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) AImage_getPlaneData(pImage, 0, &yPlane, &ylen); AImage_getPlaneData(pImage, 1, &uvPlane, &uvlen); - int32_t facing, sensorOrientation; - mCamera->GetSensorOrientation(mCameraId, &facing, &sensorOrientation); - - switch (facing) + if (mWidth > mHeight) // landscape mode, copy without rotate { - case ACAMERA_LENS_FACING_FRONT: - { - ImsMediaImageRotate::YUV420_SP_Rotate270( - encoderBuf, yPlane, uvPlane, width, height); - } - break; + memcpy(encoderBuf, yPlane, ylen); + memcpy(encoderBuf + ylen, uvPlane, uvlen); + } + else + { + int32_t facing, sensorOrientation; + mCamera->GetSensorOrientation(mCameraId, &facing, &sensorOrientation); - case ACAMERA_LENS_FACING_BACK: + switch (facing) { - ImsMediaImageRotate::YUV420_SP_Rotate90(encoderBuf, yPlane, uvPlane, width, height); - } - break; + case ACAMERA_LENS_FACING_FRONT: + { + ImsMediaImageRotate::YUV420_SP_Rotate270( + encoderBuf, yPlane, uvPlane, width, height); + } + break; - case ACAMERA_LENS_FACING_EXTERNAL: - { - uint32_t size = width * height; - memcpy(encoderBuf, yPlane, size); - memcpy(encoderBuf + size, uvPlane, size / 2); + case ACAMERA_LENS_FACING_BACK: + { + ImsMediaImageRotate::YUV420_SP_Rotate90( + encoderBuf, yPlane, uvPlane, width, height); + } + break; + + case ACAMERA_LENS_FACING_EXTERNAL: + { + uint32_t size = width * height; + memcpy(encoderBuf, yPlane, size); + memcpy(encoderBuf + size, uvPlane, size / 2); + } + break; } - break; } IMLOGD_PACKET1(IM_PACKET_LOG_VIDEO, "[onCameraFrame] queue buffer size[%d]", ylen + uvlen); @@ -440,6 +415,8 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) { IMLOGE1("[onCameraFrame] dequeueInputBuffer returned index[%d]", index); } + + processOutputBuffer(); } void ImsMediaVideoSource::changeBitrate(const uint32_t bitrate) @@ -484,29 +461,8 @@ void ImsMediaVideoSource::requestIdrFrame() void ImsMediaVideoSource::EncodePauseImage() { - auto index = AMediaCodec_dequeueInputBuffer(mCodec, CODEC_TIMEOUT_NANO); - if (index >= 0) - { - size_t buffCapacity = 0; - uint8_t* encoderBuf = AMediaCodec_getInputBuffer(mCodec, index, &buffCapacity); - if (!encoderBuf || !buffCapacity) - { - IMLOGE1("[EncodePauseImage] returned null buffer pointer or buffCapacity[%d]", - buffCapacity); - return; - } - size_t len = mPauseImageSource.GetYuvImage(encoderBuf, buffCapacity); - AMediaCodec_queueInputBuffer( - mCodec, index, 0, len, ImsMediaTimer::GetTimeInMicroSeconds(), 0); - } - else - { - IMLOGE1("[EncodePauseImage] dequeueInputBuffer returned index[%d]", index); - } -} + IMLOGD0("[EncodePauseImage] start"); -void ImsMediaVideoSource::processOutputBuffer() -{ uint32_t nextTime = ImsMediaTimer::GetTimeInMilliSeconds(); uint32_t timeInterval = 66; @@ -515,74 +471,37 @@ void ImsMediaVideoSource::processOutputBuffer() timeInterval = 1000 / mFramerate; } - IMLOGD2("[processOutputBuffer] interval[%d] CameraId[%d]", timeInterval, mCameraId); - - for (;;) + while (!IsStopped()) { - if (IsStopped()) - { - IMLOGD0("[processOutputBuffer] terminated"); - break; - } - - if (mVideoMode == kVideoModePauseImage) - { - EncodePauseImage(); - } - - AMediaCodecBufferInfo info; - auto index = AMediaCodec_dequeueOutputBuffer(mCodec, &info, CODEC_TIMEOUT_NANO); + mMutex.lock(); + auto index = AMediaCodec_dequeueInputBuffer(mCodec, CODEC_TIMEOUT_NANO); if (index >= 0) { - IMLOGD_PACKET5(IM_PACKET_LOG_VIDEO, - "[processOutputBuffer] index[%d], size[%d], offset[%d], time[%ld], flags[%d]", - index, info.size, info.offset, info.presentationTimeUs, info.flags); - - if (info.size > 0) - { - size_t buffCapacity; - uint8_t* buf = AMediaCodec_getOutputBuffer(mCodec, index, &buffCapacity); - - if (IsStopped()) - { - break; - } - - if (buf != nullptr && buffCapacity > 0) - { - if (mListener != nullptr) - { - mListener->OnUplinkEvent( - buf + info.offset, info.size, info.presentationTimeUs, info.flags); - } - } - - AMediaCodec_releaseOutputBuffer(mCodec, index, false); - } - } - else if (index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) - { - IMLOGI0("[processOutputBuffer] Encoder output buffer changed"); - } - else if (index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) - { - if (mFormat != nullptr) + size_t buffCapacity = 0; + uint8_t* encoderBuf = AMediaCodec_getInputBuffer(mCodec, index, &buffCapacity); + if (!encoderBuf || !buffCapacity) { - AMediaFormat_delete(mFormat); + IMLOGE1("[EncodePauseImage] returned null buffer pointer or buffCapacity[%d]", + buffCapacity); + return; } - mFormat = AMediaCodec_getOutputFormat(mCodec); - IMLOGI1("[processOutputBuffer] Encoder format changed, format[%s]", - AMediaFormat_toString(mFormat)); + size_t len = mPauseImageSource.GetYuvImage(encoderBuf, buffCapacity); + AMediaCodec_queueInputBuffer( + mCodec, index, 0, len, ImsMediaTimer::GetTimeInMicroSeconds(), 0); } - else if (index == AMEDIACODEC_INFO_TRY_AGAIN_LATER) + else { - IMLOGD_PACKET0(IM_PACKET_LOG_VIDEO, "[processOutputBuffer] no output buffer"); + IMLOGE1("[EncodePauseImage] dequeueInputBuffer returned index[%d]", index); } - else + + processOutputBuffer(); + mMutex.unlock(); + + if (IsStopped()) { - IMLOGI1("[processOutputBuffer] unexpected index[%d]", index); + break; } nextTime += timeInterval; @@ -591,28 +510,77 @@ void ImsMediaVideoSource::processOutputBuffer() if (nextTime > nCurrTime) { uint32_t timeDiff = nextTime - nCurrTime; - IMLOGD_PACKET1(IM_PACKET_LOG_VIDEO, "[processOutputBuffer] timeDiff[%u]", timeDiff); + IMLOGD_PACKET1(IM_PACKET_LOG_VIDEO, "[EncodePauseImage] timeDiff[%u]", timeDiff); ImsMediaTimer::Sleep(timeDiff); } } - IMLOGD0("[processOutputBuffer] exit"); + IMLOGD0("[EncodePauseImage] end"); + mConditionExit.signal(); } -static void ImageCallback(void* context, AImageReader* reader) +void ImsMediaVideoSource::processOutputBuffer() { - if (context == nullptr) + AMediaCodecBufferInfo info; + auto index = AMediaCodec_dequeueOutputBuffer(mCodec, &info, CODEC_TIMEOUT_NANO); + + if (index >= 0) { - return; + IMLOGD_PACKET5(IM_PACKET_LOG_VIDEO, + "[processOutputBuffer] index[%d], size[%d], offset[%d], time[%ld], flags[%d]", + index, info.size, info.offset, info.presentationTimeUs, info.flags); + + if (info.size > 0) + { + size_t buffCapacity; + uint8_t* buf = AMediaCodec_getOutputBuffer(mCodec, index, &buffCapacity); + + if (buf != nullptr && buffCapacity > 0) + { + if (mListener != nullptr) + { + mListener->OnUplinkEvent( + buf + info.offset, info.size, info.presentationTimeUs, info.flags); + } + } + + AMediaCodec_releaseOutputBuffer(mCodec, index, false); + } + } + else if (index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) + { + IMLOGI0("[processOutputBuffer] Encoder output buffer changed"); } + else if (index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) + { + if (mFormat != nullptr) + { + AMediaFormat_delete(mFormat); + } - ImsMediaVideoSource* pVideoSource = static_cast<ImsMediaVideoSource*>(context); + mFormat = AMediaCodec_getOutputFormat(mCodec); + IMLOGI1("[processOutputBuffer] Encoder format changed, format[%s]", + AMediaFormat_toString(mFormat)); + } + else if (index == AMEDIACODEC_INFO_TRY_AGAIN_LATER) + { + IMLOGD_PACKET0(IM_PACKET_LOG_VIDEO, "[processOutputBuffer] no output buffer"); + } + else + { + IMLOGI1("[processOutputBuffer] unexpected index[%d]", index); + } +} - if (pVideoSource->IsStopped()) +static void ImageCallback(void* context, AImageReader* reader) +{ + if (context == nullptr) { return; } + ImsMediaVideoSource* pVideoSource = static_cast<ImsMediaVideoSource*>(context); + AImage* image = nullptr; auto status = AImageReader_acquireNextImage(reader, &image); 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 65b429e2..a54dc377 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 @@ -57,7 +57,6 @@ kBaseNodeId IVideoSourceNode::GetNodeId() ImsMediaResult IVideoSourceNode::Start() { IMLOGD3("[Start] codec[%d], mode[%d], cameraId[%d]", mCodecType, mVideoMode, mCameraId); - std::lock_guard<std::mutex> guard(mMutex); if (mVideoSource) { @@ -99,7 +98,6 @@ ImsMediaResult IVideoSourceNode::Start() void IVideoSourceNode::Stop() { IMLOGD0("[Stop]"); - std::lock_guard<std::mutex> guard(mMutex); if (mVideoSource) { @@ -263,9 +261,9 @@ void IVideoSourceNode::UpdateSurface(ANativeWindow* window) mWindow = window; } -void IVideoSourceNode::OnUplinkEvent(uint8_t* data, uint32_t size, int64_t timestamp, uint32_t flag) +void IVideoSourceNode::OnUplinkEvent( + uint8_t* data, uint32_t size, int64_t timestamp, uint32_t /*flag*/) { - (void)flag; IMLOGD_PACKET2( IM_PACKET_LOG_VIDEO, "[OnUplinkEvent] size[%zu], timestamp[%ld]", size, timestamp); std::lock_guard<std::mutex> guard(mMutex); 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 0a0a6257..51e981fa 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 @@ -102,8 +102,8 @@ public class MainActivity extends AppCompatActivity { private static final int DTMF_SAMPLING_RATE_KHZ = 16; private static final int DTMF_DURATION = 140; private static final int IDR_INTERVAL = 1; - private static final int RESOLUTION_WIDTH = 640; - private static final int RESOLUTION_HEIGHT = 480; + private static final int RESOLUTION_WIDTH = 480; + private static final int RESOLUTION_HEIGHT = 640; private static final String IMAGE = "data/user_de/0/com.android.telephony.imsmedia/test.jpg"; private static final float DISABLED_ALPHA = 0.3f; private static final float ENABLED_ALPHA = 1.0f; @@ -134,6 +134,7 @@ public class MainActivity extends AppCompatActivity { private int mSelectedCameraZoom = CAMERA_ZOOM; private int mSelectedDeviceOrientationDegree = 0; private int mSelectedCvoValue = -1; + private String mSelectedVideoResolution = "VGA_PR"; private Set<Integer> mSelectedRtcpFbTypes = new HashSet<>(); // The order of these values determines the priority in which they would be @@ -569,6 +570,34 @@ public class MainActivity extends AppCompatActivity { } } + public String[] mVideoResolutionStrings = new String[] { + "HD_PR", "HD_LS", "VGA_PR", "VGA_LS", "QVGA_PR", "QVGA_LS", "SIF_PR", "SIF_LS", "CIF_PR", + "CIF_LS", "QCIF_PR", "QCIF_LS", + }; + + public int[][] mVideoResolution = { + {720, 1280}, {1280, 720}, {480, 640}, {640, 480}, {240, 320}, {320, 240}, {240, 352}, + {352, 240}, {288, 352}, {352, 288}, {176, 144}, {144, 176}, + }; + + public int getResolutionWidth(String resolution) { + for (int i = 0; i < mVideoResolutionStrings.length; i++) { + if (mVideoResolutionStrings[i].equals(resolution)) { + return mVideoResolution[i][0]; + } + } + return RESOLUTION_WIDTH; + } + + public int getResolutionHeight(String resolution) { + for (int i = 0; i < mVideoResolutionStrings.length; i++) { + if (mVideoResolutionStrings[i].equals(resolution)) { + return mVideoResolution[i][1]; + } + } + return RESOLUTION_HEIGHT; + } + /** * Enum of the different states the application can be in. Mainly used to decide * how @@ -1425,7 +1454,7 @@ public class MainActivity extends AppCompatActivity { private VideoConfig createVideoConfig(InetSocketAddress remoteRtpAddress, RtcpConfig rtcpConfig, int codecType, int videoMode, int framerate, int bitrate, int profile, int level, int cameraId, int cameraZoom, int deviceOrientation, int cvo, - int rtcpFbTypes) { + int rtcpFbTypes, int width, int height) { VideoConfig config = new VideoConfig.Builder() .setMediaDirection(RtpConfig.MEDIA_DIRECTION_SEND_RECEIVE) .setAccessNetwork(AccessNetworkType.EUTRAN) @@ -1446,8 +1475,8 @@ public class MainActivity extends AppCompatActivity { .setPacketizationMode(VideoConfig.MODE_NON_INTERLEAVED) .setCameraId(cameraId) .setCameraZoom(cameraZoom) - .setResolutionWidth(RESOLUTION_WIDTH) - .setResolutionHeight(RESOLUTION_HEIGHT) + .setResolutionWidth(width) + .setResolutionHeight(height) .setPauseImagePath(IMAGE) .setDeviceOrientationDegree(deviceOrientation) .setCvoValue(cvo) @@ -1641,7 +1670,7 @@ public class MainActivity extends AppCompatActivity { */ private VideoConfig createVideoConfig(int codecType, int videoMode, int framerate, int bitrate, int profile, int level, int cameraId, int cameraZoom, int deviceOrientation, int cvo, - int rtcpFbTypes) { + int rtcpFbTypes, int width, int height) { VideoConfig videoConfig = null; switch (codecType) { @@ -1649,7 +1678,8 @@ public class MainActivity extends AppCompatActivity { case VideoConfig.VIDEO_CODEC_HEVC: videoConfig = createVideoConfig(getRemoteVideoSocketAddress(), getRemoteVideoRtcpConfig(), codecType, videoMode, framerate, bitrate, - profile, level, cameraId, cameraZoom, deviceOrientation, cvo, rtcpFbTypes); + profile, level, cameraId, cameraZoom, deviceOrientation, cvo, rtcpFbTypes, + width, height); break; } @@ -1844,7 +1874,9 @@ public class MainActivity extends AppCompatActivity { mSelectedFramerate, mSelectedBitrate, mSelectedCodecProfile, mSelectedCodecLevel, mSelectedCameraId, mSelectedCameraZoom, mSelectedDeviceOrientationDegree, - mSelectedCvoValue, rtcpfbTypes); + mSelectedCvoValue, rtcpfbTypes, + getResolutionWidth(mSelectedVideoResolution), + getResolutionHeight(mSelectedVideoResolution)); Log.d(TAG, "VideoConfig: " + mVideoConfig.toString()); RtpVideoSessionCallback sessionVideoCallback = new RtpVideoSessionCallback(); @@ -1906,6 +1938,7 @@ public class MainActivity extends AppCompatActivity { Spinner videoBitrateSpinner = findViewById(R.id.spinnerVideoBitrates); Spinner videoDeviceOrientationSpinner = findViewById(R.id.spinnerVideoDeviceOrientations); Spinner videoCvoValueSpinner = findViewById(R.id.spinnerVideoCvoValues); + Spinner videoResolutionSpinner = (Spinner) findViewById(R.id.spinnerVideoResolution); mSelectedVideoCodec = ((VideoCodecEnum) videoCodecSpinner.getSelectedItem()).getValue(); @@ -1929,6 +1962,7 @@ public class MainActivity extends AppCompatActivity { .getValue(); mSelectedCvoValue = ((VideoCvoValueEnum) videoCvoValueSpinner.getSelectedItem()) .getValue(); + mSelectedVideoResolution = (String) videoResolutionSpinner.getSelectedItem(); Toast.makeText(getApplicationContext(), R.string.save_button_action_toast, Toast.LENGTH_SHORT).show(); } @@ -2084,7 +2118,7 @@ public class MainActivity extends AppCompatActivity { setupCodecSelectionOnClickListeners(); } - private int getSpinnerIndex(Spinner spinner, int value) { + private int getSpinnerIndex(Spinner spinner, Object value) { int index = 0; for (int i = 0; i < spinner.getCount(); i++) { if (spinner.getItemAtPosition(i).equals(value)) { @@ -2107,8 +2141,7 @@ public class MainActivity extends AppCompatActivity { } /** - * Gets the saved user selections for the audio codec settings and updates the - * UI's lists to + * Gets the saved user selections for the audio codec settings and updates the UI's lists to * match. */ private void setupAudioCodecSelectionLists() { @@ -2236,6 +2269,15 @@ public class MainActivity extends AppCompatActivity { videoCvoValueSpinner.setAdapter(videoCvoValueAdaptor); videoCvoValueSpinner.setSelection(getSpinnerIndex(videoCvoValueSpinner, mSelectedCvoValue)); + + Spinner videoResolutionSpinner = (Spinner) findViewById(R.id.spinnerVideoResolution); + ArrayAdapter<String> videoResolutionAdapter = new ArrayAdapter<String>(this, + android.R.layout.simple_spinner_item, mVideoResolutionStrings); + videoResolutionAdapter.setDropDownViewResource( + android.R.layout.simple_spinner_dropdown_item); + videoResolutionSpinner.setAdapter(videoResolutionAdapter); + videoResolutionSpinner.setSelection(getSpinnerIndex(videoResolutionSpinner, + mSelectedVideoResolution)); } /** @@ -2631,8 +2673,8 @@ public class MainActivity extends AppCompatActivity { .setFramerate(10) .setIntraFrameIntervalSec(1) .setPacketizationMode(VideoConfig.MODE_NON_INTERLEAVED) - .setResolutionWidth(480) - .setResolutionHeight(640) + .setResolutionWidth(RESOLUTION_WIDTH) + .setResolutionHeight(RESOLUTION_HEIGHT) .setVideoMode(VideoConfig.VIDEO_MODE_RECORDING) .setMaxMtuBytes(1500); diff --git a/test/app/ImsMediaTestingApp/app/src/main/res/layout/settings_video.xml b/test/app/ImsMediaTestingApp/app/src/main/res/layout/settings_video.xml index 89f103ae..ec502bec 100644 --- a/test/app/ImsMediaTestingApp/app/src/main/res/layout/settings_video.xml +++ b/test/app/ImsMediaTestingApp/app/src/main/res/layout/settings_video.xml @@ -254,6 +254,26 @@ android:layout_toEndOf="@id/videoCvoValueTitle" android:layout_below="@id/videoPauseImagePathTitle" /> + <TextView + android:id="@+id/videoResolutionTitle" + android:textStyle="bold" + android:layout_width="150dp" + android:layout_height="wrap_content" + android:layout_marginTop="30dp" + android:layout_below="@id/videoCvoValueTitle" + android:layout_alignStart="@id/videoCodecTitle" + android:text="@string/video_resolution" + android:textAlignment="textStart" /> + + <Spinner + android:id="@+id/spinnerVideoResolution" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:layout_marginTop="30dp" + android:layout_marginStart="15dp" + android:layout_toEndOf="@id/videoResolutionTitle" + android:layout_below="@id/videoCvoValueTitle" /> + <Button android:id="@+id/saveVideoSettingsButton" android:layout_width="wrap_content" 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 37d6b5a7..7dd2cf86 100644 --- a/test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml +++ b/test/app/ImsMediaTestingApp/app/src/main/res/values/strings.xml @@ -64,6 +64,7 @@ <string name="video_device_orientation">Device Orientation</string> <string name="video_pause_image_path">Pause Image Path</string> <string name="video_cvo_value">CVO Value</string> + <string name="video_resolution">Resolution</string> <!-- Save button text --> <string name="save">SAVE</string> |