VideoMgmt_Buffer.c 7.6 KB
/**************************************************
 * 
 *    文件名:缓冲区管理文件
 * 
 * **********************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#include "JZsdkLib.h"
#include "BaseConfig.h"

#include "./VideoMgmt.h"
#include "../MediaParm.h"
#include "./VideoMgmt_Parm.h"


/*视频流缓冲区地址说明
    留有三对缓冲区,一队中的数据分别为成型数据,以及原始数据

    如果设备只有一个摄像头,则使用一号视频流

    如果设备为 红外+光学 则红外为1号,光学为2号

*/
void *VideoMgmt_FirstVideo_index = NULL; //一号视频流的缓冲地址
void *VideoMgmt_SecondVideo_index = NULL; //二号视频流的缓冲地址
void *VideoMgmt_ThirdVideo_index = NULL; //三号视频流的缓冲地址

void *VideoMgmt_FirstRaw_index = NULL; //一号原始流的缓冲地址
void *VideoMgmt_SecondRaw_index = NULL; //二号原始流的缓冲地址
void *VideoMgmt_ThirdRaw_index = NULL; //三号原始流的缓冲地址

//视频流缓冲区结构  
typedef struct JZsdk_VideoBuffer{  
    unsigned char *data;  //缓冲区数据
    unsigned int data_len;  
    int is_ready; // 标志位,表示数据是否准备好被读取  
    pthread_mutex_t lock; // 互斥锁,用于线程同步  
    pthread_cond_t cond; // 条件变量,用于通知读取线程数据已准备好  
} JZsdk_VideoBuffer; 

// 初始化缓冲区  
T_JZsdkReturnCode VideoMgmt_init_buffer(void **index) 
{  
    //从索引值获取对应的缓冲区
    //创建一个缓冲区
    struct JZsdk_VideoBuffer *VideoBuffer = NULL;

    //为编码器参数注册内存
    VideoBuffer = (struct JZsdk_VideoBuffer *)malloc(sizeof(struct JZsdk_VideoBuffer));  
    if (VideoBuffer == NULL) {  
        JZSDK_LOG_ERROR("视频流缓冲区注册失败");  
        return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;  
    }  
    
    VideoBuffer->data = NULL;  
    VideoBuffer->data_len = 0;  
    VideoBuffer->is_ready = 0;  
    pthread_mutex_init(&VideoBuffer->lock, NULL);  
    pthread_cond_init(&VideoBuffer->cond, NULL);  

    if (*index != NULL)
    {
        free(*index);
    }

    *index = (void *)VideoBuffer;
    
    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}  

//缓冲区清理
T_JZsdkReturnCode VideoMgmt_VideoBuffer_Deinit(void **index)
{
    if (index == NULL || *index == NULL) {  
        // 如果索引或缓冲区指针为空,则直接返回  
        return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
    }  

    //从索引值获取对应的缓冲区
    struct JZsdk_VideoBuffer *VideoBuffer = (struct JZsdk_VideoBuffer *)*index; 

    if (VideoBuffer->data != NULL)
    {
        free(VideoBuffer->data);
        VideoBuffer->data = NULL;
    }
    
    VideoBuffer->data_len = 0;
    VideoBuffer->is_ready = 0;
    pthread_mutex_destroy(&VideoBuffer->lock);  
    pthread_cond_destroy(&VideoBuffer->cond);  

    free(VideoBuffer);
    index = NULL; // 防止悬挂指针  

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

//缓冲区写入
T_JZsdkReturnCode VideoMgmt_write_data(void **index, unsigned char *data, unsigned int data_len)
{
    //从索引值获取对应的缓冲区
    struct JZsdk_VideoBuffer *VideoBuffer = (struct JZsdk_VideoBuffer *)*index; 

    pthread_mutex_lock(&VideoBuffer->lock);  

    // 释放旧数据  
    if (VideoBuffer->data) 
    {  
        free(VideoBuffer->data);  
        VideoBuffer->data = NULL;
    }  
      
    // 分配新内存并复制数据
    VideoBuffer->data = (unsigned char *)malloc(data_len);  
    memcpy(VideoBuffer->data, data, data_len);  
    VideoBuffer->data_len = data_len;  
    VideoBuffer->is_ready = 1; // 标记数据已准备好  
      
    // 通知读取线程数据已准备好  
    pthread_cond_signal(&VideoBuffer->cond);  
      
    pthread_mutex_unlock(&VideoBuffer->lock);  
}

//缓冲区读取
//输入的参数,缓冲区索引地址 回复的数据地址 回复的数据长度 帧头帧尾模式 帧头帧尾长度
T_JZsdkReturnCode VideoMgmt_read_data(void **index, unsigned char **data, unsigned int *data_len, unsigned int mode, unsigned int extra_len)
{
    //从索引值获取对应的缓冲区
    struct JZsdk_VideoBuffer *VideoBuffer = (struct JZsdk_VideoBuffer *)*index; 

    // 检查缓冲区指针是否有效  
    if (VideoBuffer == NULL) 
    {  
        return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 假设的错误码,表示参数无效  
    }  

    pthread_mutex_lock(&VideoBuffer->lock);  
        
    // 等待数据准备好  
    while (!VideoBuffer->is_ready) 
    {  
        pthread_cond_wait(&VideoBuffer->cond, &VideoBuffer->lock);  
    }  

    // 检查数据指针是否有效  
    if (VideoBuffer->data == NULL) 
    {  
        pthread_mutex_unlock(&VideoBuffer->lock);  
        return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 假设的错误码,表示没有数据可供读取  
    }  

    // 返回数据和长度
    *data_len = VideoBuffer->data_len;
    if (mode == JZ_FLAGCODE_OFF)
    {
        *data = (unsigned char *)malloc(*data_len);  
        memcpy(*data, VideoBuffer->data, *data_len);
    }
    else if (mode == VIDEOMGMT_USE_FRAMEHEAD)
    {
        *data = (unsigned char *)malloc(*data_len + extra_len);  
        memcpy(*data+extra_len, VideoBuffer->data, VideoBuffer->data_len);
    }
    else if (mode == VIDEOMGMT_USE_FRAMEEND)
    {
        *data = (unsigned char *)malloc(*data_len + extra_len);  
        memcpy(*data, VideoBuffer->data, VideoBuffer->data_len);
    }   
    else
    {
        *data = (unsigned char *)malloc(*data_len);  
        memcpy(*data, VideoBuffer->data, *data_len);
    }
    
    VideoBuffer->is_ready = 0;
    pthread_mutex_unlock(&VideoBuffer->lock); 
    
    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

/**********
 * 
 *  直接返回地址略有风险,暂时不考虑使用这个以下注释的方法
 * 
 * ************/
// //缓冲区读取
// T_JZsdkReturnCode VideoMgmt_read_data(void **index, unsigned char **data, unsigned int *data_len)
// {
//     //从索引值获取对应的缓冲区
//     struct JZsdk_VideoBuffer *VideoBuffer = (struct JZsdk_VideoBuffer *)*index; 

//     // 检查缓冲区指针是否有效  
//     if (VideoBuffer == NULL) 
//     {  
//         return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 假设的错误码,表示参数无效  
//     }  

//     pthread_mutex_lock(&VideoBuffer->lock);  
        
//     // 等待数据准备好  
//     while (!VideoBuffer->is_ready) 
//     {  
//         pthread_cond_wait(&VideoBuffer->cond, &VideoBuffer->lock);  
//     }  

//     // 检查数据指针是否有效  
//     if (VideoBuffer->data == NULL) 
//     {  
//         pthread_mutex_unlock(&VideoBuffer->lock);  
//         return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 假设的错误码,表示没有数据可供读取  
//     }  

//     // 返回数据和长度
//     *data = (VideoBuffer->data);
//     *data_len = VideoBuffer->data_len;

//     return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
// }

// //回复已经读取完成,在read函数,且数据处理完成后调用
// T_JZsdkReturnCode VideoMgmt_ReplyRead(void **index)
// {
//     //从索引值获取对应的缓冲区
//     struct JZsdk_VideoBuffer *VideoBuffer = (struct JZsdk_VideoBuffer *)*index; 

//     // 检查缓冲区指针是否有效  
//     if (VideoBuffer == NULL) 
//     {  
//         return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 假设的错误码,表示参数无效  
//     }  

//     VideoBuffer->is_ready = 0;
//     pthread_mutex_unlock(&VideoBuffer->lock); 

//     return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
// }