diff --git a/.github/workflows/eeasy-sv82x.yml b/.github/workflows/eeasy-sv82x.yml
new file mode 100644
index 0000000..0a7887b
--- /dev/null
+++ b/.github/workflows/eeasy-sv82x.yml
@@ -0,0 +1,69 @@
+name: eeasy-sv82x
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+ workflow_dispatch:
+ branches: [ main ]
+
+env:
+ # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+ BUILD_TYPE: Release
+ BOARD: SV82x
+
+jobs:
+ ecr-prepare:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Configure AWS credentials
+ id: configure-aws-credentials
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ aws-region: ${{ secrets.AWS_REGION }}
+
+ - name: Login to Amazon ECR
+ id: login-ecr
+ uses: codingspirit/amazon-ecr-login@master
+
+ - name: Set ECR credentials
+ id: set-ecr-credentials
+ run: |
+ gh auth login --with-token <<< ${{ secrets.PA_TOKEN }}
+ gh secret set --env ECR ECR_REGISTRY --body ${{ steps.login-ecr.outputs.registry }} --repo ${{ github.repository }}
+ gh secret set --env ECR ECR_USERNAME --body ${{ steps.login-ecr.outputs.docker_username }} --repo ${{ github.repository }}
+ gh secret set --env ECR ECR_PASSWORD --body ${{ steps.login-ecr.outputs.docker_password }} --repo ${{ github.repository }}
+
+ eeasy:
+ environment: ECR
+ needs: ecr-prepare
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ container: [ "482862934379.dkr.ecr.us-east-1.amazonaws.com/eeasy:7.5.0" ]
+ container:
+ image: ${{ matrix.container }}
+ credentials:
+ username: ${{ secrets.ECR_USERNAME }}
+ password: ${{ secrets.ECR_PASSWORD }}
+
+ steps:
+ - name: Git checkout
+ uses: actions/checkout@v2
+
+ - name: Prepare board SDK
+ run: |
+ cp -r /SV82x/* ${GITHUB_WORKSPACE}/3rdparty/SV82x/
+
+ - name: Configure CMake
+ run: cmake -B ${{ github.workspace }}/build -DBOARD=${{ env.BOARD }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_WEBRTC_SAMPLES=ON -DBUILD_KVS_SAMPLES=ON -DBUILD_SAVE_FRAME_SAMPLES=ON
+
+ - name: Build
+ run: cmake --build ${{ github.workspace }}/build --config ${{ env.BUILD_TYPE }} --parallel 4
+
+ - name: Test
+ run: ctest -C ${{ env.BUILD_TYPE }}
diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml
index 14bbd00..69e7daa 100644
--- a/.github/workflows/file.yml
+++ b/.github/workflows/file.yml
@@ -1,12 +1,6 @@
name: file
-on:
- push:
- branches: [ develop, main ]
- pull_request:
- branches: [ develop, main ]
- workflow_dispatch:
- branches: [ develop, main ]
+on: [push, pull_request, workflow_dispatch]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
diff --git a/.github/workflows/v4l2.yml b/.github/workflows/v4l2.yml
index db3dd05..0dc4054 100644
--- a/.github/workflows/v4l2.yml
+++ b/.github/workflows/v4l2.yml
@@ -1,12 +1,6 @@
name: v4l2
-on:
- push:
- branches: [ develop, main ]
- pull_request:
- branches: [ develop, main ]
- workflow_dispatch:
- branches: [ develop, main ]
+on: [push, pull_request, workflow_dispatch]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
diff --git a/3rdparty/README.md b/3rdparty/README.md
index 7a35bb5..532f9bb 100644
--- a/3rdparty/README.md
+++ b/3rdparty/README.md
@@ -9,6 +9,7 @@ This documents provides guidelines to install board SDK required by this library
- [FH8626V100](#fh8626v100)
- [AK3918](#ak3918)
- [C302](#c302)
+ - [SV82x](#sv82x)
## FILE
@@ -112,3 +113,15 @@ C302/
```
> Other related dependent libraries and header files need to obtain the cross-compiled toolchain of C302.
+
+## SV82x
+
+User need to put SV82x board SDK under [3rdparty/SV82x/](SV82x/):
+
+```
+SV82x/
+├── common
+├── include
+├── lib
+└── sample
+```
diff --git a/3rdparty/SV82x/.gitkeep b/3rdparty/SV82x/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/CMake/SV82x.cmake b/CMake/SV82x.cmake
new file mode 100755
index 0000000..91e791a
--- /dev/null
+++ b/CMake/SV82x.cmake
@@ -0,0 +1,177 @@
+if(BOARD STREQUAL "SV82x")
+ set(BOARD_SDK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/${BOARD})
+ set(BOARD_SRCS
+ ${BOARD_SDK_DIR}/common/sample_comm_audio.c
+ ${BOARD_SDK_DIR}/common/sample_comm_doss.c
+ ${BOARD_SDK_DIR}/common/sample_comm_ippu.c
+ ${BOARD_SDK_DIR}/common/sample_comm_isp.c
+ ${BOARD_SDK_DIR}/common/sample_comm_sys.c
+ ${BOARD_SDK_DIR}/common/sample_comm_vdec.c
+ ${BOARD_SDK_DIR}/common/sample_comm_venc.c
+ ${BOARD_SDK_DIR}/common/sample_comm_video.c
+ ${BOARD_SDK_DIR}/common/sample_comm_viss.c
+ )
+ set(BOARD_INCS_DIR
+ ${BOARD_SDK_DIR}/include/
+ ${BOARD_SDK_DIR}/common/
+ )
+
+ if(USE_MUCLIBC)
+ set(BOARD_LIBS_DIR
+ ${BOARD_SDK_DIR}/lib/uclibc
+ )
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -muclibc")
+ set(BOARD_DESTINATION_PLATFORM arm-unknown-linux-uclibc)
+ else()
+ set(BOARD_LIBS_DIR
+ ${BOARD_SDK_DIR}/lib/glibc
+ )
+ set(BOARD_DESTINATION_PLATFORM arm-unknown-linux-gnu)
+ endif()
+
+ set(BOARD_LIBS_SHARED
+ i2cops
+ cam_gc4653_mipi
+ ext_drv_ms41929
+ extops
+ audioin
+ cam_sc2335_mipi
+ ext_drv_a6208
+ ei_AGC
+ customer_af
+ audiocommon
+ cam_imx327_mipi
+ cam_ar0230_dvp
+ ax
+ cam_ov9732_mipi
+ ei_hpf
+ panel_spcs92048_prgb
+ cam_ov5640_mipi
+ ae
+ awb
+ audioout
+ cam_gc4663_mipi
+ threadpool
+ ei_eq
+ panel_wks43178_cpu
+ cam_tp9950_mipi
+ mbase
+ ei_drc
+ cam_sc4210_mipi
+ cam_cr286_dvp
+ panel_ili9488_mipi
+ cam_sc200ai_mipi
+ ctest
+ cam_tp2850_mipi
+ viss
+ af
+ panel_eos_default
+ cam_imx415_mipi
+ cam_tp2815_mipi
+ isp
+ mfake
+ cam_sc4238_mipi
+ doss
+ audioenc
+ vgss
+ audiodec
+ cam_imx307_mipi
+ cam_os05a20_mipi
+ cam_imx335_mipi
+ cam_gc2145_mipi
+ cam_tp9930_dvp
+ cam_ov2710_dvp
+ cam_ov5640_dvp
+ mlink
+ cam_tp9950_dvp
+ ext_drv_ap1511b
+ region
+ vc
+ dnvqe
+ vbuf
+ cam_ov2735_mipi
+ panel_wks70002_lvds
+ sam
+ ei_RES
+ cam_ov8858_mipi
+ ei_common
+ panel_otm1289a_mipi
+ upvqe
+ cam_clb
+ panel_lt8912b_mipi
+ m pthread dl
+ )
+ set(BOARD_LIBS_STATIC
+ cam_gc4653_mipi.a
+ ext_drv_ms41929.a
+ extops.a
+ audioin.a
+ cam_sc2335_mipi.a
+ ext_drv_a6208.a
+ ei_AGC
+ customer_af.a
+ audiocommon.a
+ cam_imx327_mipi.a
+ cam_ar0230_dvp.a
+ ax.a
+ cam_ov9732_mipi.a
+ ei_hpf
+ panel_spcs92048_prgb.a
+ cam_ov5640_mipi.a
+ ae.a
+ awb.a
+ audioout.a
+ cam_gc4663_mipi.a
+ threadpool.a
+ ei_eq
+ panel_wks43178_cpu.a
+ cam_tp9950_mipi.a
+ mbase.a
+ ei_drc
+ cam_sc4210_mipi.a
+ cam_cr286_dvp.a
+ panel_ili9488_mipi.a
+ cam_sc200ai_mipi.a
+ ctest.a
+ cam_tp2850_mipi.a
+ viss.a
+ af.a
+ panel_eos_default.a
+ cam_imx415_mipi.a
+ cam_tp2815_mipi.a
+ isp.a
+ mfake.a
+ cam_sc4238_mipi.a
+ doss.a
+ audioenc.a
+ vgss.a
+ audiodec.a
+ cam_imx307_mipi.a
+ cam_os05a20_mipi.a
+ cam_imx335_mipi.a
+ cam_gc2145_mipi.a
+ cam_tp9930_dvp.a
+ cam_ov2710_dvp.a
+ cam_ov5640_dvp.a
+ mlink.a
+ cam_tp9950_dvp.a
+ ext_drv_ap1511b.a
+ region.a
+ vc.a
+ dnvqe.a
+ vbuf.a
+ cam_ov2735_mipi.a
+ log.a
+ panel_wks70002_lvds.a
+ sam.a
+ ei_RES
+ cam_ov8858_mipi.a
+ ei_common
+ i2cops.a
+ panel_otm1289a_mipi.a
+ upvqe.a
+ cam_clb.a
+ panel_lt8912b_mipi.a
+ libm.a pthread dl
+ )
+endif()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0695ece..af00d8b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,6 +25,8 @@ elseif(BOARD STREQUAL "AK3918")
message(STATUS "Selected board AK3918")
elseif(BOARD STREQUAL "C302")
message(STATUS "Selected board C302")
+elseif(BOARD STREQUAL "SV82x")
+ message(STATUS "Selected board SV82x")
else()
message(FATAL_ERROR "${BOARD} is not implemented yet.")
endif()
diff --git a/README.md b/README.md
index 1f54aa6..7b2ba69 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@
[![fullhan-fh8626v100](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/fullhan-fh8626v100.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/fullhan-fh8626v100.yml)
[![anyka-ak3918](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/anyka-ak3918.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/anyka-ak3918.yml)
[![amlogic-c302](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/amlogic-c302.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/amlogic-c302.yml)
+[![eeasy-sv82x](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/eeasy-sv82x.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/eeasy-sv82x.yml)
- [Amazon Kinesis Video Streams Media Interface](#amazon-kinesis-video-streams-media-interface)
- [Introduction](#introduction)
@@ -25,15 +26,16 @@
## Supported Boards
-| Name | Description | CMake Parameter | Status |
-| ------------------ | --------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| FILE | Dummy boards that can capture from [sample frames](resources/frames/) | `-DBOARD=FILE` | [![file](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml) |
-| x86/x64 | Capture from V4L2 device or capture from dummy frames | `-DBOARD=V4L2`
or `-DBOARD=FILE` | [![v4l2](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml)[![file](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml) |
-| Raspberry Pi | Capture from V4L2 device or capture from dummy frames | `-DBOARD=V4L2`
or `-DBOARD=FILE` | [![v4l2](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml)[![file](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml) |
-| Ingenic T31 | IPC SoC designed by Ingenic | `-DBOARD=T31` | [![ingenic-t31](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/ingenic-t31.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/ingenic-t31.yml) |
-| Fullhan FH8626V100 | IPC SoC designed by Fullhan | `-DBOARD=FH8626V100` | [![fullhan-fh8626v100](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/fullhan-fh8626v100.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/fullhan-fh8626v100.yml) |
-| Anyka AK3918 | IPC SoC designed by Anyka | `-DBOARD=AK3918` | [![anyka-ak3918](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/anyka-ak3918.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/anyka-ak3918.yml) |
-| Amlogic C302 | IPC SoC designed by Amlogic | `-DBOARD=C302` | [![amlogic-c302](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/amlogic-c302.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/amlogic-c302.yml) |
+| Name | Description | CMake Parameter | Status |
+| ------------------ | --------------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| FILE | Dummy boards that can capture from [sample frames](resources/frames/) | `-DBOARD=FILE` | [![file](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml) |
+| x86/x64 | Capture from V4L2 device or capture from [sample frames](resources/frames/) | `-DBOARD=V4L2`
or `-DBOARD=FILE` | [![v4l2](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml)[![file](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml) |
+| Raspberry Pi | Capture from V4L2 device or capture from [sample frames](resources/frames/) | `-DBOARD=V4L2`
or `-DBOARD=FILE` | [![v4l2](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/v4l2.yml)[![file](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/file.yml) |
+| Ingenic T31 | IPC SoC designed by Ingenic | `-DBOARD=T31` | [![ingenic-t31](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/ingenic-t31.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/ingenic-t31.yml) |
+| Fullhan FH8626V100 | IPC SoC designed by Fullhan | `-DBOARD=FH8626V100` | [![fullhan-fh8626v100](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/fullhan-fh8626v100.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/fullhan-fh8626v100.yml) |
+| Anyka AK3918 | IPC SoC designed by Anyka | `-DBOARD=AK3918` | [![anyka-ak3918](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/anyka-ak3918.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/anyka-ak3918.yml) |
+| Amlogic C302 | IPC SoC designed by Amlogic | `-DBOARD=C302` | [![amlogic-c302](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/amlogic-c302.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/amlogic-c302.yml) |
+| Eeasy SV82x | IPC SoC designed by Eeasy | `-DBOARD=SV82x` | [![eeasy-sv82x](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/eeasy-sv82x.yml/badge.svg)](https://github.com/aws-samples/amazon-kinesis-video-streams-media-interface/actions/workflows/eeasy-sv82x.yml) |
## Getting started with out-of-box KVS WebRTC sample
diff --git a/source/SV82x/SV82xAudioCapturer.c b/source/SV82x/SV82xAudioCapturer.c
new file mode 100644
index 0000000..37024c4
--- /dev/null
+++ b/source/SV82x/SV82xAudioCapturer.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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
+#include
+
+#include "com/amazonaws/kinesis/video/capturer/AudioCapturer.h"
+
+#include "SV82xCommon.h"
+
+#define SV82X_HANDLE_GET(x) SV82XAudioCapturer* sv82xHandle = (SV82XAudioCapturer*) ((x))
+#define AAC_HEADER_SIZE (7)
+
+typedef struct {
+ AudioCapturerStatus status;
+ AudioCapability capability;
+ AudioFormat format;
+ AudioChannel channel;
+ AudioBitDepth bitDepth;
+ AudioSampleRate sampleRate;
+} SV82XAudioCapturer;
+
+sv82x_audio_stream_info_t g_audio_capture = {
+ .AiDev = 0,
+ .AencChn = 0,
+ .paramEncode.payload_type = PT_LPCM,
+ .paramEncode.samplerate = AUDIO_SAMPLE_RATE_48000,
+ .paramEncode.num_per_frm = 160,
+ .paramEncode.fps = 25,
+ .paramEncode.sound_mode = AUDIO_SOUND_MODE_MONO,
+ .paramEncode.bitwidth = AUDIO_BIT_WIDTH_8,
+ .paramEncode.volume = 50,
+ .paramEncode.u32ChnCnt = 1,
+ .bAioReSample = EI_FALSE,
+ .enInSampleRate = AUDIO_SAMPLE_RATE_BUTT,
+ .enOutSampleRate = AUDIO_SAMPLE_RATE_BUTT,
+ .enVqe = EI_TRUE,
+ .audio_vqe.open_mask = AI_VQE_MASK_AEC,
+ .enAudioCreate = EI_FALSE,
+ .enAencCreate = EI_FALSE,
+};
+
+static int setStatus(AudioCapturerHandle handle, const AudioCapturerStatus newStatus)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (newStatus != sv82xHandle->status) {
+ sv82xHandle->status = newStatus;
+ LOG("AudioCapturer new status[%d]", newStatus);
+ }
+
+ return 0;
+}
+
+AudioCapturerHandle audioCapturerCreate(void)
+{
+ SV82XAudioCapturer* sv82xHandle = (SV82XAudioCapturer*) malloc(sizeof(SV82XAudioCapturer));
+
+ if (!sv82xHandle) {
+ LOG("%s OOM", __func__);
+ return NULL;
+ }
+
+ memset(sv82xHandle, 0, sizeof(SV82XAudioCapturer));
+
+ // Now implementation supports raw PCM, G.711 ALAW and ULAW, MONO, 8k/16k, 16 bits
+ sv82xHandle->capability.formats = (1 << (AUD_FMT_G711A - 1)) | (1 << (AUD_FMT_G711U - 1)) | (1 << (AUD_FMT_PCM - 1)) | (1 << (AUD_FMT_AAC - 1));
+ sv82xHandle->capability.channels = (1 << (AUD_CHN_MONO - 1));
+ sv82xHandle->capability.sampleRates = (1 << (AUD_SAM_8K - 1)) | (1 << (AUD_SAM_16K - 1));
+ sv82xHandle->capability.bitDepths = (1 << (AUD_BIT_16 - 1));
+
+ setStatus((AudioCapturerHandle) sv82xHandle, AUD_CAP_STATUS_STREAM_OFF);
+ return (AudioCapturerHandle) sv82xHandle;
+}
+
+AudioCapturerStatus audioCapturerGetStatus(const AudioCapturerHandle handle)
+{
+ if (!handle) {
+ return AUD_CAP_STATUS_NOT_READY;
+ }
+
+ SV82X_HANDLE_GET(handle);
+ return sv82xHandle->status;
+}
+
+int audioCapturerGetCapability(const AudioCapturerHandle handle, AudioCapability* pCapability)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (!pCapability) {
+ return -EINVAL;
+ }
+
+ *pCapability = sv82xHandle->capability;
+
+ return 0;
+}
+
+// START AENC
+int audioCapturerSetFormat(AudioCapturerHandle handle, const AudioFormat format, const AudioChannel channel, const AudioSampleRate sampleRate,
+ const AudioBitDepth bitDepth)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ EI_S32 s32AencChnCnt;
+ AIO_ATTR_S stAioAttr;
+ PAYLOAD_TYPE_E payType;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ SV82X_HANDLE_STATUS_CHECK(sv82xHandle, AUD_CAP_STATUS_STREAM_OFF);
+
+ switch (format) {
+ case AUD_FMT_AAC:
+ payType = PT_AAC;
+ break;
+ case AUD_FMT_PCM:
+ payType = PT_LPCM;
+ break;
+ case AUD_FMT_G711A:
+ payType = PT_G711A;
+ break;
+ case AUD_FMT_G711U:
+ payType = PT_G711U;
+ break;
+ case AUD_FMT_OPUS:
+ default:
+ LOG("Unsupported format %d", format);
+ return -EINVAL;
+ }
+
+ if (channel == AUD_CHN_MONO) {
+ g_audio_capture.paramEncode.sound_mode == AUDIO_SOUND_MODE_MONO;
+ g_audio_capture.paramEncode.u32ChnCnt = 1;
+ } else {
+ g_audio_capture.paramEncode.sound_mode == AUDIO_SOUND_MODE_STEREO;
+ g_audio_capture.paramEncode.u32ChnCnt = 2;
+ }
+
+ switch (sampleRate) {
+ case AUD_SAM_8K:
+ g_audio_capture.paramEncode.samplerate = AUDIO_SAMPLE_RATE_8000;
+ break;
+ case AUD_SAM_16K:
+ g_audio_capture.paramEncode.samplerate = AUDIO_SAMPLE_RATE_16000;
+ break;
+ case AUD_SAM_24K:
+ g_audio_capture.paramEncode.samplerate = AUDIO_SAMPLE_RATE_24000;
+ break;
+ case AUD_SAM_32K:
+ g_audio_capture.paramEncode.samplerate = AUDIO_SAMPLE_RATE_32000;
+ break;
+ case AUD_SAM_44_1K:
+ g_audio_capture.paramEncode.samplerate = AUDIO_SAMPLE_RATE_44100;
+ break;
+ case AUD_SAM_48K:
+ g_audio_capture.paramEncode.samplerate = AUDIO_SAMPLE_RATE_48000;
+ break;
+ default:
+ LOG("Unsupported sampleRate %d", sampleRate);
+ return -EINVAL;
+ }
+
+ switch (bitDepth) {
+ case AUD_BIT_8:
+ g_audio_capture.paramEncode.bitwidth = AUDIO_BIT_WIDTH_8;
+ break;
+ case AUD_BIT_16:
+ g_audio_capture.paramEncode.bitwidth = AUDIO_BIT_WIDTH_16;
+ break;
+ case AUD_BIT_32:
+ g_audio_capture.paramEncode.bitwidth = AUDIO_BIT_WIDTH_24;
+ break;
+ default:
+ LOG("Unsupported bitDepth %d", bitDepth);
+ return -EINVAL;
+ }
+
+ g_audio_capture.paramEncode.payload_type = payType;
+ stAioAttr.enSamplerate = g_audio_capture.paramEncode.samplerate;
+ stAioAttr.enBitwidth = g_audio_capture.paramEncode.bitwidth;
+ stAioAttr.enSoundmode = g_audio_capture.paramEncode.sound_mode;
+ stAioAttr.u32EXFlag = 0;
+ stAioAttr.u32FrmNum = 30;
+ stAioAttr.u32PtNumPerFrm = g_audio_capture.paramEncode.num_per_frm;
+ stAioAttr.u32ChnCnt = g_audio_capture.paramEncode.u32ChnCnt;
+
+ s32AencChnCnt = stAioAttr.u32ChnCnt >> stAioAttr.enSoundmode;
+ s32Ret = SAMPLE_COMM_AUDIO_StartAenc(s32AencChnCnt, &stAioAttr, g_audio_capture.paramEncode.payload_type);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StartAenc failed, s32Ret=%d\n", s32Ret);
+ s32Ret = SAMPLE_COMM_AUDIO_StopAenc(s32AencChnCnt);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAenc failed, s32Ret=%d\n", s32Ret);
+ }
+ return -EAGAIN;
+ }
+
+ sv82xHandle->format = format;
+ sv82xHandle->channel = channel;
+ sv82xHandle->sampleRate = sampleRate;
+ sv82xHandle->bitDepth = bitDepth;
+
+ return 0;
+}
+
+int audioCapturerGetFormat(const AudioCapturerHandle handle, AudioFormat* pFormat, AudioChannel* pChannel, AudioSampleRate* pSampleRate,
+ AudioBitDepth* pBitDepth)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ *pFormat = sv82xHandle->format;
+ *pChannel = sv82xHandle->channel;
+ *pSampleRate = sv82xHandle->sampleRate;
+ *pBitDepth = sv82xHandle->bitDepth;
+
+ return 0;
+}
+
+// START AI
+int audioCapturerAcquireStream(AudioCapturerHandle handle)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ AI_CHN AiChn = 0;
+ EI_S32 s32AiChnCnt;
+ AENC_CHN AeChn = 0;
+ AIO_ATTR_S stAioAttr;
+ AI_VQE_CONFIG_S stAiVqeAttr;
+ EI_VOID* pAiVqeAttr = NULL;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ AUDIO_DEV AiDev = g_audio_capture.AiDev;
+
+ stAioAttr.enSamplerate = g_audio_capture.paramEncode.samplerate;
+ stAioAttr.enBitwidth = g_audio_capture.paramEncode.bitwidth;
+ stAioAttr.enSoundmode = g_audio_capture.paramEncode.sound_mode;
+ stAioAttr.u32EXFlag = 0;
+ stAioAttr.u32FrmNum = 30;
+ stAioAttr.u32PtNumPerFrm = g_audio_capture.paramEncode.num_per_frm;
+ stAioAttr.u32ChnCnt = g_audio_capture.paramEncode.u32ChnCnt;
+
+ s32AiChnCnt = stAioAttr.u32ChnCnt;
+ if (g_audio_capture.enVqe == EI_TRUE) {
+ memset(&stAiVqeAttr, 0, sizeof(AI_VQE_CONFIG_S));
+ g_audio_capture.audio_vqe.sample_rate = g_audio_capture.paramEncode.samplerate;
+ stAiVqeAttr.s32WorkSampleRate = g_audio_capture.audio_vqe.sample_rate;
+ stAiVqeAttr.s32FrameSample = g_audio_capture.paramEncode.num_per_frm;
+ stAiVqeAttr.enWorkstate = VQE_WORKSTATE_COMMON;
+ stAiVqeAttr.u32OpenMask = g_audio_capture.audio_vqe.open_mask;
+ pAiVqeAttr = (EI_VOID*) &stAiVqeAttr;
+ }
+
+ s32Ret = SAMPLE_COMM_AUDIO_StartAi(AiDev, s32AiChnCnt, &stAioAttr, g_audio_capture.enOutSampleRate, g_audio_capture.bAioReSample, pAiVqeAttr);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StartAi failed, s32Ret=%d\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = SAMPLE_COMM_AUDIO_CreatTrdAiAenc(AiDev, AiChn, AeChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_AUDIO_OpenSaveFile failed, s32Ret=%d\n", s32Ret);
+ s32AiChnCnt = stAioAttr.u32ChnCnt >> stAioAttr.enSoundmode;
+ s32Ret |= SAMPLE_COMM_AUDIO_StopAi(AiDev, s32AiChnCnt, g_audio_capture.bAioReSample, g_audio_capture.enVqe);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAi failed, s32Ret=%d\n", s32Ret);
+ }
+ return -EAGAIN;
+ }
+
+ LOG("SAMPLE_COMM_AUDIO_StartAi OK,AI(%d,%d),AencChn:%d\n", AiDev, AiChn, AeChn);
+
+ return setStatus(handle, AUD_CAP_STATUS_STREAM_ON);
+}
+
+int audioCapturerGetFrame(AudioCapturerHandle handle, void* pFrameDataBuffer, const size_t frameDataBufferSize, uint64_t* pTimestamp,
+ size_t* pFrameSize)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ AUDIO_STREAM_S stStream;
+ int AeChn = g_audio_capture.AencChn;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ SV82X_HANDLE_STATUS_CHECK(sv82xHandle, AUD_CAP_STATUS_STREAM_ON);
+
+ if (!pFrameDataBuffer || !pTimestamp || !pFrameSize)
+ return -EINVAL;
+
+ while (handle) {
+ s32Ret = EI_MI_AENC_GetStream(AeChn, &stStream, -1);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_AENC_GetStream failed. s32Ret=%x\n", s32Ret);
+ continue;
+ }
+ if (PT_AAC == g_audio_capture.paramEncode.payload_type) {
+ if (stStream.u32Len > 0 && stStream.u32Len <= frameDataBufferSize) {
+ memcpy(pFrameDataBuffer, stStream.pStream + AAC_HEADER_SIZE, stStream.u32Len - AAC_HEADER_SIZE);
+ *pFrameSize = stStream.u32Len - AAC_HEADER_SIZE;
+ *pTimestamp = stStream.u64TimeStamp;
+ EI_MI_AENC_ReleaseStream(AeChn, &stStream);
+ return 0;
+ }
+ } else {
+ if (stStream.u32Len > 0 && stStream.u32Len <= frameDataBufferSize) {
+ memcpy(pFrameDataBuffer, stStream.pStream, stStream.u32Len);
+ *pFrameSize = stStream.u32Len;
+ *pTimestamp = stStream.u64TimeStamp;
+ EI_MI_AENC_ReleaseStream(AeChn, &stStream);
+ return 0;
+ }
+ }
+
+ s32Ret = EI_MI_AENC_ReleaseStream(AeChn, &stStream);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_AENC_ReleaseStream(%d), failed with %#x!\n", AeChn, s32Ret);
+ }
+ return -EAGAIN;
+ }
+
+ return -EAGAIN;
+}
+
+int audioCapturerReleaseStream(AudioCapturerHandle handle)
+{
+ int s32Ret = EI_SUCCESS;
+ int bAioReSample = 0;
+ EI_BOOL bVqeEn = g_audio_capture.enVqe;
+ int s32AiChncnt = 1;
+ AUDIO_DEV AiDev = g_audio_capture.AiDev;
+ AUDIO_DEV AdChn = g_audio_capture.AdecChn;
+ AI_CHN AiChn;
+ int i = 0;
+ int s32AencChnCnt;
+ int u32ChnCnt = 2;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ SV82X_HANDLE_STATUS_CHECK(sv82xHandle, AUD_CAP_STATUS_STREAM_ON);
+
+ if (g_audio_capture.enAencCreate == EI_FALSE)
+ return -EINVAL;
+
+ g_audio_capture.enAencCreate = EI_FALSE;
+
+ s32AencChnCnt = u32ChnCnt >> g_audio_capture.paramEncode.sound_mode;
+
+ for (i = 0; i < s32AencChnCnt; i++) {
+ AiChn = i;
+ s32Ret = SAMPLE_COMM_AUDIO_DestroyTrdAi(AiDev, AiChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_DestroyTrdAi failed, s32Ret=%d\n", s32Ret);
+ }
+
+ s32Ret = SAMPLE_COMM_AUDIO_DestroyTrdAencAdec(AdChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_DestroyTrdAencAdec failed, s32Ret=%d\n", s32Ret);
+ }
+ }
+
+ s32Ret = SAMPLE_COMM_AUDIO_StopAenc(s32AencChnCnt);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAenc failed %x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = SAMPLE_COMM_AUDIO_StopAi(AiDev, s32AiChncnt, bAioReSample, bVqeEn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAi failed %x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ return setStatus(handle, AUD_CAP_STATUS_STREAM_OFF);
+}
+
+void audioCapturerDestory(AudioCapturerHandle handle)
+{
+ if (!handle)
+ return;
+
+ SV82X_HANDLE_GET(handle);
+
+ if (sv82xHandle->status == AUD_CAP_STATUS_STREAM_ON) {
+ audioCapturerReleaseStream(handle);
+ }
+
+ setStatus(handle, AUD_CAP_STATUS_NOT_READY);
+
+ free(handle);
+}
diff --git a/source/SV82x/SV82xAudioPlayer.c b/source/SV82x/SV82xAudioPlayer.c
new file mode 100644
index 0000000..885e6fa
--- /dev/null
+++ b/source/SV82x/SV82xAudioPlayer.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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
+#include
+
+#include "com/amazonaws/kinesis/video/player/AudioPlayer.h"
+
+#include "SV82xCommon.h"
+
+#define SV82X_HANDLE_GET(x) SV82XAudioPlayer* sv82xHandle = (SV82XAudioPlayer*) ((x))
+
+typedef struct {
+ AudioPlayerStatus status;
+ AudioCapability capability;
+ AudioFormat format;
+ AudioChannel channel;
+ AudioBitDepth bitDepth;
+ AudioSampleRate sampleRate;
+} SV82XAudioPlayer;
+
+sv82x_audio_stream_info_t g_audio_player = {
+ .AdecChn = 0,
+ .AoChn = 0,
+ .AoDev = 0,
+ .paramDecode.payload_type = PT_MP3,
+ .paramDecode.samplerate = AUDIO_SAMPLE_RATE_48000,
+ .paramDecode.num_per_frm = 512,
+ .paramDecode.fps = 25,
+ .paramDecode.sound_mode = AUDIO_SOUND_MODE_MONO,
+ .paramDecode.bitwidth = AUDIO_BIT_WIDTH_16,
+ .paramDecode.volume = 50,
+ .paramDecode.u32ChnCnt = 1,
+ .bAioReSample = EI_FALSE,
+ .enInSampleRate = AUDIO_SAMPLE_RATE_BUTT,
+ .enOutSampleRate = AUDIO_SAMPLE_RATE_BUTT,
+ .enVqe = EI_FALSE,
+ .enAudioCreate = EI_FALSE,
+ .enUserGetMode = EI_FALSE,
+};
+
+static int setStatus(AudioPlayerHandle handle, const AudioPlayerStatus newStatus)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (newStatus != sv82xHandle->status) {
+ sv82xHandle->status = newStatus;
+ LOG("AudioPlayer new status[%d]", newStatus);
+ }
+
+ return 0;
+}
+
+AudioPlayerHandle audioPlayerCreate(void)
+{
+ SV82XAudioPlayer* sv82xHandle = (SV82XAudioPlayer*) malloc(sizeof(SV82XAudioPlayer));
+
+ if (!sv82xHandle) {
+ LOG("%s OOM", __func__);
+ return NULL;
+ }
+
+ memset(sv82xHandle, 0, sizeof(SV82XAudioPlayer));
+
+ sv82xHandle->capability.formats = (1 << (AUD_FMT_G711A - 1)) | (1 << (AUD_FMT_G711U - 1)) | (1 << (AUD_FMT_PCM - 1)) | (1 << (AUD_FMT_AAC - 1));
+ sv82xHandle->capability.channels = (1 << (AUD_CHN_MONO - 1));
+ sv82xHandle->capability.sampleRates = (1 << (AUD_SAM_8K - 1));
+ sv82xHandle->capability.bitDepths = (1 << (AUD_BIT_16 - 1));
+
+ setStatus((AudioPlayerHandle) sv82xHandle, AUD_PLY_STATUS_STREAM_OFF);
+
+ return (AudioPlayerHandle) sv82xHandle;
+}
+
+int audioPlayerGetCapability(const AudioPlayerHandle handle, AudioCapability* pCapability)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (!pCapability) {
+ return -EINVAL;
+ }
+
+ *pCapability = sv82xHandle->capability;
+
+ return 0;
+}
+
+int audioPlayerSetFormat(AudioPlayerHandle handle, const AudioFormat format, const AudioChannel channel, const AudioSampleRate sampleRate,
+ const AudioBitDepth bitDepth)
+{
+ EI_S32 s32Ret;
+ ADEC_CHN AdChn = 0;
+ AIO_ATTR_S stAioAttr;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ SV82X_HANDLE_STATUS_CHECK(sv82xHandle, AUD_PLY_STATUS_STREAM_OFF);
+
+ switch (format) {
+ case AUD_FMT_AAC:
+ g_audio_player.paramDecode.payload_type = PT_AAC;
+ break;
+ case AUD_FMT_PCM:
+ g_audio_player.paramDecode.payload_type = PT_LPCM;
+ break;
+ case AUD_FMT_G711A:
+ g_audio_player.paramDecode.payload_type = PT_G711A;
+ break;
+ case AUD_FMT_G711U:
+ g_audio_player.paramDecode.payload_type = PT_G711U;
+ break;
+ case AUD_FMT_OPUS:
+ default:
+ LOG("Unsupported format %d", format);
+ return -EINVAL;
+ }
+
+ if (channel == AUD_CHN_MONO) {
+ g_audio_player.paramDecode.sound_mode = AUDIO_SOUND_MODE_MONO;
+ g_audio_player.paramDecode.u32ChnCnt = 1;
+ } else {
+ g_audio_player.paramDecode.sound_mode = AUDIO_SOUND_MODE_STEREO;
+ g_audio_player.paramDecode.u32ChnCnt = 2;
+ }
+
+ switch (sampleRate) {
+ case AUD_SAM_8K:
+ g_audio_player.paramDecode.samplerate = AUDIO_SAMPLE_RATE_8000;
+ break;
+ case AUD_SAM_16K:
+ g_audio_player.paramDecode.samplerate = AUDIO_SAMPLE_RATE_16000;
+ break;
+ case AUD_SAM_24K:
+ g_audio_player.paramDecode.samplerate = AUDIO_SAMPLE_RATE_24000;
+ break;
+ case AUD_SAM_32K:
+ g_audio_player.paramDecode.samplerate = AUDIO_SAMPLE_RATE_32000;
+ break;
+ case AUD_SAM_44_1K:
+ g_audio_player.paramDecode.samplerate = AUDIO_SAMPLE_RATE_44100;
+ break;
+ case AUD_SAM_48K:
+ g_audio_player.paramDecode.samplerate = AUDIO_SAMPLE_RATE_48000;
+ break;
+ default:
+ LOG("Unsupported sampleRate %d", sampleRate);
+ return -EINVAL;
+ }
+
+ switch (bitDepth) {
+ case AUD_BIT_8:
+ g_audio_player.paramDecode.bitwidth = AUDIO_BIT_WIDTH_8;
+ break;
+ case AUD_BIT_16:
+ g_audio_player.paramDecode.bitwidth = AUDIO_BIT_WIDTH_16;
+ break;
+ case AUD_BIT_32:
+ g_audio_player.paramDecode.bitwidth = AUDIO_BIT_WIDTH_24;
+ break;
+ default:
+ LOG("Unsupported bitDepth %d", bitDepth);
+ return -EINVAL;
+ }
+ sv82xHandle->format = format;
+ sv82xHandle->channel = channel;
+ sv82xHandle->sampleRate = sampleRate;
+ sv82xHandle->bitDepth = bitDepth;
+
+ return 0;
+}
+
+int audioPlayerGetFormat(const AudioPlayerHandle handle, AudioFormat* pFormat, AudioChannel* pChannel, AudioSampleRate* pSampleRate,
+ AudioBitDepth* pBitDepth)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ *pFormat = sv82xHandle->format;
+ *pChannel = sv82xHandle->channel;
+ *pSampleRate = sv82xHandle->sampleRate;
+ *pBitDepth = sv82xHandle->bitDepth;
+
+ return 0;
+}
+
+int audioPlayerAcquireStream(AudioPlayerHandle handle)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ EI_S32 s32Ret;
+ AO_CHN AoChn = 0;
+ ADEC_CHN AdChn = 0;
+ EI_S32 s32AoChnCnt;
+ AIO_ATTR_S stAioAttr;
+ AUDIO_DEV AoDev = g_audio_player.AoDev;
+
+ stAioAttr.enSamplerate = g_audio_player.paramDecode.samplerate;
+ stAioAttr.enBitwidth = g_audio_player.paramDecode.bitwidth;
+ stAioAttr.enSoundmode = g_audio_player.paramDecode.sound_mode;
+ stAioAttr.u32EXFlag = 0;
+ stAioAttr.u32FrmNum = 30;
+ stAioAttr.u32PtNumPerFrm = g_audio_player.paramDecode.num_per_frm;
+ stAioAttr.u32ChnCnt = g_audio_player.paramDecode.u32ChnCnt;
+
+ s32Ret = SAMPLE_COMM_AUDIO_StartAdec(AdChn, &stAioAttr, g_audio_player.paramDecode.payload_type);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StartAdec failed, ret=%d\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ stAioAttr.enSamplerate = g_audio_player.paramDecode.samplerate;
+ stAioAttr.enBitwidth = g_audio_player.paramDecode.bitwidth;
+ stAioAttr.enSoundmode = g_audio_player.paramDecode.sound_mode;
+ stAioAttr.u32EXFlag = 0;
+ stAioAttr.u32FrmNum = 30;
+ stAioAttr.u32PtNumPerFrm = g_audio_player.paramDecode.num_per_frm;
+ stAioAttr.u32ChnCnt = g_audio_player.paramDecode.u32ChnCnt;
+
+ s32AoChnCnt = stAioAttr.u32ChnCnt;
+ s32Ret = SAMPLE_COMM_AUDIO_StartAo(AoDev, s32AoChnCnt, &stAioAttr, g_audio_player.enInSampleRate, g_audio_player.bAioReSample);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StartAo failed, ret=%d\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ if (g_audio_player.enUserGetMode == EI_TRUE) {
+ s32Ret = SAMPLE_COMM_AUDIO_CreatTrdAdeAo(AoDev, AoChn, AdChn, NULL);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_CreatTrdAdeAo failed, ret=%d\n", s32Ret);
+ s32AoChnCnt = stAioAttr.u32ChnCnt >> stAioAttr.enSoundmode;
+ s32Ret |= SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, g_audio_player.bAioReSample);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAo failed, ret=%d\n", s32Ret);
+ }
+ return -EAGAIN;
+ }
+ } else {
+ s32Ret = SAMPLE_COMM_AUDIO_AoLinkAdec(AoDev, AoChn, AdChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_AoLinkAdec failed, ret=%d\n", s32Ret);
+ s32AoChnCnt = stAioAttr.u32ChnCnt >> stAioAttr.enSoundmode;
+ s32Ret |= SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, g_audio_player.bAioReSample);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAo failed, ret=%d\n", s32Ret);
+ }
+ return -EAGAIN;
+ }
+ }
+
+ setStatus(handle, AUD_PLY_STATUS_STREAM_ON);
+
+ return 0;
+}
+
+int audioPlayerWriteFrame(AudioPlayerHandle handle, void* pData, const size_t size)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ AUDIO_STREAM_S stStream;
+ int AdChn = g_audio_player.AdecChn;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ SV82X_HANDLE_STATUS_CHECK(sv82xHandle, AUD_PLY_STATUS_STREAM_ON);
+
+ if (!pData)
+ return -EINVAL;
+
+ if (size <= 0) {
+ s32Ret = EI_MI_ADEC_SendEndOfStream(AdChn, EI_FALSE);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s: EI_MI_ADEC_SendEndOfStream failed:%d!\n", __func__, size);
+ return -EAGAIN;
+ }
+ return 0;
+ }
+
+ memset(&stStream, 0, sizeof(AUDIO_STREAM_S));
+ stStream.pStream = (EI_U8 ATTRIBUTE*) pData;
+ stStream.u32Len = size;
+ s32Ret = EI_MI_ADEC_SendStream(AdChn, &stStream, EI_TRUE);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_ADEC_SendStream(%d) failed with %#x!\n", AdChn, s32Ret);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+int audioPlayerReleaseStream(AudioPlayerHandle handle)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ int s32Ret = EI_SUCCESS;
+ AO_CHN AoChn = g_audio_player.AoChn;
+ ADEC_CHN AdChn = g_audio_player.AdecChn;
+ AUDIO_DEV AoDev = g_audio_player.AoDev;
+ EI_S32 s32AoChnCnt;
+ EI_BOOL bResampleEn = EI_FALSE;
+
+ if (g_audio_player.enUserGetMode == EI_TRUE) {
+ s32Ret = SAMPLE_COMM_AUDIO_DestroyTrdAdec(AdChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_DestroyTrdAdec failed %x\n", s32Ret);
+ return -EAGAIN;
+ }
+ } else {
+ s32Ret = SAMPLE_COMM_AUDIO_AoUnbindAdec(AoDev, AoChn, AdChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_AoUnbindAdec failed %x\n", s32Ret);
+ return -EAGAIN;
+ }
+ }
+
+ s32AoChnCnt = g_audio_player.paramDecode.u32ChnCnt >> g_audio_player.paramDecode.sound_mode;
+ s32Ret = SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, bResampleEn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAo failed %x\n", s32Ret);
+ return -EAGAIN;
+ }
+ s32Ret = SAMPLE_COMM_AUDIO_StopAdec(AdChn);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_AUDIO_StopAdec failed %x\n", s32Ret);
+ return -EAGAIN;
+ }
+ return setStatus(handle, AUD_PLY_STATUS_STREAM_OFF);
+}
+
+void audioPlayerDestory(AudioPlayerHandle handle)
+{
+ if (!handle)
+ return;
+
+ SV82X_HANDLE_GET(handle);
+
+ if (sv82xHandle->status == AUD_PLY_STATUS_STREAM_ON)
+ audioPlayerReleaseStream(handle);
+
+ setStatus(handle, AUD_PLY_STATUS_NOT_READY);
+
+ free(handle);
+}
diff --git a/source/SV82x/SV82xCommon.h b/source/SV82x/SV82xCommon.h
new file mode 100644
index 0000000..e33e9c8
--- /dev/null
+++ b/source/SV82x/SV82xCommon.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+#include "sample_comm.h"
+
+#define LOG(msg, ...) printf(msg "\n", ##__VA_ARGS__)
+
+#define SV82X_HANDLE_NULL_CHECK(x) \
+ if (!(x)) { \
+ return -EINVAL; \
+ }
+#define EI_TRACE_AUDIO(level, fmt, args...) EI_TRACE(EI_ID_AUDIOIN, level, fmt, ##args)
+#define SV82X_HANDLE_STATUS_CHECK(Handle, expectedStatus) \
+ if ((Handle)->status != (expectedStatus)) { \
+ return -EAGAIN; \
+ }
+
+typedef enum {
+ ELF_AUDIO_FRAME_G711A,
+ ELF_AUDIO_FRAME_G711U,
+ ELF_AUDIO_FRAME_ADPCMA,
+ ELF_AUDIO_FRAME_G726,
+ ELF_AUDIO_FRAME_G729,
+ ELF_AUDIO_FRAME_LPCM,
+ ELF_AUDIO_FRAME_AAC,
+ ELF_AUDIO_FRAME_MP3,
+ ELF_AUDIO_FRAME_TYPE_MAX,
+} sv82x_audio_frame_type_e;
+
+typedef enum { ELF_AUDIO_STREAM_CAPTURE, ELF_AUDIO_STREAM_PLAYBACK, ELF_AUDIO_STREAM_MAX } sv82x_audio_stream_e;
+
+typedef struct {
+ PAYLOAD_TYPE_E payload_type; /* payload type */
+ AUDIO_SAMPLE_RATE_E samplerate;
+ unsigned int num_per_frm; /* sample per frame */
+ unsigned int fps; /* frame rate ;default 25*/
+ AUDIO_SOUND_MODE_E sound_mode;
+ AUDIO_BIT_WIDTH_E bitwidth;
+ int volume;
+ unsigned int u32ChnCnt;
+} sv82x_audio_param_t;
+
+typedef struct {
+ int sample_rate;
+ int frame_rate;
+ EI_U32 open_mask; /*AEC | AGC | ANR | EQ | HPF */
+} sv82x_audio_vqe_t;
+
+typedef struct VIDEO_STREAM_CTX {
+ EI_U32 AiDev;
+ EI_U32 AencChn;
+ EI_U32 AdecChn;
+ EI_U32 AoChn;
+ EI_U32 AoDev;
+ EI_U32 u32ChnCnt;
+ sv82x_audio_param_t paramEncode;
+ sv82x_audio_param_t paramDecode;
+ EI_BOOL audio_adec_ao_flag;
+ PAYLOAD_TYPE_E enPayloadType;
+ EI_BOOL bAioReSample;
+ EI_BOOL enInSampleRate;
+ EI_BOOL enOutSampleRate;
+ EI_BOOL enVqe;
+ EI_BOOL enAudioCreate;
+ EI_BOOL enAencCreate;
+ EI_BOOL enUserGetMode;
+ sv82x_audio_vqe_t audio_vqe;
+ EI_CHAR playFileName[512];
+} sv82x_audio_stream_info_t;
diff --git a/source/SV82x/SV82xVideoCapturer.c b/source/SV82x/SV82xVideoCapturer.c
new file mode 100644
index 0000000..4a5b743
--- /dev/null
+++ b/source/SV82x/SV82xVideoCapturer.c
@@ -0,0 +1,699 @@
+/*
+ * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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
+#include
+#include
+#include
+#include
+#include
+#include "errno.h"
+#include "com/amazonaws/kinesis/video/capturer/VideoCapturer.h"
+#include "SV82xCommon.h"
+#include "sample_comm.h"
+
+#define SV82X_VIDEO_STREAM_1080P_CHN (0)
+#define SV82X_VIDEO_STREAM_720P_CHN (1)
+#define SV82X_VIDEO_STREAM_LOW_RES_CHN (2)
+#define SV82X_VIDEO_STREAM_CHN_NUM (3)
+
+#define SV82X_VIDEO_STREAM_FPS (30)
+#define SV82X_VIDEO_STREAM_BITRATE (2 * 1024 * 1024)
+#define SV82X_VIDEO_STREAM_GOP (30)
+#define SV82X_VIDEO_RC_MODE (SAMPLE_RC_VBR)
+
+#define SV82X_IPPU_DEV (0)
+#define SV82X_ISP_DEV (0)
+
+#define SV82X_HANDLE_NULL_CHECK_RET_VOID(x) \
+ do { \
+ if (x == EI_NULL) { \
+ LOG("Null Pointer!\n"); \
+ return; \
+ } \
+ } while (0)
+
+#define SV82X_HANDLE_GET(x) Sv82xVideoCapturer_t* Sv82xHandle = (Sv82xVideoCapturer_t*) ((x))
+
+typedef struct {
+ VideoCapturerStatus status;
+ VideoCapability capability;
+ VideoFormat format;
+ VideoResolution resolution;
+ uint8_t channel;
+ VBUF_POOL Pool;
+ uint8_t VideoCreatFlag;
+ uint8_t enable;
+} Sv82xVideoCapturer_t;
+
+typedef struct {
+ SAMPLE_VISS_CONFIG_S stVissConfig;
+ int VideoCreatHandleCnt;
+ int IppuEnableCnt;
+} Sv82xVideoInfo_t;
+static Sv82xVideoInfo_t VideoAttrs = {0};
+static int SystemInitFlag = 0;
+
+static int SystemInit(void)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+
+ SNS_TYPE_E enSnsType;
+ VISS_PIC_TYPE_E stPicType = {0};
+ IPPU_DEV_ATTR_S stDevAttr = {0};
+ SAMPLE_VISS_CONFIG_S stVissConfig;
+
+ EI_MI_MBASE_Init();
+ EI_MI_VBUF_Init();
+ EI_MI_MLINK_Init();
+
+ enSnsType = GC4663_MIPI_2560_1440_30FPS_RAW10;
+ memset(&VideoAttrs.stVissConfig, 0, sizeof(SAMPLE_VISS_CONFIG_S));
+ stVissConfig = VideoAttrs.stVissConfig;
+ stVissConfig.astVissInfo[0].stDevInfo.VissDev = (enSnsType < 200000) ? 0 : 1;
+ stVissConfig.astVissInfo[0].stDevInfo.aBindPhyChn[0] = 0;
+ stVissConfig.astVissInfo[0].stDevInfo.enOutPath = VISS_OUT_PATH_PIXEL;
+ stVissConfig.astVissInfo[0].stChnInfo.aVissChn[0] = 0;
+ stVissConfig.astVissInfo[0].stChnInfo.enWorkMode = VISS_WORK_MODE_1Chn;
+ stVissConfig.astVissInfo[0].stIspInfo.IspDev = SV82X_ISP_DEV;
+ stVissConfig.astVissInfo[0].stIspInfo.enRunningMode = ISP_MODE_RUNNING_ONLINE;
+ stVissConfig.astVissInfo[0].stSnsInfo.enSnsType = enSnsType;
+ stVissConfig.s32WorkingVissNum = 1;
+
+ s32Ret = SAMPLE_COMM_ISP_Start(&stVissConfig.astVissInfo[0]);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_ISP_Start failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = SAMPLE_COMM_VISS_StartViss(&stVissConfig);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_VISS_StartViss failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = SAMPLE_COMM_VISS_GetPicTypeBySensor(enSnsType, &stPicType);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_VISS_GetPicTypeBySensor failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ stDevAttr.s32IppuDev = SV82X_IPPU_DEV;
+ stDevAttr.u32DataSrc = (enSnsType < 200000) ? 0 : 1;
+ stDevAttr.u32InputWidth = stPicType.stSize.u32Width;
+ stDevAttr.u32InputHeight = stPicType.stSize.u32Height;
+ stDevAttr.enRunningMode = IPPU_MODE_RUNNING_ONLINE;
+ s32Ret = EI_MI_IPPU_Create(SV82X_IPPU_DEV, &stDevAttr);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_IPPU_Create failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+ s32Ret = EI_MI_IPPU_Start(SV82X_IPPU_DEV);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_IPPU_Start failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static int SystemDeinit(void)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+ SAMPLE_VISS_CONFIG_S stVissConfig;
+
+ s32Ret = EI_MI_IPPU_Stop(SV82X_IPPU_DEV);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_IPPU_Stop failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = EI_MI_IPPU_Destroy(SV82X_IPPU_DEV);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_IPPU_Destroy failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ stVissConfig = VideoAttrs.stVissConfig;
+ s32Ret = SAMPLE_COMM_VISS_StopViss(&stVissConfig);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_VISS_StopViss failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = SAMPLE_COMM_ISP_Stop(SV82X_IPPU_DEV);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_ISP_Stop failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ EI_MI_MLINK_Exit();
+ EI_MI_VBUF_Exit();
+ EI_MI_MBASE_Exit();
+
+ return 0;
+}
+
+static int setStatus(VideoCapturerHandle handle, const VideoCapturerStatus newStatus)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (newStatus != Sv82xHandle->status) {
+ Sv82xHandle->status = newStatus;
+ LOG("VideoCapturer new status[%d]", newStatus);
+ }
+
+ return 0;
+}
+
+static int _Sv82xVideoBufPoolCreat(VideoCapturerHandle handle, VIDEO_FRAME_INFO_S* pstVideoFrameInfo)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+ VBUF_POOL_CONFIG_S stPoolCfg = {0};
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ stPoolCfg.u32BufSize = EI_MI_VBUF_GetPicBufferSize(pstVideoFrameInfo);
+ stPoolCfg.u32BufCnt = 4;
+ stPoolCfg.enRemapMode = VBUF_REMAP_MODE_NOCACHE;
+ stPoolCfg.enVbufUid = VBUF_UID_COMMON;
+ /* create buffer pool */
+ Sv82xHandle->Pool = EI_MI_VBUF_CreatePool(&stPoolCfg);
+ /* set buffer pool info */
+ s32Ret = EI_MI_VBUF_SetFrameInfo(Sv82xHandle->Pool, pstVideoFrameInfo);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_VBUF_SetFrameInfo failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static int _Sv82xVideoBufPoolDestory(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ s32Ret = EI_MI_VBUF_DestroyPool(Sv82xHandle->Pool);
+ if (s32Ret) {
+ LOG("EI_MI_VBUF_DestroyPool error s32Ret:%d\n", s32Ret);
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static int _Sv82xIppuStart(VideoCapturerHandle handle, const IPPU_CHN_ATTR_S* pstChnAttr)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+ IPPU_DEV dev = 0;
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ s32Ret = EI_MI_IPPU_SetChnAttr(dev, Sv82xHandle->channel, pstChnAttr);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d EI_MI_IPPU_SetChnAttr failed\n", __func__, __LINE__);
+ EI_MI_IPPU_Destroy(dev);
+ return -EAGAIN;
+ }
+ s32Ret = EI_MI_IPPU_EnableChn(dev, Sv82xHandle->channel);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d EI_MI_IPPU_EnableChn failed\n", __func__, __LINE__);
+ EI_MI_IPPU_Destroy(dev);
+ return -EAGAIN;
+ }
+ Sv82xHandle->enable = 1;
+ VideoAttrs.IppuEnableCnt++;
+
+ return 0;
+}
+
+static int _Sv82xIppuStop(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ IPPU_DEV dev = 0;
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ LOG("%s chn is :%d\n", __func__, Sv82xHandle->channel);
+ if (!Sv82xHandle->enable) {
+ LOG("ippu channel:%d is disable\n", Sv82xHandle->channel);
+ return -EINVAL;
+ }
+
+ if (Sv82xHandle->channel >= IPPU_PHY_CHN_MAX_NUM || Sv82xHandle->channel < 0) {
+ LOG("channel:%d is illegal\n", Sv82xHandle->channel);
+ return -EINVAL;
+ }
+
+ s32Ret = EI_MI_IPPU_DisableChn(dev, Sv82xHandle->channel);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("IPPU_DisableChn failed with %d!\n", s32Ret);
+ return -EAGAIN;
+ }
+ Sv82xHandle->enable = 0;
+ VideoAttrs.IppuEnableCnt--;
+
+ return 0;
+}
+
+static int _Sv82xVideoCreat(VideoCapturerHandle handle, const VideoFormat format, SAMPLE_VENC_CONFIG_S* pstSamplVenc)
+{
+ EI_S32 s32Ret = 0, RcMode = 0, GopMode = 0, PayloadType = 0;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ RcMode = SV82X_VIDEO_RC_MODE;
+ GopMode = VENC_GOPMODE_NORMAL_P;
+ switch (format) {
+ case VID_FMT_H264:
+ PayloadType = PT_H264;
+ break;
+ case VID_FMT_H265:
+ PayloadType = PT_H265;
+ break;
+ default:
+ LOG("Unsupported format %d", format);
+ return -EINVAL;
+ }
+
+ if (PayloadType == PT_H264 || PayloadType == PT_H265) {
+ s32Ret = SAMPLE_COMM_VENC_Creat(Sv82xHandle->channel, PayloadType, RcMode, pstSamplVenc, COMPRESS_MODE_NONE, GopMode);
+ if (EI_SUCCESS != s32Ret) {
+ LOG("SAMPLE_COMM_VENC_Creat faild with%#x! \n", s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = SAMPLE_COMM_IPPU_Link_VPU(0, Sv82xHandle->channel, Sv82xHandle->channel);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_IPPU_Link_VPU failed with %#x\n", s32Ret);
+ EI_MI_VENC_DestroyChn(Sv82xHandle->channel);
+ return -EAGAIN;
+ }
+ }
+ Sv82xHandle->VideoCreatFlag = 1;
+ return 0;
+}
+
+static int _Sv82xVideoDestory(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = 0;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ s32Ret = SAMPLE_COMM_IPPU_UnLink_VPU(0, Sv82xHandle->channel, Sv82xHandle->channel);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SAMPLE_COMM_IPPU_UnLink_VPU failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+ s32Ret = EI_MI_VENC_DestroyChn(Sv82xHandle->channel);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_VENC_DestroyChn failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+ Sv82xHandle->VideoCreatFlag = 0;
+
+ return 0;
+}
+
+static int _Sv82xVideoStart(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = 0;
+ VENC_RECV_PIC_PARAM_S stRecvParam = {0};
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ stRecvParam.s32RecvPicNum = -1;
+ s32Ret = EI_MI_VENC_StartRecvFrame(Sv82xHandle->channel, &stRecvParam);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_VENC_StartRecvFrame failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+ setStatus(handle, VID_CAP_STATUS_STREAM_ON);
+
+ return 0;
+}
+
+static int _Sv82xVideoStop(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = 0;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ s32Ret = EI_MI_VENC_StopRecvFrame(Sv82xHandle->channel);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("EI_MI_VENC_StopRecvFrame failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ setStatus(handle, VID_CAP_STATUS_STREAM_OFF);
+
+ return 0;
+}
+
+VideoCapturerHandle videoCapturerCreate(void)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ Sv82xVideoCapturer_t* Handle = NULL;
+ if (VideoAttrs.VideoCreatHandleCnt >= SV82X_VIDEO_STREAM_CHN_NUM)
+ return NULL;
+ if (!(Handle = (Sv82xVideoCapturer_t*) malloc(sizeof(Sv82xVideoCapturer_t)))) {
+ LOG("%s:%d oom\n", __func__, __LINE__);
+ return NULL;
+ }
+ memset(Handle, 0, sizeof(Sv82xVideoCapturer_t));
+
+ if (!SystemInitFlag) {
+ s32Ret = SystemInit();
+ if (s32Ret) {
+ LOG("%s:%d SystemInit\n", __func__, __LINE__);
+ free(Handle);
+ return NULL;
+ }
+ }
+ SystemInitFlag = 1;
+ Handle->capability.formats = (1 << (VID_FMT_H264 - 1)) | (1 << (VID_FMT_H265 - 1)) | (1 << (VID_FMT_RAW - 1));
+ Handle->capability.resolutions =
+ (1 << (VID_RES_1080P - 1)) | (1 << (VID_RES_720P - 1)) | (1 << (VID_RES_480P - 1)) | (1 << (VID_RES_360P - 1)) | (1 << (VID_RES_320P - 1));
+
+ setStatus((VideoCapturerHandle) Handle, VID_CAP_STATUS_STREAM_OFF);
+
+ VideoAttrs.VideoCreatHandleCnt++;
+
+ return (VideoCapturerHandle) Handle;
+}
+
+VideoCapturerStatus videoCapturerGetStatus(const VideoCapturerHandle const handle)
+{
+ if (!handle) {
+ return VID_CAP_STATUS_NOT_READY;
+ }
+
+ SV82X_HANDLE_GET(handle);
+ return Sv82xHandle->status;
+}
+
+int videoCapturerGetCapability(const VideoCapturerHandle const handle, VideoCapability* pCapability)
+{
+ EI_S32 s32Ret = EI_SUCCESS;
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (!pCapability)
+ return -EINVAL;
+
+ *pCapability = Sv82xHandle->capability;
+
+ return 0;
+}
+
+int videoCapturerSetFormat(VideoCapturerHandle const handle, const VideoFormat format, const VideoResolution resolution)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+ EI_S32 width = 0, height = 0;
+ VIDEO_FRAME_INFO_S stVideoFrameInfo = {0};
+ IPPU_CHN_ATTR_S ippu_chn_attr = {0};
+ SAMPLE_VENC_CONFIG_S stSamplVenc = {0};
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ SV82X_HANDLE_STATUS_CHECK(Sv82xHandle, VID_CAP_STATUS_STREAM_OFF);
+
+ switch (resolution) {
+ case VID_RES_1080P:
+ Sv82xHandle->channel = SV82X_VIDEO_STREAM_1080P_CHN;
+ width = 1920;
+ height = 1080;
+ break;
+ case VID_RES_720P:
+ Sv82xHandle->channel = SV82X_VIDEO_STREAM_720P_CHN;
+ width = 1280;
+ height = 720;
+ break;
+ case VID_RES_480P:
+ Sv82xHandle->channel = SV82X_VIDEO_STREAM_LOW_RES_CHN;
+ width = 640;
+ height = 480;
+ break;
+ case VID_RES_360P:
+ Sv82xHandle->channel = SV82X_VIDEO_STREAM_LOW_RES_CHN;
+ width = 480;
+ height = 360;
+ break;
+ case VID_RES_320P:
+ Sv82xHandle->channel = SV82X_VIDEO_STREAM_LOW_RES_CHN;
+ width = 416;
+ height = 320;
+ break;
+ default:
+ LOG("Unsupported resolution %d", resolution);
+ return -EINVAL;
+ }
+ // creat buf pool
+ stVideoFrameInfo.enFrameType = MDP_FRAME_TYPE_COMMON;
+ stVideoFrameInfo.stCommFrameInfo.u32Align = 32;
+ stVideoFrameInfo.stCommFrameInfo.u32Width = width;
+ stVideoFrameInfo.stCommFrameInfo.u32Height = height;
+ stVideoFrameInfo.stCommFrameInfo.enPixelFormat = PIX_FMT_YUV_SEMIPLANAR_420;
+ s32Ret = _Sv82xVideoBufPoolCreat(handle, &stVideoFrameInfo);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d _sv82x_video_init failed\n", __func__, __LINE__);
+ return -EAGAIN;
+ }
+
+ // set ippu chn attrs and enable ippu chn
+ ippu_chn_attr.s32Chn = Sv82xHandle->channel;
+ ippu_chn_attr.u32Width = width;
+ ippu_chn_attr.u32Height = height;
+ ippu_chn_attr.enPixelFormat = PIX_FMT_YUV_SEMIPLANAR_420;
+ ippu_chn_attr.u32Align = 32;
+ ippu_chn_attr.stFrameRate.s32DstFrameRate = SV82X_VIDEO_STREAM_FPS;
+ ippu_chn_attr.stFrameRate.s32SrcFrameRate = SV82X_VIDEO_STREAM_FPS;
+ if (format == VID_FMT_RAW)
+ ippu_chn_attr.u32Depth = 1;
+ else
+ ippu_chn_attr.u32Depth = 0;
+ ippu_chn_attr.enCompressMode = COMPRESS_MODE_NONE;
+
+ s32Ret = _Sv82xIppuStart(handle, &ippu_chn_attr);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d _Sv82xIppuStart failed\n", __func__, __LINE__);
+ return -EAGAIN;
+ }
+ if (format != VID_FMT_RAW) {
+ // vpu chn creat
+ stSamplVenc.enInputFormat = PIX_FMT_YUV_SEMIPLANAR_420;
+ stSamplVenc.u32width = width;
+ stSamplVenc.u32height = height;
+ stSamplVenc.u32bitrate = SV82X_VIDEO_STREAM_BITRATE;
+ stSamplVenc.u32srcframerate = SV82X_VIDEO_STREAM_FPS;
+ stSamplVenc.u32dstframerate = SV82X_VIDEO_STREAM_FPS;
+ s32Ret = _Sv82xVideoCreat(handle, format, &stSamplVenc);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d _Sv82xVideoCreat failed\n", __func__, __LINE__);
+ return -EAGAIN;
+ }
+ }
+
+ Sv82xHandle->format = format;
+ Sv82xHandle->resolution = resolution;
+
+ return 0;
+}
+
+int videoCapturerGetFormat(const VideoCapturerHandle const handle, VideoFormat* pFormat, VideoResolution* pResolution)
+{
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+
+ *pFormat = Sv82xHandle->format;
+ *pResolution = Sv82xHandle->resolution;
+ return 0;
+}
+
+int videoCapturerAcquireStream(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+
+ s32Ret = _Sv82xVideoStart(handle);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("_Sv82xVideoStart failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+int videoCapturerGetFrame(VideoCapturerHandle handle, void* pFrameDataBuffer, const size_t frameDataBufferSize, uint64_t* pTimestamp,
+ size_t* pFrameSize)
+{
+ EI_S32 s32Ret = -1;
+ VENC_CHN_STATUS_S stStatus = {0};
+ VENC_STREAM_S stStream = {0};
+ VENC_STREAM_S VencStream = {0};
+ VIDEO_FRAME_INFO_S stVFrameInfo = {0};
+ VC_CHN channel;
+ EI_U32 data_len = 0;
+
+ SV82X_HANDLE_NULL_CHECK(handle);
+ SV82X_HANDLE_GET(handle);
+ channel = Sv82xHandle->channel;
+ if (Sv82xHandle->format == VID_FMT_RAW) {
+ s32Ret = EI_MI_IPPU_GetChnFrame(0, channel, &stVFrameInfo, 2000);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d EI_MI_IPPU_GetChnFrame chn-%d error : %d\n", __func__, __LINE__, channel, s32Ret);
+ return -EAGAIN;
+ }
+
+ EI_MI_VBUF_FrameMmap(&stVFrameInfo, VBUF_REMAP_MODE_CACHED);
+ if (((char*) stVFrameInfo.stVFrame.ulPlaneVirAddr[0] != NULL) && (stVFrameInfo.stVFrame.u32PlaneSize[0] != 0) &&
+ ((char*) stVFrameInfo.stVFrame.ulPlaneVirAddr[1] != NULL) && (stVFrameInfo.stVFrame.u32PlaneSize[1] != 0)) {
+ *pFrameSize = stVFrameInfo.stCommFrameInfo.u32Width * stVFrameInfo.stCommFrameInfo.u32Height * 1.5;
+ }
+ memset(pFrameDataBuffer, 0, frameDataBufferSize);
+ if (*pFrameSize <= frameDataBufferSize) {
+ if (((char*) stVFrameInfo.stVFrame.ulPlaneVirAddr[0] != NULL) && (stVFrameInfo.stVFrame.u32PlaneSize[0] != 0)) {
+ memcpy(pFrameDataBuffer, (char*) stVFrameInfo.stVFrame.ulPlaneVirAddr[0],
+ stVFrameInfo.stCommFrameInfo.u32Width * stVFrameInfo.stCommFrameInfo.u32Height);
+ if (((char*) stVFrameInfo.stVFrame.ulPlaneVirAddr[1] != NULL) && (stVFrameInfo.stVFrame.u32PlaneSize[1] != 0)) {
+ memcpy(pFrameDataBuffer + stVFrameInfo.stCommFrameInfo.u32Width * stVFrameInfo.stCommFrameInfo.u32Height,
+ (char*) stVFrameInfo.stVFrame.ulPlaneVirAddr[1],
+ stVFrameInfo.stCommFrameInfo.u32Width * stVFrameInfo.stCommFrameInfo.u32Height * 0.5);
+ }
+ }
+ } else
+ LOG("ch:%d data len is to big datalen:%d buflen:%d\n", channel, *pFrameSize, frameDataBufferSize);
+ *pTimestamp = stVFrameInfo.stVFrame.u64PTS;
+ EI_MI_IPPU_ReleaseChnFrame(0, channel, &stVFrameInfo);
+ } else if (Sv82xHandle->format == VID_FMT_H264 || Sv82xHandle->format == VID_FMT_H265) {
+ s32Ret = EI_MI_VENC_QueryStatus(channel, &stStatus);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("%s:%d query status chn-%d error : %d\n", __func__, __LINE__, channel, s32Ret);
+ return -EAGAIN;
+ }
+
+ s32Ret = EI_MI_VENC_GetStream(channel, &stStream, 1000);
+ if (s32Ret == EI_ERR_VENC_NOBUF) {
+ LOG("No buffer\n");
+ return -EAGAIN;
+ } else if (s32Ret != EI_SUCCESS) {
+ LOG("get stream chn-%d error : %d\n", channel, s32Ret);
+ return -EAGAIN;
+ }
+
+ memset(&VencStream, 0, sizeof(VENC_STREAM_S));
+ memcpy(&VencStream, &stStream, sizeof(VENC_STREAM_S));
+
+ if ((VencStream.pstPack.pu8Addr[0] != EI_NULL) && (VencStream.pstPack.u32Len[0] != 0)) {
+ data_len = VencStream.pstPack.u32Len[0];
+ if ((VencStream.pstPack.pu8Addr[1] != EI_NULL) && (VencStream.pstPack.u32Len[1] != 0))
+ data_len += VencStream.pstPack.u32Len[1];
+ }
+
+ if (pFrameDataBuffer == NULL) {
+ LOG("pFrameDataBuffer is null\n");
+ EI_MI_VENC_ReleaseStream(channel, &stStream);
+ return -EAGAIN;
+ }
+
+ *pFrameSize = data_len;
+ memset(pFrameDataBuffer, 0, frameDataBufferSize);
+ if (frameDataBufferSize < *pFrameSize) {
+ LOG("ch:%d data len is to big datalen:%d buflen:%d\n", channel, *pFrameSize, frameDataBufferSize);
+ EI_MI_VENC_ReleaseStream(channel, &stStream);
+ return -EAGAIN;
+ }
+
+ if ((VencStream.pstPack.pu8Addr[0] != EI_NULL) && (VencStream.pstPack.u32Len[0] != 0)) {
+ memcpy(pFrameDataBuffer, VencStream.pstPack.pu8Addr[0], VencStream.pstPack.u32Len[0]);
+ if ((VencStream.pstPack.pu8Addr[1] != EI_NULL) && (VencStream.pstPack.u32Len[1] != 0))
+ memcpy(pFrameDataBuffer + VencStream.pstPack.u32Len[0], VencStream.pstPack.pu8Addr[1], VencStream.pstPack.u32Len[1]);
+ }
+ *pTimestamp = stStream.pstPack.u64PTS;
+ s32Ret = EI_MI_VENC_ReleaseStream(channel, &stStream);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("release stream chn-%d error s32Ret: %d\n", channel, s32Ret);
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+
+int videoCapturerReleaseStream(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+
+ s32Ret = _Sv82xVideoStop(handle);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("_Sv82xVideoStop failed with %#x\n", s32Ret);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+void videoCapturerDestory(VideoCapturerHandle handle)
+{
+ EI_S32 s32Ret = EI_FAILURE;
+
+ SV82X_HANDLE_NULL_CHECK_RET_VOID(handle);
+ SV82X_HANDLE_GET(handle);
+
+ if (Sv82xHandle->status == VID_CAP_STATUS_STREAM_ON) {
+ s32Ret = videoCapturerReleaseStream(handle);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("videoCapturerReleaseStream failed with %#x\n", s32Ret);
+ return;
+ }
+ }
+
+ if (Sv82xHandle->VideoCreatFlag) {
+ s32Ret = _Sv82xVideoDestory(handle);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("_Sv82xVideoDestory failed with %#x\n", s32Ret);
+ return;
+ }
+ }
+ if (Sv82xHandle->enable) {
+ s32Ret = _Sv82xIppuStop(handle);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("_Sv82xIppuStop failed with %#x\n", s32Ret);
+ return;
+ }
+ }
+
+ s32Ret = _Sv82xVideoBufPoolDestory(handle);
+ if (s32Ret != EI_SUCCESS) {
+ LOG("_Sv82xVideoBufPoolDestory failed with %#x\n", s32Ret);
+ return;
+ }
+ VideoAttrs.VideoCreatHandleCnt--;
+ if (VideoAttrs.IppuEnableCnt == 0) {
+ s32Ret = SystemDeinit();
+ if (s32Ret != EI_SUCCESS) {
+ LOG("SystemDeinit failed with %#x\n", s32Ret);
+ return;
+ }
+ }
+
+ SystemInitFlag = 0;
+
+ return;
+}