Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
494
sdk/app/video_demo/video_demo.c
Normal file
494
sdk/app/video_demo/video_demo.c
Normal file
@@ -0,0 +1,494 @@
|
||||
#include "basic_include.h"
|
||||
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_define.h"
|
||||
#include "app_lcd/app_lcd.h"
|
||||
#include "lib/video/dvp/jpeg/jpg.h"
|
||||
#include "app/video_app/file_thumb.h"
|
||||
#include "video_demo.h"
|
||||
#include "stream_define.h"
|
||||
#include "osal_file.h"
|
||||
struct msi *jpg_concat_msi_init_start(uint32_t jpgid, uint16_t w, uint16_t h, uint16_t *filter_type, uint8_t src_from, uint8_t run);
|
||||
struct msi *h264_msi_init_with_mode(uint32_t drv1_from, uint16_t drv1_w, uint16_t drv1_h, uint16_t drv2_from, uint16_t drv2_w, uint16_t drv2_h);
|
||||
struct msi *route_msi(const char *name);
|
||||
struct msi *video_thumb_msi_init(const char *msi_name, uint16_t filter);
|
||||
void takephoto_with_thumb_init(const char *thumb_msi_name);
|
||||
void takephoto_with_thumb_over_dpi_init(const char *thumb_msi_name,uint8_t jpg_num);
|
||||
/*****************************************************************************************
|
||||
* demo都是简单的接收流程,如果有过滤type等,需要将接收msi实现更多东西才可以
|
||||
*****************************************************************************************/
|
||||
// 从其他文件调用解析mjpeg的函数
|
||||
extern void ex_parse_jpg(uint8_t *jpg_buf, uint32_t maxsize, uint32_t *w, uint32_t *h);
|
||||
|
||||
/**********************************************************
|
||||
* 这个demo是使用JPG0从VPP_DATA0编码
|
||||
*
|
||||
* msi数据流程:
|
||||
* "H_JPG_XXX"->RS_JPG_CONCAT->recv_jpg_demo
|
||||
*
|
||||
* 说明:
|
||||
* 如果没有修改,只需要关注recv_jpg_demo,
|
||||
* "H_JPG_XXX"->RS_JPG_CONCAT,已经默认绑定,"H_JPG_XXX"是动态
|
||||
* 名称,RS_JPG_CONCAT是固定输出jpg图片的msi名称
|
||||
* msi_add_output(NULL,RS_JPG_CONCAT,"recv_jpg_demo"),这样
|
||||
* 就可以绑定
|
||||
*
|
||||
**********************************************************/
|
||||
static void jpg0_encode_demo_from_vpp_data0(void *d)
|
||||
{
|
||||
// 请配置与数据源一致的分辨率
|
||||
// 这里采用VPP_DATA0,所以与摄像头采进来的数据w和h一致
|
||||
struct msi *jpg0_msi = jpg_concat_msi_init_start(JPGID0, 1280, 720, NULL, VPP_DATA0, 1);
|
||||
os_printf(KERN_INFO "jpg0_msi:%X\n", jpg0_msi);
|
||||
if (jpg0_msi)
|
||||
{
|
||||
msi_add_output(jpg0_msi, NULL, "recv_jpg_demo");
|
||||
}
|
||||
|
||||
// 创建接收的接收的msi模块
|
||||
uint8_t is_new = 0;
|
||||
uint32_t w, h;
|
||||
struct msi *recv_jpg_msi = msi_new("recv_jpg_demo", 8, &is_new);
|
||||
os_printf(KERN_INFO "recv_jpg_msi:%X\n", recv_jpg_msi);
|
||||
// 需要使能,不使能不会接收
|
||||
recv_jpg_msi->enable = 1;
|
||||
struct framebuff *fb = NULL;
|
||||
uint8_t *jpg_buf = NULL;
|
||||
while (recv_jpg_msi)
|
||||
{
|
||||
fb = msi_get_fb(recv_jpg_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
jpg_buf = (uint8_t *) fb->data;
|
||||
// 解析图片的size,看log知道图片生成是否正常
|
||||
ex_parse_jpg(jpg_buf, fb->len, &w, &h);
|
||||
// os_printf(KERN_INFO"fb:%X\tdata:%X\tlen:%d\n",fb,fb->data,fb->len);
|
||||
// os_printf(KERN_INFO"fb mtype:%X\tstype:%d\n",fb->mtype,fb->stype);
|
||||
// 打印前2byte,FF D8证明接收到的是正常图片
|
||||
os_printf(KERN_INFO "jpg_buf[0]:%02X\tjpg_buf[1]:%02X\n", jpg_buf[0], jpg_buf[1]);
|
||||
// os_printf(KERN_INFO"jpg w:%d\th:%d\n",w,h);
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* 这个demo是使用JPG0从VPP_DATA1编码
|
||||
*
|
||||
* msi数据流程:
|
||||
* "H_JPG_XXX"->RS_JPG_CONCAT->recv_jpg_demo
|
||||
*
|
||||
* 说明:
|
||||
* 如果没有修改,只需要关注recv_jpg_demo,
|
||||
* "H_JPG_XXX"->RS_JPG_CONCAT,已经默认绑定,"H_JPG_XXX"是动态
|
||||
* 名称,RS_JPG_CONCAT是固定输出jpg图片的msi名称
|
||||
* msi_add_output(NULL,RS_JPG_CONCAT,"recv_jpg_demo"),这样
|
||||
* 就可以绑定
|
||||
*
|
||||
**********************************************************/
|
||||
static void jpg0_encode_demo_from_vpp_data1(void *d)
|
||||
{
|
||||
// 请配置与数据源一致的分辨率
|
||||
// 这里采用VPP_DATA1,所以与vpp_data1配置的参数相关联
|
||||
struct msi *jpg0_msi = jpg_concat_msi_init_start(JPGID1, 640, 360, NULL, VPP_DATA1,1);
|
||||
os_printf(KERN_INFO "jpg0_msi:%X\n", jpg0_msi);
|
||||
if (jpg0_msi)
|
||||
{
|
||||
msi_add_output(jpg0_msi, NULL, "recv_jpg_demo"); // 与这个等效msi_add_output(NULL,RS_JPG_CONCAT,"recv_jpg_demo");
|
||||
}
|
||||
|
||||
// 创建接收的接收的msi模块
|
||||
uint8_t is_new = 0;
|
||||
uint32_t w, h;
|
||||
struct msi *recv_jpg_msi = msi_new("recv_jpg_demo", 8, &is_new);
|
||||
os_printf(KERN_INFO "recv_jpg_msi:%X\n", recv_jpg_msi);
|
||||
// 需要使能,不使能不会接收
|
||||
recv_jpg_msi->enable = 1;
|
||||
struct framebuff *fb = NULL;
|
||||
uint8_t *jpg_buf = NULL;
|
||||
while (recv_jpg_msi)
|
||||
{
|
||||
fb = msi_get_fb(recv_jpg_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
jpg_buf = (uint8_t *) fb->data;
|
||||
// 解析图片的size,看log知道图片生成是否正常
|
||||
ex_parse_jpg(jpg_buf, fb->len, &w, &h);
|
||||
os_printf(KERN_INFO "fb:%X\tdata:%X\tlen:%d\n", fb, fb->data, fb->len);
|
||||
os_printf(KERN_INFO "fb mtype:%X\tstype:%d\n", fb->mtype, fb->stype);
|
||||
// 打印前2byte,FF D8证明接收到的是正常图片
|
||||
os_printf(KERN_INFO "jpg_buf[0]:%02X\tjpg_buf[1]:%02X\n", jpg_buf[0], jpg_buf[1]);
|
||||
os_printf(KERN_INFO "jpg w:%d\th:%d\n", w, h);
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* 这个demo是简单h264接收,这里从VPP_DATA0去编码
|
||||
* h264->count这个主要是判断是否有丢帧,范围是2-255,如果丢帧
|
||||
* 应用应该是要去等到下一个I帧发送,否则可能花屏
|
||||
*
|
||||
* msi的数据流流程:
|
||||
* S_H264->recv_h264_demo
|
||||
**********************************************************/
|
||||
static void h264_encode_demo_from_vpp_data0(void *d)
|
||||
{
|
||||
// 请配置与数据源一致的分辨率
|
||||
// 这里采用VPP_DATA1,所以与vpp_data1配置的参数相关联
|
||||
struct msi *h264_msi = h264_msi_init_with_mode(VPP_DATA0, 1280, 720, ~0, 0, 0);
|
||||
os_printf(KERN_INFO "h264_msi:%X\n", h264_msi);
|
||||
if (h264_msi)
|
||||
{
|
||||
msi_add_output(h264_msi, NULL, "recv_h264_demo");
|
||||
}
|
||||
|
||||
// 创建接收的接收的msi模块
|
||||
uint8_t is_new = 0;
|
||||
//uint32_t w, h;
|
||||
struct msi *recv_h264_msi = msi_new("recv_h264_demo", 8, &is_new);
|
||||
os_printf(KERN_INFO "recv_h264_msi:%X\n", recv_h264_msi);
|
||||
// 需要使能,不使能不会接收
|
||||
recv_h264_msi->enable = 1;
|
||||
struct framebuff *fb = NULL;
|
||||
while (recv_h264_msi)
|
||||
{
|
||||
fb = msi_get_fb(recv_h264_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
struct fb_h264_s *h264 = (struct fb_h264_s *) fb->priv;
|
||||
if (h264->type == 1)
|
||||
{
|
||||
os_printf(KERN_INFO "############h264 I frame\tsize:%d\tcount:%d\r\n", fb->len, h264->count);
|
||||
}
|
||||
else if (h264->type == 2)
|
||||
{
|
||||
os_printf(KERN_INFO "h264 P frame\tsize:%d\tcount:%d\r\n", fb->len, h264->count);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_INFO "h264 err frame\r\n");
|
||||
}
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* 这个demo是简单h264接收,这里从VPP_DATA1去编码,注意:
|
||||
* 从VPP_DATA1去编码,VPP_DATA1不能保存到psram
|
||||
* h264->count这个主要是判断是否有丢帧,范围是2-255,如果丢帧
|
||||
* 应用应该是要去等到下一个I帧发送,否则可能花屏
|
||||
*
|
||||
* msi的数据流流程:
|
||||
* S_H264->recv_h264_demo
|
||||
**********************************************************/
|
||||
static void h264_encode_demo_from_vpp_data1(void *d)
|
||||
{
|
||||
// 请配置与数据源一致的分辨率
|
||||
// 这里采用VPP_DATA1,所以与vpp_data1配置的参数相关联
|
||||
struct msi *h264_msi = h264_msi_init_with_mode(VPP_DATA1, 640, 360, ~0, 0, 0);
|
||||
os_printf(KERN_INFO "h264_msi:%X\n", h264_msi);
|
||||
if (h264_msi)
|
||||
{
|
||||
msi_add_output(h264_msi, NULL, "recv_h264_demo");
|
||||
}
|
||||
|
||||
// 创建接收的接收的msi模块
|
||||
uint8_t is_new = 0;
|
||||
//uint32_t w, h;
|
||||
struct msi *recv_h264_msi = msi_new("recv_h264_demo", 8, &is_new);
|
||||
os_printf(KERN_INFO "recv_h264_msi:%X\n", recv_h264_msi);
|
||||
// 需要使能,不使能不会接收
|
||||
recv_h264_msi->enable = 1;
|
||||
struct framebuff *fb = NULL;
|
||||
while (recv_h264_msi)
|
||||
{
|
||||
fb = msi_get_fb(recv_h264_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
struct fb_h264_s *h264 = (struct fb_h264_s *) fb->priv;
|
||||
if (h264->type == 1)
|
||||
{
|
||||
os_printf(KERN_INFO "############h264 I frame\tsize:%d\tcount:%d\r\n", fb->len, h264->count);
|
||||
}
|
||||
else if (h264->type == 2)
|
||||
{
|
||||
os_printf(KERN_INFO "h264 P frame\tsize:%d\tcount:%d\r\n", fb->len, h264->count);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_INFO "h264 err frame\r\n");
|
||||
}
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* 这个demo是简单h264接收,这里从VPP_DATA1去编码,然后写卡10s
|
||||
* 注意:
|
||||
* 从VPP_DATA1去编码,VPP_DATA1不能保存到psram
|
||||
* h264->count这个主要是判断是否有丢帧,范围是2-255,如果丢帧
|
||||
* 应用应该是要去等到下一个I帧发送,否则可能花屏
|
||||
*
|
||||
* msi的数据流流程:
|
||||
* S_H264->recv_h264_demo
|
||||
**********************************************************/
|
||||
static void h264_encode_demo_from_vpp_data1_save_to_sd(void *d)
|
||||
{
|
||||
// 请配置与数据源一致的分辨率
|
||||
// 这里采用VPP_DATA1,所以与vpp_data1配置的参数相关联
|
||||
struct msi *h264_msi = h264_msi_init_with_mode(VPP_DATA1, 640, 360, ~0, 0, 0);
|
||||
os_printf(KERN_INFO "h264_msi:%X\n", h264_msi);
|
||||
if (h264_msi)
|
||||
{
|
||||
msi_add_output(h264_msi, NULL, "recv_h264_demo");
|
||||
}
|
||||
|
||||
// 创建接收的接收的msi模块
|
||||
uint8_t is_new = 0;
|
||||
//uint32_t w, h;
|
||||
struct msi *recv_h264_msi = msi_new("recv_h264_demo", 8, &is_new);
|
||||
os_printf(KERN_INFO "recv_h264_msi:%X\n", recv_h264_msi);
|
||||
// 需要使能,不使能不会接收
|
||||
recv_h264_msi->enable = 1;
|
||||
struct framebuff *fb = NULL;
|
||||
uint32_t record_start_time = os_jiffies();
|
||||
void *fp = osal_fopen("1.264", "wb");
|
||||
while (recv_h264_msi)
|
||||
{
|
||||
fb = msi_get_fb(recv_h264_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
struct fb_h264_s *h264 = (struct fb_h264_s *) fb->priv;
|
||||
if (h264->type == 1)
|
||||
{
|
||||
os_printf(KERN_INFO "h264 I frame\tsize:%d\tcount:%d\r\n", fb->len, h264->count);
|
||||
}
|
||||
else if (h264->type == 2)
|
||||
{
|
||||
os_printf(KERN_INFO "h264 P frame\tsize:%d\tcount:%d\r\n", fb->len, h264->count);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_INFO "h264 err frame h264->type:%d\r\n", h264->type);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
osal_fwrite((void*)fb->data, 1, fb->len, fp);
|
||||
if (os_jiffies() - record_start_time > 10000)
|
||||
{
|
||||
osal_fclose((F_FILE*)fp);
|
||||
fp = NULL;
|
||||
os_printf(KERN_INFO "H264 save finish\r\n");
|
||||
}
|
||||
}
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void jpg_demo_from_USB(void *d)
|
||||
{
|
||||
// 请配置与数据源一致的分辨率
|
||||
// 这里采用VPP_DATA0,所以与摄像头采进来的数据w和h一致
|
||||
struct msi *usb_jpg_route = route_msi(ROUTE_USB);
|
||||
os_printf(KERN_INFO "usb_jpg_route:%X\n", usb_jpg_route);
|
||||
if (usb_jpg_route)
|
||||
{
|
||||
msi_add_output(usb_jpg_route, NULL, "recv_jpg_demo");
|
||||
}
|
||||
|
||||
// 创建接收的接收的msi模块
|
||||
uint8_t is_new = 0;
|
||||
uint32_t w, h;
|
||||
struct msi *recv_jpg_msi = msi_new("recv_jpg_demo", 8, &is_new);
|
||||
os_printf(KERN_INFO "recv_jpg_msi:%X\n", recv_jpg_msi);
|
||||
// 需要使能,不使能不会接收
|
||||
recv_jpg_msi->enable = 1;
|
||||
struct framebuff *fb = NULL;
|
||||
uint8_t *jpg_buf = NULL;
|
||||
while (recv_jpg_msi)
|
||||
{
|
||||
fb = msi_get_fb(recv_jpg_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
jpg_buf = (uint8_t *) fb->data;
|
||||
// 解析图片的size,看log知道图片生成是否正常
|
||||
ex_parse_jpg(jpg_buf, fb->len, &w, &h);
|
||||
// os_printf(KERN_INFO"fb:%X\tdata:%X\tlen:%d\n",fb,fb->data,fb->len);
|
||||
// os_printf(KERN_INFO"fb mtype:%X\tstype:%d\n",fb->mtype,fb->stype);
|
||||
// 打印前2byte,FF D8证明接收到的是正常图片
|
||||
os_printf(KERN_INFO "jpg_buf[0]:%02X\tjpg_buf[1]:%02X\n", jpg_buf[0], jpg_buf[1]);
|
||||
// os_printf(KERN_INFO"jpg w:%d\th:%d\n",w,h);
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************************************************************************
|
||||
* 缩略图demo,这里是从USB获取一张图(所以这个demo运行前提是usb能正常获取到uvc的图片),然后到解码后生成缩略图并且按照sdk特定方式保存缩略图
|
||||
*
|
||||
* ROUTE_USB->video_thumb_name(原图)->R_THUMB
|
||||
**************************************************************************************************************************************/
|
||||
static void usb_thumb_demo(void *d)
|
||||
{
|
||||
extern void video_thumb_init(const char *thumb_msi_name);
|
||||
char filename[64];
|
||||
uint32_t start_time = os_jiffies();
|
||||
// 拍照以及缩略图的一些msi初始化
|
||||
video_thumb_init(R_THUMB);
|
||||
|
||||
// 从usb获取图片数据
|
||||
struct msi *usb_jpg_route = route_msi(ROUTE_USB);
|
||||
|
||||
char *video_thumb_name = "video_thumb_demo";
|
||||
struct msi *video_thumb_msi = video_thumb_msi_init(video_thumb_name, 0);
|
||||
if (video_thumb_msi)
|
||||
{
|
||||
// 给到解码然后生成缩略图
|
||||
msi_add_output(video_thumb_msi, NULL, R_THUMB);
|
||||
msi_add_output(usb_jpg_route, NULL, video_thumb_name);
|
||||
}
|
||||
|
||||
while (video_thumb_msi)
|
||||
{
|
||||
if (os_jiffies() - start_time > 1000)
|
||||
{
|
||||
start_time = os_jiffies();
|
||||
// 定时启动缩略图生成
|
||||
os_sprintf(filename, "%08d.jpg", (uint32_t) os_jiffies() % 99999999);
|
||||
os_printf(KERN_INFO "filename:%s\n", filename);
|
||||
msi_do_cmd(video_thumb_msi, MSI_CMD_JPG_THUMB, MSI_JPG_THUMB_TAKEPHOTO, (uint32_t)filename);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************************************************************************
|
||||
* 缩略图demo,这里是从USB获取一张图(所以这个demo运行前提是usb能正常获取到uvc的图片),然后到解码后生成缩略图并且按照sdk特定方式保存缩略图
|
||||
*
|
||||
* AUTO_JPG(实际是mjpeg图片)->video_thumb_name(原图)->R_THUMB
|
||||
**************************************************************************************************************************************/
|
||||
static void VPP_thumb_demo(void *d)
|
||||
{
|
||||
extern void video_thumb_init(const char *thumb_msi_name);
|
||||
char filename[64];
|
||||
uint32_t start_time = os_jiffies();
|
||||
// 拍照以及缩略图的一些msi初始化
|
||||
video_thumb_init(R_THUMB);
|
||||
|
||||
// 从usb获取图片数据
|
||||
char *video_thumb_name = "video_thumb_demo";
|
||||
struct msi *video_thumb_msi = video_thumb_msi_init(video_thumb_name, 0);
|
||||
if (video_thumb_msi)
|
||||
{
|
||||
// 给到解码然后生成缩略图
|
||||
msi_add_output(video_thumb_msi, NULL, R_THUMB);
|
||||
|
||||
|
||||
msi_add_output(NULL, AUTO_JPG, R_JPG_THUMB);
|
||||
}
|
||||
|
||||
while (video_thumb_msi)
|
||||
{
|
||||
if (os_jiffies() - start_time > 1000)
|
||||
{
|
||||
start_time = os_jiffies();
|
||||
// 定时启动缩略图生成
|
||||
os_sprintf(filename, "%08d.jpg", (uint32_t) os_jiffies() % 99999999);
|
||||
os_printf(KERN_INFO "filename:%s\n", filename);
|
||||
msi_do_cmd(video_thumb_msi, MSI_CMD_JPG_THUMB, MSI_JPG_THUMB_TAKEPHOTO, (uint32_t)filename);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void takephoto_demo(void *d)
|
||||
{
|
||||
#define MAX_DPI_NUM 5
|
||||
// 拍照的数量
|
||||
uint8_t takephoto_num = 1;
|
||||
uint8_t photo_value = 0;
|
||||
// 大分辨率和普通分辨率拍照的初始化
|
||||
// 正常拍照和缩略图
|
||||
takephoto_with_thumb_init(R_THUMB);
|
||||
// 大分辨率拍照和缩略图
|
||||
takephoto_with_thumb_over_dpi_init(SR_OVER_DPI_THUMB_JPG,JPGID0);
|
||||
static const int dpi[][2] = {
|
||||
{1280, 720}, // 720P
|
||||
{1920, 1080}, // 8M
|
||||
{2560, 1440}, // 8M
|
||||
{3840, 2160}, // 8M
|
||||
{7680, 4320}, // 12M
|
||||
};
|
||||
|
||||
while (1)
|
||||
{
|
||||
// 普通模式
|
||||
if (photo_value % MAX_DPI_NUM == 0)
|
||||
{
|
||||
struct msi *jpg_thumb_msi = msi_find(R_JPG_THUMB,1); // 需要预先创建,否则不会真正拍照
|
||||
if (jpg_thumb_msi)
|
||||
{
|
||||
msi_do_cmd(jpg_thumb_msi, MSI_CMD_JPG_THUMB, MSI_JPG_THUMB_TAKEPHOTO, takephoto_num);
|
||||
msi_put(jpg_thumb_msi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct msi *over_dpi_recode_msi = msi_find(R_SCALE1_JPG_RECODE, 0);
|
||||
uint32_t dpi_w_h = dpi[photo_value % MAX_DPI_NUM][0] << 16 | dpi[photo_value % MAX_DPI_NUM][1];
|
||||
if (over_dpi_recode_msi)
|
||||
{
|
||||
msi_do_cmd(over_dpi_recode_msi, MSI_CMD_SCALE1, MSI_SCALE1_RESET_DPI, dpi_w_h);
|
||||
msi_put(over_dpi_recode_msi);
|
||||
}
|
||||
|
||||
struct msi *over_dpi_msi = msi_find(S_SCALE3_OVER_DPI, 0);
|
||||
if (over_dpi_msi)
|
||||
{
|
||||
msi_do_cmd(over_dpi_msi, MSI_CMD_TAKEPHOTO_SCALE3, MSI_TAKEPHOTO_SCALE3_KICK, takephoto_num);
|
||||
msi_put(over_dpi_msi);
|
||||
}
|
||||
}
|
||||
photo_value++;
|
||||
// 间隔1s后切换拍照分辨率
|
||||
os_sleep_ms(1000);
|
||||
}
|
||||
}
|
||||
typedef void (*demo_func)(void *d);
|
||||
static const demo_func demo[DEMO_MAX] = {
|
||||
jpg0_encode_demo_from_vpp_data0,
|
||||
jpg0_encode_demo_from_vpp_data1,
|
||||
h264_encode_demo_from_vpp_data0,
|
||||
h264_encode_demo_from_vpp_data1,
|
||||
h264_encode_demo_from_vpp_data1_save_to_sd,
|
||||
jpg_demo_from_USB,
|
||||
usb_thumb_demo,
|
||||
VPP_thumb_demo,
|
||||
takephoto_demo,
|
||||
};
|
||||
|
||||
void video_demo_thread(enum DEMO_ENUM which)
|
||||
{
|
||||
if (which >= DEMO_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
os_task_create("video_demo", demo[which], NULL, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024); // 320x240
|
||||
}
|
||||
19
sdk/app/video_demo/video_demo.h
Normal file
19
sdk/app/video_demo/video_demo.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef __VIDEO_DEMO_H
|
||||
#define __VIDEO_DEMO_H
|
||||
enum DEMO_ENUM
|
||||
{
|
||||
JPG0_ENCODE_DEMO_FROM_VPP_DATA0,
|
||||
JPG0_ENCODE_DEMO_FROM_VPP_DATA1,
|
||||
H264_ENCODE_DEMO_FROM_VPP_DATA0,
|
||||
H264_ENCODE_DEMO_FROM_VPP_DATA1,
|
||||
H264_ENCODE_DEMO_FROM_VPP_DATA0_SAVE_TO_SD,
|
||||
JPG_DEMO_FROM_USB,
|
||||
USB_THUMB_DEMO,
|
||||
VPP_THUMB_DEMO,
|
||||
TAKEPHOTO_DEMO,
|
||||
DEMO_MAX,
|
||||
};
|
||||
|
||||
void video_demo_thread(enum DEMO_ENUM which);
|
||||
|
||||
#endif
|
||||
196
sdk/app/video_demo/video_thumb_demo.c
Normal file
196
sdk/app/video_demo/video_thumb_demo.c
Normal file
@@ -0,0 +1,196 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/video/dvp/jpeg/jpg_common.h"
|
||||
#include "gen420_hardware_msi.h"
|
||||
#include "video_msi.h"
|
||||
|
||||
struct msi *jpg_decode_msg_msi(const char *name, uint16_t out_w, uint16_t out_h, uint16_t step_w, uint16_t step_h, uint32_t filter);
|
||||
struct msi *thumb_over_dpi_msi_init(const char *msi_name, uint8_t jpg_type, uint8_t stype, uint32_t magic);
|
||||
struct msi *jpg_decode_msi(const char *name);
|
||||
|
||||
// 过滤类型,因为缩略图的stype一定大于FSYPTE_INVALID
|
||||
static uint8_t filter(void *f, uint8_t recv_type)
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) f;
|
||||
uint8_t res = 1;
|
||||
|
||||
if (fb->mtype == F_JPG && fb->stype == recv_type)
|
||||
{
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
struct video_thumb_s
|
||||
{
|
||||
struct msi *msi;
|
||||
uint8_t thumb_name[64];
|
||||
uint16_t filter_type;
|
||||
};
|
||||
|
||||
int32_t video_thumb_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
|
||||
struct video_thumb_s *video_thumb = (struct video_thumb_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
STREAM_LIBC_FREE(video_thumb);
|
||||
}
|
||||
break;
|
||||
|
||||
// 需要关闭,则将关联的msi关闭
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
// 接收到数据,唤醒workqueue,去组图,理论有图都要重新组,然后通过output的时候过滤类型,这里也可以先过滤部分类型
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
|
||||
if (video_thumb->filter_type)
|
||||
{
|
||||
if (video_thumb->filter_type != fb->stype)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
if (ret == RET_OK)
|
||||
{
|
||||
// fb->stype < FSYPTE_INVALID,防止生成的缩略图误认为是图片,video_thumb->filter_type最好
|
||||
if (fb->mtype == F_JPG && fb->stype < FSYPTE_INVALID)
|
||||
{
|
||||
// 转发然后生成缩略图,然后关闭使能
|
||||
struct framebuff *c_fb = fb_clone(fb, F_THUMB_JPG << 8 | fb->stype, msi);
|
||||
if (c_fb)
|
||||
{
|
||||
c_fb->priv = video_thumb->thumb_name;
|
||||
msi_output_fb(msi, c_fb);
|
||||
msi->enable = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 这个主要为了生成缩略图,所以这里不需要接收数据
|
||||
ret = RET_ERR;
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
// 这里是demo,复用MSI_CMD_JPG_THUMB
|
||||
case MSI_CMD_JPG_THUMB:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
switch (cmd_self)
|
||||
{
|
||||
// 修改保存文件的名称
|
||||
case MSI_JPG_THUMB_TAKEPHOTO:
|
||||
{
|
||||
char *filename = (char *) param2;
|
||||
video_thumb = (struct video_thumb_s *) msi->priv;
|
||||
os_memcpy(video_thumb->thumb_name, filename, strlen(filename) + 1);
|
||||
// os_printf(KERN_INFO"save thumb name:%s\n", video_thumb->thumb_name);
|
||||
msi->enable = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *video_thumb_msi_init(const char *msi_name, uint16_t filter)
|
||||
{
|
||||
uint8_t is_new;
|
||||
struct msi *msi = msi_new(msi_name, 0, &is_new);
|
||||
|
||||
struct video_thumb_s *video_thumb = NULL;
|
||||
|
||||
if (is_new)
|
||||
{
|
||||
video_thumb = (struct video_thumb_s *) STREAM_LIBC_ZALLOC(sizeof(struct video_thumb_s));
|
||||
msi->priv = video_thumb;
|
||||
video_thumb->msi = msi;
|
||||
video_thumb->filter_type = filter;
|
||||
msi->action = video_thumb_msi_action;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************************************
|
||||
* thumb_msi_name(如果是原图就去解码,如果是缩略图就保存)->R_THUMB_DECODE_MSG->R_THUMB_DECODE_MSG->R_GEN420_THUMB_JPG
|
||||
* ^ |
|
||||
* | |
|
||||
* | |
|
||||
* | V
|
||||
* --------------------------------------------------------------------------------------------------
|
||||
*****************************************************************************************************************************/
|
||||
// 这里是demo,msi的名字与sdk的名字一致,所以这里仅仅做参考
|
||||
void video_thumb_init(const char *thumb_msi_name)
|
||||
{
|
||||
uint32_t magic = 0;
|
||||
|
||||
// 启动解码模块,名称已经固定,参数已经无效
|
||||
struct msi *decode_msi = jpg_decode_msi(S_JPG_DECODE);
|
||||
if (decode_msi)
|
||||
{
|
||||
// 给到gen420去重新生成缩略图jpg
|
||||
msi_add_output(decode_msi, NULL, R_GEN420_THUMB_JPG);
|
||||
}
|
||||
|
||||
// 生成缩略图的size
|
||||
struct msi *decode_msg_msi = jpg_decode_msg_msi(R_THUMB_DECODE_MSG, 320, 180, 320, 180, 0);
|
||||
// 生成一个随机magic
|
||||
do
|
||||
{
|
||||
magic ^= os_jiffies();
|
||||
magic ^= (uint32_t) decode_msg_msi;
|
||||
} while (!magic);
|
||||
|
||||
struct msi *thumb_msi = thumb_over_dpi_msi_init(thumb_msi_name, 0,FSTYPE_NORMAL_THUMB_JPG, magic);
|
||||
if (thumb_msi)
|
||||
{
|
||||
// 处理原图,然后给到解码后生成缩略图
|
||||
msi_add_output(thumb_msi, NULL, R_THUMB_DECODE_MSG);
|
||||
|
||||
msi_add_output(thumb_msi, NULL, R_FILE_MSI);
|
||||
}
|
||||
|
||||
if (decode_msg_msi && decode_msi)
|
||||
{
|
||||
msi_do_cmd(decode_msg_msi, MSI_CMD_DECODE_JPEG_MSG, MSI_JPEG_DECODE_MAGIC, magic);
|
||||
msi_add_output(decode_msg_msi, NULL, decode_msi->name);
|
||||
}
|
||||
|
||||
// 启动一个专门用yuv->gen420->mjpg的模块,这个模块会接收mjpg图片,并且通过filter函数决定是否转发
|
||||
struct msi *gen420_jpg_msi = gen420_jpg_msi_init(R_GEN420_THUMB_JPG, JPGID0,FSTYPE_NORMAL_THUMB_JPG, JPG_LOCK_GEN420_THUBM_ENCODE, GEN420_QUEUE_THUMB_JPEG, NULL, filter);
|
||||
if (gen420_jpg_msi && thumb_msi)
|
||||
{
|
||||
msi_do_cmd(gen420_jpg_msi, MSI_CMD_JPG_RECODE, MSI_JPG_RECODE_MAGIC, magic);
|
||||
msi_add_output(gen420_jpg_msi, NULL, thumb_msi->name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user