Pullrequest mis5001 clear patch 0305 (#242)

* project/app : Add uvc_app_tiny application

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC/overlay : Add Ubuntu system support for Rockit and RKNN libraries

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/drivers/of : Add support for dynamic device tree

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/drivers/usb/serial : Add CH343 driver support

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/drivers/staging : Disable partial logging of fbtft

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/drivers/pinctrl/pinctrl-rockchip.h : Fix pinctrl configuration failure issue

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/include/dt-bindings/soc/rockchip,boot-mode.h : Add support for the reboot U-Boot command in the BusyBox system

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/drivers/video : Add logo display support for LF40-480480-ARK and LF40-720720-ARK

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm/boot/dts : Add device tree files for the Luckfox RV1103/RV1106 series boards

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm/configs : Add device tree files for the Luckfox RV1103/RV1106 series boards

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/uboot/u-boot/drivers/mmc/mmc.c : Fix the issue where some Micro SD cards fail to boot

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/uboot/u-boot/common/image-fit.c : Add U-Boot support for luckfox-config

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/uboot/rkbin/bin/rv11 : Add firmware with a serial baud rate of 115200 and back up the original firmware

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/uboot/u-boot/arch/arm/dts : Add device tree files for the Luckfox RV1103/RV1106 series boards

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/uboot/u-boot/configs : Add defconfig files for the Luckfox RV1103/RV1106 series boards

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/uboot/u-boot : Add support for the reboot U-Boot command in the BusyBox system

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/drivers/media/i2c : Add MIS5001 driver support

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm : Add default support for MIS5001 on Luckfox RV1106 series boards

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/tools/board : Delete irrelevant overwrite files and patch files

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/drv_ko/insmod_ko.sh : Register mis5001 driver during boot process

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* media/isp/release_camera_engine_rkaiq_rv1106_arm-rockchip830-linux-uclibcgnueabihf/isp_iqfiles : Add mis5001 iqfile

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/app/rkipc/rkipc/src/rv1106_ipc : Add rkipc application support for mis5001 sensor

Signed-off-by: eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC : Enable default retrieval of mis5001 iqfile and include ROCKIT and RKNN libraries of RV1106 series board

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/build.sh : Remove operations related to applying and deleting patches

Signed-off-by: eng29 <eng29@luckfox.com>

* project/build.sh : Modify build system menu description; Apply lightweight system processing only during Buildroot and BusyBox system compilation

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/tools/board/buildroot/luckfox_pico_w_defconfig : Add pppd and pgrep for 4G module

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/tools/board/kernel/rv1106-luckfox-pico-ultra-ipc.dtsi : Add uart4m1 support for lastest luckfox-config tool

Signed-off-by: eng29 <eng29@luckfox.com>

---------

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
Signed-off-by: eng29 <eng29@luckfox.com>
This commit is contained in:
luckfox-eng29
2025-03-05 17:21:58 +08:00
committed by GitHub
parent a4230afbf4
commit 485f09ece6
208 changed files with 44172 additions and 15059 deletions

View File

@@ -69,6 +69,7 @@ install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
install(FILES rkipc-300w.ini DESTINATION share)
install(FILES rkipc-400w.ini DESTINATION share)
install(FILES rkipc-500w.ini DESTINATION share)
install(FILES rkipc-mis5001-500w.ini DESTINATION share)
install(FILES rkipc-800w.ini DESTINATION share)
install(FILES ../../common/speaker_test.wav DESTINATION share)
install(PROGRAMS RkLunch.sh DESTINATION bin)

View File

@@ -73,6 +73,10 @@ post_chk() {
default_rkipc_ini=/tmp/rkipc-factory-config.ini
if [ ! -f "/oem/usr/share/rkipc.ini" ]; then
lsmod | grep mis5001
if [ $? -eq 0 ]; then
ln -s -f /oem/usr/share/rkipc-mis5001-500w.ini $default_rkipc_ini
fi
lsmod | grep sc530ai
if [ $? -eq 0 ]; then
ln -s -f /oem/usr/share/rkipc-500w.ini $default_rkipc_ini

View File

@@ -0,0 +1,542 @@
[audio.0]
enable = 0
card_name = hw:0,0
encode_type = G711A
format = S16
sample_rate = 8000
channels = 1
frame_size = 1152
bit_rate = 16000
input = mic_in
volume = 50
enable_aed = 0
enable_bcd = 0
enable_vqe = 1
vqe_cfg = /oem/usr/share/vqefiles/config_aivqe.json
[video.source]
enable_aiq = 1
enable_vo = 0
vo_dev_id = 3 ; 0 is hdmi, 3 is mipi
enable_ivs = 1
enable_jpeg = 1
enable_venc_0 = 1
enable_venc_1 = 1
enable_venc_2 = 0
enable_npu = 0
npu_fps = 10
enable_rtsp = 1
enable_rtmp = 0
rotation = 0 ; available value:0 90 180 270
[video.0]
buffer_size = 2519424 ; w * h / 2
buffer_count = 4
enable_refer_buffer_share = 1
stream_type = mainStream
video_type = compositeStream
max_width = 2592
max_height = 1944
width = 2592
height = 1944
rc_mode = CBR
rc_quality = high
src_frame_rate_den = 1
src_frame_rate_num = 25
dst_frame_rate_den = 1
dst_frame_rate_num = 25
target_rate = 0
mid_rate = 2048
max_rate = 4096
min_rate = 0
output_data_type = H.265
smart = close
h264_profile = high
gop = 50
smartp_viridrlen = 25
gop_mode = normalP
stream_smooth = 50
enable_motion_deblur = 1
motion_deblur_strength = 3
enable_motion_static_switch = 0
frame_min_i_qp = 26
frame_min_qp = 28
frame_max_i_qp = 51
frame_max_qp = 51
scalinglist = 0
enable_debreath_effect = 0
debreath_effect_strength = 16
thrd_i = 0,0,0,0,3,3,5,5,8,8,8,15,15,20,25,25
thrd_p = 0,0,0,0,3,3,5,5,8,8,8,15,15,20,25,25
aq_step_i = -8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,7,8
aq_step_p = -8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,7,8
qbias_enable = 1
qbias_i = 171
qbias_p = 85
flt_str_i = 0
flt_str_p = 0
cu_dqp = 1
anti_ring = 2
anti_line = 2
lambds = 4
[video.1]
input_buffer_count = 2 ; only wrap can use one buffer
buffer_size = 202752 ; w * h / 2
buffer_count = 4
enable_refer_buffer_share = 1
stream_type = subStream
video_type = compositeStream
max_width = 704
max_height = 576
width = 704
height = 576
rc_mode = CBR
rc_quality = high
src_frame_rate_den = 1
src_frame_rate_num = 25
dst_frame_rate_den = 1
dst_frame_rate_num = 25
target_rate = 0
mid_rate = 256
max_rate = 512
min_rate = 0
output_data_type = H.265
smart = close
h264_profile = high
gop = 50
smartp_viridrlen = 25
gop_mode = normalP
stream_smooth = 50
enable_motion_deblur = 1
motion_deblur_strength = 3
enable_motion_static_switch = 0
frame_min_i_qp = 26
frame_min_qp = 28
frame_max_i_qp = 51
frame_max_qp = 51
scalinglist = 0
enable_debreath_effect = 0
debreath_effect_strength = 16
cu_dqp = 1
anti_ring = 2
anti_line = 2
lambds = 4
[video.2]
max_width = 960
max_height = 540
width = 960
height = 540
[ivs]
smear = 0
weightp = 0
md = 1
od = 1
md_sensibility = 3 ;available: 1 2 3,max 3
[video.jpeg]
width = 1920
height = 1080
jpeg_buffer_size = 1048576 ; 1024KB
jpeg_qfactor = 70
enable_cycle_snapshot = 0
snapshot_interval_ms = 1000
[isp]
scenario = normal ; normal or custom1
init_form_ini = 1
normal_scene = day
custom1_scene = night
ircut_open_gpio = 36
ircut_close_gpio = 35
; isp.0
[isp.0.adjustment]
contrast = 50
brightness = 50
saturation = 50
sharpness = 50
fps = 25
hue = 50
[isp.0.exposure]
iris_type = auto
exposure_mode = auto
gain_mode = auto
auto_iris_level = 5
auto_exposure_enabled = 1
audo_gain_enabled = 1
exposure_time = 1/6
exposure_gain = 1
[isp.0.night_to_day]
night_to_day = day
night_to_day_filter_level = 5
night_to_day_filter_time = 5
dawn_time = 07:00:00
dusk_time = 18:00:00
ircut_filter_action = day
over_exposure_suppress = open
over_exposure_suppress_type = auto
fill_light_mode = IR
brightness_adjustment_mode = auto
light_brightness = 1
distance_level = 1
[isp.0.blc]
blc_region = close
blc_strength = 1
wdr = close
wdr_level = 0
hdr = close
hdr_level = 1
hlc = close
hlc_level = 0
dark_boost_level = 0
position_x = 0
position_y = 0
blc_region_width = 120
blc_region_high = 92
[isp.0.white_blance]
white_blance_style = autoWhiteBalance
white_blance_red = 50
white_blance_green = 50
white_blance_blue = 50
[isp.0.enhancement]
noise_reduce_mode = close
denoise_level = 50
spatial_denoise_level = 50
temporal_denoise_level = 50
dehaze = close
dehaze_level = 0
dis = close
gray_scale_mode = [0-255]
distortion_correction = close
ldch_level = 0
[isp.0.video_adjustment]
image_flip = close
scene_mode = indoor
power_line_frequency_mode = PAL(50HZ)
[isp.0.auto_focus]
af_mode = semi-auto
zoom_level = 0
focus_level = 0
; isp.1
[isp.1.adjustment]
contrast = 50
brightness = 75
saturation = 50
sharpness = 50
fps = 25
hue = 50
[isp.1.exposure]
iris_type = auto
exposure_mode = auto
gain_mode = auto
auto_iris_level = 5
auto_exposure_enabled = 1
audo_gain_enabled = 1
exposure_time = 1/6
exposure_gain = 1
[isp.1.night_to_day]
night_to_day = day
night_to_day_filter_level = 5
night_to_day_filter_time = 5
dawn_time = 07:00:00
dusk_time = 18:00:00
ircut_filter_action = day
over_exposure_suppress = open
over_exposure_suppress_type = auto
fill_light_mode = IR
brightness_adjustment_mode = auto
light_brightness = 1
distance_level = 1
[isp.1.blc]
blc_region = close
blc_strength = 1
wdr = close
wdr_level = 0
hdr = close
hdr_level = 1
hlc = close
hlc_level = 0
dark_boost_level = 0
position_x = 0
position_y = 0
blc_region_width = 120
blc_region_high = 92
[isp.1.white_blance]
white_blance_style = autoWhiteBalance
white_blance_red = 50
white_blance_green = 50
white_blance_blue = 50
[isp.1.enhancement]
noise_reduce_mode = close
denoise_level = 50
spatial_denoise_level = 50
temporal_denoise_level = 50
dehaze = close
dehaze_level = 0
dis = close
gray_scale_mode = [0-255]
distortion_correction = close
ldch_level = 0
[isp.1.video_adjustment]
image_flip = close
scene_mode = indoor
power_line_frequency_mode = PAL(50HZ)
[isp.1.auto_focus]
af_mode = semi-auto
zoom_level = 0
focus_level = 0
[storage]
mount_path = /userdata
free_size_del_min = 500; MB
free_size_del_max = 1000; MB
num_limit_enable = 1; limit by file num
[storage.0]
enable = 0
folder_name = video0
file_format = mp4 ; flv,ts
file_duration = 60
video_quota = 30
file_max_num = 300
[storage.1]
enable = 0
folder_name = video1
file_format = mp4 ; flv,ts
file_duration = 60
video_quota = 30
file_max_num = 300
[storage.2]
enable = 0
folder_name = video2
file_format = mp4 ; flv,ts
file_duration = 60
video_quota = 30
file_max_num = 300
[system.device_info]
deivce_name = RK IP Camera
telecontrol_id = 88
model = RK-003
serial_number = RK-003-A
firmware_version = V0.2.6 build 202108
encoder_version = V1.0 build 202108
web_version = V2.12.2 build 202108
plugin_version = V1.0.0.0
channels_number = 1
hard_disks_number = 1
alarm_inputs_number = 0
alarm_outputs_number = 0
firmware_version_info = CP-3-B
manufacturer = Rockchip
hardware_id = c3d9b8674f4b94f6
user_num = 1
[capability.video]
0 = {"disabled":[{"name":"sStreamType","options":{"subStream":{"sSmart":"close"},"thirdStream":{"sSmart":"close"}},"type":"disabled/limit"},{"name":"sRCMode","options":{"CBR":{"sRCQuality":null}},"type":"disabled"},{"name":"sOutputDataType","options":{"H.265":{"sH264Profile":null}},"type":"disabled"},{"name":"unspport","options":{"iStreamSmooth":null,"sVideoType":null},"type":"disabled"}],"dynamic":{"sSmart":{"open":{"iMinRate":{"dynamicRange":{"max":"iMaxRate","maxRate":1,"min":"iMaxRate","minRate":0.125},"type":"dynamicRange"}}},"sStreamType":{"mainStream":{"iMaxRate":{"options":[256,512,1024,2048,3072,4096,6144],"type":"options"},"sResolution":{"options":["2880*1616","1920*1080","1280*720","960*540","640*360","320*240"],"type":"options"}},"subStream":{"iMaxRate"
1 = :{"options":[128,256,512],"type":"options"},"sResolution":{"options":["704*576","640*480","352*288","320*240"],"type":"options"}},"thirdStream":{"iMaxRate":{"options":[256,512],"type":"options"},"sResolution":{"options":["416*416"],"type":"options"}}}},"layout":{"encoder":["sStreamType","sVideoType","sResolution","sRCMode","sRCQuality","sFrameRate","sOutputDataType","sSmart","sH264Profile","sGOPMode","iMaxRate","iGOP","iStreamSmooth"]},"static":{"iGOP":{"range":{"max":400,"min":1},"type":"range"},"iStreamSmooth":{"range":{"max":100,"min":1,"step":1},"type":"range"},"sFrameRate":{"dynamicRange":{"max":"sFrameRateIn","maxRate":1},"options":["1/2","1","2","4","6","8","10","12","14","16","18","20","25","30"],"type":"options/dynamicRange"},"sH264Profile":{"options":["high","main","baseline"],"type":"options"},"sOutputDataType":{"options"
2 = :["H.264","H.265"],"type":"options"},"sRCMode":{"options":["CBR","VBR"],"type":"options"},"sRCQuality":{"options":["lowest","lower","low","medium","high","higher","highest"],"type":"options"},"sGOPMode":{"options":["normalP","smartP"],"type":"options"},"sSmart":{"options":["open","close"],"type":"options"},"sStreamType":{"options":["mainStream","subStream","thirdStream"],"type":"options"},"sVideoType":{"options":["videoStream","compositeStream"],"type":"options"}}}
[capability.image_adjustment]
0 = {"layout":{"image_adjustment":["iBrightness","iContrast","iSaturation","iSharpness","iHue"]},"static":{"iBrightness":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iContrast":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iHue":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iSaturation":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iSharpness":{"range":{"max":100,"min":0,"step":1},"type":"range"}}}
[capability.image_blc]
0 = {"disabled":[{"name":"sHLC","options":{"open":{"sBLCRegion":null}},"type":"disabled"},{"name":"sBLCRegion","options":{"open":{"iDarkBoostLevel":null,"iHLCLevel":null,"sHLC":null}},"type":"disabled"}],"dynamic":{"sBLCRegion":{"open":{"iBLCStrength":{"range":{"max":100,"min":0,"step":1},"type":"range"}}},"sHDR":{"HDR2":{"iHDRLevel":{"options":[1,2,3,4],"type":"options"}},"close":{"sBLCRegion":{"options":["close","open"],"type":"options"},"sHLC":{"options"
1 = :["close","open"],"type":"options"}}},"sHLC":{"open":{"iDarkBoostLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iHLCLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}}},"sWDR":{"open":{"iWDRLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}}}},"layout":{"image_blc":["sHDR","iHDRLevel","sBLCRegion","iBLCStrength","sHLC","iHLCLevel"]},"static":{"sHDR":{"options":["close","HDR2"],"type":"options"}}}
[capability.image_enhancement]
0 = {"dynamic":{"sDehaze":{"open":{"iDehazeLevel":{"range":{"max":10,"min":0,"step":1},"type":"range"}}},"sDistortionCorrection":{"FEC":{"iFecLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}},"LDCH":{"iLdchLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}}},"sNoiseReduceMode":{"2dnr":{"iSpatialDenoiseLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}},"3dnr":{"iTemporalDenoiseLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}},"mixnr":{"iSpatialDenoiseLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iTemporalDenoiseLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}}}},"layout"
1 = :{"image_enhancement":["sNoiseReduceMode","iSpatialDenoiseLevel","iTemporalDenoiseLevel","sDehaze","iDehazeLevel","sGrayScaleMode","sDistortionCorrection","iLdchLevel","iFecLevel"]},"static":{"sDIS":{"options":["open","close"],"type":"options"},"sDehaze":{"options":["open","close","auto"],"type":"options"},"sDistortionCorrection":{"options":["LDCH","close"],"type":"options"},"sFEC":{"options":["open","close"],"type":"options"},"sGrayScaleMode":{"options":["[0-255]","[16-235]"],"type":"options"},"sNoiseReduceMode":{"options":["close","2dnr","3dnr","mixnr"],"type":"options"}}}
[capability.image_exposure]
0 = {"dynamic":{"sExposureMode":{"auto":{"iAutoIrisLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}},"manual":{"sExposureTime":{"options":["1","1/3","1/6","1/12","1/25","1/50","1/100","1/150","1/200","1/250","1/500","1/750","1/1000","1/2000","1/4000","1/10000","1/100000"],"type":"options"},"sGainMode":{"options":["auto","manual"],"type":"options"}}},"sGainMode":{"manual":{"iExposureGain":{"range":{"max":100,"min":1,"step":1},"type":"range"}}}},"layout":{"image_exposure":["sExposureMode","sExposureTime","sGainMode","iExposureGain","iFPS"]},"static":{"sExposureMode":{"options":["auto","manual"],"type":"options"},"iFPS":{"range":{"max":30,"min":0,"step":1},"type":"range"}}}
[capability.image_night_to_day]
0 = {"disabled":[{"name":"sNightToDay","options":{"day":{"iLightBrightness":null,"sFillLightMode":null},"night":{"iDarkBoostLevel":null,"iHDRLevel":null,"iHLCLevel":null,"sHDR":null,"sHLC":"close"}},"type":"disabled"}],"dynamic":{"sNightToDay":{"auto":{"iNightToDayFilterLevel":{"options":[0,1,2,3,4,5,6,7],"type":"options"},"iNightToDayFilterTime":{"range":{"max":10,"min":3,"step":1},"type":"range"}},"schedule":{"sDawnTime":{"input":"time","type":"input"},"sDuskTime":{"input":"time","type":"input"}}},"sOverexposeSuppress":{"open"
1 = :{"sOverexposeSuppressType":{"options":["auto","manual"],"type":"options"}}},"sOverexposeSuppressType":{"manual":{"iDistanceLevel":{"range":{"max":100,"min":0,"step":1},"type":"range"}}}},"layout":{"image_night_to_day":["sNightToDay","iNightToDayFilterLevel","iNightToDayFilterTime","sDawnTime","sDuskTime","sFillLightMode","iLightBrightness"]},"static":{"iLightBrightness":{"range":{"max":100,"min":0,"step":10},"type":"range"},"sNightToDay":{"options":["day","night"],"type":"options"},"sFillLightMode":{"type":"options","options":["IR"]}}}
[capability.image_video_adjustment]
0 = {"layout":{"image_video_adjustment":["sPowerLineFrequencyMode","sImageFlip","iImageRotation"]},"static":{"sImageFlip":{"options":["close","flip","mirror","centrosymmetric"],"type":"options"},"sPowerLineFrequencyMode":{"options":["PAL(50HZ)","NTSC(60HZ)"],"type":"options"},"sSceneMode":{"options":["indoor","outdoor"],"type":"options"},"iImageRotation":{"options":[0,90,180,270],"type":"options"}}}
[capability.image_white_blance]
0 = {"dynamic":{"sWhiteBlanceStyle":{"manualWhiteBalance":{"iWhiteBalanceBlue":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iWhiteBalanceGreen":{"range":{"max":100,"min":0,"step":1},"type":"range"},"iWhiteBalanceRed":{"range":{"max":100,"min":0,"step":1},"type":"range"}}}},"layout":{"image_white_blance":["sWhiteBlanceStyle","iWhiteBalanceRed","iWhiteBalanceGreen","iWhiteBalanceBlue"]},"static":{"sWhiteBlanceStyle":{"options":["manualWhiteBalance","autoWhiteBalance","lockingWhiteBalance","fluorescentLamp","incandescent","warmLight","naturalLight"],"type":"options"}}}
[user.0]
user_name = admin
password = YWRtaW4=
user_level = 1 ; administrator=0 operator=1 user=2
[osd.common]
enable_osd = 1
is_presistent_text = 1
attribute = transparent/not-flashing
font_size = 32
font_color_mode = customize
font_color = fff799
alignment = customize
boundary = 0
font_path = /oem/usr/share/simsun_en.ttf
normalized_screen_width = 704
normalized_screen_height = 480
[osd.0]
type = channelName
enabled = 0
position_x = 1104
position_y = 640
display_text = Camera 01
[osd.1]
type = dateTime
enabled = 1
position_x = 16
position_y = 16
date_style = CHR-YYYY-MM-DD
time_style = 24hour
display_week_enabled = 0
[osd.2]
type = character
enabled = 0
position_x = 0
position_y = 0
display_text = null
[osd.3]
type = character
enabled = 0
position_x = 0
position_y = 0
display_text = null
[osd.4]
type = privacyMask
enabled = 0
position_x = 0
position_y = 0
width = 0
height = 0
[osd.5]
type = privacyMask
enabled = 0
position_x = 0
position_y = 0
width = 0
height = 0
[osd.6]
type = image
enabled = 0
position_x = 16
position_y = 640
image_path = /userdata/image.bmp
[event.regional_invasion]
enabled = 1
position_x = 0
position_y = 0
width = 700
height = 560
proportion = 1
sensitivity_level = 90
time_threshold = 1
rockiva_model_type = small ;big medium small
[roi.0]
stream_type = mainStream
id = 1
enabled = 0
name = test
position_x = 0
position_y = 0
width = 0
height = 0
quality_level = 3
[roi.1]
stream_type = mainStream
id = 2
enabled = 0
name = test
position_x = 0
position_y = 0
width = 0
height = 0
quality_level = 3
[roi.2]
stream_type = subStream
id = 1
enabled = 0
name = test
position_x = 0
position_y = 0
width = 0
height = 0
quality_level = 3
[roi.3]
stream_type = subStream
id = 2
enabled = 0
name = test
position_x = 0
position_y = 0
width = 0
height = 0
quality_level = 3
[roi.4]
stream_type = thirdStream
id = 1
enabled = 0
name = test
position_x = 0
position_y = 0
width = 0
height = 0
quality_level = 3
[roi.5]
stream_type = thirdStream
id = 2
enabled = 0
name = test
position_x = 0
position_y = 0
width = 0
height = 0
quality_level = 3
[region_clip.1]
enabled = 0
position_x = 0
position_y = 0
width = 640
height = 480
[network.ntp]
enable = 1
refresh_time_s = 60
ntp_server = 119.28.183.184

2
project/app/uvc_app_tiny/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
out/
build/

View File

@@ -0,0 +1,102 @@
ifeq ($(APP_PARAM), )
APP_PARAM:=../Makefile.param
include $(APP_PARAM)
endif
export LC_ALL=C
SHELL:=/bin/bash
CURRENT_DIR := $(shell pwd)
PKG_NAME := uvc_app
PKG_BIN ?= out
PKG_BUILD ?= build
# debug: build cmake with more message
# PKG_CONF_OPTS += -DCMAKE_VERBOSE_MAKEFILE=ON
#
RK_UVC_APP_CONFIG :=
ifeq ($(RK_ENABLE_FASTBOOT),y)
PKG_CONF_OPTS += -DRK_ENABLE_FASTBOOT=ON
RK_APP_OPTS += -DRK_ENABLE_FASTBOOT
endif
ifeq ($(RK_APP_CHIP), rv1106)
ifneq (, $(filter UVC_TINY, $(RK_APP_TYPE)))
RK_UVC_APP_CONFIG := -DCOMPILE_FOR_MPI=ON
else
$(info ### disable make uvc demo)
endif
else
$(info ### unknow RK_APP_CHIP)
endif
RK_APP_CFLAGS = -I $(RK_APP_MEDIA_INCLUDE_PATH) \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/libdrm \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/uAPI \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/uAPI2 \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/algos \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/common \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/xcore \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/iq_parser \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/rkaiq/iq_parser_v2 \
-I $(RK_APP_MEDIA_INCLUDE_PATH)/easymedia
RK_APP_LDFLAGS = -L $(RK_APP_MEDIA_LIBS_PATH)
RK_APP_OPTS += -Wl,-rpath-link,$(RK_APP_MEDIA_LIBS_PATH):$(RK_APP_PATH_LIB_INCLUDE)/root/usr/lib
PKG_CONF_OPTS += -DCMAKE_C_FLAGS="$(RK_APP_CFLAGS) $(RK_APP_LDFLAGS) $(RK_APP_OPTS)" \
-DCMAKE_CXX_FLAGS="$(RK_APP_CFLAGS) $(RK_APP_LDFLAGS) $(RK_APP_OPTS)"
PKG_CONF_OPTS += -DUVC_APP_CROSS_COMPILE="$(RK_APP_CROSS)"
# define project/cfg/BoardConfig*.mk
ifneq ($(RK_UVC_APP_CONFIG),)
PKG_TARGET := uvc_app-build
$(info ** $(PKG_NAME) build $(RK_APP_TYPE) **)
endif
ifeq ($(PKG_BIN),)
$(error ### $(CURRENT_DIR): PKG_BIN is NULL, Please Check !!!)
endif
all: $(PKG_TARGET)
@echo "build $(PKG_NAME) done"
uvc_app-build:
@echo "RK_APP_CHIP is $(RK_APP_CHIP)"
@echo "RK_APP_TYPE is $(RK_APP_TYPE)"
rm -rf $(PKG_BIN) $(PKG_BUILD); \
mkdir -p $(PKG_BIN);
mkdir -p $(PKG_BUILD);
pushd $(PKG_BUILD)/; \
rm -rf CMakeCache.txt; \
cmake $(CURRENT_DIR)/$(PKG_NAME)/ \
-DCMAKE_C_COMPILER=$(RK_APP_CROSS)-gcc \
-DCMAKE_CXX_COMPILER=$(RK_APP_CROSS)-g++ \
-DCMAKE_INSTALL_PREFIX="$(CURRENT_DIR)/$(PKG_BIN)" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_COLOR_MAKEFILE=OFF \
-DCMAKE_SYSTEM_NAME=Linux \
$(RK_UVC_APP_CONFIG) \
$(PKG_CONF_OPTS) ;\
make -j$(RK_APP_JOBS) || exit -1; \
make install; \
popd;
$(call MAROC_COPY_PKG_TO_APP_OUTPUT, $(RK_APP_OUTPUT), $(PKG_BIN))
clean:
@rm -rf $(PKG_BIN) $(PKG_BUILD)
distclean: clean
info:
ifneq ($(RK_UVC_APP_CONFIG),)
@echo -e "$(C_YELLOW)-------------------------------------------------------------------------$(C_NORMAL)"
@echo -e "RK_APP_TYPE=$(RK_APP_TYPE)"
@echo -e "option support as follow:"
@echo -e " UVC"
@echo -e "$(C_YELLOW)-------------------------------------------------------------------------$(C_NORMAL)"
endif

View File

@@ -0,0 +1,81 @@
[video.source]
enable_aiq = 1
enable_vo = 0
enable_npu = 0
enable_uac = 0
enable_2uvc = 0
[isp.0.adjustment]
contrast = 50
brightness = 50
saturation = 50
sharpness = 50
fps = 30
hue = 50
[isp.0.exposure]
iris_type = auto
exposure_mode = auto
gain_mode = auto
auto_iris_level = 5
auto_exposure_enabled = 1
audo_gain_enabled = 1
exposure_time = 1/6
exposure_gain = 1
[isp.0.night_to_day]
night_to_day = day
night_to_day_filter_level = 5
night_to_day_filter_time = 5
dawn_time = 07:00:00
dusk_time = 18:00:00
ircut_filter_action = day
over_exposure_suppress = open
over_exposure_suppress_type = auto
fill_light_mode = IR
brightness_adjustment_mode = auto
light_brightness = 1
distance_level = 1
[isp.0.blc]
blc_region = close
blc_strength = 1
wdr = close
wdr_level = 0
hdr = close
hdr_level = 1
hlc = close
hlc_level = 0
dark_boost_level = 0
position_x = 0
position_y = 0
blc_region_width = 120
blc_region_high = 92
[isp.0.white_blance]
white_blance_style = autoWhiteBalance
white_blance_ct = 5000
[isp.0.enhancement]
noise_reduce_mode = close
denoise_level = 50
spatial_denoise_level = 50
temporal_denoise_level = 50
dehaze = close
dehaze_level = 0
dis = close
gray_scale_mode = [0-255]
image_rotation = 0
distortion_correction = close
ldch_level = 0
[isp.0.video_adjustment]
image_flip = close
scene_mode = indoor
power_line_frequency_mode = PAL(50HZ)
[isp.0.auto_focus]
af_mode = semi-auto
zoom_level = 0
focus_level = 0

View File

@@ -0,0 +1,728 @@
{
"index_0": {
"version" : 1,
"common_cfg": {
"version" : 1,
"property" : {
"param_init": {
"check_param_change_thread": "off",
"uvc_debug": "off",
"yuyv_debug": "off",
"nn_enable": "off",
"uvc_debug_file_name": "/data/uvc.bin",
"uvc_debug_file_cnt": 0,
"nn_debug_file_name": "/data/nn.bin",
"nn_debug_file_cnt": 0,
"uvc_enable_vpss": "off",
"geometric_output": "16:9"
},
"param_change": {
}
}
},
"eptz_cfg": {
"version" : 2,
"param_init": {
"enable": "on",
"enable_boot": "off",
"debug": "off",
"align": 2,
"zoom_speed": 3,
"fast_move_frame_judge": 40,
"zoom_frame_judge": 40,
"iterate_x": 10,
"iterate_y": 5,
"ratio": 0.4
},
"param_change": {
}
},
"vi_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"dev_id": 0,
"channel_id": 0,
"buf_cnt": 1,
"assign_width": 0,
"assign_height": 0,
"min_width": 1920,
"min_height": 1080,
"max_width": 2880,
"max_height": 1616,
"format": "nv12",
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"dev_id": 0,
"channel_id": 1,
"assign_width": 512,
"assign_height": 288,
"format": "nv12",
"buf_cnt": 1,
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"vpss_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"group_id": 0,
"channel_id": 0,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"group_id": 1,
"channel_id": 0,
"format": "bgr888",
"assign_width": 512,
"assign_height": 288,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"venc_cfg": {
"version" : 1,
"common" : {
"param_init": {
"channel_id": 0,
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"mjpeg": {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"rc_mode": "fixqp",
"fps": "0:0",
"range": "full",
"sei": "off",
"qfactor": 85,
"qfactor_min": 30,
"qfactor_max": 99,
"bps": 60000
},
"1280*720p30": {
"qfactor": 80,
"qfactor_min": 60,
"qfactor_max": 90,
"bps": 70000
},
"1920*1080p30": {
"qfactor": 75,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 80000
},
"2560*1440p30": {
"qfactor": 70,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 90000
},
"2880*1616@30": {
"qfactor": 70,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 90000
}
},
"param_change": {
}
},
"h264" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"profile": 100,
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2880*1616p30": {
"bps": 15000,
"force_idr": "5:5:40000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
},
"h265" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
},
"2880*1616p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
}
},
"osd_cfg": {
"version" : 1,
"param_init": {
"enable": "off",
"force_use_vpss": "off"
},
"param_change": {
}
}
},
"index_1": {
"version" : 1,
"common_cfg": {
"version" : 1,
"property" : {
"param_init": {
"check_param_change_thread": "off",
"uvc_debug": "off",
"yuyv_debug": "off",
"nn_enable": "off",
"uvc_debug_file_name": "/data/uvc1.bin",
"uvc_debug_file_cnt": 0,
"nn_debug_file_name": "/data/nn1.bin",
"nn_debug_file_cnt": 0,
"uvc_enable_vpss": "off",
"geometric_output": "16:9"
},
"param_change": {
}
}
},
"eptz_cfg": {
"version" : 2,
"param_init": {
"enable": "on",
"enable_boot": "off",
"debug": "off",
"align": 2,
"zoom_speed": 3,
"fast_move_frame_judge": 40,
"zoom_frame_judge": 40,
"iterate_x": 10,
"iterate_y": 5,
"ratio": 0.4
},
"param_change": {
}
},
"vi_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"dev_id": 1,
"channel_id": 0,
"buf_cnt": 1,
"assign_width": 0,
"assign_height": 0,
"min_width": 1280,
"min_height": 720,
"max_width": 2880,
"max_height": 1616,
"format": "nv12",
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"dev_id": 1,
"channel_id": 1,
"assign_width": 512,
"assign_height": 288,
"format": "nv12",
"buf_cnt": 1,
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"vpss_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"group_id": 1,
"channel_id": 0,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"group_id": 1,
"channel_id": 0,
"format": "bgr888",
"assign_width": 512,
"assign_height": 288,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"venc_cfg": {
"version" : 1,
"common" : {
"param_init": {
"channel_id": 1,
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"mjpeg": {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"rc_mode": "fixqp",
"fps": "0:0",
"range": "full",
"sei": "off",
"qfactor": 85,
"qfactor_min": 30,
"qfactor_max": 99,
"bps": 60000
},
"1280*720p30": {
"qfactor": 80,
"qfactor_min": 60,
"qfactor_max": 90,
"bps": 70000
},
"1920*1080p30": {
"qfactor": 75,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 80000
},
"2560*1440p30": {
"qfactor": 70,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 90000
},
"2880*1616@30": {
"qfactor": 70,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 90000
}
},
"param_change": {
}
},
"h264" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"profile": 100,
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
},
"2880*1616p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
},
"h265" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
},
"2880*1616p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
}
},
"osd_cfg": {
"version" : 1,
"param_init": {
"enable": "off",
"force_use_vpss": "off"
},
"param_change": {
}
}
},
"index_2": {
"version" : 1,
"common_cfg": {
"version" : 1,
"property" : {
"param_init": {
"check_param_change_thread": "off",
"uvc_debug": "off",
"yuyv_debug": "off",
"nn_enable": "off",
"uvc_debug_file_name": "/data/uvc2.bin",
"uvc_debug_file_cnt": 0,
"nn_debug_file_name": "/data/nn2.bin",
"nn_debug_file_cnt": 0,
"uvc_enable_vpss": "off",
"geometric_output": "16:9"
},
"param_change": {
}
}
},
"eptz_cfg": {
"version" : 2,
"param_init": {
"enable": "on",
"enable_boot": "off",
"debug": "off",
"align": 2,
"zoom_speed": 3,
"fast_move_frame_judge": 40,
"zoom_frame_judge": 40,
"iterate_x": 10,
"iterate_y": 5,
"ratio": 0.4
},
"param_change": {
}
},
"vi_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"dev_id": 2,
"channel_id": 0,
"buf_cnt": 1,
"assign_width": 0,
"assign_height": 0,
"min_width": 640,
"min_height": 480,
"max_width": 2880,
"max_height": 1616,
"format": "nv12",
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"dev_id": 2,
"channel_id": 1,
"assign_width": 512,
"assign_height": 288,
"format": "nv12",
"buf_cnt": 1,
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"vpss_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"group_id": 2,
"channel_id": 0,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"group_id": 1,
"channel_id": 0,
"format": "bgr888",
"assign_width": 512,
"assign_height": 288,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"venc_cfg": {
"version" : 1,
"common" : {
"param_init": {
"channel_id": 2,
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"mjpeg": {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"rc_mode": "fixqp",
"fps": "0:0",
"range": "full",
"sei": "off",
"qfactor": 85,
"qfactor_min": 30,
"qfactor_max": 99,
"bps": 60000
},
"1280*720p30": {
"qfactor": 80,
"qfactor_min": 60,
"qfactor_max": 90,
"bps": 70000
},
"1920*1080p30": {
"qfactor": 75,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 80000
},
"2560*1440p30": {
"qfactor": 70,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 90000
},
"2880*1616@30": {
"qfactor": 70,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 90000
}
},
"param_change": {
}
},
"h264" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"profile": 100,
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
},
"2880*1616p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
},
"h265" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
},
"2880*1616p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
}
},
"osd_cfg": {
"version" : 1,
"param_init": {
"enable": "off",
"force_use_vpss": "off"
},
"param_change": {
}
}
}
}

View File

@@ -0,0 +1,116 @@
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 11)
add_definitions(-DDBUG)
add_definitions(-g)
PROJECT(rk_mpi_uvc)
include(FindPkgConfig)
include_directories(uvc)
include_directories(uvc/cJSON)
include_directories(isp)
include_directories(param)
include_directories(${PROJECT_SOURCE_DIR}/include
${CMAKE_SYSROOT}/usr/include/rkaiq/
${CMAKE_SYSROOT}/usr/include/rkaiq/uAPI
${CMAKE_SYSROOT}/usr/include/rkaiq/uAPI2
${CMAKE_SYSROOT}/usr/include/rkaiq/algos
${CMAKE_SYSROOT}/usr/include/rkaiq/common
${CMAKE_SYSROOT}/usr/include/rkaiq/xcore
${CMAKE_SYSROOT}/usr/include/rkaiq/iq_parser
${CMAKE_SYSROOT}/usr/include/rkaiq/iq_parser_v2
${CMAKE_SYSROOT}/usr/include/libdrm
)
option(COMPILE_FOR_UVC_UAC "compile for uac" OFF)
if(COMPILE_FOR_UVC_UAC)
include(uac/uac.cmake)
endif()
set(LIB_SOURCE
uvc/uvc-gadget.c
uvc/uvc_video.cpp
uvc/uvc_control.cpp
uvc/uvc_process.cpp
uvc/uvc_mpi_config.c
uvc/uvc_mpi_venc.cpp
uvc/uvc_mpi_vi.cpp
uvc/uvc_mpi_vpss.cpp
uvc/uevent.c
uvc/uvc_configfs.c
uvc/camera_control.c
uvc/camera_pu_control.c
uvc/cJSON/cJSON.c
uvc/osd.c
isp/isp.c
param/dictionary.c
param/iniparser.c
param/param.c
)
if(COMPILE_FOR_UVC_UAC)
add_definitions(-DCOMPILE_FOR_UVC_UAC)
set(SOURCE
main.c
${LIB_SOURCE}
${UAC_SOURCE}
)
else()
set(SOURCE
main.c
${LIB_SOURCE}
)
endif()
if (RK_ENABLE_FASTBOOT)
set(RK_MPI_UVC_DEPENDENT_LIBS
pthread
rt
rkaiq
librockit.a
librockchip_mpp.a
librkaudio_detect.a
libaec_bf_process.a
librga.a
)
message(STATUS "RK_ENABLE_FASTBOOT is enabled.")
else()
set(RK_MPI_UVC_DEPENDENT_LIBS
pthread
rt
rkaiq
rockit
)
message(STATUS "RK_ENABLE_FASTBOOT is disabled.")
endif()
set(RK_MPI_UVC_INC
${CMAKE_CURRENT_SOURCE_DIR}/uvc/
)
add_definitions(-fno-rtti)
ADD_EXECUTABLE(rk_mpi_uvc ${SOURCE})
link_directories(${PROJECT_SOURCE_DIR}/lib/)
target_link_libraries(rk_mpi_uvc ${RK_MPI_UVC_DEPENDENT_LIBS})
install(DIRECTORY ./uvc DESTINATION include
FILES_MATCHING PATTERN "*.h")
install(TARGETS rk_mpi_uvc DESTINATION bin)
install(FILES uvc_mpi_cfg.conf DESTINATION share)
install(FILES rkuvc.ini DESTINATION share)
install(FILES usb_config.sh DESTINATION bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_WRITE GROUP_EXECUTE
WORLD_READ WORLD_WRITE WORLD_EXECUTE)
#install(FILES RkLunch.sh DESTINATION bin
# PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
# GROUP_READ GROUP_WRITE GROUP_EXECUTE
# WORLD_READ WORLD_WRITE WORLD_EXECUTE)
#install(FILES RkLunch-stop.sh DESTINATION bin
# PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
# GROUP_READ GROUP_WRITE GROUP_EXECUTE
# WORLD_READ WORLD_WRITE WORLD_EXECUTE)

View File

@@ -0,0 +1,28 @@
// Copyright 2021 Rockchip Electronics Co.,Ltd.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,30 @@
#!/bin/sh
program_kill()
{
P_PID=`ps | grep $1 | grep -v grep | awk '{print $1}'`
test -z ${P_PID} || kill -9 ${P_PID}
}
echo "Stop Application ..."
program_kill RkLunch.sh
killall rk_mpi_uvc &
cnt=0
while [ 1 ];
do
sleep 1
cnt=$(( cnt + 1 ))
if [ $cnt -eq 8 ]; then
echo "killall -9 rk_mpi_uvc"
killall -9 rk_mpi_uvc
sleep 0.1
break
fi
ps|grep rk_mpi_uvc|grep -v grep
if [ $? -ne 0 ]; then
echo "rk_mpi_uvc exit"
break
else
echo "rk_mpi_uvc active"
fi
done

View File

@@ -0,0 +1,105 @@
#!/bin/sh
check_usb_state()
{
if [[ ! -f "/oem/usr/bin/rk_mpi_uvc" && ! -f "/usr/bin/rk_mpi_uvc" ]]; then
return 1
fi
PID=`ps |grep rk_mpi_uvc |grep -v grep | wc -l`
if [ $PID -le 0 ];then
echo " exit rk_mpi_uvc ,restart it for uvc recovery..."
killall adbd
sleep 1
killall -9 adbd
rm -rf /sys/kernel/config/usb_gadget/rockchip/configs/b.1/f*
echo none > /sys/kernel/config/usb_gadget/rockchip/UDC
rmdir /sys/kernel/config/usb_gadget/rockchip/functions/ffs.adb
rmdir /sys/kernel/config/usb_gadget/rockchip/functions/uac*
UDC=`ls /sys/class/udc/| awk '{print $1}'`
echo $UDC > /sys/bus/platform/drivers/dwc3/unbind
echo $UDC > /sys/bus/platform/drivers/dwc3/bind
/oem/usr/bin/usb_config.sh uac1 #off #disable adb
if [ -d "/oem/usr/share/iqfiles" ];then
rk_mpi_uvc -c /tmp/rkuvc.ini -a /oem/usr/share/iqfiles &
else
rk_mpi_uvc &
fi
fi
}
post_chk()
{
#TODO: ensure /userdata mount done
cnt=0
while [ $cnt -lt 30 ];
do
cnt=$(( cnt + 1 ))
if mount | grep -w userdata; then
break
fi
sleep .1
done
# if ko exist, install ko first
default_ko_dir=/ko
if [ -f "/oem/usr/ko/insmod_ko.sh" ];then
default_ko_dir=/oem/usr/ko
fi
if [ -f "$default_ko_dir/insmod_ko.sh" ];then
cd $default_ko_dir && sh insmod_ko.sh && cd -
fi
# if /data/rkuvc not exist, cp /usr/share
rkuvc_ini=/tmp/rkuvc.ini
default_rkuvc_ini=/usr/share/rkuvc.ini
if [ ! -f "$default_rkuvc_ini" ];then
default_rkuvc_ini=/oem/usr/share/rkuvc.ini
fi
if [ ! -f "$default_rkuvc_ini" ];then
echo "Error: not found rkuvc.ini !!!"
exit -1
fi
if [ ! -f "$rkuvc_ini" ]; then
cp $default_rkuvc_ini $rkuvc_ini -f
fi
export rt_log_level=3
export rk_mpi_uvc_log_level=2
export uac_app_log_level=2
touch /tmp/uvc_no_timeout
/oem/usr/bin/usb_config.sh uac1
ifconfig lo 127.0.0.1
if [ -d "/oem/usr/share/iqfiles" ];then
rk_mpi_uvc -c /tmp/rkuvc.ini -a /oem/usr/share/iqfiles &
else
rk_mpi_uvc &
fi
while true
do
sleep 2
if [ -f "/tmp/uvc_stop_check" ]; then
echo " stop check usb state sh " && break
else
check_usb_state
fi
if [ -f "/tmp/reboot_loader" ]; then
echo "exec reboot loader cmd..."
reboot loader &
fi
done
}
start_app()
{
if [ -f "/etc/init.d/S50usbdevice" ];then
mv /etc/init.d/S50usbdevice /etc/S50usbdevice -f
fi
echo "##### start uvc app ..."
post_chk &
}
ulimit -c unlimited
echo "/data/core-%p-%e" > /proc/sys/kernel/core_pattern
start_app

View File

@@ -0,0 +1,9 @@
#!/bin/bash
##
## Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
## Use of this source code is governed by a BSD-style license that can be
## found in the LICENSE file.
##
find . -name "*.c" -o -name "*.h" | xargs clang-format -style=file -i
find . -name "*.cpp" -o -name "*.h" | xargs clang-format -style=file -i

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
int rk_isp_init(int cam_id, char *iqfile_path);
int rk_isp_deinit(int cam_id);
int rk_isp_group_init(int cam_group_id, char *iqfile_path);
int rk_isp_group_deinit(int cam_group_id);
int rk_isp_set_frame_rate(int cam_id, int value);
// image adjustment
int rk_isp_get_contrast(int cam_id, int *value);
int rk_isp_set_contrast(int cam_id, int value);
int rk_isp_get_brightness(int cam_id, int *value);
int rk_isp_set_brightness(int cam_id, int value);
int rk_isp_get_saturation(int cam_id, int *value);
int rk_isp_set_saturation(int cam_id, int value);
int rk_isp_get_sharpness(int cam_id, int *value);
int rk_isp_set_sharpness(int cam_id, int value);
int rk_isp_get_hue(int cam_id, int *value);
int rk_isp_set_hue(int cam_id, int value);
int rk_isp_get_hue_mode(int cam_id, int *value);
int rk_isp_set_hue_mode(int cam_id, int value);
// exposure
int rk_isp_get_exposure_mode(int cam_id, const char **value);
int rk_isp_set_exposure_mode(int cam_id, const char *value);
int rk_isp_get_gain_mode(int cam_id, const char **value);
int rk_isp_set_gain_mode(int cam_id, const char *value);
int rk_isp_get_exposure_time(int cam_id, const char **value);
int rk_isp_set_exposure_time(int cam_id, const char *value);
int rk_isp_get_exposure_gain(int cam_id, int *value);
int rk_isp_set_exposure_gain(int cam_id, int value);
// blc
int rk_isp_get_hdr(int cam_id, const char **value);
int rk_isp_set_hdr(int cam_id, const char *value);
int rk_isp_get_blc_region(int cam_id, const char **value);
int rk_isp_set_blc_region(int cam_id, const char *value);
int rk_isp_get_hlc(int cam_id, const char **value);
int rk_isp_set_hlc(int cam_id, const char *value);
int rk_isp_get_hdr_level(int cam_id, int *value);
int rk_isp_set_hdr_level(int cam_id, int value);
int rk_isp_get_blc_strength(int cam_id, int *value);
int rk_isp_set_blc_strength(int cam_id, int value);
int rk_isp_get_hlc_level(int cam_id, int *value);
int rk_isp_set_hlc_level(int cam_id, int value);
int rk_isp_get_dark_boost_level(int cam_id, int *value);
int rk_isp_set_dark_boost_level(int cam_id, int value);
// white_blance
int rk_isp_get_white_blance_style(int cam_id, const char **value);
int rk_isp_set_white_blance_style(int cam_id, const char *value);
int rk_isp_get_white_blance_ct(int cam_id, int *value);
int rk_isp_set_white_blance_ct(int cam_id, int value);
// enhancement
int rk_isp_get_noise_reduce_mode(int cam_id, const char **value);
int rk_isp_set_noise_reduce_mode(int cam_id, const char *value);
int rk_isp_get_dehaze(int cam_id, const char **value);
int rk_isp_set_dehaze(int cam_id, const char *value);
int rk_isp_get_gray_scale_mode(int cam_id, const char **value);
// int rk_isp_set_gray_scale_mode(int cam_id, const char *value);
int rk_isp_get_distortion_correction(int cam_id, const char **value);
int rk_isp_set_distortion_correction(int cam_id, const char *value);
int rk_isp_get_spatial_denoise_level(int cam_id, int *value);
int rk_isp_set_spatial_denoise_level(int cam_id, int value);
int rk_isp_get_temporal_denoise_level(int cam_id, int *value);
int rk_isp_set_temporal_denoise_level(int cam_id, int value);
int rk_isp_get_dehaze_level(int cam_id, int *value);
int rk_isp_set_dehaze_level(int cam_id, int value);
int rk_isp_get_ldch_level(int cam_id, int *value);
int rk_isp_set_ldch_level(int cam_id, int value);
// video_adjustment
int rk_isp_get_power_line_frequency_mode(int cam_id, const char **value);
int rk_isp_set_power_line_frequency_mode(int cam_id, const char *value);
int rk_isp_get_image_flip(int cam_id, const char **value);
int rk_isp_set_image_flip(int cam_id, const char *value);
// auto focus
int rk_isp_get_af_mode(int cam_id, const char **value);
int rk_isp_set_af_mode(int cam_id, const char *value);
int rk_isp_get_zoom_level(int cam_id, int *value);
int rk_isp_get_focus_level(int cam_id, int *value);
int rk_isp_af_zoom_in(int cam_id);
int rk_isp_af_zoom_out(int cam_id);
int rk_isp_af_focus_in(int cam_id);
int rk_isp_af_focus_out(int cam_id);
int rk_isp_af_focus_once(int cam_id);

View File

@@ -0,0 +1,189 @@
#include "camera_control.h"
#include "isp.h"
#include "param.h"
#include "rk_mpi_sys.h"
#include "uevent.h"
#include "uevent.h"
#include "uvc_control.h"
#include "uvc_log.h"
#include "uvc_video.h"
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#ifdef COMPILE_FOR_UVC_UAC
#include "uac_control.h"
#include "uac_log.h"
#include "uac_uevent.h"
#include <pthread.h>
#include <sys/prctl.h>
#endif
#define LOG_TAG "rk_mpi_uvc"
#define UVC_VERSION "SDK V2.01"
enum { LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG };
int rkuvc_log_level = LOG_DEBUG;
char *rkuvc_ini_path_ = NULL;
char *rkuvc_iq_file_path_ = NULL;
// int enable_minilog = 0;
// int rk_mpi_uvc_log_level = LOG_LEVEL_INFO;
// int app_quit;
static const char short_options[] = "c:a:l:";
static const struct option long_options[] = {
{"config", required_argument, NULL, 'c'},
{"aiq_file", no_argument, NULL, 'a'},
{"log_level", no_argument, NULL, 'l'},
{"help", no_argument, NULL, 'h'},
{0, 0, 0, 0}};
static void usage_tip(FILE *fp, int argc, char **argv) {
fprintf(fp, "Usage: %s [options]\n"
"Version %s\n"
"Options:\n"
"-c | --config rkuvc ini file, default is "
"/userdata/rkuvc.ini, need to be writable\n"
"-a | --aiq_file aiq file dir path, default is /etc/iqfiles\n"
"-l | --log_level log_level [0/1/2/3], default is 2\n"
"-h | --help for help \n\n"
"\n",
argv[0], "V1.0");
}
#ifdef COMPILE_FOR_UVC_UAC
void *uac_app_thread(void *arg) {
prctl(PR_SET_NAME, "uac_pthread", 0, 0, 0);
LOG_INFO("uac uevent version = 1.0\n");
// create uac control
char *ch;
int type = 0; // UAC_API_MPI;
// rkuac_get_opt(argc, argv);
int result = uac_control_create(type);
if (result < 0) {
LOG_ERROR("uac_control_create fail\n");
goto err_monitor;
}
// register uevent monitor
uac_uevent_monitor_run();
while (1) {
usleep(100000);
}
err_monitor:
pthread_detach(pthread_self());
pthread_exit(NULL);
}
int uac_app_run() {
pthread_t tid;
return pthread_create(&tid, NULL, uac_app_thread, NULL);
}
#endif
void rkuvc_get_opt(int argc, char *argv[]) {
for (;;) {
int idx;
int c;
c = getopt_long(argc, argv, short_options, long_options, &idx);
if (-1 == c)
break;
switch (c) {
case 0: /* getopt_long() flag */
break;
case 'c':
rkuvc_ini_path_ = optarg;
break;
case 'a':
rkuvc_iq_file_path_ = optarg;
break;
case 'l':
rkuvc_log_level = atoi(optarg);
break;
case 'h':
usage_tip(stdout, argc, argv);
exit(EXIT_SUCCESS);
default:
usage_tip(stderr, argc, argv);
exit(EXIT_FAILURE);
}
}
}
void sigterm_handler(int sig) {
LOG_INFO("signal %d\n", sig);
app_quit = sig;
}
int main(int argc, char *argv[]) {
int fd;
int ret;
unsigned int handle;
char *buffer;
int handle_fd;
size_t size;
int i = 0;
int width, height;
int y, uv;
int extra_cnt = 0;
uint32_t flags = 0;
int media_set = 0;
RK_S32 s32Ret = RK_FAILURE;
rk_mpi_uvc_log_level = LOG_LEVEL_INFO;
app_quit = 0;
signal(SIGQUIT, sigterm_handler);
signal(SIGTERM, sigterm_handler);
char *log_level = getenv("rk_mpi_uvc_log_level");
if (log_level) {
LOG_INFO("rk_mpi_uvc_log_level=%d", atoi(log_level));
rk_mpi_uvc_log_level = atoi(log_level);
}
LOG_INFO("VERSION:%s %s %s \n", UVC_VERSION, __DATE__, __TIME__);
rkuvc_get_opt(argc, argv);
LOG_INFO("rkuvc_ini_path_ is %s, rkuvc_iq_file_path_ is %s, rkuvc_log_level "
"is %d\n",
rkuvc_ini_path_, rkuvc_iq_file_path_, rkuvc_log_level);
rk_param_init(rkuvc_ini_path_);
camera_control_init();
s32Ret = RK_MPI_SYS_Init();
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_SYS_Init %x\n", s32Ret);
return -1;
}
uvc_control_start_setcallback(camera_control_start);
uvc_control_stop_setcallback(camera_control_stop);
uevent_monitor_run(UVC_CONTROL_CAMERA);
uvc_control_run(UVC_CONTROL_CAMERA);
#ifdef COMPILE_FOR_UVC_UAC
uac_app_log_level = LOG_DEBUG;
char *uac_log_level = getenv("uac_app_log_level");
if (uac_log_level) {
uac_app_log_level = atoi(uac_log_level);
}
if (rk_param_get_int("video.source:enable_uac", 0))
uac_app_run();
#endif
while (1) {
if (0 == uvc_control_loop())
break;
usleep(100000);
}
uvc_video_id_exit_all();
camera_control_deinit();
#ifdef COMPILE_FOR_UVC_UAC
if (rk_param_get_int("video.source:enable_uac", 0)) {
LOG_INFO("uac control destory...\n");
uac_control_destory();
}
#endif
RK_MPI_SYS_Exit();
rk_param_deinit();
LOG_INFO("uvc_app exit.\n");
return 0;
}

View File

@@ -0,0 +1,375 @@
/*-------------------------------------------------------------------------*/
/**
@file dictionary.c
@author N. Devillard
@brief Implements a dictionary for string variables.
This module implements a simple dictionary object, i.e. a list
of string/string associations. This object is useful to store e.g.
informations retrieved from a configuration file (ini files).
*/
/*--------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Includes
---------------------------------------------------------------------------*/
#include "dictionary.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/** Maximum value size for integers and doubles. */
#define MAXVALSZ 1024
/** Minimal allocated number of entries in a dictionary */
#define DICTMINSZ 128
/** Invalid key token */
#define DICT_INVALID_KEY ((char *)-1)
/*---------------------------------------------------------------------------
Private functions
---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
@brief Duplicate a string
@param s String to duplicate
@return Pointer to a newly allocated string, to be freed with free()
This is a replacement for strdup(). This implementation is provided
for systems that do not have it.
*/
/*--------------------------------------------------------------------------*/
static char *xstrdup(const char *s) {
char *t;
size_t len;
if (!s)
return NULL;
len = strlen(s) + 1;
t = (char *)malloc(len);
if (t) {
memcpy(t, s, len);
}
return t;
}
/*-------------------------------------------------------------------------*/
/**
@brief Double the size of the dictionary
@param d Dictionary to grow
@return This function returns non-zero in case of failure
*/
/*--------------------------------------------------------------------------*/
static int dictionary_grow(dictionary *d) {
char **new_val;
char **new_key;
unsigned *new_hash;
new_val = (char **)calloc(d->size * 2, sizeof *d->val);
new_key = (char **)calloc(d->size * 2, sizeof *d->key);
new_hash = (unsigned *)calloc(d->size * 2, sizeof *d->hash);
if (!new_val || !new_key || !new_hash) {
/* An allocation failed, leave the dictionary unchanged */
if (new_val)
free(new_val);
if (new_key)
free(new_key);
if (new_hash)
free(new_hash);
return -1;
}
/* Initialize the newly allocated space */
memcpy(new_val, d->val, d->size * sizeof(char *));
memcpy(new_key, d->key, d->size * sizeof(char *));
memcpy(new_hash, d->hash, d->size * sizeof(unsigned));
/* Delete previous data */
free(d->val);
free(d->key);
free(d->hash);
/* Actually update the dictionary */
d->size *= 2;
d->val = new_val;
d->key = new_key;
d->hash = new_hash;
return 0;
}
/*---------------------------------------------------------------------------
Function codes
---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
@brief Compute the hash key for a string.
@param key Character string to use for key.
@return 1 unsigned int on at least 32 bits.
This hash function has been taken from an Article in Dr Dobbs Journal.
This is normally a collision-free function, distributing keys evenly.
The key is stored anyway in the struct so that collision can be avoided
by comparing the key itself in last resort.
*/
/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char *key) {
size_t len;
unsigned hash;
size_t i;
if (!key)
return 0;
len = strlen(key);
for (hash = 0, i = 0; i < len; i++) {
hash += (unsigned)key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
/*-------------------------------------------------------------------------*/
/**
@brief Create a new dictionary object.
@param size Optional initial size of the dictionary.
@return 1 newly allocated dictionary object.
This function allocates a new dictionary object of given size and returns
it. If you do not know in advance (roughly) the number of entries in the
dictionary, give size=0.
*/
/*-------------------------------------------------------------------------*/
dictionary *dictionary_new(size_t size) {
dictionary *d;
/* If no size was specified, allocate space for DICTMINSZ */
if (size < DICTMINSZ)
size = DICTMINSZ;
d = (dictionary *)calloc(1, sizeof *d);
if (d) {
d->size = size;
d->val = (char **)calloc(size, sizeof *d->val);
d->key = (char **)calloc(size, sizeof *d->key);
d->hash = (unsigned *)calloc(size, sizeof *d->hash);
}
return d;
}
/*-------------------------------------------------------------------------*/
/**
@brief Delete a dictionary object
@param d dictionary object to deallocate.
@return void
Deallocate a dictionary object and all memory associated to it.
*/
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary *d) {
ssize_t i;
if (d == NULL)
return;
for (i = 0; i < d->size; i++) {
if (d->key[i] != NULL)
free(d->key[i]);
if (d->val[i] != NULL)
free(d->val[i]);
}
free(d->val);
free(d->key);
free(d->hash);
free(d);
return;
}
/*-------------------------------------------------------------------------*/
/**
@brief Get a value from a dictionary.
@param d dictionary object to search.
@param key Key to look for in the dictionary.
@param def Default value to return if key not found.
@return 1 pointer to internally allocated character string.
This function locates a key in a dictionary and returns a pointer to its
value, or the passed 'def' pointer if no such key can be found in
dictionary. The returned character pointer points to data internal to the
dictionary object, you should not try to free it or modify it.
*/
/*--------------------------------------------------------------------------*/
const char *dictionary_get(const dictionary *d, const char *key,
const char *def) {
unsigned hash;
ssize_t i;
hash = dictionary_hash(key);
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
/* Compare hash */
if (hash == d->hash[i]) {
/* Compare string, to avoid hash collisions */
if (!strcmp(key, d->key[i])) {
return d->val[i];
}
}
}
return def;
}
/*-------------------------------------------------------------------------*/
/**
@brief Set a value in a dictionary.
@param d dictionary object to modify.
@param key Key to modify or add.
@param val Value to add.
@return int 0 if Ok, anything else otherwise
If the given key is found in the dictionary, the associated value is
replaced by the provided one. If the key cannot be found in the
dictionary, it is added to it.
It is Ok to provide a NULL value for val, but NULL values for the dictionary
or the key are considered as errors: the function will return immediately
in such a case.
Notice that if you dictionary_set a variable to NULL, a call to
dictionary_get will return a NULL value: the variable will be found, and
its value (NULL) is returned. In other words, setting the variable
content to NULL is equivalent to deleting the variable from the
dictionary. It is not possible (in this implementation) to have a key in
the dictionary without value.
This function returns non-zero in case of failure.
*/
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary *d, const char *key, const char *val) {
ssize_t i;
unsigned hash;
if (d == NULL || key == NULL)
return -1;
/* Compute hash for this key */
hash = dictionary_hash(key);
/* Find if value is already in dictionary */
if (d->n > 0) {
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
if (hash == d->hash[i]) { /* Same hash value */
if (!strcmp(key, d->key[i])) { /* Same key */
/* Found a value: modify and return */
if (d->val[i] != NULL)
free(d->val[i]);
d->val[i] = (val ? xstrdup(val) : NULL);
/* Value has been modified: return */
return 0;
}
}
}
}
/* Add a new value */
/* See if dictionary needs to grow */
if (d->n == d->size) {
/* Reached maximum size: reallocate dictionary */
if (dictionary_grow(d) != 0)
return -1;
}
/* Insert key in the first empty slot. Start at d->n and wrap at
d->size. Because d->n < d->size this will necessarily
terminate. */
for (i = d->n; d->key[i];) {
if (++i == d->size)
i = 0;
}
/* Copy key */
d->key[i] = xstrdup(key);
d->val[i] = (val ? xstrdup(val) : NULL);
d->hash[i] = hash;
d->n++;
return 0;
}
/*-------------------------------------------------------------------------*/
/**
@brief Delete a key in a dictionary
@param d dictionary object to modify.
@param key Key to remove.
@return void
This function deletes a key in a dictionary. Nothing is done if the
key cannot be found.
*/
/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary *d, const char *key) {
unsigned hash;
ssize_t i;
if (key == NULL || d == NULL) {
return;
}
hash = dictionary_hash(key);
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
/* Compare hash */
if (hash == d->hash[i]) {
/* Compare string, to avoid hash collisions */
if (!strcmp(key, d->key[i])) {
/* Found key */
break;
}
}
}
if (i >= d->size)
/* Key not found */
return;
free(d->key[i]);
d->key[i] = NULL;
if (d->val[i] != NULL) {
free(d->val[i]);
d->val[i] = NULL;
}
d->hash[i] = 0;
d->n--;
return;
}
/*-------------------------------------------------------------------------*/
/**
@brief Dump a dictionary to an opened file pointer.
@param d Dictionary to dump
@param f Opened file pointer.
@return void
Dumps a dictionary onto an opened file pointer. Key pairs are printed out
as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
output file pointers.
*/
/*--------------------------------------------------------------------------*/
void dictionary_dump(const dictionary *d, FILE *out) {
ssize_t i;
if (d == NULL || out == NULL)
return;
if (d->n < 1) {
fprintf(out, "empty dictionary\n");
return;
}
for (i = 0; i < d->size; i++) {
if (d->key[i]) {
fprintf(out, "%20s\t[%s]\n", d->key[i], d->val[i] ? d->val[i] : "UNDEF");
}
}
return;
}

View File

@@ -0,0 +1,170 @@
/*-------------------------------------------------------------------------*/
/**
@file dictionary.h
@author N. Devillard
@brief Implements a dictionary for string variables.
This module implements a simple dictionary object, i.e. a list
of string/string associations. This object is useful to store e.g.
informations retrieved from a configuration file (ini files).
*/
/*--------------------------------------------------------------------------*/
#ifndef _DICTIONARY_H_
#define _DICTIONARY_H_
/*---------------------------------------------------------------------------
Includes
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------
New types
---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
@brief Dictionary object
This object contains a list of string/string associations. Each
association is identified by a unique string key. Looking up values
in the dictionary is speeded up by the use of a (hopefully collision-free)
hash function.
*/
/*-------------------------------------------------------------------------*/
typedef struct _dictionary_ {
int n; /** Number of entries in dictionary */
ssize_t size; /** Storage size */
char **val; /** List of string values */
char **key; /** List of string keys */
unsigned *hash; /** List of hash values for keys */
} dictionary;
/*---------------------------------------------------------------------------
Function prototypes
---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
@brief Compute the hash key for a string.
@param key Character string to use for key.
@return 1 unsigned int on at least 32 bits.
This hash function has been taken from an Article in Dr Dobbs Journal.
This is normally a collision-free function, distributing keys evenly.
The key is stored anyway in the struct so that collision can be avoided
by comparing the key itself in last resort.
*/
/*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char *key);
/*-------------------------------------------------------------------------*/
/**
@brief Create a new dictionary object.
@param size Optional initial size of the dictionary.
@return 1 newly allocated dictionary object.
This function allocates a new dictionary object of given size and returns
it. If you do not know in advance (roughly) the number of entries in the
dictionary, give size=0.
*/
/*--------------------------------------------------------------------------*/
dictionary *dictionary_new(size_t size);
/*-------------------------------------------------------------------------*/
/**
@brief Delete a dictionary object
@param d dictionary object to deallocate.
@return void
Deallocate a dictionary object and all memory associated to it.
*/
/*--------------------------------------------------------------------------*/
void dictionary_del(dictionary *vd);
/*-------------------------------------------------------------------------*/
/**
@brief Get a value from a dictionary.
@param d dictionary object to search.
@param key Key to look for in the dictionary.
@param def Default value to return if key not found.
@return 1 pointer to internally allocated character string.
This function locates a key in a dictionary and returns a pointer to its
value, or the passed 'def' pointer if no such key can be found in
dictionary. The returned character pointer points to data internal to the
dictionary object, you should not try to free it or modify it.
*/
/*--------------------------------------------------------------------------*/
const char *dictionary_get(const dictionary *d, const char *key,
const char *def);
/*-------------------------------------------------------------------------*/
/**
@brief Set a value in a dictionary.
@param d dictionary object to modify.
@param key Key to modify or add.
@param val Value to add.
@return int 0 if Ok, anything else otherwise
If the given key is found in the dictionary, the associated value is
replaced by the provided one. If the key cannot be found in the
dictionary, it is added to it.
It is Ok to provide a NULL value for val, but NULL values for the dictionary
or the key are considered as errors: the function will return immediately
in such a case.
Notice that if you dictionary_set a variable to NULL, a call to
dictionary_get will return a NULL value: the variable will be found, and
its value (NULL) is returned. In other words, setting the variable
content to NULL is equivalent to deleting the variable from the
dictionary. It is not possible (in this implementation) to have a key in
the dictionary without value.
This function returns non-zero in case of failure.
*/
/*--------------------------------------------------------------------------*/
int dictionary_set(dictionary *vd, const char *key, const char *val);
/*-------------------------------------------------------------------------*/
/**
@brief Delete a key in a dictionary
@param d dictionary object to modify.
@param key Key to remove.
@return void
This function deletes a key in a dictionary. Nothing is done if the
key cannot be found.
*/
/*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary *d, const char *key);
/*-------------------------------------------------------------------------*/
/**
@brief Dump a dictionary to an opened file pointer.
@param d Dictionary to dump
@param f Opened file pointer.
@return void
Dumps a dictionary onto an opened file pointer. Key pairs are printed out
as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
output file pointers.
*/
/*--------------------------------------------------------------------------*/
void dictionary_dump(const dictionary *d, FILE *out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,820 @@
/*-------------------------------------------------------------------------*/
/**
@file iniparser.c
@author N. Devillard
@brief Parser for ini files.
*/
/*--------------------------------------------------------------------------*/
/*---------------------------- Includes ------------------------------------*/
#include "iniparser.h"
#include <ctype.h>
#include <stdarg.h>
/*---------------------------- Defines -------------------------------------*/
#define ASCIILINESZ (1024)
#define INI_INVALID_KEY ((char *)-1)
/*---------------------------------------------------------------------------
Private to this module
---------------------------------------------------------------------------*/
/**
* This enum stores the status for each parsed line (internal use only).
*/
typedef enum _line_status_ {
LINE_UNPROCESSED,
LINE_ERROR,
LINE_EMPTY,
LINE_COMMENT,
LINE_SECTION,
LINE_VALUE
} line_status;
/*-------------------------------------------------------------------------*/
/**
@brief Convert a string to lowercase.
@param in String to convert.
@param out Output buffer.
@param len Size of the out buffer.
@return ptr to the out buffer or NULL if an error occured.
This function convert a string into lowercase.
At most len - 1 elements of the input string will be converted.
*/
/*--------------------------------------------------------------------------*/
static const char *strlwc(const char *in, char *out, unsigned len) {
unsigned i;
if (in == NULL || out == NULL || len == 0)
return NULL;
i = 0;
while (in[i] != '\0' && i < len - 1) {
out[i] = (char)tolower((int)in[i]);
i++;
}
out[i] = '\0';
return out;
}
/*-------------------------------------------------------------------------*/
/**
@brief Duplicate a string
@param s String to duplicate
@return Pointer to a newly allocated string, to be freed with free()
This is a replacement for strdup(). This implementation is provided
for systems that do not have it.
*/
/*--------------------------------------------------------------------------*/
static char *xstrdup(const char *s) {
char *t;
size_t len;
if (!s)
return NULL;
len = strlen(s) + 1;
t = (char *)malloc(len);
if (t) {
memcpy(t, s, len);
}
return t;
}
/*-------------------------------------------------------------------------*/
/**
@brief Remove blanks at the beginning and the end of a string.
@param str String to parse and alter.
@return unsigned New size of the string.
*/
/*--------------------------------------------------------------------------*/
static unsigned strstrip(char *s) {
char *last = NULL;
char *dest = s;
if (s == NULL)
return 0;
last = s + strlen(s);
while (isspace((int)*s) && *s)
s++;
while (last > s) {
if (!isspace((int)*(last - 1)))
break;
last--;
}
*last = (char)0;
memmove(dest, s, last - s + 1);
return last - s;
}
/*-------------------------------------------------------------------------*/
/**
@brief Default error callback for iniparser: wraps `fprintf(stderr, ...)`.
*/
/*--------------------------------------------------------------------------*/
static int default_error_callback(const char *format, ...) {
int ret;
va_list argptr;
va_start(argptr, format);
ret = vfprintf(stderr, format, argptr);
va_end(argptr);
return ret;
}
static int (*iniparser_error_callback)(const char *,
...) = default_error_callback;
/*-------------------------------------------------------------------------*/
/**
@brief Configure a function to receive the error messages.
@param errback Function to call.
By default, the error will be printed on stderr. If a null pointer is passed
as errback the error callback will be switched back to default.
*/
/*--------------------------------------------------------------------------*/
void iniparser_set_error_callback(int (*errback)(const char *, ...)) {
if (errback) {
iniparser_error_callback = errback;
} else {
iniparser_error_callback = default_error_callback;
}
}
/*-------------------------------------------------------------------------*/
/**
@brief Get number of sections in a dictionary
@param d Dictionary to examine
@return int Number of sections found in dictionary
This function returns the number of sections found in a dictionary.
The test to recognize sections is done on the string stored in the
dictionary: a section name is given as "section" whereas a key is
stored as "section:key", thus the test looks for entries that do not
contain a colon.
This clearly fails in the case a section name contains a colon, but
this should simply be avoided.
This function returns -1 in case of error.
*/
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(const dictionary *d) {
int i;
int nsec;
if (d == NULL)
return -1;
nsec = 0;
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
if (strchr(d->key[i], ':') == NULL) {
nsec++;
}
}
return nsec;
}
/*-------------------------------------------------------------------------*/
/**
@brief Get name for section n in a dictionary.
@param d Dictionary to examine
@param n Section number (from 0 to nsec-1).
@return Pointer to char string
This function locates the n-th section in a dictionary and returns
its name as a pointer to a string statically allocated inside the
dictionary. Do not free or modify the returned string!
This function returns NULL in case of error.
*/
/*--------------------------------------------------------------------------*/
const char *iniparser_getsecname(const dictionary *d, int n) {
int i;
int foundsec;
if (d == NULL || n < 0)
return NULL;
foundsec = 0;
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
if (strchr(d->key[i], ':') == NULL) {
foundsec++;
if (foundsec > n)
break;
}
}
if (foundsec <= n) {
return NULL;
}
return d->key[i];
}
/*-------------------------------------------------------------------------*/
/**
@brief Dump a dictionary to an opened file pointer.
@param d Dictionary to dump.
@param f Opened file pointer to dump to.
@return void
This function prints out the contents of a dictionary, one element by
line, onto the provided file pointer. It is OK to specify @c stderr
or @c stdout as output files. This function is meant for debugging
purposes mostly.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dump(const dictionary *d, FILE *f) {
int i;
if (d == NULL || f == NULL)
return;
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
if (d->val[i] != NULL) {
fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
} else {
fprintf(f, "[%s]=UNDEF\n", d->key[i]);
}
}
return;
}
/*-------------------------------------------------------------------------*/
/**
@brief Save a dictionary to a loadable ini file
@param d Dictionary to dump
@param f Opened file pointer to dump to
@return void
This function dumps a given dictionary into a loadable ini file.
It is Ok to specify @c stderr or @c stdout as output files.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(const dictionary *d, FILE *f) {
int i;
int nsec;
const char *secname;
if (d == NULL || f == NULL)
return;
nsec = iniparser_getnsec(d);
if (nsec < 1) {
/* No section in file: dump all keys as they are */
for (i = 0; i < d->size; i++) {
if (d->key[i] == NULL)
continue;
fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
}
return;
}
for (i = 0; i < nsec; i++) {
secname = iniparser_getsecname(d, i);
iniparser_dumpsection_ini(d, secname, f);
}
fprintf(f, "\n");
return;
}
/*-------------------------------------------------------------------------*/
/**
@brief Save a dictionary section to a loadable ini file
@param d Dictionary to dump
@param s Section name of dictionary to dump
@param f Opened file pointer to dump to
@return void
This function dumps a given section of a given dictionary into a loadable ini
file. It is Ok to specify @c stderr or @c stdout as output files.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(const dictionary *d, const char *s, FILE *f) {
int j;
char keym[ASCIILINESZ + 1];
int seclen;
if (d == NULL || f == NULL)
return;
if (!iniparser_find_entry(d, s))
return;
seclen = (int)strlen(s);
fprintf(f, "\n[%s]\n", s);
sprintf(keym, "%s:", s);
for (j = 0; j < d->size; j++) {
if (d->key[j] == NULL)
continue;
if (!strncmp(d->key[j], keym, seclen + 1)) {
fprintf(f, "%-30s = %s\n", d->key[j] + seclen + 1,
d->val[j] ? d->val[j] : "");
}
}
fprintf(f, "\n");
return;
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the number of keys in a section of a dictionary.
@param d Dictionary to examine
@param s Section name of dictionary to examine
@return Number of keys in section
*/
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(const dictionary *d, const char *s) {
int seclen, nkeys;
char keym[ASCIILINESZ + 1];
int j;
nkeys = 0;
if (d == NULL)
return nkeys;
if (!iniparser_find_entry(d, s))
return nkeys;
seclen = (int)strlen(s);
strlwc(s, keym, sizeof(keym));
keym[seclen] = ':';
for (j = 0; j < d->size; j++) {
if (d->key[j] == NULL)
continue;
if (!strncmp(d->key[j], keym, seclen + 1))
nkeys++;
}
return nkeys;
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the number of keys in a section of a dictionary.
@param d Dictionary to examine
@param s Section name of dictionary to examine
@param keys Already allocated array to store the keys in
@return The pointer passed as `keys` argument or NULL in case of error
This function queries a dictionary and finds all keys in a given section.
The keys argument should be an array of pointers which size has been
determined by calling `iniparser_getsecnkeys` function prior to this one.
Each pointer in the returned char pointer-to-pointer is pointing to
a string allocated in the dictionary; do not free or modify them.
*/
/*--------------------------------------------------------------------------*/
const char **iniparser_getseckeys(const dictionary *d, const char *s,
const char **keys) {
int i, j, seclen;
char keym[ASCIILINESZ + 1];
if (d == NULL || keys == NULL)
return NULL;
if (!iniparser_find_entry(d, s))
return NULL;
seclen = (int)strlen(s);
strlwc(s, keym, sizeof(keym));
keym[seclen] = ':';
i = 0;
for (j = 0; j < d->size; j++) {
if (d->key[j] == NULL)
continue;
if (!strncmp(d->key[j], keym, seclen + 1)) {
keys[i] = d->key[j];
i++;
}
}
return keys;
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key
@param d Dictionary to search
@param key Key string to look for
@param def Default value to return if key not found.
@return pointer to statically allocated character string
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the pointer passed as 'def' is returned.
The returned char pointer is pointing to a string allocated in
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
const char *iniparser_getstring(const dictionary *d, const char *key,
const char *def) {
const char *lc_key;
const char *sval;
char tmp_str[ASCIILINESZ + 1];
if (d == NULL || key == NULL)
return def;
lc_key = strlwc(key, tmp_str, sizeof(tmp_str));
sval = dictionary_get(d, lc_key, def);
return sval;
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an long int
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return long integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
Supported values for integers include the usual C notation
so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
are supported. Examples:
"42" -> 42
"042" -> 34 (octal -> decimal)
"0x42" -> 66 (hexa -> decimal)
Warning: the conversion may overflow in various ways. Conversion is
totally outsourced to strtol(), see the associated man page for overflow
handling.
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
long int iniparser_getlongint(const dictionary *d, const char *key,
long int notfound) {
const char *str;
str = iniparser_getstring(d, key, INI_INVALID_KEY);
if (str == INI_INVALID_KEY)
return notfound;
return strtol(str, NULL, 0);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an int
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
Supported values for integers include the usual C notation
so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
are supported. Examples:
"42" -> 42
"042" -> 34 (octal -> decimal)
"0x42" -> 66 (hexa -> decimal)
Warning: the conversion may overflow in various ways. Conversion is
totally outsourced to strtol(), see the associated man page for overflow
handling.
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
int iniparser_getint(const dictionary *d, const char *key, int notfound) {
return (int)iniparser_getlongint(d, key, notfound);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a double
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return double
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(const dictionary *d, const char *key,
double notfound) {
const char *str;
str = iniparser_getstring(d, key, INI_INVALID_KEY);
if (str == INI_INVALID_KEY)
return notfound;
return atof(str);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a boolean
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
A true boolean is found if one of the following is matched:
- A string starting with 'y'
- A string starting with 'Y'
- A string starting with 't'
- A string starting with 'T'
- A string starting with '1'
A false boolean is found if one of the following is matched:
- A string starting with 'n'
- A string starting with 'N'
- A string starting with 'f'
- A string starting with 'F'
- A string starting with '0'
The notfound value returned if no boolean is identified, does not
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(const dictionary *d, const char *key, int notfound) {
int ret;
const char *c;
c = iniparser_getstring(d, key, INI_INVALID_KEY);
if (c == INI_INVALID_KEY)
return notfound;
if (c[0] == 'y' || c[0] == 'Y' || c[0] == '1' || c[0] == 't' || c[0] == 'T') {
ret = 1;
} else if (c[0] == 'n' || c[0] == 'N' || c[0] == '0' || c[0] == 'f' ||
c[0] == 'F') {
ret = 0;
} else {
ret = notfound;
}
return ret;
}
/*-------------------------------------------------------------------------*/
/**
@brief Finds out if a given entry exists in a dictionary
@param ini Dictionary to search
@param entry Name of the entry to look for
@return integer 1 if entry exists, 0 otherwise
Finds out if a given entry exists in the dictionary. Since sections
are stored as keys with NULL associated values, this is the only way
of querying for the presence of sections in a dictionary.
*/
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(const dictionary *ini, const char *entry) {
int found = 0;
if (iniparser_getstring(ini, entry, INI_INVALID_KEY) != INI_INVALID_KEY) {
found = 1;
}
return found;
}
/*-------------------------------------------------------------------------*/
/**
@brief Set an entry in a dictionary.
@param ini Dictionary to modify.
@param entry Entry to modify (entry name)
@param val New value to associate to the entry.
@return int 0 if Ok, -1 otherwise.
If the given entry can be found in the dictionary, it is modified to
contain the provided value. If it cannot be found, the entry is created.
It is Ok to set val to NULL.
*/
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary *ini, const char *entry, const char *val) {
char tmp_str[ASCIILINESZ + 1];
return dictionary_set(ini, strlwc(entry, tmp_str, sizeof(tmp_str)), val);
}
/*-------------------------------------------------------------------------*/
/**
@brief Delete an entry in a dictionary
@param ini Dictionary to modify
@param entry Entry to delete (entry name)
@return void
If the given entry can be found, it is deleted from the dictionary.
*/
/*--------------------------------------------------------------------------*/
void iniparser_unset(dictionary *ini, const char *entry) {
char tmp_str[ASCIILINESZ + 1];
dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str)));
}
/*-------------------------------------------------------------------------*/
/**
@brief Load a single line from an INI file
@param input_line Input line, may be concatenated multi-line input
@param section Output space to store section
@param key Output space to store key
@param value Output space to store value
@return line_status value
*/
/*--------------------------------------------------------------------------*/
static line_status iniparser_line(const char *input_line, char *section,
char *key, char *value) {
line_status sta;
char *line = NULL;
size_t len;
line = xstrdup(input_line);
len = strstrip(line);
sta = LINE_UNPROCESSED;
if (len < 1) {
/* Empty line */
sta = LINE_EMPTY;
} else if (line[0] == '#' || line[0] == ';') {
/* Comment line */
sta = LINE_COMMENT;
} else if (line[0] == '[' && line[len - 1] == ']') {
/* Section name */
sscanf(line, "[%[^]]", section);
strstrip(section);
strlwc(section, section, len);
sta = LINE_SECTION;
} else if (sscanf(line, "%[^=] = \"%[^\"]\"", key, value) == 2 ||
sscanf(line, "%[^=] = '%[^\']'", key, value) == 2) {
/* Usual key=value with quotes, with or without comments */
strstrip(key);
strlwc(key, key, len);
/* Don't strip spaces from values surrounded with quotes */
sta = LINE_VALUE;
} else if (sscanf(line, "%[^=] = %[^;#]", key, value) == 2) {
/* Usual key=value without quotes, with or without comments */
strstrip(key);
strlwc(key, key, len);
strstrip(value);
/*
* sscanf cannot handle '' or "" as empty values
* this is done here
*/
if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
value[0] = 0;
}
sta = LINE_VALUE;
} else if (sscanf(line, "%[^=] = %[;#]", key, value) == 2 ||
sscanf(line, "%[^=] %[=]", key, value) == 2) {
/*
* Special cases:
* key=
* key=;
* key=#
*/
strstrip(key);
strlwc(key, key, len);
value[0] = 0;
sta = LINE_VALUE;
} else {
/* Generate syntax error */
sta = LINE_ERROR;
}
free(line);
return sta;
}
/*-------------------------------------------------------------------------*/
/**
@brief Parse an ini file and return an allocated dictionary object
@param ininame Name of the ini file to read.
@return Pointer to newly allocated dictionary
This is the parser for ini files. This function is called, providing
the name of the file to be read. It returns a dictionary object that
should not be accessed directly, but through accessor functions
instead.
The returned dictionary must be freed using iniparser_freedict().
*/
/*--------------------------------------------------------------------------*/
dictionary *iniparser_load(const char *ininame) {
FILE *in;
char line[ASCIILINESZ + 1];
char section[ASCIILINESZ + 1];
char key[ASCIILINESZ + 1];
char tmp[(ASCIILINESZ * 2) + 2];
char val[ASCIILINESZ + 1];
int last = 0;
int len;
int lineno = 0;
int errs = 0;
int mem_err = 0;
dictionary *dict;
if ((in = fopen(ininame, "r")) == NULL) {
iniparser_error_callback("iniparser: cannot open %s\n", ininame);
return NULL;
}
dict = dictionary_new(0);
if (!dict) {
fclose(in);
return NULL;
}
memset(line, 0, ASCIILINESZ);
memset(section, 0, ASCIILINESZ);
memset(key, 0, ASCIILINESZ);
memset(val, 0, ASCIILINESZ);
last = 0;
while (fgets(line + last, ASCIILINESZ - last, in) != NULL) {
lineno++;
len = (int)strlen(line) - 1;
if (len <= 0)
continue;
/* Safety check against buffer overflows */
if (line[len] != '\n' && !feof(in)) {
iniparser_error_callback("iniparser: input line too long in %s (%d)\n",
ininame, lineno);
dictionary_del(dict);
fclose(in);
return NULL;
}
/* Get rid of \n and spaces at end of line */
while ((len >= 0) && ((line[len] == '\n') || (isspace(line[len])))) {
line[len] = 0;
len--;
}
if (len < 0) { /* Line was entirely \n and/or spaces */
len = 0;
}
/* Detect multi-line */
if (line[len] == '\\') {
/* Multi-line value */
last = len;
continue;
} else {
last = 0;
}
switch (iniparser_line(line, section, key, val)) {
case LINE_EMPTY:
case LINE_COMMENT:
break;
case LINE_SECTION:
mem_err = dictionary_set(dict, section, NULL);
break;
case LINE_VALUE:
sprintf(tmp, "%s:%s", section, key);
mem_err = dictionary_set(dict, tmp, val);
break;
case LINE_ERROR:
iniparser_error_callback("iniparser: syntax error in %s (%d):\n-> %s\n",
ininame, lineno, line);
errs++;
break;
default:
break;
}
memset(line, 0, ASCIILINESZ);
last = 0;
if (mem_err < 0) {
iniparser_error_callback("iniparser: memory allocation failure\n");
break;
}
}
if (errs) {
dictionary_del(dict);
dict = NULL;
}
fclose(in);
return dict;
}
/*-------------------------------------------------------------------------*/
/**
@brief Free all memory associated to an ini dictionary
@param d Dictionary to free
@return void
Free all memory associated to an ini dictionary.
It is mandatory to call this function before the dictionary object
gets out of the current context.
*/
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary *d) { dictionary_del(d); }

View File

@@ -0,0 +1,356 @@
/*-------------------------------------------------------------------------*/
/**
@file iniparser.h
@author N. Devillard
@brief Parser for ini files.
*/
/*--------------------------------------------------------------------------*/
#ifndef _INIPARSER_H_
#define _INIPARSER_H_
/*---------------------------------------------------------------------------
Includes
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* The following #include is necessary on many Unixes but not Linux.
* It is not needed for Windows platforms.
* Uncomment it if needed.
*/
/* #include <unistd.h> */
#include "dictionary.h"
#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------------------------*/
/**
@brief Configure a function to receive the error messages.
@param errback Function to call.
By default, the error will be printed on stderr. If a null pointer is passed
as errback the error callback will be switched back to default.
*/
/*--------------------------------------------------------------------------*/
void iniparser_set_error_callback(int (*errback)(const char *, ...));
/*-------------------------------------------------------------------------*/
/**
@brief Get number of sections in a dictionary
@param d Dictionary to examine
@return int Number of sections found in dictionary
This function returns the number of sections found in a dictionary.
The test to recognize sections is done on the string stored in the
dictionary: a section name is given as "section" whereas a key is
stored as "section:key", thus the test looks for entries that do not
contain a colon.
This clearly fails in the case a section name contains a colon, but
this should simply be avoided.
This function returns -1 in case of error.
*/
/*--------------------------------------------------------------------------*/
int iniparser_getnsec(const dictionary *d);
/*-------------------------------------------------------------------------*/
/**
@brief Get name for section n in a dictionary.
@param d Dictionary to examine
@param n Section number (from 0 to nsec-1).
@return Pointer to char string
This function locates the n-th section in a dictionary and returns
its name as a pointer to a string statically allocated inside the
dictionary. Do not free or modify the returned string!
This function returns NULL in case of error.
*/
/*--------------------------------------------------------------------------*/
const char *iniparser_getsecname(const dictionary *d, int n);
/*-------------------------------------------------------------------------*/
/**
@brief Save a dictionary to a loadable ini file
@param d Dictionary to dump
@param f Opened file pointer to dump to
@return void
This function dumps a given dictionary into a loadable ini file.
It is Ok to specify @c stderr or @c stdout as output files.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dump_ini(const dictionary *d, FILE *f);
/*-------------------------------------------------------------------------*/
/**
@brief Save a dictionary section to a loadable ini file
@param d Dictionary to dump
@param s Section name of dictionary to dump
@param f Opened file pointer to dump to
@return void
This function dumps a given section of a given dictionary into a loadable ini
file. It is Ok to specify @c stderr or @c stdout as output files.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dumpsection_ini(const dictionary *d, const char *s, FILE *f);
/*-------------------------------------------------------------------------*/
/**
@brief Dump a dictionary to an opened file pointer.
@param d Dictionary to dump.
@param f Opened file pointer to dump to.
@return void
This function prints out the contents of a dictionary, one element by
line, onto the provided file pointer. It is OK to specify @c stderr
or @c stdout as output files. This function is meant for debugging
purposes mostly.
*/
/*--------------------------------------------------------------------------*/
void iniparser_dump(const dictionary *d, FILE *f);
/*-------------------------------------------------------------------------*/
/**
@brief Get the number of keys in a section of a dictionary.
@param d Dictionary to examine
@param s Section name of dictionary to examine
@return Number of keys in section
*/
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(const dictionary *d, const char *s);
/*-------------------------------------------------------------------------*/
/**
@brief Get the number of keys in a section of a dictionary.
@param d Dictionary to examine
@param s Section name of dictionary to examine
@param keys Already allocated array to store the keys in
@return The pointer passed as `keys` argument or NULL in case of error
This function queries a dictionary and finds all keys in a given section.
The keys argument should be an array of pointers which size has been
determined by calling `iniparser_getsecnkeys` function prior to this one.
Each pointer in the returned char pointer-to-pointer is pointing to
a string allocated in the dictionary; do not free or modify them.
*/
/*--------------------------------------------------------------------------*/
const char **iniparser_getseckeys(const dictionary *d, const char *s,
const char **keys);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key
@param d Dictionary to search
@param key Key string to look for
@param def Default value to return if key not found.
@return pointer to statically allocated character string
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the pointer passed as 'def' is returned.
The returned char pointer is pointing to a string allocated in
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
const char *iniparser_getstring(const dictionary *d, const char *key,
const char *def);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an int
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
Supported values for integers include the usual C notation
so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
are supported. Examples:
- "42" -> 42
- "042" -> 34 (octal -> decimal)
- "0x42" -> 66 (hexa -> decimal)
Warning: the conversion may overflow in various ways. Conversion is
totally outsourced to strtol(), see the associated man page for overflow
handling.
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
int iniparser_getint(const dictionary *d, const char *key, int notfound);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an long int
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
Supported values for integers include the usual C notation
so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
are supported. Examples:
- "42" -> 42
- "042" -> 34 (octal -> decimal)
- "0x42" -> 66 (hexa -> decimal)
Warning: the conversion may overflow in various ways. Conversion is
totally outsourced to strtol(), see the associated man page for overflow
handling.
*/
/*--------------------------------------------------------------------------*/
long int iniparser_getlongint(const dictionary *d, const char *key,
long int notfound);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a double
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return double
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
double iniparser_getdouble(const dictionary *d, const char *key,
double notfound);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a boolean
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
A true boolean is found if one of the following is matched:
- A string starting with 'y'
- A string starting with 'Y'
- A string starting with 't'
- A string starting with 'T'
- A string starting with '1'
A false boolean is found if one of the following is matched:
- A string starting with 'n'
- A string starting with 'N'
- A string starting with 'f'
- A string starting with 'F'
- A string starting with '0'
The notfound value returned if no boolean is identified, does not
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
int iniparser_getboolean(const dictionary *d, const char *key, int notfound);
/*-------------------------------------------------------------------------*/
/**
@brief Set an entry in a dictionary.
@param ini Dictionary to modify.
@param entry Entry to modify (entry name)
@param val New value to associate to the entry.
@return int 0 if Ok, -1 otherwise.
If the given entry can be found in the dictionary, it is modified to
contain the provided value. If it cannot be found, the entry is created.
It is Ok to set val to NULL.
*/
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary *ini, const char *entry, const char *val);
/*-------------------------------------------------------------------------*/
/**
@brief Delete an entry in a dictionary
@param ini Dictionary to modify
@param entry Entry to delete (entry name)
@return void
If the given entry can be found, it is deleted from the dictionary.
*/
/*--------------------------------------------------------------------------*/
void iniparser_unset(dictionary *ini, const char *entry);
/*-------------------------------------------------------------------------*/
/**
@brief Finds out if a given entry exists in a dictionary
@param ini Dictionary to search
@param entry Name of the entry to look for
@return integer 1 if entry exists, 0 otherwise
Finds out if a given entry exists in the dictionary. Since sections
are stored as keys with NULL associated values, this is the only way
of querying for the presence of sections in a dictionary.
*/
/*--------------------------------------------------------------------------*/
int iniparser_find_entry(const dictionary *ini, const char *entry);
/*-------------------------------------------------------------------------*/
/**
@brief Parse an ini file and return an allocated dictionary object
@param ininame Name of the ini file to read.
@return Pointer to newly allocated dictionary
This is the parser for ini files. This function is called, providing
the name of the file to be read. It returns a dictionary object that
should not be accessed directly, but through accessor functions
instead.
The returned dictionary must be freed using iniparser_freedict().
*/
/*--------------------------------------------------------------------------*/
dictionary *iniparser_load(const char *ininame);
/*-------------------------------------------------------------------------*/
/**
@brief Free all memory associated to an ini dictionary
@param d Dictionary to free
@return void
Free all memory associated to an ini dictionary.
It is mandatory to call this function before the dictionary object
gets out of the current context.
*/
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary *d);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,139 @@
// Copyright 2021 Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "iniparser.h"
#include "uvc_log.h"
#include <pthread.h>
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "param.c"
char g_ini_path_[256];
dictionary *g_ini_d_;
static pthread_mutex_t g_param_mutex = PTHREAD_MUTEX_INITIALIZER;
int rk_param_dump() {
const char *section_name;
const char *keys[32];
int section_keys;
int section_num = iniparser_getnsec(g_ini_d_);
LOG_INFO("section_num is %d\n", section_num);
for (int i = 0; i < section_num; i++) {
section_name = iniparser_getsecname(g_ini_d_, i);
LOG_INFO("section_name is %s\n", section_name);
section_keys = iniparser_getsecnkeys(g_ini_d_, section_name);
for (int j = 0; j < section_keys; j++) {
iniparser_getseckeys(g_ini_d_, section_name, keys);
LOG_INFO("%s = %s\n", keys[j],
iniparser_getstring(g_ini_d_, keys[j], ""));
}
}
return 0;
}
int rk_param_save() {
FILE *fp = fopen(g_ini_path_, "w");
if (fp == NULL) {
LOG_ERROR("%s, fopen error!\n", g_ini_path_);
iniparser_freedict(g_ini_d_);
g_ini_d_ = NULL;
return -1;
}
iniparser_dump_ini(g_ini_d_, fp);
fflush(fp);
fclose(fp);
return 0;
}
int rk_param_get_int(const char *entry, int default_val) {
int ret;
pthread_mutex_lock(&g_param_mutex);
ret = iniparser_getint(g_ini_d_, entry, default_val);
pthread_mutex_unlock(&g_param_mutex);
return ret;
}
int rk_param_set_int(const char *entry, int val) {
char tmp[8];
sprintf(tmp, "%d", val);
pthread_mutex_lock(&g_param_mutex);
iniparser_set(g_ini_d_, entry, tmp);
rk_param_save();
pthread_mutex_unlock(&g_param_mutex);
return 0;
}
const char *rk_param_get_string(const char *entry, const char *default_val) {
const char *ret;
pthread_mutex_lock(&g_param_mutex);
ret = iniparser_getstring(g_ini_d_, entry, default_val);
pthread_mutex_unlock(&g_param_mutex);
return ret;
}
int rk_param_set_string(const char *entry, const char *val) {
pthread_mutex_lock(&g_param_mutex);
iniparser_set(g_ini_d_, entry, val);
rk_param_save();
pthread_mutex_unlock(&g_param_mutex);
return 0;
}
int rk_param_init(char *ini_path) {
LOG_INFO("%s\n", __func__);
pthread_mutex_lock(&g_param_mutex);
g_ini_d_ = NULL;
if (ini_path)
memcpy(g_ini_path_, ini_path, strlen(ini_path));
else
memcpy(g_ini_path_, "/oem/usr/share/rkuvc.ini", strlen("/oem/usr/share/rkuvc.ini"));
LOG_INFO("g_ini_path_ is %s\n", g_ini_path_);
g_ini_d_ = iniparser_load(g_ini_path_);
if (g_ini_d_ == NULL) {
LOG_ERROR("iniparser_load error!\n");
return -1;
}
rk_param_dump();
pthread_mutex_unlock(&g_param_mutex);
return 0;
}
int rk_param_deinit() {
LOG_INFO("%s\n", __func__);
if (g_ini_d_ == NULL)
return 0;
pthread_mutex_lock(&g_param_mutex);
rk_param_save();
if (g_ini_d_)
iniparser_freedict(g_ini_d_);
pthread_mutex_unlock(&g_param_mutex);
return 0;
}
int rk_param_reload() {
LOG_INFO("%s\n", __func__);
pthread_mutex_lock(&g_param_mutex);
if (g_ini_d_)
iniparser_freedict(g_ini_d_);
g_ini_d_ = iniparser_load(g_ini_path_);
if (g_ini_d_ == NULL) {
LOG_ERROR("iniparser_load error!\n");
return -1;
}
rk_param_dump();
pthread_mutex_unlock(&g_param_mutex);
return 0;
}

View File

@@ -0,0 +1,28 @@
// Copyright 2021 Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#include "iniparser.h"
extern dictionary *g_ini_d_;
int rk_param_get_int(const char *entry, int default_val);
int rk_param_set_int(const char *entry, int val);
const char *rk_param_get_string(const char *entry, const char *default_val);
int rk_param_set_string(const char *entry, const char *val);
int rk_param_save();
int rk_param_init(char *ini_path);
int rk_param_deinit();
int rk_param_reload();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

View File

@@ -0,0 +1,82 @@
[video.source]
enable_aiq = 1
enable_vo = 0
enable_npu = 0
enable_uac = 0
[isp.0.adjustment]
contrast = 50
brightness = 50
saturation = 50
sharpness = 50
fps = 30
hue = 50
[isp.0.exposure]
iris_type = auto
exposure_mode = auto
gain_mode = auto
auto_iris_level = 5
auto_exposure_enabled = 1
audo_gain_enabled = 1
exposure_time = 1/6
exposure_gain = 1
[isp.0.night_to_day]
night_to_day = day
night_to_day_filter_level = 5
night_to_day_filter_time = 5
dawn_time = 07:00:00
dusk_time = 18:00:00
ircut_filter_action = day
over_exposure_suppress = open
over_exposure_suppress_type = auto
fill_light_mode = IR
brightness_adjustment_mode = auto
light_brightness = 1
distance_level = 1
[isp.0.blc]
blc_region = close
blc_strength = 1
wdr = close
wdr_level = 0
hdr = close
hdr_level = 1
hlc = close
hlc_level = 0
dark_boost_level = 0
position_x = 0
position_y = 0
blc_region_width = 120
blc_region_high = 92
[isp.0.white_blance]
white_blance_style = autoWhiteBalance
white_blance_red = 50
white_blance_green = 50
white_blance_blue = 50
[isp.0.enhancement]
noise_reduce_mode = close
denoise_level = 50
spatial_denoise_level = 50
temporal_denoise_level = 50
dehaze = close
dehaze_level = 0
dis = close
gray_scale_mode = [0-255]
image_rotation = 0
distortion_correction = close
ldch_level = 0
[isp.0.video_adjustment]
image_flip = close
scene_mode = indoor
power_line_frequency_mode = PAL(50HZ)
[isp.0.auto_focus]
af_mode = semi-auto
zoom_level = 0
focus_level = 0

View File

@@ -0,0 +1,79 @@
{
"skv_configs": {
"aec": {
"status" : "disable",
"drop_ref_channel" : 0,
"delay_len" : 0,
"look_ahead" : 0
},
"bf": {
"status" : "enable",
"targ" : 0,
"drop_ref_channel" : 0
},
"fast_aec": {
"status" : "enable"
},
"aes": {
"status" : "enable",
"beta_up": "float:0.0005",
"beta_down": "float:0.01"
},
"gsc": {
"status" : "disable",
"method" : 0
},
"agc": {
"status" : "enable",
"attack_time" : "float:100.0",
"release_time" : "float:400.0",
"attenuate_time" : "float:1000",
"max_gain" : "float:30.0",
"max_peak" : "float:-1.0",
"fRth0": "float:-65",
"fRth1" : "float:-50",
"fRth2" : "float:-35",
"fRk0" : "float:2.5",
"fRk1" : "float:0.8",
"fRk2" : "float:0.4",
"fLineGainDb" : "float:10.0",
"swSmL0" : 40,
"swSmL1" : 80,
"swSmL2" : 80
},
"anr": {
"status" : "enable",
"noiseFactor" : "float:0.88",
"swU" : 10,
"psiMin" : "float:0.02",
"psiMax" : "float:0.516",
"fGmin" : "float:0.1"
},
"nlp": {
"status" : "disable",
"band_pass_thd" : "10,10,10,5,5,5,0,0",
"super_est_factor" : "6,10,10,10,10,10,6,6"
},
"dereverb": {
"status" : "disable",
"rlsLg" : 4,
"curveLg" : 10,
"delay" : 2,
"forgetting" : "float:0.98",
"t60" : "float:1.5",
"coCoeff" : "float:2.0"
},
"cng": {
"status" : "disable",
"fGain" : "float:2.0",
"fMpy" : "float:5",
"fSmoothAlpha" : "float:0.92",
"fSpeechGain" : "float:0.3"
},
"dtd": {
"status" : "disable",
"ksiThd_high" : "float:0.7",
"ksiThd_low" : "float:0.5"
}
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_MPI_MPI_CONTROL_H_
#define SRC_MPI_MPI_CONTROL_H_
#ifdef __cplusplus
#include "uac_common_def.h"
#include <rk_comm_af.h>
#include <rk_comm_aio.h>
#include <rk_debug.h>
#include <rk_mpi_af.h>
#include <rk_mpi_ai.h>
#include <rk_mpi_amix.h>
#include <rk_mpi_ao.h>
#include <rk_mpi_sys.h>
#include <rk_type.h>
#define UAC_MPI_ENABLE (1 << 1)
#define MIC_SPK_SOUNDCARD_INDEX 0
typedef enum _UacMpiType {
UAC_MPI_TYPE_AI = 0,
UAC_MPI_TYPE_AO = 1,
UAC_MPI_TYPE_AF_VQE = 2,
UAC_MPI_TYPE_MAX
} UacMpiType;
typedef enum _UacMpiAODevId {
AO_USB_DEV, // ao[0]
AO_SPK_DEV, // ao[1]
} UacMpiAODevId;
typedef enum _UacMpiAIDevId {
AI_MIC_DEV, // ai[0]
AI_USB_DEV, // ai[1]
} UacMpiAIDevId;
typedef enum _UacMpiAFChnId {
AF_VQE_CHN, // af[0]
} UacMpiAFChnId;
typedef struct _UacMpiIdConfig {
AUDIO_DEV aoDevId;
AUDIO_DEV aiDevId;
AO_CHN aoChnId;
AI_CHN aiChnId;
AF_CHN vqeChnId;
} UacMpiIdConfig;
typedef struct _UacMpiStream {
int flag;
UacMpiIdConfig idCfg;
UacAudioConfig config;
} UacMpiStream;
class UacMpiUtil {
public:
static const char *getSndCardName(UacMpiType type, int mode);
static RK_U32 getSndCardChannels(UacMpiType type, int mode);
static RK_U32 getSndCardSampleRate(UacMpiType type, int mode);
static AUDIO_BIT_WIDTH_E getSndCardbitWidth(UacMpiType type, int mode);
static RK_U32 getDataSamplerate(UacMpiType type, int mode);
static AUDIO_BIT_WIDTH_E getDataBitwidth(UacMpiType type, int mode);
static AUDIO_SOUND_MODE_E getDataSoundmode(UacMpiType type, int mode);
static const char *getVqeCfgPath();
static RK_U32 getVqeSampleRate();
static RK_U32 getVqeChannels();
static RK_U32 getVqeChnLayout();
static RK_U32 getVqeRefLayout();
static RK_U32 getVqeMicLayout();
};
void mpi_set_samplerate(int type, UacMpiStream &streamCfg);
void mpi_set_volume(int type, UacMpiStream &streamCfg);
void mpi_set_ppm(int type, UacMpiStream &streamCfg);
#endif
#endif // SRC_MPI_MPI_CONTROL_H_

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_MPI_MPI_UAC_AMIXER_H_
#define SRC_MPI_MPI_UAC_AMIXER_H_
#include "rk_common.h"
typedef enum _HARDWARE_REF_MODE {
HARDWARE_REF_DISABLE = 0, // disable hardware ref channel
HARDWARE_REF_MODE1, // 4chn: 2 mic + 1 ref
HARDWARE_REF_MODE2, // 2chn: 1 mic + 1 ref
HARDWARE_REF_MODE2_SWAP // 2chn: 1 ref + 1 mic
} HARDWARE_REF_MODE;
typedef struct _MpiChnAttrConfigMap {
RK_U32 u32Index;
RK_U32 u32Channels;
RK_U32 u32MicLayout;
RK_U32 u32RefLayout;
const char *chMode;
} MpiChnAttrConfigMap;
// the hardware of our RV1106's evb board support mode2
const static int sRefMode = HARDWARE_REF_MODE2;
const static MpiChnAttrConfigMap sChnAttrCfgs[] = {
{HARDWARE_REF_DISABLE, 2, 0x3, 0x0,
"Disable"}, // disable hardware ref channel
{HARDWARE_REF_MODE1, 4, 0x3, 0xc, "Mode1"}, // 4chn: 2 mic + 1 ref
{HARDWARE_REF_MODE2, 2, 0x1, 0x2,
"Mode2"}, // 2chn: 1 mic(ADC Left) + 1 ref(DAC Right)
{HARDWARE_REF_MODE2_SWAP, 2, 0x2, 0x1,
"Mode2 Swap"}, // 2chn: 1 ref(DAC Left) + 1 mic(ADC Right)
};
class UACAmixer {
public:
static RK_S32 set(AUDIO_DEV AmixDevId, const char *ctrlName,
const char *value);
static RK_S32 get(AUDIO_DEV AmixDevId, const char *ctrlName);
static void dumpContents(AUDIO_DEV AmixDevId);
};
RK_S32 amix_set_ref_mode(AUDIO_DEV AoDevId);
RK_S32 amix_set_ppm(AUDIO_DEV AoDevId, RK_S32 ppm);
#endif // SRC_MPI_MPI_UAC_AMIXER_H_

View File

@@ -0,0 +1,87 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_INCLUDE_UAC_COMMON_DEF_H_
#define SRC_INCLUDE_UAC_COMMON_DEF_H_
#ifdef __cplusplus
#include <dirent.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define OPT_SAMPLE_RATE "opt_samaple_rate"
#define OPT_CHANNELS "opt_channel"
#define OPT_VOLUME "opt_volume"
#define OPT_MUTE "opt_mute"
#define OPT_CONFIGS "opt_configs"
#define OPT_PPM "opt_ppm"
#define OPT_SET_ALSA_CAPTURE "set_capture_config"
#define OPT_SET_RESAMPLE "set_resample_config"
#define OPT_SET_VOLUME "set_volume_config"
#define OPT_SET_CONFIG "set_config"
#define OPT_SET_PPM "set_ppm"
#define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
#define GET_ENTRY_VALUE(INPUT1, INPUT2, MAP, KEY1, KEY2, VALUE) \
do { \
for (size_t i = 0; i < ARRAY_ELEMS(MAP); i++) { \
if (INPUT1 == MAP[i].KEY1 && INPUT2 == MAP[i].KEY2) \
return MAP[i].VALUE; \
} \
} while (0)
enum UacStreamType {
// our device record datas from usb, pc/remote->our device
UAC_STREAM_RECORD = 0,
// play datas to usb, our device->pc/remote
UAC_STREAM_PLAYBACK,
UAC_STREAM_MAX
};
typedef struct _UacAudioConfig {
int samplerate;
union {
int intVol;
float floatVol;
};
int mute;
int ppm;
} UacAudioConfig;
uint64_t getRelativeTimeMs();
uint64_t getRelativeTimeUs();
#endif
#endif // SRC_INCLUDE_UAC_COMMON_DEF_H_

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2020 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_INCLUDE_UAC_CONTROL_H_
#define SRC_INCLUDE_UAC_CONTROL_H_
#include "uac_common_def.h"
enum UacApiType { UAC_API_MPI = 0, UAC_API_GRAPH = 1, UAC_API_MAX };
#ifdef __cplusplus
class UACControl {
public:
UACControl() {}
virtual ~UACControl() {}
public:
virtual int uacStart() = 0;
virtual void uacStop() = 0;
virtual void uacSetSampleRate(int sampleRate) = 0;
virtual void uacSetVolume(int volume) = 0;
virtual void uacSetMute(int mute) = 0;
virtual void uacSetPpm(int ppm) = 0;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
int uac_start(int mode);
void uac_stop(int mode);
void uac_set_sample_rate(int mode, int samplerate);
void uac_set_volume(int mode, int volume);
void uac_set_mute(int mode, int mute);
void uac_set_ppm(int mode, int ppm);
int uac_control_create(int type);
void uac_control_destory();
#ifdef __cplusplus
}
#endif
#endif // SRC_INCLUDE_UAC_CONTROL_H_

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_INCLUDE_UAC_CONTROL_FACTORY_H
#define SRC_INCLUDE_UAC_CONTROL_FACTORY_H
#ifdef __cplusplus
#include "uac_common_def.h"
#include "uac_control.h"
class UacControlFactory {
public:
static UACControl *create(UacApiType type, int mode);
};
#endif
#endif // SRC_INCLUDE_UAC_CONTROL_FACTORY_H

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_INCLUDE_UAC_CONTROL_GRAPH_H_
#define SRC_INCLUDE_UAC_CONTROL_GRAPH_H_
#ifdef __cplusplus
#include "uac_control.h"
class UACControlGraph : public UACControl {
public:
UACControlGraph(int mode);
virtual ~UACControlGraph();
public:
virtual int uacStart();
virtual void uacStop();
virtual void uacSetSampleRate(int sampleRate);
virtual void uacSetVolume(int volume);
virtual void uacSetMute(int mute);
virtual void uacSetPpm(int ppm);
private:
void *mCtx;
};
#endif
#endif // SRC_INCLUDE_UAC_CONTROL_GRAPH_H_

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SRC_INCLUDE_UAC_CONTROL_MPI_H_
#define SRC_INCLUDE_UAC_CONTROL_MPI_H_
#ifdef __cplusplus
#include "uac_control.h"
class UACControlMpi : public UACControl {
public:
UACControlMpi(int mode);
virtual ~UACControlMpi();
public:
virtual int uacStart();
virtual void uacStop();
virtual void uacSetSampleRate(int sampleRate);
virtual void uacSetVolume(int volume);
virtual void uacSetMute(int mute);
virtual void uacSetPpm(int ppm);
protected:
int startAi();
int startVqe();
int startAo();
void streamBind();
int stopAi();
int stopVqe();
int stopAo();
void streamUnBind();
private:
void *mCtx;
};
#endif
#endif // SRC_INCLUDE_UAC_CONTROL_MPI_H_

View File

@@ -0,0 +1,63 @@
// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_INCLUDE_UAC_LOGGER_H_
#define SRC_INCLUDE_UAC_LOGGER_H_
//#ifdef __cplusplus
#ifdef uac_minilogGER
#include "minilogger/log.h"
#else
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#define uac_minilog_warn(...)
#define uac_minilog_error(...)
#define uac_minilog_info(...)
#define uac_minilog_debug(...)
#define __uac_minilog_log_init(...)
#endif
extern int uac_app_log_level;
#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_WARN 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_DEBUG 3
#ifndef LOG_TAG
#define LOG_TAG "uac_app"
#endif
#define ALOGI(format, ...) \
do { \
if (uac_app_log_level < LOG_LEVEL_INFO) \
break; \
\ fprintf(stderr, "[%s][%s]:" format, LOG_TAG, __FUNCTION__, \
##__VA_ARGS__); \
} while (0)
#define ALOGW(format, ...) \
do { \
if (uac_app_log_level < LOG_LEVEL_WARN) \
break; \
\ fprintf(stderr, "[%s][%s]:" format, LOG_TAG, __FUNCTION__, \
##__VA_ARGS__); \
} while (0)
#define ALOGE(format, ...) \
do { \
if (uac_app_log_level < LOG_LEVEL_ERROR) \
break; \
fprintf(stderr, "[%s][%s]:" format, LOG_TAG, __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#define ALOGD(format, ...) \
do { \
if (uac_app_log_level < LOG_LEVEL_DEBUG) \
break; \
fprintf(stderr, "[%s][%s]:" format, LOG_TAG, __FUNCTION__, ##__VA_ARGS__); \
} while (0)
//#endif
#endif // SRC_INCLUDE_UAC_LOGGER_H_

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SRC_INCLUDE_UEVENT_H_
#define SRC_INCLUDE_UEVENT_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
struct _uevent {
char *strs[30];
int size;
};
#ifdef __cplusplus
extern "C" {
#endif
int uac_uevent_monitor_run();
#ifdef __cplusplus
}
#endif
#endif // SRC_INCLUDE_UEVENT_H_

View File

@@ -0,0 +1,536 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
//#ifdef __cplusplus
#include "uac_control_mpi.h"
#include "mpi_control_common.h"
#include "uac_amixer.h"
#include "uac_log.h"
#ifdef LOG_TAG
#undef LOG_TAG
#define LOG_TAG "uac_mpi"
#endif
#define OPEN_VQE 1
typedef struct _UacControlMpi {
int mode;
UacMpiStream stream;
} UacControlMpi;
UacControlMpi *getContextMpi(void *context) {
UacControlMpi *ctx = reinterpret_cast<UacControlMpi *>(context);
return ctx;
}
UACControlMpi::UACControlMpi(int mode) {
UacControlMpi *ctx = (UacControlMpi *)calloc(1, sizeof(UacControlMpi));
memset(ctx, 0, sizeof(UacControlMpi));
ctx->mode = mode;
ctx->stream.config.intVol = 100;
ctx->stream.config.mute = 0;
ctx->stream.config.ppm = 0;
if (mode == UAC_STREAM_PLAYBACK) {
ctx->stream.idCfg.aiDevId = (AUDIO_DEV)AI_MIC_DEV;
ctx->stream.idCfg.aoDevId = (AUDIO_DEV)AO_USB_DEV;
ctx->stream.config.samplerate =
UacMpiUtil::getDataSamplerate(UAC_MPI_TYPE_AO, ctx->mode);
} else if (mode == UAC_STREAM_RECORD) {
ctx->stream.idCfg.aiDevId = (AUDIO_DEV)AI_USB_DEV;
ctx->stream.idCfg.aoDevId = (AUDIO_DEV)AO_SPK_DEV;
ctx->stream.config.samplerate =
UacMpiUtil::getDataSamplerate(UAC_MPI_TYPE_AI, ctx->mode);
// always set index of spk's sound card(hw:0,0)
amix_set_ref_mode(MIC_SPK_SOUNDCARD_INDEX);
}
mCtx = reinterpret_cast<void *>(ctx);
}
UACControlMpi::~UACControlMpi() {
UacControlMpi *ctx = getContextMpi(mCtx);
if (ctx) {
free(ctx);
}
mCtx = NULL;
}
void UACControlMpi::uacSetSampleRate(int sampleRate) {
UacControlMpi *ctx = getContextMpi(mCtx);
ctx->stream.config.samplerate = sampleRate;
ALOGD("mode = %d, sampleRate = %d\n", ctx->mode, sampleRate);
if ((ctx->stream.flag &= UAC_MPI_ENABLE) == UAC_MPI_ENABLE) {
mpi_set_samplerate(ctx->mode, ctx->stream);
}
}
void UACControlMpi::uacSetVolume(int volume) {
UacControlMpi *ctx = getContextMpi(mCtx);
ALOGD("mode = %d, volume = %d\n", ctx->mode, volume);
ctx->stream.config.intVol = volume;
if ((ctx->stream.flag &= UAC_MPI_ENABLE) == UAC_MPI_ENABLE) {
mpi_set_volume(ctx->mode, ctx->stream);
}
}
void UACControlMpi::uacSetMute(int mute) {
UacControlMpi *ctx = getContextMpi(mCtx);
ALOGD("mode = %d, mute = %d\n", ctx->mode, mute);
ctx->stream.config.mute = mute;
if ((ctx->stream.flag &= UAC_MPI_ENABLE) == UAC_MPI_ENABLE) {
mpi_set_volume(ctx->mode, ctx->stream);
}
}
void UACControlMpi::uacSetPpm(int ppm) {
ALOGD("ppm = %d\n", ppm);
UacControlMpi *ctx = getContextMpi(mCtx);
ctx->stream.config.ppm = ppm;
if ((ctx->stream.flag &= UAC_MPI_ENABLE) == UAC_MPI_ENABLE) {
mpi_set_ppm(ctx->mode, ctx->stream);
}
}
int UACControlMpi::uacStart() {
uacStop();
int ret = 0;
UacControlMpi *ctx = getContextMpi(mCtx);
ret = startAi();
if (ret != 0) {
goto __FAILED;
}
/*
* only add 3A process in playback(data flow: 1106's mic-->pc/host),
* do not add 3A process in record(data flow: pc/host-->1106's spk )
* for avoid sound like music process by 3A
*/
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
ret = startVqe();
if (ret != 0) {
goto __FAILED;
}
}
ret = startAo();
if (ret != 0) {
goto __FAILED;
}
mpi_set_samplerate(ctx->mode, ctx->stream);
mpi_set_volume(ctx->mode, ctx->stream);
mpi_set_ppm(ctx->mode, ctx->stream);
streamBind();
ctx->stream.flag |= UAC_MPI_ENABLE;
return 0;
__FAILED:
return -1;
}
void UACControlMpi::uacStop() {
UacControlMpi *ctx = getContextMpi(mCtx);
ALOGD("stop mode = %d, flag = %d\n", ctx->mode, ctx->stream.flag);
if ((ctx->stream.flag &= UAC_MPI_ENABLE) == UAC_MPI_ENABLE) {
streamUnBind();
stopAi();
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
stopVqe();
}
stopAo();
ctx->stream.flag &= (~UAC_MPI_ENABLE);
}
}
int UACControlMpi::startAi() {
UacControlMpi *ctx = getContextMpi(mCtx);
AUDIO_DEV aiDevId = ctx->stream.idCfg.aiDevId;
AI_CHN aiChn = ctx->stream.idCfg.aiChnId;
ALOGD("this:%p, startAi(dev:%d, chn:%d), mode : %d\n", this, aiDevId, aiChn,
ctx->mode);
const char *cardName = RK_NULL;
RK_S32 result = 0;
AUDIO_SAMPLE_RATE_E rate;
AIO_ATTR_S aiAttr;
memset(&aiAttr, 0, sizeof(AIO_ATTR_S));
cardName = UacMpiUtil::getSndCardName(UAC_MPI_TYPE_AI, ctx->mode);
snprintf(reinterpret_cast<char *>(aiAttr.u8CardName),
sizeof(aiAttr.u8CardName), "%s", cardName);
aiAttr.soundCard.channels =
UacMpiUtil::getSndCardChannels(UAC_MPI_TYPE_AI, ctx->mode);
aiAttr.soundCard.sampleRate =
UacMpiUtil::getSndCardSampleRate(UAC_MPI_TYPE_AI, ctx->mode);
aiAttr.soundCard.bitWidth =
UacMpiUtil::getSndCardbitWidth(UAC_MPI_TYPE_AI, ctx->mode);
/*
* 1. if datas are sended from pc to uac device, the ai device is usb,
* we set the samplerate which uevent report.
* 2. if datas are sended from uac device to pc, the ai device is mic,
we use the a fix samplerate like 16000.
*/
if (ctx->mode == UAC_STREAM_PLAYBACK) {
if (OPEN_VQE) {
rate = (AUDIO_SAMPLE_RATE_E)UacMpiUtil::getVqeSampleRate();
} else {
rate = (AUDIO_SAMPLE_RATE_E)UacMpiUtil::getSndCardSampleRate(
UAC_MPI_TYPE_AI, ctx->mode);
}
} else {
rate = (AUDIO_SAMPLE_RATE_E)ctx->stream.config.samplerate;
// update samplerate of usb cards which coming from uevent
aiAttr.soundCard.sampleRate = rate;
}
aiAttr.enBitwidth = UacMpiUtil::getDataBitwidth(UAC_MPI_TYPE_AI, ctx->mode);
aiAttr.enSamplerate = rate;
aiAttr.enSoundmode = UacMpiUtil::getDataSoundmode(UAC_MPI_TYPE_AI, ctx->mode);
ALOGD("this:%p, startAi(dev:%d, chn:%d), enSamplerate : %d\n", this, aiDevId,
aiChn, aiAttr.enSamplerate);
aiAttr.u32FrmNum = 4;
aiAttr.u32PtNumPerFrm = 1024;
aiAttr.u32EXFlag = 0;
aiAttr.u32ChnCnt = 2;
result = RK_MPI_AI_SetPubAttr(aiDevId, &aiAttr);
if (result != 0) {
ALOGE("ai set attr(dev:%d) fail, reason = %x\n", aiDevId, result);
goto __FAILED;
}
result = RK_MPI_AI_Enable(aiDevId);
if (result != 0) {
ALOGE("ai enable(dev:%d) fail, reason = %x\n", aiDevId, result);
goto __FAILED;
}
result = RK_MPI_AI_EnableChn(aiDevId, aiChn);
if (result != 0) {
ALOGE("ai enable channel(dev:%d, chn:%d) fail, reason = %x\n", aiDevId,
aiChn, result);
return RK_FAILURE;
}
/*
* If 3A filter is after ai, and the samplerate of ai's datas is not support
* by 3A,
* enable resample to convert the samplerate.
*/
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
result = RK_MPI_AI_EnableReSmp(aiDevId, aiChn, aiAttr.enSamplerate);
if (result != 0) {
ALOGE("ai enable resample(dev:%d, chn:%d) fail, reason = %x\n", aiDevId,
aiChn, result);
return RK_FAILURE;
}
} else {
// disable resample in ai, this means the samplerate of output of ai is the
// samplerate of sound card
result = RK_MPI_AI_DisableReSmp(aiDevId, aiChn);
if (result != 0) {
ALOGE("ai disable resample(dev:%d, chn:%d) fail, reason = %x\n", aiDevId,
aiChn, result);
return RK_FAILURE;
}
}
return 0;
__FAILED:
return -1;
}
// init 3A filter
int UACControlMpi::startVqe() {
UacControlMpi *ctx = getContextMpi(mCtx);
AF_CHN vqeChnId = ctx->stream.idCfg.vqeChnId;
RK_S32 result;
AF_ATTR_S attr;
ALOGD("this:%p, startVqe(chn:%d), mode : %d\n", this, vqeChnId, ctx->mode);
memset(&attr, 0, sizeof(AF_ATTR_S));
attr.enType = AUDIO_FILTER_3A;
attr.u32InBufCount = 2;
attr.u32OutBufCount = 2;
snprintf(reinterpret_cast<char *>(attr.st3AAttr.cfgPath),
sizeof(attr.st3AAttr.cfgPath), "%s", UacMpiUtil::getVqeCfgPath());
attr.st3AAttr.u32SampleRate = UacMpiUtil::getVqeSampleRate();
attr.st3AAttr.enBitWidth = AUDIO_BIT_WIDTH_16;
attr.st3AAttr.u32Channels = UacMpiUtil::getVqeChannels();
attr.st3AAttr.u32ChnLayout = UacMpiUtil::getVqeChnLayout();
attr.st3AAttr.u32RecLayout = UacMpiUtil::getVqeMicLayout();
attr.st3AAttr.u32RefLayout = UacMpiUtil::getVqeRefLayout();
result = RK_MPI_AF_Create(vqeChnId, &attr);
if (result != RK_SUCCESS) {
ALOGE("create af vqe(chn:%d) fail, reason = %x\n", vqeChnId, result);
return RK_FAILURE;
}
return 0;
__FAILED:
return -1;
}
int UACControlMpi::startAo() {
UacControlMpi *ctx = getContextMpi(mCtx);
AUDIO_DEV aoDevId = ctx->stream.idCfg.aoDevId;
AO_CHN aoChn = ctx->stream.idCfg.aoChnId;
ALOGD("this:%p, startAo(dev:%d, chn:%d), mode : %d\n", this, aoDevId, aoChn,
ctx->mode);
const char *cardName = RK_NULL;
RK_S32 result;
AIO_ATTR_S aoAttr;
AUDIO_SAMPLE_RATE_E rate;
AUDIO_SOUND_MODE_E soundMode;
memset(&aoAttr, 0, sizeof(AIO_ATTR_S));
cardName = UacMpiUtil::getSndCardName(UAC_MPI_TYPE_AO, ctx->mode);
snprintf(reinterpret_cast<char *>(aoAttr.u8CardName),
sizeof(aoAttr.u8CardName), "%s", cardName);
/*
* 1. if datas is from pc to uac device, the ao device is spk,
we use the a fix samplerate like 48000.
* 2. if datas is from uac device to pc, the ao device is usb,
* we set the samplerate which uevent report.
*/
if (ctx->mode == UAC_STREAM_RECORD) {
rate = (AUDIO_SAMPLE_RATE_E)UacMpiUtil::getSndCardSampleRate(
UAC_MPI_TYPE_AO, ctx->mode);
} else {
rate = (AUDIO_SAMPLE_RATE_E)ctx->stream.config.samplerate;
}
aoAttr.soundCard.channels =
UacMpiUtil::getSndCardChannels(UAC_MPI_TYPE_AO, ctx->mode);
aoAttr.soundCard.sampleRate = rate;
aoAttr.soundCard.bitWidth =
UacMpiUtil::getSndCardbitWidth(UAC_MPI_TYPE_AO, ctx->mode);
aoAttr.enBitwidth = UacMpiUtil::getDataBitwidth(UAC_MPI_TYPE_AO, ctx->mode);
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
rate = (AUDIO_SAMPLE_RATE_E)UacMpiUtil::getVqeSampleRate();
}
aoAttr.enSamplerate = rate;
soundMode = UacMpiUtil::getDataSoundmode(UAC_MPI_TYPE_AO, ctx->mode);
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
soundMode = AUDIO_SOUND_MODE_MONO;
}
aoAttr.enSoundmode = soundMode;
ALOGD("this:%p, startAo(dev:%d, chn:%d), mode : %d, enSamplerate = %d\n",
this, aoDevId, aoChn, ctx->mode, aoAttr.enSamplerate);
aoAttr.u32FrmNum = 4;
aoAttr.u32PtNumPerFrm = 1024;
aoAttr.u32EXFlag = 0;
aoAttr.u32ChnCnt = 2;
result = RK_MPI_AO_SetPubAttr(aoDevId, &aoAttr);
if (result != 0) {
ALOGE("ao set attr(dev:%d) fail, reason = %x\n", aoDevId, result);
goto __FAILED;
}
result = RK_MPI_AO_Enable(aoDevId);
if (result != 0) {
ALOGE("ao enable(dev:%d) fail, reason = %x\n", aoDevId, result);
goto __FAILED;
}
result = RK_MPI_AO_EnableChn(aoDevId, aoChn);
if (result != 0) {
ALOGE("ao enable channel(dev:%d, chn:%d) fail, reason = %x\n", aoDevId,
aoChn, result);
return RK_FAILURE;
}
result = RK_MPI_AO_EnableReSmp(aoDevId, aoChn, aoAttr.enSamplerate);
if (result != 0) {
ALOGE("ao enable resample(dev:%d, chn:%d) fail, reason = %x\n", aoDevId,
aoChn, result);
return RK_FAILURE;
}
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
result = RK_MPI_AO_SetTrackMode(aoDevId, AUDIO_TRACK_OUT_STEREO);
if (result != 0) {
ALOGE("ao enable track mode(dev:%d, chn:%d) fail, reason = %x\n", aoDevId,
aoChn, result);
return RK_FAILURE;
}
}
return 0;
__FAILED:
return -1;
}
void UACControlMpi::streamBind() {
UacControlMpi *ctx = getContextMpi(mCtx);
MPP_CHN_S stSrcChn, stDstChn;
// have af, the data flow is ai-->af-->ao
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
// ai bind af, this means data from ai to af
stSrcChn.enModId = RK_ID_AI;
stSrcChn.s32DevId = ctx->stream.idCfg.aiDevId;
stSrcChn.s32ChnId = ctx->stream.idCfg.aiChnId;
stDstChn.enModId = RK_ID_AF;
stDstChn.s32DevId = 0;
stDstChn.s32ChnId = ctx->stream.idCfg.vqeChnId;
ALOGD("AiBindVqe(mode:%d) : src(%d,%d), dst(%d,%d)\n", ctx->mode,
stSrcChn.s32DevId, stSrcChn.s32ChnId, stDstChn.s32DevId,
stDstChn.s32ChnId);
RK_MPI_SYS_Bind(&stSrcChn, &stDstChn);
// af bind ao, this means data from af to ao
stSrcChn.enModId = RK_ID_AF;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = ctx->stream.idCfg.vqeChnId;
stDstChn.enModId = RK_ID_AO;
stDstChn.s32DevId = ctx->stream.idCfg.aoDevId;
stDstChn.s32ChnId = ctx->stream.idCfg.aoChnId;
ALOGD("VqeBindAo(mode:%d) : src(%d,%d), dst(%d,%d)\n", ctx->mode,
stSrcChn.s32DevId, stSrcChn.s32ChnId, stDstChn.s32DevId,
stDstChn.s32ChnId);
RK_MPI_SYS_Bind(&stSrcChn, &stDstChn);
} else {
// no af, the data flow is ai-->ao
stSrcChn.enModId = RK_ID_AI;
stSrcChn.s32DevId = ctx->stream.idCfg.aiDevId;
stSrcChn.s32ChnId = ctx->stream.idCfg.aiChnId;
stDstChn.enModId = RK_ID_AO;
stDstChn.s32DevId = ctx->stream.idCfg.aoDevId;
stDstChn.s32ChnId = ctx->stream.idCfg.aoChnId;
ALOGD("AiBindAO(mode:%d) : src(%d,%d), dst(%d,%d)\n", ctx->mode,
stSrcChn.s32DevId, stSrcChn.s32ChnId, stDstChn.s32DevId,
stDstChn.s32ChnId);
RK_MPI_SYS_Bind(&stSrcChn, &stDstChn);
}
}
int UACControlMpi::stopAi() {
UacControlMpi *ctx = getContextMpi(mCtx);
AUDIO_DEV aiDevId = ctx->stream.idCfg.aiDevId;
AI_CHN aiChn = ctx->stream.idCfg.aiChnId;
ALOGD("this:%p, stopAi(dev:%d, chn:%d), mode : %d\n", this, aiDevId, aiChn,
ctx->mode);
RK_MPI_AI_DisableReSmp(aiDevId, aiChn);
RK_S32 result = RK_MPI_AI_DisableChn(aiDevId, aiChn);
if (result != 0) {
ALOGE("ai disable channel(dev:%d, chn:%d) fail, reason = %x\n", aiDevId,
aiChn, result);
return RK_FAILURE;
}
result = RK_MPI_AI_Disable(aiDevId);
if (result != 0) {
ALOGE("ai disable(dev:%d) fail, reason = %x\n", aiDevId, result);
return RK_FAILURE;
}
return 0;
__FAILED:
return -1;
}
int UACControlMpi::stopVqe() {
UacControlMpi *ctx = getContextMpi(mCtx);
AF_CHN vqeChn = ctx->stream.idCfg.vqeChnId;
ALOGD("this:%p, stopVqe(chn:%d), mode : %d\n", this, vqeChn, ctx->mode);
RK_S32 result = RK_MPI_AF_Destroy(vqeChn);
if (result != 0) {
ALOGE("vqe disable(dev:%d) fail, reason = %x\n", vqeChn, result);
return RK_FAILURE;
}
return 0;
__FAILED:
return -1;
}
int UACControlMpi::stopAo() {
UacControlMpi *ctx = getContextMpi(mCtx);
AUDIO_DEV aoDevId = ctx->stream.idCfg.aoDevId;
AO_CHN aoChn = ctx->stream.idCfg.aoChnId;
ALOGD("this:%p, stopAo(dev:%d, chn:%d), mode : %d\n", this, aoDevId, aoChn,
ctx->mode);
RK_MPI_AO_DisableReSmp(aoDevId, aoChn);
RK_S32 result = RK_MPI_AO_DisableChn(aoDevId, aoChn);
if (result != 0) {
ALOGE("ao disable channel(dev:%d, chn:%d) fail, reason = %x\n", aoDevId,
aoChn, result);
return RK_FAILURE;
}
result = RK_MPI_AO_Disable(aoDevId);
if (result != 0) {
ALOGE("ao disable(dev:%d) fail, reason = %x\n", aoDevId, result);
return RK_FAILURE;
}
return 0;
__FAILED:
return -1;
}
void UACControlMpi::streamUnBind() {
UacControlMpi *ctx = getContextMpi(mCtx);
MPP_CHN_S stSrcChn, stDstChn;
if (OPEN_VQE && ctx->mode == UAC_STREAM_PLAYBACK) {
stSrcChn.enModId = RK_ID_AI;
stSrcChn.s32DevId = ctx->stream.idCfg.aiDevId;
stSrcChn.s32ChnId = ctx->stream.idCfg.aiChnId;
stDstChn.enModId = RK_ID_AF;
stDstChn.s32DevId = 0;
stDstChn.s32ChnId = ctx->stream.idCfg.vqeChnId;
ALOGD("AiUnBindVqe(mode:%d) : src(%d,%d), dst(%d,%d)\n", ctx->mode,
stSrcChn.s32DevId, stSrcChn.s32ChnId, stDstChn.s32DevId,
stDstChn.s32ChnId);
RK_MPI_SYS_UnBind(&stSrcChn, &stDstChn);
stSrcChn.enModId = RK_ID_AF;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = ctx->stream.idCfg.vqeChnId;
stDstChn.enModId = RK_ID_AO;
stDstChn.s32DevId = ctx->stream.idCfg.aoDevId;
stDstChn.s32ChnId = ctx->stream.idCfg.aoChnId;
ALOGD("VqeUnBindAo(mode:%d) : src(%d,%d), dst(%d,%d)\n", ctx->mode,
stSrcChn.s32DevId, stSrcChn.s32ChnId, stDstChn.s32DevId,
stDstChn.s32ChnId);
RK_MPI_SYS_UnBind(&stSrcChn, &stDstChn);
} else {
stSrcChn.enModId = RK_ID_AI;
stSrcChn.s32DevId = ctx->stream.idCfg.aiDevId;
stSrcChn.s32ChnId = ctx->stream.idCfg.aiChnId;
stDstChn.enModId = RK_ID_AO;
stDstChn.s32DevId = ctx->stream.idCfg.aoDevId;
stDstChn.s32ChnId = ctx->stream.idCfg.aoChnId;
ALOGD("AiUnBindAO(mode:%d) : src(%d,%d), dst(%d,%d)\n", ctx->mode,
stSrcChn.s32DevId, stSrcChn.s32ChnId, stDstChn.s32DevId,
stDstChn.s32ChnId);
RK_MPI_SYS_UnBind(&stSrcChn, &stDstChn);
}
}
//#endif

View File

@@ -0,0 +1,174 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
//#ifdef __cplusplus
#include "mpi_control_common.h"
#include "uac_amixer.h"
#include "uac_log.h"
#include "uac_log.h"
#ifdef LOG_TAG
#undef LOG_TAG
#define LOG_TAG "mpi_contol_comm"
#endif
typedef struct _MpiAioDeviceAttrConfigMap {
UacMpiType mpiType;
int uacMode;
const char *sndCardname;
RK_U32 sndCardChannels;
RK_U32 sndCardSampleRate;
AUDIO_BIT_WIDTH_E sndCardbitWidth;
RK_U32 dataSamplerate;
AUDIO_BIT_WIDTH_E dataBitwidth;
AUDIO_SOUND_MODE_E dataSoundmode;
} MpiAioDeviceAttrConfigMap;
const static MpiAioDeviceAttrConfigMap sAioDevAttrCfgs[] = {
// usb
{UAC_MPI_TYPE_AI, UAC_STREAM_RECORD, "hw:1,0", 2, 44100, AUDIO_BIT_WIDTH_16,
44100, AUDIO_BIT_WIDTH_16, AUDIO_SOUND_MODE_STEREO},
// mic
{UAC_MPI_TYPE_AI, UAC_STREAM_PLAYBACK, "hw:0,0", 2, 16000,
AUDIO_BIT_WIDTH_16, 16000, AUDIO_BIT_WIDTH_16, AUDIO_SOUND_MODE_STEREO},
// spk
{UAC_MPI_TYPE_AO, UAC_STREAM_RECORD, "hw:0,0", 2, 16000, AUDIO_BIT_WIDTH_16,
16000, AUDIO_BIT_WIDTH_16, AUDIO_SOUND_MODE_STEREO},
// usb
{UAC_MPI_TYPE_AO, UAC_STREAM_PLAYBACK, "hw:1,0", 2, 44100,
AUDIO_BIT_WIDTH_16, 44100, AUDIO_BIT_WIDTH_16, AUDIO_SOUND_MODE_STEREO},
};
const static char *sAfVqeCfgPath = "/oem/usr/share/uac_app/configs_skv.json";
#define VQE_SAMPLERATE 16000
RK_U32 UacMpiUtil::getSndCardSampleRate(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode,
sndCardSampleRate);
return 0;
}
const char *UacMpiUtil::getSndCardName(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode, sndCardname);
return NULL;
}
RK_U32 UacMpiUtil::getSndCardChannels(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode,
sndCardChannels);
return 0;
}
AUDIO_BIT_WIDTH_E UacMpiUtil::getSndCardbitWidth(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode,
sndCardbitWidth);
return AUDIO_BIT_WIDTH_BUTT;
}
RK_U32 UacMpiUtil::getDataSamplerate(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode,
dataSamplerate);
return 0;
}
AUDIO_BIT_WIDTH_E UacMpiUtil::getDataBitwidth(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode, dataBitwidth);
return AUDIO_BIT_WIDTH_BUTT;
}
AUDIO_SOUND_MODE_E UacMpiUtil::getDataSoundmode(UacMpiType type, int mode) {
GET_ENTRY_VALUE(type, mode, sAioDevAttrCfgs, mpiType, uacMode, dataSoundmode);
return AUDIO_SOUND_MODE_BUTT;
}
const char *UacMpiUtil::getVqeCfgPath() { return sAfVqeCfgPath; }
RK_U32 UacMpiUtil::getVqeSampleRate() { return VQE_SAMPLERATE; }
RK_U32 UacMpiUtil::getVqeChannels() {
return sChnAttrCfgs[sRefMode].u32Channels;
}
RK_U32 UacMpiUtil::getVqeChnLayout() {
RK_U32 layout =
sChnAttrCfgs[sRefMode].u32MicLayout + sChnAttrCfgs[sRefMode].u32RefLayout;
return layout;
}
RK_U32 UacMpiUtil::getVqeRefLayout() {
return sChnAttrCfgs[sRefMode].u32RefLayout;
}
RK_U32 UacMpiUtil::getVqeMicLayout() {
return sChnAttrCfgs[sRefMode].u32MicLayout;
}
void mpi_set_samplerate(int type, UacMpiStream &streamCfg) {
int sampleRate = streamCfg.config.samplerate;
if (sampleRate == 0)
return;
AUDIO_DEV aiDevId = streamCfg.idCfg.aiDevId;
AI_CHN aiChn = streamCfg.idCfg.aiChnId;
AUDIO_DEV aoDevId = streamCfg.idCfg.aoDevId;
AO_CHN aoChn = streamCfg.idCfg.aoChnId;
ALOGD("type = %d, sampleRate = %d\n", type, sampleRate);
/*
* 1. for usb capture, we update audio config to capture
* 2. for usb playback, if there is resample before usb playback,
* we set audio config to this resample, the new config will
* pass to usb playback from resample to usb playback when
* the datas move from resample to usb.
* 3. we alway use samperate=48K to open mic and speaker,
* because usually, they use the same group i2s, and
* not allowned to use diffrent samplerate.
*/
if (type == UAC_STREAM_RECORD) {
// the usb record always the first node
AI_CHN_ATTR_S params;
memset(&params, 0, sizeof(AI_CHN_ATTR_S));
params.u32SampleRate = sampleRate;
params.enChnAttr = AUDIO_CHN_ATTR_RATE;
RK_MPI_AI_SetChnAttr(aiDevId, aiChn, &params);
} else {
// find the resample before usb playback
AO_CHN_ATTR_S params;
memset(&params, 0, sizeof(AO_CHN_ATTR_S));
params.u32SampleRate = sampleRate;
params.enChnAttr = AUDIO_CHN_ATTR_RATE;
RK_MPI_AO_SetChnAttr(aoDevId, aoChn, &params);
}
}
void mpi_set_volume(int type, UacMpiStream &streamCfg) {
int mute = streamCfg.config.mute;
int volume = streamCfg.config.intVol;
AUDIO_DEV aoDevId = streamCfg.idCfg.aoDevId;
ALOGD("type = %d, mute = %d, volume = %d\n", type, mute, volume);
AUDIO_FADE_S aFade;
memset(&aFade, 0, sizeof(AUDIO_FADE_S));
RK_BOOL bMute = (mute == 0) ? RK_FALSE : RK_TRUE;
RK_MPI_AO_SetMute(aoDevId, bMute, &aFade);
RK_MPI_AO_SetVolume(aoDevId, volume);
}
void mpi_set_ppm(int type, UacMpiStream &streamCfg) {
int ppm = streamCfg.config.ppm;
amix_set_ppm(MIC_SPK_SOUNDCARD_INDEX, ppm);
}
//#endif

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "uac_amixer.h"
#include "rk_mpi_amix.h"
#include "uac_log.h"
#ifdef LOG_TAG
#undef LOG_TAG
#define LOG_TAG "amixer"
#endif
const static char *sRefCtrlName = "I2STDM Digital Loopback Mode";
const static char *sPpmCtrlName = "PCM Clk Compensation In PPM";
RK_S32 UACAmixer::set(AUDIO_DEV AmixDevId, const char *ctrlName,
const char *value) {
ALOGD("AmixDevId = %d, ctrl = %s, value = %s", AmixDevId, ctrlName, value);
return RK_MPI_AMIX_SetControl(AmixDevId, ctrlName, (char *)value);
}
RK_S32 UACAmixer::get(AUDIO_DEV AmixDevId, const char *ctrlName) {
return RK_MPI_AMIX_GetControl(AmixDevId, ctrlName, NULL);
}
void UACAmixer::dumpContents(AUDIO_DEV AmixDevId) {
RK_MPI_AMIX_ListContents(AmixDevId);
}
RK_S32 amix_set_ref_mode(AUDIO_DEV AoDevId) {
return UACAmixer::set(AoDevId, sRefCtrlName, sChnAttrCfgs[sRefMode].chMode);
}
RK_S32 amix_set_ppm(AUDIO_DEV AoDevId, RK_S32 ppm) {
char str[64];
snprintf(str, sizeof(str), "%d", ppm);
return UACAmixer::set(AoDevId, sPpmCtrlName, str);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
//#ifdef __cplusplus
#include "uac_common_def.h"
uint64_t getRelativeTimeMs() {
return getRelativeTimeUs() / 1000; /* milliseconds */
}
uint64_t getRelativeTimeUs() {
struct timespec time = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &time);
return (uint64_t)time.tv_sec * 1000000LL +
(uint64_t)time.tv_nsec / 1000; /* microseconds */
}
//#endif

View File

@@ -0,0 +1,147 @@
/*
* Copyright 2020 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
//#ifdef __cplusplus
#include "uac_control.h"
#include "uac_control_factory.h"
#include "uac_log.h"
#ifdef UAC_MPI
#include "mpi_control_common.h"
#endif
int uac_app_log_level;
typedef struct _UacControls {
int mode;
UACControl *uac;
pthread_mutex_t mutex;
} UacControls;
static UacControls *gUAControl = NULL;
int uac_control_create(int type) {
int i = 0;
char *ch = NULL;
if (type == UAC_API_GRAPH) {
ch = (char *)"graph";
} else if (type == UAC_API_MPI) {
ch = (char *)"mpi";
}
ALOGD("-------------uac use %s--------------\n", ch);
if (!gUAControl) {
uac_control_destory();
}
gUAControl = (UacControls *)calloc(UAC_STREAM_MAX, sizeof(UacControls));
if (!gUAControl) {
ALOGE("fail to malloc memory!\n");
return -1;
}
memset(gUAControl, 0, sizeof(UacControls));
for (i = 0; i < UAC_STREAM_MAX; i++) {
gUAControl[i].mode = i;
pthread_mutex_init(&gUAControl[i].mutex, NULL);
gUAControl[i].uac = UacControlFactory::create((UacApiType)type, i);
if (!gUAControl[i].uac) {
uac_control_destory();
return -1;
}
}
return 0;
}
void uac_control_destory() {
if (gUAControl == NULL)
return;
int i = 0;
UACControl *uac = NULL;
if (gUAControl) {
for (i = 0; i < UAC_STREAM_MAX; i++) {
uac = gUAControl[i].uac;
if (uac)
delete uac;
gUAControl[i].uac = NULL;
pthread_mutex_destroy(&gUAControl[i].mutex);
}
}
free(gUAControl);
gUAControl = NULL;
}
UacControls *getControlContext(int mode) { return &gUAControl[mode]; }
int uac_start(int mode) {
int ret = 0;
UacControls *uacs = getControlContext(mode);
pthread_mutex_lock(&uacs->mutex);
if (mode == uacs->mode) {
ret = uacs->uac->uacStart();
}
pthread_mutex_unlock(&uacs->mutex);
return ret;
}
void uac_stop(int mode) {
UacControls *uacs = getControlContext(mode);
pthread_mutex_lock(&uacs->mutex);
if (mode == uacs->mode) {
uacs->uac->uacStop();
}
pthread_mutex_unlock(&uacs->mutex);
}
void uac_set_sample_rate(int mode, int samplerate) {
UacControls *uacs = getControlContext(mode);
pthread_mutex_lock(&uacs->mutex);
if (mode == uacs->mode) {
uacs->uac->uacSetSampleRate(samplerate);
}
pthread_mutex_unlock(&uacs->mutex);
}
void uac_set_volume(int mode, int volume) {
UacControls *uacs = getControlContext(mode);
pthread_mutex_lock(&uacs->mutex);
if (mode == uacs->mode) {
uacs->uac->uacSetVolume(volume);
}
pthread_mutex_unlock(&uacs->mutex);
}
void uac_set_mute(int mode, int mute) {
UacControls *uacs = getControlContext(mode);
pthread_mutex_lock(&uacs->mutex);
if (mode == uacs->mode) {
uacs->uac->uacSetMute(mute);
}
pthread_mutex_unlock(&uacs->mutex);
}
void uac_set_ppm(int mode, int ppm) {
UacControls *uacs = getControlContext(mode);
pthread_mutex_lock(&uacs->mutex);
if (mode == uacs->mode) {
uacs->uac->uacSetPpm(ppm);
}
pthread_mutex_unlock(&uacs->mutex);
}
//#endif

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2022 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
//#ifdef __cplusplus
#include "uac_control_factory.h"
#include "uac_control_graph.h"
#include "uac_control_mpi.h"
#include "uac_log.h"
UACControl *createUacGraph(int mode) {
UACControl *uac = NULL;
#ifdef UAC_GRAPH
uac = new UACControlGraph(mode);
#endif
return uac;
}
UACControl *createUacMpi(int mode) {
UACControl *uac = NULL;
#ifdef UAC_MPI
uac = new UACControlMpi(mode);
#endif
return uac;
}
UACControl *UacControlFactory::create(UacApiType type, int mode) {
UACControl *uac = NULL;
switch (type) {
case UAC_API_MPI:
uac = createUacMpi(mode);
break;
case UAC_API_GRAPH:
uac = createUacGraph(mode);
break;
default:
ALOGD("unkown UacApiType(%d), please check!\n", type);
break;
}
return uac;
}
//#endif

View File

@@ -0,0 +1,427 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
//#ifdef __cplusplus
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include "uac_control.h"
#include "uac_log.h"
#include "uac_uevent.h"
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/time.h>
#ifdef LOG_TAG
#undef LOG_TAG
#define LOG_TAG "audio_event"
#endif
/*
* case 1:
* the UAC1 uevent when pc/remote close(play sound of usb close)
*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0 // UAC2_Gadget
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_INTERFACE
* strs[4] = STREAM_DIRECTION=OUT
* strs[5] = STREAM_STATE=OFF
*
*
* case 2:
* the UAC1 uevent when pc/remote play start(play sound of usb open)
*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_INTERFACE
* strs[4] = STREAM_DIRECTION=OUT
* strs[5] = STREAM_STATE=ON
*
*
* case 3:
* the UAC1 uevent when pc/remote capture start(record sound of usb open)
*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_INTERFACE
* strs[4] = STREAM_DIRECTION=IN
* strs[5] = STREAM_STATE=ON
*
*
* case 4:
* the UAC1 uevent when pc/remote capture stop(record sound of usb open)
*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_INTERFACE
* strs[4] = STREAM_DIRECTION=IN
* strs[5] = STREAM_STATE=OFF
*
*
* case 5:
* the UAC1 uevent
*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_SAMPLE_RATE
* strs[4] = STREAM_DIRECTION=IN
* strs[5] = SAMPLE_RATE=48000
*/
#define UAC_UEVENT_AUDIO "SUBSYSTEM=u_audio"
#define UAC_UEVENT_SET_INTERFACE "USB_STATE=SET_INTERFACE"
#define UAC_UEVENT_SET_SAMPLE_RATE "USB_STATE=SET_SAMPLE_RATE"
#define UAC_UEVENT_SET_VOLUME "USB_STATE=SET_VOLUME"
#define UAC_UEVENT_SET_MUTE "USB_STATE=SET_MUTE"
#define UAC_UEVENT_SET_AUDIO_CLK "USB_STATE=SET_AUDIO_CLK"
#define UAC_STREAM_DIRECT "STREAM_DIRECTION="
#define UAC_STREAM_STATE "STREAM_STATE="
#define UAC_SAMPLE_RATE "SAMPLE_RATE="
#define UAC_SET_VOLUME "VOLUME="
#define UAC_SET_MUTE "MUTE="
#define UAC_PPM "PPM="
// remote device/pc->our device
#define UAC_REMOTE_PLAY "OUT"
// our device->remote device/pc
#define UAC_REMOTE_CAPTURE "IN"
// sound card is opened
#define UAC_STREAM_START "ON"
// sound card is closed
#define UAC_STREAM_STOP "OFF"
enum UAC_UEVENT_KEY {
UAC_KEY_AUDIO = 2,
UAC_KEY_USB_STATE = 3,
UAC_KEY_DIRECTION = 4,
UAC_KEY_PPM = 4,
UAC_KEY_STREAM_STATE = 5,
UAC_KEY_SAMPLE_RATE = UAC_KEY_STREAM_STATE,
UAC_KEY_VOLUME = UAC_KEY_STREAM_STATE,
UAC_KEY_MUTE = UAC_KEY_STREAM_STATE,
};
bool compare(const char *dst, const char *srt) {
if ((dst == NULL) || (srt == NULL))
return false;
if (!strncmp(dst, srt, strlen(srt))) {
return true;
}
return false;
}
void audio_play(const struct _uevent *uevent) {
char *direct = uevent->strs[UAC_KEY_DIRECTION];
char *status = uevent->strs[UAC_KEY_STREAM_STATE];
if (compare(direct, UAC_STREAM_DIRECT) && compare(status, UAC_STREAM_STATE)) {
char *device = &direct[strlen(UAC_STREAM_DIRECT)];
char *state = &status[strlen(UAC_STREAM_STATE)];
// remote device/pc open/close usb sound card to write data
if (compare(device, UAC_REMOTE_PLAY)) {
if (compare(UAC_STREAM_START, state)) {
// stream start, we need to open usb card to record datas
ALOGD("remote device/pc start to play data to us, we need to open usb "
"to capture datas\n");
uac_start(UAC_STREAM_RECORD);
} else if (compare(UAC_STREAM_STOP, state)) {
ALOGD("remote device/pc stop to play data to us, we need to stop "
"capture datas\n");
uac_stop(UAC_STREAM_RECORD);
}
} else if (compare(device, UAC_REMOTE_CAPTURE)) {
// our device->remote device/pc
if (compare(UAC_STREAM_START, state)) {
// stream start, we need to open usb card to record datas
ALOGD("remote device/pc start to record from us, we need to open usb "
"to send datas\n");
uac_start(UAC_STREAM_PLAYBACK);
} else if (compare(UAC_STREAM_STOP, state)) {
ALOGD("remote device/pc stop to record from us, we need to stop write "
"datas to usb\n");
uac_stop(UAC_STREAM_PLAYBACK);
}
}
}
}
void audio_set_samplerate(const struct _uevent *uevent) {
char *direct = uevent->strs[UAC_KEY_DIRECTION];
char *samplerate = uevent->strs[UAC_KEY_SAMPLE_RATE];
ALOGD("%s: %s\n", __FUNCTION__, direct);
ALOGD("%s: %s\n", __FUNCTION__, samplerate);
if (compare(direct, UAC_STREAM_DIRECT)) {
char *device = &direct[strlen(UAC_STREAM_DIRECT)];
char *rate = &samplerate[strlen(UAC_SAMPLE_RATE)];
int sampleRate = atoi(rate);
if (compare(device, UAC_REMOTE_PLAY)) {
ALOGD("set samplerate %d to usb record\n", sampleRate);
uac_set_sample_rate(UAC_STREAM_RECORD, sampleRate);
} else if (compare(device, UAC_REMOTE_CAPTURE)) {
ALOGD("set samplerate %d to usb playback\n", sampleRate);
uac_set_sample_rate(UAC_STREAM_PLAYBACK, sampleRate);
}
}
}
/*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devicges/virtual/u_audio/UAC1_Gadgeta 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_VOLUME
* strs[4] = STREAM_DIRECTION=OUT
* strs[5] = VOLUME=0x7FFF
* index db
* 0x7FFF: 127.9961
* ......
* 0x0100: 1.0000
* ......
* 0x0002: 0.0078
* 0x0001: 0.0039
* 0x0000: 0.0000
* 0xFFFF: -0.0039
* 0xFFFE: -0.0078
* ......
* 0xFE00: -1.0000
* ......
* 0x8002: -127.9922
* 0x8001: -127.9961
*
*/
void audio_set_volume(const struct _uevent *uevent) {
char *direct = uevent->strs[UAC_KEY_DIRECTION];
char *volumeStr = uevent->strs[UAC_KEY_VOLUME];
int unit = 0x100;
ALOGD("direct = %s volume = %s\n", direct, volumeStr);
if (compare(direct, UAC_STREAM_DIRECT)) {
char *device = &direct[strlen(UAC_STREAM_DIRECT)];
short volume = 0;
float db = 0;
sscanf(volumeStr, "VOLUME=0x%x", &volume);
db = volume / (float)unit;
double precent = pow(10, db / 10);
int precentInt = (int)(precent * 100);
ALOGD("set db = %f, precent = %lf, precentInt = %d\n", db, precent,
precentInt);
if (compare(device, UAC_REMOTE_PLAY)) {
ALOGD("set volume %d to usb record\n", precentInt);
uac_set_volume(UAC_STREAM_RECORD, precentInt);
} else if (compare(device, UAC_REMOTE_CAPTURE)) {
ALOGD("set volume %d to usb playback\n", precentInt);
uac_set_volume(UAC_STREAM_PLAYBACK, precentInt);
}
}
}
/*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_MUTE
* strs[4] = STREAM_DIRECTION=OUT
* strs[5] = MUTE=1
*/
void audio_set_mute(const struct _uevent *uevent) {
char *direct = uevent->strs[UAC_KEY_DIRECTION];
char *muteStr = uevent->strs[UAC_KEY_MUTE];
ALOGD("direct = %s mute = %s\n", direct, muteStr);
if (compare(direct, UAC_STREAM_DIRECT)) {
char *device = &direct[strlen(UAC_STREAM_DIRECT)];
int mute = 0;
sscanf(muteStr, "MUTE=%d", &mute);
if (compare(device, UAC_REMOTE_PLAY)) {
ALOGD("set mute = %d to usb record\n", mute);
uac_set_mute(UAC_STREAM_RECORD, mute);
} else if (compare(device, UAC_REMOTE_CAPTURE)) {
ALOGD("set mute = %d to usb playback\n", mute);
uac_set_mute(UAC_STREAM_PLAYBACK, mute);
}
}
}
/*
* strs[0] = ACTION=change
* strs[1] = DEVPATH=/devices/virtual/u_audio/UAC1_Gadget 0
* strs[2] = SUBSYSTEM=u_audio
* strs[3] = USB_STATE=SET_AUDIO_CLK
* strs[4] = PPM=-21
* strs[5] = SEQNUM=1573
*/
void audio_set_ppm(const struct _uevent *uevent) {
char *ppmStr = uevent->strs[UAC_KEY_PPM];
if (compare(ppmStr, UAC_PPM)) {
int ppm = 0;
sscanf(ppmStr, "PPM=%d", &ppm);
uac_set_ppm(UAC_STREAM_RECORD, ppm);
uac_set_ppm(UAC_STREAM_PLAYBACK, ppm);
}
}
void audio_event(const struct _uevent *uevent) {
char *event = uevent->strs[UAC_KEY_USB_STATE];
char *direct = uevent->strs[UAC_KEY_DIRECTION];
char *status = uevent->strs[UAC_KEY_STREAM_STATE];
ALOGD("event = %s\n", event);
ALOGD("direct = %s\n", direct);
ALOGD("status = %s\n", status);
if ((event == NULL) || (direct == NULL) || (status == NULL)) {
return;
}
bool setInterface = compare(event, UAC_UEVENT_SET_INTERFACE);
bool setSampleRate = compare(event, UAC_UEVENT_SET_SAMPLE_RATE);
bool setVolume = compare(event, UAC_UEVENT_SET_VOLUME);
bool setMute = compare(event, UAC_UEVENT_SET_MUTE);
bool setClk = compare(event, UAC_UEVENT_SET_AUDIO_CLK);
if (!setInterface && !setSampleRate && !setVolume && !setMute && !setClk) {
return;
}
if (setInterface) {
ALOGD("uevent---------------audio_play\n");
audio_play(uevent);
} else if (setSampleRate) {
ALOGD("uevent---------------audio_set_samplerate\n");
audio_set_samplerate(uevent);
} else if (setVolume) {
ALOGD("uevent---------------setVolume\n");
audio_set_volume(uevent);
} else if (setMute) {
ALOGD("uevent---------------setMute\n");
audio_set_mute(uevent);
} else if (setClk) {
ALOGD("uevent---------------setClk\n");
audio_set_ppm(uevent);
}
}
static void parse_event(const struct _uevent *event) {
if (event->size <= 0)
return;
#if 0
for (int i = 0 ; i < 10; i++) {
if (event->strs[i] != NULL) {
ALOGD("strs[%d] = %s\n", i, event->strs[i]);
}
}
#endif
if (compare(event->strs[UAC_KEY_AUDIO], UAC_UEVENT_AUDIO)) {
audio_event(event);
}
}
static void *uac_event_monitor_thread(void *arg) {
int sockfd;
int i, j, len;
char buf[512];
struct iovec iov;
struct msghdr msg;
struct sockaddr_nl sa;
struct _uevent event;
// uint32_t flags = *(uint32_t *)arg;
prctl(PR_SET_NAME, "event_monitor", 0, 0, 0);
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = NETLINK_KOBJECT_UEVENT;
sa.nl_pid = 0;
memset(&msg, 0, sizeof(msg));
iov.iov_base = (void *)buf;
iov.iov_len = sizeof(buf);
msg.msg_name = (void *)&sa;
msg.msg_namelen = sizeof(sa);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (sockfd == -1) {
ALOGE("socket creating failed:%s\n", strerror(errno));
goto err_event_monitor;
}
if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
ALOGE("bind error:%s\n", strerror(errno));
goto err_event_monitor;
}
while (1) {
event.size = 0;
len = recvmsg(sockfd, &msg, 0);
if (len < 0) {
ALOGD("receive error\n");
} else if (len < 32 || len > sizeof(buf)) {
ALOGD("invalid message");
} else {
for (i = 0, j = 0; i < len; i++) {
if (*(buf + i) == '\0' && (i + 1) != len) {
event.strs[j++] = buf + i + 1;
event.size = j;
}
}
}
parse_event(&event);
}
err_event_monitor:
pthread_detach(pthread_self());
pthread_exit(NULL);
}
int uac_uevent_monitor_run() {
pthread_t tid;
return pthread_create(&tid, NULL, uac_event_monitor_thread, NULL);
}
//#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,61 @@
##PROJECT(uac)
include_directories(uac/src)
include_directories(uac/src/include)
option(UAC_GRAPH "uac open graph" OFF)
option(UAC_MPI "uac open mpi" ON)
if (${UAC_GRAPH})
add_definitions(-DUAC_GRAPH)
set(SOURCE_FILES_GRAPH
${CMAKE_CURRENT_LIST_DIR}/src/graph/graph_control.cpp
${CMAKE_CURRENT_LIST_DIR}/src/graph/uac_control_graph.cpp
)
message(STATUS "Build With Rockit Graph")
else()
message(STATUS "Build None Rockit Graph")
endif()
if (${UAC_MPI})
add_definitions(-DUAC_MPI)
set(SOURCE_FILES_MPI
${CMAKE_CURRENT_LIST_DIR}/src/mpi/uac_control_mpi.cpp
${CMAKE_CURRENT_LIST_DIR}/src/mpi_common/uac_amixer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/mpi_common/mpi_control_common.cpp
)
message(STATUS "Build With Rockit Mpi")
else()
message(STATUS "Build None Rockit Mpi")
endif()
set(UAC_SOURCE
${CMAKE_CURRENT_LIST_DIR}/src/uac_uevent.cpp
${CMAKE_CURRENT_LIST_DIR}/src/uac_control.cpp
${CMAKE_CURRENT_LIST_DIR}/src/uac_common_def.cpp
${CMAKE_CURRENT_LIST_DIR}/src/uac_control_factory.cpp
${SOURCE_FILES_GRAPH}
${SOURCE_FILES_MPI}
)
#set(UAC_DEPENDENT_LIBS
# pthread
# rockit
#)
#set(UAC_AUDIO_ALGORITHM
# ${CMAKE_CURRENT_LIST_DIR}/libs/libaec_bf_process.so)
#install(FILES ${UAC_AUDIO_ALGORITHM} DESTINATION lib)
#ADD_EXECUTABLE(uac_app ${UAC_SOURCE})
#target_link_libraries(uac_app ${UAC_APP_DEPENDENT_LIBS})
install(DIRECTORY ./uac DESTINATION include
FILES_MATCHING PATTERN "*.h")
option(ENABLE_DEMO_BOARD "use demo board conf" OFF)
if (${ENABLE_DEMO_BOARD})
install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/configs/demo/ DESTINATION share/uac_app FILES_MATCHING PATTERN "*.json")
else()
install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/configs/ DESTINATION share/uac_app FILES_MATCHING PATTERN "configs_skv.json")
endif()

View File

@@ -0,0 +1,406 @@
#!/bin/sh
# UVC_MULTI_OPTIONS: Defines the options for UVC_MULTI variable.
# Available options: off (close), one (Expand a device), two (Expand two devices)
UVC_MULTI=one
CDC_ENABLE=NO
USB_FUNCTIONS_DIR=/sys/kernel/config/usb_gadget/rockchip/functions
USB_CONFIGS_DIR=/sys/kernel/config/usb_gadget/rockchip/configs/b.1
configure_uvc_resolution_yuyv()
{
UVC_DISPLAY_W=$1
UVC_DISPLAY_H=$2
UVC_DISPLAY_DIR=${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/uncompressed/u/${UVC_DISPLAY_W}_${UVC_DISPLAY_H}p
mkdir ${UVC_DISPLAY_DIR}
echo $UVC_DISPLAY_W > ${UVC_DISPLAY_DIR}/wWidth
echo $UVC_DISPLAY_H > ${UVC_DISPLAY_DIR}/wHeight
echo 333333 > ${UVC_DISPLAY_DIR}/dwDefaultFrameInterval
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMinBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMaxBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*2)) > ${UVC_DISPLAY_DIR}/dwMaxVideoFrameBufferSize
echo -e "333333\n666666\n1000000\n2000000" > ${UVC_DISPLAY_DIR}/dwFrameInterval
}
configure_uvc_resolution_yuyv_720p()
{
UVC_DISPLAY_W=$1
UVC_DISPLAY_H=$2
UVC_DISPLAY_DIR=${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/uncompressed/u/${UVC_DISPLAY_W}_${UVC_DISPLAY_H}p
mkdir ${UVC_DISPLAY_DIR}
echo $UVC_DISPLAY_W > ${UVC_DISPLAY_DIR}/wWidth
echo $UVC_DISPLAY_H > ${UVC_DISPLAY_DIR}/wHeight
echo 1000000 > ${UVC_DISPLAY_DIR}/dwDefaultFrameInterval
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMinBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMaxBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*2)) > ${UVC_DISPLAY_DIR}/dwMaxVideoFrameBufferSize
echo -e "1000000\n2000000" > ${UVC_DISPLAY_DIR}/dwFrameInterval
}
configure_uvc_resolution_yuyv_1080p()
{
UVC_DISPLAY_W=$1
UVC_DISPLAY_H=$2
UVC_DISPLAY_DIR=${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/uncompressed/u/${UVC_DISPLAY_W}_${UVC_DISPLAY_H}p
mkdir ${UVC_DISPLAY_DIR}
echo $UVC_DISPLAY_W > ${UVC_DISPLAY_DIR}/wWidth
echo $UVC_DISPLAY_H > ${UVC_DISPLAY_DIR}/wHeight
echo 2500000 > ${UVC_DISPLAY_DIR}/dwDefaultFrameInterval
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMinBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMaxBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*2)) > ${UVC_DISPLAY_DIR}/dwMaxVideoFrameBufferSize
echo -e "2500000\n5000000" > ${UVC_DISPLAY_DIR}/dwFrameInterval
}
configure_uvc_resolution_mjpeg()
{
UVC_DISPLAY_W=$1
UVC_DISPLAY_H=$2
UVC_DISPLAY_DIR=${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/mjpeg/m/${UVC_DISPLAY_W}_${UVC_DISPLAY_H}p
mkdir ${UVC_DISPLAY_DIR}
echo $UVC_DISPLAY_W > ${UVC_DISPLAY_DIR}/wWidth
echo $UVC_DISPLAY_H > ${UVC_DISPLAY_DIR}/wHeight
echo 333333 > ${UVC_DISPLAY_DIR}/dwDefaultFrameInterval
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMinBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*20)) > ${UVC_DISPLAY_DIR}/dwMaxBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*2)) > ${UVC_DISPLAY_DIR}/dwMaxVideoFrameBufferSize
echo -e "333333\n666666\n1000000\n2000000" > ${UVC_DISPLAY_DIR}/dwFrameInterval
}
configure_uvc_resolution_h264()
{
UVC_DISPLAY_W=$1
UVC_DISPLAY_H=$2
UVC_DISPLAY_DIR=${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f1/${UVC_DISPLAY_W}_${UVC_DISPLAY_H}p
mkdir ${UVC_DISPLAY_DIR}
echo $UVC_DISPLAY_W > ${UVC_DISPLAY_DIR}/wWidth
echo $UVC_DISPLAY_H > ${UVC_DISPLAY_DIR}/wHeight
echo 333333 > ${UVC_DISPLAY_DIR}/dwDefaultFrameInterval
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*10)) > ${UVC_DISPLAY_DIR}/dwMinBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*10)) > ${UVC_DISPLAY_DIR}/dwMaxBitRate
echo -e "333333\n400000\n500000\n666666\n1000000\n2000000" > ${UVC_DISPLAY_DIR}/dwFrameInterval
echo -ne \\x48\\x32\\x36\\x34\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f1/guidFormat
}
configure_uvc_resolution_h265()
{
UVC_DISPLAY_W=$1
UVC_DISPLAY_H=$2
UVC_DISPLAY_DIR=${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f2/${UVC_DISPLAY_W}_${UVC_DISPLAY_H}p
mkdir ${UVC_DISPLAY_DIR}
echo $UVC_DISPLAY_W > ${UVC_DISPLAY_DIR}/wWidth
echo $UVC_DISPLAY_H > ${UVC_DISPLAY_DIR}/wHeight
echo 333333 > ${UVC_DISPLAY_DIR}/dwDefaultFrameInterval
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*10)) > ${UVC_DISPLAY_DIR}/dwMinBitRate
echo $((UVC_DISPLAY_W*UVC_DISPLAY_H*10)) > ${UVC_DISPLAY_DIR}/dwMaxBitRate
echo -e "333333\n400000\n500000\n666666" > ${UVC_DISPLAY_DIR}/dwFrameInterval
echo -ne \\x48\\x32\\x36\\x35\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f2/guidFormat
}
cdc_device_config()
{
mkdir ${USB_FUNCTIONS_DIR}/acm.g0
CONFIG_STR=`cat /sys/kernel/config/usb_gadget/rockchip/configs/b.1/strings/0x409/configuration`
STR=${CONFIG_STR}_acm
echo $STR > ${USB_CONFIGS_DIR}/strings/0x409/configuration
USB_CNT=`echo $STR | awk -F"_" '{print NF-1}'`
let USB_CNT=USB_CNT+2
if [ $UVC_MULTI = one ];then
let USB_CNT=USB_CNT+1
elif [ $UVC_MULTI = two ];then
let USB_CNT=USB_CNT+2
fi
echo "acm on++++++ ${USB_CNT}"
ln -s ${USB_FUNCTIONS_DIR}/acm.g0 ${USB_CONFIGS_DIR}/f${USB_CNT}
}
uvc_device_config()
{
UVC_GS=$1
UVC_NAME=$2
mkdir ${USB_FUNCTIONS_DIR}/$UVC_GS
echo $UVC_NAME > ${USB_FUNCTIONS_DIR}/$UVC_GS/device_name
echo $UVC_NAME > ${USB_FUNCTIONS_DIR}/$UVC_GS/function_name
if [ $UVC_MULTI = one ];then
echo 2048 > ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming_maxpacket
elif [ $UVC_MULTI = two ];then
echo 1024 > ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming_maxpacket
else
echo 3072 > ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming_maxpacket
fi
echo 2 > ${USB_FUNCTIONS_DIR}/$UVC_GS/uvc_num_request
#echo 1 > /sys/kernel/config/usb_gadget/rockchip/functions/$UVC_GS/streaming_bulk
mkdir ${USB_FUNCTIONS_DIR}/$UVC_GS/control/header/h
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/control/header/h ${USB_FUNCTIONS_DIR}/$UVC_GS/control/class/fs/h
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/control/header/h ${USB_FUNCTIONS_DIR}/$UVC_GS/control/class/ss/h
##YUYV support config
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/$UVC_GS/streaming/uncompressed/u
configure_uvc_resolution_yuyv 320 240
configure_uvc_resolution_yuyv 640 480
configure_uvc_resolution_yuyv_720p 1280 720
#configure_uvc_resolution_yuyv_1080p 1920 1080
##mjpeg support config
mkdir ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/mjpeg/m
configure_uvc_resolution_mjpeg 320 240
configure_uvc_resolution_mjpeg 640 360
configure_uvc_resolution_mjpeg 640 480
configure_uvc_resolution_mjpeg 768 448
configure_uvc_resolution_mjpeg 1280 720
configure_uvc_resolution_mjpeg 1024 768
configure_uvc_resolution_mjpeg 1920 1080
configure_uvc_resolution_mjpeg 2048 1536
# configure_uvc_resolution_mjpeg 2560 1440
## h.264 support config
mkdir ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f1
configure_uvc_resolution_h264 640 480
configure_uvc_resolution_h264 1280 720
configure_uvc_resolution_h264 1920 1080
configure_uvc_resolution_h264 2048 1536
# configure_uvc_resolution_h264 2560 1440
## h.265 support config
mkdir ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f2
configure_uvc_resolution_h265 640 480
configure_uvc_resolution_h265 1280 720
configure_uvc_resolution_h265 1920 1080
configure_uvc_resolution_h265 2048 1536
#configure_uvc_resolution_h265 2560 1440
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/$UVC_GS/streaming/header/h
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/uncompressed/u ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h/u
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/mjpeg/m ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h/m
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f1 ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h/f1
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/framebased/f2 ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h/f2
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/class/fs/h
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/class/hs/h
ln -s ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/header/h ${USB_FUNCTIONS_DIR}/$UVC_GS/streaming/class/ss/h
}
uac1_device_config()
{
UAC=$1
mkdir ${USB_FUNCTIONS_DIR}/${UAC}.gs0
UAC_GS0=${USB_FUNCTIONS_DIR}/${UAC}.gs0
echo 3 > ${UAC_GS0}/p_chmask
echo 2 > ${UAC_GS0}/p_ssize
echo 1 > ${UAC_GS0}/p_mute_present
echo 1 > ${UAC_GS0}/p_volume_present
echo -5120 > ${UAC_GS0}/p_volume_min #-20db min must > -96db
echo 8000,16000,44100,48000 > ${UAC_GS0}/p_srate
echo 3 > ${UAC_GS0}/c_chmask
echo 2 > ${UAC_GS0}/c_ssize
echo 4 > ${UAC_GS0}/req_number
echo 1 > ${UAC_GS0}/c_mute_present
echo 1 > ${UAC_GS0}/c_volume_present
echo -3200 > ${UAC_GS0}/c_volume_min #-12.5db
echo 0 > ${UAC_GS0}/c_volume_max #0db
echo 32 > ${UAC_GS0}/c_volume_res #0.125db
echo 8000,16000,44100,48000 > ${UAC_GS0}/c_srate
if [ $UVC_MULTI = one ];then
ln -s ${UAC_GS0} ${USB_CONFIGS_DIR}/f3
elif [ $UVC_MULTI = two ];then
ln -s ${UAC_GS0} ${USB_CONFIGS_DIR}/f4
else
ln -s ${UAC_GS0} ${USB_CONFIGS_DIR}/f2
fi
}
uac2_device_config()
{
UAC=$1
mkdir ${USB_FUNCTIONS_DIR}/${UAC}.gs0
UAC_GS0=${USB_FUNCTIONS_DIR}/${UAC}.gs0
echo 3 > ${UAC_GS0}/p_chmask
echo 2 > ${UAC_GS0}/p_ssize
echo 1 > ${UAC_GS0}/p_mute_present
echo 1 > ${UAC_GS0}/p_volume_present
echo -5120 > ${UAC_GS0}/p_volume_min #-20db min must > -96db
echo 8000,16000,44100,48000 > ${UAC_GS0}/p_srate
echo 3 > ${UAC_GS0}/c_chmask
echo 2 > ${UAC_GS0}/c_ssize
echo 4 > ${UAC_GS0}/req_number
echo 1 > ${UAC_GS0}/c_mute_present
echo 1 > ${UAC_GS0}/c_volume_present
echo -3200 > ${UAC_GS0}/c_volume_min #-12.5db
echo 0 > ${UAC_GS0}/c_volume_max #0db
echo 32 > ${UAC_GS0}/c_volume_res #0.125db
echo 8000,16000,44100,48000 > ${UAC_GS0}/c_srate
if [ $UVC_MULTI = one ];then
ln -s ${UAC_GS0} ${USB_CONFIGS_DIR}/f3
elif [ $UVC_MULTI = two ];then
ln -s ${UAC_GS0} ${USB_CONFIGS_DIR}/f4
else
ln -s ${UAC_GS0} ${USB_CONFIGS_DIR}/f2
fi
}
pre_run_rndis()
{
RNDIS_STR="rndis"
if ( echo $1 |grep -q "rndis" ); then
#sleep 1
IP_FILE=/data/uvc_xu_ip_save
echo "config usb0 IP..."
if [ -f $IP_FILE ]; then
for line in `cat $IP_FILE`
do
echo "save ip is: $line"
ifconfig usb0 $line
done
else
ifconfig usb0 172.16.110.6
fi
ifconfig usb0 up
fi
}
insmod /oem/usr/ko/usb-common.ko
insmod /oem/usr/ko/usbcore.ko
insmod /oem/usr/ko/udc-core.ko
insmod /oem/usr/ko/libcomposite.ko
insmod /oem/usr/ko/usb_f_fs.ko
#UAC
insmod /oem/usr/ko/u_audio.ko
insmod /oem/usr/ko/usb_f_uac2.ko
insmod /oem/usr/ko/usb_f_uac1.ko
#UVC
insmod /oem/usr/ko/usb_f_uvc.ko
if [ "$CDC_ENABLE" = "YES" ];then
insmod /oem/usr/ko/u_serial.ko
insmod /oem/usr/ko/usb_f_acm.ko
fi
insmod /oem/usr/ko/phy-rockchip-inno-usb2.ko
insmod /oem/usr/ko/dwc3-of-simple.ko
insmod /oem/usr/ko/dwc3.ko
##main
#init usb config
ifconfig lo up # for adb ok
/etc/init.d/S10udev stop
umount /sys/kernel/config
mkdir /dev/usb-ffs
mount -t configfs none /sys/kernel/config
mkdir -p /sys/kernel/config/usb_gadget/rockchip
mkdir -p /sys/kernel/config/usb_gadget/rockchip/strings/0x409
mkdir -p ${USB_CONFIGS_DIR}/strings/0x409
echo 0x2207 > /sys/kernel/config/usb_gadget/rockchip/idVendor
echo 0x0310 > /sys/kernel/config/usb_gadget/rockchip/bcdDevice
echo 0x0200 > /sys/kernel/config/usb_gadget/rockchip/bcdUSB
echo 239 > /sys/kernel/config/usb_gadget/rockchip/bDeviceClass
echo 2 > /sys/kernel/config/usb_gadget/rockchip/bDeviceSubClass
echo 1 > /sys/kernel/config/usb_gadget/rockchip/bDeviceProtocol
SERIAL_NUM=`cat /proc/cpuinfo |grep Serial | awk -F ":" '{print $2}'`
echo "serialnumber is $SERIAL_NUM"
echo $SERIAL_NUM > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/serialnumber
echo "rockchip" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/manufacturer
echo "UVC" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/product
echo 0x1 > /sys/kernel/config/usb_gadget/rockchip/os_desc/b_vendor_code
echo "MSFT100" > /sys/kernel/config/usb_gadget/rockchip/os_desc/qw_sign
echo 500 > /sys/kernel/config/usb_gadget/rockchip/configs/b.1/MaxPower
#ln -s /sys/kernel/config/usb_gadget/rockchip/configs/b.1 /sys/kernel/config/usb_gadget/rockchip/os_desc/b.1
#Windows computers will remember the device by default.
#Changing the pid does not require re-uninstalling and loading the windows driver.
echo 0x0016 > /sys/kernel/config/usb_gadget/rockchip/idProduct
if [ $UVC_MULTI = one ];then
echo 0x0018 > /sys/kernel/config/usb_gadget/rockchip/idProduct
elif [ $UVC_MULTI = two ];then
echo 0x001A > /sys/kernel/config/usb_gadget/rockchip/idProduct
fi
#uvc config init
uvc_device_config uvc.gs1 "UVC RGB"
if [ $UVC_MULTI = one ];then
uvc_device_config uvc.gs2 "RK UVC"
elif [ $UVC_MULTI = two ];then
uvc_device_config uvc.gs2 "RK UVC 1"
uvc_device_config uvc.gs3 "RK UVC 2"
fi
##reset config,del default adb config
if [ -e ${USB_CONFIGS_DIR}/ffs.adb ]; then
#for rk1808 kernel 4.4
rm -f ${USB_CONFIGS_DIR}/ffs.adb
else
ls ${USB_CONFIGS_DIR} | grep f[0-9] | xargs -I {} rm ${USB_CONFIGS_DIR}/{}
fi
case "$1" in
rndis)
# config rndis
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/rndis.gs0
echo "uvc_rndis" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
if [ $UVC_MULTI = one ];then
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f3
elif [ $UVC_MULTI = two ];then
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f4
else
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f2
fi
echo "config uvc and rndis..."
;;
uac1)
uac1_device_config uac1
echo "uvc_uac1" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
echo "config uvc and uac1..."
;;
uac2)
uac2_device_config uac2
echo "uvc_uac2" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
echo "config uvc and uac2..."
;;
uac1_rndis)
#uac_device_config uac1
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/rndis.gs0
if [ $UVC_MULTI = one ];then
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f4
elif [ $UVC_MULTI = two ];then
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f5
else
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f3
fi
uac1_device_config uac1
echo "uvc_uac1_rndis" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
echo "config uvc and uac1 rndis..."
;;
uac2_rndis)
#uac_device_config uac2
mkdir /sys/kernel/config/usb_gadget/rockchip/functions/rndis.gs0
if [ $UVC_MULTI = one ];then
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f4
elif [ $UVC_MULTI = two ];then
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f5
else
ln -s ${USB_FUNCTIONS_DIR}/rndis.gs0 ${USB_CONFIGS_DIR}/f3
fi
uac2_device_config uac2
echo "uvc_uac2_rndis" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
echo "config uvc and uac2 rndis..."
;;
*)
echo "uvc" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
echo "config uvc ..."
esac
ln -s ${USB_FUNCTIONS_DIR}/uvc.gs1 ${USB_CONFIGS_DIR}/f1
if [ $UVC_MULTI = one ];then
ln -s ${USB_FUNCTIONS_DIR}/uvc.gs2 ${USB_CONFIGS_DIR}/f2
elif [ $UVC_MULTI = two ];then
ln -s ${USB_FUNCTIONS_DIR}/uvc.gs2 ${USB_CONFIGS_DIR}/f2
ln -s ${USB_FUNCTIONS_DIR}/uvc.gs3 ${USB_CONFIGS_DIR}/f3
fi
if [ "$CDC_ENABLE" = "YES" ];then
cdc_device_config
fi
UDC=`ls /sys/class/udc/| awk '{print $1}'`
echo $UDC > /sys/kernel/config/usb_gadget/rockchip/UDC
if [ "$1" ]; then
pre_run_rndis $1
fi

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,171 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,
*prev; /* next/prev allow you to walk array/object chains. Alternatively,
use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON
*child; /* An array or object item will have a child pointer pointing
to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is
in the list of subitems of an object. */
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks *hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate.
* Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when
* finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting.
* Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful.
*/
extern cJSON *cJSON_GetArrayItem(cJSON *array, int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error.
* You'll probably need to look a few chars back to make sense of it. Defined
* when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);
/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object, const char *string,
cJSON *item);
/* Append reference to item to the specified array/object. Use this when you
* want to add an existing cJSON to a new cJSON, but don't want to corrupt your
* existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string,
cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
/* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string,
cJSON *newitem);
/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item, int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new
memory that will
need to be released. With recurse!=0, it will duplicate any children connected
to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* ParseWithOpts allows you to require (and check) that the JSON is null
* terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,
const char **return_parse_end,
int require_null_terminated);
extern void cJSON_Minify(char *json);
/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object, name) \
cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object, name) \
cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object, name) \
cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object, name, b) \
cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object, name, n) \
cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object, name, s) \
cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
/* When assigning an integer value, it needs to be propagated to valuedouble
* too. */
#define cJSON_SetIntValue(object, val) \
((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "camera_control.h"
#include "isp.h"
#include "param.h"
#include "uvc_log.h"
extern char *rkuvc_iq_file_path_;
struct Camera_Stream {};
void video_record_signal(struct Camera_Stream *stream) {}
static void camera_stop(struct Camera_Stream *stream) {
LOG_INFO("%s \n", __func__);
}
static void *uvc_camera(void *arg) {}
int camera_control_start(int id, int width, int height, int fps, int format,
int eptz) {
if (rk_param_get_int("video.source:enable_aiq", 1))
camera_control_set_rate(id, fps);
return 0;
}
void camera_control_stop(int id) {
LOG_INFO("%s: id:%d\n", __func__, id);
int ret = 0;
if (rk_param_get_int("video.source:enable_aiq", 1))
ret |= rk_isp_deinit(id);
if (rk_param_get_int("video.source:enable_aiq", 1))
ret |= rk_isp_init(id, rkuvc_iq_file_path_);
return ret;
}
void camera_control_init() {
LOG_INFO("%s \n", __func__);
if (rk_param_get_int("video.source:enable_aiq", 1)) {
rk_isp_init(0, rkuvc_iq_file_path_);
rk_isp_set_frame_rate(0, rk_param_get_int("isp.0.adjustment:fps", 30));
if (rk_param_get_int("video.source:enable_2uvc", 0))
rk_isp_init(1, rkuvc_iq_file_path_);
} else {
LOG_INFO("%s disabled aiq \n", __func__);
}
}
void camera_control_set_rate(int index, int rate) {
LOG_INFO("camera index:%d rate:%d \n", index, rate);
if (rk_param_get_int("video.source:enable_aiq", 1)) {
rk_isp_set_frame_rate(index, rate);
}
}
void camera_control_set_zoom(int val) { LOG_INFO("set_zoom:%d\n", val); }
void camera_control_set_pan(int val) { LOG_INFO("set_pan:%d\n", val); }
void camera_control_set_tilt(int val) { LOG_INFO("set_tilt:%d\n", val); }
void camera_control_set_roll(int val) {
LOG_INFO("set_roll:%d\n", val);
// todo
}
void camera_control_deinit() {
LOG_INFO("%s \n", __func__);
if (rk_param_get_int("video.source:enable_aiq", 1)) {
rk_isp_deinit(0);
if (rk_param_get_int("video.source:enable_2uvc", 0))
rk_isp_deinit(1);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __CARERA_CONTROL_H__
#define __CARERA_CONTROL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "isp.h"
#include "param.h"
#include <unistd.h>
void camera_control_init();
void camera_control_deinit();
int camera_control_start(int id, int width, int height, int fps, int format,
int eptz);
void camera_control_stop(int id);
void camera_control_set_zoom(int val);
void camera_control_set_pan(int val);
void camera_control_set_tilt(int val);
void camera_control_set_roll(int val);
void camera_control_set_rate(int index, int rate);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,255 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "camera_pu_control.h"
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "uvc_log.h"
#include <pthread.h>
int video_record_set_brightness(int brightness) {
rk_isp_set_brightness(0, brightness);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_contrast(int contrast) {
rk_isp_set_contrast(0, contrast);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_hue(int hue) {
rk_isp_set_hue(0, hue);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_staturation(int staturation) {
rk_isp_set_saturation(0, staturation);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_sharpness(int sharpness) {
rk_isp_set_sharpness(0, sharpness);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_fps(int fixfps) {
rk_isp_set_frame_rate(0, fixfps);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_gamma(int gamma) {
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_white_balance_temperature(int balance) {
//[2800,6500]
LOG_INFO("WhiteBalance color temperature is %d \n", balance);
rk_isp_set_white_blance_ct(0, balance);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_white_balance_temperature_auto(int balance) {
if (balance == 1)
rk_isp_set_white_blance_style(0, "autoWhiteBalance");
else
rk_isp_set_white_blance_style(0, "manualWhiteBalance");
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_gain(int gain) {
rk_isp_set_exposure_gain(0, gain);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_hue_auto(int hue_auto) {
rk_isp_set_hue_mode(0, hue_auto);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_frequency_mode(int mode) {
if (mode == 1)
rk_isp_set_power_line_frequency_mode(0, "PAL(50HZ)");
else
rk_isp_set_power_line_frequency_mode(0, "NTSC(60HZ)");
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_roll_mode(int mode) {
switch (mode) {
case 0: {
rk_isp_set_image_flip(0, "close");
break;
}
case 1: {
rk_isp_set_image_flip(0, "flip");
break;
}
case 2: {
rk_isp_set_image_flip(0, "centrosymmetric");
break;
}
case 3: {
rk_isp_set_image_flip(0, "mirror");
break;
}
default: {
rk_isp_set_image_flip(0, "close");
break;
}
}
return 0;
}
int video_record_set_exposure_time(int time) {
char str[8];
sprintf(str, "%f", ((float)time / 10000));
rk_isp_set_exposure_time(0, str);
LOG_INFO("%s \n", __func__);
return 0;
}
int video_record_set_ae_mode(int mode) {
if (mode == 2) {
LOG_DEBUG("AE:set auto mode!!\n");
rk_isp_set_exposure_mode(0, "auto");
} else {
LOG_DEBUG("AE:set manual mode!!\n");
rk_isp_set_exposure_mode(0, "manual");
}
LOG_INFO("%s \n", __func__);
return 0;
}
void camera_pu_control_init(int type, int def, int min, int max) {
LOG_DEBUG("%s!\n", __func__);
}
int camera_pu_control_get(int type, int def) {
LOG_DEBUG("%s!\n", __func__);
return def;
}
int check_ispserver_work() {
if (rk_param_get_int("video.source:enable_aiq", 1))
return 1;
else
return 0;
}
int camera_pu_control_set(int type, int value) {
LOG_DEBUG("%s! type is %d,value is %d\n", __func__, type, value);
if (!check_ispserver_work()) {
LOG_INFO("check ispserver is no ready,pu set fail!\n");
return 0;
}
switch (type) {
case UVC_PU_BRIGHTNESS_CONTROL:
video_record_set_brightness(value);
break;
case UVC_PU_CONTRAST_CONTROL:
video_record_set_contrast(value);
break;
case UVC_PU_HUE_CONTROL:
video_record_set_hue(value);
break;
case UVC_PU_SATURATION_CONTROL:
video_record_set_staturation(value);
break;
case UVC_PU_SHARPNESS_CONTROL:
video_record_set_sharpness(value);
break;
case UVC_PU_GAMMA_CONTROL:
// video_record_set_gamma(value);
break;
case UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
video_record_set_white_balance_temperature(value);
break;
case UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
video_record_set_white_balance_temperature_auto(value);
break;
case UVC_PU_GAIN_CONTROL:
video_record_set_gain(value);
break;
case UVC_PU_HUE_AUTO_CONTROL:
video_record_set_hue_auto(value);
break;
case UVC_PU_POWER_LINE_FREQUENCY_CONTROL:
video_record_set_frequency_mode(value);
break;
case UVC_PU_FPS_CONTROL:
video_record_set_fps(value);
break;
case UVC_PU_ROLL_CONTROL:
video_record_set_roll_mode(value);
break;
case UVC_PU_EXPOSURE_TIME_CONTROL:
video_record_set_exposure_time(value);
break;
case UVC_PU_AE_MODE_CONTROL:
video_record_set_ae_mode(value);
break;
default:
LOG_DEBUG("====unknow pu cmd.\n");
break;
}
return 0;
}
int camera_pu_control_check(int deviceid) {
LOG_DEBUG("%s!\n", __func__);
return 0;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __CARERA_PU_CONTROL_H__
#define __CARERA_PU_CONTROL_H__
#include "camera_control.h"
#include <uvc-gadget.h>
void camera_pu_control_init(int type, int def, int min, int max);
int camera_pu_control_get(int type, int def);
int camera_pu_control_set(int type, int value);
int camera_pu_control_check(int deviceid);
int check_ispserver_work();
#endif

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "osd.h"
#include "osd_rockchip_logo.h"
#include "uvc_log.h"
#include "uvc_mpi_config.h"
#include "uvc_video.h"
static RK_S32 osd_create(RGN_HANDLE handle, MPP_CHN_S *mppChn, RK_U32 layer,
RECT_S *rect) {
RK_S32 s32Ret = RK_SUCCESS;
RGN_ATTR_S stRgnAttr;
RGN_CHN_ATTR_S stRgnChnAttr;
if (mppChn->enModId == RK_ID_VPSS)
stRgnAttr.enType = OVERLAY_EX_RGN;
else
stRgnAttr.enType = OVERLAY_RGN;
stRgnAttr.unAttr.stOverlay.enPixelFmt = RK_FMT_RGBA8888;
stRgnAttr.unAttr.stOverlay.stSize.u32Width = rect->u32Width;
stRgnAttr.unAttr.stOverlay.stSize.u32Height = rect->u32Height;
stRgnAttr.unAttr.stOverlay.u32ClutNum = 0;
s32Ret = RK_MPI_RGN_Create(handle, &stRgnAttr);
if (RK_SUCCESS != s32Ret) {
LOG_ERROR("RK_MPI_RGN_Create (%d) failed with %#x!\n", handle, s32Ret);
RK_MPI_RGN_Destroy(handle);
return s32Ret;
}
memset(&stRgnChnAttr, 0, sizeof(stRgnChnAttr));
stRgnChnAttr.bShow = RK_TRUE;
stRgnChnAttr.enType = stRgnAttr.enType;
stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = rect->s32X;
stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = rect->s32Y;
stRgnChnAttr.unChnAttr.stOverlayChn.u32BgAlpha = 0;
stRgnChnAttr.unChnAttr.stOverlayChn.u32FgAlpha = 255;
stRgnChnAttr.unChnAttr.stOverlayChn.u32Layer = layer;
stRgnChnAttr.unChnAttr.stOverlayChn.stQpInfo.bEnable = RK_FALSE;
s32Ret = RK_MPI_RGN_AttachToChn(handle, mppChn, &stRgnChnAttr);
if (RK_SUCCESS != s32Ret) {
LOG_ERROR("RK_MPI_RGN_AttachToChn (%d) failed with %#x!\n", handle, s32Ret);
}
return s32Ret;
}
static RK_S32 osd_destroy(RGN_HANDLE handle, MPP_CHN_S *mppChn) {
RK_S32 s32Ret = RK_SUCCESS;
s32Ret = RK_MPI_RGN_DetachFromChn(handle, mppChn);
if (RK_SUCCESS != s32Ret) {
LOG_ERROR("RK_MPI_RGN_DetachFrmChn (%d) failed with %#x!\n", handle,
s32Ret);
}
s32Ret = RK_MPI_RGN_Destroy(handle);
if (RK_SUCCESS != s32Ret) {
LOG_ERROR("RK_MPI_RGN_Destroy [%d] failed with %#x\n", handle, s32Ret);
}
return s32Ret;
}
static RK_S32 osd_show_or_hide(RGN_HANDLE handle, const MPP_CHN_S *mppChn,
RK_BOOL bShow) {
RGN_CHN_ATTR_S stChnAttr;
RK_S32 s32Ret = RK_SUCCESS;
if (RK_NULL == mppChn) {
LOG_ERROR("input parameter is null. it is invaild!\n");
return RK_FAILURE;
}
s32Ret = RK_MPI_RGN_GetDisplayAttr(handle, mppChn, &stChnAttr);
if (RK_SUCCESS != s32Ret) {
LOG_ERROR("RK_MPI_RGN_GetDisplayAttr (%d)) failed with %#x!\n", handle,
s32Ret);
return RK_FAILURE;
}
stChnAttr.bShow = bShow;
s32Ret = RK_MPI_RGN_SetDisplayAttr(handle, mppChn, &stChnAttr);
if (RK_SUCCESS != s32Ret) {
LOG_ERROR("RK_MPI_RGN_SetDisplayAttr (%d)) failed with %#x!\n", handle,
s32Ret);
return RK_FAILURE;
}
return RK_SUCCESS;
}
static RK_S32 osd_test_show_rockchip_logo(RGN_HANDLE handle) {
RK_S32 s32Ret = RK_SUCCESS;
RGN_CANVAS_INFO_S stCanvasInfo;
RK_U32 *data;
FILE *p;
LOG_ERROR("test show rockchip logo\n");
memset(&stCanvasInfo, 0, sizeof(RGN_CANVAS_INFO_S));
s32Ret = RK_MPI_RGN_GetCanvasInfo(handle, &stCanvasInfo);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_RGN_GetCanvasInfo failed with %#x!\n", s32Ret);
}
data = (RK_U32 *)stCanvasInfo.u64VirAddr;
p = fopen("/data/rockchip-logo-320-96.rgba", "r");
if (p) {
fread(data, 4, stCanvasInfo.u32VirWidth * stCanvasInfo.u32VirHeight, p);
fclose(p);
} else {
// no osd file, copy array to rgn
#if 1 // test rgba data to set 0
memcpy(data, u32BGRA8888RKLOGO,
stCanvasInfo.u32VirWidth * stCanvasInfo.u32VirHeight * 4);
#else // test rgba data
for (RK_U32 i = 0; i < stCanvasInfo.u32VirWidth * stCanvasInfo.u32VirHeight;
i++) {
// RK_FMT_RGBA8888
if (i < stCanvasInfo.u32VirWidth * stCanvasInfo.u32VirHeight / 4)
data[i] = 0xff000000; // black
else if (i < stCanvasInfo.u32VirWidth * stCanvasInfo.u32VirHeight / 2)
data[i] = 0xffff0000; // blue
else if (i < stCanvasInfo.u32VirWidth * stCanvasInfo.u32VirHeight / 4 * 3)
data[i] = 0xff00ff00; // green
else
data[i] = 0xff0000ff; // red
}
#endif
}
s32Ret = RK_MPI_RGN_UpdateCanvas(handle);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_RGN_UpdateCanvas failed with %#x!\n", s32Ret);
}
return s32Ret;
}
static RK_S32 osd_test_init(UVC_MPI_CFG *uvcCfg) {
RGN_HANDLE handle = 0;
MPP_CHN_S mppChn;
RK_U32 layer = 0;
RECT_S rect;
RK_S32 s32Ret;
if (uvcCfg->uvc_cfg.fcc == V4L2_PIX_FMT_YUYV ||
uvcCfg->osd_cfg.force_use_vpss) {
mppChn.enModId = RK_ID_VPSS;
mppChn.s32DevId = uvcCfg->vpss_cfg[MPI_VPSS_CHANNEL_TYPE_UVC].group_id;
mppChn.s32ChnId = uvcCfg->vpss_cfg[MPI_VPSS_CHANNEL_TYPE_UVC].channel_id;
} else {
mppChn.enModId = RK_ID_VENC;
mppChn.s32DevId = 0;
mppChn.s32ChnId = uvcCfg->venc_cfg.common_cfg.channel_id;
}
rect.s32X = 100;
rect.s32Y = 200;
rect.u32Width = 320; // need align 16
rect.u32Height = 96; // need align 16
s32Ret = osd_create(handle, &mppChn, layer, &rect);
s32Ret = osd_test_show_rockchip_logo(handle);
// defalut is show, if want hide this osd, refer to below setting
// osd_show_or_hide(handle, &mppChn, RK_FALSE);
return s32Ret;
}
static RK_S32 osd_test_deinit(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret;
MPP_CHN_S mppChn;
RGN_HANDLE handle = 0;
if (uvcCfg->uvc_cfg.fcc == V4L2_PIX_FMT_YUYV ||
uvcCfg->osd_cfg.force_use_vpss) {
mppChn.enModId = RK_ID_VPSS;
mppChn.s32DevId = uvcCfg->vpss_cfg[MPI_VPSS_CHANNEL_TYPE_UVC].group_id;
mppChn.s32ChnId = uvcCfg->vpss_cfg[MPI_VPSS_CHANNEL_TYPE_UVC].channel_id;
} else {
mppChn.enModId = RK_ID_VENC;
mppChn.s32DevId = 0;
mppChn.s32ChnId = uvcCfg->venc_cfg.common_cfg.channel_id;
}
return osd_destroy(handle, &mppChn);
}
RK_S32 osd_start(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret;
// now just for test run
s32Ret = osd_test_init(uvcCfg);
// TODO(user) you can comment the code above, and implement it yourself
return s32Ret;
}
RK_S32 osd_stop(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret;
// now just for test run
s32Ret = osd_test_deinit(uvcCfg);
// TODO(user) you can comment the code above, and implement it yourself
return s32Ret;
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __OSD_H__
#define __OSD_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "rk_common.h"
#include "rk_mpi_rgn.h"
#include "uvc_mpi_config.h"
RK_S32 osd_start(UVC_MPI_CFG *uvcCfg);
RK_S32 osd_stop(UVC_MPI_CFG *uvcCfg);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "uevent.h"
#include "uvc_control.h"
#include "uvc_log.h"
extern int app_quit;
static void handle_uvc_event(struct uevent *uevent) {
if (strcmp(uevent->subsystem, "android_usb"))
return;
if (!strcmp(uevent->usb_state, "DISCONNECTED")) {
LOG_INFO("udc disconnected\n");
app_quit = 1;
} else if (!strcmp(uevent->usb_state, "CONNECTED")) {
LOG_INFO("udc connected\n");
} else if (!strcmp(uevent->usb_state, "CONFIGURED")) {
LOG_INFO("udc configured\n");
} else {
LOG_INFO("unknow usb event\n");
}
}
static void parse_event(const char *msg, struct uevent *uevent) {
uevent->action = "";
uevent->path = "";
uevent->subsystem = "";
uevent->usb_state = "";
uevent->device_name = "";
while (*msg) {
if (!strncmp(msg, "ACTION=", 7)) {
msg += 7;
uevent->action = msg;
} else if (!strncmp(msg, "DEVPATH=", 8)) {
msg += 8;
uevent->path = msg;
} else if (!strncmp(msg, "SUBSYSTEM=", 10)) {
msg += 10;
uevent->subsystem = msg;
} else if (!strncmp(msg, "USB_STATE=", 10)) {
msg += 10;
uevent->usb_state = msg;
} else if (!strncmp(msg, "DEVNAME=", 8)) {
msg += 8;
uevent->device_name = msg;
}
/* advance to after the next \0 */
while (*msg++)
;
}
LOG_DEBUG("event { '%s', '%s', '%s', '%s', '%s' }\n", uevent->action,
uevent->path, uevent->subsystem, uevent->usb_state,
uevent->device_name);
handle_uvc_event(uevent);
}
static void *event_monitor_thread(void *arg) {
int sockfd;
int i, j, len;
char buf[1024 + 2];
struct iovec iov;
struct msghdr msg;
struct sockaddr_nl sa;
struct uevent uevent;
uint32_t flags = *(uint32_t *)arg;
prctl(PR_SET_NAME, "event_monitor", 0, 0, 0);
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = NETLINK_KOBJECT_UEVENT;
sa.nl_pid = 0;
memset(&msg, 0, sizeof(msg));
iov.iov_base = (void *)buf;
iov.iov_len = sizeof(buf);
msg.msg_name = (void *)&sa;
msg.msg_namelen = sizeof(sa);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (sockfd == -1) {
LOG_ERROR("socket creating failed:%s\n", strerror(errno));
goto err_event_monitor;
}
if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
LOG_ERROR("bind error:%s\n", strerror(errno));
goto err_event_monitor;
}
while (1) {
len = recvmsg(sockfd, &msg, 0);
if (len < 0) {
LOG_ERROR("receive error\n");
} else if (len < 32 || len > sizeof(buf)) {
LOG_INFO("invalid message");
} else {
buf[len] = '\0';
buf[len + 1] = '\0';
parse_event(buf, &uevent);
}
}
err_event_monitor:
pthread_detach(pthread_self());
pthread_exit(NULL);
}
int uevent_monitor_run(uint32_t flags) {
pthread_t tid;
return pthread_create(&tid, NULL, event_monitor_thread, &flags);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UEVENT_H__
#define __UEVENT_H__
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
struct uevent {
const char *action;
const char *path;
const char *subsystem;
const char *usb_state;
const char *device_name;
};
int uevent_monitor_run(uint32_t flags);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,253 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _UVC_GADGET_H_
#define _UVC_GADGET_H_
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/usb/ch9.h>
#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_SUSPEND (V4L2_EVENT_PRIVATE_START + 6)
#define UVC_EVENT_RESUME (V4L2_EVENT_PRIVATE_START + 7)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 8)
#define MAX_UVC_REQUEST_DATA_LENGTH 60
#define UVC_CTRL_INTERFACE_ID 0x00
#define UVC_CTRL_CAMERA_TERMINAL_ID 0x01
#define UVC_CTRL_PROCESSING_UNIT_ID 0x02
#define UVC_CTRL_EXTENSION_UNIT_ID 0x03
#define UVC_CTRL_OUTPUT_TERMINAL_ID 0x04
#define UVC_CTRL_XU_UNIT_ID 0x06
struct uvc_request_data {
__s32 length;
__u8 data[60];
};
struct uvc_event {
union {
enum usb_device_speed speed;
struct usb_ctrlrequest req;
struct uvc_request_data data;
};
};
#define UVCIOC_SEND_RESPONSE _IOW('U', 1, struct uvc_request_data)
#define UVC_INTF_CONTROL 0
#define UVC_INTF_STREAMING 1
#ifdef __cplusplus
extern "C" {
#endif
#include "uvc_control.h"
#include "uvc_video.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "uvc_configfs.h"
#include <linux/usb/ch9.h>
#include <linux/usb/video.h>
#include <linux/videodev2.h>
#define V4L2_PIX_FMT_H265 \
v4l2_fourcc('H', '2', '6', '5') /* H265 with start codes */
#define UVC_PU_FPS_CONTROL 0xff
#define UVC_PU_ROLL_CONTROL 0xfd
#define UVC_PU_EXPOSURE_TIME_CONTROL 0xfc
#define UVC_PU_AE_MODE_CONTROL 0xfb
/* ---------------------------------------------------------------------------
* Generic stuff
*/
enum XuCmd {
CMD_TOOLS_CTRL_1 = 0x01,
CMD_GET_CAMERA_VERSION,
CMD_SHUTDOWN_CAMERA,
CMD_RESET_CAMERA,
CMD_SET_MOTOR_RATE = 0x06,
CMD_SET_MOTOR_BY_STEPS = 0x07,
CMD_SET_MOTOR_BY_USER = 0x08,
CMD_STOP_MOTOR_BY_USER = 0x09,
CMD_SET_CAMERA_IP = 0x0a,
CMD_SET_H265 = 0x0b,
CMD_MAX_NUM = CMD_SET_H265,
};
/* IO methods supported */
enum io_method {
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
IO_METHOD_DMA_BUFF,
};
#define UVC_IO_METHOD_MMAP 0
#define UVC_IO_METHOD_USERPTR 1
#define UVC_IO_METHOD_DMA_BUFF 2
#define USE_MPI_BUF_TO_UVC_VIDEO_BUFFER 1
#define UVC_IO_METHOD UVC_IO_METHOD_USERPTR
/* Buffer representing one video frame */
struct buffer {
struct v4l2_buffer buf;
void *start;
size_t length;
};
struct v4l2_buffer_info {
// struct uvc_buffer *uvc_buf;
void *frame; // mb
int fd;
int index;
unsigned long userptr;
};
enum USB_STATE {
USB_STATE_INIT,
USB_STATE_FIRST_CMD,
USB_STATE_FIRST_GET_READY,
USB_STATE_FIRST_GET_OK,
USB_STATE_FIRST_SEND_OK,
USB_STATE_NORMAL_RUN
};
/* Represents a UVC based video output device */
struct uvc_device {
int video_id;
/* uvc device specific */
int uvc_fd;
int is_streaming;
int run_standalone;
char *uvc_devname;
struct uvc_function_config *fc;
int suspend;
int need_bypass;
/* uvc control request specific */
struct uvc_streaming_control probe;
struct uvc_streaming_control commit;
int control;
struct uvc_request_data request_error_code;
unsigned int brightness_val;
unsigned short contrast_val;
int hue_val;
unsigned int saturation_val;
unsigned int sharpness_val;
unsigned int gamma_val;
unsigned int white_balance_temperature_val;
unsigned int white_balance_temperature_auto_val;
unsigned int gain_val;
unsigned int hue_auto_val;
unsigned int zoom_val;
int pan_val;
int tilt_val;
short roll_val;
short iris_val;
int exposure_time_val;
unsigned char ae_mode_val;
unsigned char power_line_frequency_val;
unsigned char ex_tool_ctrl1[4];
unsigned char ex_sn_data[MAX_UVC_REQUEST_DATA_LENGTH];
unsigned char ex_ip_data[MAX_UVC_REQUEST_DATA_LENGTH]; //
unsigned char ex_date_data[MAX_UVC_REQUEST_DATA_LENGTH];
unsigned int eptz_flag;
unsigned int xu_h265;
/* uvc buffer specific */
enum io_method io;
struct buffer *mem;
struct buffer *dummy_buf;
int nbufs;
unsigned int fcc;
unsigned int width;
unsigned int height;
unsigned int fps;
unsigned int bulk;
uint8_t color;
unsigned int imgsize;
void *imgdata;
/* USB speed specific */
int mult;
int burst;
int maxpkt;
enum usb_device_speed speed;
/* uvc specific flags */
int first_buffer_queued;
int uvc_shutdown_requested;
/* uvc buffer queue and dequeue counters */
unsigned long long int qbuf_count;
unsigned long long int dqbuf_count;
/* v4l2 device hook */
struct v4l2_device *vdev;
uint8_t cs;
uint8_t entity_id;
struct v4l2_buffer ubuf;
struct v4l2_buffer_info *vbuf_info;
int drop_count;
int try_count;
enum USB_STATE usb_state;
unsigned int first_usb_get_ready_pts;
unsigned int first_usb_get_ok_pts;
unsigned int first_usb_send_ok_pts;
unsigned int first_cmd_pts;
unsigned int stream_on_pts;
int get_buf_count;
};
int uvc_gadget_main(struct uvc_function_config *fc);
int uvc_video_reqbufs(struct uvc_device *dev, int nbufs);
int uvc_video_stream(struct uvc_device *dev, int enable);
#ifdef __cplusplus
}
#endif
#endif /* _UVC_GADGET_H_ */

View File

@@ -0,0 +1,693 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* ConfigFS Gadget device handling
*
* Copyright (C) 2020 Rockchip Electronics Co., Ltd.
*
*/
/* To provide basename and asprintf from the GNU library. */
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <linux/videodev2.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "uvc_configfs.h"
#define V4L2_PIX_FMT_H265 \
v4l2_fourcc('H', '2', '6', '5') /* H265 with start codes */
#define UVC_FUNCTION_NAME "uvc*"
#define UVC_GUID_FORMAT_MJPEG \
{ \
'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, \
0x38, 0x9b, 0x71 \
}
#define UVC_GUID_FORMAT_YUY2 \
{ \
'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, \
0x38, 0x9b, 0x71 \
}
#define UVC_GUID_FORMAT_NV12 \
{ \
'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, \
0x38, 0x9b, 0x71 \
}
#define UVC_GUID_FORMAT_H264 \
{ \
'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, \
0x38, 0x9b, 0x71 \
}
#define UVC_GUID_FORMAT_H265 \
{ \
'H', '2', '6', '5', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, \
0x38, 0x9b, 0x71 \
}
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
struct uvc_function_format_info {
uint8_t guid[16];
uint32_t fcc;
};
static struct uvc_function_format_info uvc_formats[] = {
{
.guid = UVC_GUID_FORMAT_YUY2, .fcc = V4L2_PIX_FMT_YUYV,
},
{
.guid = UVC_GUID_FORMAT_MJPEG, .fcc = V4L2_PIX_FMT_MJPEG,
},
{
.guid = UVC_GUID_FORMAT_H264, .fcc = V4L2_PIX_FMT_H264,
},
{
.guid = UVC_GUID_FORMAT_H265, .fcc = V4L2_PIX_FMT_H265,
},
{
.guid = UVC_GUID_FORMAT_NV12, .fcc = V4L2_PIX_FMT_NV12,
}};
/* -----------------------------------------------------------------------------
* Path handling and support
*/
static char *path_join(const char *dirname, const char *name) {
char *path;
int ret;
ret = asprintf(&path, "%s/%s", dirname, name);
/*
* asprintf returns -1 on allocation or other errors, leaving 'path'
* undefined. We shouldn't even call free(path) here. We want to return
* NULL on error, so we must manually set it.
*/
if (ret < 0)
path = NULL;
return path;
}
static char *path_glob_index_match(const char *g, unsigned int index) {
glob_t globbuf;
char *match = NULL;
glob(g, 0, NULL, &globbuf);
if (globbuf.gl_pathc > index)
match = strdup(globbuf.gl_pathv[index]);
globfree(&globbuf);
return match;
}
/*
* Find and return the full path of the first directory entry that satisfies
* the match function.
*/
static char *dir_first_match(const char *dir,
int (*match)(const struct dirent *)) {
struct dirent **entries;
unsigned int i;
int n_entries;
char *path;
n_entries = scandir(dir, &entries, match, alphasort);
if (n_entries < 0)
return NULL;
if (n_entries == 0) {
free(entries);
return NULL;
}
path = path_join(dir, entries[0]->d_name);
for (i = 0; i < (unsigned int)n_entries; ++i)
free(entries[i]);
free(entries);
return path;
}
/* -----------------------------------------------------------------------------
* Attribute handling
*/
static int attribute_read(const char *path, const char *file, void *buf,
unsigned int len) {
char *f;
int ret;
int fd;
f = path_join(path, file);
if (!f)
return -ENOMEM;
fd = open(f, O_RDONLY);
free(f);
if (fd == -1) {
printf("Failed to open attribute %s: %s\n", file, strerror(errno));
return -ENOENT;
}
ret = read(fd, buf, len);
close(fd);
if (ret < 0) {
printf("Failed to read attribute %s: %s\n", file, strerror(errno));
return -ENODATA;
}
return len;
}
static int attribute_read_uint(const char *path, const char *file,
unsigned int *val) {
char buf[11] = {0};
char *endptr;
int ret;
ret = attribute_read(path, file, buf, sizeof(buf) - 1);
if (ret < 0)
return ret;
buf[ret] = '\0';
errno = 0;
/* base 0: Autodetect hex, octal, decimal. */
*val = strtoul(buf, &endptr, 0);
if (errno)
return -errno;
if (endptr == buf)
return -ENODATA;
return 0;
}
static char *attribute_read_str(const char *path, const char *file) {
char buf[1024] = {0};
char *p;
int ret;
ret = attribute_read(path, file, buf, sizeof(buf) - 1);
if (ret < 0)
return NULL;
buf[ret] = '\0';
p = strrchr(buf, '\n');
if (p == NULL)
return NULL;
if (p != buf)
*p = '\0';
return strdup(buf);
}
static char *configfs_find_uvc_function(unsigned int index) {
const char *target = UVC_FUNCTION_NAME;
const char *format;
char *func_path;
char *path;
int ret;
format = "%s/usb_gadget/*/functions/%s";
ret = asprintf(&path, format, "/sys/kernel/config", target);
if (!ret)
return NULL;
func_path = path_glob_index_match(path, index);
free(path);
return func_path;
}
static int udc_find_video_device(const char *udc, const char *function) {
char *vpath;
char *video = NULL;
glob_t globbuf;
int video_id = -1;
unsigned int i;
int ret;
ret = asprintf(&vpath, "/sys/class/udc/%s/device/gadget/video4linux/video*",
udc ? udc : "*");
if (!ret)
return -1;
glob(vpath, 0, NULL, &globbuf);
free(vpath);
for (i = 0; i < globbuf.gl_pathc; ++i) {
char *config;
bool match;
/* Match on the first if no search string. */
if (!function)
break;
config = attribute_read_str(globbuf.gl_pathv[i], "function_name");
match = strcmp(function, config) == 0;
free(config);
if (match)
break;
}
if (i < globbuf.gl_pathc) {
const char *v = basename(globbuf.gl_pathv[i]);
video = path_join("/dev", v);
if (sscanf(video, "/dev/video%d", &video_id) != 1)
video_id = -1;
free(video);
}
globfree(&globbuf);
return video_id;
}
/*
* configfs_free_uvc_function - Free a uvc_function_config object
* @fc: The uvc_function_config to be freed
*
* Free the given @fc function previously allocated by a call to
* configfs_parse_uvc_function().
*/
void configfs_free_uvc_function(struct uvc_function_config *fc) {
unsigned int i, j;
free(fc->udc);
free(fc->dev_name);
for (i = 0; i < fc->streaming.num_formats; ++i) {
struct uvc_function_config_format *format = &fc->streaming.formats[i];
for (j = 0; j < format->num_frames; ++j) {
struct uvc_function_config_frame *frame = &format->frames[j];
free(frame->intervals);
}
free(format->frames);
}
free(fc->streaming.formats);
free(fc);
}
#define configfs_parse_child(parent, child, cfg, parse) \
({ \
char *__path; \
int __ret; \
\
__path = path_join((parent), (child)); \
if (__path) { \
__ret = parse(__path, (cfg)); \
free(__path); \
} else { \
__ret = -ENOMEM; \
} \
\
__ret; \
})
static int configfs_parse_interface(const char *path,
struct uvc_function_config_interface *cfg) {
int ret;
ret = attribute_read_uint(path, "bInterfaceNumber", &cfg->bInterfaceNumber);
return ret;
}
static int configfs_parse_control(const char *path,
struct uvc_function_config_control *cfg) {
int ret;
ret = configfs_parse_interface(path, &cfg->intf);
return ret;
}
static int
configfs_parse_streaming_frame(const char *path,
struct uvc_function_config_frame *frame) {
char *intervals;
char *p;
int ret = 0;
ret = ret ?: attribute_read_uint(path, "bFrameIndex", &frame->index);
ret = ret ?: attribute_read_uint(path, "wWidth", &frame->width);
ret = ret ?: attribute_read_uint(path, "wHeight", &frame->height);
if (ret)
return ret;
intervals = attribute_read_str(path, "dwFrameInterval");
if (!intervals)
return -EINVAL;
for (p = intervals; *p;) {
unsigned int interval;
unsigned int *mem;
char *endp;
size_t size;
interval = strtoul(p, &endp, 10);
if (*endp != '\0' && *endp != '\n') {
ret = -EINVAL;
break;
}
p = *endp ? endp + 1 : endp;
size = sizeof *frame->intervals * (frame->num_intervals + 1);
mem = realloc(frame->intervals, size);
if (!mem) {
ret = -ENOMEM;
break;
}
frame->intervals = mem;
frame->intervals[frame->num_intervals++] = interval;
}
free(intervals);
return ret;
}
static int frame_filter(const struct dirent *ent) {
/* Accept all directories but "." and "..". */
if (ent->d_type != DT_DIR)
return 0;
if (!strcmp(ent->d_name, "."))
return 0;
if (!strcmp(ent->d_name, ".."))
return 0;
return 1;
}
static int frame_compare(const void *a, const void *b) {
const struct uvc_function_config_frame *fa = a;
const struct uvc_function_config_frame *fb = b;
if (fa->index < fb->index)
return -1;
else if (fa->index == fb->index)
return 0;
else
return 1;
}
static int
configfs_parse_streaming_format(const char *path,
struct uvc_function_config_format *format) {
struct dirent **entries;
char link_target[1024] = {0};
char *segment;
unsigned int i;
int n_entries;
int ret;
ret = attribute_read_uint(path, "bFormatIndex", &format->index);
if (ret < 0)
return ret;
ret = readlink(path, link_target, sizeof(link_target) - 1);
if (ret < 0)
return ret;
link_target[ret] = '\0';
/*
* Extract the second-to-last path component of the link target,
* which contains the format descriptor type name as exposed by
* the UVC function driver.
*/
segment = strrchr(link_target, '/');
if (!segment)
return -EINVAL;
*segment = '\0';
segment = strrchr(link_target, '/');
if (!segment)
return -EINVAL;
segment++;
if (!strcmp(segment, "framebased")) {
ret =
attribute_read(path, "guidFormat", format->guid, sizeof(format->guid));
} else if (!strcmp(segment, "mjpeg")) {
static const uint8_t guid[16] = UVC_GUID_FORMAT_MJPEG;
memcpy(format->guid, guid, 16);
} else if (!strcmp(segment, "uncompressed")) {
ret =
attribute_read(path, "guidFormat", format->guid, sizeof(format->guid));
if (ret < 0)
return ret;
} else {
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(uvc_formats); ++i) {
if (!memcmp(uvc_formats[i].guid, format->guid, 16)) {
format->fcc = uvc_formats[i].fcc;
break;
}
}
/* Find all entries corresponding to a frame and parse them. */
n_entries = scandir(path, &entries, frame_filter, alphasort);
if (n_entries < 0)
return -errno;
if (n_entries == 0) {
free(entries);
return -EINVAL;
}
format->num_frames = n_entries;
format->frames = calloc(sizeof *format->frames, format->num_frames);
if (!format->frames)
return -ENOMEM;
for (i = 0; i < (unsigned int)n_entries; ++i) {
char *frame;
frame = path_join(path, entries[i]->d_name);
if (!frame) {
ret = -ENOMEM;
goto done;
}
ret = configfs_parse_streaming_frame(frame, &format->frames[i]);
free(frame);
if (ret < 0)
goto done;
}
/* Sort the frames by index. */
qsort(format->frames, format->num_frames, sizeof *format->frames,
frame_compare);
done:
for (i = 0; i < (unsigned int)n_entries; ++i)
free(entries[i]);
free(entries);
return ret;
}
static int format_filter(const struct dirent *ent) {
char *path;
bool valid;
/*
* Accept all links that point to a directory containing a
* "bFormatIndex" file.
*/
if (ent->d_type != DT_LNK)
return 0;
path = path_join(ent->d_name, "bFormatIndex");
if (!path)
return 0;
valid = access(path, R_OK);
free(path);
return valid;
}
static int format_compare(const void *a, const void *b) {
const struct uvc_function_config_format *fa = a;
const struct uvc_function_config_format *fb = b;
if (fa->index < fb->index)
return -1;
else if (fa->index == fb->index)
return 0;
else
return 1;
}
static int
configfs_parse_streaming_header(const char *path,
struct uvc_function_config_streaming *cfg) {
struct dirent **entries;
unsigned int i;
int n_entries;
int ret;
/* Find all entries corresponding to a format and parse them. */
n_entries = scandir(path, &entries, format_filter, alphasort);
if (n_entries < 0)
return -errno;
if (n_entries == 0) {
free(entries);
return -EINVAL;
}
cfg->num_formats = n_entries;
cfg->formats = calloc(sizeof *cfg->formats, cfg->num_formats);
if (!cfg->formats)
return -ENOMEM;
for (i = 0; i < (unsigned int)n_entries; ++i) {
char *format;
format = path_join(path, entries[i]->d_name);
if (!format) {
ret = -ENOMEM;
goto done;
}
ret = configfs_parse_streaming_format(format, &cfg->formats[i]);
free(format);
if (ret < 0)
goto done;
}
/* Sort the formats by index. */
qsort(cfg->formats, cfg->num_formats, sizeof *cfg->formats, format_compare);
done:
for (i = 0; i < (unsigned int)n_entries; ++i)
free(entries[i]);
free(entries);
return ret;
}
static int link_filter(const struct dirent *ent) {
/* Accept all links. */
return ent->d_type == DT_LNK;
}
static int configfs_parse_streaming(const char *path,
struct uvc_function_config_streaming *cfg) {
char *header;
char *class;
int ret;
ret = configfs_parse_interface(path, &cfg->intf);
if (ret < 0)
return ret;
/*
* Handle the high-speed class descriptors only for now. Find the first
* link to the class descriptors.
*/
class = path_join(path, "class/hs");
if (!class)
return -ENOMEM;
header = dir_first_match(class, link_filter);
free(class);
if (!header)
return -EINVAL;
ret = configfs_parse_streaming_header(header, cfg);
free(header);
return ret;
}
static int configfs_parse_uvc(const char *fpath,
struct uvc_function_config *fc) {
int ret = 0;
ret = ret ?: configfs_parse_child(fpath, "control", &fc->control,
configfs_parse_control);
ret = ret ?: configfs_parse_child(fpath, "streaming", &fc->streaming,
configfs_parse_streaming);
/*
* These parameters should be part of the streaming interface in
* ConfigFS, but for legacy reasons they are located directly in the
* function directory.
*/
ret = ret ?: attribute_read_uint(fpath, "streaming_interval",
&fc->streaming.ep.bInterval);
ret = ret ?: attribute_read_uint(fpath, "streaming_maxburst",
&fc->streaming.ep.bMaxBurst);
ret = ret ?: attribute_read_uint(fpath, "streaming_maxpacket",
&fc->streaming.ep.wMaxPacketSize);
return ret;
}
struct uvc_function_config *configfs_parse_uvc_function(unsigned int index) {
struct uvc_function_config *fc;
char *fpath;
char *function;
int ret = 0;
fc = malloc(sizeof *fc);
if (fc == NULL)
return NULL;
memset(fc, 0, sizeof *fc);
/* Find the function in ConfigFS. */
fpath = configfs_find_uvc_function(index);
if (!fpath) {
free(fc);
printf("[configfs_parse_uvc_function] configfs_find_uvc_function error!\n");
return NULL;
}
function = basename(fpath);
fc->dev_name = attribute_read_str(fpath, "device_name");
if (fc->dev_name == NULL)
fc->dev_name = "UVC CAMERA";
fc->udc = attribute_read_str(fpath, "../../UDC");
fc->video = udc_find_video_device(fc->udc, function);
printf("fc->dev_name:%s, fc->udc:%s, fc->video:%d \n", fc->dev_name, fc->udc,
fc->video);
if (fc->video < 0) {
ret = -ENODEV;
goto done;
}
fc->index = index;
ret = configfs_parse_uvc(fpath, fc);
done:
if (ret) {
configfs_free_uvc_function(fc);
printf("[configfs_parse_uvc_function] configfs_free_uvc_function\n");
fc = NULL;
}
free(fpath);
return fc;
}

View File

@@ -0,0 +1,117 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* ConfigFS Gadget device handling
*
* Copyright (C) 2020 Rockchip Electronics Co., Ltd.
*
*/
#ifndef __UVC_CONFIGFS_H__
#define __UVC_CONFIGFS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/*
* struct uvc_function_config_endpoint - Endpoint parameters
* @bInterval: Transfer interval (interrupt and isochronous only)
* @bMaxBurst: Transfer burst size (super-speed only)
* @wMaxPacketSize: Maximum packet size (including the multiplier)
*/
struct uvc_function_config_endpoint {
unsigned int bInterval;
unsigned int bMaxBurst;
unsigned int wMaxPacketSize;
};
/*
* struct uvc_function_config_interface - Interface parameters
* @bInterfaceNumber: Interface number
*/
struct uvc_function_config_interface {
unsigned int bInterfaceNumber;
};
/*
* struct uvc_function_config_control - Control interface parameters
* @intf: Generic interface parameters
*/
struct uvc_function_config_control {
struct uvc_function_config_interface intf;
};
/*
* struct uvc_function_config_frame - Streaming frame parameters
* @index: Frame index in the UVC descriptors
* @width: Frame width in pixels
* @height: Frame height in pixels
* @num_intervals: Number of entries in the intervals array
* @intervals: Array of frame intervals
*/
struct uvc_function_config_frame {
unsigned int index;
unsigned int width;
unsigned int height;
unsigned int num_intervals;
unsigned int *intervals;
};
/*
* struct uvc_function_config_format - Streaming format parameters
* @index: Format index in the UVC descriptors
* @guid: Format GUID
* @fcc: V4L2 pixel format
* @num_frames: Number of entries in the frames array
* @frames: Array of frame descriptors
*/
struct uvc_function_config_format {
unsigned int index;
uint8_t guid[16];
unsigned int fcc;
unsigned int num_frames;
struct uvc_function_config_frame *frames;
};
/*
* struct uvc_function_config_streaming - Streaming interface parameters
* @intf: Generic interface parameters
* @ep: Endpoint parameters
* @num_formats: Number of entries in the formats array
* @formats: Array of format descriptors
*/
struct uvc_function_config_streaming {
struct uvc_function_config_interface intf;
struct uvc_function_config_endpoint ep;
unsigned int num_formats;
struct uvc_function_config_format *formats;
};
/*
* struct uvc_function_config - UVC function configuration parameters
* @video: Full path to the video device node
* @udc: UDC name
* @control: Control interface configuration
* @streaming: Streaming interface configuration
*/
struct uvc_function_config {
int video;
int video_src;
unsigned int index;
char *udc;
char *dev_name;
struct uvc_function_config_control control;
struct uvc_function_config_streaming streaming;
};
struct uvc_function_config *configfs_parse_uvc_function(unsigned int index);
void configfs_free_uvc_function(struct uvc_function_config *fc);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,403 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "uvc_control.h"
#include "camera_control.h"
#include "uevent.h"
#include "uvc-gadget.h"
#include "uvc_configfs.h"
#include "uvc_log.h"
#include "uvc_process_unit.h"
#include "uvc_video.h"
#include <fcntl.h>
#include <map>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define UVC_STREAMING_INTF_PATH \
"/sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/streaming/" \
"bInterfaceNumber"
#define UVC_STREAMING_MAXPACKET_PATH \
"/sys/kernel/config/usb_gadget/rockchip/functions/uvc.gs6/" \
"streaming_maxpacket"
int enable_minilog;
int rk_mpi_uvc_log_level;
int app_quit;
int uvc_ir_cnt;
int uvc_rgb_cnt;
static int (*camera_start_callback)(int id, int width, int height, int fps,
int format, int eptz);
static void (*camera_stop_callback)(int id);
uvc_pu_control_callback_t uvc_pu_control_cb = NULL;
struct uvc_ctrl {
int id;
bool start;
bool stop;
int width;
int height;
int fps;
int format;
int eptz;
int suspend;
struct uvc_function_config *fc;
};
static struct uvc_ctrl uvc_ctrl[CAM_MAX_NUM] = {
{.id = -1, .start = false, .stop = false, .width = -1, .height = -1, .fps = -1, .format = 1, .eptz = 0, .suspend = 0, .fc = NULL},
{.id = -1, .start = false, .stop = false, .width = -1, .height = -1, .fps = -1, .format = 1, .eptz = 0, .suspend = 0, .fc = NULL},
{.id = -1, .start = false, .stop = false, .width = -1, .height = -1, .fps = -1, .format = 1, .eptz = 0, .suspend = 0, .fc = NULL},
};
static std::map<int, UVC_CTRL_INFO> gUVCIdCtlInfoMap;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static int uvc_streaming_intf = -1;
static int uvc_streaming_maxpacket = 1024;
bool uvc_process_init_flag = false;
bool uvc_process_config_flag = false;
static pthread_t run_id = 0;
static bool uvc_restart = false;
static bool run_flag = true;
static uint32_t uvc_flags = UVC_CONTROL_CAMERA;
static pthread_mutex_t run_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t run_cond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t video_added = PTHREAD_COND_INITIALIZER;
static int32_t g_suspend;
static void query_uvc_streaming_maxpacket(void) {
int fd;
fd = open(UVC_STREAMING_MAXPACKET_PATH, O_RDONLY);
if (fd >= 0) {
char intf[32] = {0};
read(fd, intf, sizeof(intf) - 1);
uvc_streaming_maxpacket = atoi(intf);
if (uvc_streaming_maxpacket < 1023)
uvc_streaming_maxpacket = 1024;
LOG_DEBUG("uvc_streaming_maxpacket = %d\n", uvc_streaming_maxpacket);
close(fd);
} else {
LOG_ERROR("open %s failed!\n", UVC_STREAMING_MAXPACKET_PATH);
}
}
int get_uvc_streaming_maxpacket(void) { return uvc_streaming_maxpacket; }
static void query_uvc_streaming_intf(void) {
int fd;
fd = open(UVC_STREAMING_INTF_PATH, O_RDONLY);
if (fd >= 0) {
char intf[32] = {0};
read(fd, intf, sizeof(intf) - 1);
uvc_streaming_intf = atoi(intf);
LOG_DEBUG("uvc_streaming_intf = %d\n", uvc_streaming_intf);
close(fd);
} else {
LOG_ERROR("open %s failed!\n", UVC_STREAMING_INTF_PATH);
}
}
void register_uvc_pu_control_callback(uvc_pu_control_callback_t cb) {
uvc_pu_control_cb = cb;
}
void uvc_control_start_setcallback(int (*callback)(int fd, int width,
int height, int fps,
int format, int eptz)) {
camera_start_callback = callback;
}
void uvc_control_stop_setcallback(void (*callback)(int fd)) {
camera_stop_callback = callback;
}
static void get_uvc_index_to_name(unsigned int index, char *name) {
if (strstr(name, "depth") || strstr(name, "DEPTH") || strstr(name, "ir") ||
strstr(name, "IR")) {
uvc_ir_cnt = index;
LOG_DEBUG("uvc_ir_cnt = %d, name:%s\n", uvc_ir_cnt, name);
} else if (strstr(name, "rgb") || strstr(name, "RGB")) {
uvc_rgb_cnt = index;
LOG_DEBUG("uvc_rgb_cnt = %d, name:%s\n", uvc_rgb_cnt, name);
}
}
int check_uvc_video_id(void) {
bool find_dev = false;
struct uvc_function_config *fc[CAM_MAX_NUM] = {};
for (uint32_t i = 0; i < CAM_MAX_NUM; i++) {
fc[i] = configfs_parse_uvc_function(i);
if (fc[i]) {
get_uvc_index_to_name(fc[i]->index, fc[i]->dev_name);
uvc_ctrl[i].id = fc[i]->video;
uvc_ctrl[i].fc = fc[i];
find_dev = true;
LOG_DEBUG("uvc_function_config fc->video:%d,fc->streaming.num_formats:%d",
fc[i]->video, uvc_ctrl[i].fc->streaming.num_formats);
}
}
if (false == find_dev) {
LOG_WARN("Please configure uvc...\n");
return -1;
}
return 0;
}
void add_uvc_video() {
for (uint32_t i = 0; i < CAM_MAX_NUM; i++) {
if (uvc_ctrl[i].id >= 0) {
uvc_video_id_add(uvc_ctrl[i].fc);
LOG_INFO("uvc_ctrl:%u, id:%d, fc->video:%d\n",i , uvc_ctrl[i].id, uvc_ctrl[i].fc->video);
}
}
}
int uvc_control_loop(void) {
if (uvc_restart) {
// uvc_video_id_exit_all();
// add_uvc_video();
uvc_restart = false;
return 0;
}
unsigned int i;
for (i = 0; i < CAM_MAX_NUM; i++) {
if (uvc_ctrl[i].stop) {
if (camera_stop_callback)
camera_stop_callback(i);
uvc_ctrl[i].stop = false;
}
if (uvc_ctrl[i].start) {
LOG_INFO("%s: video_id:%d, width:%d,height:%d,fps:%d,format:%d,eptz:%d !\n",
__func__, uvc_ctrl[i].id, uvc_ctrl[i].width, uvc_ctrl[i].height,
uvc_ctrl[i].fps, uvc_ctrl[i].format, uvc_ctrl[i].eptz);
if (camera_start_callback) {
LOG_INFO("%s camera_start_callback start!\n", __func__);
camera_start_callback(i, uvc_ctrl[i].width, uvc_ctrl[i].height,
uvc_ctrl[i].fps, uvc_ctrl[i].format,
uvc_ctrl[i].eptz);
}
uvc_ctrl[i].start = false;
}
}
if (g_suspend) {
if (access("/tmp/uvc_no_suspend", 0)) {
sleep(5);
if (g_suspend) {
LOG_INFO("uvc ready to suspend...\n");
g_suspend = 0;
system("touch /tmp/uvc_goto_suspend");
}
}
}
return 1;
}
int uvc_control_run(uint32_t flags) {
uvc_ir_cnt = -1;
uvc_rgb_cnt = -1;
uvc_flags = flags;
if ((flags & UVC_CONTROL_CHECK_STRAIGHT) || (flags & UVC_CONTROL_CAMERA)) {
if (!check_uvc_video_id()) {
add_uvc_video();
}
}
return 0;
}
void set_uvc_control_suspend(int suspend) {
LOG_INFO("suspend is %d\n", suspend);
g_suspend = suspend;
if ((suspend == 0) && !access("/tmp/uvc_goto_suspend", 0))
system("rm /tmp/uvc_goto_suspend");
}
// TODO: use video id start uvc_ctrl
void set_uvc_control_start(int video_id, int width, int height, int fps,
int format, int eptz) {
LOG_DEBUG("%s: video_id:%d\n", __func__, video_id);
for (int i = 0; i < CAM_MAX_NUM; i++) {
if (uvc_ctrl[i].id == video_id) {
LOG_DEBUG("%s: camera:%d, video_id:%d, width:%d,height:%d,fps:%d,eptz:%d!\n",
__func__, i, video_id, width, height, fps, eptz);
uvc_ctrl[i].id = video_id;
uvc_ctrl[i].width = width;
uvc_ctrl[i].height = height;
uvc_ctrl[i].fps = fps;
uvc_ctrl[i].format = format;
uvc_ctrl[i].start = true;
uvc_ctrl[i].eptz = eptz;
}
}
}
// TODO: use video id stop uvc_ctrl
void set_uvc_control_stop(int video_id) {
LOG_INFO("%s:video_id:%d\n", __func__, video_id);
for (int i = 0; i < CAM_MAX_NUM; i++) {
if (uvc_ctrl[i].id == video_id)
uvc_ctrl[i].stop = true;
}
}
void set_uvc_control_restart(void) {
if (uvc_flags & UVC_CONTROL_CAMERA) {
LOG_INFO("received uvc to exit,restart to recovery now!\n");
// system("killall -9 uvc_app &");
uvc_restart = true;
}
}
UVC_CTRL_INFO uvc_find_uvc_ctrl_info_by_id(int id) {
for (std::map<int, UVC_CTRL_INFO>::iterator iter = gUVCIdCtlInfoMap.begin();
iter != gUVCIdCtlInfoMap.end(); ++iter) {
if (iter->first == id) {
LOG_DEBUG("index:%d find uvc_enc:%p by id:%d\n", iter->second.index,
&iter->second, id);
// iter->second.index = index;
return iter->second;
}
}
UVC_CTRL_INFO uvc_ctrl_info;
for (int i = 0; i < CAM_MAX_NUM; i++) {
if (uvc_ctrl[i].id == id)
uvc_ctrl_info.index = i;
}
// uvc_ctrl_info.index = gUVCIdCtlInfoMap.size();
gUVCIdCtlInfoMap.insert(std::map<int, UVC_CTRL_INFO>::value_type(id, uvc_ctrl_info));
LOG_INFO("index:%d new uvc_ctrl_info:%p by id:%d\n", uvc_ctrl_info.index,
&uvc_ctrl_info, id);
return uvc_ctrl_info;
}
void uvc_control_config(struct uvc_device *dev) {
pthread_mutex_lock(&lock);
UVC_CTRL_INFO uvc_ctrl_info = uvc_find_uvc_ctrl_info_by_id(dev->video_id);
uvc_ctrl_info.width = dev->width;
uvc_ctrl_info.height = dev->height;
uvc_ctrl_info.fcc = dev->fcc;
uvc_ctrl_info.fps = dev->fps;
uvc_ctrl_info.eptz[UVC_EPTZ_AUTO] = dev->eptz_flag; // read by cfg
uvc_ctrl_info.video_id = dev->video_id;
uvc_ctrl_info.eptz[UVC_EPTZ_ZOOM] = 10;
uvc_ctrl_info.eptz[UVC_EPTZ_PAN] = 0;
uvc_ctrl_info.eptz[UVC_EPTZ_TILT] = 0;
// camera_control_set_rate(uvc_ctrl_info.index, dev->fps);
dev->nbufs = uvc_process_config(uvc_ctrl_info);
if (dev->nbufs <= 0) {
LOG_ERROR("%s fail!\n", __func__);
abort();
}
LOG_INFO("uvc_enc->video_id:%d dev->nbufs:%d\n", uvc_ctrl_info.video_id,
dev->nbufs);
uvc_process_init_flag = true;
uvc_process_config_flag = true;
pthread_mutex_unlock(&lock);
}
void uvc_control_streamon(struct uvc_device *dev) {
pthread_mutex_lock(&lock);
UVC_CTRL_INFO uvc_ctrl_info = uvc_find_uvc_ctrl_info_by_id(dev->video_id);
uvc_ctrl_info.width = dev->width;
uvc_ctrl_info.height = dev->height;
uvc_ctrl_info.fcc = dev->fcc;
uvc_ctrl_info.fps = dev->fps;
uvc_ctrl_info.eptz[UVC_EPTZ_AUTO] = dev->eptz_flag;
uvc_ctrl_info.video_id = dev->video_id;
// uvc_ctrl_info->zoom = dev->zoom_val; // init have not zoom info
if (uvc_process_start(uvc_ctrl_info)) {
LOG_ERROR("%s fail!\n", __func__);
abort();
}
LOG_INFO("uvc_enc->video_id:%d", uvc_ctrl_info.video_id);
uvc_process_init_flag = true;
pthread_mutex_unlock(&lock);
}
void uvc_control_inbuf_deinit() {
pthread_mutex_lock(&lock);
// if(uvc_process_init_flag)
// uvc_encode_inbuf_deinit(&uvc_enc);
pthread_mutex_unlock(&lock);
}
void uvc_control_streamoff(int video_id) {
pthread_mutex_lock(&lock);
if (uvc_process_init_flag) {
UVC_CTRL_INFO uvc_ctrl_info = uvc_find_uvc_ctrl_info_by_id(video_id);
uvc_process_stop(uvc_ctrl_info);
}
uvc_process_init_flag = false;
pthread_mutex_unlock(&lock);
}
void uvc_control_delete(int video_id) {
pthread_mutex_lock(&lock);
if (uvc_process_config_flag) {
UVC_CTRL_INFO uvc_ctrl_info = uvc_find_uvc_ctrl_info_by_id(video_id);
uvc_process_delete(uvc_ctrl_info);
}
uvc_process_config_flag = false;
pthread_mutex_unlock(&lock);
}
void uvc_control_release_frame_nonlock(struct uvc_device *dev, void *frame) {
int ret = 0;
UVC_CTRL_INFO uvc_ctrl_info = uvc_find_uvc_ctrl_info_by_id(dev->video_id);
ret = uvc_process_release_frame(uvc_ctrl_info, frame);
if (ret < 0) {
LOG_ERROR("%s fail: %d!\n", __func__, ret);
abort();
}
}
void uvc_control_release_frame(struct uvc_device *dev, void *frame) {
pthread_mutex_lock(&lock);
uvc_control_release_frame_nonlock(dev, frame);
pthread_mutex_unlock(&lock);
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_CONTROL_H__
#define __UVC_CONTROL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "uvc_process_unit.h"
#include <stdint.h>
#ifdef USE_RK_MODULE
#define ISP_SEQ 1
#define ISP_FMT HAL_FRMAE_FMT_NV12
#define CIF_SEQ 0
#define CIF_FMT HAL_FRMAE_FMT_SBGGR10
#else
#define ISP_SEQ 0
#define ISP_FMT HAL_FRMAE_FMT_SBGGR8
#define CIF_SEQ 1
#define CIF_FMT HAL_FRMAE_FMT_NV12
#endif
#define UVC_CONTROL_LOOP_ONCE (1 << 0)
#define UVC_CONTROL_CHECK_STRAIGHT (1 << 1)
#define UVC_CONTROL_CAMERA (1 << 2)
extern int app_quit;
typedef void (*uvc_pu_control_callback_t)(unsigned char cs, unsigned int val);
void register_uvc_pu_control_callback(uvc_pu_control_callback_t cb);
extern uvc_pu_control_callback_t uvc_pu_control_cb;
void add_uvc_video();
int uvc_control_loop(void);
int check_uvc_video_id(void);
void set_uvc_control_start(int video_id, int width, int height, int fps,
int format, int eptz);
void set_uvc_control_stop(int video_id);
void set_uvc_control_restart(void);
void uvc_control_start_setcallback(int (*callback)(int id, int width,
int height, int fps,
int format, int eptz));
void uvc_control_stop_setcallback(void (*callback)(int id));
void uvc_control_config(struct uvc_device *dev);
void uvc_control_streamon(struct uvc_device *dev);
void uvc_control_streamoff(int video_id);
void uvc_control_delete(int video_id);
void uvc_control_inbuf_deinit();
int uvc_control_run(uint32_t flags);
void set_uvc_control_suspend(int suspend);
void uvc_control_release_frame(struct uvc_device *dev, void *frame);
void uvc_control_release_frame_nonlock(struct uvc_device *dev, void *frame);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,52 @@
#ifndef __UVC_IPC_EXT_H__
#define __UVC_IPC_EXT_H__
#ifdef __cplusplus
extern "C" {
#endif
#if DBUG
#define UVC_DYNAMIC_DEBUG_USE_TIME 1 // release version can set to 0
#define UVC_DYNAMIC_DEBUG_USE_TIME_CHECK "/tmp/uvc_use_time"
#else
#define UVC_DYNAMIC_DEBUG_USE_TIME 0
#endif
enum UVC_IPC_EVENT {
UVC_IPC_EVENT_START = 1,
UVC_IPC_EVENT_STOP = 2,
UVC_IPC_EVENT_ENABLE_ETPTZ = 3,
UVC_IPC_EVENT_SET_ZOOM = 4,
UVC_IPC_EVENT_RET_TRANSPORT_BUF = 5,
UVC_IPC_EVENT_CONFIG_CAMERA = 6,
UVC_IPC_EVENT_SET_EPTZ_PAN = 7,
UVC_IPC_EVENT_SET_EPTZ_TILT = 8,
UVC_IPC_EVENT_ENABLE_BYPASS = 9
};
enum UVC_IPC_ENC_TYPE {
UVC_IPC_ENC_YUV = 0,
UVC_IPC_ENC_MJPEG_NORMAL,
UVC_IPC_ENC_MJPEG_LOW_LATENCY,
UVC_IPC_ENC_H264,
UVC_IPC_ENC_H265
};
struct CAMERA_INFO {
int width;
int height;
int vir_width;
int vir_height;
int buf_size;
int range;
enum UVC_IPC_ENC_TYPE encode_type;
int uvc_fps_set;
};
extern void uvc_ipc_event(enum UVC_IPC_EVENT event, void *data);
extern void uvc_ipc_reconnect(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,91 @@
// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef _RK_LOGGER_H_
#define _RK_LOGGER_H_
#ifdef ENABLE_MINILOGGER
#include "minilogger/log.h"
#else
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#define minilog_warn(...)
#define minilog_error(...)
#define minilog_info(...)
#define minilog_debug(...)
#define __minilog_log_init(...)
#endif
extern int enable_minilog;
extern int rk_mpi_uvc_log_level;
#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_WARN 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_DEBUG 3
#ifndef LOG_TAG
#define LOG_TAG "rk_mpi_uvc"
#endif // LOG_TAG
//#define ENABLE_BUFFER_TIME_DEBUG
#define LOG_INFO(format, ...) \
do { \
if (rk_mpi_uvc_log_level < LOG_LEVEL_INFO) \
break; \
if (enable_minilog) \
minilog_info("[%s][%s]:" format, LOG_TAG, __FUNCTION__, ##__VA_ARGS__); \
else { \
struct timeval tv; \
gettimeofday(&tv, NULL); \
fprintf(stderr, "[%d.%06d][%s][%s][%d]:" format, tv.tv_sec, tv.tv_usec, \
LOG_TAG, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_WARN(format, ...) \
do { \
if (rk_mpi_uvc_log_level < LOG_LEVEL_WARN) \
break; \
if (enable_minilog) \
minilog_warn("[%s][%s]:" format, LOG_TAG, __FUNCTION__, ##__VA_ARGS__); \
else { \
struct timeval tv; \
gettimeofday(&tv, NULL); \
fprintf(stderr, "[%d.%06d][%s][%s][%d]:" format, tv.tv_sec, tv.tv_usec, \
LOG_TAG, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_ERROR(format, ...) \
do { \
if (rk_mpi_uvc_log_level < LOG_LEVEL_ERROR) \
break; \
if (enable_minilog) \
minilog_error("[%s][%s]:" format, LOG_TAG, __FUNCTION__, ##__VA_ARGS__); \
else { \
struct timeval tv; \
gettimeofday(&tv, NULL); \
fprintf(stderr, "[%d.%06d][%s][%s][%d]:" format, tv.tv_sec, tv.tv_usec, \
LOG_TAG, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_DEBUG(format, ...) \
do { \
if (rk_mpi_uvc_log_level < LOG_LEVEL_DEBUG) \
break; \
if (enable_minilog) \
minilog_debug("[%s][%s]:" format, LOG_TAG, __FUNCTION__, ##__VA_ARGS__); \
else { \
struct timeval tv; \
gettimeofday(&tv, NULL); \
fprintf(stderr, "[%d.%06d][%s][%s][%d]:" format, tv.tv_sec, tv.tv_usec, \
LOG_TAG, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,376 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_MPI_CONFIG_H__
#define __UVC_MPI_CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "rk_mpi_vi.h"
#include "rk_mpi_vpss.h"
#include <rk_mpi_venc.h>
#define UVC_MPI_CFG_CHANGE_BIT(x) (1 << x)
#define UVC_MPI_STREAM_SAVE_FILE_LEN 32
#define VPSS_MAX_CHN 1 // now only support one chn.
typedef enum _MpiUvcCommonCfgChange {
MPI_UVC_COMMON_CFG_NEED_CHECK = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_UVC_COMMON_CFG_UVC_DEBUG = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_UVC_COMMON_CFG_UVC_DEBUG_FILE_NAME = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_UVC_COMMON_CFG_UVC_DEBUG_FILE_CNT = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_UVC_COMMON_CFG_GEOMETRIC_OUT = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_UVC_COMMON_CFG_UVC_YUYV_DEBUG = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_UVC_COMMON_CFG_UVC_NN_ENABLE = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_UVC_COMMON_CFG_NN_DEBUG_FILE_NAME = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_UVC_COMMON_CFG_NN_DEBUG_FILE_CNT = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_UVC_COMMON_CFG_UVC_ENABLE_VPSS = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_UVC_COMMON_CFG_CHANGE_ALL = (0xffffffff),
} MpiUvcCommonCfgChange;
typedef enum _MpiViCfgChange {
MPI_VI_CFG_CHANGE_DEV_ID = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_VI_CFG_CHANGE_CHANNEL_ID = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_VI_CFG_CHANGE_BUF_CNT = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_VI_CFG_CHANGE_FBC = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_VI_CFG_CHANGE_MEMORY_TYPE = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_VI_CFG_CHANGE_ROTATION = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_VI_CFG_CHANGE_MIRROR = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_VI_CFG_CHANGE_DEV_NAME = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_VI_CFG_CHANGE_FPS = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_VI_CFG_CHANGE_ASSIGN_WIDTH = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_VI_CFG_CHANGE_ASSIGN_HEIGHT = UVC_MPI_CFG_CHANGE_BIT(10),
MPI_VI_CFG_CHANGE_MIN_WIDTH = UVC_MPI_CFG_CHANGE_BIT(11),
MPI_VI_CFG_CHANGE_MIN_HEIGHT = UVC_MPI_CFG_CHANGE_BIT(12),
MPI_VI_CFG_CHANGE_MAX_WIDTH = UVC_MPI_CFG_CHANGE_BIT(13),
MPI_VI_CFG_CHANGE_MAX_HEIGHT = UVC_MPI_CFG_CHANGE_BIT(14),
MPI_VI_CFG_CHANGE_FORMAT = UVC_MPI_CFG_CHANGE_BIT(15),
MPI_VI_CFG_CHANGE_ALL = (0xffffffff),
} MpiViCfgChange;
typedef enum _MpiVpssCfgChange {
MPI_VPSS_CFG_CHANGE_GROUP_ID = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_VPSS_CFG_CHANGE_CHANNEL_ID = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_VPSS_CFG_CHANGE_BUF_CNT = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_VPSS_CFG_CHANGE_FBC = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_VPSS_CFG_CHANGE_ROTATION = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_VPSS_CFG_CHANGE_MIRROR = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_VPSS_CFG_CHANGE_FPS = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_VPSS_CFG_CHANGE_FORMAT = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_VPSS_CFG_CHANGE_ASSIGN_WIDTH = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_VPSS_CFG_CHANGE_ASSIGN_HEIGHT = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_VPSS_CFG_CHANGE_ALL = (0xffffffff),
} MpiVpssCfgChange;
typedef enum _MpiVencCommonCfgChange {
MPI_VENC_COMMON_CFG_CHANGE_CREATE = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_VENC_COMMON_CFG_CHANGE_ROTATION = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_VENC_COMMON_CFG_CHANGE_MIRROR = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_VENC_COMMON_CFG_CHANGE_CHN_ATTR = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_VENC_COMMON_CFG_CHANGE_ALL = (0xffffffff),
} MpiVencCommonCfgChange;
typedef enum _MpiVencMjpegCfgChange {
MPI_VENC_MJPEG_CFG_CHANGE_RC_MODE = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_VENC_MJPEG_CFG_CHANGE_QFACTOR = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_VENC_MJPEG_CFG_CHANGE_QFACTOR_MIN = UVC_MPI_CFG_CHANGE_BIT(2), // reserver
MPI_VENC_MJPEG_CFG_CHANGE_QFACTOR_MAX = UVC_MPI_CFG_CHANGE_BIT(3), // reserver
MPI_VENC_MJPEG_CFG_CHANGE_BPS = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_VENC_MJPEG_CFG_CHANGE_FPS = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_VENC_MJPEG_CFG_CHANGE_BUF_CNT = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_VENC_MJPEG_CFG_CHANGE_SEI = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_VENC_MJPEG_CFG_CHANGE_RANGE = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_VENC_MJPEG_CFG_CHANGE_FBC = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_VENC_MJPEG_CFG_CHANGE_ALL = (0xffffffff),
} MpiVencMjpegCfgChange;
typedef enum _MpiVencH264CfgChange {
MPI_VENC_H264_CFG_CHANGE_GOP = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_VENC_H264_CFG_CHANGE_RC_MODE = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_VENC_H264_CFG_CHANGE_BPS = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_VENC_H264_CFG_CHANGE_GOP_MODE = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_VENC_H264_CFG_CHANGE_VI_LEN = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_VENC_H264_CFG_CHANGE_FPS = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_VENC_H264_CFG_CHANGE_BUF_CNT = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_VENC_H264_CFG_CHANGE_RANGE = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_VENC_H264_CFG_CHANGE_SEI = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_VENC_H264_CFG_CHANGE_PROFILE = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_VENC_H264_CFG_CHANGE_FBC = UVC_MPI_CFG_CHANGE_BIT(10),
MPI_VENC_H264_CFG_CHANGE_QP = UVC_MPI_CFG_CHANGE_BIT(11),
MPI_VENC_H264_CFG_CHANGE_ALL = (0xffffffff),
} MpiVencH264CfgChange;
typedef enum _MpiVencH265CfgChange {
MPI_VENC_H265_CFG_CHANGE_GOP = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_VENC_H265_CFG_CHANGE_RC_MODE = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_VENC_H265_CFG_CHANGE_BPS = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_VENC_H265_CFG_CHANGE_GOP_MODE = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_VENC_H265_CFG_CHANGE_VI_LEN = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_VENC_H265_CFG_CHANGE_FPS = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_VENC_H265_CFG_CHANGE_BUF_CNT = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_VENC_H265_CFG_CHANGE_RANGE = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_VENC_H265_CFG_CHANGE_SEI = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_VENC_H265_CFG_CHANGE_PROFILE = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_VENC_H265_CFG_CHANGE_FBC = UVC_MPI_CFG_CHANGE_BIT(10),
MPI_VENC_H265_CFG_CHANGE_QP = UVC_MPI_CFG_CHANGE_BIT(11),
MPI_VENC_H265_CFG_CHANGE_ALL = (0xffffffff),
} MpiVencH265CfgChange;
typedef enum _MpiEptzCfgChange {
MPI_EPTZ_CFG_CHANGE_ENABLE_EPTZ = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_EPTZ_CFG_CHANGE_ENABLE_EPTZ_BOOT = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_EPTZ_CFG_CHANGE_ENABLE_DEBUG = UVC_MPI_CFG_CHANGE_BIT(2),
MPI_EPTZ_CFG_CHANGE_ALIGN = UVC_MPI_CFG_CHANGE_BIT(3),
MPI_EPTZ_CFG_CHANGE_ZOOM_SPEED = UVC_MPI_CFG_CHANGE_BIT(4),
MPI_EPTZ_CFG_CHANGE_FAST_MOVE_FRAME_JUDGE = UVC_MPI_CFG_CHANGE_BIT(5),
MPI_EPTZ_CFG_CHANGE_ZOOM_FRAME_JUDGE = UVC_MPI_CFG_CHANGE_BIT(6),
MPI_EPTZ_CFG_CHANGE_ITERATE_X = UVC_MPI_CFG_CHANGE_BIT(7),
MPI_EPTZ_CFG_CHANGE_ITERATE_Y = UVC_MPI_CFG_CHANGE_BIT(8),
MPI_EPTZ_CFG_CHANGE_RATIO = UVC_MPI_CFG_CHANGE_BIT(9),
MPI_EPTZ_CFG_CHANGE_ALL = (0xffffffff),
} MpiEptzCfgChange;
typedef enum _MpiOsdCfgChange {
MPI_OSD_CFG_CHANGE_ENABLE_OSD = UVC_MPI_CFG_CHANGE_BIT(0),
MPI_OSD_CFG_CHANGE_FORCE_USE_VPSS = UVC_MPI_CFG_CHANGE_BIT(1),
MPI_OSD_CFG_CHANGE_ALL = (0xffffffff),
} MpiOsdCfgChange;
typedef enum _MpiViChannelType {
MPI_VI_CHANNEL_TYPE_UVC = 0,
MPI_VI_CHANNEL_TYPE_NN = 1,
MPI_VI_CHANNEL_TYPE_MAX = 2,
} MpiViChannelType;
typedef enum _MpiVpssChannelType {
MPI_VPSS_CHANNEL_TYPE_UVC = 0,
MPI_VPSS_CHANNEL_TYPE_NN = 1,
MPI_VPSS_CHANNEL_TYPE_MAX = 2,
} MpiVpssChannelType;
typedef struct {
RK_U32 change;
RK_U32 channel_id;
// idr begin
RK_U32 idr_gop;
RK_U32 idr_cnt;
RK_U32 idr_bps;
RK_U32 normal_gop;
RK_U32 normal_bps;
// idr end
RK_U32 enable_vpss;
ROTATION_E rotation;
MIRROR_E mirror;
} MpiVencCommonCfg;
typedef struct {
RK_U32 change;
RK_U32 qfactor_min;
RK_U32 qfactor_max;
RK_U32 range_full;
RK_U32 bps;
RK_U32 sei;
RK_U32 buf_cnt;
RK_S32 fps_in;
RK_S32 fps_out;
COMPRESS_MODE_E fbc;
VENC_RC_MODE_E rc_mode;
VENC_RC_PARAM_S qp;
} MpiVencMjpegCfg;
typedef struct {
RK_U32 change;
RK_U32 gop;
RK_U32 range_full;
RK_U32 sei;
RK_U32 profile;
RK_U32 bps;
RK_U32 buf_cnt;
RK_S32 fps_in;
RK_S32 fps_out;
COMPRESS_MODE_E fbc;
VENC_RC_MODE_E rc_mode;
VENC_RC_PARAM_S qp;
VENC_GOP_ATTR_S gop_mode;
} MpiVencH264Cfg;
typedef struct {
RK_U32 change;
RK_U32 gop;
RK_U32 range_full;
RK_U32 sei;
RK_U32 profile;
RK_U32 bps;
RK_U32 buf_cnt;
RK_S32 fps_in;
RK_S32 fps_out;
COMPRESS_MODE_E fbc;
VENC_RC_MODE_E rc_mode;
VENC_RC_PARAM_S qp;
VENC_GOP_ATTR_S gop_mode;
} MpiVencH265Cfg;
#if 0
#define MPP_ENC_OSD_IMAGE_PATH_LEN 32
typedef struct {
bool set_ok;
bool enable; //dynamic on/off set this
enum OSD_REGION_TYPE type;
RK_U32 start_x;
RK_U32 start_y;
char image_path[MPP_ENC_OSD_IMAGE_PATH_LEN];//*image_path;//
// for mjpeg rga osd
RK_U32 width;
RK_U32 height;
int rga_osd_fd;
unsigned int handle; // for drm handle
uint8_t *buffer;
int drm_size;
// for mjpeg rga osd
} MpiEncOSDCfg;
#endif
typedef struct {
RK_U32 version;
MpiVencCommonCfg common_cfg;
MpiVencMjpegCfg mjpeg_cfg;
MpiVencH264Cfg h264_cfg;
MpiVencH265Cfg h265_cfg;
} MpiVencCfg;
typedef struct {
RK_U32 version;
RK_U32 change;
RK_U32 dev_id;
RK_U32 channel_id;
RK_U32 buf_cnt;
RK_U32 assign_width;
RK_U32 assign_height;
RK_U32 min_width;
RK_U32 min_height;
RK_U32 max_width;
RK_U32 max_height;
RK_S32 fps_in;
RK_S32 fps_out;
PIXEL_FORMAT_E format;
COMPRESS_MODE_E fbc;
VI_V4L2_MEMORY_TYPE memory_type;
ROTATION_E rotation;
MIRROR_E mirror;
RK_CHAR dev_name[MAX_VI_ENTITY_NAME_LEN];
} MpiViCfg;
typedef struct {
RK_U32 version;
RK_U32 change;
RK_U32 group_id;
RK_U32 channel_id;
RK_U32 buf_cnt;
RK_S32 fps_in;
RK_S32 fps_out;
RK_U32 assign_width;
RK_U32 assign_height;
PIXEL_FORMAT_E format;
COMPRESS_MODE_E fbc;
ROTATION_E rotation;
MIRROR_E mirror;
} MpiVpssCfg;
typedef struct {
RK_U32 version;
RK_U32 change;
RK_U32 need_check;
RK_U32 uvc_debug_cnt;
RK_U32 nn_debug_cnt;
RK_U32 uvc_debug;
RK_U32 yuyv_debug;
RK_U32 nn_enable;
RK_U32 geometric_output_num;
RK_U32 geometric_output_den;
RK_U32 uvc_enable_vpss;
RK_U32 eptz_enable;
RK_U32 eptz_enable_boot;
RK_CHAR uvc_debug_file[UVC_MPI_STREAM_SAVE_FILE_LEN];
RK_CHAR nn_debug_file[UVC_MPI_STREAM_SAVE_FILE_LEN];
} MpiUvcCommonCfg;
typedef struct {
RK_U32 version;
RK_U32 change;
RK_U32 enable;
RK_U32 enable_boot;
RK_U32 debug;
RK_S32 align;
RK_S32 zoom_speed;
RK_S32 fast_move_frame_judge;
RK_S32 zoom_frame_judge;
RK_S32 iterate_x;
RK_S32 iterate_y;
RK_FLOAT ratio;
} MpiUvcEptzCfg;
typedef struct {
RK_U32 version;
RK_U32 change;
RK_U32 enable;
RK_U32 force_use_vpss;
} MpiOsdCfg;
typedef struct {
RK_S32 width;
RK_S32 height;
RK_S32 fcc;
RK_U32 fps;
} MpiUvcCfg;
typedef struct _rkUvcMpiCfg {
RK_U32 index;
RK_U32 version;
MpiUvcCfg uvc_cfg; // for uvc setting
MpiUvcCommonCfg common_cfg;
MpiUvcEptzCfg eptz_cfg;
MpiOsdCfg osd_cfg;
MpiViCfg vi_cfg[MPI_VI_CHANNEL_TYPE_MAX];
MpiVpssCfg vpss_cfg[MPI_VPSS_CHANNEL_TYPE_MAX];
MpiVencCfg venc_cfg;
} UVC_MPI_CFG;
int check_uvc_mpi_cfg_file_init(UVC_MPI_CFG *cfg);
void uvc_mpi_cfg_set_default(UVC_MPI_CFG *mpiCfg);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,528 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "uvc_mpi_venc.h"
#include "rk_mpi_sys.h"
#include "uvc_log.h"
#include "uvc_video.h"
#include <cstring>
// config
static RK_S32 venc_set_gopsize(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32GopSize);
static RK_S32 venc_set_bitrate(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32BitRate);
static RK_S32 venc_set_framerate(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32FpsIn,
RK_U32 u32FpsOut);
static RK_S32 venc_set_fixqp(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32FixIQp,
RK_U32 u32FixPQp, RK_U32 u32FixBQp);
static RK_S32 venc_set_qp(VENC_RC_ATTR_S *pRcAttr, VENC_RC_PARAM_S qp);
static RK_S32 config_venc_chn_attr(UVC_MPI_CFG uvcCfg);
static RK_S32 config_venc_rc_param(UVC_MPI_CFG uvcCfg);
UVC_VENC_CHN_CTX_S uvc_get_venc_chn_ctx(UVC_MPI_CFG uvcCfg) {
UVC_VENC_CHN_CTX_S vencChnCtx;
memset(&vencChnCtx, 0, sizeof(UVC_VENC_CHN_CTX_S));
vencChnCtx.devId = 0;
vencChnCtx.channelId = uvcCfg.venc_cfg.common_cfg.channel_id;
return vencChnCtx;
}
static void set_venc_mjpeg_attr(VENC_CHN_ATTR_S *vencAttr, UVC_MPI_CFG uvcCfg) {
vencAttr->stVencAttr.enType = RK_VIDEO_ID_MJPEG;
vencAttr->stVencAttr.u32StreamBufCnt = uvcCfg.venc_cfg.mjpeg_cfg.buf_cnt;
vencAttr->stRcAttr.enRcMode = uvcCfg.venc_cfg.mjpeg_cfg.rc_mode;
venc_set_bitrate(&vencAttr->stRcAttr, uvcCfg.venc_cfg.mjpeg_cfg.bps);
venc_set_framerate(&vencAttr->stRcAttr, uvcCfg.venc_cfg.mjpeg_cfg.fps_in,
uvcCfg.venc_cfg.mjpeg_cfg.fps_out);
venc_set_qp(&vencAttr->stRcAttr, uvcCfg.venc_cfg.mjpeg_cfg.qp);
}
static void set_venc_h264_attr(VENC_CHN_ATTR_S *vencAttr, UVC_MPI_CFG uvcCfg) {
vencAttr->stVencAttr.enType = RK_VIDEO_ID_AVC;
vencAttr->stVencAttr.u32Profile = uvcCfg.venc_cfg.h264_cfg.profile;
vencAttr->stVencAttr.u32StreamBufCnt = uvcCfg.venc_cfg.h264_cfg.buf_cnt;
vencAttr->stRcAttr.enRcMode = uvcCfg.venc_cfg.h264_cfg.rc_mode;
vencAttr->stGopAttr = uvcCfg.venc_cfg.h264_cfg.gop_mode;
venc_set_gopsize(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h264_cfg.gop);
venc_set_bitrate(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h264_cfg.bps);
venc_set_framerate(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h264_cfg.fps_in,
uvcCfg.venc_cfg.h264_cfg.fps_out);
venc_set_qp(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h264_cfg.qp);
LOG_INFO("venc gop:%d bps:%d\n", uvcCfg.venc_cfg.h264_cfg.gop,
uvcCfg.venc_cfg.h264_cfg.bps);
}
static void set_venc_h265_attr(VENC_CHN_ATTR_S *vencAttr, UVC_MPI_CFG uvcCfg) {
vencAttr->stVencAttr.enType = RK_VIDEO_ID_HEVC;
vencAttr->stVencAttr.u32Profile = uvcCfg.venc_cfg.h265_cfg.profile;
vencAttr->stVencAttr.u32StreamBufCnt = uvcCfg.venc_cfg.h265_cfg.buf_cnt;
vencAttr->stRcAttr.enRcMode = uvcCfg.venc_cfg.h265_cfg.rc_mode;
vencAttr->stGopAttr = uvcCfg.venc_cfg.h265_cfg.gop_mode;
venc_set_gopsize(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h265_cfg.gop);
venc_set_bitrate(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h265_cfg.bps);
venc_set_framerate(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h265_cfg.fps_in,
uvcCfg.venc_cfg.h265_cfg.fps_out);
venc_set_qp(&vencAttr->stRcAttr, uvcCfg.venc_cfg.h265_cfg.qp);
}
static VENC_CHN_ATTR_S get_venc_chn_attr(UVC_MPI_CFG uvcCfg) {
VENC_CHN_ATTR_S vencAttr;
memset(&vencAttr, 0, sizeof(VENC_CHN_ATTR_S));
switch (uvcCfg.uvc_cfg.fcc) {
case V4L2_PIX_FMT_MJPEG:
set_venc_mjpeg_attr(&vencAttr, uvcCfg);
break;
case V4L2_PIX_FMT_H264:
set_venc_h264_attr(&vencAttr, uvcCfg);
break;
case V4L2_PIX_FMT_H265:
set_venc_h265_attr(&vencAttr, uvcCfg);
break;
default:
LOG_ERROR("venc not support this fcc 0x%x\n", uvcCfg.uvc_cfg.fcc);
break;
}
vencAttr.stVencAttr.enPixelFormat = RK_FMT_YUV420SP;
vencAttr.stVencAttr.enMirror = uvcCfg.venc_cfg.common_cfg.mirror;
vencAttr.stVencAttr.u32PicWidth = uvcCfg.uvc_cfg.width;
vencAttr.stVencAttr.u32PicHeight = uvcCfg.uvc_cfg.height;
vencAttr.stVencAttr.u32VirWidth = uvcCfg.uvc_cfg.width;
vencAttr.stVencAttr.u32VirHeight = uvcCfg.uvc_cfg.height;
vencAttr.stVencAttr.u32BufSize =
uvcCfg.uvc_cfg.width * uvcCfg.uvc_cfg.height * 2;
return vencAttr;
}
static VENC_RC_PARAM_S get_venc_rc_param(UVC_MPI_CFG uvcCfg) {
VENC_RC_PARAM_S vencRcParam;
memset(&vencRcParam, 0, sizeof(VENC_RC_PARAM_S));
switch (uvcCfg.uvc_cfg.fcc) {
case V4L2_PIX_FMT_MJPEG:
vencRcParam = uvcCfg.venc_cfg.mjpeg_cfg.qp;
break;
case V4L2_PIX_FMT_H264:
vencRcParam = uvcCfg.venc_cfg.h264_cfg.qp;
break;
case V4L2_PIX_FMT_H265:
vencRcParam = uvcCfg.venc_cfg.h265_cfg.qp;
break;
default:
LOG_ERROR("venc not support this fcc 0x%x\n", uvcCfg.uvc_cfg.fcc);
break;
}
return vencRcParam;
}
static RK_S32 config_venc_chn_attr(UVC_MPI_CFG uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VENC_CHN_CTX_S vencChnCtx = uvc_get_venc_chn_ctx(uvcCfg);
VENC_CHN_ATTR_S vencAttr = get_venc_chn_attr(uvcCfg);
s32Ret = RK_MPI_VENC_SetChnAttr(vencChnCtx.channelId, &vencAttr);
return s32Ret;
}
static RK_S32 config_venc_rc_param(UVC_MPI_CFG uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VENC_CHN_CTX_S vencChnCtx = uvc_get_venc_chn_ctx(uvcCfg);
VENC_RC_PARAM_S vencRcParam = get_venc_rc_param(uvcCfg);
s32Ret = RK_MPI_VENC_SetRcParam(vencChnCtx.channelId, &vencRcParam);
return s32Ret;
}
static RK_S32 venc_set_bitrate(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32BitRate) {
switch (pRcAttr->enRcMode) {
case VENC_RC_MODE_MJPEGCBR:
pRcAttr->stMjpegCbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_H264CBR:
pRcAttr->stH264Cbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_H265CBR:
pRcAttr->stH265Cbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_MJPEGVBR:
pRcAttr->stMjpegVbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_H264VBR:
pRcAttr->stH264Vbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_H265VBR:
pRcAttr->stH265Vbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_H264AVBR:
pRcAttr->stH264Avbr.u32BitRate = u32BitRate;
break;
case VENC_RC_MODE_H265AVBR:
pRcAttr->stH265Avbr.u32BitRate = u32BitRate;
break;
default:
return RK_ERR_VENC_NOT_SUPPORT;
}
return RK_SUCCESS;
}
static RK_S32 venc_set_gopsize(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32GopSize) {
switch (pRcAttr->enRcMode) {
case VENC_RC_MODE_H264CBR:
pRcAttr->stH264Cbr.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H265CBR:
pRcAttr->stH265Cbr.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H264VBR:
pRcAttr->stH264Vbr.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H265VBR:
pRcAttr->stH265Vbr.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H264AVBR:
pRcAttr->stH264Avbr.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H265AVBR:
pRcAttr->stH265Avbr.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H264FIXQP:
pRcAttr->stH264FixQp.u32Gop = u32GopSize;
break;
case VENC_RC_MODE_H265FIXQP:
pRcAttr->stH265FixQp.u32Gop = u32GopSize;
break;
default:
return RK_ERR_VENC_NOT_SUPPORT;
}
return RK_SUCCESS;
}
static RK_S32 venc_set_framerate(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32FpsIn,
RK_U32 u32FpsOut) {
switch (pRcAttr->enRcMode) {
case VENC_RC_MODE_MJPEGCBR:
pRcAttr->stMjpegCbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stMjpegCbr.u32SrcFrameRateDen = 1;
pRcAttr->stMjpegCbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stMjpegCbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H264CBR:
pRcAttr->stH264Cbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH264Cbr.u32SrcFrameRateDen = 1;
pRcAttr->stH264Cbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH264Cbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H265CBR:
pRcAttr->stH265Cbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH265Cbr.u32SrcFrameRateDen = 1;
pRcAttr->stH265Cbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH265Cbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_MJPEGVBR:
pRcAttr->stMjpegVbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stMjpegVbr.u32SrcFrameRateDen = 1;
pRcAttr->stMjpegVbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stMjpegVbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H264VBR:
pRcAttr->stH264Vbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH264Vbr.u32SrcFrameRateDen = 1;
pRcAttr->stH264Vbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH264Vbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H265VBR:
pRcAttr->stH265Vbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH265Vbr.u32SrcFrameRateDen = 1;
pRcAttr->stH265Vbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH265Vbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H264AVBR:
pRcAttr->stH264Avbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH264Avbr.u32SrcFrameRateDen = 1;
pRcAttr->stH264Avbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH264Avbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H265AVBR:
pRcAttr->stH265Avbr.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH265Avbr.u32SrcFrameRateDen = 1;
pRcAttr->stH265Avbr.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH265Avbr.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_MJPEGFIXQP:
pRcAttr->stMjpegFixQp.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stMjpegFixQp.u32SrcFrameRateDen = 1;
pRcAttr->stMjpegFixQp.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stMjpegFixQp.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H264FIXQP:
pRcAttr->stH264FixQp.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH264FixQp.u32SrcFrameRateDen = 1;
pRcAttr->stH264FixQp.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH264FixQp.fr32DstFrameRateDen = 1;
break;
case VENC_RC_MODE_H265FIXQP:
pRcAttr->stH265FixQp.u32SrcFrameRateNum = u32FpsIn;
pRcAttr->stH265FixQp.u32SrcFrameRateDen = 1;
pRcAttr->stH265FixQp.fr32DstFrameRateNum = u32FpsOut;
pRcAttr->stH265FixQp.fr32DstFrameRateDen = 1;
break;
default:
return RK_ERR_VENC_NOT_SUPPORT;
}
return RK_SUCCESS;
}
static RK_S32 venc_set_fixqp(VENC_RC_ATTR_S *pRcAttr, RK_U32 u32FixIQp,
RK_U32 u32FixPQp, RK_U32 u32FixBQp) {
switch (pRcAttr->enRcMode) {
case VENC_RC_MODE_MJPEGFIXQP:
pRcAttr->stMjpegFixQp.u32Qfactor = u32FixIQp;
break;
case VENC_RC_MODE_H264FIXQP:
pRcAttr->stH264FixQp.u32IQp = u32FixIQp;
pRcAttr->stH264FixQp.u32PQp = u32FixPQp;
pRcAttr->stH264FixQp.u32BQp = u32FixBQp;
break;
case VENC_RC_MODE_H265FIXQP:
pRcAttr->stH265FixQp.u32IQp = u32FixIQp;
pRcAttr->stH265FixQp.u32PQp = u32FixPQp;
pRcAttr->stH265FixQp.u32BQp = u32FixBQp;
break;
default:
return RK_ERR_VENC_NOT_SUPPORT;
}
return RK_SUCCESS;
}
static RK_S32 venc_set_qp(VENC_RC_ATTR_S *pRcAttr, VENC_RC_PARAM_S qp) {
switch (pRcAttr->enRcMode) {
case VENC_RC_MODE_MJPEGFIXQP:
venc_set_fixqp(pRcAttr, qp.stParamMjpeg.u32Qfactor,
qp.stParamMjpeg.u32Qfactor, qp.stParamMjpeg.u32Qfactor);
break;
case VENC_RC_MODE_H264FIXQP:
venc_set_fixqp(pRcAttr, qp.stParamH264.u32MinIQp, qp.stParamH264.u32MinQp,
qp.stParamH264.u32MinQp);
break;
case VENC_RC_MODE_H265FIXQP:
venc_set_fixqp(pRcAttr, qp.stParamH265.u32MinIQp, qp.stParamH265.u32MinQp,
qp.stParamH265.u32MinQp);
break;
case VENC_RC_MODE_MJPEGCBR:
case VENC_RC_MODE_MJPEGVBR:
case VENC_RC_MODE_H264CBR:
case VENC_RC_MODE_H264VBR:
case VENC_RC_MODE_H264AVBR:
case VENC_RC_MODE_H265CBR:
case VENC_RC_MODE_H265VBR:
case VENC_RC_MODE_H265AVBR:
// just call RK_MPI_VENC_SetRcParam
break;
default:
return RK_ERR_VENC_NOT_SUPPORT;
}
return RK_SUCCESS;
}
static RK_S32 config_venc_common(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VENC_CHN_CTX_S vencChnCtx = uvc_get_venc_chn_ctx(*uvcCfg);
if (uvcCfg->venc_cfg.common_cfg.change & MPI_VENC_COMMON_CFG_CHANGE_CREATE) {
VENC_CHN_ATTR_S vencAttr = get_venc_chn_attr(*uvcCfg);
s32Ret = RK_MPI_VENC_CreateChn(vencChnCtx.channelId, &vencAttr);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_CreateChn fail 0x%x\n", s32Ret);
goto __FAILED;
} else {
LOG_INFO("RK_MPI_VENC_CreateChn %d\n", vencChnCtx.channelId);
}
uvcCfg->venc_cfg.common_cfg.change &= (~MPI_VENC_COMMON_CFG_CHANGE_CREATE);
uvcCfg->venc_cfg.common_cfg.change &=
(~MPI_VENC_COMMON_CFG_CHANGE_CHN_ATTR);
} else {
if (uvcCfg->venc_cfg.common_cfg.change &
MPI_VENC_COMMON_CFG_CHANGE_CHN_ATTR) {
s32Ret = config_venc_chn_attr(*uvcCfg);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("config_venc_chn_attr fail 0x%x\n", s32Ret);
goto __FAILED;
} else {
LOG_INFO("config_venc_chn_attr %d\n", vencChnCtx.channelId);
}
uvcCfg->venc_cfg.common_cfg.change &=
(~MPI_VENC_COMMON_CFG_CHANGE_CHN_ATTR);
}
}
if (uvcCfg->venc_cfg.common_cfg.change &
MPI_VENC_COMMON_CFG_CHANGE_ROTATION) {
s32Ret = RK_MPI_VENC_SetChnRotation(vencChnCtx.channelId,
uvcCfg->venc_cfg.common_cfg.rotation);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_CreateChn fail 0x%x\n", s32Ret);
goto __FAILED;
}
uvcCfg->venc_cfg.common_cfg.change &=
(~MPI_VENC_COMMON_CFG_CHANGE_ROTATION);
}
__FAILED:
return s32Ret;
}
static RK_S32 config_venc_mjpeg(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
if (uvcCfg->venc_cfg.mjpeg_cfg.change & MPI_VENC_MJPEG_CFG_CHANGE_QFACTOR) {
s32Ret = config_venc_rc_param(*uvcCfg);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_CreateChn fail 0x%x\n", s32Ret);
goto __FAILED;
}
uvcCfg->venc_cfg.mjpeg_cfg.change &= (~MPI_VENC_MJPEG_CFG_CHANGE_QFACTOR);
}
__FAILED:
return s32Ret;
}
static RK_S32 config_venc_h264(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
if (uvcCfg->venc_cfg.h264_cfg.change & MPI_VENC_H264_CFG_CHANGE_QP) {
s32Ret = config_venc_rc_param(*uvcCfg);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_CreateChn fail 0x%x\n", s32Ret);
goto __FAILED;
}
uvcCfg->venc_cfg.h264_cfg.change &= (~MPI_VENC_H264_CFG_CHANGE_QP);
}
__FAILED:
return s32Ret;
}
static RK_S32 config_venc_h265(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
if (uvcCfg->venc_cfg.h265_cfg.change & MPI_VENC_H265_CFG_CHANGE_QP) {
s32Ret = config_venc_rc_param(*uvcCfg);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_CreateChn fail 0x%x\n", s32Ret);
goto __FAILED;
}
uvcCfg->venc_cfg.h265_cfg.change &= (~MPI_VENC_H265_CFG_CHANGE_QP);
}
__FAILED:
return s32Ret;
}
RK_S32 uvc_venc_config(UVC_MPI_CFG *uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
config_venc_common(uvcCfg);
switch (uvcCfg->uvc_cfg.fcc) {
case V4L2_PIX_FMT_MJPEG:
config_venc_mjpeg(uvcCfg);
break;
case V4L2_PIX_FMT_H264:
config_venc_h264(uvcCfg);
break;
case V4L2_PIX_FMT_H265:
config_venc_h265(uvcCfg);
break;
default:
LOG_ERROR("venc not support this fcc 0x%x\n", uvcCfg->uvc_cfg.fcc);
break;
}
__FAILED:
return s32Ret;
}
RK_S32 uvc_venc_start(UVC_MPI_CFG uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
VENC_RECV_PIC_PARAM_S stRecvParam;
UVC_VENC_CHN_CTX_S vencChnCtx = uvc_get_venc_chn_ctx(uvcCfg);
stRecvParam.s32RecvPicNum = -1;
LOG_INFO("RK_MPI_VENC_StartRecvFrame %d\n", vencChnCtx.channelId);
s32Ret = RK_MPI_VENC_StartRecvFrame(vencChnCtx.channelId, &stRecvParam);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_StartRecvFrame fail 0x%x\n", s32Ret);
goto __FAILED;
}
__FAILED:
return s32Ret;
}
RK_S32 uvc_venc_stop(UVC_MPI_CFG uvcCfg) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VENC_CHN_CTX_S vencChnCtx = uvc_get_venc_chn_ctx(uvcCfg);
s32Ret = RK_MPI_VENC_StopRecvFrame(vencChnCtx.channelId);
if (s32Ret != RK_SUCCESS) {
return s32Ret;
}
LOG_INFO("reset enc chn:%d\n", vencChnCtx.channelId);
s32Ret = RK_MPI_VENC_ResetChn(vencChnCtx.channelId);
if (s32Ret != RK_SUCCESS) {
return s32Ret;
}
LOG_INFO("destroy enc chn:%d\n", vencChnCtx.channelId);
s32Ret = RK_MPI_VENC_DestroyChn(vencChnCtx.channelId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VDEC_DestroyChn :%d fail %x", vencChnCtx.channelId,
s32Ret);
}
__FAILED:
return s32Ret;
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_MPI_VENC_H__
#define __UVC_MPI_VENC_H__
#include "rk_mpi_venc.h"
#include "uvc_mpi_config.h"
typedef struct _uvcVencChnCtx {
RK_S32 devId;
RK_S32 channelId;
} UVC_VENC_CHN_CTX_S;
UVC_VENC_CHN_CTX_S uvc_get_venc_chn_ctx(UVC_MPI_CFG uvcCfg);
RK_S32 uvc_venc_config(UVC_MPI_CFG *uvcCfg);
RK_S32 uvc_venc_start(UVC_MPI_CFG uvcCfg);
RK_S32 uvc_venc_stop(UVC_MPI_CFG uvcCfg);
#endif

View File

@@ -0,0 +1,259 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "uvc_mpi_vi.h"
#include "rk_mpi_sys.h"
#include "rk_mpi_vi.h"
#include "uvc_log.h"
#include "uvc_video.h"
#include <cstring>
typedef struct _rkMpiVICtx {
UVC_VI_CHN_CTX_S stChnCtx;
COMPRESS_MODE_E enCompressMode;
VI_DEV_ATTR_S stDevAttr;
VI_DEV_BIND_PIPE_S stBindPipe;
VI_CHN_ATTR_S stChnAttr;
VI_CHN_STATUS_S stChnStatus;
} MPI_VI_CTX_S;
UVC_VI_CHN_CTX_S uvc_get_vi_chn_ctx(UVC_MPI_CFG uvcCfg,
MpiViChannelType chnType) {
UVC_VI_CHN_CTX_S viChnCtx;
memset(&viChnCtx, 0, sizeof(UVC_VI_CHN_CTX_S));
viChnCtx.devId = uvcCfg.vi_cfg[chnType].dev_id;
viChnCtx.pipeId = viChnCtx.devId;
viChnCtx.channelId = uvcCfg.vi_cfg[chnType].channel_id;
return viChnCtx;
}
static MPI_VI_CTX_S uvc_get_vi_ctx(UVC_MPI_CFG *uvcCfg,
MpiViChannelType chnType) {
MPI_VI_CTX_S viCtx;
memset(&viCtx, 0, sizeof(MPI_VI_CTX_S));
LOG_INFO("chnType:%d uvc out:%dx%d, vi assign_resolution:%dx%d vi_name:%s\n",
chnType, uvcCfg->uvc_cfg.width, uvcCfg->uvc_cfg.height,
uvcCfg->vi_cfg[chnType].assign_width,
uvcCfg->vi_cfg[chnType].assign_height,
uvcCfg->vi_cfg[chnType].dev_name);
// this is for uvc vi/nn vi different cfg.
switch (chnType) {
case MPI_VI_CHANNEL_TYPE_UVC:
if (uvcCfg->vi_cfg[chnType].assign_width <= 0 ||
uvcCfg->vi_cfg[chnType].assign_height <=
0) { // not assign the vi uvc output
if (uvcCfg->uvc_cfg.width < uvcCfg->vi_cfg[chnType].min_width ||
uvcCfg->uvc_cfg.height <
uvcCfg->vi_cfg[chnType]
.min_height) { // not support this resolution(too small)
uvcCfg->vi_cfg[chnType].assign_width =
uvcCfg->vi_cfg[chnType].min_width;
uvcCfg->vi_cfg[chnType].assign_height =
uvcCfg->vi_cfg[chnType].min_height;
LOG_INFO("uvc out:%dx%d, the min resolution:%dx%d\n",
uvcCfg->uvc_cfg.width, uvcCfg->uvc_cfg.height,
uvcCfg->vi_cfg[chnType].min_width,
uvcCfg->vi_cfg[chnType].min_height);
} else if (uvcCfg->uvc_cfg.width > uvcCfg->vi_cfg[chnType].max_width ||
uvcCfg->uvc_cfg.height >
uvcCfg->vi_cfg[chnType].max_height) { // not support this
// resolution(too
// large)
uvcCfg->vi_cfg[chnType].assign_width =
uvcCfg->vi_cfg[chnType].max_width;
uvcCfg->vi_cfg[chnType].assign_height =
uvcCfg->vi_cfg[chnType].max_height;
LOG_INFO("uvc out:%dx%d, the max resolution:%dx%d\n",
uvcCfg->uvc_cfg.width, uvcCfg->uvc_cfg.height,
uvcCfg->vi_cfg[chnType].max_width,
uvcCfg->vi_cfg[chnType].max_height);
} else {
uvcCfg->vi_cfg[chnType].assign_width = uvcCfg->uvc_cfg.width;
uvcCfg->vi_cfg[chnType].assign_height = uvcCfg->uvc_cfg.height;
}
}
switch (uvcCfg->uvc_cfg.fcc) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_NV12: // reserver
#if 0
if (uvcCfg->uvc_cfg.width == 1280) {
LOG_ERROR("vi workaround and here alloc 1 buf count!!!\n");
uvcCfg->vi_cfg[chnType].buf_cnt =
1; // workaround for 1280*720 vpss stuck
}
#endif
viCtx.stChnAttr.enPixelFormat =
uvcCfg->vi_cfg[chnType].format; // RK_FMT_YUV422_YUYV;
viCtx.stChnAttr.u32Depth = 0; // viCtx.stChnAttr.stIspOpt.u32BufCount; //
// bind 0; not bind u32BufCount;
break;
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_H265:
viCtx.stChnAttr.enPixelFormat = RK_FMT_YUV420SP;
viCtx.stChnAttr.u32Depth = 0; // bind 0; not bind u32BufCount;
break;
default:
LOG_ERROR("vi not support this fcc 0x%x\n", uvcCfg->uvc_cfg.fcc);
break;
}
break;
case MPI_VI_CHANNEL_TYPE_NN:
viCtx.stChnAttr.enPixelFormat = uvcCfg->vi_cfg[chnType].format;
viCtx.stChnAttr.u32Depth = 0;
break;
default:
LOG_ERROR("vi not support this chnType 0x%x\n", chnType);
break;
}
// common cfg
viCtx.stChnCtx = uvc_get_vi_chn_ctx(*uvcCfg, chnType);
viCtx.stChnAttr.stIspOpt.bNoUseLibV4L2 = RK_FALSE;
viCtx.stChnAttr.stIspOpt.u32BufCount = uvcCfg->vi_cfg[chnType].buf_cnt;
viCtx.stChnAttr.stIspOpt.u32BufSize =
0; // uvcCfg.vi_cfg[chnType].width * uvcCfg.vi_cfg[chnType].height * 2;
// uvcCfg.uvc_cfg.width * uvcCfg.uvc_cfg.height;
viCtx.stChnAttr.stIspOpt.enMemoryType = uvcCfg->vi_cfg[chnType].memory_type;
if (strncmp(uvcCfg->vi_cfg[chnType].dev_name, "null", strlen("null"))) {
memcpy(viCtx.stChnAttr.stIspOpt.aEntityName,
uvcCfg->vi_cfg[chnType].dev_name,
strlen(uvcCfg->vi_cfg[chnType].dev_name));
}
viCtx.stChnAttr.stFrameRate.s32SrcFrameRate =
uvcCfg->vi_cfg[chnType].fps_in > 0 ? uvcCfg->vi_cfg[chnType].fps_in : -1;
viCtx.stChnAttr.stFrameRate.s32DstFrameRate =
uvcCfg->vi_cfg[chnType].fps_out > 0 ? uvcCfg->vi_cfg[chnType].fps_out
: -1;
viCtx.stChnAttr.stSize.u32Width = uvcCfg->vi_cfg[chnType].assign_width;
viCtx.stChnAttr.stSize.u32Height = uvcCfg->vi_cfg[chnType].assign_height;
LOG_INFO("chnType:%d uvc out:%dx%d, vi resolution:%dx%d name:%s\n", chnType,
uvcCfg->uvc_cfg.width, uvcCfg->uvc_cfg.height,
viCtx.stChnAttr.stSize.u32Width, viCtx.stChnAttr.stSize.u32Height,
viCtx.stChnAttr.stIspOpt.aEntityName);
return viCtx;
}
// todo: multi vi from cfg.
RK_S32 uvc_vi_config(UVC_MPI_CFG *uvcCfg, MpiViChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
MPI_VI_CTX_S ctx;
ctx = uvc_get_vi_ctx(uvcCfg, chnType);
// 0. get dev config status
s32Ret = RK_MPI_VI_GetDevAttr(ctx.stChnCtx.devId, &ctx.stDevAttr);
if (s32Ret == RK_ERR_VI_NOT_CONFIG) {
// 0-1.config dev
s32Ret = RK_MPI_VI_SetDevAttr(ctx.stChnCtx.devId, &ctx.stDevAttr);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_SetDevAttr %x\n", s32Ret);
goto __FAILED;
}
}
// 1.get dev enable status
s32Ret = RK_MPI_VI_GetDevIsEnable(ctx.stChnCtx.devId);
if (s32Ret != RK_SUCCESS) {
// 1-2.enable dev
s32Ret = RK_MPI_VI_EnableDev(ctx.stChnCtx.devId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_EnableDev %x\n", s32Ret);
goto __FAILED;
}
// 1-3.bind dev/pipe
ctx.stBindPipe.u32Num = ctx.stChnCtx.pipeId;
ctx.stBindPipe.PipeId[0] = ctx.stChnCtx.pipeId;
s32Ret = RK_MPI_VI_SetDevBindPipe(ctx.stChnCtx.devId, &ctx.stBindPipe);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_SetDevBindPipe %x\n", s32Ret);
goto __FAILED;
}
}
// 2.config channel
s32Ret = RK_MPI_VI_SetChnAttr(ctx.stChnCtx.pipeId, ctx.stChnCtx.channelId,
&ctx.stChnAttr);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_SetChnAttr %x\n", s32Ret);
goto __FAILED;
}
__FAILED:
return s32Ret;
}
RK_S32 uvc_vi_start(UVC_MPI_CFG uvcCfg, MpiViChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VI_CHN_CTX_S ctx;
ctx = uvc_get_vi_chn_ctx(uvcCfg, chnType);
// isp&aiq init here
// 3.enable channel
LOG_INFO("RK_MPI_VI_EnableChn %x %d %d\n", ctx.devId, ctx.pipeId,
ctx.channelId);
s32Ret = RK_MPI_VI_EnableChn(ctx.pipeId, ctx.channelId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_EnableChn %x\n", s32Ret);
goto __FAILED;
}
__FAILED:
return s32Ret;
}
RK_S32 uvc_vi_stop(UVC_MPI_CFG uvcCfg, MpiViChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VI_CHN_CTX_S ctx;
ctx = uvc_get_vi_chn_ctx(uvcCfg, chnType);
// 5. disable one chn
s32Ret = RK_MPI_VI_DisableChn(ctx.pipeId, ctx.channelId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_DisableChn %x\n", s32Ret);
goto __FAILED;
}
// 6.disable dev(will diabled all chn)
s32Ret = RK_MPI_VI_DisableDev(ctx.devId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VI_DisableDev %x\n", s32Ret);
goto __FAILED;
}
// isp&aiq deinit here
__FAILED:
return s32Ret;
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_MPI_VI_H__
#define __UVC_MPI_VI_H__
#include "uvc_mpi_config.h"
typedef struct _uvcViChnCtx {
RK_S32 devId;
RK_S32 pipeId;
RK_S32 channelId;
} UVC_VI_CHN_CTX_S;
RK_S32 uvc_vi_config(UVC_MPI_CFG *uvcCfg, MpiViChannelType chnType);
RK_S32 uvc_vi_start(UVC_MPI_CFG uvcCfg, MpiViChannelType chnType);
RK_S32 uvc_vi_stop(UVC_MPI_CFG uvcCfg, MpiViChannelType chnType);
UVC_VI_CHN_CTX_S uvc_get_vi_chn_ctx(UVC_MPI_CFG uvcCfg,
MpiViChannelType chnType);
#endif

View File

@@ -0,0 +1,215 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "uvc_mpi_vpss.h"
#include "rk_mpi_sys.h"
#include "rk_mpi_vpss.h"
#include "uvc_log.h"
#include "uvc_video.h"
#include <cstring>
typedef struct _rkVpssCfg {
RK_U32 u32VpssChnCnt;
VPSS_GRP_ATTR_S stGrpVpssAttr;
VPSS_CHN_ATTR_S stVpssChnAttr[VPSS_MAX_CHN_NUM];
} VPSS_CFG_S;
typedef struct _rkMpiVpssCtx {
UVC_VPSS_CHN_CTX_S stChnCtx;
VPSS_CFG_S stVpssCfg;
} MPI_VPSS_CTX_S;
UVC_VPSS_CHN_CTX_S uvc_get_vpss_chn_ctx(UVC_MPI_CFG uvcCfg,
MpiVpssChannelType chnType) {
UVC_VPSS_CHN_CTX_S vpssChnCtx;
memset(&vpssChnCtx, 0, sizeof(UVC_VPSS_CHN_CTX_S));
vpssChnCtx.group = uvcCfg.vpss_cfg[chnType].group_id;
vpssChnCtx.channelId = uvcCfg.vpss_cfg[chnType].channel_id;
return vpssChnCtx;
}
// todo: read cfg
static MPI_VPSS_CTX_S uvc_get_vpss_ctx(UVC_MPI_CFG uvcCfg,
MpiVpssChannelType chnType) {
MPI_VPSS_CTX_S vpssCtx;
PIXEL_FORMAT_E outFormat = RK_FMT_YUV420SP;
int chn = uvcCfg.vpss_cfg[chnType].channel_id;
memset(&vpssCtx, 0, sizeof(MPI_VPSS_CTX_S));
switch (chnType) {
case MPI_VPSS_CHANNEL_TYPE_UVC:
switch (uvcCfg.uvc_cfg.fcc) {
case V4L2_PIX_FMT_YUYV:
outFormat = RK_FMT_YUV422_YUYV;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Depth =
uvcCfg.vpss_cfg[chnType].buf_cnt;
break;
case V4L2_PIX_FMT_NV12:
outFormat = RK_FMT_YUV420SP;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Depth =
uvcCfg.vpss_cfg[chnType].buf_cnt;
break;
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_H265:
outFormat = RK_FMT_YUV420SP;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Depth = 0; // bind venc.
break;
default:
LOG_ERROR("vpss not support this fcc 0x%x\n", uvcCfg.uvc_cfg.fcc);
break;
}
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Width = uvcCfg.uvc_cfg.width;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Height = uvcCfg.uvc_cfg.height;
break;
case MPI_VPSS_CHANNEL_TYPE_NN:
outFormat = uvcCfg.vpss_cfg[chnType].format;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Width =
uvcCfg.vpss_cfg[chnType].assign_width;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Height =
uvcCfg.vpss_cfg[chnType].assign_height;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32Depth =
uvcCfg.vpss_cfg[chnType].buf_cnt;
break;
default:
LOG_ERROR("vpss not support this type 0x%x\n", chnType);
break;
}
vpssCtx.stChnCtx = uvc_get_vpss_chn_ctx(uvcCfg, chnType);
vpssCtx.stVpssCfg.stGrpVpssAttr.u32MaxW = 4096;
vpssCtx.stVpssCfg.stGrpVpssAttr.u32MaxH = 4096;
vpssCtx.stVpssCfg.stGrpVpssAttr.enPixelFormat = outFormat;
vpssCtx.stVpssCfg.stGrpVpssAttr.stFrameRate.s32SrcFrameRate =
uvcCfg.vpss_cfg[chnType].fps_in;
vpssCtx.stVpssCfg.stGrpVpssAttr.stFrameRate.s32DstFrameRate =
uvcCfg.vpss_cfg[chnType].fps_out;
vpssCtx.stVpssCfg.stGrpVpssAttr.enCompressMode = uvcCfg.vpss_cfg[chnType].fbc;
{ // chn
vpssCtx.stVpssCfg.stVpssChnAttr[chn].enChnMode = VPSS_CHN_MODE_USER;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].enDynamicRange = DYNAMIC_RANGE_SDR8;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].enPixelFormat = outFormat;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].stFrameRate.s32SrcFrameRate = -1;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].stFrameRate.s32DstFrameRate = -1;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].enCompressMode =
uvcCfg.vpss_cfg[chnType].fbc;
vpssCtx.stVpssCfg.stVpssChnAttr[chn].u32FrameBufCnt =
uvcCfg.vpss_cfg[chnType].buf_cnt;
}
return vpssCtx;
}
RK_S32 uvc_vpss_config(UVC_MPI_CFG *uvcCfg, MpiVpssChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
MPI_VPSS_CTX_S ctx;
ctx = uvc_get_vpss_ctx(*uvcCfg, chnType);
s32Ret =
RK_MPI_VPSS_CreateGrp(ctx.stChnCtx.group, &ctx.stVpssCfg.stGrpVpssAttr);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_CreateGrp fail 0x%x\n", s32Ret);
return s32Ret;
}
s32Ret = RK_MPI_VPSS_SetChnAttr(
ctx.stChnCtx.group, ctx.stChnCtx.channelId,
&ctx.stVpssCfg.stVpssChnAttr[ctx.stChnCtx.channelId]);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_SetChnAttr fail 0x%x\n", s32Ret);
return s32Ret;
}
return RK_SUCCESS;
}
// from the data.
RK_S32 uvc_vpss_config_crop(UVC_MPI_CFG uvcCfg, VPSS_CROP_INFO_S stCropInfo,
MpiVpssChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VPSS_CHN_CTX_S ctx;
ctx = uvc_get_vpss_chn_ctx(uvcCfg, chnType);
s32Ret = RK_MPI_VPSS_SetChnCrop(ctx.group, ctx.channelId, &stCropInfo);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_SetChnCrop fail 0x%x\n", s32Ret);
return s32Ret;
}
return RK_SUCCESS;
}
RK_S32 uvc_vpss_start(UVC_MPI_CFG uvcCfg, MpiVpssChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VPSS_CHN_CTX_S ctx;
ctx = uvc_get_vpss_chn_ctx(uvcCfg, chnType);
s32Ret = RK_MPI_VPSS_EnableChn(ctx.group, ctx.channelId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_EnableChn fail 0x%x\n", s32Ret);
return s32Ret;
}
s32Ret = RK_MPI_VPSS_StartGrp(ctx.group);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_StartGrp fail 0x%x\n", s32Ret);
return s32Ret;
}
return RK_SUCCESS;
}
RK_S32 uvc_vpss_stop(UVC_MPI_CFG uvcCfg, MpiVpssChannelType chnType) {
RK_S32 s32Ret = RK_FAILURE;
UVC_VPSS_CHN_CTX_S ctx;
ctx = uvc_get_vpss_chn_ctx(uvcCfg, chnType);
s32Ret = RK_MPI_VPSS_StopGrp(ctx.group);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_StopGrp fail 0x%x\n", s32Ret);
return s32Ret;
}
s32Ret = RK_MPI_VPSS_DisableChn(ctx.group, ctx.channelId);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_DisableChn fail 0x%x\n", s32Ret);
return s32Ret;
}
s32Ret = RK_MPI_VPSS_DestroyGrp(ctx.group);
if (s32Ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VPSS_DestroyGrp fail 0x%x\n", s32Ret);
return s32Ret;
}
return RK_SUCCESS;
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_MPI_VPSS_H__
#define __UVC_MPI_VPSS_H__
#include "uvc_mpi_config.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _uvcVpssChnCtx {
RK_S32 group;
RK_S32 channelId;
} UVC_VPSS_CHN_CTX_S;
RK_S32 uvc_vpss_config(UVC_MPI_CFG *uvcCfg, MpiVpssChannelType chnType);
RK_S32 uvc_vpss_config_crop(UVC_MPI_CFG uvcCfg, VPSS_CROP_INFO_S stCropInfo,
MpiVpssChannelType chnType);
RK_S32 uvc_vpss_start(UVC_MPI_CFG uvcCfg, MpiVpssChannelType chnType);
RK_S32 uvc_vpss_stop(UVC_MPI_CFG uvcCfg, MpiVpssChannelType chnType);
UVC_VPSS_CHN_CTX_S uvc_get_vpss_chn_ctx(UVC_MPI_CFG uvcCfg,
MpiVpssChannelType chnType);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_PROCESS_H__
#define __UVC_PROCESS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "rk_comm_video.h"
#include "uvc_process_unit.h"
#ifdef __cplusplus
}
#endif
class UVCProcess {
public:
explicit UVCProcess();
~UVCProcess();
void *getCtx() { return mCtx; }
int configProcess(UVC_CTRL_INFO uvc_ctrl_info);
int startProcess();
int stopProcess();
int doProcess();
int releaseFrame(void *frame);
private:
int initialize();
int deinitialize();
int configVi();
int startVi();
int stopVi();
int configVenc();
int startVenc();
int stopVenc();
int resetCtx();
int configVpss();
int configCropScale(RECT_S src, RECT_S dst);
int startVpss();
int stopVpss();
int bindViVenc();
int unBindViVenc();
int bindViVpss();
int unBindViVpss();
int bindVpssVenc();
int unBindVpssVenc();
static void *threadLoop(void *arg);
private:
void *mCtx;
};
#endif

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_PROCESS_UNIT_H__
#define __UVC_PROCESS_UNIT_H__
#ifdef __cplusplus
extern "C" {
#endif
#define CAM_MAX_NUM 3
typedef enum _UVC_EPTZ_TYPE {
UVC_EPTZ_ZOOM = 0,
UVC_EPTZ_PAN = 1,
UVC_EPTZ_TILT = 2,
UVC_EPTZ_ROLL = 3, // reserve
UVC_EPTZ_AUTO = 4,
UVC_EPTZ_MAX,
} UVC_EPTZ_TYPE;
typedef enum _UVC_RATIO_TYPE {
VERTICAL = 0,
HORIZONTAL = 1,
UVC_RATIO_MAX,
} UVC_RATIO_TYPE;
typedef enum _UVC_RET_TYPE {
UVC_RET_ERR = -1,
UVC_RET_OK = 0,
UVC_RET_WAT = 1,
UVC_RET_MAX,
} UVC_RET_TYPE;
typedef struct uvc_ctrl_info {
int index;
int width;
int height;
int video_id;
int fcc;
unsigned int fps;
UVC_EPTZ_TYPE type;
int eptz[UVC_EPTZ_MAX];
} UVC_CTRL_INFO;
int uvc_process_config(UVC_CTRL_INFO uvc_ctrl_info);
int uvc_process_start(UVC_CTRL_INFO uvc_ctrl_info);
void uvc_process_stop(UVC_CTRL_INFO uvc_ctrl_info);
void uvc_process_delete(UVC_CTRL_INFO uvcCtrlInfo);
int uvc_process_release_frame(UVC_CTRL_INFO uvcCtrlInfo, void *frame);
int nn_process_release_frame_by_id(int frameId);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL), available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __UVC_VIDEO_H__
#define __UVC_VIDEO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "uvc-gadget.h"
#include <linux/videodev2.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <unistd.h>
#define V4L2_PIX_FMT_H265 \
v4l2_fourcc('H', '2', '6', '5') /* H265 with start codes */
#define YUYV_AS_RAW 0
#define UVC_DYNAMIC_DEBUG_USE_TIME 1 // release version can set to 0
#define UVC_DYNAMIC_DEBUG_USE_TIME_CHECK "/tmp/uvc_use_time"
#define UVC_DYNAMIC_DEBUG_FPS 1 // release version can set to 0
#define UVC_DYNAMIC_DEBUG_ISP_FPS_CHECK "/tmp/uvc_isp_fps"
#define UVC_DYNAMIC_DEBUG_IPC_FPS_CHECK "/tmp/uvc_ipc_fps"
#if UVC_DYNAMIC_DEBUG_FPS
struct uvc_debug_info_def {
bool first_frm;
bool debug_isp_fps;
bool debug_ipc_fps;
float fps;
int ipc_frm;
int isp_frm;
struct timeval enter_time;
unsigned int stream_on_pts;
};
extern struct uvc_debug_info_def uvc_debug_info;
#endif
struct uvc_device;
struct uvc_buffer {
void *buffer;
size_t size; // encode out size
size_t total_size;
unsigned int offset;
int width;
int height;
int video_id;
int fd;
unsigned int pts;
unsigned int seq;
int index;
void *frame;
};
struct uvc_user {
unsigned int width;
unsigned int height;
bool run;
unsigned int fcc;
};
struct uvc_video {
int id;
bool uvc_process;
pthread_t uvc_pid;
struct video_uvc *uvc;
pthread_mutex_t buffer_mutex;
pthread_mutex_t user_mutex;
struct uvc_user uvc_user;
int uvc_buf_cnt;
int idle_cnt;
int drop_frame_cnt;
bool can_exit;
unsigned int last_pts;
unsigned int now_pts;
unsigned int last_seq;
struct uvc_device *dev;
};
int uvc_gadget_pthread_create(struct uvc_function_config *fc);
int uvc_video_id_check(int id);
int uvc_video_id_add(struct uvc_function_config *fc);
void uvc_video_id_remove(int id);
void uvc_video_id_exit_all();
int uvc_video_id_get(unsigned int seq);
void uvc_video_set_uvc_process(int id, bool state);
bool uvc_video_get_uvc_process(int id);
int uvc_buffer_init(struct uvc_device *dev);
void uvc_buffer_deinit(int id);
bool uvc_buffer_write_enable(int id);
void uvc_set_user_resolution(int width, int height, int id);
void uvc_get_user_resolution(int *width, int *height, int id);
bool uvc_get_user_run_state(int id);
void uvc_set_user_run_state(bool state, int id);
void uvc_set_user_fcc(unsigned int fcc, int id);
unsigned int uvc_get_user_fcc(int id);
void uvc_memset_uvc_user(int id);
pthread_t *uvc_video_get_uvc_pid(int id);
struct uvc_buffer *uvc_user_fill_buffer(struct uvc_device *dev,
struct v4l2_buffer *buf, int id);
struct uvc_buffer *uvc_get_enc_data(struct uvc_device *dev, struct uvc_video *v,
bool init);
int uvc_video_qbuf_index(struct uvc_device *dev, struct uvc_buffer *send_buf,
int index, int len);
void uvc_user_release_cache_buffer(struct uvc_device *dev,
struct v4l2_buffer *buf, int id);
bool uvc_buffer_read_enable(int id);
struct uvc_buffer *uvc_buffer_write_get(int id);
void uvc_buffer_write_set(int id, struct uvc_buffer *buf);
void uvc_buffer_read_set(int id, struct uvc_buffer *buf);
void uvc_buffer_cache_set(int id, struct uvc_buffer *buf);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,212 @@
{
"index_0": {
"version" : 1,
"common_cfg": {
"version" : 1,
"property" : {
"param_init": {
"check_param_change_thread": "off",
"uvc_debug": "off",
"yuyv_debug": "off",
"nn_enable": "off",
"uvc_debug_file_name": "/data/uvc.bin",
"uvc_debug_file_cnt": 0,
"nn_debug_file_name": "/data/nn.bin",
"nn_debug_file_cnt": 0,
"uvc_enable_vpss": "on",
"geometric_output": "16:9"
},
"param_change": {
}
}
},
"eptz_cfg": {
"version" : 1,
"param_init": {
"enable": "on",
"enable_boot": "off",
"debug": "off"
},
"param_change": {
}
},
"vi_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"dev_id": 0,
"channel_id": 1,
"buf_cnt": 1,
"assign_width": 0,
"assign_height": 0,
"min_width": 640,
"min_height": 480,
"max_width": 1920,
"max_height": 1080,
"format": "nv12",
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"dev_id": 0,
"channel_id": 1,
"assign_width": 512,
"assign_height": 288,
"format": "nv12",
"buf_cnt": 1,
"dev_name": "null",
"fps": "0:0",
"memory_type": 4,
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"vpss_cfg": {
"version" : 1,
"uvc" : {
"param_init": {
"group_id": 0,
"channel_id": 0,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"nn" : {
"param_init": {
"group_id": 1,
"channel_id": 0,
"format": "bgr888",
"assign_width": 512,
"assign_height": 288,
"buf_cnt": 1,
"fps": "0:0",
"fbc": "off",
"rotation": 0,
"mirror": 0
},
"param_change": {
}
}
},
"venc_cfg": {
"version" : 1,
"common" : {
"param_init": {
"channel_id": 1,
"rotation": 0,
"mirror": 0
},
"param_change": {
}
},
"mjpeg": {
"param_init": {
"default": {
"buf_cnt": 1,
"fbc": "off",
"rc_mode": "fixqp",
"fps": "0:0",
"range": "full",
"sei": "off",
"qfactor": 85,
"qfactor_min": 30,
"qfactor_max": 99,
"bps": 60000
},
"1280*720p30": {
"qfactor": 80,
"qfactor_min": 60,
"qfactor_max": 90,
"bps": 70000
},
"1920*1080p30": {
"qfactor": 75,
"qfactor_min": 50,
"qfactor_max": 90,
"bps": 80000
}
},
"param_change": {
}
},
"h264" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"profile": 100,
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
}
},
"param_change": {
}
},
"h265" : {
"param_init": {
"default": {
"buf_cnt": 2,
"fbc": "off",
"gop": 60,
"rc_mode": "cbr",
"fps": "0:0",
"range": "full",
"qp": "26:4:20:40:8:48:2:1",
"sei": "off",
"vi_len": 30,
"gop_mode": 0,
"bps": 10000,
"force_idr": "5:5:20000"
},
"1920*1080p30": {
"bps": 10000,
"force_idr": "5:5:30000"
},
"2560*1440p30": {
"bps": 15000,
"force_idr": "5:5:40000"
}
},
"param_change": {
}
}
},
"osd_cfg": {
"version" : 1,
"param_init": {
"enable": "off"
},
"param_change": {
}
}
}
}

View File

@@ -312,12 +312,12 @@ function choose_target_board() {
echo -e "${C_GREEN} "${space8}选择系统版本:"${C_NORMAL}"
if (("$BM_INDEX" == 1)); then
echo "${space8}${space8}[0] Buildroot(Support Rockchip official features) "
echo "${space8}${space8}[0] Buildroot "
read -p "Which would you like? [0~1][default:0]: " SYS_INDEX
MAX_SYS_INDEX=0
elif (("$BM_INDEX" == 0)); then
echo "${space8}${space8}[0] Buildroot(Support Rockchip official features) "
echo "${space8}${space8}[1] Ubuntu(Support for the apt package management tool)"
echo "${space8}${space8}[0] Buildroot "
echo "${space8}${space8}[1] Ubuntu "
read -p "Which would you like? [0~1][default:0]: " SYS_INDEX
MAX_SYS_INDEX=1
fi
@@ -689,24 +689,6 @@ function build_uboot() {
echo "TARGET_UBOOT_CONFIG=$RK_UBOOT_DEFCONFIG $RK_UBOOT_DEFCONFIG_FRAGMENT"
echo "========================================="
#Apply patch
if [ ! -f ${SDK_SYSDRV_DIR}/source/.uboot_patch ]; then
echo "============Apply Uboot Patch============"
cd ${SDK_ROOT_DIR}
git apply ${SDK_SYSDRV_DIR}/tools/board/uboot/*.patch
if [ $? -eq 0 ]; then
msg_info "Patch applied successfully."
touch ${SDK_SYSDRV_DIR}/source/.uboot_patch
else
msg_error "Failed to apply the patch."
exit 1
fi
fi
cp ${SDK_SYSDRV_DIR}/tools/board/uboot/*_defconfig ${SDK_SYSDRV_DIR}/source/uboot/u-boot/configs
cp ${SDK_SYSDRV_DIR}/tools/board/uboot/*.dts ${SDK_SYSDRV_DIR}/source/uboot/u-boot/arch/arm/dts
cp ${SDK_SYSDRV_DIR}/tools/board/uboot/*.dtsi ${SDK_SYSDRV_DIR}/source/uboot/u-boot/arch/arm/dts
local uboot_rkbin_ini tempfile target_ini_dir
tempfile="$SDK_SYSDRV_DIR/source/uboot/rkbin/$RK_UBOOT_RKBIN_INI_OVERLAY"
if [ -f "$tempfile" ]; then
@@ -841,24 +823,6 @@ function build_sysdrv() {
}
function build_kernel() {
#Apply patch
if [ ! -f ${SDK_SYSDRV_DIR}/source/.kernel_patch ]; then
echo "============Apply Kernel Patch============"
cd ${SDK_ROOT_DIR}
git apply --verbose ${SDK_SYSDRV_DIR}/tools/board/kernel/*.patch
if [ $? -eq 0 ]; then
msg_info "Patch applied successfully."
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*_defconfig ${KERNEL_PATH}/arch/arm/configs/
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*.config ${KERNEL_PATH}/arch/arm/configs/
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/kernel-drivers-video-logo_linux_clut224.ppm ${KERNEL_PATH}/drivers/video/logo/logo_linux_clut224.ppm
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*.dts ${KERNEL_PATH}/arch/arm/boot/dts
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*.dtsi ${KERNEL_PATH}/arch/arm/boot/dts
touch ${SDK_SYSDRV_DIR}/source/.kernel_patch
else
msg_error "Failed to apply the patch."
fi
fi
check_config RK_KERNEL_DTS RK_KERNEL_DEFCONFIG || return 0
echo "============Start building kernel============"
@@ -1318,25 +1282,6 @@ function build_clean() {
recovery)
make kernel_clean -C ${SDK_SYSDRV_DIR} SYSDRV_BUILD_RECOVERY=y
;;
patch)
cd ${SDK_ROOT_DIR}
make uboot_clean -C ${SDK_SYSDRV_DIR}
if [ -f ${SDK_SYSDRV_DIR}/source/.uboot_patch ]; then
git apply -R --verbose ${SDK_SYSDRV_DIR}/tools/board/uboot/*.patch
rm -rf ${SDK_SYSDRV_DIR}/source/uboot/u-boot/arch/arm/dts/*luckfox*
rm -rf ${SDK_SYSDRV_DIR}/source/uboot/u-boot/configs/*luckfox*
rm ${SDK_SYSDRV_DIR}/source/.uboot_patch
fi
make kernel_clean -C ${SDK_SYSDRV_DIR}
if [ -f ${SDK_SYSDRV_DIR}/source/.kernel_patch ]; then
git apply -R --verbose ${SDK_SYSDRV_DIR}/tools/board/kernel/*.patch
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/logo_linux_clut224.ppm ${SDK_SYSDRV_DIR}/source/kernel/drivers/video/logo/logo_linux_clut224.ppm
rm -rf ${SDK_SYSDRV_DIR}/source/kernel/arch/arm/configs/*luckfox*
rm -rf ${SDK_SYSDRV_DIR}/source/kernel/arch/arm/boot/dts/*luckfox*
rm ${SDK_SYSDRV_DIR}/source/.kernel_patch
fi
;;
all)
make distclean -C ${SDK_SYSDRV_DIR}
make distclean -C ${SDK_MEDIA_DIR}
@@ -2212,23 +2157,6 @@ __LINK_DEFCONFIG_FROM_BOARD_CFG() {
sudo chmod a+rw $SDK_CONFIG_DIR
fi
if [ ! -f ${SDK_SYSDRV_DIR}/source/.kernel_patch ]; then
echo "============Apply Kernel Patch============"
cd ${SDK_ROOT_DIR}
git apply ${SDK_SYSDRV_DIR}/tools/board/kernel/*.patch
if [ $? -eq 0 ]; then
msg_info "Patch applied successfully."
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*_defconfig ${KERNEL_PATH}/arch/arm/configs/
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*.config ${KERNEL_PATH}/arch/arm/configs/
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/kernel-drivers-video-logo_linux_clut224.ppm ${KERNEL_PATH}/drivers/video/logo/logo_linux_clut224.ppm
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*.dts ${KERNEL_PATH}/arch/arm/boot/dts
cp ${SDK_SYSDRV_DIR}/tools/board/kernel/*.dtsi ${KERNEL_PATH}/arch/arm/boot/dts
touch ${SDK_SYSDRV_DIR}/source/.kernel_patch
else
msg_error "Failed to apply the patch."
fi
fi
if [ -n "$RK_KERNEL_DTS" ]; then
rm -f $DTS_CONFIG
ln -rfs $SDK_SYSDRV_DIR/source/kernel/arch/arm/boot/dts/$RK_KERNEL_DTS $DTS_CONFIG
@@ -2295,7 +2223,9 @@ function build_mkimg() {
fs_type="\$${fs_type}"
fs_type=$(eval "echo ${fs_type}")
__RELEASE_FILESYSTEM_FILES $src
if [ "$LF_TARGET_ROOTFS" == "buildroot" ] || [ "$LF_TARGT_ROOTFS" == "busybox" ]; then
__RELEASE_FILESYSTEM_FILES $src
fi
msg_info "src=$src"
msg_info "dst=$dst"

View File

@@ -90,7 +90,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files

View File

@@ -90,7 +90,7 @@ export RK_KERNEL_DEFCONFIG_FRAGMENT=rv1106-bt.config
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files

View File

@@ -11,7 +11,7 @@ export RK_CHIP=rv1106
# export RK_APP_TYPE=RKIPC_RV1106
# Config CMA size in environment
export RK_BOOTARGS_CMA_SIZE="1M"
export RK_BOOTARGS_CMA_SIZE="36M"
# Kernel dts
export RK_KERNEL_DTS=rv1106g-luckfox-pico-ultra.dts
@@ -90,7 +90,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files
@@ -120,4 +120,4 @@ export RK_PRE_BUILD_OEM_SCRIPT=luckfox-buildroot-oem-pre.sh
export RK_PRE_BUILD_USERDATA_SCRIPT=luckfox-userdata-pre.sh
# declare overlay directory
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu-config overlay-luckfox-ubuntu-ultra"
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu-config overlay-luckfox-ubuntu-ultra overlay-luckfox-ubuntu-rockchip"

View File

@@ -11,7 +11,7 @@ export RK_CHIP=rv1106
# export RK_APP_TYPE=RKIPC_RV1106
# Config CMA size in environment
export RK_BOOTARGS_CMA_SIZE="1M"
export RK_BOOTARGS_CMA_SIZE="36M"
# Kernel dts
export RK_KERNEL_DTS=rv1106g-luckfox-pico-ultra-w.dts
@@ -93,7 +93,7 @@ export RK_KERNEL_DEFCONFIG_FRAGMENT=rv1106-bt.config
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files
@@ -128,4 +128,4 @@ export RK_PRE_BUILD_OEM_SCRIPT=luckfox-buildroot-oem-pre.sh
export RK_PRE_BUILD_USERDATA_SCRIPT=luckfox-userdata-pre.sh
# declare overlay directory
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu-config overlay-luckfox-ubuntu-ultra"
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu-config overlay-luckfox-ubuntu-ultra overlay-luckfox-ubuntu-rockchip"

View File

@@ -87,7 +87,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files

View File

@@ -87,7 +87,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files

View File

@@ -11,7 +11,7 @@ export RK_CHIP=rv1106
# export RK_APP_TYPE=RKIPC_RV1106
# Config CMA size in environment
export RK_BOOTARGS_CMA_SIZE="1M"
export RK_BOOTARGS_CMA_SIZE="36M"
# Kernel dts
export RK_KERNEL_DTS=rv1106g-luckfox-pico-max.dts
@@ -90,7 +90,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files
@@ -117,4 +117,4 @@ export RK_PRE_BUILD_OEM_SCRIPT=luckfox-ubuntu-oem-pre.sh
export RK_PRE_BUILD_USERDATA_SCRIPT=luckfox-userdata-pre.sh
# declare overlay directory
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu overlay-luckfox-ubuntu-config"
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu overlay-luckfox-ubuntu-config overlay-luckfox-ubuntu-rockchip"

View File

@@ -11,7 +11,7 @@ export RK_CHIP=rv1106
# export RK_APP_TYPE=RKIPC_RV1106
# Config CMA size in environment
export RK_BOOTARGS_CMA_SIZE="1M"
export RK_BOOTARGS_CMA_SIZE="36M"
# Kernel dts
export RK_KERNEL_DTS=rv1106g-luckfox-pico-pro.dts
@@ -90,7 +90,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files
@@ -117,4 +117,4 @@ export RK_PRE_BUILD_OEM_SCRIPT=luckfox-ubuntu-oem-pre.sh
export RK_PRE_BUILD_USERDATA_SCRIPT=luckfox-userdata-pre.sh
# declare overlay directory
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu overlay-luckfox-ubuntu-config"
export RK_POST_OVERLAY="overlay-luckfox-config overlay-luckfox-ubuntu overlay-luckfox-ubuntu-config overlay-luckfox-ubuntu-rockchip"

View File

@@ -87,7 +87,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files

View File

@@ -87,7 +87,7 @@ export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig
# RK_CAMERA_SENSOR_IQFILES format:
# "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json mis5001_CMK-OT2115-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"
# Config sensor lens CAC calibrattion bin files

Some files were not shown because too many files have changed in this diff Show More