【技术干货】双镜头对接demo
Posted: 2023年 Apr 21日 10:42
1. 功能接入
1.1 摄像头参数设置
在TUYA_IPC_SDK_START中,需要设置第二路摄像头的流媒体参数:
Code: Select all
/************************************** second camera parameter begin*****************************************************/
#if defined(IPC_CHANNEL_NUM) && (IPC_CHANNEL_NUM==2)
ipc_sdk_run_var.media_info.media_info2.stream_enable[E_IPC_STREAM_VIDEO_MAIN] = TRUE; /* Whether to enable local HD video streaming */
ipc_sdk_run_var.media_info.media_info2.video_fps[E_IPC_STREAM_VIDEO_MAIN] = 30; /* FPS */
ipc_sdk_run_var.media_info.media_info2.video_gop[E_IPC_STREAM_VIDEO_MAIN] = 60; /* GOP */
ipc_sdk_run_var.media_info.media_info2.video_bitrate[E_IPC_STREAM_VIDEO_MAIN] = TUYA_VIDEO_BITRATE_1M; /* Rate limit */
ipc_sdk_run_var.media_info.media_info2.video_width[E_IPC_STREAM_VIDEO_MAIN] = 426; /* Single frame resolution of width*/
ipc_sdk_run_var.media_info.media_info2.video_height[E_IPC_STREAM_VIDEO_MAIN] = 240;/* Single frame resolution of height */
ipc_sdk_run_var.media_info.media_info2.video_freq[E_IPC_STREAM_VIDEO_MAIN] = 90000; /* Clock frequency */
ipc_sdk_run_var.media_info.media_info2.video_codec[E_IPC_STREAM_VIDEO_MAIN] = TUYA_CODEC_VIDEO_H264; /* Encoding format */
ipc_sdk_run_var.media_info.media_info2.stream_enable[E_IPC_STREAM_VIDEO_SUB] = TRUE; /* Whether to enable local SD video stream */
ipc_sdk_run_var.media_info.media_info2.video_fps[E_IPC_STREAM_VIDEO_SUB] = 30; /* FPS */
ipc_sdk_run_var.media_info.media_info2.video_gop[E_IPC_STREAM_VIDEO_SUB] = 60; /* GOP */
ipc_sdk_run_var.media_info.media_info2.video_bitrate[E_IPC_STREAM_VIDEO_SUB] = TUYA_VIDEO_BITRATE_512K; /* Rate limit */
ipc_sdk_run_var.media_info.media_info2.video_width[E_IPC_STREAM_VIDEO_SUB] = 426; /* Single frame resolution of width */
ipc_sdk_run_var.media_info.media_info2.video_height[E_IPC_STREAM_VIDEO_SUB] = 240;/* Single frame resolution of height */
ipc_sdk_run_var.media_info.media_info2.video_freq[E_IPC_STREAM_VIDEO_SUB] = 90000; /* Clock frequency */
ipc_sdk_run_var.media_info.media_info2.video_codec[E_IPC_STREAM_VIDEO_SUB] = TUYA_CODEC_VIDEO_H264; /* Encoding format */
ipc_sdk_run_var.media_info.media_info2.stream_enable[E_IPC_STREAM_AUDIO_MAIN] = TRUE; /* Whether to enable local sound collection */
ipc_sdk_run_var.media_info.media_info2.audio_codec[E_IPC_STREAM_AUDIO_MAIN] = TUYA_CODEC_AUDIO_PCM;/* Encoding format */
ipc_sdk_run_var.media_info.media_info2.audio_sample [E_IPC_STREAM_AUDIO_MAIN]= TUYA_AUDIO_SAMPLE_8K;/* Sampling Rate */
ipc_sdk_run_var.media_info.media_info2.audio_databits [E_IPC_STREAM_AUDIO_MAIN]= TUYA_AUDIO_DATABITS_16;/* Bit width */
ipc_sdk_run_var.media_info.media_info2.audio_channel[E_IPC_STREAM_AUDIO_MAIN]= TUYA_AUDIO_CHANNEL_MONO;/* channel */
ipc_sdk_run_var.media_info.media_info2.audio_fps[E_IPC_STREAM_AUDIO_MAIN] = 25;/* Fragments per second */
#endif
/************************************** second camera parameter end *****************************************************/
1.2 媒体参数初始化
在IPC_APP_Media_Adapter_Init中,将第二路镜头的多媒体参数设置给sdk
Code: Select all
#if defined(IPC_CHANNEL_NUM) && (IPC_CHANNEL_NUM==2)
memcpy(&device_media_info.av_encode_info, &p_media_infos->media_info2,sizeof(IPC_MEDIA_INFO_T));
tuya_ipc_media_adapter_set_media_info(0, 1, device_media_info);
#endif
1.3 Ring Buffer初始化
在tuya_ipc_app_start中,增加第二路摄像头的Ring Buffer初始化
Code: Select all
#if defined(IPC_CHANNEL_NUM) && (IPC_CHANNEL_NUM==2)
ret = TUYA_APP_Init_Ring_Buffer(&pRunInfo->media_info.media_info2, 1);
if(OPRT_OK != ret)
{
PR_ERR("create ring buffer is error\n");
return ret;
}
#endif
1.4 创建取流线程
在IPC_APP_Init_Media_Task函数中,创建第二路摄像头取流线程
Code: Select all
#if defined(IPC_CHANNEL_NUM) && (IPC_CHANNEL_NUM==2)
pthread_t h264_output_thread2;
pthread_create(&h264_output_thread2, NULL, thread_live_video2, NULL);
pthread_detach(h264_output_thread2);
#endif
thread_live_video2线程如下:
Code: Select all
#if defined(IPC_CHANNEL_NUM) && (IPC_CHANNEL_NUM==2)
void *thread_live_video2(void *arg)
{
char raw_fullpath[128] = {0};
char info_fullpath[128] = {0};
unsigned int FrameLen=0,Frame_start=0;
unsigned int offset=0;
unsigned int IsKeyFrame=0;
unsigned char *pVideoBuf = NULL;
int channel = 1;
sprintf(raw_fullpath, "%s/resource/media2/demo_video.264", s_raw_path);
PR_DEBUG("start live video using %s",raw_fullpath);
g_v_handle[channel] = tuya_ipc_ring_buffer_open(0, channel, E_IPC_STREAM_VIDEO_MAIN, E_RBUF_WRITE);
g_v_handle_sub[channel] = tuya_ipc_ring_buffer_open(0, channel, E_IPC_STREAM_VIDEO_SUB, E_RBUF_WRITE);
if(g_v_handle[channel] == NULL || g_v_handle_sub[channel] == NULL)
{
pthread_exit(0);
}
FILE *streamBin_fp = fopen(raw_fullpath, "rb");
if((streamBin_fp == NULL))
{
PR_ERR("can't read live video file %s\n",raw_fullpath);
pthread_exit(0);
}
fseek(streamBin_fp, 0, SEEK_END);
UINT_T file_size = ftell(streamBin_fp);
fseek(streamBin_fp, 0, SEEK_SET);
pVideoBuf = malloc(file_size);
fread(pVideoBuf, 1, file_size, streamBin_fp);
MEDIA_FRAME_T video_frame = {0};
while(1)
{
offset=Frame_start+FrameLen;
if(offset>=file_size)
{
offset=0;
}
read_one_frame_from_demo_video_file(pVideoBuf+offset,offset,file_size-offset,&IsKeyFrame,&FrameLen,&Frame_start);
//Note: For I frame of H264, SPS/PPS/SEI/IDR should be combined within one frame, and the NALU separator should NOT be deleted.
if(IsKeyFrame==1)
{
video_frame.type = E_VIDEO_I_FRAME;
video_frame.size = FrameLen;
}
else
{
video_frame.type = E_VIDEO_PB_FRAME;
video_frame.size = FrameLen;
}
int frameRate = 30;
int sleepTick = 1000000/frameRate;
static UINT64_T pts = 0;
pts += sleepTick;
video_frame.p_buf = pVideoBuf+Frame_start;
video_frame.pts = pts;
/* Send HD video data to the SDK */
TUYA_APP_Put_Frame(g_v_handle[channel], &video_frame);
/* Send SD video data to the SDK */
TUYA_APP_Put_Frame(g_v_handle_sub[channel], &video_frame);
usleep(sleepTick);
}
if(g_v_handle[channel]) {
tuya_ipc_ring_buffer_close(g_v_handle[channel]);
g_v_handle[channel] = NULL ;
}
if(g_v_handle_sub[channel]) {
tuya_ipc_ring_buffer_close(g_v_handle_sub[channel]);
g_v_handle_sub[channel] = NULL ;
}
pthread_exit(0);
}
#endif
1.5 媒体参数更新
调用IPC_APP_Media_Adapter_Set更新媒体参数时,需要同时更新第二路摄像头的参数
Code: Select all
#if defined(IPC_CHANNEL_NUM) && (IPC_CHANNEL_NUM==2)
memcpy(&device_media_info.av_encode_info, &p_media_infos->media_info2, sizeof(IPC_MEDIA_INFO_T));
tuya_ipc_media_adapter_set_media_info(0, 1, device_media_info);
#endif