本模块用于设备端音视频数据存储在本地,打包为 mp4 文件。
功能介绍
本模块用于把用户音视频数据保存为 mp4 文件,输入音频数据为 AAC 数据,视频为 H.264 或 H.265 裸数据,观看端在回放时由 SDK 内部进行回放。
流程指引
录像模块初始化 > 开始录像 > 发送音视频数据 > 停止录像 > 录像模块去初始化
接口参考
该功能模块提供以下接口:
iv_rd_init:录像模块初始化
iv_rd_exit:录像模块去初始化
iv_rd_record_start:开始录像
iv_rd_record_stop:停止录像
iv_rd_push_stream:发送录像流数据
iv_rd_delete_oldest_file:删除最旧的文件以腾出空间(循环录像)
iv_rd_sort_out_list_file:整理录像索引文件(防止索引和录像文件不同步)
iv_rd_playback_notice_cb:有本地回放发生的通知回调
iv_rd_get_recording_type_cb:获取正在录像的文件的类型
iv_rd_recording_cut_slice:主动切片正在录像的文件
iv_rd_init
接口描述
录像功能模块初始化。进行录像模式初始化,资源申请,需要本模块启动时调用。
int iv_rd_init(iv_rd_init_parm_s *pstInitParm);
参数说明
参数名称 | 类型 | 描述 | 输入/输出 |
pstInitParm | iv_rd_init_parm_s * | 初始化参数。 | 输入 |
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_exit
接口描述
录像功能模块去初始化。停止录像模块时调用,释放资源。
int iv_rd_exit(void);
参数说明
无
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_record_start
接口描述
开始录像。
int iv_rd_record_start(char *ps8RecordType);
参数说明
参数名称 | 类型 | 描述 | 输入/输出 |
ps8RecordType | char * | 录像类型(字符串,长度最大不超过16)。 | 输入 |
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_record_stop
接口描述
停止录像。
int iv_rd_record_stop(void);
参数说明
无
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_push_stream
接口描述
发送音视频数据,视频输入编码格式为 h264 和 h265,音频输入格式为 AAC 编码。
int iv_rd_push_stream(iv_rd_stream_type_e eStreamType, void *pStream);
参数说明
参数名称 | 类型 | 描述 | 输入/输出 |
eStreamType | iv_rd_stream_type_e | 录像回放发送的录像数据类型(音频/视频)。 | 输入 |
pStream | void* | 录像回放发送的数据内容。 | 输入 |
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_delete_oldest_file
接口描述
删除录像列表里最旧的一个文件,通过该接口可以删除最旧文件的同时删除文件记录。
说明:
1. 如果不调用改接口进行删除,而是应用层自行删除最旧录像文件则会导致录像列表不同步,App 能够获取到录像列表但是无法播放(可通过调用
iv_rd_sort_out_list_file
解决)。2. 该接口和录像文件结束生成录像列表、App 获取回放列表,录像列表整理互斥。
3. 如果需要删除多个文件可以多次调用该接口,或者自行删除录像文件之后调用
iv_rd_sort_out_list_file
同步列表文件。int iv_rd_delete_oldest_file(void);
参数说明
无
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_sort_out_list_file
接口描述
整理录像列表文件。
说明
1. 该接口设计用于当用户主动拔出 SD 卡删除录像文件,重新插入 SD 卡时可以调用该接口同步录像列表,防止 App 获取录像列表却无法找到实际录像文件。
2. 建议在 SD 卡插入和设备上电时主动调用该接口进行同步录像列表。
3. 该接口和录像文件结束生成录像列表、App 获取回放列表,删除最旧文件互斥。
4. 该接口不会删除任何录像文件,只会整理索引文件。
int iv_rd_sort_out_list_file(void);
参数说明
无
返回值
返回值 | 描述 |
IV_CODE_SUCCESS | 成功。 |
IV_CODE_ERR_* | 失败,对应相应错误码。 |
iv_rd_playback_notice_cb
接口描述
进行本地录像回放、关闭本地录像时调用该回调,设计是用来告知应用层此时有回放业务发生,应用层此时不可进入睡眠,同时 SDK 会根据该回调的返回结果决定是否进行本次回放。
1. 远端发起回放的开启和关闭会通过注册的回调函数通知上层(如果有注册回调),可以通过参数
link_id
获知 SDK 当前使用的回放通路。2. 上层可做鉴权等处理。
如果不允许本次回放则返回
0(IV_RD_PLAYBACK_STA_STOP)
。如果允许本次回放则返回
1(IV_RD_PLAYBACK_STA_START)
。3. 该函数可阻塞处理,只会影响当前通道的回放处理。
iv_rd_play_back_status_e (*iv_rd_playback_notice_cb)(uint32_t link_id,iv_rd_play_back_status_e status);
参数说明
参数名称 | 类型 | 描述 | 输入/输出 |
link_id | uint32_t | 回放通路 ID。 | 输入 |
status | iv_rd_play_back_status | 回放状态枚。 | 输入 |
返回值
返回值 | 描述 |
IV_RD_PLAYBACK_STA_STOP | 不允许本次回放。 |
IV_RD_PLAYBACK_STA_START | 允许本次回放。 |
iv_rd_get_recording_type_cb
在 SDK 结束录像时会调用该回调获取本次录像文件的录像类型,便于生成文件名。该回调可使得录像文件类型在关闭时才最终确定,中途可根据需要进行变更。
说明:
如果中途不会变更录像类型则无需注册该函数。
int32_t (*iv_rd_get_recording_type_cb)(uint64_t file_start_time_ms,uint8_t out_type_string[IV_RD_RECORD_TYPE_SIZE],uint32_t out_type_buff_size);
参数说明
无
返回值
返回值 | 描述 |
IV_ERR_NONE | 成功。 |
IV_ERR_* | 失败,对应相应错误码。 |
iv_rd_recording_cut_slice
进行本地录像的主动切片,当调用该接口时,SDK会在下一个I帧来临后打包文件并且重新创建一个新的录像文件。
该接口不会阻塞。
说明:
如果无需中途主动切断录像并开启则无需注册该函数。
int iv_rd_recording_cut_slice(void);
参数说明
无
返回值
返回值 | 描述 |
IV_ERR_NONE | 成功。 |
IV_ERR_* | 失败,对应相应错误码。 |
数据结构
该模块提供以下数据结构:
iv_rd_stream_type_e:流类型枚举。
iv_rd_pack_type_e: 录像文件切分类型枚举。
iv_rd_init_parm_s:初始化参数结构。
音视频结构参考公共模块音视频结构。
iv_rd_play_back_status_e 本地回放状态枚举。
iv_rd_stream_type_e
接口描述
流类型枚举。
typedef enum{IV_RD_STREAM_TYPE_AUDIO = 0, /*audio*/IV_RD_STREAM_TYPE_VIDEO = 1, /*video*/IV_RD_STREAM_TYPE_BUTT}iv_rd_stream_type_e;
参数说明
成员名称 | 描述 | 取值 |
IV_RD_STREAM_TYPE_AUDIO | 音频 | - |
IV_RD_STREAM_TYPE_VIDEO | 视频 | - |
iv_rd_pack_type_e
接口描述
录像文件切分类型。
typedef enum{IV_RD_PACK_TYPE_NONE, /* pack record file by max limit size 3G bytes */IV_RD_PACK_TYPE_TIME, /* pack record file by fix time duration */IV_RD_PACK_TYPE_SIZE, /* pack record file by fix size */IV_RD_PACK_TYPE_BUTT /*invalid pack type */}iv_rd_pack_type_e;
参数说明
成员名称 | 描述 | 取值 |
IV_RD_PACK_TYPE_NONE | 不切分录像文件 | - |
IV_RD_PACK_TYPE_TIME | 按文件时长进行切分文件 | - |
IV_RD_PACK_TYPE_SIZE | 按文件大小进行切分文件 | - |
IV_RD_PACK_TYPE_BUTT | 非法的录像文件切分类型 | - |
注意
不切分类型,录像文件切分不受时长限制,只有当文件达到录像模块支持的最大文件大小后进行文件切分,其中最大文件大小为3G。
按时长切分是指录制的文件时长,假如录制的文件先达到3G但还未达到设置的文件时长,此时也将强制进行切分操作。
iv_rd_play_back_status_e
接口描述
本地录像回放的状态枚举。
typedef enum{IV_RD_PLAYBACK_STA_STOP, /* local recoed playback stop */IV_RD_PLAYBACK_STA_START, /* local recoed playback start */IV_RD_PLAYBACK_STA_BUTT /*invalid playback status */}iv_rd_play_back_status_e;
参数说明
成员名称 | 描述 | 取值 |
IV_RD_PLAYBACK_STA_STOP | 本地录像回放处于停止(未开始)的状态。 | - |
IV_RD_PLAYBACK_STA_START | 本地录像回放处于准备开始播放的状态。 | - |
IV_RD_PLAYBACK_STA_BUTT | 未知类型。 | - |
注意
录像回放处于停止的状态时表明整个回放的链路已经停止,相关线程已经停止,资源已经释放。
录像回放处于准备开始的状态,表明回放的链路已经建立完成,准备开始搜索指定的文件并播放,此前的获取文件列表以及播放指定文件等播放信息数据交互过程已经完成。
iv_rd_init_parm_s
接口描述
模块初始化参数结构。
typedef struct iv_rd_init_parm_s{char s8SdcardPath[64]; /*the sdcard path that use to record*/iv_cm_aenc_sample_rate_e eAudioSampleRate; /*the sample rate of audio*/iv_cm_venc_type_e eVencType; /*venc type*/iv_rd_pack_type_e ePackType; /* record file pack type */union{uint32_t u32PackTimeSec; /* seconds of pack record file */uint32_t u32PackFileSize; /* file size of pack record file */}uPackLen;}iv_rd_init_parm_s;
接口描述
成员名称 | 描述 | 取值 |
s8SdcardPath | SD 卡路径 | - |
eAudioSampleRate | 音频采样率 | 参考 iv_cm_aenc_sample_rate_e |
eVencType | 视频编码类型 | 参考 iv_cm_venc_type_e |
ePackType | 录像文件切分类型 | 参考 iv_rd_pack_type_e |
uPackLen | 录像文件切分长度 | 当 ePackType=IV_RD_PACK_TYPE_TIME 时,uPackLen 等于u32PackTimeSec ;当 ePackType=IV_RD_PACK_TYPE_SIZE 时,uPackLen 等于u32PackFileSize ;当 ePackType=IV_RD_PACK_TYPE_NONE 时,uPackLen 无效 |
示例代码
1. 录像模块初始化
iv_err_code_e eErrCode = 0;iv_rd_init_parm_s stRdInitParm;memset(&stRdInitParm, 0, sizeof(iv_rd_init_parm_s));strcpy(stRdInitParm.s8SdcardPath, "/mnt/disc1/");// /mnt/disc1/stRdInitParm.eAudioSampleRate = IV_CM_AENC_SAMPLE_RATE_8000;stRdInitParm.eVencType = IV_CM_VENC_TYPE_H264;stRdInitParm.ePackType = IV_RD_PACK_TYPE_TIME;stRdInitParm.uPackLen.u32PackTimeSec = 60;stRdInitParm.iv_rd_playback_notice_cb = record_playback_status_cb;//register playback status callback functioneErrCode = iv_rd_init(&stRdInitParm);if(eErrCode < 0){GDB_ERR("fail:%d\\n", eErrCode);return eErrCode;}iv_rd_sort_out_list_file();//sort out record index list file with record file}
2. 录像模块去初始化
iv_err_code_e eErrCode = 0;eErrCode = iv_rd_exit();if(eErrCode < 0){GDB_ERR("fail:%d\\n", eErrCode);return eErrCode;}
3. 录像
pf_audio_stream_s stAudioStream;iv_cm_aenc_stream_s stIvAencStream;av_encdec_dst_type_e eEncdecDstType = AV_ENCDEC_DST_TYPE_RD_HD;pf_venc_stream_s stVencStream;iv_cm_venc_stream_s *pstIvVencStream;memset(&stVencStream, 0, sizeof(pf_venc_stream_s));while(!u32RecordExit){int s32GetAudioStreamRet = 0;int s32GetVideoStreamRet = 0;/*audio data*/s32GetAudioStreamRet = av_encdec_get_audio_stream(eEncdecDstType, &stAudioStream);if(s32GetAudioStreamRet < 0) goto RECORD_NO_AUDIO_DATA;if(0 != stAudioStream.u32Len){stIvAencStream.pu8Stream = stAudioStream.pStream;stIvAencStream.u32Len = stAudioStream.u32Len;stIvAencStream.u64TimeStamp = stAudioStream.u64TimeStamp;//us#if 0GDB_INFO("stAudioStream.u32Len:%d, pts:%lld, %x %x %x %x\\n",stIvAencStream.u32Len, stIvAencStream.u64TimeStamp, stIvAencStream.pu8Stream[8],stIvAencStream.pu8Stream[9], stIvAencStream.pu8Stream[10], stIvAencStream.pu8Stream[11]);#endifiv_rd_push_stream(IV_RD_STREAM_TYPE_AUDIO, (void *)&stIvAencStream);}RECORD_NO_AUDIO_DATA:/*video data*/s32GetVideoStreamRet = av_encdec_get_video_stream(0, eEncdecDstType, &stVencStream);//GDB_INFO("stVencStream.u32Len:%d\\n", stVencStream.pstPack->u32Len);if(s32GetVideoStreamRet < 0) goto RECORD_NO_VIDEO_DATA;pstIvVencStream = (iv_cm_venc_stream_s*)&stVencStream;iv_rd_push_stream(IV_RD_STREAM_TYPE_VIDEO, (void *)pstIvVencStream);RECORD_NO_VIDEO_DATA:if(s32GetAudioStreamRet < 0 && s32GetVideoStreamRet < 0){usleep(5000);continue;}}
4. 测试删除最旧录像
void record_test_drop_oldest_file(){while(1){static int time_cnt = 0;if(time_cnt++ == 12){time_cnt = 0;iv_rd_delete_oldest_file();}sleep(10);}}
5. 回放开启关闭通知
iv_rd_play_back_status_e record_playback_status_cb(uint32_t link_id,iv_rd_play_back_status_e status){GDB_INFO("link id:%d playback status:%s\\n",link_id,status?"start":"stop");#if 0 //if you want to stop playbackif(status == IV_RD_PLAYBACK_STA_START){status = IV_RD_PLAYBACK_STA_STOP;}#endifreturn status;}