[update][mjpeg] update mjpeg with cam demo

This commit is contained in:
jzlv 2023-03-06 10:57:21 +08:00
parent d80f7a043e
commit 10eea5e835
9 changed files with 426 additions and 10 deletions

View file

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
target_sources(app PRIVATE jpeg_head.c)
sdk_set_main_file(main.c)
project(mjpeg_cam_normal)

View file

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View file

@ -0,0 +1,43 @@
# cam_normal
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL702/BL704/BL706 | |
|BL616/BL618 | |
|BL808 | |
## Compile
- BL602/BL604
```
make CHIP=bl602 BOARD=bl602dk
```
- BL702/BL704/BL706
```
make CHIP=bl702 BOARD=bl702dk
```
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
- BL808
```
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View file

@ -0,0 +1,11 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/mjpeg*_$(CHIPNAME).bin
address = 0x000000

View file

@ -0,0 +1,195 @@
#include "jpeg_head.h"
static const uint8_t tableQy[] = {
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99
};
static const uint8_t tableQuv[] = {
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
static const uint8_t tableHuffman[] = {
0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B,
0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1,
0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19,
0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84,
0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2,
0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
0xFF, 0xC4, 0x00, 0x1F, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B,
0xFF, 0xC4, 0x00, 0xB5, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1,
0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0X2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43,
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82,
0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5,
0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3,
0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
};
static void QCalc(const uint8_t *in, uint8_t *out, uint8_t q)
{
float tq, result;
int i;
if (q < 1)
tq = 5000.0f;
else if (q <= 50)
tq = 5000.0f / q;
else if (q <= 100)
tq = 200.0f - 2.0f * q;
else
tq = 0.0f;
tq = tq / 100.0f;
for (i = 0; i < 64; i++)
{
result = in[i] * tq;
if (result > 255.0f)
out[i] = 255;
else if (result < 1.0f)
out[i] = 1;
else
out[i] = (uint8_t)(result + 0.5f);
}
}
uint32_t JpegHeadCreate(uint8_t type, uint8_t q, int width, int height, uint8_t *out)
{
uint32_t index = 0;
uint32_t i;
/* start of jpeg file */
out[index++] = 0xFF;
out[index++] = 0xD8;
/* define quality table */
out[index++] = 0xFF;
out[index++] = 0xDB;
out[index++] = 0x00;
out[index++] = 0x43; //=3+N, N=64
out[index++] = 0x00;
QCalc(tableQy, out + index, q); //Y quality table
index += 64;
out[index++] = 0xFF;
out[index++] = 0xDB;
out[index++] = 0x00;
out[index++] = 0x43; //=3+N, N=64
out[index++] = 0x01;
QCalc(tableQuv, out + index, q); //UV quality table
index += 64;
/* basic information of mjpeg */
out[index++] = 0xFF;
out[index++] = 0xC0;
out[index++] = 0x00;
if(type==YUV_MODE_400)
out[index++] = 0x0B; //length:2 + bits:1 + height:2 + width:2 + num:1 + 3 * part=1
else
out[index++] = 0x11; //length:2 + bits:1 + height:2 + width:2 + num:1 + 3 * part=3
out[index++] = 0x08;
out[index++] = (uint8_t)((height >> 8) & 0xFF);
out[index++] = (uint8_t)(height & 0xFF);
out[index++] = (uint8_t)((width >> 8) & 0xFF);
out[index++] = (uint8_t)(width & 0xFF);
if (type == YUV_MODE_400)
{
out[index++] = 0x01; //number of part
out[index++] = 0x01; //the first part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x00; //id of quality tab
}
else if (type == YUV_MODE_420)
{
out[index++] = 0x03; //number of part
out[index++] = 0x01; //the first part id
out[index++] = 0x22; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x00; //id of quality tab
out[index++] = 0x02; //the second part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
out[index++] = 0x03; //the third part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
}
else if (type == YUV_MODE_422)
{
out[index++] = 0x03; //number of part
out[index++] = 0x01; //the first part id
out[index++] = 0x21; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x00; //id of quality tab
out[index++] = 0x02; //the second part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
out[index++] = 0x03; //the third part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
}
/* define Huffman table */
for (i = 0; i < sizeof(tableHuffman); i++)
{
out[index++] = tableHuffman[i];
}
/* start of scan*/
out[index++] = 0xFF;
out[index++] = 0xDA;
if (type == YUV_MODE_400)
{
out[index++] = 0x00;
out[index++] = 0x08; //length
out[index++] = 0x01;
out[index++] = 0x01;
out[index++] = 0x00;
out[index++] = 0x02;
out[index++] = 0x3F;
out[index++] = 0x00;
}
else
{
out[index++] = 0x00;
out[index++] = 0x0C; //length
out[index++] = 0x03;
out[index++] = 0x01;
out[index++] = 0x00;
out[index++] = 0x02;
out[index++] = 0x11;
out[index++] = 0x03;
out[index++] = 0x11;
out[index++] = 0x00;
out[index++] = 0x3F;
out[index++] = 0x00;
}
return index;
}

View file

@ -0,0 +1,12 @@
#ifndef __JPEG_HEAD_H__
#define __JPEG_HEAD_H__
#include "stdint.h"
#define YUV_MODE_400 1
#define YUV_MODE_420 2
#define YUV_MODE_422 3
extern uint32_t JpegHeadCreate(uint8_t type, uint8_t q, int width, int height, uint8_t *out);
#endif /* __JPEG_HEAD_H__ */

View file

@ -0,0 +1,133 @@
#include "bflb_mtimer.h"
#include "bflb_i2c.h"
#include "bflb_cam.h"
#include "bflb_mjpeg.h"
#include "image_sensor.h"
#include "board.h"
#include "jpeg_head.h"
#define BLOCK_NUM 2
#define ROW_NUM (8 * BLOCK_NUM)
#define CAM_FRAME_COUNT_USE 50
static struct bflb_device_s *i2c0;
static struct bflb_device_s *cam0;
static struct bflb_device_s *mjpeg;
volatile uint32_t pic_count = 0;
volatile uint32_t pic_addr[CAM_FRAME_COUNT_USE] = { 0 };
volatile uint32_t pic_len[CAM_FRAME_COUNT_USE] = { 0 };
void mjpeg_isr(int irq, void *arg)
{
uint8_t *pic;
uint32_t jpeg_len;
uint32_t intstatus = bflb_mjpeg_get_intstatus(mjpeg);
if (intstatus & MJPEG_INTSTS_ONE_FRAME) {
bflb_mjpeg_int_clear(mjpeg, MJPEG_INTCLR_ONE_FRAME);
jpeg_len = bflb_mjpeg_get_frame_info(mjpeg, &pic);
pic_addr[pic_count] = (uint32_t)pic;
pic_len[pic_count] = jpeg_len;
pic_count++;
bflb_mjpeg_pop_one_frame(mjpeg);
if (pic_count == CAM_FRAME_COUNT_USE) {
bflb_cam_stop(cam0);
bflb_mjpeg_stop(mjpeg);
}
}
}
uint8_t jpg_head_buf[800] = { 0 };
uint32_t jpg_head_len;
uint8_t MJPEG_QUALITY = 50;
#define SIZE_BUFFER (4 * 1024 * 1024)
void bflb_mjpeg_dump_hex(uint8_t *data, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len; i++) {
if (i % 16 == 0) {
printf("\r\n");
}
printf("%02x ", data[i]);
}
printf("\r\n");
}
int main(void)
{
struct bflb_cam_config_s cam_config;
struct image_sensor_config_s *sensor_config;
board_init();
board_dvp_gpio_init();
i2c0 = bflb_device_get_by_name("i2c0");
cam0 = bflb_device_get_by_name("cam0");
if (image_sensor_scan(i2c0, &sensor_config)) {
printf("\r\nSensor name: %s\r\n", sensor_config->name);
} else {
printf("\r\nError! Can't identify sensor!\r\n");
while (1) {
}
}
memcpy(&cam_config, sensor_config, IMAGE_SENSOR_INFO_COPY_SIZE);
cam_config.with_mjpeg = true;
cam_config.input_source = CAM_INPUT_SOURCE_DVP;
cam_config.output_format = CAM_OUTPUT_FORMAT_AUTO;
cam_config.output_bufaddr = BFLB_PSRAM_BASE;
cam_config.output_bufsize = cam_config.resolution_x * 2 * ROW_NUM;
bflb_cam_init(cam0, &cam_config);
bflb_cam_start(cam0);
mjpeg = bflb_device_get_by_name("mjpeg");
struct bflb_mjpeg_config_s config;
config.format = MJPEG_FORMAT_YUV422_YUYV;
config.quality = MJPEG_QUALITY;
config.rows = ROW_NUM;
config.resolution_x = cam_config.resolution_x;
config.resolution_y = cam_config.resolution_y;
config.input_bufaddr0 = (uint32_t)BFLB_PSRAM_BASE;
config.input_bufaddr1 = 0;
config.output_bufaddr = (uint32_t)BFLB_PSRAM_BASE + cam_config.resolution_x * 2 * ROW_NUM;
config.output_bufsize = SIZE_BUFFER - cam_config.resolution_x * 2 * ROW_NUM;
config.input_yy_table = NULL; /* use default table */
config.input_uv_table = NULL; /* use default table */
bflb_mjpeg_init(mjpeg, &config);
jpg_head_len = JpegHeadCreate(YUV_MODE_422, MJPEG_QUALITY, cam_config.resolution_x, cam_config.resolution_y, jpg_head_buf);
bflb_mjpeg_fill_jpeg_header_tail(mjpeg, jpg_head_buf, jpg_head_len);
bflb_mjpeg_tcint_mask(mjpeg, false);
bflb_irq_attach(mjpeg->irq_num, mjpeg_isr, NULL);
bflb_irq_enable(mjpeg->irq_num);
bflb_mjpeg_start(mjpeg);
while (pic_count < CAM_FRAME_COUNT_USE) {
printf("pic count:%d\r\n", pic_count);
bflb_mtimer_delay_ms(200);
}
for (uint8_t i = 0; i < CAM_FRAME_COUNT_USE; i++) {
printf("jpg addr:%08x ,jpg size:%d\r\n", pic_addr[i], pic_len[i]);
//bflb_mjpeg_dump_hex((uint8_t *)pic_addr[i], pic_len[i]);
}
while (1) {
bflb_mtimer_delay_ms(1000);
}
}

View file

@ -0,0 +1,2 @@
set(CONFIG_BSP_IMAGE_SENSOR 1)
set(CONFIG_PSRAM 1)

View file

@ -6,8 +6,10 @@
static struct bflb_device_s *mjpeg;
#define X 64
#define Y 64
#define X 64
#define Y 64
#define ROW_NUM (Y * MJPEG_MAX_FRAME_COUNT)
volatile uint32_t pic_count = 0;
volatile uint32_t pic_addr[MJPEG_MAX_FRAME_COUNT] = { 0 };
@ -34,12 +36,6 @@ uint32_t jpg_head_len;
uint8_t MJPEG_QUALITY = 50;
#if defined(BL616)
#define BSP_PSRAM_BASE 0xA8000000
#elif defined(BL808)
#define BSP_PSRAM_BASE 0x50000000
#endif
#define SIZE_BUFFER (4 * 1024 * 1024)
void bflb_mjpeg_dump_hex(uint8_t *data, uint32_t len)
@ -67,12 +63,13 @@ int main(void)
config.format = MJPEG_FORMAT_YUV422_YUYV;
config.quality = MJPEG_QUALITY;
config.rows = ROW_NUM;
config.resolution_x = X;
config.resolution_y = Y;
config.input_bufaddr0 = (uint32_t)test_64x64;
config.input_bufaddr1 = 0;
config.output_bufaddr = (uint32_t)BSP_PSRAM_BASE + MJPEG_MAX_FRAME_COUNT * X * Y * 2;
config.output_bufsize = SIZE_BUFFER - MJPEG_MAX_FRAME_COUNT * X * Y * 2;
config.output_bufaddr = (uint32_t)BFLB_PSRAM_BASE + X * 2 * ROW_NUM;
config.output_bufsize = SIZE_BUFFER - X * 2 * ROW_NUM;
config.input_yy_table = NULL; /* use default table */
config.input_uv_table = NULL; /* use default table */