实现数据循环缓存、缓存数据写入文件

538 阅读2分钟

开辟一块内存来循环缓存H264码流,避免碰撞导致录像数据无法写入外存储器中。能够及时将内存碰撞前的一段视频及时存储到内置Flash中。

/************************************************************************
**函数:dvr_h264_prerec_start
**功能:循环缓存H264码流
**参数:
        [in] channel        - 通道号,从1开始
        [in] type           - 1:视频,2:音频
        [in] u64timestamp   - 时间戳(单位us)
        [in] tm             - 底层产生数据时的系统时间
        [in] buf            - 音视频数据
        [in] buf_len        - buf数据长度(in bytes)
**返回:失败返回-1,成功返回0
************************************************************************/
INT32S dvr_h264_prerec_start(CHNNO_APP  channel,
                           INT8U       type,
                           INT64U      u64timestamp,
                           time_t      tm,
                           const void *buf,
                           INT32U      buf_len
                           )
{
	INT32U size_to_max, ret;
	H264_BUFFER_T *pbuf;
	char save_file[100] = {0};
	INT32S fd, len;
	
	ret = dvr_h264_prerec_init(channel);
	if (0 != ret) {
		FK_TRACE_ERROR("[cwr] dvr_h264_prerec_init fail\n");
		return -1;
	}
	pbuf = &s_h264_buf[channel];
	/* 循环缓存海思传过来的H264码流 */
	if (pbuf->H264_buf_offset + buf_len >= H264_MAXBUFSZIE) {
		size_to_max = H264_MAXBUFSZIE - pbuf->H264_buf_offset;
		if (size_to_max < buf_len) {
			FK_TRACE_INFO("[cwr] buf cycle\n");
	        memcpy(pbuf->h264_buf + pbuf->H264_buf_offset, buf, size_to_max);
			memcpy(pbuf->h264_buf, (INT8S *)buf + size_to_max, buf_len - size_to_max);
            pbuf->H264_buf_offset = (buf_len - size_to_max);
		}
	} else {
        memcpy(pbuf->h264_buf + pbuf->H264_buf_offset, buf, buf_len);
        pbuf->H264_buf_offset += buf_len;
	}

	/* 检测到碰撞将缓存数据存储内置Flash */
	if (true == g_fat_crash && false == pbuf->save_h264_state) {	
		snprintf(save_file, 100, "%s/crash_chn%d_save_h264.mp4", H264_SAVE_PATH, channel);
	    fd = open(save_file, O_RDWR|O_CREAT|O_TRUNC);//覆盖原先数据O_TRUNC
	    if(fd < 0) {
	        FK_TRACE_ERROR("[cwr] create flash file fail\n");
			return -1;
	    }
		/* 先写缓存区中旧的数据 */
		len = write(fd, pbuf->h264_buf + pbuf->H264_buf_offset, H264_MAXBUFSZIE - pbuf->H264_buf_offset);
		FK_TRACE_ERROR("[cwr] len = %d, H264_MAXBUFSZIE - pbuf->H264_buf_offset = %d\n", len, H264_MAXBUFSZIE - pbuf->H264_buf_offset);
	    if (len != (H264_MAXBUFSZIE - pbuf->H264_buf_offset)) {
	        FK_TRACE_ERROR("[cwr] write data fail %d\n", fd);
	        if (0 != errno) {
	            FK_TRACE_ERROR("[cwr] [err data] write data errno=%d (%s)!\n", errno, strerror(errno));
	        }
			close(fd);
			return -1;
	    }
		/* 接着写缓存中新的数据 */
		len = write(fd, pbuf->h264_buf, pbuf->H264_buf_offset);
	    if (len != pbuf->H264_buf_offset) {
	        FK_TRACE_ERROR("[cwr] write data fail %d\n", fd);
	        if (0 != errno) {
	            FK_TRACE_ERROR("[cwr] [err data] write data errno=%d (%s)!\n", errno, strerror(errno));
	        }
			close(fd);
			return -1;
	    }
		close(fd);
		FK_TRACE_INFO("[cwr] dvr_save_h264 file %s save suc\n", save_file);
		pbuf->save_h264_state = true;
	}
	return 0;
}