lock_lfvx/bk_idk/middleware/driver/camera/video_common_driver.c

1393 lines
34 KiB
C
Raw Normal View History

2025-10-10 16:07:00 +08:00
// Copyright 2023-2024 Beken
//
// 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 <os/os.h>
#include <os/mem.h>
#include <os/str.h>
#include <driver/int.h>
#include <driver/jpeg_enc.h>
#include <driver/h264.h>
#include <driver/yuv_buf.h>
#include <driver/gpio.h>
#include <driver/video_common_driver.h>
#include <driver/dma.h>
#include "sys_driver.h"
#include "gpio_driver.h"
#include <modules/pm.h>
#include "bk_misc.h"
#define TAG "video_drv"
#define LOGI(...) BK_LOGW(TAG, ##__VA_ARGS__)
#define LOGW(...) BK_LOGW(TAG, ##__VA_ARGS__)
#define LOGE(...) BK_LOGE(TAG, ##__VA_ARGS__)
#define LOGD(...) BK_LOGD(TAG, ##__VA_ARGS__)
typedef struct {
gpio_id_t gpio_id;
gpio_dev_t dev;
} camera_gpio_map_t;
#define VIDEO_GPIO_PIN_NUMBER 12
#define VIDEO_GPIO_MAP \
{\
{GPIO_27, GPIO_DEV_JPEG_MCLK},\
{GPIO_29, GPIO_DEV_JPEG_PCLK},\
{GPIO_30, GPIO_DEV_JPEG_HSYNC},\
{GPIO_31, GPIO_DEV_JPEG_VSYNC},\
{GPIO_32, GPIO_DEV_JPEG_PXDATA0},\
{GPIO_33, GPIO_DEV_JPEG_PXDATA1},\
{GPIO_34, GPIO_DEV_JPEG_PXDATA2},\
{GPIO_35, GPIO_DEV_JPEG_PXDATA3},\
{GPIO_36, GPIO_DEV_JPEG_PXDATA4},\
{GPIO_37, GPIO_DEV_JPEG_PXDATA5},\
{GPIO_38, GPIO_DEV_JPEG_PXDATA6},\
{GPIO_39, GPIO_DEV_JPEG_PXDATA7},\
}
#define AUXS_CLK_CIS_ENABLE 1
extern uint32_t g_n_uvc_dev;
static uint8_t list_cnt = 0;
static camera_packet_t **camera_packet_list = NULL;
static camera_packet_t ** camera_packet_list_dual = NULL;
bk_err_t bk_video_camera_packet_list_deinit(void)
{
LOGI("%s, %d\r\n", __func__, __LINE__);
if (list_cnt == 0)
{
return BK_OK;
}
if(camera_packet_list != NULL)
{
for (uint8_t j = 0; j < list_cnt; j++)
{
if (camera_packet_list[j] == NULL)
continue;
if (camera_packet_list[j]->data_buffer)
{
os_free(camera_packet_list[j]->data_buffer);
camera_packet_list[j]->data_buffer = NULL;
}
if (camera_packet_list[j]->state)
{
os_free(camera_packet_list[j]->state);
camera_packet_list[j]->state = NULL;
}
if (camera_packet_list[j]->num_byte)
{
os_free(camera_packet_list[j]->num_byte);
camera_packet_list[j]->num_byte = NULL;
}
if (camera_packet_list[j]->actual_num_byte)
{
os_free(camera_packet_list[j]->actual_num_byte);
camera_packet_list[j]->actual_num_byte = NULL;
}
os_free(camera_packet_list[j]);
camera_packet_list[j] = NULL;
}
os_free(camera_packet_list);
camera_packet_list = NULL;
}
if(camera_packet_list_dual != NULL)
{
for (uint8_t j = 0; j < list_cnt; j++)
{
if (camera_packet_list_dual[j] == NULL)
continue;
if (camera_packet_list_dual[j]->data_buffer)
{
os_free(camera_packet_list_dual[j]->data_buffer);
camera_packet_list_dual[j]->data_buffer = NULL;
}
if (camera_packet_list_dual[j]->state)
{
os_free(camera_packet_list_dual[j]->state);
camera_packet_list_dual[j]->state = NULL;
}
if (camera_packet_list_dual[j]->num_byte)
{
os_free(camera_packet_list_dual[j]->num_byte);
camera_packet_list_dual[j]->num_byte = NULL;
}
if (camera_packet_list_dual[j]->actual_num_byte)
{
os_free(camera_packet_list_dual[j]->actual_num_byte);
camera_packet_list_dual[j]->actual_num_byte = NULL;
}
os_free(camera_packet_list_dual[j]);
camera_packet_list_dual[j] = NULL;
}
os_free(camera_packet_list_dual);
camera_packet_list_dual = NULL;
}
list_cnt = 0;
return BK_OK;
}
bk_err_t bk_video_camera_packet_list_init(mem_location_t locate, uint16_t MaxPacketSize, uint8_t max_packet_cnt, uint8_t cnt, uint32_t idx_uvc)
{
uint8_t i = 0;
uint32_t idx = idx_uvc;
if (idx_uvc == 0)
{
if (camera_packet_list != NULL)
{
bk_video_camera_packet_list_free();
return BK_OK;
}
list_cnt = cnt;
camera_packet_list = (camera_packet_t **)os_malloc(sizeof(camera_packet_t *) * cnt);
if (camera_packet_list == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
for (i = 0; i < list_cnt; i++)
{
camera_packet_list[i] = (camera_packet_t *)os_malloc(sizeof(camera_packet_t));
camera_packet_list[i]->uvc_dev_id = idx;
if (camera_packet_list[i] == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
camera_packet_list[i]->locate = locate;
// camera_packet_list[i]->state = (cam_stream_state_t *)os_malloc(sizeof(cam_stream_state_t) * max_packet_cnt);
camera_packet_list[i]->state = (uint8_t *)os_malloc(sizeof(uint8_t) * max_packet_cnt);
if (camera_packet_list[i]->state == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
os_memset(camera_packet_list[i]->state, 1, max_packet_cnt);
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list[i]->num_byte = (uint16_t *)psram_malloc(sizeof(uint16_t) * max_packet_cnt);
}
else
{
camera_packet_list[i]->num_byte = (uint16_t *)os_malloc(sizeof(uint16_t) * max_packet_cnt);
}
if (camera_packet_list[i]->num_byte == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
for (int j = 0; j < max_packet_cnt; j++)
camera_packet_list[i]->num_byte[j] = MaxPacketSize;
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list[i]->actual_num_byte = (uint16_t *)psram_malloc(sizeof(uint16_t) * max_packet_cnt);
}
else
{
camera_packet_list[i]->actual_num_byte = (uint16_t *)os_malloc(sizeof(uint16_t) * max_packet_cnt);
}
if (camera_packet_list[i]->actual_num_byte == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
os_memset(camera_packet_list[i]->actual_num_byte, 0, sizeof(uint16_t) * max_packet_cnt);
camera_packet_list[i]->data_buffer_size = MaxPacketSize * max_packet_cnt;
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list[i]->data_buffer = (uint8_t *)psram_malloc(camera_packet_list[i]->data_buffer_size);
}
else
{
camera_packet_list[i]->data_buffer = (uint8_t *)os_malloc(camera_packet_list[i]->data_buffer_size);
}
if (camera_packet_list[i]->data_buffer == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
LOGD("camera_packet_list[%d]->data_buffer:%p\r\n", i, camera_packet_list[i]->data_buffer);
camera_packet_list[i]->num_packets = max_packet_cnt;
camera_packet_list[i]->packet_state = CAM_STREAM_IDLE;
}
}
else if (idx_uvc == 1)
{
if (camera_packet_list_dual != NULL)
{
bk_video_camera_packet_list_dual_free();
return BK_OK;
}
list_cnt = cnt;
camera_packet_list_dual = (camera_packet_t **)os_malloc(sizeof(camera_packet_t *) * cnt);
LOGD("size of camera_packet_list_dual pointer : %d\n", (sizeof(camera_packet_t *) * cnt));
if (camera_packet_list_dual == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
for (i = 0; i < list_cnt; i++)
{
camera_packet_list_dual[i] = (camera_packet_t *)os_malloc(sizeof(camera_packet_t));
camera_packet_list_dual[i]->uvc_dev_id = idx;
if (camera_packet_list_dual[i] == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
camera_packet_list_dual[i]->locate = locate;
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list_dual[i]->state = (uint8_t *)psram_malloc(sizeof(uint8_t) * max_packet_cnt);
}
else
{
camera_packet_list_dual[i]->state = (uint8_t *)os_malloc(sizeof(uint8_t) * max_packet_cnt);
}
if (camera_packet_list_dual[i]->state == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
os_memset(camera_packet_list_dual[i]->state, 1, max_packet_cnt);
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list_dual[i]->num_byte = (uint16_t *)psram_malloc(sizeof(uint16_t) * max_packet_cnt);
}
else
{
camera_packet_list_dual[i]->num_byte = (uint16_t *)os_malloc(sizeof(uint16_t) * max_packet_cnt);
}
if (camera_packet_list_dual[i]->num_byte == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
for (int j = 0; j < max_packet_cnt; j++)
camera_packet_list_dual[i]->num_byte[j] = MaxPacketSize;
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list_dual[i]->actual_num_byte = (uint16_t *)psram_malloc(sizeof(uint16_t) * max_packet_cnt);
}
else
{
camera_packet_list_dual[i]->actual_num_byte = (uint16_t *)os_malloc(sizeof(uint16_t) * max_packet_cnt);
}
if (camera_packet_list_dual[i]->actual_num_byte == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
os_memset(camera_packet_list_dual[i]->actual_num_byte, 0, sizeof(uint16_t) * max_packet_cnt);
camera_packet_list_dual[i]->data_buffer_size = MaxPacketSize * max_packet_cnt;
if (locate == CAMERA_MEM_IN_PSRAM)
{
camera_packet_list_dual[i]->data_buffer = (uint8_t *)psram_malloc(camera_packet_list_dual[i]->data_buffer_size);
}
else
{
camera_packet_list_dual[i]->data_buffer = (uint8_t *)os_malloc(camera_packet_list_dual[i]->data_buffer_size);
}
if (camera_packet_list_dual[i]->data_buffer == NULL)
{
bk_video_camera_packet_list_deinit();
return BK_ERR_NO_MEM;
}
LOGD("camera_packet_list_dual[%d]->data_buffer:%p\r\n", i, camera_packet_list_dual[i]->data_buffer);
camera_packet_list_dual[i]->num_packets = max_packet_cnt;
camera_packet_list_dual[i]->packet_state = CAM_STREAM_IDLE;
}
}
return BK_OK;
}
bk_err_t bk_video_camera_packet_list_free(void)
{
for (uint8_t i = 0; i < list_cnt; i++)
{
if (camera_packet_list[i]->packet_state == CAM_STREAM_IDLE)
continue;
for (uint8_t j = 0; j < camera_packet_list[i]->num_packets; j++)
{
camera_packet_list[i]->state[j] = CAM_STREAM_IDLE;
camera_packet_list[i]->actual_num_byte[j] = 0;
// camera_packet_list[i]->num_byte[j] = 0;
}
camera_packet_list[i]->packet_state = CAM_STREAM_IDLE;
}
return BK_OK;
}
bk_err_t bk_video_camera_packet_list_dual_free(void)
{
if (camera_packet_list_dual != NULL)
{
for (uint8_t i = 0; i < list_cnt; i++)
{
if (camera_packet_list_dual[i]->packet_state == CAM_STREAM_IDLE)
continue;
for (uint8_t j = 0; j < camera_packet_list_dual[i]->num_packets; j++)
{
camera_packet_list_dual[i]->state[j] = CAM_STREAM_IDLE;
camera_packet_list_dual[i]->actual_num_byte[j] = 0;
// camera_packet_list_dual[i]->num_byte[j] = 0;
}
camera_packet_list_dual[i]->packet_state = CAM_STREAM_IDLE;
}
}
return BK_OK;
}
camera_packet_t *bk_video_camera_packet_malloc(void)
{
uint8_t i = 0;
GLOBAL_INT_DECLARATION();
for (i = 0; i < list_cnt; i++)
{
if (camera_packet_list[i]->packet_state == CAM_STREAM_IDLE)
{
break;
}
}
GLOBAL_INT_DISABLE();
if (i == list_cnt)
{
for (i = list_cnt; i > 0; i--)
{
if (camera_packet_list[i - 1]->packet_state == CAM_STREAM_READY)
{
LOGW("%s, index:%d [%d,%d,%d,%d]\r\n", __func__, i - 1,
camera_packet_list[0]->packet_state,
camera_packet_list[1]->packet_state,
camera_packet_list[2]->packet_state,
camera_packet_list[3]->packet_state);
camera_packet_list[i - 1]->packet_state = CAM_STREAM_IDLE;
i--;
break;
}
}
}
for (uint8_t j = 0; j < camera_packet_list[i]->num_packets; j++)
{
camera_packet_list[i]->state[j] = CAM_STREAM_IDLE;
camera_packet_list[i]->actual_num_byte[j] = 0;
//camera_packet_list[i]->num_byte[j] = 0;
}
camera_packet_list[i]->packet_state = CAM_STREAM_BUSY;
GLOBAL_INT_RESTORE();
return camera_packet_list[i];
}
camera_packet_t *bk_video_camera_packet_dual_malloc(void)
{
uint8_t i = 0;
GLOBAL_INT_DECLARATION();
for (i = 0; i < list_cnt; i++)
{
if (camera_packet_list_dual[i]->packet_state == CAM_STREAM_IDLE)
{
break;
}
}
GLOBAL_INT_DISABLE();
if (i == list_cnt)
{
for (i = list_cnt; i > 0; i--)
{
if (camera_packet_list_dual[i - 1]->packet_state == CAM_STREAM_READY)
{
LOGW("%s, index:%d [%d,%d,%d,%d]\r\n", __func__, i - 1,
camera_packet_list_dual[0]->packet_state,
camera_packet_list_dual[1]->packet_state,
camera_packet_list_dual[2]->packet_state,
camera_packet_list_dual[3]->packet_state);
camera_packet_list_dual[i - 1]->packet_state = CAM_STREAM_IDLE;
i--;
break;
}
}
}
for (uint8_t j = 0; j < camera_packet_list_dual[i]->num_packets; j++)
{
camera_packet_list_dual[i]->state[j] = CAM_STREAM_IDLE;
camera_packet_list_dual[i]->actual_num_byte[j] = 0;
// camera_packet_list_dual[i]->num_byte[j] = 0;
}
camera_packet_list_dual[i]->packet_state = CAM_STREAM_BUSY;
GLOBAL_INT_RESTORE();
return camera_packet_list_dual[i];
}
void bk_video_camera_packet_free(camera_packet_t *camera_packet)
{
if (camera_packet == NULL)
return;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
camera_packet->packet_state = CAM_STREAM_IDLE;
GLOBAL_INT_RESTORE();
}
void bk_video_camera_packet_dual_free(camera_packet_t *camera_packet)
{
if (camera_packet == NULL)
return;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
camera_packet->packet_state = CAM_STREAM_IDLE;
GLOBAL_INT_RESTORE();
}
camera_packet_t *bk_video_camera_packet_pop(void)
{
uint8_t count = 10;
uint8_t i = 0;
while (1)
{
for (i = 0; i < list_cnt; i++)
{
if (camera_packet_list[i]->packet_state == CAM_STREAM_READY)
{
break;
}
count--;
rtos_delay_milliseconds(5);
if (count == 0)
break;
}
};
if (count == 0 && camera_packet_list[i]->packet_state != CAM_STREAM_READY)
{
return NULL;
}
return camera_packet_list[i];
}
camera_packet_t *bk_video_camera_packet_dual_pop(void)
{
uint8_t count = 10;
uint8_t i = 0;
while (1)
{
for (i = 0; i < list_cnt; i++)
{
if (camera_packet_list_dual[i]->packet_state == CAM_STREAM_READY)
{
break;
}
count--;
rtos_delay_milliseconds(5);
if (count == 0)
break;
}
};
if (count == 0 && camera_packet_list_dual[i]->packet_state != CAM_STREAM_READY)
{
return NULL;
}
return camera_packet_list_dual[i];
}
void bk_video_camera_packet_push(camera_packet_t *camera_packet)
{
if (camera_packet == NULL)
return;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
camera_packet->packet_state = CAM_STREAM_READY;
GLOBAL_INT_RESTORE();
}
void bk_video_camera_packet_dual_push(camera_packet_t *camera_packet)
{
if (camera_packet == NULL)
return;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
camera_packet->packet_state = CAM_STREAM_READY;
GLOBAL_INT_RESTORE();
}
bk_err_t bk_video_power_on(uint8_t gpio, uint8_t activ_level)
{
#if (CONFIG_CAMERA_POWER_GPIO_CTRL)
gpio_dev_unmap(gpio);
bk_gpio_set_capacity(gpio, 0);
BK_LOG_ON_ERR(bk_gpio_disable_input(gpio));
BK_LOG_ON_ERR(bk_gpio_enable_output(gpio));
if (activ_level)
bk_gpio_set_output_high(gpio); // high active
else
bk_gpio_set_output_low(gpio); // low active
delay_ms(5);
#endif
return BK_OK;
}
bk_err_t bk_video_power_off(uint8_t gpio, uint8_t activ_level)
{
#if (CONFIG_CAMERA_POWER_GPIO_CTRL)
if (activ_level)
bk_gpio_set_output_low(gpio);
else
bk_gpio_set_output_high(gpio);
#endif //CONFIG_CAMERA_POWER_GPIO_CTRL
return BK_OK;
}
bk_err_t bk_video_set_mclk(mclk_freq_t mclk)
{
int ret = BK_OK;
#if (AUXS_CLK_CIS_ENABLE && CONFIG_SOC_BK7236XX)
gpio_dev_unmap(GPIO_27);
gpio_dev_map(GPIO_27, GPIO_DEV_CLK_AUXS_CIS);
sys_hal_set_cis_auxs_clk_en(1);
switch (mclk)
{
case MCLK_15M:
sys_drv_set_auxs_cis(3, 31);
break;
case MCLK_16M:
sys_drv_set_auxs_cis(3, 29);
break;
case MCLK_20M:
sys_drv_set_auxs_cis(3, 23);
break;
case MCLK_24M:
sys_drv_set_auxs_cis(3, 19);
break;
case MCLK_30M:
sys_drv_set_auxs_cis(3, 15);
break;
case MCLK_32M:
sys_drv_set_auxs_cis(3, 14);
break;
case MCLK_40M:
sys_drv_set_auxs_cis(3, 11);
break;
case MCLK_48M:
sys_drv_set_auxs_cis(3, 9);
break;
default:
return BK_FAIL;
}
sys_drv_set_jpeg_clk_sel(VIDEO_SYS_CLK_480M);
#endif
#if (!CONFIG_SOC_BK7236XX)
// for 7256xx
switch (mclk)
{
case MCLK_16M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(4);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_6);
break;
case MCLK_20M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(3);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_6);
break;
case MCLK_24M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(4);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_4);
break;
case MCLK_30M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(3);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_4);
break;
case MCLK_32M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(4);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_3);
break;
case MCLK_40M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(2);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_4);
break;
case MCLK_48M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(3);
bk_jpeg_enc_set_mclk_div(YUV_MCLK_DIV_6);
break;
default:
return BK_FAIL;
}
#else
// for bk7236xx, use auxs
sys_drv_set_jpeg_clk_sel(VIDEO_SYS_CLK_480M);
switch (mclk)
{
case MCLK_16M:
case MCLK_20M:
case MCLK_24M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(1);
bk_yuv_buf_set_mclk_div(YUV_MCLK_DIV_6);
break;
case MCLK_30M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(1);
bk_yuv_buf_set_mclk_div(YUV_MCLK_DIV_4);
break;
case MCLK_40M:
sys_drv_set_clk_div_mode1_clkdiv_jpeg(1);
bk_yuv_buf_set_mclk_div(YUV_MCLK_DIV_3);
break;
default:
return BK_FAIL;
}
#endif
return ret;
}
bk_err_t bk_video_dvp_mclk_enable(yuv_mode_t mode)
{
// step 1: vid_power on, current only have jpeg_enc vote, need add yuv_buf/h264 .etc
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN, PM_POWER_MODULE_STATE_ON);
// step 2: clk enable
bk_pm_clock_ctrl(PM_CLK_ID_JPEG, CLK_PWR_CTRL_PWR_UP); //jpeg_clk
#if (CONFIG_SOC_BK7236XX)
sys_drv_yuv_buf_pwr_up(); // yuv_buf clk enable
sys_drv_h264_pwr_up(); // h264 clk enable
bk_yuv_buf_soft_reset();
#endif
// step 3: config mclk
bk_video_set_mclk(MCLK_24M);
// step 4: enable encode
bk_video_encode_start(mode);
return BK_OK;
}
bk_err_t bk_video_dvp_mclk_disable(void)
{
bk_pm_clock_ctrl(PM_CLK_ID_JPEG, CLK_PWR_CTRL_PWR_DOWN); //jpeg_clk
#if (CONFIG_SOC_BK7236XX)
sys_drv_yuv_buf_pwr_down(); // yuv_buf clk enable
sys_drv_h264_pwr_down(); // h264 clk enable
#endif
#if (AUXS_CLK_CIS_ENABLE)
sys_drv_set_cis_auxs_clk_en(0); // ausx_clk disable
#endif
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN, PM_POWER_MODULE_STATE_OFF);
return BK_OK;
}
bk_err_t bk_video_encode_start(yuv_mode_t mode)
{
switch (mode)
{
case YUV_MODE:
case GRAY_MODE:
#if (CONFIG_SOC_BK7236XX)
bk_yuv_buf_start(YUV_MODE);
#else
bk_jpeg_enc_start(YUV_MODE);
#endif
break;
case JPEG_MODE:
case JPEG_YUV_MODE:
#if (CONFIG_SOC_BK7236XX)
bk_yuv_buf_start(JPEG_MODE);
#else
bk_jpeg_enc_start(JPEG_MODE);
#endif
break;
case H264_MODE:
case H264_YUV_MODE:
#if (CONFIG_SOC_BK7236XX)
//BK_LOG_ON_ERR(bk_gpio_enable_input(CAMERA_DVP_VSYNC_PIN));
bk_yuv_buf_start(H264_MODE);
bk_h264_encode_enable();
#endif
break;
default:
break;
}
return BK_OK;
}
bk_err_t bk_video_encode_stop(yuv_mode_t mode)
{
switch (mode)
{
case YUV_MODE:
case GRAY_MODE:
#if (CONFIG_SOC_BK7236XX)
bk_yuv_buf_stop(YUV_MODE);
#else
bk_jpeg_enc_stop(YUV_MODE);
#endif
break;
case JPEG_MODE:
case JPEG_YUV_MODE:
#if (CONFIG_SOC_BK7236XX)
bk_yuv_buf_stop(JPEG_MODE);
#else
bk_jpeg_enc_stop(JPEG_MODE);
#endif
break;
case H264_MODE:
case H264_YUV_MODE:
#if (CONFIG_SOC_BK7236XX)
bk_yuv_buf_stop(H264_MODE);
#endif
break;
default:
break;
}
return BK_OK;
}
bk_err_t bk_video_gpio_init(dvp_gpio_mode_t mode)
{
camera_gpio_map_t camera_gpio_map_table[] = VIDEO_GPIO_MAP;
if (mode == DVP_GPIO_CLK)
{
for (uint32_t i = 0; i < 2; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
gpio_dev_map(camera_gpio_map_table[i].gpio_id, camera_gpio_map_table[i].dev);
}
}
else if (mode == DVP_GPIO_DATA)
{
for (uint32_t i = 2; i < VIDEO_GPIO_PIN_NUMBER; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
gpio_dev_map(camera_gpio_map_table[i].gpio_id, camera_gpio_map_table[i].dev);
}
}
else if (mode == DVP_GPIO_HSYNC_DATA)
{
gpio_dev_unmap(camera_gpio_map_table[2].gpio_id);
gpio_dev_map(camera_gpio_map_table[2].gpio_id, camera_gpio_map_table[2].dev);
for (uint32_t i = 4; i < VIDEO_GPIO_PIN_NUMBER; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
gpio_dev_map(camera_gpio_map_table[i].gpio_id, camera_gpio_map_table[i].dev);
}
}
else // DVP_GPIO_ALL
{
for (uint32_t i = 0; i < VIDEO_GPIO_PIN_NUMBER; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
gpio_dev_map(camera_gpio_map_table[i].gpio_id, camera_gpio_map_table[i].dev);
}
}
return BK_OK;
}
bk_err_t bk_video_gpio_deinit(dvp_gpio_mode_t mode)
{
camera_gpio_map_t camera_gpio_map_table[] = VIDEO_GPIO_MAP;
if (mode == DVP_GPIO_CLK)
{
for (uint32_t i = 0; i < 2; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
}
}
else if (mode == DVP_GPIO_DATA)
{
for (uint32_t i = 2; i < VIDEO_GPIO_PIN_NUMBER; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
}
}
else if (mode == DVP_GPIO_HSYNC_DATA)
{
gpio_dev_unmap(camera_gpio_map_table[2].gpio_id);
for (uint32_t i = 4; i < VIDEO_GPIO_PIN_NUMBER; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
}
}
else //DVP_GPIO_ALL
{
for (uint32_t i = 0; i < VIDEO_GPIO_PIN_NUMBER; i++) {
gpio_dev_unmap(camera_gpio_map_table[i].gpio_id);
}
}
return BK_OK;
}
typedef struct
{
uint8_t encode_line_odd; // encode line flag
uint8_t *src_buffer;
uint8_t dma_channel;
beken_semaphore_t sem; // wait encode success
yuv_mode_t mode; // encode mode:h264/jpeg
pixel_format_t fmt; // input data format
frame_resl_t resolution; // image size
frame_buffer_t *src_frame;
frame_buffer_t *dst_frame;
uint32_t node_length;
uint32_t rx_encode_length;
uint32_t rx_read_length;
} yuv_encode_config_t;
static yuv_encode_config_t *yuv_encode_config = NULL;
static bk_err_t yuv_encode_memcpy_by_chnl(void *out, const void *in, uint32_t len, dma_id_t cpy_chnl)
{
dma_config_t dma_config = {0};
os_memset(&dma_config, 0, sizeof(dma_config_t));
dma_config.mode = DMA_WORK_MODE_SINGLE;
dma_config.chan_prio = 0;
dma_config.src.dev = DMA_DEV_DTCM;
dma_config.src.width = DMA_DATA_WIDTH_32BITS;
dma_config.src.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.src.start_addr = (uint32_t)in;
dma_config.src.end_addr = (uint32_t)(in + len);
dma_config.dst.dev = DMA_DEV_DTCM;
dma_config.dst.width = DMA_DATA_WIDTH_32BITS;
dma_config.dst.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.dst.start_addr = (uint32_t)out;
dma_config.dst.end_addr = (uint32_t)(out + len);
bk_dma_init(cpy_chnl, &dma_config);
bk_dma_set_transfer_len(cpy_chnl, len);
#if (CONFIG_SPE)
bk_dma_set_src_sec_attr(cpy_chnl, DMA_ATTR_SEC);
bk_dma_set_dest_sec_attr(cpy_chnl, DMA_ATTR_SEC);
#endif
bk_dma_start(cpy_chnl);
BK_WHILE(bk_dma_get_enable_status(cpy_chnl));
return BK_OK;
}
static void yuv_encode_line_done_handler(jpeg_unit_t id, void *param)
{
if (yuv_encode_config->encode_line_odd)
{
yuv_encode_config->encode_line_odd = 0;
yuv_encode_config->rx_read_length += yuv_encode_config->rx_encode_length;
bk_yuv_buf_set_em_base_addr((uint32_t)(yuv_encode_config->src_frame->frame + yuv_encode_config->rx_read_length));
}
else
{
yuv_encode_config->encode_line_odd = 1;
}
bk_yuv_buf_rencode_start();
}
static void yuv_encode_final_out_handler(jpeg_unit_t id, void *param)
{
uint32_t real_length = 0;
uint32_t remain_length = 0;
bk_dma_flush_src_buffer(yuv_encode_config->dma_channel);
bk_dma_stop(yuv_encode_config->dma_channel);
remain_length = yuv_encode_config->node_length - bk_dma_get_remain_len(yuv_encode_config->dma_channel);
if (yuv_encode_config->mode == JPEG_MODE)
{
real_length = bk_jpeg_enc_get_frame_size();
if (yuv_encode_config->dst_frame->length + remain_length - JPEG_CRC_SIZE != real_length)
{
LOGW("size no match: %u:%u\n", yuv_encode_config->dst_frame->length + remain_length - JPEG_CRC_SIZE, real_length);
}
yuv_encode_config->dst_frame->fmt = PIXEL_FMT_JPEG;
}
else
{
real_length = bk_h264_get_encode_count() * 4;
if (yuv_encode_config->dst_frame->length + remain_length != real_length)
{
LOGW("size no match: %u:%u\n", yuv_encode_config->dst_frame->length + remain_length, real_length);
}
yuv_encode_config->dst_frame->fmt = PIXEL_FMT_H264;
}
bk_video_encode_stop(yuv_encode_config->mode);
//yuv_encode_config->dst_frame->length += remain_length;
yuv_encode_config->dst_frame->length = real_length;
yuv_encode_config->dst_frame->sequence = yuv_encode_config->src_frame->sequence;
yuv_encode_config->dst_frame->width = yuv_encode_config->resolution.width;
yuv_encode_config->dst_frame->height = yuv_encode_config->resolution.height;
rtos_set_semaphore(&yuv_encode_config->sem);
}
static void yuv_encode_head_output_handler(jpeg_unit_t id, void *param)
{
bk_yuv_buf_rencode_start();
}
static void yuv_encode_dma_finish_callback(dma_id_t id)
{
yuv_encode_config->dst_frame->length += yuv_encode_config->node_length;
}
static bk_err_t yuv_encode_dma_config(yuv_mode_t mode)
{
uint32_t encode_fifo_addr;
if (mode == H264_MODE)
{
bk_h264_get_fifo_addr(&encode_fifo_addr);
yuv_encode_config->dma_channel = bk_dma_alloc(DMA_DEV_H264);
}
else
{
bk_jpeg_enc_get_fifo_addr(&encode_fifo_addr);
yuv_encode_config->dma_channel = bk_dma_alloc(DMA_DEV_JPEG);
}
LOGI("dma for encode is %x \r\n", yuv_encode_config->dma_channel);
dma_config_t dma_config = {0};
dma_config.mode = DMA_WORK_MODE_REPEAT;
dma_config.chan_prio = 0;
dma_config.src.dev = DMA_DEV_H264;
dma_config.src.width = DMA_DATA_WIDTH_32BITS;
dma_config.src.start_addr = encode_fifo_addr;
dma_config.dst.dev = DMA_DEV_DTCM;
dma_config.dst.width = DMA_DATA_WIDTH_32BITS;
dma_config.dst.addr_inc_en = DMA_ADDR_INC_ENABLE;
dma_config.dst.start_addr = 0x60000000;//(uint32_t)yuv_encode_config->frame->frame;
dma_config.dst.end_addr = 0x60800000;//(uint32_t)(yuv_encode_config->frame->frame + yuv_encode_config->frame->size);
BK_LOG_ON_ERR(bk_dma_init(yuv_encode_config->dma_channel, &dma_config));
BK_LOG_ON_ERR(bk_dma_register_isr(yuv_encode_config->dma_channel, NULL, yuv_encode_dma_finish_callback));
BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(yuv_encode_config->dma_channel));
BK_LOG_ON_ERR(bk_dma_set_transfer_len(yuv_encode_config->dma_channel, yuv_encode_config->node_length));
#if (CONFIG_SPE)
BK_LOG_ON_ERR(bk_dma_set_src_burst_len(yuv_encode_config->dma_channel, BURST_LEN_SINGLE));
BK_LOG_ON_ERR(bk_dma_set_dest_burst_len(yuv_encode_config->dma_channel, BURST_LEN_INC16));
BK_LOG_ON_ERR(bk_dma_set_dest_sec_attr(yuv_encode_config->dma_channel, DMA_ATTR_SEC));
BK_LOG_ON_ERR(bk_dma_set_src_sec_attr(yuv_encode_config->dma_channel, DMA_ATTR_SEC));
#endif
return BK_OK;
}
bk_err_t bk_video_yuv_encode_init(media_camera_device_t *device)
{
int ret = BK_OK;
uint32_t encode_buffer_length = 0;
yuv_buf_config_t yuv_config = {0};
jpeg_config_t jpeg_config = {0};
// encode_clk 120M
sys_drv_set_jpeg_clk_sel(VIDEO_SYS_CLK_480M);
sys_drv_set_clk_div_mode1_clkdiv_jpeg(1);
if (device->info.resolution.width * device->info.resolution.height > 1280 * 720)
{
LOGE("%s, not support more than 1280X720 resolution\r\n", __func__);
ret = BK_FAIL;
goto error;
}
if (device->mode == JPEG_MODE)
{
encode_buffer_length = device->info.resolution.width * 2 * 8 * 2;
}
else if (device->mode == H264_MODE)
{
encode_buffer_length = device->info.resolution.width * 2 * 16 * 2;
}
else
{
LOGE("%s, not support this mode:%d!\r\n", __func__, device->mode);
ret = BK_FAIL;
goto error;
}
if (yuv_encode_config == NULL)
{
yuv_encode_config = (yuv_encode_config_t *)os_malloc(sizeof(yuv_encode_config_t));
if (yuv_encode_config == NULL)
{
LOGE("%s, malloc yuv_encode_config failed!\r\n", __func__);
ret = BK_FAIL;
goto error;
}
os_memset(yuv_encode_config, 0, sizeof(yuv_encode_config_t));
ret = rtos_init_semaphore(&yuv_encode_config->sem, 1);
if (yuv_encode_config->sem == NULL)
{
LOGE("%s, malloc yuv_encode_config->sem failed!\r\n", __func__);
ret = BK_FAIL;
goto error;
}
}
yuv_encode_config->resolution.width = device->info.resolution.width;
yuv_encode_config->resolution.height = device->info.resolution.height;
yuv_encode_config->mode = device->mode;
yuv_encode_config->fmt = device->fmt;
yuv_config.x_pixel = yuv_encode_config->resolution.width / 8;
yuv_config.y_pixel = yuv_encode_config->resolution.height / 8;
yuv_config.work_mode = yuv_encode_config->mode;
yuv_config.base_addr = NULL;
yuv_config.yuv_mode_cfg.yuv_format = YUV_FORMAT_YUYV;
ret = bk_yuv_buf_init(&yuv_config);
if (ret != BK_OK)
{
LOGE("%s, init yuv_buf error\r\n", __func__);
goto error;
}
bk_yuv_buf_enable_nosensor_encode_mode();
if (yuv_encode_config->mode == JPEG_MODE)
{
jpeg_config.x_pixel = yuv_config.x_pixel;
jpeg_config.y_pixel = yuv_config.y_pixel;
jpeg_config.mode = yuv_config.work_mode;
ret = bk_jpeg_enc_init(&jpeg_config);
bk_jpeg_enc_register_isr(JPEG_LINE_CLEAR, yuv_encode_line_done_handler, NULL);
bk_jpeg_enc_register_isr(JPEG_EOF, yuv_encode_final_out_handler, NULL);
bk_jpeg_enc_register_isr(JPEG_HEAD_OUTPUT, yuv_encode_head_output_handler, NULL);
}
else
{
ret = bk_h264_init((yuv_encode_config->resolution.width << 16) | yuv_encode_config->resolution.height);
/* register h264 callback */
bk_h264_register_isr(H264_LINE_DONE, yuv_encode_line_done_handler, 0);
bk_h264_register_isr(H264_FINAL_OUT, yuv_encode_final_out_handler, 0);
}
if (ret != BK_OK)
{
LOGE("%s, init encode module error\r\n", __func__);
goto error;
}
yuv_encode_config->node_length = 1024 * 5;
yuv_encode_config->rx_encode_length = encode_buffer_length;
yuv_encode_config->rx_read_length = 0;
ret = yuv_encode_dma_config(yuv_encode_config->mode);
if (ret != BK_OK)
{
LOGE("%s, init dma error\r\n", __func__);
goto error;
}
LOGI("%s complete\n", __func__);
return ret;
error:
bk_video_yuv_encode_deinit();
return ret;
}
bk_err_t bk_video_yuv_encode_deinit(void)
{
if (yuv_encode_config == NULL)
{
return BK_OK;
}
// step 1: stop encode
bk_video_encode_stop(yuv_encode_config->mode);
bk_h264_deinit();
bk_jpeg_enc_deinit();
if (yuv_encode_config)
{
if (yuv_encode_config->dma_channel < DMA_ID_MAX)
{
bk_dma_stop(yuv_encode_config->dma_channel);
bk_dma_deinit(yuv_encode_config->dma_channel);
if (yuv_encode_config->mode == JPEG_MODE)
bk_dma_free(DMA_DEV_JPEG, yuv_encode_config->dma_channel);
else
bk_dma_free(DMA_DEV_H264, yuv_encode_config->dma_channel);
}
if (yuv_encode_config->sem)
{
rtos_deinit_semaphore(&yuv_encode_config->sem);
yuv_encode_config->sem = NULL;
}
os_free(yuv_encode_config);
yuv_encode_config = NULL;
}
return BK_OK;
}
bk_err_t bk_video_yuv_encode_start(frame_buffer_t *src_frame, frame_buffer_t *dst_frame)
{
if (yuv_encode_config == NULL)
{
return BK_FAIL;
}
yuv_encode_config->dst_frame = dst_frame;
yuv_encode_config->src_frame = src_frame;
yuv_encode_config->rx_read_length = 0;
yuv_encode_config->encode_line_odd = 0;
bk_yuv_buf_set_em_base_addr((uint32_t)src_frame->frame);
bk_dma_set_dest_addr(yuv_encode_config->dma_channel, (uint32_t)dst_frame->frame, (uint32_t)(dst_frame->frame + dst_frame->size));
bk_dma_start(yuv_encode_config->dma_channel);
bk_video_encode_start(yuv_encode_config->mode);
bk_yuv_buf_rencode_start();
if (rtos_get_semaphore(&yuv_encode_config->sem, 500) != BK_OK)//BEKEN_WAIT_FOREVER
{
bk_video_encode_stop(yuv_encode_config->mode);
yuv_encode_config->encode_line_odd = 0;
bk_dma_stop(yuv_encode_config->dma_channel);
return BK_FAIL;
}
yuv_encode_config->encode_line_odd = 0;
return BK_OK;
}
uint8_t *dvp_camera_yuv_base_addr_init(frame_resl_t resolution, yuv_mode_t mode)
{
uint8_t *encode_buffer = NULL;
#if CONFIG_ENCODE_BUF_DYNAMIC
if (encode_buffer == NULL)
{
if (mode == H264_MODE)
{
encode_buffer = (uint8_t *)os_malloc(resolution.width * 32 * 2);
}
else
encode_buffer = (uint8_t *)os_malloc(resolution.width * 16 * 2);
if (encode_buffer == NULL)
{
LOGE("yuv_buf base addr init failed!\n");
}
}
#endif
return encode_buffer;
}
uint32_t bk_video_identify_h264_nal_fmt(uint8_t *buf, uint32_t size)
{
uint32_t h264_type = 0;
uint8_t nal_type = 0;
uint8_t i = 0;
uint8_t nal_ref_idc = 0;
if (size < 128)
return h264_type;
for (i = 0; i < 128; i++)
{
if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 0 && buf[i + 3] == 1)
{
i += 4;
nal_ref_idc = (buf[i] >> 5) & 0x3;
nal_type = buf[i] & 0x1f;
h264_type |= 0x1 << nal_type;
if (nal_type == 1)
{
if (nal_ref_idc > 0)
h264_type |= (0x1 << H264_NAL_I_FRAME);
else
h264_type |= (0x1 << H264_NAL_P_FRAME);
}
}
}
return h264_type;
}
bk_err_t bk_video_compression_ratio_config(compress_ratio_t *config)
{
int ret = BK_FAIL;
if (!config)
{
LOGE("%s, param error\n", __func__);
return ret;
}
if (config->mode == JPEG_MODE)
{
ret = bk_jpeg_enc_encode_config(config->enable, config->jpeg_up, config->jpeg_low);
}
else if (config->mode == H264_MODE)
{
ret = bk_h264_set_base_config(config);
}
else
{
LOGE("%s, mode:%d error\n", __func__, config->mode);
return BK_FAIL;
}
return ret;
}