401 lines
11 KiB
C
401 lines
11 KiB
C
|
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <stdio.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <pthread.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <semaphore.h>
|
||
|
#include <signal.h>
|
||
|
|
||
|
#define LOG_TAG "demo_video"
|
||
|
|
||
|
#include "AW_VideoInput_API.h"
|
||
|
#include "aw_util.h"
|
||
|
|
||
|
#define OUT_PUT_FILE_PREFIX "/tmp/stream0_osd"
|
||
|
#define IN_OSD_ARGB_FILE "/mnt/extsd/fs_v853/osd_test.dat"
|
||
|
#define IN_OSD_ARGB_FILE_2 "/mnt/extsd/fs_v853/01_argb_464x32_time.dat"
|
||
|
|
||
|
static int max_bitstream_count = SAVE_BITSTREAM_COUNT;
|
||
|
FILE *out_file_0 = NULL;
|
||
|
|
||
|
static int stream_count_0 = 0;
|
||
|
|
||
|
static sem_t finish_sem;
|
||
|
static int video_finish_flag = 0;
|
||
|
|
||
|
demo_video_param mparam;
|
||
|
|
||
|
static uint64_t pre_pts = 0;
|
||
|
static int save_file_cnt = 0;
|
||
|
static int need_save_new_file = 0;
|
||
|
|
||
|
static int pre_pts_in_seconds = 0;
|
||
|
static int cb_stream_cnt_in_seconds = 0;
|
||
|
|
||
|
void video_stream_cb(const AWVideoInput_StreamInfo* stream_info)
|
||
|
{
|
||
|
int keyframe = stream_info->keyframe_flag;
|
||
|
|
||
|
if (stream_info->size0 == 0 || stream_info->data0 == NULL) {
|
||
|
aw_logd("stream data error: data = %p, len = %d",stream_info->data0, stream_info->size0);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if(stream_count_0 < max_bitstream_count)
|
||
|
{
|
||
|
|
||
|
uint64_t cur_time = get_cur_time_us();
|
||
|
|
||
|
uint64_t pts = stream_info->pts;
|
||
|
uint64_t pts_in_seconds = pts/1000/1000;
|
||
|
unsigned char file_name[128] = {0};
|
||
|
unsigned char new_file_name[128] = {0};
|
||
|
|
||
|
if(stream_count_0%15 == 0)
|
||
|
{
|
||
|
aw_logd("*data = %p, len = %d, cnt = %d, kf = %d, pts = %llu us, %llu s; diff = %llu ms, cur_time = %llu us, diff = %llu ms\n",
|
||
|
stream_info->data0, stream_info->size0, stream_count_0, keyframe,
|
||
|
pts, pts/1000000, (pts - pre_pts)/1000, cur_time, (cur_time - pts)/1000);
|
||
|
}
|
||
|
|
||
|
if(pts_in_seconds != pre_pts_in_seconds)
|
||
|
{
|
||
|
aw_logd("get video stream, fps = %d", cb_stream_cnt_in_seconds);
|
||
|
pre_pts_in_seconds = pts_in_seconds;
|
||
|
cb_stream_cnt_in_seconds = 0;
|
||
|
}
|
||
|
cb_stream_cnt_in_seconds++;
|
||
|
|
||
|
pre_pts = pts;
|
||
|
|
||
|
if(stream_count_0%450 == 0)
|
||
|
need_save_new_file = 1;
|
||
|
|
||
|
if((need_save_new_file == 1 && keyframe == 1)
|
||
|
|| out_file_0 == NULL)
|
||
|
{
|
||
|
save_file_cnt++;
|
||
|
sprintf(file_name, "%s_%d.h264", mparam.OutputFilePath, save_file_cnt);
|
||
|
aw_logd("save new file, cnt = %d, file_name = %s", stream_count_0, file_name);
|
||
|
need_save_new_file = 0;
|
||
|
|
||
|
if(out_file_0)
|
||
|
{
|
||
|
fclose(out_file_0);
|
||
|
}
|
||
|
out_file_0 = fopen(file_name, "wb");
|
||
|
}
|
||
|
if(out_file_0) {
|
||
|
if (stream_info->b_insert_sps_pps && stream_info->sps_pps_size && stream_info->sps_pps_buf)
|
||
|
fwrite(stream_info->sps_pps_buf, 1, stream_info->sps_pps_size, out_file_0);
|
||
|
|
||
|
fwrite(stream_info->data0, 1, stream_info->size0, out_file_0);
|
||
|
|
||
|
if (stream_info->size1)
|
||
|
fwrite(stream_info->data1, 1, stream_info->size1, out_file_0);
|
||
|
if (stream_info->size2)
|
||
|
fwrite(stream_info->data2, 1, stream_info->size2, out_file_0);
|
||
|
}
|
||
|
|
||
|
if(stream_count_0 == 0)
|
||
|
{
|
||
|
uint64_t time = get_cur_time_us();
|
||
|
/* led_fwrite("/sys/class/gpio_sw/PF6/data", "0"); */
|
||
|
aw_logw("route 0 save first stream buffer done, time: %lld.%lldms ", time/1000, time%1000);
|
||
|
sprintf(new_file_name, "%s_%d_%lld.%lldms.h264", mparam.OutputFilePath, save_file_cnt, time/1000, time%1000);
|
||
|
rename(file_name, new_file_name);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aw_logd("already arrive max_bitstream_count %d", max_bitstream_count);
|
||
|
return ;
|
||
|
}
|
||
|
stream_count_0++;
|
||
|
#if 0//clean osd reverse
|
||
|
if(stream_count_0 == 49) {
|
||
|
if (mparam.enable_osd) {
|
||
|
aw_logw("begin clean osd");
|
||
|
VideoInputOSD OverlayInfo;
|
||
|
memset(&OverlayInfo, 0, sizeof(VideoInputOSD));
|
||
|
AWVideoInput_SetOSD(mparam.use_vipp_num, &OverlayInfo);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
if(stream_count_0 >= max_bitstream_count && !video_finish_flag)
|
||
|
{
|
||
|
video_finish_flag = 1;
|
||
|
sem_post(&finish_sem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int init_overlay_info(VideoInputOSD *pOverlayInfo, int index, char *file_path)
|
||
|
{
|
||
|
int i = index;
|
||
|
unsigned int start_x;
|
||
|
unsigned int start_y;
|
||
|
FILE* fd = NULL;
|
||
|
int width = pOverlayInfo->item_info[i].widht;
|
||
|
int height = pOverlayInfo->item_info[i].height;
|
||
|
unsigned char *argb_addr = NULL;
|
||
|
int b_isbmp = 0, ret = 0;
|
||
|
int argb_size = width * height * 4;
|
||
|
uint16_t type;
|
||
|
|
||
|
if (pOverlayInfo->argb_type != OVERLAY_ARGB8888)
|
||
|
argb_size = width * height * 2;
|
||
|
|
||
|
if (pOverlayInfo->item_info[index].osd_type == RT_NORMAL_OVERLAY
|
||
|
|| pOverlayInfo->item_info[index].osd_type == RT_LUMA_REVERSE_OVERLAY) {
|
||
|
|
||
|
fd = fopen(file_path, "r");
|
||
|
if (fd == NULL)
|
||
|
{
|
||
|
aw_loge("get fd error: %s\n", file_path);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
fseek(fd, 0x0, SEEK_SET);
|
||
|
fread(&type, sizeof(uint16_t), 1, fd);
|
||
|
fseek(fd, 0x0, SEEK_SET);
|
||
|
aw_logd("type = 0x%x", type);
|
||
|
if (type == 0x4D42)
|
||
|
b_isbmp = 1;
|
||
|
|
||
|
if (b_isbmp) {
|
||
|
argb_addr = deal_bmp_data(fd, pOverlayInfo, index);
|
||
|
if (argb_addr == NULL)
|
||
|
return -1;
|
||
|
width = pOverlayInfo->item_info[i].widht;
|
||
|
height = pOverlayInfo->item_info[i].height;
|
||
|
if (pOverlayInfo->argb_type == OVERLAY_ARGB8888)
|
||
|
argb_size = width * height * 4;
|
||
|
else
|
||
|
argb_size = width * height * 2;
|
||
|
} else {
|
||
|
aw_logw("The file is not a BMP file.\n");
|
||
|
fseek(fd, 0x0, SEEK_SET);
|
||
|
}
|
||
|
|
||
|
if(argb_addr == NULL)
|
||
|
{
|
||
|
argb_addr = (unsigned char*)malloc(argb_size);
|
||
|
if(argb_addr == NULL)
|
||
|
{
|
||
|
aw_logd("malloc bit_map_info[%d].argb_addr fail\n", i);
|
||
|
if (fd) {
|
||
|
fclose(fd);
|
||
|
fd = NULL;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
memset(argb_addr, 0, argb_size);
|
||
|
}
|
||
|
aw_logd("bitMap[%d] size[%d,%d], argb_addr:%p\n", i, width, height, argb_addr);
|
||
|
if (!b_isbmp) {
|
||
|
ret = fread(argb_addr, 1, argb_size, fd);
|
||
|
if(ret != argb_size)
|
||
|
aw_logd("read bitMap[%d] error, ret value:%d\n", i, ret);
|
||
|
}
|
||
|
fseek(fd, 0, SEEK_SET);
|
||
|
|
||
|
fclose(fd);
|
||
|
|
||
|
aw_logd("osd_num:%d, argb_type:%d\n", pOverlayInfo->osd_num, pOverlayInfo->argb_type);
|
||
|
|
||
|
start_x = 80;
|
||
|
start_y = 68;
|
||
|
|
||
|
if(width%16 !=0 || height%16 !=0)
|
||
|
{
|
||
|
aw_logd("error: w or h is not 16_align: %d, %d", width, height);
|
||
|
}
|
||
|
pOverlayInfo->item_info[i].data_buf = argb_addr;
|
||
|
pOverlayInfo->item_info[i].data_size = argb_size;
|
||
|
|
||
|
} else if (pOverlayInfo->item_info[index].osd_type == RT_COVER_OSD) {
|
||
|
aw_logd("osd_type RT_COVER_OSD!");
|
||
|
} else {
|
||
|
aw_logd("not support!");
|
||
|
}
|
||
|
|
||
|
aw_logd("osd item info[%d]: x = %d, y = %d, w = %d, h = %d, buf = %p, size = %d",
|
||
|
i, pOverlayInfo->item_info[i].start_x, pOverlayInfo->item_info[i].start_y,
|
||
|
pOverlayInfo->item_info[i].widht, pOverlayInfo->item_info[i].height,
|
||
|
pOverlayInfo->item_info[i].data_buf, pOverlayInfo->item_info[i].data_size);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void exit_demo()
|
||
|
{
|
||
|
int i = 0;
|
||
|
|
||
|
AWVideoInput_DeInit();
|
||
|
aw_logd("exit: deInit end\n");
|
||
|
sem_destroy(&finish_sem);
|
||
|
if(out_file_0)
|
||
|
{
|
||
|
fclose(out_file_0);
|
||
|
out_file_0 = NULL;
|
||
|
}
|
||
|
aw_logd("aw_demo, finish!\n");
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char** argv)
|
||
|
{
|
||
|
aw_logw("osd test start, time: %lld\n", get_cur_time_us());
|
||
|
pthread_t thread = 0;
|
||
|
int i = 0;
|
||
|
int ret = 0;
|
||
|
int channelId_0 = 0;
|
||
|
|
||
|
stream_count_0 = 0;
|
||
|
video_finish_flag = 0;
|
||
|
save_file_cnt = 0;
|
||
|
need_save_new_file = 0;
|
||
|
|
||
|
memset(&mparam, 0, sizeof(demo_video_param));
|
||
|
mparam.c0_encoder_format = -1;
|
||
|
mparam.pixelformat = RT_PIXEL_NUM;
|
||
|
mparam.use_vipp_num = 0;
|
||
|
strcpy(mparam.OutputFilePath, OUT_PUT_FILE_PREFIX);
|
||
|
/******** begin parse the config paramter ********/
|
||
|
if(argc >= 2)
|
||
|
{
|
||
|
aw_logd("******************************\n");
|
||
|
for(i = 1; i < (int)argc; i += 2)
|
||
|
{
|
||
|
ParseArgument(&mparam, argv[i], argv[i + 1]);
|
||
|
}
|
||
|
aw_logd("******************************\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
aw_logd(" we need more arguments \n");
|
||
|
PrintDemoUsage();
|
||
|
}
|
||
|
|
||
|
check_param(&mparam);
|
||
|
|
||
|
if(mparam.encoder_num > 0)
|
||
|
max_bitstream_count = mparam.encoder_num;
|
||
|
else
|
||
|
max_bitstream_count = SAVE_BITSTREAM_COUNT;
|
||
|
|
||
|
channelId_0 = mparam.use_vipp_num;
|
||
|
VideoInputConfig config_0;
|
||
|
memset(&config_0, 0, sizeof(VideoInputConfig));
|
||
|
config_0.channelId = channelId_0;
|
||
|
config_0.fps = 15;
|
||
|
config_0.gop = 30;
|
||
|
config_0.vbr = 0;
|
||
|
config_0.qp_range.i_min_qp = 35;
|
||
|
config_0.qp_range.i_max_qp = 51;
|
||
|
config_0.qp_range.p_min_qp = 35;
|
||
|
config_0.qp_range.p_max_qp = 51;
|
||
|
config_0.qp_range.i_init_qp = 35;
|
||
|
config_0.profile = AW_Video_H264ProfileMain;
|
||
|
config_0.level = AW_Video_H264Level51;
|
||
|
config_0.pixelformat = mparam.pixelformat;
|
||
|
config_0.enable_sharp = mparam.enable_sharp;
|
||
|
config_0.bonline_channel = mparam.bonline_channel;
|
||
|
config_0.share_buf_num = mparam.share_buf_num;
|
||
|
config_0.breduce_refrecmem = 1;
|
||
|
config_0.venc_video_signal.video_format = RT_DEFAULT;
|
||
|
config_0.venc_video_signal.full_range_flag = 1;
|
||
|
config_0.venc_video_signal.src_colour_primaries = RT_VENC_BT709;
|
||
|
config_0.venc_video_signal.dst_colour_primaries = RT_VENC_BT709;
|
||
|
|
||
|
config_0.output_mode = OUTPUT_MODE_STREAM;
|
||
|
config_0.width = mparam.c0_src_w;
|
||
|
config_0.height = mparam.c0_src_h;
|
||
|
config_0.bitrate = mparam.c0_bitrate/1024; //* kb
|
||
|
config_0.encodeType = mparam.c0_encoder_format;
|
||
|
config_0.drop_frame_num = 0;
|
||
|
config_0.enable_wdr = 0;
|
||
|
if (config_0.encodeType == 1) {//jpg encode
|
||
|
config_0.jpg_quality = 80;
|
||
|
if (mparam.encoder_num > 1) {//mjpg
|
||
|
config_0.jpg_mode = mparam.jpg_mode = 1;
|
||
|
config_0.bitrate = 12*1024;//kb
|
||
|
config_0.bit_rate_range.bitRateMin = 10*1024;//kb
|
||
|
config_0.bit_rate_range.bitRateMax = 14*1024;//kb
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AWVideoInput_Init();
|
||
|
sem_init(&finish_sem, 0, 0);
|
||
|
|
||
|
if(AWVideoInput_Configure(channelId_0, &config_0))
|
||
|
{
|
||
|
aw_loge("config err, exit!");
|
||
|
goto _exit;
|
||
|
}
|
||
|
AWVideoInput_CallBack(channelId_0, video_stream_cb, 1);
|
||
|
AWVideoInput_Start(channelId_0, 1);
|
||
|
|
||
|
if (mparam.enable_osd) {
|
||
|
VideoInputOSD OverlayInfo;
|
||
|
int index = 0;
|
||
|
memset(&OverlayInfo, 0, sizeof(VideoInputOSD));
|
||
|
|
||
|
OverlayInfo.osd_num = 3;
|
||
|
|
||
|
OverlayInfo.item_info[index].osd_type = RT_NORMAL_OVERLAY;
|
||
|
OverlayInfo.item_info[index].start_x = 16;
|
||
|
OverlayInfo.item_info[index].start_y = 752;
|
||
|
OverlayInfo.item_info[index].widht = 464;
|
||
|
OverlayInfo.item_info[index].height = 32;
|
||
|
OverlayInfo.argb_type = mparam.argb_type;
|
||
|
ret = init_overlay_info(&OverlayInfo, index, IN_OSD_ARGB_FILE);
|
||
|
|
||
|
index = 1;
|
||
|
OverlayInfo.item_info[index].osd_type = RT_NORMAL_OVERLAY;
|
||
|
OverlayInfo.item_info[index].start_x = 608;
|
||
|
OverlayInfo.item_info[index].start_y = 752;
|
||
|
OverlayInfo.item_info[index].widht = 464;
|
||
|
OverlayInfo.item_info[index].height = 32;
|
||
|
OverlayInfo.argb_type = mparam.argb_type;
|
||
|
// OverlayInfo.invert_mode = 3;
|
||
|
// OverlayInfo.invert_threshold = 90;
|
||
|
ret = init_overlay_info(&OverlayInfo, index, IN_OSD_ARGB_FILE_2);
|
||
|
|
||
|
index = 2;
|
||
|
OverlayInfo.item_info[index].osd_type = RT_COVER_OSD;
|
||
|
OverlayInfo.item_info[index].start_x = 800;
|
||
|
OverlayInfo.item_info[index].start_y = 192;
|
||
|
OverlayInfo.item_info[index].widht = 320;
|
||
|
OverlayInfo.item_info[index].height = 160;
|
||
|
OverlayInfo.item_info[index].cover_yuv.cover_y = 0;
|
||
|
OverlayInfo.item_info[index].cover_yuv.cover_u = 0;
|
||
|
OverlayInfo.item_info[index].cover_yuv.cover_v = 0x64;
|
||
|
ret |= init_overlay_info(&OverlayInfo, index, NULL);
|
||
|
|
||
|
if(ret == 0)
|
||
|
AWVideoInput_SetOSD(channelId_0, &OverlayInfo);
|
||
|
|
||
|
//usleep(2*1000*1000);
|
||
|
}
|
||
|
|
||
|
if(thread != 0)
|
||
|
pthread_join(thread, (void**)&ret);
|
||
|
|
||
|
//* wait for finish
|
||
|
sem_wait(&finish_sem);
|
||
|
AWVideoInput_Start(mparam.use_vipp_num, 0);
|
||
|
|
||
|
_exit:
|
||
|
exit_demo();
|
||
|
return 0;
|
||
|
}
|
||
|
|