作者 ookk303

更新

正在显示 38 个修改的文件 包含 4800 行增加0 行删除

要显示太多修改。

为保证性能只显示 38 of 38+ 个文件。

#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include "JZsdkLib.h"
#include "../AudioDeal.h"
#include "../FF_Statement.h"
#include "./pcm_AlsaPlay.h"
#include "../AudioDealThread/AudioDealThread.h"
#include "alsa/asoundlib.h"
#define FRAME_SIZE 4 // 假设是双声道16位PCM,即每个帧4字节
struct pcm_AlsaInfo
{
int SampleRate;
snd_pcm_t* g_handle;
snd_pcm_hw_params_t* g_params;
snd_pcm_sw_params_t* g_sw_params;
snd_pcm_status_t* pcm_status;
snd_pcm_uframes_t g_period_size; //实际处理的数数据长度
int g_gorup_size; //每次处理获取的数据长度
int dealFlag; //处理标志位,用于避免卡死
}pcm_AlsaInfo;
extern T_JZsdkReturnCode g_AudioDealPauseFlag;
/**********
*
* 参数初始化
*
* *****/
static T_JZsdkReturnCode AlsaParamInit(struct pcm_AlsaInfo *AlsaInfo, int SampleRate)
{
//设置采样率
AlsaInfo->SampleRate = SampleRate;
//音频设备模式为 0 ,也可以用SND_PCM_ASYNC模式,该模式允许以异步方式进行数据的读写操作
static int open_mode = 0;
//open_mode = open_mode | SND_PCM_ASYNC;
//调用默认default音频设备
int ret = snd_pcm_open(&(AlsaInfo->g_handle), "default", SND_PCM_STREAM_PLAYBACK, open_mode);
if(ret < 0)
{
printf("open device failed\n");
return 0;
}
//设置解码的周期
//g_period_size 的值太大,可能会导致写入操作失败,返回一个负数的错误码;如果 g_period_size 的值太小,可能会导致写入操作成功,但音频播放可能会出现不连续或延迟。
AlsaInfo->g_period_size = 384;
//AlsaInfo->g_period_size = 512;
AlsaInfo->g_gorup_size = AlsaInfo->g_period_size * 2 * 16 / 8; //2声道数 16位深 8字节长度 即真正的一组数据的长度
/***************
*
* 硬件参数分配
*
* **************/
//为硬件参数分配内存空间,并将其指针保存在 g_params 中
snd_pcm_hw_params_alloca(&AlsaInfo->g_params);
//函数初始化硬件参数为默认值
snd_pcm_hw_params_any(AlsaInfo->g_handle, AlsaInfo->g_params);
/* 采样位数 Signed 16-bit little-endian format */
ret = snd_pcm_hw_params_set_format(AlsaInfo->g_handle, AlsaInfo->g_params, SND_PCM_FORMAT_S16);
if (ret < 0)
{
JZSDK_LOG_ERROR("unable to set hw format: %s\n",snd_strerror(ret));
}
/* 交错模式 Interleaved mode */
ret = snd_pcm_hw_params_set_access(AlsaInfo->g_handle, AlsaInfo->g_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (ret < 0)
{
JZSDK_LOG_ERROR("unable to set hw access: %s\n",snd_strerror(ret));
}
/* 通道数 */
ret = snd_pcm_hw_params_set_channels(AlsaInfo->g_handle, AlsaInfo->g_params, 2);
if (ret < 0) {
JZSDK_LOG_ERROR("unable to set hw channels: %s\n",snd_strerror(ret));
}
// ret = snd_pcm_hw_params_set_channels(AlsaInfo->g_handle, AlsaInfo->g_params, 1);
// if (ret < 0) {
// JZSDK_LOG_ERROR("unable to set hw channels: %s\n",snd_strerror(ret));
// }
/* 采样率 44100 bits/second sampling rate (CD quality) */
ret = snd_pcm_hw_params_set_rate_near(AlsaInfo->g_handle, AlsaInfo->g_params, &AlsaInfo->SampleRate, NULL);
if (ret < 0)
{
JZSDK_LOG_ERROR("unable to set hw sampleRate: %s\n",snd_strerror(ret));
}
//设置一个周期的多少帧
ret = snd_pcm_hw_params_set_period_size_near(AlsaInfo->g_handle, AlsaInfo->g_params, &AlsaInfo->g_period_size, NULL);
if (ret < 0) {
JZSDK_LOG_ERROR("unable to set hw period_size: %s\n",snd_strerror(ret));
}
/* 将设置好的参数写入驱动 */
ret = snd_pcm_hw_params(AlsaInfo->g_handle, AlsaInfo->g_params);
if (ret < 0) {
JZSDK_LOG_ERROR("unable to set hw parameters: %s\n",snd_strerror(ret));
return 0;
}
/***************
*
* 软件参数分配
*
* **************/
snd_pcm_sw_params_alloca(&AlsaInfo->g_sw_params);
snd_pcm_uframes_t start_t = 1;
snd_pcm_uframes_t stop_t = 65536 * 2;
ret = snd_pcm_sw_params_current(AlsaInfo->g_handle, AlsaInfo->g_sw_params);
if (ret < 0) {
JZSDK_LOG_ERROR("unable to get current sw params: %s\n",snd_strerror(ret));
}
ret = snd_pcm_sw_params_set_start_threshold(AlsaInfo->g_handle, AlsaInfo->g_sw_params, start_t);
if (ret < 0) {
JZSDK_LOG_ERROR("unable to set sw start_threshold: %s\n",snd_strerror(ret));
}
ret = snd_pcm_sw_params_set_stop_threshold(AlsaInfo->g_handle, AlsaInfo->g_sw_params, stop_t);
if (ret < 0) {
JZSDK_LOG_ERROR("unable to set sw stop_threshold: %s\n",snd_strerror(ret));
}
ret = snd_pcm_sw_params(AlsaInfo->g_handle, AlsaInfo->g_sw_params);/* 将设置好的参数写入驱动 */
if (ret < 0) {
JZSDK_LOG_ERROR("unable to set sw parameters: %s\n",snd_strerror(ret));
return 0;
}
//分配音频设备的状态结构体内存
snd_pcm_status_malloc(&AlsaInfo->pcm_status);
printf("播放参数初始化完毕\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**********
*
* 播放等待参数
*
* *****/
static T_JZsdkReturnCode AlsaWaitPlayEnd(struct pcm_AlsaInfo *AlsaInfo)
{
while(1){
snd_pcm_sframes_t delay_samples = 0;
snd_pcm_delay(AlsaInfo->g_handle, &delay_samples);
//未播放的组小于15个就可以返还了
if(delay_samples <= (AlsaInfo->g_period_size * 15))
{
break;
}
delayUs(100);
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**********
*
* pcm播放线程
*
* *****/
static void *Alsa_CheckThread(void *arg)
{
struct AudioDealInfo *IndexInfo = (struct AudioDealInfo *) arg;
struct pcm_AlsaInfo *AlsaInfo = (struct pcm_AlsaInfo *)IndexInfo->AlsaInfo;
int realLen = 0;//实际数据读取长度
int LastStatus = JZ_FLAGCODE_OFF;
//每10ms检测一次
while (1)
{
snd_pcm_sframes_t delay_samples = 0;
snd_pcm_delay(AlsaInfo->g_handle, &delay_samples);
//JZSDK_LOG_INFO("当前alsa存放了%d组",delay_samples);
if ( (delay_samples > 0) && (LastStatus == JZ_FLAGCODE_OFF))
{
//设置alsa状态
Set_AudioDeal_Alsa_Flag(IndexInfo , JZ_FLAGCODE_ON);
LastStatus = JZ_FLAGCODE_ON;
}
else if ( ( delay_samples == 0 ) && (LastStatus == JZ_FLAGCODE_ON))
{
//设置alsa状态
Set_AudioDeal_Alsa_Flag(IndexInfo , JZ_FLAGCODE_OFF);
LastStatus = JZ_FLAGCODE_OFF;
}
delayMs(10);
}
}
/**********
*
* alsa play反初始化
*
* *****/
// T_JZsdkReturnCode Pcm_Play_deInit(struct pcm_AlsaInfo *AlsaInfo)
// {
// //printf("snd_pcm_hw_params_free\n");
// //snd_pcm_hw_params_free(g_params);
// printf("snd_pcm_drain\n");
// snd_pcm_drain(AlsaInfo->g_handle);
// printf("snd_pcm_close\n");
// snd_pcm_close(AlsaInfo->g_handle);
// }
/**********
*
* alsa play初始化
*
* *****/
T_JZsdkReturnCode AlsaPlay_Init(struct AudioDealInfo *IndexInfo)
{
// 尝试获取或分配ResampleInfo
struct pcm_AlsaInfo **AlsaInfoPtr = (struct pcm_AlsaInfo **)&IndexInfo->AlsaInfo;
if (*AlsaInfoPtr == NULL) {
// 分配内存
*AlsaInfoPtr = (struct pcm_AlsaInfo *)malloc(sizeof(struct pcm_AlsaInfo));
if (*AlsaInfoPtr == NULL) {
// 内存分配失败处理
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 使用更具体的错误码
}
}
else
{
JZsdk_Free(*AlsaInfoPtr);
// 分配内存
*AlsaInfoPtr = (struct pcm_AlsaInfo *)malloc(sizeof(struct pcm_AlsaInfo));
if (*AlsaInfoPtr == NULL) {
// 内存分配失败处理
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 使用更具体的错误码
}
}
struct pcm_AlsaInfo *AlsaInfo = *AlsaInfoPtr;
//设置alsa参数
AlsaParamInit(AlsaInfo, IndexInfo->Target_SampleRate);
//创建pcm检测线程
pthread_t alsa_check_task;
pthread_attr_t task_attribute; //线程属性
pthread_attr_init(&task_attribute); //初始化线程属性
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程属性
int tts_ret = pthread_create(&alsa_check_task,&task_attribute,Alsa_CheckThread,(void *)IndexInfo); //TTS线程
if(tts_ret != 0)
{
JZSDK_LOG_ERROR("创建pcm检测线程失败!\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
T_JZsdkReturnCode Pcm_AlsaPlay(struct AudioDealInfo *IndexInfo, unsigned char *buf, int num_samples)
{
struct pcm_AlsaInfo *AlsaInfo = (struct pcm_AlsaInfo *)IndexInfo->AlsaInfo;
//打开alsa播放标志
IndexInfo->AudioDeal_Alsa_Execute_Flag = JZ_FLAGCODE_ON;
int ret = 0;
//printf("num_samples: %d, g_period_size: %d\n", num_samples, (int)AlsaInfo->g_period_size);
//当输入的数据长度 》 每次写入音频设备时处理的帧数量384
int UnDeal_samples = num_samples;
while(UnDeal_samples > 0 && IndexInfo->AudioDeal_Alsa_Execute_Flag != JZ_FLAGCODE_OFF)
{
int dealSamples = 0;
if (UnDeal_samples >= AlsaInfo->g_period_size)
{
dealSamples = AlsaInfo->g_period_size;
UnDeal_samples = UnDeal_samples - dealSamples;
}
else
{
dealSamples = UnDeal_samples;
UnDeal_samples = UnDeal_samples - dealSamples;
}
//将数据写入alsa音频设备
ret = snd_pcm_writei(AlsaInfo->g_handle, (void*)buf, dealSamples);
//当前设备不可用
if(ret == -EAGAIN)
{
//等待一段时间后重试
printf("again");
snd_pcm_wait(AlsaInfo->g_handle, 1000);
}
//音频设备溢出错误
else if(ret == -EPIPE)
{
printf("snd_pcm_prepare 1\n");
//重置音频设备
snd_pcm_prepare(AlsaInfo->g_handle);
}
//音频设备需要挂起 忙时
else if(ret == -ESTRPIPE)
{
printf("Need suspend!\n");
}
//出现其他错误
else if(ret < 0)
{
printf("snd_pcm_writei error:%s\n", snd_strerror(ret));
}
//位移数据
//buf + 解码的帧数*单帧长度 //单帧长度 2个16bit长度的数据 即2*16/8 = 4字节
buf += dealSamples * FRAME_SIZE;
}
//等待播放完毕
AlsaWaitPlayEnd(AlsaInfo);
//暂停播放
while(g_AudioDealPauseFlag)
{
delayMs(1);
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**********
*
* 清空pcm数据
*
*
* ***********/
T_JZsdkReturnCode Alsa_DropPcm(struct AudioDealInfo *IndexInfo)
{
struct pcm_AlsaInfo *AlsaInfo = (struct pcm_AlsaInfo *)IndexInfo->AlsaInfo;
snd_pcm_drop(AlsaInfo->g_handle);
snd_pcm_prepare(AlsaInfo->g_handle);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
... ...
/**
********************************************************************
* @file pcm_AlsaPlay.h
* pcm_AlsaPlay的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef PCM_ALSAPLAY_H
#define PCM_ALSAPLAY_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "../AudioDeal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode AlsaPlay_Init(struct AudioDealInfo *IndexInfo);
T_JZsdkReturnCode Pcm_AlsaPlay(struct AudioDealInfo *IndexInfo, unsigned char *buf, int num_samples);
T_JZsdkReturnCode Alsa_DropPcm(struct AudioDealInfo *IndexInfo);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <pthread.h>
#include <alsa/asoundlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "FF_Statement.h"
#include "./AudioDeal.h"
#include "JZsdkLib.h"
#include "./AudioDealThread/AudioDealThread.h"
#include "./Alsa/pcm_AlsaPlay.h"
#include "Resample/pcm_Resample.h"
#include "AudioStreamDeal/AudioStreamDeal.h"
#include "Filter/FF_Filter.h"
#define MP3_DIR "/root/sdcard/1.mp3"
#define PCM_16000_DIR "/root/sdcard/16000_test.pcm"
#define READ_SIZE (2000)
//音频库索引值,用于管理所有的音频库信息
struct AudioDealInfo *AudioDeakInfo_index = NULL;
T_JZsdkReturnCode g_AudioDealPauseFlag = JZ_FLAGCODE_OFF;
T_JZsdkReturnCode AudioDeal_Init()
{
T_JZsdkReturnCode ret;
ret = JZsdk_Malloc((void **)&AudioDeakInfo_index, sizeof(struct AudioDealInfo));
//初始化参数
AudioDeakInfo_index->AudioDeal_ResampleAndFilter_Execute_Flag = JZ_FLAGCODE_OFF;
AudioDeakInfo_index->AudioDeal_ResampleAndFilterAndPlay_Finish_Flag = JZ_FLAGCODE_OFF;
AudioDeakInfo_index->Target_SampleRate = 44100; //cd采样率
AudioDeakInfo_index->Target_SampleFormat = AV_SAMPLE_FMT_S16; //16位深
av_channel_layout_copy(&(AudioDeakInfo_index->Target_ChannelLayout), &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
//AudioDeakInfo_index->Target_ChannelLayout = AV_CH_LAYOUT_STEREO; //立体声道
//AudioDeakInfo_index->Target_ChannelLayout = AV_CH_LAYOUT_MONO; //dan声道
AudioDeakInfo_index->Raw_SampleRate = 0;
AudioDeakInfo_index->FilterMode = JZ_FLAGCODE_ON; //滤波模式
//JZSDK_LOG_DEBUG("thread_init开始");
//初始化thread线程管理
AudioDealThread_Init(AudioDeakInfo_index);
AudioDeakInfo_index->AlsaInfo = NULL;
AlsaPlay_Init(AudioDeakInfo_index);
JZSDK_LOG_DEBUG("初始化重采样器开始");
//初始化重采样器, 以下为默认文本的参数
AudioDeakInfo_index->ResampleInfo = NULL;
FF_Resample_Init(AudioDeakInfo_index, 16000, (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, AV_SAMPLE_FMT_S16);
JZSDK_LOG_DEBUG("初始化滤波器开始");
//初始化滤波器
AudioDeakInfo_index->FilterInfo = NULL;
FF_Filter_Init(AudioDeakInfo_index, 0x00);
JZSDK_LOG_INFO("MODULE_AUDIODEL_INIT_COMPLETE");
}
T_JZsdkReturnCode AudioDeal_FilterReset(int mode)
{
FF_Filter_Init(AudioDeakInfo_index, mode);
}
/******************************
*
* 采样器重初始化
*
*
* *********************************************/
T_JZsdkReturnCode AudioDeal_ResampleRest(unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format)
{
FF_Resample_Reset(AudioDeakInfo_index ,in_sampleRate, in_ch_layout, in_format);
}
/***************************************************************************************************************************************************
*
* 各音频播放接口
*
*
* ***************************************************************************************************************************************************/
/***************************
*
* pcm数据接入接口
*
* ************/
T_JZsdkReturnCode AudioDeal_PcmDataInput(int In_Bitrate, unsigned char *buffer, int bytesRead)
{
if (AudioDeakInfo_index == NULL)
{
JZSDK_LOG_ERROR("音频处理器未注册");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
//1、打开音频库的处理标志位,该标志可以重复打开,只有强制关闭音频时,需要关闭该标志
AudioDeakInfo_index->AudioDeal_ResampleAndFilter_Execute_Flag = JZ_FLAGCODE_ON;
//Set_AudioDeal_ResampleAndFilterAndPlay_Flag(AudioDeakInfo_index, JZ_FLAGCODE_ON);
//默认数据pcm接入口都是 单声道,16位
PCM_PooL_Interface_PcmData(AudioDeakInfo_index, In_Bitrate, (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO, AV_SAMPLE_FMT_S16, buffer, bytesRead);
//printf("Read %zu bytes from the PCM file.\n", bytesRead);
//标志音频库已经结束,不过alsa库内有10组缓存,该标志位结束,只能认为重采样和滤波结束
//Set_AudioDeal_ResampleAndFilterAndPlay_Flag(AudioDeakInfo_index, JZ_FLAGCODE_OFF);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/***************************
*
* 无回复接口
*
* ************/
T_JZsdkReturnCode AudioDeal_PcmDataInput_WithoutReply(int In_Bitrate, unsigned char *buffer, int bytesRead)
{
if (AudioDeakInfo_index == NULL)
{
JZSDK_LOG_ERROR("音频处理器未注册");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
//1、打开音频库的处理标志位,该标志可以重复打开,只有强制关闭音频时,需要关闭该标志
AudioDeakInfo_index->AudioDeal_ResampleAndFilter_Execute_Flag = JZ_FLAGCODE_ON;
//默认数据pcm接入口都是 单声道,16位
PCM_PooL_Interface_PcmData(AudioDeakInfo_index, In_Bitrate, (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO, AV_SAMPLE_FMT_S16, buffer, bytesRead);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/***************************
*
* mp3数据接入接口
*
* ************/
T_JZsdkReturnCode AudioDeal_Mp3DataInput(int In_Bitrate, unsigned char *buffer, int bytesRead)
{
if (AudioDeakInfo_index == NULL)
{
JZSDK_LOG_ERROR("音频处理器未注册");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
//1、打开音频库的处理标志位,该标志可以重复打开,只有强制关闭音频时,需要关闭该标志
AudioDeakInfo_index->AudioDeal_ResampleAndFilter_Execute_Flag = JZ_FLAGCODE_ON;
mp3_Stream_Interface_Mp3Data(AudioDeakInfo_index, In_Bitrate, buffer, bytesRead);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/*******************
*
* 暂停播放
* jzon 为暂停播放
* jzoff 为继续播放
* *********************/
T_JZsdkReturnCode AudioDeal_PauseAndContinuePlay(int status)
{
//如果处于实时喊话,禁止使用该功能
g_AudioDealPauseFlag = status;
}
/***************************
*
* 音频文件数据接入接口
*
* ************/
T_JZsdkReturnCode AudioFile_Stream_DataInput(AVFrame *frame)
{
if (AudioDeakInfo_index == NULL)
{
JZSDK_LOG_ERROR("音频处理器未注册");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
//1、打开音频库的处理标志位,该标志可以重复打开,只有强制关闭音频时,需要关闭该标志
AudioDeakInfo_index->AudioDeal_ResampleAndFilter_Execute_Flag = JZ_FLAGCODE_ON;
AudioFile_Stream_Interface_PcmData(AudioDeakInfo_index, frame);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/*********************
*
* 音频库停止处理函数
*
* *********************/
T_JZsdkReturnCode AudioDeal_StopDeal()
{
if (AudioDeakInfo_index == NULL)
{
JZSDK_LOG_ERROR("音频处理器未注册");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
//1、关闭数据处理和alsa部分
AudioDeakInfo_index->AudioDeal_ResampleAndFilter_Execute_Flag = JZ_FLAGCODE_OFF;
AudioDeakInfo_index->AudioDeal_Alsa_Execute_Flag = JZ_FLAGCODE_OFF;
//2、等候完成
while (AudioDeakInfo_index->AudioDeal_ResampleAndFilterAndPlay_Finish_Flag != JZ_FLAGCODE_OFF)
{
delayMs(1);
}
//清空alsa里的缓冲区
Alsa_DropPcm(AudioDeakInfo_index);
while (AudioDeakInfo_index->AudioDeal_Alsa_Finish_Flag != JZ_FLAGCODE_OFF)
{
delayMs(1);
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**************
*
* 获取音频库的处理状态
*
* ***********/
T_JZsdkReturnCode Get_AudioDealStatus()
{
return Get_AudioDealThreadStatus();
}
... ...
/**
********************************************************************
* @file AudioDeal.h
* AudioDeal的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef AUDIO_DEAL_H
#define AUDIO_DEAL_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "libavutil/channel_layout.h"
#include "libavutil/frame.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/*******
*
* 音频库信息结构体
*
* ********/
struct AudioDealInfo
{
int Flag_AudioPlayStatus; //播放状态线程 用于标识当前的播放状态
int Flag_AudioSwicthStatus; //音频切换状态标志位 用于是否是播放中切换播放中
int Flag_AudioDataGeneration; //音频数据产生的标志位 用于判断是否是
int Flag_AlsaPlay; //alsa库的播放标志位,用于标志alsa库是否处于播放中
int Flag_AudioDataGenerationImplement; //数据产生线程执行中
int Flag_AudioDataGenerationFinsh; //数据产生线程执行完毕
int AudioDeal_ResampleAndFilter_Execute_Flag; //音频库的滤波及重采样的执行标志位,用于进行管理音频库的线程使用
int AudioDeal_ResampleAndFilterAndPlay_Finish_Flag; //音频库的滤波及重采样的执行完成的函数
//用于管理alsa部分的内容
int AudioDeal_Alsa_Execute_Flag;
int AudioDeal_Alsa_Finish_Flag;
int FilterMode; //滤波模式
//输出的pcm部分
void *PcmPoolIndex;
unsigned int Target_SampleRate; //目标采样率
unsigned int Target_SampleFormat; //目标采样深度
//unsigned int Target_ChannelLayout; //目标频道数
AVChannelLayout Target_ChannelLayout; //目标通道布局
//alsa部分
void *AlsaInfo;
//重采样
void *ResampleInfo;
//滤波
void *FilterInfo;
//原始数据信息
unsigned int Raw_SampleRate;
unsigned int Raw_SampleFormat; //原始数据信息采样深度
//unsigned int Raw_ChannelLayout; //原始数据信息频道数
AVChannelLayout Raw_ChannelLayout; //原始数据通道布局
}AudioDealInfo;
/*******
*
* 音频库播放类型枚举
*
* ********/
enum AudioDealPlayType
{
AUDIO_TYPE_IDLE = 0x00, //空闲状态
AUDIO_TYPE_FILE = 0x01, //文件播放状态
AUDIO_TYPE_MP3_STREAM = 0x02, //mp3流播放状态
AUDIO_TYPE_PCM_STREAM = 0x03, //pcm流播放状态
}AudioDealPlayType;
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode AudioDeal_Init();
T_JZsdkReturnCode AudioDeal_PcmDataInput(int In_Bitrate, unsigned char *buffer, int bytesRead);
T_JZsdkReturnCode AudioDeal_StopDeal();
T_JZsdkReturnCode AudioDeal_FilePlayInput(unsigned char *FilePath);
T_JZsdkReturnCode AudioDeal_ResampleRest(unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format);
T_JZsdkReturnCode AudioFile_Stream_DataInput(AVFrame *frame);
T_JZsdkReturnCode AudioDeal_Mp3DataInput(int In_Bitrate, unsigned char *buffer, int bytesRead);
T_JZsdkReturnCode AudioDeal_PauseAndContinuePlay(int status);
T_JZsdkReturnCode Get_AudioDealStatus();
T_JZsdkReturnCode AudioDeal_FilterReset(int mode);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "JZsdkLib.h"
#include "../AudioDeal.h"
#include "Megaphone/Megaphone.h"
#include "version_choose.h"
static pthread_mutex_t LibStatusPthread_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t LibStatusPthread_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t PlayStatus_mutex = PTHREAD_MUTEX_INITIALIZER;
static int AudioDealThreadStatus = JZ_FLAGCODE_OFF;
/**************
*
* 设置音频库的处理状态
*
* ***********/
static T_JZsdkReturnCode Set_AudioThreadStatus(int status)
{
AudioDealThreadStatus = status;
}
/**************
*
* 获取音频库的处理状态
*
* ***********/
T_JZsdkReturnCode Get_AudioDealThreadStatus()
{
return AudioDealThreadStatus;
}
/**************
*
* 音频库重采样与滤波标志位
*
* ***********/
T_JZsdkReturnCode Set_AudioDeal_ResampleAndFilterAndPlay_Flag(struct AudioDealInfo *IndexInfo ,int value)
{
pthread_mutex_lock(&LibStatusPthread_mutex);
//状态无变化
if (IndexInfo->AudioDeal_ResampleAndFilterAndPlay_Finish_Flag == value)
{
//直接退出
pthread_mutex_unlock(&LibStatusPthread_mutex);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//1、修改结构体的值
IndexInfo->AudioDeal_ResampleAndFilterAndPlay_Finish_Flag = value;
//2、通知播放状态管理线程
pthread_cond_signal(&LibStatusPthread_cond);
pthread_mutex_unlock(&LibStatusPthread_mutex);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**************
*
* 音频库alsa标志位
*
* ***********/
T_JZsdkReturnCode Set_AudioDeal_Alsa_Flag(struct AudioDealInfo *IndexInfo ,int value)
{
pthread_mutex_lock(&LibStatusPthread_mutex);
//状态无变化
if (IndexInfo->AudioDeal_Alsa_Finish_Flag == value)
{
//直接退出
pthread_mutex_unlock(&LibStatusPthread_mutex);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//1、修改结构体的值
IndexInfo->AudioDeal_Alsa_Finish_Flag = value;
//2、通知播放状态管理线程
pthread_cond_signal(&LibStatusPthread_cond);
pthread_mutex_unlock(&LibStatusPthread_mutex);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/************************
*
* 播放状态线程初始化
*
* *******************/
static void *AudioDeal_LibStatusThread(void *arg)
{
struct AudioDealInfo *IndexInfo = (struct AudioDealInfo *) arg;
while (1)
{
pthread_mutex_lock(&LibStatusPthread_mutex);
//等候解锁线程
pthread_cond_wait(&LibStatusPthread_cond, &LibStatusPthread_mutex);
if (IndexInfo->AudioDeal_Alsa_Finish_Flag == JZ_FLAGCODE_OFF
&& IndexInfo->AudioDeal_ResampleAndFilterAndPlay_Finish_Flag == JZ_FLAGCODE_OFF)
{
//广播音频库的处理部分处于空闲状态
Set_AudioThreadStatus(JZ_FLAGCODE_OFF);
//printf("音频库状态变化off");
}
else
{
Set_AudioThreadStatus(JZ_FLAGCODE_ON);
//printf("音频库状态变化on");
}
pthread_mutex_unlock(&LibStatusPthread_mutex);
}
}
static T_JZsdkReturnCode AudioDeal_LibStatus_Init(struct AudioDealInfo *IndexInfo)
{
pthread_t alsa_play_task;
pthread_attr_t task_attribute; //线程属性
pthread_attr_init(&task_attribute); //初始化线程属性
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程属性
int tts_ret = pthread_create(&alsa_play_task,&task_attribute,AudioDeal_LibStatusThread,(void *)IndexInfo); //TTS线程
if(tts_ret != 0)
{
JZSDK_LOG_ERROR("创建播放线程失败!\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
/************************
*
* 三大线程的管理文件
* 分别是 数据生成线程 播放线程 播放状态线程
*
* *******************/
T_JZsdkReturnCode AudioDealThread_Init(struct AudioDealInfo *IndexInfo)
{
pthread_cond_init(&LibStatusPthread_cond, NULL);
pthread_mutex_init(&LibStatusPthread_mutex, NULL);
pthread_mutex_init(&PlayStatus_mutex, NULL);
AudioDeal_LibStatus_Init(IndexInfo);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
... ...
/**
********************************************************************
* @file AudioDealThread.h
* AudioDealThread
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef AUDIO_DEAL_THREAD_H
#define AUDIO_DEAL_THREAD_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "../AudioDeal.h"
#ifdef __cplusplus
extern "C" {
#endif
T_JZsdkReturnCode Pcm_Data_Pool_Init(struct AudioDealInfo *IndexInfo);
T_JZsdkReturnCode Set_AudioPlayStatus(struct AudioDealInfo *IndexInfo ,enum AudioDealPlayType status, int PlayStatus);
T_JZsdkReturnCode Set_AudioSwitchStatus(struct AudioDealInfo *IndexInfo ,int value);
T_JZsdkReturnCode Set_AudioDataGeneration(struct AudioDealInfo *IndexInfo ,int value);
//T_JZsdkReturnCode Set_AudioDataClear(struct AudioDealInfo *IndexInfo ,int value);
T_JZsdkReturnCode Set_AlsaPlay(struct AudioDealInfo *IndexInfo ,int value);
T_JZsdkReturnCode AudioDealThread_Init(struct AudioDealInfo *IndexInfo);
T_JZsdkReturnCode Set_AudioDeal_ResampleAndFilterAndPlay_Flag(struct AudioDealInfo *IndexInfo ,int value);
T_JZsdkReturnCode Set_AudioDeal_Alsa_Flag(struct AudioDealInfo *IndexInfo ,int value);
T_JZsdkReturnCode Get_AudioDealThreadStatus();
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavcodec/avcodec.h"
#include "AudioDeal/FF_Statement.h"
#include <stdio.h>
#include "JZsdkLib.h"
#include "../AudioDeal.h"
#include "../Resample/pcm_Resample.h"
#include "../Filter/FF_Filter.h"
#include "../Alsa/pcm_AlsaPlay.h"
#include "./AudioStreamDeal.h"
//音频文件直接播放
T_JZsdkReturnCode AudioFile_StartPlay_Interface(struct AudioDealInfo *AD_Info, unsigned char* FilePath)
{
T_JZsdkReturnCode jzret;
//1、检测这个文件是否存在
jzret = JZsdk_check_file_exists((const char *)FilePath);
if (jzret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_INFO("播放文件不存在");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//2、创建音频解码器
const AVCodec *codec;
AVCodecContext *codec_ctx = NULL;
double total_duration = 0; // 累计播放时间(秒)
//3、创建一个音频上下文
AVFormatContext *fmt_ctx;
//4、打开输出的音频文件
int ret = avformat_open_input(&fmt_ctx, FilePath, NULL, NULL);
if (ret < 0) {
JZSDK_LOG_ERROR("歌曲播放文件打开失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//5、检索音频的流信息
if (avformat_find_stream_info(fmt_ctx, NULL) < 0)
{
JZSDK_LOG_ERROR("检索音频的流信息失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//6、找到音频流信息
ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
if (ret < 0) {
JZSDK_LOG_ERROR("无法从文件中找到音频流信息 %d",ret);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
int audio_stream_index = ret;
// //7、查找解码器
// codec = avcodec_find_decoder(fmt_ctx->streams[audio_stream_index]->codecpar->codec_id);
// if (!codec)
// {
// JZSDK_LOG_ERROR("无法找到解码器");
// return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
// }
//8、分配解码器上下文
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
JZSDK_LOG_ERROR("Could not allocate audio codec context");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[audio_stream_index]->codecpar) < 0)
{
JZSDK_LOG_ERROR("Could not copy codec parameters to decoder context");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
codec_ctx->pkt_timebase = fmt_ctx->streams[audio_stream_index]->time_base;
//9、打开解码器
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
JZSDK_LOG_ERROR("Could not open codec");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//10、分配AVPacket和AVFrame
AVPacket *packet = av_packet_alloc();
AVFrame *frame = av_frame_alloc();
AVFrame *temp_frame = av_frame_alloc();
AVFrame *eq_frame = av_frame_alloc();
if (!packet || !frame || !temp_frame || !eq_frame)
{
JZSDK_LOG_ERROR("Could not allocate packet or frame");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//如果此次输入的音频数据不同于采样的当前设置,重设采样
FF_Resample_Reset(AD_Info, codec_ctx->sample_rate, codec_ctx->ch_layout, codec_ctx->sample_fmt);
//读取,并解码歌曲数据
while (AD_Info->AudioDeal_FileRead_Execute_Flag == JZ_FLAGCODE_ON)
{
//读取音频内容
if (av_read_frame(fmt_ctx, packet) < 0) //没有正常取出数据包
{
//执行读取数据完毕之类的操作
JZSDK_LOG_ERROR("没有正常取出数据包");
break;
}
//如果音频流指引值不相同
if (packet->stream_index != audio_stream_index)
{
av_packet_unref(packet);
continue;
}
// 发送数据包到解码器
ret = avcodec_send_packet(codec_ctx, packet);
if (ret < 0)
{
char errbuf[128];
av_strerror(ret, errbuf, sizeof(errbuf));
JZSDK_LOG_ERROR("Error while sending a packet to the decoder %s",errbuf);
break;
}
// 接收解码后的帧
while ( (ret >= 0) && (AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON) )
{
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
//JZSDK_LOG_ERROR("解码完毕");
break;
}
else if (ret < 0)
{
JZSDK_LOG_ERROR("Error while receiving a frame from the decoder\n");
break;
}
// 计算当前帧的持续时间(秒)
double frame_duration = (double)frame->nb_samples / codec_ctx->sample_rate;
//JZSDK_LOG_INFO("nb:%d rate:%d duration:%f", frame->nb_samples, codec_ctx->sample_rate, frame_duration);
// 累计总持续时间
total_duration += frame_duration;
//JZSDK_LOG_INFO("当前播放时间%f",total_duration);
int out_nb_samples = 0;
//丢进重采样器
void* resampledData = FF_Resample_Send_And_Get_ResampleData(AD_Info ,frame->data, frame->nb_samples, &out_nb_samples);
//滤波
if(AD_Info->FilterMode != JZ_FLAGCODE_OFF)
{
temp_frame->data[0] = (unsigned char*)resampledData;
temp_frame->nb_samples = out_nb_samples;
//将临时帧 放入 均衡滤波器
FF_Filter_push_frame_to_fliter(AD_Info, temp_frame);
while(AD_Info->Flag_AudioDataGenerationImplement == JZ_FLAGCODE_ON)
{
//得到滤波器输出的音频帧 eq_frame
int fret = FF_Filter_get_frame_from_filter(AD_Info, eq_frame);
if (fret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
break;
}
//播放改滤波后的帧
Pcm_AlsaPlay(AD_Info, (unsigned char*)eq_frame->data[0], eq_frame->nb_samples);
av_frame_unref(eq_frame);
}
av_frame_unref(temp_frame);
}
else //不滤波
{
//直接播放
//JZSDK_LOG_INFO("播放 %d 数据",out_nb_samples);
Pcm_AlsaPlay(AD_Info ,resampledData, out_nb_samples);
}
FF_Resample_freeReasmpleData(resampledData);
}
av_packet_unref(packet);
}
// 清理资源
av_frame_free(&frame);
av_frame_free(&temp_frame);
av_frame_free(&eq_frame);
av_packet_free(&packet);
avcodec_free_context(&codec_ctx);
avformat_close_input(&fmt_ctx);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
... ...
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavcodec/avcodec.h"
#include "AudioDeal/FF_Statement.h"
#include <stdio.h>
#include "JZsdkLib.h"
#include "../AudioDeal.h"
#include "../Resample/pcm_Resample.h"
#include "../Filter/FF_Filter.h"
#include "../Alsa/pcm_AlsaPlay.h"
#include "./AudioStreamDeal.h"
/***************************
*
* 文件播放的数据入口
*
* ************/
T_JZsdkReturnCode AudioFile_Stream_Interface_PcmData(struct AudioDealInfo *AD_Info, AVFrame *frame)
{
AVFrame *eq_frame = av_frame_alloc();
AVFrame *temp_frame = av_frame_alloc();
if (!eq_frame || !temp_frame)
{
JZSDK_LOG_ERROR("Could not allocate packet or frame");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
int out_nb_samples = 0;
//丢进重采样器
void* resampledData = FF_Resample_Send_And_Get_ResampleData(AD_Info ,frame->data, frame->nb_samples, &out_nb_samples);
//JZSDK_LOG_INFO("滤波已完成");
//滤波
if(AD_Info->FilterMode != JZ_FLAGCODE_OFF)
{
temp_frame->data[0] = (unsigned char*)resampledData;
temp_frame->nb_samples = out_nb_samples;
//将临时帧 放入 均衡滤波器
FF_Filter_push_frame_to_fliter(AD_Info, temp_frame);
//JZSDK_LOG_INFO("放入均衡器");
while(AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON)
{
//得到滤波器输出的音频帧 eq_frame
int fret = FF_Filter_get_frame_from_filter(AD_Info, eq_frame);
if (fret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
break;
}
//播放改滤波后的帧
Pcm_AlsaPlay(AD_Info, (unsigned char*)eq_frame->data[0], eq_frame->nb_samples);
//JZSDK_LOG_INFO("代替播放 %d", eq_frame->nb_samples);
av_frame_unref(eq_frame);
}
av_frame_unref(temp_frame);
}
else //不滤波
{
//直接播放
//JZSDK_LOG_INFO("播放 %d 数据",out_nb_samples);
Pcm_AlsaPlay(AD_Info ,resampledData, out_nb_samples);
}
FF_Resample_freeReasmpleData(resampledData);
av_frame_free(&eq_frame);
av_frame_free(&temp_frame);
}
... ...
/**
********************************************************************
* @file AudioStreamDeal.h
* AudioStreamDeal的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef AUDIO_STREAM_DEAL_H
#define AUDIO_STREAM_DEAL_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "AudioDeal/FF_Statement.h"
#include "../AudioDeal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
int PCM_PooL_Interface_PcmData(struct AudioDealInfo *AD_Info,unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format , unsigned char* data, int dataSize);
int PCM_PooL_Interface_PcmData_WithoutReply(struct AudioDealInfo *AD_Info,unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format , unsigned char* data, int dataSize);
T_JZsdkReturnCode AudioFile_Stream_Interface_PcmData(struct AudioDealInfo *AD_Info, AVFrame *frame);
T_JZsdkReturnCode mp3_Stream_Interface_Mp3Data(struct AudioDealInfo *AD_Info, unsigned int in_sampleRate, unsigned char *data, int dataSize);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include "AudioDeal/FF_Statement.h"
#include "../Resample/pcm_Resample.h"
#include "AudioDeal/AudioDeal.h"
#include "AudioDeal/Filter/FF_Filter.h"
#include "JZsdkLib.h"
#include "AudioDeal/Alsa/pcm_AlsaPlay.h"
/******************************
*
* 用于处理mp3流的.c
* 输入mp3数据 → 解码成pcm → pcm流处理模块
*
* ******************************/
static AVCodecParserContext *parser = NULL;
static AVCodecContext *cdc_ctx = NULL;
static AVPacket *pkt;
static AVFrame *decoded_frame = NULL;
static const AVCodec *codec;
T_JZsdkReturnCode Stream_Player_decode(struct AudioDealInfo *AD_Info, AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame);
int File_Stream_deal_Init(enum AVCodecID id)
{
pkt = av_packet_alloc();
if(!pkt)
{
JZSDK_LOG_ERROR("av_packet_alloc failed.");
}
codec = avcodec_find_decoder(id);
if (!codec) {
JZSDK_LOG_ERROR("Codec not found\n");
}
parser = av_parser_init(codec->id);
if (!parser) {
JZSDK_LOG_ERROR("Parser not found\n");
}
cdc_ctx = avcodec_alloc_context3(codec);
if (!cdc_ctx) {
JZSDK_LOG_ERROR("Could not allocate audio codec context\n");
}
/* open it */
if (avcodec_open2(cdc_ctx, codec, NULL) < 0)
{
JZSDK_LOG_ERROR("Could not open codec\n");
}
//如果解码器不存在,初始化解码器
if (!decoded_frame)
{
if (!(decoded_frame = av_frame_alloc()))
{
JZSDK_LOG_ERROR("Could not allocate audio frame\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
}
//输入mp3的实时数据,以及本次数据的长度
T_JZsdkReturnCode mp3_Stream_Interface_Mp3Data(struct AudioDealInfo *AD_Info, unsigned int in_sampleRate, unsigned char *data, int dataSize)
{
//将数据输入到
while(dataSize > 0)
{
//检查参数,并将正确的数据输入到pkt中
//parser 解析器
//cdc_ctx 上下文
//pkt输出的数据指针
//data datasize 输入的数据指针
//pts、dts、pos:时间戳和位置信息,一般可以设置为AV_NOPTS_VALUE和0。
int ret = av_parser_parse2(parser, cdc_ctx, &pkt->data, &pkt->size, data, dataSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
printf("Error while parsing\n");
return -1;
}
//重置重采样器
FF_Resample_Reset(AD_Info, in_sampleRate, (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO, AV_SAMPLE_FMT_S16);
//数据指针 往后一个解析长度
//长度指针 减少一个被解析数据的长度
data += ret;
dataSize -= ret;
//如果输出有长度 解码输出的数据
if (pkt->size > 0)
{
Stream_Player_decode(AD_Info, cdc_ctx, pkt, decoded_frame);
}
}
}
//
T_JZsdkReturnCode Stream_Player_decode(struct AudioDealInfo *AD_Info, AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame)
{
int ret;
//发送数据包给解码器解码,已将数据解码为pcm原始数据
ret = avcodec_send_packet(dec_ctx, pkt);
if (ret < 0)
{
JZSDK_LOG_ERROR("Error submitting the packet to the decoder, ret=%d\n",ret);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//申请内存
AVFrame *eq_frame = av_frame_alloc();
AVFrame *temp_frame = av_frame_alloc();
/* read all the output frames (in general there may be any number of them */
//读取输出的帧
while ( (ret >= 0) && (AD_Info->Flag_AudioDataGenerationImplement == JZ_FLAGCODE_ON) )
{
//从解码器中读取解码后的音频帧数据
ret = avcodec_receive_frame(dec_ctx, frame);
//输出帧不可用 、 输出帧 已用完
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
break;
}
else if (ret < 0)
{
JZSDK_LOG_ERROR("Error during decoding\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
int out_nb_samples = 0;
//重采样解码后的数据
void* resampledData = FF_Resample_Send_And_Get_ResampleData(AD_Info, frame->data, frame->nb_samples, &out_nb_samples);
//滤波
if(AD_Info->FilterMode != JZ_FLAGCODE_OFF)
{
temp_frame->data[0] = (unsigned char*)resampledData;
temp_frame->nb_samples = out_nb_samples;
//将临时帧 放入 均衡滤波器
FF_Filter_push_frame_to_fliter(AD_Info, temp_frame);
while(AD_Info->Flag_AudioDataGenerationImplement == JZ_FLAGCODE_ON)
{
//得到滤波器输出的音频帧 eq_frame
int fret = FF_Filter_get_frame_from_filter(AD_Info, eq_frame);
if (fret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
break;
}
//播放改滤波后的帧
Pcm_AlsaPlay(AD_Info, (unsigned char*)eq_frame->data[0], eq_frame->nb_samples);
av_frame_unref(eq_frame);
}
av_frame_unref(temp_frame);
}
else //不滤波
{
//直接播放
//JZSDK_LOG_INFO("播放 %d 数据",out_nb_samples);
Pcm_AlsaPlay(AD_Info ,resampledData, out_nb_samples);
}
FF_Resample_freeReasmpleData(resampledData);
}
//释放掉输出的变量
av_frame_unref(temp_frame);
av_frame_unref(eq_frame);
}
... ...
#include <stdio.h>
#include "AudioDeal/FF_Statement.h"
#include "../Alsa/pcm_AlsaPlay.h"
#include "AudioDeal/AudioDeal.h"
#include "../Filter/FF_Filter.h"
#include "../Resample/pcm_Resample.h"
#include "JZsdkLib.h"
#include "./AudioStreamDeal.h"
#define MEM_BLOCK_LEN (4096) //设置内存块处理长度为4096
/***************************
*
* pcm数据池子,pcm数据的接入接口
*
* ************/
int PCM_PooL_Interface_PcmData(struct AudioDealInfo *AD_Info,unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format , unsigned char* data, int dataSize)
{
T_JZsdkReturnCode ret;
//这段代码遍历 data,将连续的 0x00 0x00 替换为 0x00 0x01。这可能是为了确保音频数据中没有静默的连续帧,或者是为了满足某种特定的播放要求。
for(int i=0; i<dataSize; i+=2)
{
if(i+1 < dataSize && data[i]==0x00 && data[i+1]==0x00)
{
data[i+1] = 0x01; // MSB,LSB
}
}
//分配了两个 AVFrame 对象,一个用于临时存储重采样后的数据(temp_frame),另一个用于从过滤器中获取数据(eq_frame)。
AVFrame *temp_frame = av_frame_alloc();
AVFrame *eq_frame = av_frame_alloc();
//如果此次输入的音频数据不同于采样的当前设置,重设采样
FF_Resample_Reset(AD_Info, in_sampleRate, in_ch_layout, in_format);
int out_nb_samples = 0; //重采样输出的数据长度
int UnDeal_DataSize = dataSize; //未处理的数据长度
while( (UnDeal_DataSize > 0) && (AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON))
{
int dealLen = 0;
if (UnDeal_DataSize > MEM_BLOCK_LEN)
{
dealLen = MEM_BLOCK_LEN;
UnDeal_DataSize = UnDeal_DataSize - dealLen;
}
else
{
dealLen = UnDeal_DataSize;
UnDeal_DataSize = UnDeal_DataSize - dealLen;
}
//重采样 //仅处理一半样本量
void *resampledData = FF_Resample_Send_And_Get_ResampleData(AD_Info, &data, dealLen/2, &out_nb_samples);
//如果滤波打开
//滤波处理
if(AD_Info->FilterMode != JZ_FLAGCODE_OFF)
{
temp_frame->data[0] = (unsigned char*)resampledData;
temp_frame->nb_samples = out_nb_samples;
//将临时帧 放入 均衡滤波器
FF_Filter_push_frame_to_fliter(AD_Info, temp_frame);
while(AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON)
{
//得到滤波器输出的音频帧 eq_frame
int fret = FF_Filter_get_frame_from_filter(AD_Info, eq_frame);
if (fret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
break;
}
//播放改滤波后的帧
Pcm_AlsaPlay(AD_Info, (unsigned char*)eq_frame->data[0], eq_frame->nb_samples);
av_frame_unref(eq_frame);
}
av_frame_unref(temp_frame);
}
else //不滤波
{
//直接播放
//JZSDK_LOG_INFO("播放 %d 数据",out_nb_samples);
Pcm_AlsaPlay(AD_Info ,resampledData, out_nb_samples);
}
//先改用保存
//AudioDeal_Test_DataSave((unsigned char *)resampledData, out_nb_samples, ResampleInfo->Out_SampleRate, 1, 16);
FF_Resample_freeReasmpleData(resampledData);
data += dealLen;
}
av_frame_free(&temp_frame);
av_frame_free(&eq_frame);
}
... ...
/**
********************************************************************
* @file FF_Resample.h
* FF_Resample
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef FF_STATEMENT_H
#define FF_STATEMENT_H
/* Includes ------------------------------------------------------------------*/
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libavutil/samplefmt.h"
#include "libswresample/swresample.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/frame.h"
#include "libavutil/avutil.h"
#include "libavutil/samplefmt.h"
#include "libavfilter/avfilter.h"
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libavutil/samplefmt.h"
#include "libavutil/frame.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavcodec/avcodec.h"
#include "AudioDeal/FF_Statement.h"
#include <stdio.h>
#include "JZsdkLib.h"
#include "../AudioDeal.h"
#include "./FF_FilterParam.h"
struct FF_Filter
{
//创建滤波器上下文
AVFilterContext *abuffersrc_ctx;
const AVFilter *abuffersrc;
AVFilterContext *abuffersink_ctx;
const AVFilter *abuffersink;
// 创建滤波器图
AVFilterGraph *filter_graph;
AVFilterInOut *outputs, *inputs;
AVFilterLink *outlink;
AVChannelLayout ch_layout;
//输入音频的参数
int In_SampleRate;
enum AVSampleFormat In_Format;
}FF_Filter;
static int FilterFlag = JZ_FLAGCODE_OFF;
static T_JZsdkReturnCode FF_Filter_ParamInit(struct AudioDealInfo *AD_Info, unsigned char *FilterParam)
{
// 尝试获取或分配FilterInfo
struct FF_Filter **FilterInfoPtr = (struct FF_Filter **)&AD_Info->FilterInfo;
if (*FilterInfoPtr == NULL) {
// 分配内存
*FilterInfoPtr = (struct FF_Filter *)malloc(sizeof(struct FF_Filter));
if (*FilterInfoPtr == NULL) {
// 内存分配失败处理
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 使用更具体的错误码
}
}
/*************
*
* 初始化
*
* ****************/
//创建一个记录结结构体
struct FF_Filter *FilterInfo = *FilterInfoPtr;
//参数填写数组
char args[512];
int ret = 0;
// 创建滤波器发送实例
FilterInfo->abuffersrc = avfilter_get_by_name("abuffer");
// 创建滤波器接收实例
FilterInfo->abuffersink = avfilter_get_by_name("abuffersink");
//注册端点
FilterInfo->inputs = avfilter_inout_alloc();
if (!FilterInfo->inputs)
{
JZSDK_LOG_ERROR("in端点创建失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
FilterInfo->outputs = avfilter_inout_alloc();
if (!FilterInfo->outputs)
{
JZSDK_LOG_ERROR("out端点创建失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
enum AVSampleFormat out_sample_fmts[] = { AD_Info->Target_SampleFormat, -1 };
int out_sample_rates[] = { AD_Info->Target_SampleRate, -1 };
FilterInfo->outlink = NULL;
//没有做时基
//AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base;
// 创建滤波器图
FilterInfo->filter_graph = avfilter_graph_alloc();
if (!FilterInfo->filter_graph)
{
// 错误处理:无法分配滤波器图
JZSDK_LOG_ERROR("滤波器图创建失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
printf("Filter初始化完成\n");
/*************
*
* 创建滤波器链
*
* ****************/
// if (AD_Info->Target_ChannelLayout == AV_CHANNEL_LAYOUT_STEREO)
// {
// FilterInfo->In_Channels = 2;
// }
// else
// {
// FilterInfo->In_Channels = 1;
// }
//FilterInfo->In_Channels = AD_Info->Target_ChannelLayout.nb_channels;
//av_channel_layout_default(&FilterInfo->ch_layout, FilterInfo->In_Channels);
av_channel_layout_copy(&FilterInfo->ch_layout, &AD_Info->Target_ChannelLayout);
memset(args, 0 ,sizeof(args));
ret = snprintf(args, sizeof(args),
"sample_rate=%d:sample_fmt=%s:channel_layout=",
AD_Info->Target_SampleRate,
av_get_sample_fmt_name(AD_Info->Target_SampleFormat));
av_channel_layout_describe(&FilterInfo->ch_layout, args + ret, sizeof(args) - ret);
ret = avfilter_graph_create_filter(&FilterInfo->abuffersrc_ctx, FilterInfo->abuffersrc, "in",
args, NULL, FilterInfo->filter_graph);
if (ret < 0)
{
// 错误处理:无法创建abuffer滤波器
JZSDK_LOG_ERROR("无法创建abuffer滤波器 ");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//建立输出参数
if (avfilter_graph_create_filter(&FilterInfo->abuffersink_ctx, FilterInfo->abuffersink, "out", NULL, NULL, FilterInfo->filter_graph) < 0)
{
// 错误处理:无法创建abuffersink滤波器
JZSDK_LOG_ERROR("无法创建abuffersink滤波器 ");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
ret = av_opt_set_int_list(FilterInfo->abuffersink_ctx, "sample_fmts", out_sample_fmts, -1, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
JZSDK_LOG_ERROR("Cannot set output sample format");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
ret = av_opt_set(FilterInfo->abuffersink_ctx, "ch_layouts", "stereo",
AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
JZSDK_LOG_ERROR("Cannot set output channel layout");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
ret = av_opt_set_int_list(FilterInfo->abuffersink_ctx, "sample_rates", out_sample_rates, -1,
AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
JZSDK_LOG_ERROR("Cannot set output sample rate");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
printf("Filter滤波器链完成\n");
/*************
*
* 设置滤镜图的端点。这个滤镜图将依据filters_descr中的描述进行链接。
*
* ****************/
// 设置输出端点的信息,其名称设为"in",关联的滤镜上下文为buffersrc_ctx,焊盘索引为0,并设置下一个端点为NULL。
FilterInfo->outputs->name = av_strdup("in");
FilterInfo->outputs->filter_ctx = FilterInfo->abuffersrc_ctx;
FilterInfo->outputs->pad_idx = 0;
FilterInfo->outputs->next = NULL;
/*
* 缓冲区源(buffersrc)的输出应连接到filters_descr中描述的第一个滤镜的输入焊盘;
* 如果没有明确指定第一个滤镜的输入标签,则默认使用"in"。
*/
// 设置输入端点的信息,其名称设为"out",关联的滤镜上下文为buffersink_ctx,焊盘索引为0,并设置下一个端点为NULL。
FilterInfo->inputs->name = av_strdup("out");
FilterInfo->inputs->filter_ctx = FilterInfo->abuffersink_ctx;
FilterInfo->inputs->pad_idx = 0;
FilterInfo->inputs->next = NULL;
printf("Filter端点完成\n");
/*************
*
* 链接滤波器
*
* ****************/
char filters_descr[1024];
// sprintf(filters_descr,
// "anequalizer=c0 f=250 w=500 g=-48 t=2|c1 f=250 w=500 g=-48 t=2,anequalizer=c0 f=3000 w=1000 g=-48 t=2|c1 f=3000 w=1000 g=-48 t=2"
// );
sprintf(filters_descr,
"%s",FilterParam
);
//使用avfilter_graph_parse_ptr函数解析滤镜图,将filters_descr中的描述转换成实际的滤镜和连接。
ret = avfilter_graph_parse_ptr(FilterInfo->filter_graph, filters_descr, &FilterInfo->inputs, &FilterInfo->outputs, NULL);
if (ret < 0)
{
JZSDK_LOG_ERROR("滤波配置出错");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
/*
* 使用avfilter_graph_config函数配置滤镜图,使其准备好处理数据。
* 如果配置失败,则返回错误码。
*/
if ((ret = avfilter_graph_config(FilterInfo->filter_graph, NULL)) < 0){
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
/*
* 打印接收器缓冲区(buffersink)的摘要。
* 注意:args缓冲区被重用以存储声道布局字符串。
*/
FilterInfo->outlink = FilterInfo->abuffersink_ctx->inputs[0];
av_channel_layout_describe(&FilterInfo->outlink->ch_layout, args, sizeof(args));
av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n",
(int)FilterInfo->outlink->sample_rate,
(char *)av_x_if_null(av_get_sample_fmt_name(FilterInfo->outlink->format), "?"),
args);
/*
* 释放inputs和outputs结构体所占用的内存。
*/
avfilter_inout_free(&FilterInfo->inputs);
avfilter_inout_free(&FilterInfo->outputs);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
T_JZsdkReturnCode FF_Filter_Release(struct AudioDealInfo *AD_Info)
{
if (AD_Info == NULL || AD_Info->FilterInfo == NULL)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
struct FF_Filter *FilterInfo = (struct FF_Filter *)AD_Info->FilterInfo;
// 释放滤波器图
if (FilterInfo->filter_graph) {
avfilter_graph_free(&FilterInfo->filter_graph);
FilterInfo->filter_graph = NULL; // 避免野指针
}
// // 释放过滤器实例
// if (FilterInfo->abuffersrc_ctx) {
// avfilter_free(FilterInfo->abuffersrc_ctx);
// FilterInfo->abuffersrc_ctx = NULL; // 避免野指针
// }
// if (FilterInfo->abuffersink_ctx) {
// avfilter_free(FilterInfo->abuffersink_ctx);
// FilterInfo->abuffersink_ctx = NULL; // 避免野指针
// }
// 释放输入输出端点
if (FilterInfo->inputs) {
avfilter_inout_free(&FilterInfo->inputs);
FilterInfo->inputs = NULL; // 避免野指针
}
if (FilterInfo->outputs) {
avfilter_inout_free(&FilterInfo->outputs);
FilterInfo->outputs = NULL; // 避免野指针
}
// 释放FilterInfo结构体本身
free(FilterInfo);
AD_Info->FilterInfo = NULL;
FilterFlag = JZ_FLAGCODE_OFF;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/***********************
*
* 滤波器初始化
*
* **************/
T_JZsdkReturnCode FF_Filter_Init(struct AudioDealInfo *AD_Info, int mode)
{
T_JZsdkReturnCode ret;
//如果已经注册过滤波器
if (FilterFlag == JZ_FLAGCODE_ON)
{
ret = FF_Filter_Release(AD_Info);
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_ERROR("filter init error");
}
}
//初始化滤波器
if(mode == 0x00)
{
ret =FF_Filter_ParamInit(AD_Info, FILTER_PARAM);
}
else if (mode == 0x01)
{
ret =FF_Filter_ParamInit(AD_Info, Filter_M30);
}
else
{
ret =FF_Filter_ParamInit(AD_Info, FILTER_PARAM);
}
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_ERROR("filter init error");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
FilterFlag = JZ_FLAGCODE_ON;
JZSDK_LOG_DEBUG("Filter注册完成\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//将帧放入滤波器
T_JZsdkReturnCode FF_Filter_push_frame_to_fliter(struct AudioDealInfo *AD_Info ,AVFrame* in_frame)
{
struct FF_Filter *FilterInfo = (struct FF_Filter *)AD_Info->FilterInfo;
//给inframe除了音频数据和长度外的参数
in_frame->sample_rate = AD_Info->Target_SampleRate;
in_frame->format = AD_Info->Target_SampleFormat;
//av_channel_layout_copy(&frame->ch_layout, &INPUT_CHANNEL_LAYOUT);
// in_frame->channel_layout = AV_CH_LAYOUT_STEREO;
// in_frame->channels = 2;
av_channel_layout_copy(&in_frame->ch_layout, &AD_Info->Target_ChannelLayout);
int ret = av_buffersrc_add_frame_flags(FilterInfo->abuffersrc_ctx, in_frame, AV_BUFFERSRC_FLAG_KEEP_REF);
if (ret < 0)
{
JZSDK_LOG_ERROR("Error while feeding the audio filtergraph");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
T_JZsdkReturnCode FF_Filter_get_frame_from_filter(struct AudioDealInfo *AD_Info ,AVFrame* out_frame)
{
struct FF_Filter *FilterInfo = (struct FF_Filter *)AD_Info->FilterInfo;
int ret = av_buffersink_get_frame(FilterInfo->abuffersink_ctx, out_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file FF_Filter.h
* FF_Filter
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef FF_FILTER_H
#define FF_FILTER_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "AudioDeal/FF_Statement.h"
#ifdef __cplusplus
extern "C" {
#endif
T_JZsdkReturnCode FF_Filter_Init(struct AudioDealInfo *AD_Info, int mode);
T_JZsdkReturnCode FF_Filter_push_frame_to_fliter(struct AudioDealInfo *AD_Info ,AVFrame* in_frame);
T_JZsdkReturnCode FF_Filter_get_frame_from_filter(struct AudioDealInfo *AD_Info ,AVFrame* out_frame);
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
/**
********************************************************************
* @file FF_FilterParam.h
* FF_FilterParam.h
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef FF_FILTER_PARAM_H
#define FF_FILTER_PARAM_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
//流程 先用 acompressor 压缩动态范围 会影响声音大小
#define Filter_No1 "anequalizer=c0 f=2000 w=2000 g=+12 t=2|c1 f=2000 w=2000 g=+12 t=2"
#define Filter_No2 "acompressor=level_in=1.2:mode=downward:threshold=0.2:ratio=3:attack=50:release=300:makeup=1.2:knee=4:link=average:detection=rms:mix=0.8,highpass=f=300:p=2:mix=1,lowpass=f=5000:p=2:mix=1,lowpass=f=6000:p=2:mix=1,anequalizer=c0 f=2300 w=1500 g=+12 t=2|c1 f=2300 w=1500 g=+12 t=2"
/*
-level_in=1.5:设置输入增益为1.5,这通常用于增加输入信号的响度。
-mode=downward:设置压缩器的工作模式为向下压缩,即仅当信号超过阈值时减少增益。
-threshold=0.5:设置阈值,具体单位取决于该工具的实现,但通常与信号电平相关。
-ratio=3:1:设置压缩比为3:1,意味着每增加3dB的输入电平,输出电平仅增加1dB。
-attack=50ms:设置攻击时间为50毫秒,即信号需要超过阈值50毫秒后才开始压缩。
-release=300ms:设置释放时间为300毫秒,即信号需要低于阈值300毫秒后压缩效果才会逐渐减弱。
-makeup=1.2:设置补偿增益为1.2,用于在压缩后增加信号的总体响度。
-knee=4:设置拐点为4,用于在阈值附近平滑地过渡压缩效果。
-link=average:选择使用所有通道的平均电平来影响压缩,而不是仅使用最响的通道。
-detection=rms:选择使用RMS(均方根)检测来确定信号电平,这通常比峰值检测更平滑。
-mix=0.8:设置混合比例为0.8,意味着在输出中80%使用压缩后的信号,20%使用原始信号(这个参数的具体实现可能因工具而异)。
level_in:原信号的输入增益,相当于前置放大器,默认为1,范围[0.015625, 64]
mode:压缩模式,有 upward和downward两种模式, 默认为downward
threshold:如果媒体流信号达到此阈值,会引起增益减少。默认为0.125,范围[0.00097563, 1]
ratio:信号压缩的比例因子,默认为2,范围[1, 20]
attack:信号提升到阈值所用的毫秒数,默认为20,范围[0.01, 2000]
release:信号降低到阈值所用的毫秒数,默认为250,范围[0.01, 9000]
makeup:在处理后,多少信号被放大. 默认为1,范围[1, 64]
knee:增益降低的阶数,默认为2.82843,范围[1, 8]
link:信号衰减的average和maximum两种模式, 默认为average
detection:采用peak峰值信号或rms均方根信号,默认采用更加平滑的rms
mix:输出时使用多少压缩信号, 默认为1,范围[0, 1]
2、acrossfade
*/
/**
*
Attenuate 10 dB at 1000 Hz, with a bandwidth of 200 Hz:
equalizer=f=1000:t=h:width=200:g=-10
Apply 2 dB gain at 1000 Hz with Q 1 and attenuate 5 dB at 100 Hz with Q 2:
equalizer=f=1000:t=q:w=1:g=2,equalizer=f=100:t=q:w=2:g=-5
在您给出的例子中,您正在使用 equalizer 滤镜来调整音频信号的特定频率点。这些命令很可能是为了某种音频处理软件或库(如 FFmpeg 的滤镜系统,尽管 FFmpeg 的标准滤镜中可能没有直接名为 equalizer 的滤镜,但这里我们假设它是一个自定义或第三方滤镜)设计的。
第一个例子
Attenuate 10 dB at 1000 Hz, with a bandwidth of 200 Hz:
equalizer=f=1000:t=h:width=200:g=-10
f=1000 设置滤波器的中心频率为 1000 Hz。
t=h 或 t=Hz(尽管 t=h 可能是一个简写,但通常更明确的是 t=Hz)指定带宽的单位为 Hz。
width=200 设置滤波器的带宽为 200 Hz。
g=-10 设置在中心频率处的增益为 -10 dB,即衰减 10 dB。
第二个例子
Apply 2 dB gain at 1000 Hz with Q 1 and attenuate 5 dB at 100 Hz with Q 2:
equalizer=f=1000:t=q:w=1:g=2,equalizer=f=100:t=q:w=2:g=-5
第一个 equalizer 滤镜设置:
f=1000 设置中心频率为 1000 Hz。
t=q 指定带宽的单位为 Q 因子。
w=1 设置 Q 因子为 1,这会影响滤波器的带宽和尖锐程度。Q 因子越高,带宽越窄,滤波器越尖锐。
g=2 设置在中心频率处的增益为 2 dB。
第二个 equalizer 滤镜设置:
f=100 设置中心频率为 100 Hz。
同样地,t=q 指定带宽的单位为 Q 因子。
w=2 设置 Q 因子为 2,这会影响 100 Hz 处的滤波效果。
g=-5 设置在中心频率处的增益为 -5 dB,即衰减 5 dB。
请注意,这些命令假设了 equalizer 滤镜能够处理多个实例并应用于同一音频流,且每个实例都独立设置其参数。这在许多音频处理软件中是常见的,但在具体实现时可能会有所不同。
此外,如果您的环境不支持直接以这种方式链接多个滤镜实例(例如,在 FFmpeg 中,您可能需要使用分号 ; 而不是逗号 , 来分隔不同的滤镜,或者将滤镜放入单独的链中),您可能需要调整命令格式以符合您所使用的软件或库的语法要求。然而,在您给出的例子中,逗号 , 被用作分隔符,这通常是在某些特定上下文(如某些音频编辑软件的内部命令或脚本)中使用的。
t=h 和t=q的区别是什么 请详细说说
在音频处理或信号处理领域中,t=h 和 t=q 在设置均衡器(equalizer)或滤波器(filter)时代表了不同的带宽(bandwidth)指定方式,它们主要影响滤波器对频率的响应形状和尖锐程度。以下是详细的区别说明:
t=h(或 Hz)
含义:t=h 或 t=Hz 表示带宽(bandwidth)的单位是赫兹(Hz)。在这种情况下,你直接指定了滤波器频率响应曲线在中心频率两侧下降一定幅度(通常是3dB)所覆盖的频率范围。
影响:使用Hz作为带宽单位时,滤波器的形状(如峰形滤波器、带通滤波器或带阻滤波器等)在频率轴上的展宽是固定的,不随中心频率的变化而变化。这有助于精确控制滤波器对特定频率范围的影响。
应用:当你需要精确控制滤波器影响的频率范围时,使用Hz作为带宽单位非常有用。例如,在音频制作中,你可能想要增强或减弱某个特定频率及其附近很小范围内的声音。
t=q(Q-Factor)
含义:t=q 表示带宽的指定方式是使用Q因子(Q-Factor)。Q因子是中心频率与滤波器带宽的比值,它描述了滤波器对中心频率的选择性,即滤波器如何尖锐地聚焦于中心频率。
影响:Q因子越高,滤波器的带宽越窄,滤波器对中心频率的选择性越强,响应曲线越尖锐。相反,Q因子越低,滤波器的带宽越宽,滤波器对中心频率的选择性越弱,响应曲线越平坦。
应用:当你需要创建一个尖锐的滤波器响应,以便仅影响中心频率附近的非常小的频率范围时,使用Q因子作为带宽指定方式非常合适。例如,在电子音乐制作中,你可能想要创建一个非常尖锐的陷波滤波器来去除某个不想要的频率。
总结
t=h(或Hz)和t=q的主要区别在于它们如何指定滤波器的带宽。
使用Hz时,你直接指定了滤波器在频率轴上的展宽。
使用Q因子时,你指定了滤波器对中心频率的选择性,即滤波器的尖锐程度。
选择哪种方式取决于你的具体需求,比如你需要精确控制哪个频率范围或你想要滤波器有多尖锐。
*
*
*/
// ffmpeg -i 人民警察警歌.mp3 -af "equalizer=f=50:t=q:w=2.0:g=-48, equalizer=f=100:t=q:w=2.0:g=-48, \
// equalizer=f=250:t=q:w=2.0:g=-48, equalizer=f=500:t=q:w=2.0:g=-24, \
// equalizer=f=1000:t=q:w=2.0:g=-24, equalizer=f=4000:t=q:w=2.0:g=0, \
// equalizer=f=8000:t=q:w=2.0:g=0, equalizer=f=16000:t=q:w=2.0:g=0, \
// anequalizer=c0 f=250 w=500 g=-48 t=2|c1 f=250 w=500 g=-48 t=2" out1.mp3
//无滤波113 114
//112.6 111.8
#define Filter_No3 "equalizer=f=50:t=q:w=2.0:g=-48, \
equalizer=f=100:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-48, \
equalizer=f=500:t=q:w=2.0:g=-24, \
equalizer=f=1000:t=q:w=2.0:g=-12, \
equalizer=f=2000:t=q:w=2.0:g=4, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=-12, \
equalizer=f=16000:t=q:w=2.0:g=-24, \
equalizer=f=32000:t=q:w=2.0:g=-48, \
bass=g=-96:f=200:t=q:w=10"
//114 //117 太尖锐了
#define Filter_No4 "equalizer=f=50:t=q:w=2.0:g=-24, \
equalizer=f=100:t=q:w=2.0:g=-12, \
equalizer=f=250:t=q:w=2.0:g=-12, \
equalizer=f=500:t=q:w=2.0:g=-8, \
equalizer=f=1000:t=q:w=2.0:g=4, \
equalizer=f=2000:t=q:w=2.0:g=4, \
equalizer=f=4000:t=q:w=2.0:g=4, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=-6, \
equalizer=f=32000:t=q:w=2.0:g=-24, \
bass=g=-96:f=150:t=q:w=10"
//113 //115 还是尖锐
#define Filter_No5 "equalizer=f=50:t=q:w=2.0:g=-24, \
equalizer=f=100:t=q:w=2.0:g=-8, \
equalizer=f=250:t=q:w=2.0:g=-8, \
equalizer=f=500:t=q:w=2.0:g=-4, \
equalizer=f=1000:t=q:w=2.0:g=4, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=-6, \
equalizer=f=32000:t=q:w=2.0:g=-24, \
bass=g=-96:f=130:t=q:w=10"
//113 //115 声音效果跟平常差不多
#define Filter_No6 "equalizer=f=50:t=q:w=2.0:g=-24, \
equalizer=f=100:t=q:w=2.0:g=-24, \
equalizer=f=250:t=q:w=2.0:g=-12, \
equalizer=f=500:t=q:w=2.0:g=-12, \
equalizer=f=1000:t=q:w=2.0:g=-6, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=-6, \
equalizer=f=32000:t=q:w=2.0:g=-24"
//
#define Filter_No7 "equalizer=f=50:t=q:w=2.0:g=-24, \
equalizer=f=100:t=q:w=2.0:g=-24, \
equalizer=f=250:t=q:w=2.0:g=-12, \
equalizer=f=500:t=q:w=2.0:g=-12, \
equalizer=f=1000:t=q:w=2.0:g=-6, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=-6, \
equalizer=f=32000:t=q:w=2.0:g=-24, \
bass=g=-96:f=50:t=q:w=8"
//650 那段会影响乐器声 1400那段影响人声
#define Filter_No8 "equalizer=f=100:t=h:width=100:g=-48, \
equalizer=f=350:t=h:width=100:g=-36, \
equalizer=f=650:t=h:width=150:g=-12, \
equalizer=f=1400:t=h:width=600:g=0, \
equalizer=f=2500:t=h:width=500:g=0, \
equalizer=f=3500:t=h:width=600:g=0, \
equalizer=f=4500:t=h:width=500:g=+4, \
equalizer=f=5500:t=h:width=500:g=+8, \
equalizer=f=8000:t=h:width=2000:g=+12, \
bass=g=-96:f=50:t=q:w=8"
//11分钟
#define OLD_FILTER "equalizer=f=31:t=q:w=2.0:g=-48, \
equalizer=f=62:t=q:w=2.0:g=-48, \
equalizer=f=125:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-24, \
equalizer=f=500:t=q:w=2.0:g=-24, \
equalizer=f=1000:t=q:w=2.0:g=-4, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=0"
//111.0 111.4 保持46度
#define Filter_No9 "equalizer=f=31:t=q:w=2.0:g=-48, \
equalizer=f=62:t=q:w=2.0:g=-48, \
equalizer=f=125:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-48, \
equalizer=f=500:t=q:w=2.0:g=-48, \
equalizer=f=1000:t=q:w=2.0:g=-24, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=0"
//旧式机115
#define Filter_No10 "equalizer=f=31:t=q:w=2.0:g=-48, \
equalizer=f=62:t=q:w=2.0:g=-48, \
equalizer=f=125:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-32, \
equalizer=f=500:t=q:w=2.0:g=-24, \
equalizer=f=1000:t=q:w=2.0:g=-12, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=0"
#define Filter_M30 "equalizer=f=31:t=q:w=2.0:g=-48, \
equalizer=f=62:t=q:w=2.0:g=-48, \
equalizer=f=125:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-32, \
equalizer=f=500:t=q:w=2.0:g=-24, \
equalizer=f=1000:t=q:w=2.0:g=-12, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=0, \
anequalizer=c0 f=3250 w=750 g=-48 t=2|c1 f=3250 w=750 g=-48 t=2"
#define FILTER_PARAM Filter_No10
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
/**
********************************************************************
* @file FF_FilterParam.h
* FF_FilterParam.h
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef FF_FILTER_PARAM_DISCARD_H
#define FF_FILTER_PARAM_DISCARD_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
// 比一的发热还高 6分半
#define OLD_FILTER_2 "equalizer=f=31:t=q:w=2.0:g=-48, \
equalizer=f=62:t=q:w=2.0:g=-48, \
equalizer=f=125:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-24, \
equalizer=f=500:t=q:w=2.0:g=-24, \
equalizer=f=1000:t=q:w=2.0:g=-4, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=0, \
bass=g=-96:f=50:t=q:w=8"
//240 过热
#define OLD_FILTER_3 "equalizer=f=31:t=q:w=2.0:g=-48, \
equalizer=f=62:t=q:w=2.0:g=-48, \
equalizer=f=125:t=q:w=2.0:g=-48, \
equalizer=f=250:t=q:w=2.0:g=-24, \
equalizer=f=500:t=q:w=2.0:g=-24, \
equalizer=f=1000:t=q:w=2.0:g=-4, \
equalizer=f=2000:t=q:w=2.0:g=0, \
equalizer=f=4000:t=q:w=2.0:g=0, \
equalizer=f=8000:t=q:w=2.0:g=0, \
equalizer=f=16000:t=q:w=2.0:g=0, \
bass=g=-96:f=200:t=h:w=10"
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
#include "AudioDeal/FF_Statement.h"
#include "pcm_Resample.h"
#include "JZsdkLib.h"
#include "../AudioDeal.h"
//pcm的重采样结构体记录组
struct pcm_Resample
{
SwrContext *m_swr;
int In_SampleRate; //输入音频的码率
//unsigned int InCHLayout;
AVChannelLayout InCHLayout;
enum AVSampleFormat InFormat;
int Out_SampleRate; //输出音频的码率
//unsigned int Out_CHLayout;
AVChannelLayout Out_CHLayout;
enum AVSampleFormat Out_Format;
}pcm_Resample;
//初始化重编码器
/*****************
*
* 输入变量
* 音频库结构体
* 输入的音频采样率 输入的音频频道数, 输入的音频格式
* *************/
T_JZsdkReturnCode FF_Resample_Init(struct AudioDealInfo *AD_Info,
unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format)
{
// 尝试获取或分配ResampleInfo
struct pcm_Resample **ResampleInfoPtr = (struct pcm_Resample **)&AD_Info->ResampleInfo;
if (*ResampleInfoPtr == NULL) {
// 分配内存
*ResampleInfoPtr = (struct pcm_Resample *)malloc(sizeof(struct pcm_Resample));
if (*ResampleInfoPtr == NULL) {
// 内存分配失败处理
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 使用更具体的错误码
}
(*ResampleInfoPtr)->m_swr = NULL;
}
// 现在你可以安全地使用ResampleInfo了
struct pcm_Resample *ResampleInfo = *ResampleInfoPtr;
if (ResampleInfo->m_swr == NULL) {
ResampleInfo->m_swr = swr_alloc();
if (!ResampleInfo->m_swr) {
JZSDK_LOG_ERROR("Failed to allocate the resampling context");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; // 或者更具体的错误码
}
}
ResampleInfo->In_SampleRate = in_sampleRate;
ResampleInfo->InFormat = in_format;
//ResampleInfo->InCHLayout = in_ch_layout;
av_channel_layout_copy(&(ResampleInfo->InCHLayout), &in_ch_layout);
ResampleInfo->Out_SampleRate = AD_Info->Target_SampleRate;
ResampleInfo->Out_Format = AD_Info->Target_SampleFormat;
//ResampleInfo->Out_CHLayout = AD_Info->Target_ChannelLayout;
av_channel_layout_copy(&(ResampleInfo->Out_CHLayout), &AD_Info->Target_ChannelLayout);
//记录当前输入的比特率
AD_Info->Raw_SampleRate = in_sampleRate;
AD_Info->Raw_SampleFormat = in_format;
//AD_Info->Raw_ChannelLayout = in_ch_layout;
av_channel_layout_copy(&(AD_Info->Raw_ChannelLayout), &in_ch_layout);
// 设置输入参数
//av_opt_set_int(ResampleInfo->m_swr, "in_channel_layout", ResampleInfo->InCHLayout, 0);
av_opt_set_chlayout(ResampleInfo->m_swr, "in_chlayout", &ResampleInfo->InCHLayout, 0);
av_opt_set_sample_fmt(ResampleInfo->m_swr, "in_sample_fmt", ResampleInfo->InFormat, 0);
av_opt_set_int(ResampleInfo->m_swr, "in_sample_rate", ResampleInfo->In_SampleRate, 0);
// 设置输出参数
//av_opt_set_int(ResampleInfo->m_swr, "out_channel_layout", ResampleInfo->Out_CHLayout, 0);
av_opt_set_chlayout(ResampleInfo->m_swr, "out_chlayout", &ResampleInfo->Out_CHLayout, 0);
av_opt_set_sample_fmt(ResampleInfo->m_swr, "out_sample_fmt", ResampleInfo->Out_Format, 0);
av_opt_set_int(ResampleInfo->m_swr, "out_sample_rate", ResampleInfo->Out_SampleRate, 0);
// 初始化重采样上下文
if (swr_init(ResampleInfo->m_swr) < 0) {
printf("Failed to initialize the resampling context\n");
swr_free(&ResampleInfo->m_swr); // 释放已分配的 SwrContext
ResampleInfo->m_swr = NULL;
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//重置重编码器
T_JZsdkReturnCode FF_Resample_Reset(struct AudioDealInfo *AD_Info,
unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format)
{
int ResetFlag = JZ_FLAGCODE_OFF;
//对比编码器新设置与当前设置是否相同
int ret = av_channel_layout_compare(&in_ch_layout, &AD_Info->Raw_ChannelLayout);
if (ret != 0)
{
ResetFlag = JZ_FLAGCODE_ON;
}
if (in_sampleRate != AD_Info->Raw_SampleRate)
{
ResetFlag = JZ_FLAGCODE_ON;
}
if (in_format != AD_Info->Raw_SampleFormat)
{
ResetFlag = JZ_FLAGCODE_ON;
}
if (ResetFlag == JZ_FLAGCODE_OFF)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
struct pcm_Resample *ResampleInfo = (struct pcm_Resample *)AD_Info->ResampleInfo;
ret = 0;
if(ResampleInfo->m_swr != NULL)
{
swr_free(&ResampleInfo->m_swr);
ResampleInfo->m_swr = NULL;
}
return FF_Resample_Init(AD_Info, in_sampleRate, in_ch_layout, in_format);
}
void *FF_Resample_Send_And_Get_ResampleData(struct AudioDealInfo *AD_Info, unsigned char **src, int nb_samples, int *out_nb_samples)
{
int ret = 0;
unsigned char *dst = NULL;
struct pcm_Resample *ResampleInfo = (struct pcm_Resample *)AD_Info->ResampleInfo;
*out_nb_samples = av_rescale_rnd(nb_samples, ResampleInfo->Out_SampleRate, ResampleInfo->In_SampleRate, AV_ROUND_UP);
//printf("重采样得到的预计输出样本数量为%d\n",*out_nb_samples);
ret = av_samples_alloc(&dst, NULL, 2, *out_nb_samples, AV_SAMPLE_FMT_S16, 0);
if (ret < 0) {
printf("[ERROR][Resample]av_samples_alloc failed\n");
return NULL;
}
ret = swr_convert(ResampleInfo->m_swr, &dst, *out_nb_samples, (const uint8_t**)src, nb_samples);
if (ret < 0) {
printf("[ERROR][Resample]swr_convert failed\n");
av_freep(&dst); // 释放之前分配的内存
return NULL;
}
*out_nb_samples = ret;
return (void*)dst;
}
//用于释放掉,执行重采样后得到的新数据的内存
T_JZsdkReturnCode FF_Resample_freeReasmpleData(void *dst)
{
if (dst != NULL)
{
av_free(dst);
dst = NULL;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file pcm_Resample.h
* AudioDeal的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef PCM_REAMPLE_H
#define PCM_REAMPLE_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "AudioDeal/FF_Statement.h"
#include "AudioDeal/AudioDeal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode FF_Resample_Init(struct AudioDealInfo *AD_Info,
unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format);
T_JZsdkReturnCode FF_Resample_Reset(struct AudioDealInfo *AD_Info,
unsigned int in_sampleRate, AVChannelLayout in_ch_layout, enum AVSampleFormat in_format);
void *FF_Resample_Send_And_Get_ResampleData(struct AudioDealInfo *AD_Info, unsigned char **src, int nb_samples, int *out_nb_samples);
T_JZsdkReturnCode FF_Resample_freeReasmpleData(void *dst);
#ifdef __cplusplus
}
#endif
#endif
... ...
jzsdk的音频处理模块
用于处理底层的音频流,通常搭配如tts模块等使用
... ...
#include <stdio.h>
#include <string.h>
#include "JZsdkLib.h"
#include "BaseConfig.h"
#include "./DeviceMessage/DeviceMessage.h"
#include "DeviceInfo/DeviceInfo.h"
#include "DeviceInfo/HardwareInfo/HardwareInfo.h"
typedef struct DeviceInfo
{
unsigned int Port;
unsigned int DeviceID;
unsigned char SerialNumber[30];
unsigned int MajorVersion;
unsigned int MinjorVersion;
unsigned int ModifyVersion;
unsigned int DebugVersion;
}DeviceInfo;
static struct DeviceInfo g_DeviceID[6];
int g_DeviceIDNum = 0; //设备总数
/***************************************************
*
* 设备信息初始化
* 暂时无用
*
* *************************************************/
T_JZsdkReturnCode DeviceInfo_Init()
{
//硬件版本号初始化
HardwareInfo_Init();
//序列号模块初始化
SerialMAT_Init();
//设备打印信息模块初始化
DeviceMessage_Init();
//设备本地设备名字
DeviceInfo_SetDeviceName(DEVICE_PSDK, DEVICE_VERSION);
//设置本地序列号
unsigned char SerialNumber[30];
int SerialNumberLen = 0;
SerialMAT_Get_SerialNumber(SerialNumber, &SerialNumberLen);
DeviceInfo_SetAllSerialNumber(DEVICE_VERSION, SerialNumber, SerialNumberLen);
//设置本地的版本号
DeviceInfo_SetAllVerision(DEVICE_PSDK, MAJOR_VERSION, MINOR_VERSION, MODIFY_VERSION, DEBUG_VERSION);
JZSDK_LOG_INFO("MODULE_DEVICE_INFO_INIT_COMPLETE");
}
/************************
*
* 设置设备名
*
* *****************/
T_JZsdkReturnCode DeviceInfo_SetDeviceName(unsigned int Port, int DeviceID)
{
//检查一遍是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
if (g_DeviceID[i].Port == Port)
{
g_DeviceID[i].Port = Port;
g_DeviceID[i].DeviceID = DeviceID;
printf("接口0x%x, id:0x%x\n",Port,DeviceID);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
}
//不存在则写入新的
g_DeviceID[g_DeviceIDNum].Port = Port;
g_DeviceID[g_DeviceIDNum].DeviceID = DeviceID;
g_DeviceIDNum++;
if (g_DeviceIDNum == 6)
{
JZSDK_LOG_ERROR("错误,写入了超过5个设备");
g_DeviceIDNum = 5;
}
JZSDK_LOG_INFO("接入新设备0x%x, 0x%x",Port,DeviceID);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/************************
*
* 查询设备名
*
* *****************/
T_JZsdkReturnCode DeviceInfo_GetDeviceName(unsigned int Port, int *DeviceID)
{
if (DeviceID == NULL)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
//检查一遍是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
if (g_DeviceID[i].Port == Port)
{
*DeviceID = g_DeviceID[i].DeviceID;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
}
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
/************************
*
* 查询所有设备名
*
* *****************/
T_JZsdkReturnCode DeviceInfo_GetAllDeviceName(unsigned int *DeviceNum, unsigned int DeviceID[][2])
{
if (DeviceNum == NULL || DeviceID == NULL)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
*DeviceNum = g_DeviceIDNum;
if (*DeviceNum == 0)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//检查一遍是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
DeviceID[i][0] = g_DeviceID[i].Port;
DeviceID[i][1] = g_DeviceID[i].DeviceID;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/************************
*
* 设置所有序列号
*
* *****************/
T_JZsdkReturnCode DeviceInfo_SetAllSerialNumber(unsigned int DeviceId, unsigned char *SerialNumber, unsigned int SerialNumberLen)
{
//检查一遍设备是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
if (g_DeviceID[i].DeviceID == DeviceId)
{
memcpy(g_DeviceID[i].SerialNumber, SerialNumber, SerialNumberLen);
JZSDK_LOG_INFO("序列号0x%x %s",g_DeviceID[i].SerialNumber, g_DeviceID[i].SerialNumber);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
}
JZSDK_LOG_ERROR("设置所有序列号失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
/************************
*
* 返回设备序列号
*
* *****************/
T_JZsdkReturnCode DeviceInfo_GetAllSerialNumber(unsigned int DeviceId, unsigned char *SerialNumber, unsigned int *SerialNumberLen)
{
//检查一遍设备是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
if (g_DeviceID[i].DeviceID == DeviceId)
{
*SerialNumberLen = strlen(g_DeviceID[i].SerialNumber);
memcpy(SerialNumber, g_DeviceID[i].SerialNumber, *SerialNumberLen);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
}
JZSDK_LOG_ERROR("该设备未登记");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
/************************
*
* 设置所有版本号
*
* *****************/
T_JZsdkReturnCode DeviceInfo_SetAllVerision(unsigned int DeviceId, unsigned int MajorVersion, unsigned int MinjorVersion, unsigned int ModifyVersion, unsigned int DebugVersion)
{
//检查一遍设备是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
if (g_DeviceID[i].DeviceID == DeviceId)
{
g_DeviceID[i].MajorVersion = MajorVersion;
g_DeviceID[i].MinjorVersion = MinjorVersion;
g_DeviceID[i].ModifyVersion = ModifyVersion;
g_DeviceID[i].DebugVersion = DebugVersion;
JZSDK_LOG_INFO("设置版本号 0x%x %d %d %d %d",g_DeviceID[i].SerialNumber,
g_DeviceID[i].MajorVersion,
g_DeviceID[i].MinjorVersion,
g_DeviceID[i].ModifyVersion,
g_DeviceID[i].DebugVersion
);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
}
JZSDK_LOG_ERROR("设置失败,该设备未登记");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
/************************
*
* 返回设备版本号
*
* *****************/
T_JZsdkReturnCode DeviceInfo_GetAllVerision(unsigned int DeviceId, unsigned int *MajorVersion, unsigned int *MinjorVersion, unsigned int *ModifyVersion, unsigned int *DebugVersion)
{
//检查一遍设备是否存在
for (int i = 0; i < g_DeviceIDNum; i++)
{
if (g_DeviceID[i].DeviceID == DeviceId)
{
*MajorVersion = g_DeviceID[i].MajorVersion;
*MinjorVersion = g_DeviceID[i].MinjorVersion;
*ModifyVersion = g_DeviceID[i].ModifyVersion;
*DebugVersion = g_DeviceID[i].DebugVersion;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
}
JZSDK_LOG_ERROR("返回失败,该设备未登记");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file DeviceInfo.h
* DeviceInfo.h的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef DEVICE_INFO_H
#define DEVICE_INFO_H
#include "DeviceInfo/DeviceMessage/DeviceMessage.h"
#include "SerialNumberProc/SerialProc.h"
#include "DeviceInfo/HardwareInfo/HardwareInfo.h"
/* Includes ------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
T_JZsdkReturnCode DeviceInfo_Init();
T_JZsdkReturnCode DeviceInfo_SetAllVerision(unsigned int DeviceId, unsigned int MajorVersion, unsigned int MinjorVersion, unsigned int ModifyVersion, unsigned int DebugVersion);
T_JZsdkReturnCode DeviceInfo_GetAllVerision(unsigned int DeviceId, unsigned int *MajorVersion, unsigned int *MinjorVersion, unsigned int *ModifyVersion, unsigned int *DebugVersion);
T_JZsdkReturnCode DeviceInfo_GetAllDeviceName(unsigned int *DeviceNum, unsigned int DeviceID[][2]);
T_JZsdkReturnCode DeviceInfo_SetDeviceName(unsigned int Port, int DeviceID);
T_JZsdkReturnCode DeviceInfo_SetAllSerialNumber(unsigned int DeviceId, unsigned char *SerialNumber, unsigned int SerialNumberLen);
T_JZsdkReturnCode DeviceInfo_GetAllSerialNumber(unsigned int DeviceId, unsigned char *SerialNumber, unsigned int *SerialNumberLen);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "JZsdkLib.h"
#include "./DeviceMessage.h"
#include "version_choose.h"
#include "BaseConfig.h"
#include "../SerialNumberProc/SerialProc.h"
#include "Gimbal/Gimbal_InAndOut.h"
#include "UI_control/Psdk_UI_io.h"
#if MEGAPHONE_CONFIG_STATUS == VERSION_SWITCH_ON
#include "Megaphone/Megaphone.h"
#include "Megaphone/MegTempControl/MegTempControl.h"
#endif
#include "Lighting/Lighting_InAndOut.h"
#define MESSAGE_MAX_LEN 1024
static DeviceMessageMode g_DeviceMessageMode = DEVICE_MESSAGE_DEFAULT;
static unsigned char DeviceMessage[MESSAGE_MAX_LEN] = "默认打印信息\n"; //设备信息最多显示512长度
static DeviceMessageLanguage g_MessageLanguage = DEVICE_MESSAGE_CHINESE;
int Widget_RealTimeOpusFlag = JZ_FLAGCODE_OFF; //用于标志ui里的实时语音开关
#if IRC_CONFIG_STATUS == VERSION_SWITCH_ON
extern int g_temp_GasValueMax;
extern int g_temp_GasValueMin;
#endif
/***************************************************
*
* 设备信息初始化
* 暂时无用
*
* *************************************************/
T_JZsdkReturnCode DeviceMessage_Init()
{
}
/***************************************************
*
* 是否可用信息录入
* 如果设备不可用,直接返回错误,从而不录入其他信息
*
* *************************************************/
static T_JZsdkReturnCode DeviceMessage_Enter_UsegePermissions(unsigned char *message)
{
unsigned char old_message[MESSAGE_MAX_LEN];
unsigned char new_message[MESSAGE_MAX_LEN];
memset(message ,0, MESSAGE_MAX_LEN);
memset(old_message, 0, MESSAGE_MAX_LEN);
memset(new_message, 0, MESSAGE_MAX_LEN);
unsigned char Jz_SerialNumber[256];
int Jz_SerialNumberLenth;
SerialMAT_Get_SerialNumber(Jz_SerialNumber, &Jz_SerialNumberLenth);
//判断是否能用
int UseFlag = Main_Device_Wheather_Use();
if(UseFlag== 1)
{
//判断为未激活
//显示未激活
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
memset(message,0,sizeof(message));
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
snprintf(new_message,MESSAGE_MAX_LEN,"提示:未激活,功能不可用。\n请进入微信小程序“极至服务”\n输入设备SN码:%s\n获取激活码激活设备。\n",Jz_SerialNumber);
}
else
{
snprintf(new_message,MESSAGE_MAX_LEN,"Reminder: Not activated, function not available.\nPlease enter https://jzdrones.com/\nInput device SN code: %s\nObtain an activation code to activate the device.\n",Jz_SerialNumber);
}
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
else if (UseFlag == 2)
{
//判断为海外版
//显示为海外版不可用
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
memset(message,0,sizeof(message));
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
snprintf(new_message,MESSAGE_MAX_LEN,"海外版无法在中国境内使用\n");
}
else
{
snprintf(new_message,MESSAGE_MAX_LEN,"The international version cannot be used in China\n");
}
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/***************************************************
*
* 设备信息录入
*
*
* *************************************************/
static T_JZsdkReturnCode DeviceMessage_Enter_Default(unsigned char *message)
{
unsigned char old_message[MESSAGE_MAX_LEN];
unsigned char new_message[MESSAGE_MAX_LEN];
memset(message ,0, MESSAGE_MAX_LEN);
memset(old_message, 0, MESSAGE_MAX_LEN);
memset(new_message, 0, MESSAGE_MAX_LEN);
#if MEGAPHONE_CONFIG_STATUS == VERSION_SWITCH_ON
//如果实时语音按键打开了
if (Widget_RealTimeOpusFlag == JZ_FLAGCODE_ON)
{
memset(message ,0, MESSAGE_MAX_LEN);
memset(old_message, 0, MESSAGE_MAX_LEN);
memset(new_message, 0, MESSAGE_MAX_LEN);
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
snprintf(new_message,MESSAGE_MAX_LEN,"已开启实时语音\n禁止其他音频操作\n");
}
else
{
snprintf(new_message,MESSAGE_MAX_LEN,"Real-time Intercom has been enabled.\nOther audio operations are prohibited\n");
}
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//正常获取歌曲列表
else
{
//获取音频信息 用于显示歌曲列表
memset(old_message, 0, MESSAGE_MAX_LEN);
memset(new_message, 0, MESSAGE_MAX_LEN);
if(Megaphone_GetMusicListMessage(new_message) != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
memset(message, 0, sizeof(message));
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
snprintf(new_message,MESSAGE_MAX_LEN,"无歌曲\n",sizeof("无歌曲\n"));
}
else
{
snprintf(new_message,MESSAGE_MAX_LEN,"No Songs\n", sizeof("No Songs"));
}
}
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
//JZSDK_LOG_INFO("获取的信息%s",message);
}
#endif
#if IRC_CONFIG_STATUS == VERSION_SWITCH_ON
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
snprintf(new_message,MESSAGE_MAX_LEN,"气体阈值\n上限:%d\n下限:%d\n",g_temp_GasValueMax , g_temp_GasValueMin);
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
}
else
{
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
snprintf(new_message,MESSAGE_MAX_LEN,"Gas Threshold\nUpper Limit: %d\nLower Limit: %d\n",g_temp_GasValueMax , g_temp_GasValueMin);
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
}
#endif
//如果为组合版
#if (DEVICE_VERSION == TF_A1 || DEVICE_VERSION == JZ_U3 || DEVICE_VERSION == JZ_U3S ||DEVICE_VERSION == JZ_U3D)
// //组合板写入
// snprintf(new_message,128,"光斑y值%d\n",Widget_GetCenter_ValueY());
// snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
// snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
static int SearchLight_LeftTemperature = 0;
static int SearchLight_RightTemperature = 0;
//获取温度
Lighting_Get_SearchLightTemperature(&SearchLight_LeftTemperature, &SearchLight_RightTemperature);
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
snprintf(new_message,MESSAGE_MAX_LEN,"左灯温度:%d\n",SearchLight_LeftTemperature);
}
else
{
snprintf(new_message,MESSAGE_MAX_LEN,"SearchLight-LeftTemp:%d\n",SearchLight_LeftTemperature);
}
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
if (g_MessageLanguage == DEVICE_MESSAGE_CHINESE)
{
snprintf(new_message,MESSAGE_MAX_LEN,"右灯温度:%d\n",SearchLight_RightTemperature);
}
else
{
snprintf(new_message,MESSAGE_MAX_LEN,"SearchLight-RightTemp:%d\n",SearchLight_RightTemperature);
}
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
#endif
}
/***************************************************
*
* 设备信息录入
*
*
* *************************************************/
static T_JZsdkReturnCode DeviceMessage_Enter_Debug(unsigned char *message)
{
unsigned char old_message[MESSAGE_MAX_LEN];
unsigned char new_message[MESSAGE_MAX_LEN];
memset(message ,0, MESSAGE_MAX_LEN);
memset(old_message, 0, MESSAGE_MAX_LEN);
memset(new_message, 0, MESSAGE_MAX_LEN);
snprintf(new_message,MESSAGE_MAX_LEN,"调试界面\n");
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
//如果拥有云台,将会显示云台微调值
if (Get_JZsdk_GimbalStatusFlag() == 1)
{
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
snprintf(new_message,MESSAGE_MAX_LEN,"云台值%d\n云台微调值%d\n实际云台值%d\n",
JZsdk_Psdk_UI_io_Get_PitchAngle(),
JZsdk_Psdk_UI_io_Get_PitchFineTuninge(),
JZsdk_Psdk_UI_io_Get_PitchRealPitchAngle());
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
}
#if MEGAPHONE_CONFIG_STATUS == VERSION_SWITCH_ON
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
snprintf(new_message,MESSAGE_MAX_LEN,"rtv:%d rsv:%d",Megaphone_get_RealTargetVolume(), Megaphone_get_RealSetVolume());
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
//如果温控值不为0
double Megtemp = MegTempControl_GetTemp();
if (Megtemp != 0)
{
memset(new_message,0,sizeof(new_message));
memset(old_message,0,sizeof(old_message));
snprintf(new_message,MESSAGE_MAX_LEN,"喊话器温度%f\n",Megtemp);
snprintf(old_message,MESSAGE_MAX_LEN,"%s",message);
snprintf(message,MESSAGE_MAX_LEN,"%s%s",old_message,new_message);
}
#endif
}
/***************************************************
*
* 用于获取设备信息的函数入口
*
*
* *************************************************/
T_JZsdkReturnCode DeviceMessage_GetMessage(unsigned char *str, int MaxReadLen)
{
T_JZsdkReturnCode ret;
memset(DeviceMessage,0,sizeof(DeviceMessage));
if (MaxReadLen >= sizeof(DeviceMessage))
{
MaxReadLen = sizeof(DeviceMessage);
}
//接下来信息很重要,首先获取消息吧!
if (g_DeviceMessageMode == DEVICE_MESSAGE_ALL)
{
JZSDK_LOG_INFO("查获所有信息");
}
else
{
ret = DeviceMessage_Enter_UsegePermissions(DeviceMessage);
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
memcpy(str, DeviceMessage, MaxReadLen);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
if (g_DeviceMessageMode == DEVICE_MESSAGE_DEFAULT)
{
DeviceMessage_Enter_Default(DeviceMessage);
memcpy(str, DeviceMessage, MaxReadLen);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
else if (g_DeviceMessageMode == DEVICE_MESSAGE_DEBUG)
{
DeviceMessage_Enter_Debug(DeviceMessage);
memcpy(str, DeviceMessage, MaxReadLen);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
else
{
printf("获取设备信息失败\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/*****************************
*
* 设置信息模式
*
*
* **************************/
T_JZsdkReturnCode DeviceMessage_Mode(DeviceMessageMode mode)
{
if (mode < 0 || mode > 2)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (mode == g_DeviceMessageMode)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
g_DeviceMessageMode = mode;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/*****************************
*
* 设置设备信息的语言
*
*
* **************************/
T_JZsdkReturnCode DeviceMessage_SetMessageLanguage(DeviceMessageLanguage value)
{
if (value < 0 || value > 1)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (value == g_MessageLanguage)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
g_MessageLanguage = value;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file DeviceMessage.h
* DeviceMessage.h 的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef DEVICE_MESSAGE_H
#define DEVICE_MESSAGE_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
typedef enum DeviceMessageMode
{
DEVICE_MESSAGE_DEFAULT = 0x0000, //默认打印信息
DEVICE_MESSAGE_DEBUG = 0x0001, //调试模式下打印的信息
DEVICE_MESSAGE_ALL = 0x0002, //全内容打印,用于串口调试使用
}DeviceMessageMode;
typedef enum DeviceMessageLanguage
{
DEVICE_MESSAGE_CHINESE = 0x0000, //中文
DEVICE_MESSAGE_ENGLISH = 0x0001, //英文
}DeviceMessageLanguage;
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode DeviceMessage_GetMessage(unsigned char *str, int MaxReadLen);
T_JZsdkReturnCode DeviceMessage_Mode(DeviceMessageMode mode);
T_JZsdkReturnCode DeviceMessage_SetMessageLanguage(DeviceMessageLanguage value);
T_JZsdkReturnCode DeviceMessage_Init();
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include "JZsdkLib.h"
#define HARDWARE_DIR "/root/HardwareIdeNum"
#define MAX_LINE_LENGTH 100
static int HardwareInfo_MajorVersion = 0;
static int HardwareInfo_MinorVersion = 0;
static int HardwareInfo_ModifyVersion = 0;
static int HardwareInfo_DebugVersion = 0;
/***********************
* 获取硬件版本号
* major 0
* minor 1
* modiy 2
* debug 3
* ************/
T_JZsdkReturnCode HardwareInfo_GetVersion(int flag)
{
unsigned int version = 0;
switch (flag)
{
case 0:
version = HardwareInfo_MajorVersion;
break;
case 1:
version = HardwareInfo_MinorVersion;
break;
case 2:
version = HardwareInfo_ModifyVersion;
break;
case 3:
version = HardwareInfo_DebugVersion;
break;
default:
break;
}
return version;
}
T_JZsdkReturnCode HardwareInfo_Init()
{
T_JZsdkReturnCode ret;
ret = JZsdk_check_file_exists(HARDWARE_DIR);
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_ERROR("无硬件版本号");
return ret;
}
//加载硬件版本号
FILE *file;
char buffer[MAX_LINE_LENGTH];
int num1, num2, num3, num4;
char str[MAX_LINE_LENGTH];
// 打开文件
file = fopen(HARDWARE_DIR, "r");
if (file == NULL) {
JZSDK_LOG_ERROR("Error opening file");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
// 读取前四行到整数变量
if (fscanf(file, "%d", &num1) != 1) {
JZSDK_LOG_ERROR("Error reading hardware number 1");
fclose(file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (fscanf(file, "%d", &num2) != 1) {
JZSDK_LOG_ERROR("Error reading hardware number 2");
fclose(file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (fscanf(file, "%d", &num3) != 1) {
JZSDK_LOG_ERROR("Error reading hardware number 3");
fclose(file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (fscanf(file, "%d", &num4) != 1) {
JZSDK_LOG_ERROR("Error reading hardware number 4");
fclose(file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
// 读取第五行到字符串变量
// 清除之前的换行符
fgetc(file); // 读取并忽略换行符
if (fgets(str, MAX_LINE_LENGTH, file) == NULL)
{
JZSDK_LOG_ERROR("Error reading string");
fclose(file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
// 去除字符串末尾的换行符(如果有)
str[strcspn(str, "\n")] = 0;
HardwareInfo_MajorVersion = num1;
HardwareInfo_MinorVersion = num2;
HardwareInfo_ModifyVersion = num3;
HardwareInfo_DebugVersion = num4;
// 输出结果
JZSDK_LOG_INFO("Hardware Version: %d, %d, %d, %d\n", HardwareInfo_MajorVersion, HardwareInfo_MinorVersion, HardwareInfo_ModifyVersion, HardwareInfo_DebugVersion);
JZSDK_LOG_INFO("Hardware Info: %s\n", str);
// 关闭文件
fclose(file);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file HardwareInfo.h
* HardwareInfo.h 的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef HARDWARE_INFO_H
#define HARDWARE_INFO_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode HardwareInfo_Init();
T_JZsdkReturnCode HardwareInfo_GetVersion(int flag);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "./ActivateMAT.h"
#include "JZsdkLib.h"
#include "JZsdk_Base/JZsdk_Code/JZsdk_SMT_Code.h"
#include "./version_choose.h"
static T_JZsdkReturnCode ActivateMAT_create_SN_LOCK_file() ;
static T_JZsdkReturnCode ActivateMAT_delete_SN_LOCK_file() ;
static T_JZsdkReturnCode ActivateMAT_check_SN_LOCK_exists() ;
static T_JZsdkReturnCode ActivateMAT_UnLockDevice(char *data, unsigned long *deac_code);
static T_JZsdkReturnCode ActivateMAT_LockDevice(char *data, unsigned long *ac_code);
static T_JZsdkReturnCode ActivateMAT_ActivateAndUnActivate(int flag, unsigned char *SerialNumber,unsigned char *ActivationCode);
#define SN_LOCL_FILE_PATH "/root/SN_LOCK"
#define CRC32_POLYNOMIAL_UNLOCK 0xEDB88320L //激活解锁
#define CRC32_POLYNOMIAL_LOCK 0xEDB88321L //反激活锁住
/**********************************
*
* 判断是否需要激活/反激活,且进行激活或者反激活
* 输入 激活状态 序列号 激活码 激活码长度
* 失败 返回JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE
* 有进行了激活或者 反激活 则返回JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS
* *******************************/
T_JZsdkReturnCode ActivateMAT_ActivateInterface(int SN_status, unsigned char *SerialNumber ,unsigned char *data, int data_length)
{
T_JZsdkReturnCode ret;
//如果数组指针为空,直接退出
if (data == NULL)
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//如果已经激活了
if (SN_status == SNM_HAVE_ACTIVATED)
{
//判断是否是要反激活的
if (data[0] == '#' && data[1] == '#')
{
//复合反激活的格式 指 ##+8位数
if (data_length == 10)
{
ret = ActivateMAT_ActivateAndUnActivate(1, SerialNumber, data+2);
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
printf("反激活失败");
return ret;
}
}
else
{
printf("试图输入##反激活,但是长度为%d\n", data_length);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
else
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
//如果是未激活
else if(SN_status == SNM_NOT_ACTIVATED)
{
//判断是否是要激活的
if (data_length == 8)
{
ret = ActivateMAT_ActivateAndUnActivate(0, SerialNumber, data);
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
return ret;
}
}
else
{
JZSDK_LOG_ERROR("输入的并非是激活码,或者是激活码长度不对");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
//既不是激活也不是反激活
else
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/******************
*
* 激活与反激活
* flag 0为激活 flag 1为反激活
* ******************/
static T_JZsdkReturnCode ActivateMAT_ActivateAndUnActivate(int flag, unsigned char *SerialNumber,unsigned char *ActivationCode)
{
unsigned long Inputput_crc_code; //输入的字符串转换得到的校验码
unsigned long local_crc_code; //根据本地序列号得到的校验码
T_JZsdkReturnCode ret;
//将输入的激活或反激活码字符串转化为 识别用的16进制校验码
Inputput_crc_code = strtoul(ActivationCode, NULL, 16); //将字符串转换为16进制unsigned long
printf("输入激活码得到的校验码为:%08lX\n", Inputput_crc_code);
//激活计算
if (flag == 0)
{
//1、获取本地激活码
ActivateMAT_UnLockDevice(SerialNumber, &local_crc_code);
printf("计算得到的激活码:%08X\n", local_crc_code);
//如果校验码 等于本地激活码
if (Inputput_crc_code == local_crc_code)
{
//激活码正确
JZSDK_LOG_INFO("激活码正确");
//删除锁文件
ret = ActivateMAT_delete_SN_LOCK_file();
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_ERROR("解除激活码锁失败");
return ret;
}
//检查锁是否成功解除
ret = ActivateMAT_check_SN_LOCK_exists();
if (ret == JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) //等于就是锁还存在
{
JZSDK_LOG_ERROR("解除激活码锁失败,锁仍然存在");
return ret;
}
}
else
{
//激活码错误
JZSDK_LOG_ERROR("激活码错误");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
//反激活计算
else if(flag == 1)
{
//1、获取本地激活码
ActivateMAT_LockDevice(SerialNumber, &local_crc_code);
printf("计算得到的反激活码:%08X\n", local_crc_code);
//如果校验码 等于本地激活码
if (Inputput_crc_code == local_crc_code)
{
//激活码正确
printf("反激活正确\n");
//创建锁文件
ret = ActivateMAT_create_SN_LOCK_file();
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_ERROR("激活码锁创建失败");
return ret;
}
//检查锁是否成功上锁
ret = ActivateMAT_check_SN_LOCK_exists();
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) //不等于就是锁还=不存在
{
JZSDK_LOG_ERROR("激活码锁创建失败,锁存在");
return ret;
}
}
else
{
//反激活码错误
printf("反激活码错误\n");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
}
else
{
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/******************
*
* 激活状态判断,输入序列号类型,以及 序列号状态的地址
* 返回成功或者失败
* ******************/
T_JZsdkReturnCode ActivateMAT_DeviceActivateStatus(int SN_Type, int *SN_status)
{
// //如果序列号类型处于 UNDEFINED_SNM STANDARD_JZ_1_SNM
// //都是认为默认激活
// if (SN_Type == UNDEFINED_SNM || SN_Type == STANDARD_JZ_1_SNM)
// {
// *SN_status = SNM_HAVE_ACTIVATED;
// return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
// }
// //如果为极至标准2类型 或者 dji环类型的序列号类型
// //正常判断是否有激活
//如果是串口程序,默认为已经激活
if (APP_VERSION == APP_UART)
{
*SN_status = SNM_HAVE_ACTIVATED;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//如果sn锁文件存在
if(ActivateMAT_check_SN_LOCK_exists() == JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
printf("检测到sn存在\n");
*SN_status = SNM_NOT_ACTIVATED;
}
else
{
printf("检测到不sn存在\n");
//如果没有sn锁,就是已经激活设备
*SN_status = SNM_HAVE_ACTIVATED;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**********************************
*
* 创建SN_LOCK文件
*
* *******************************/
// 函数名:create_SN_LOCK_file
// 参数:文件路径
static T_JZsdkReturnCode ActivateMAT_create_SN_LOCK_file()
{
return JZsdk_create_file(SN_LOCL_FILE_PATH);
}
/**********************************
*
* 删除SN_LOCK文件
*
* *******************************/
// 函数名:delete_SN_LOCK_file
// 参数:文件路径
static T_JZsdkReturnCode ActivateMAT_delete_SN_LOCK_file()
{
return JZsdk_delete_file(SN_LOCL_FILE_PATH);
}
/**********************************
*
* 检查SN_LOCK锁定文件是否存在
*
* *******************************/
static T_JZsdkReturnCode ActivateMAT_check_SN_LOCK_exists()
{
return JZsdk_check_file_exists(SN_LOCL_FILE_PATH);
}
/**********************************
*
* 激活计算函数
*
* *******************************/
static T_JZsdkReturnCode ActivateMAT_UnLockDevice(char *data, unsigned long *deac_code)
{
unsigned long crc = 0xFFFFFFFF;
int length = strlen(data);
for (int i = 0; i < length; i++)
{
crc ^= (unsigned long)data[i];
for (int j = 0; j < 8; j++) {
if (crc & 1)
crc = (crc >> 1) ^ CRC32_POLYNOMIAL_UNLOCK;
else
crc >>= 1;
}
}
crc ^= 0xFFFFFFFF;
*deac_code = crc;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/**********************************
*
* 反激活计算函数
*
* *******************************/
static T_JZsdkReturnCode ActivateMAT_LockDevice(char *data, unsigned long *ac_code)
{
unsigned long crc = 0xFFFFFFFF;
int length = strlen(data);
for (int i = 0; i < length; i++)
{
crc ^= (unsigned long)data[i];
for (int j = 0; j < 8; j++) {
if (crc & 1)
crc = (crc >> 1) ^ CRC32_POLYNOMIAL_LOCK;
else
crc >>= 1;
}
}
crc ^= 0xFFFFFFFF;
*ac_code = crc;
printf("反激活 序列号%s crccode:%08X accode:%08X\n", data, crc, *ac_code);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
... ...
/**
********************************************************************
* @file ActivateMAT_InAndOut.h
* ActivateMAT_InAndOut的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef ACTIVATE_MAT_INANDOUT_H
#define ACTIVATE_MAT_INANDOUT_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode ActivateMAT_ActivateInterface(int SN_status, unsigned char *SerialNumber ,unsigned char *data, int data_length);
T_JZsdkReturnCode ActivateMAT_DeviceActivateStatus(int SN_Type, int *SN_status);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "JZsdkLib.h"
#include "BaseConfig.h"
#include "DeviceInfo/SerialNumberProc/SerialProc.h"
#include "JZsdk_Base/JZsdk_Code/JZsdk_SMT_Code.h"
#include "./FirewareOriginMAT.h"
static int g_OriginRegionNum = ORIGIN_DEFAULT;
/*****************
*
* 属地初始化
*
*
* *******************/
T_JZsdkReturnCode FOMAT_FirewareOriginRegion_Init(int SerialType, unsigned char *SerialNumber, unsigned int SerialNumberLen)
{
//没有定义过的序列号,或是没有序列号
if (SerialType == UNDEFINED_SNM || SerialType == STANDARD_DJI_SNM)
{
if (FIRMWARE_ORIGIN == DOMESTIC_VERSION)
{
g_OriginRegionNum = ORIGIN_CN;
}
else if (FIRMWARE_ORIGIN == OVERSEAS_VERSION)
{
g_OriginRegionNum = ORIGIN_EN;
}
else
{
g_OriginRegionNum = ORIGIN_CN;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//旧类型的
if (SerialType == STANDARD_JZ_1_SNM)
{
if (FIRMWARE_ORIGIN == DOMESTIC_VERSION)
{
g_OriginRegionNum = ORIGIN_CN;
}
else if (FIRMWARE_ORIGIN == OVERSEAS_VERSION)
{
g_OriginRegionNum = ORIGIN_EN;
}
else
{
g_OriginRegionNum = ORIGIN_CN;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//新序列号类型
if (SerialType == STANDARD_JZ_2_SNM)
{
//检测是否是国内的
if ((SerialNumber[4] == 'C' || SerialNumber[4] == 'c')
&& (SerialNumber[5] == 'N' || SerialNumber[5] == 'n'))
{
g_OriginRegionNum = ORIGIN_CN;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//检测是否是en通用区的
if ((SerialNumber[4] == 'E' || SerialNumber[4] == 'e')
&& (SerialNumber[5] == 'N' || SerialNumber[5] == 'n'))
{
g_OriginRegionNum = ORIGIN_EN;
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//无匹配序列号
if (FIRMWARE_ORIGIN == DOMESTIC_VERSION)
{
g_OriginRegionNum = ORIGIN_CN;
}
else if (FIRMWARE_ORIGIN == OVERSEAS_VERSION)
{
g_OriginRegionNum = ORIGIN_EN;
}
else
{
g_OriginRegionNum = ORIGIN_CN;
}
}
}
/*******************
*
* 属地获取
*
* *****************/
T_JZsdkReturnCode FOMAT_Get_FirewareOriginRegion()
{
return g_OriginRegionNum;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file FirewareOriginMAT.h
* FirewareOriginMAT.h 的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef FIREWARE_ORIGIN_MAT_H
#define FIREWARE_ORIGIN_MAT_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
T_JZsdkReturnCode FOMAT_FirewareOriginRegion_Init(int SerialType, unsigned char *SerialNumber, unsigned int SerialNumberLen);
T_JZsdkReturnCode FOMAT_Get_FirewareOriginRegion();
/* Exported types ------------------------------------------------------------*/
typedef enum OriginRegionPlace
{
ORIGIN_DEFAULT = 0x0000,
ORIGIN_CN = 0x0001,
ORIGIN_EN = 0x0002,
}OriginRegionPlace;
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "./SerialProc.h"
#include "./ActivateMAT/ActivateMAT.h"
#include "JZsdkLib.h"
#include "JZsdk_Base/JZsdk_Code/JZsdk_SMT_Code.h"
// 负载型号 (4位)+ CN/EN + F 1(默认) + 年(1) + 月(1) + 4位的计数(1-ffff 的16进制) + 2位CRC校验位
#define SNM_PATH "/root/num" //序列号存放地址
#define SERIAL_NUMBER_LENGTH STANDARD_JZ_2_SUM_LENGTH
static int SerialNumberLength; //序列号长度
static int SerialNumberType = UNDEFINED_SNM; //序列号类型
static int SerialNumberStatus = SNM_NOT_EXISTS; //激活状态,未存在序列号
static unsigned char SerialNumber[17]; //序列号
static unsigned char DJI_SkyPort_SerialNumber[15]; //大疆转接环序列号 默认为空
static T_JZsdkReturnCode SerialMAT_NumberGet();
/******************
*
* 序列号管理模块初始化
*
* ******************/
T_JZsdkReturnCode SerialMAT_Init()
{
T_JZsdkReturnCode ret;
// 1、获取序列号与类型
ret = SerialMAT_NumberGet();
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
JZSDK_LOG_ERROR("序列号获取错误");
}
// 2、根据上一步获取的情况,确认激活状态
ret = ActivateMAT_DeviceActivateStatus(SerialNumberType, &SerialNumberStatus);
// 3、进行属地的初始化
FOMAT_FirewareOriginRegion_Init(SerialNumberType, SerialNumber, SerialNumberLength);
JZSDK_LOG_INFO("序列号模块初始化完成");
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/*************
*
* 设置大疆序列号
* 固定长度14位
* ***********/
T_JZsdkReturnCode SerialMAT_Set_DJI_SkyPort_SerialNumber(char *str)
{
memcpy(DJI_SkyPort_SerialNumber, str, 14);
DJI_SkyPort_SerialNumber[14] = '\0';
}
/***************
*
* 获取序列号
*
* **************/
T_JZsdkReturnCode SerialMAT_Get_SerialNumber(char *str, int *strlen)
{
if (str != NULL)
{
memcpy(str, SerialNumber, SerialNumberLength);
}
if (strlen != NULL)
{
*strlen = SerialNumberLength;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/*********
*
* 读取,并获取序列号 暂时不开启对外使用
*
* *************/
T_JZsdkReturnCode SerialMAT_Read_SerialNumber(char *str, int *strlen)
{
SerialMAT_NumberGet();
SerialMAT_Get_SerialNumber(str, strlen);
}
/******************
*
* 获取激活状态
* SNM_NOT_EXISTS = 0x0000, // (未存在序列号)
SNM_HAVE_ACTIVATED = 0x0001, // 已激活
SNM_NOT_ACTIVATED = 0x0002, // 未激活
SNM_ERROR_ACTIVATED = 0x0003, //激活错误状态
* ******************/
T_JZsdkReturnCode SerialMAT_Get_SerialNumberStatus()
{
return SerialNumberStatus;
}
/**********************************
*
* 判断是否需要激活/反激活,且进行激活或者反激活
* 输入字符串 及长度
* 无任何操作发生 返回JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE
* 有进行了激活或者 反激活 返回JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS
* *******************************/
T_JZsdkReturnCode SerialMAT_ActivateInterface(unsigned char *data, int data_length)
{
T_JZsdkReturnCode ret;
ret = ActivateMAT_ActivateInterface(SerialNumberStatus, SerialNumber, data, data_length ) ;
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
return ret;
}
//操作完后,重新检测激活状态
ActivateMAT_DeviceActivateStatus(SerialNumberType, &SerialNumberStatus);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/******************
*
* 获取序列号,及序列号类型
*
* ******************/
static T_JZsdkReturnCode SerialMAT_NumberGet()
{
FILE *num_file;
char num_char[128];
memset(num_char, 0, sizeof(num_char));
memset(SerialNumber, 0, sizeof(SerialNumber));
T_JZsdkReturnCode ret;
//1、判断是否拥有大疆环的序列号
ret = JZsdk_Array_isEmpty(DJI_SkyPort_SerialNumber, sizeof(DJI_SkyPort_SerialNumber));
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
SerialNumberType = STANDARD_DJI_SNM;
//拥有转接环序列号
memcpy(SerialNumber,DJI_SkyPort_SerialNumber, sizeof(DJI_SkyPort_SerialNumber));
SerialNumberLength = sizeof(DJI_SkyPort_SerialNumber);
JZSDK_LOG_INFO("带SkyPort设备,序列号%s",SerialNumber);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//2、未有转接环序列号,正常读取序列号
num_file = fopen(SNM_PATH, "rb+");
if (num_file == NULL)
{
SerialNumberType = UNDEFINED_SNM;
JZSDK_LOG_ERROR("不存在序列号文件");
memcpy(SerialNumber, "SN none", sizeof("SN none"));
SerialNumberLength = sizeof("SN none");
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
if (fseek(num_file, 0, SEEK_SET) != 0)
{
JZSDK_LOG_ERROR("序列号读取时,发生计数错误");
SerialNumberType = UNDEFINED_SNM;
memcpy(SerialNumber, "SN ERROR", sizeof("SN ERROR"));
SerialNumberLength = sizeof("SN ERROR");
fclose(num_file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
ret = fread((char *)&num_char, 1, SERIAL_NUMBER_LENGTH, num_file);
if (ret == 0)
{
JZSDK_LOG_ERROR("序列号读取到的长度为0");
SerialNumberType = UNDEFINED_SNM;
memcpy(SerialNumber, "SN none", sizeof("SN none"));
SerialNumberLength = sizeof("SN none");
fclose(num_file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//判断是否是极至标准1的序列号
else if ( (ret <= 14) && (ret >= 12))
{
JZSDK_LOG_INFO("标准一序列号");
SerialNumberType = STANDARD_JZ_1_SNM;
memcpy(SerialNumber, num_char, ret);
SerialNumberLength = ret;
JZSDK_LOG_INFO("序列号%s",SerialNumber);
}
//判断是否是极至标准2的序列号
//目前只靠长度判断
else if(ret == 16)
{
JZSDK_LOG_INFO("标准二序列号");
SerialNumberType = STANDARD_JZ_2_SNM;
memcpy(SerialNumber, num_char, ret);
SerialNumberLength = ret;
JZSDK_LOG_INFO("序列号%s",SerialNumber);
}
else
{
JZSDK_LOG_ERROR("序列号长度错误%d",ret);
memcpy(SerialNumber, "SN ERROR", sizeof("SN ERROR"));
SerialNumberLength = sizeof("SN ERROR");
fclose(num_file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//检测序列号中是否存在换行符,如果有,替换成结束符
JZsdk_replace_newlines_with_null_terminator(SerialNumber);
fclose(num_file);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
/******************************
*
* 设置序列号
*
*
* ************************/
T_JZsdkReturnCode SerialMAT_SetSerialNumber(unsigned char *SerialNumber, unsigned int SerialNumberLen)
{
FILE *num_file = fopen(SNM_PATH, "wb+");
if (num_file == NULL)
{
JZSDK_LOG_ERROR("写入序列号失败");
return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
if( fwrite(SerialNumber, 1, SerialNumberLen, num_file) != SerialNumberLen)
{
JZSDK_LOG_ERROR("写入序列号失败");
fclose(num_file);
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
fclose(num_file);
//刷新序列号
SerialMAT_NumberGet();
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
\ No newline at end of file
... ...
/**
********************************************************************
* @file Megaphone_InputAndOutput.h
* Megaphone_InputAndOutput的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef SERIALMAT_INANDOUT_H
#define SERIALMAT_INANDOUT_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#include "DeviceInfo/SerialNumberProc/FirewareOriginMAT/FirewareOriginMAT.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
T_JZsdkReturnCode SerialMAT_Init();
T_JZsdkReturnCode SerialMAT_Get_SerialNumberStatus();
T_JZsdkReturnCode SerialMAT_ActivateInterface(unsigned char *data, int data_length);
T_JZsdkReturnCode SerialMAT_Set_DJI_SkyPort_SerialNumber(char *str);
T_JZsdkReturnCode SerialMAT_Get_SerialNumber(char *str, int *strlen);
T_JZsdkReturnCode SerialMAT_Read_SerialNumber(char *str, int *strlen);
T_JZsdkReturnCode SerialMAT_SetSerialNumber(unsigned char *SerialNumber, unsigned int SerialNumberLen);
#ifdef __cplusplus
}
#endif
#endif
... ...
/**
********************************************************************
* @file GIMBAL_H3.h
* GIMBAL_H3的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef GIMBAL_H3_H
#define GIMBAL_H3_H
/* Includes ------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
#include "Gimbal_H3_H150ST/Gimbal_H3_H150ST.h"
#include "Gimbal_H3_H10/Gimbal_H3_H10.h"
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
... ...
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include "Gimbal_H3_H10.h"
#include "version_choose.h"
#if WIRINGPI_STATUS == VERSION_SWITCH_ON
#include <wiringPi.h>
#endif
/* Private constants ---------------------------------------------------------*/
#define MOTOR_FILE_PATH "/root/motor"
#define H3_H10_angle_PWM_MIN 1000
#define H3_H10_angle_PWM_MAX 2000
#define H3_H10_MOTOR_ADJUSTMENT 5 //云台微调值
/* Private types -------------------------------------------------------------*/
/* Private functions declaration ---------------------------------------------*/
#define MOTOR 18
static int H3_H10_motor_precise_adjustment_pitch =0;//默认H3微调值为0
static void *Gimbal_H3_H10_Motor_control(void *arg);
static int H3_H10_Read_MotorAdjustmentPitch(void);
static void H3_H10_Write_MotorAdjustmentPitch(int MotorAdjustmentPitch);
int Gimbal_H3_H10_CheckStatus_GimbalFineTuning(int *AdjustmentPitch)
{
*AdjustmentPitch = H3_H10_motor_precise_adjustment_pitch;
}
void Gimbal_H3_H10_init_motor(void)
{
H3_H10_motor_precise_adjustment_pitch = H3_H10_Read_MotorAdjustmentPitch();//获取微调角度-读文件获取
Gimbal_H3_H10_set_angle(0);
}
int Gimbal_H3_H10_set_angle(int angle)
{
printf("H3_H10_angle:%d\n",angle);
//每43.5对饮20度
int num = 200 -angle*195/900; //正常
//int num = 200 -angle*195/900 -150*195/900; //上调15度
#if WIRINGPI_STATUS == VERSION_SWITCH_ON
pwmWrite(MOTOR,num);
#endif
}
//云台微调
T_JZsdkReturnCode Gimbal_H3_H10_set_PitchFineTuning(int Pitch)
{
//微调的角度值 提高Pitch
H3_H10_motor_precise_adjustment_pitch += Pitch;
//写入本地文件
H3_H10_Write_MotorAdjustmentPitch(H3_H10_motor_precise_adjustment_pitch);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//从文件中读出电机微调值
static int H3_H10_Read_MotorAdjustmentPitch(void)
{
FILE *motor_file;
int MotorAdjustmentPitch = 0;
motor_file = fopen(MOTOR_FILE_PATH, "rb+");
if (motor_file == NULL)
{
motor_file = fopen(MOTOR_FILE_PATH, "wb+");
if (motor_file == NULL)
{
return 0;
}
}
else
{
int ret = fseek(motor_file, 0, SEEK_SET);
if (ret != 0) {
printf("Seek log count file error, ret: %d.\r\n", ret);
}
ret = fread((unsigned int *) &MotorAdjustmentPitch, 1, sizeof(unsigned int), motor_file);
if (ret != sizeof(unsigned int)) {
printf("Read motor weitiao error.\r\n");
}
else{
printf("Read motor weitiao=%d\n",MotorAdjustmentPitch);
}
}
fclose(motor_file);
return MotorAdjustmentPitch;
}
//写入电机微调值刀文件中
static void H3_H10_Write_MotorAdjustmentPitch(int MotorAdjustmentPitch)
{
//写入文件
FILE *motor_file;
motor_file = fopen(MOTOR_FILE_PATH, "wb+");
int ret = fwrite((unsigned int *) &MotorAdjustmentPitch, 1, sizeof(unsigned int),motor_file);
if (ret != sizeof(unsigned int)) {
printf("Write motor weitiao error.\r\n");
}
else{
printf("Write motor weitiao=%d\n",MotorAdjustmentPitch);
}
fclose(motor_file);
}
... ...
/**
********************************************************************
* @file GIMBAL_H3_H10.h
* H3板子的h10云台头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef GIMBAL_H3_H10_H
#define GIMBAL_H3_H10_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
int Gimbal_H3_H10_set_angle(int angle);
void Gimbal_H3_H10_init_motor(void);
int Gimbal_H3_H10_CheckStatus_GimbalFineTuning(int *AdjustmentPitch);
//云台微调
T_JZsdkReturnCode Gimbal_H3_H10_set_PitchFineTuning(int Pitch);
#ifdef __cplusplus
}
#endif
#endif
... ...
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "Gimbal_H3_H150ST_UartDeal.h"
#include "Gimbal_H3_H150ST.h"
#include "BaseConfig.h"
#include "JZsdk_uart/UartConnection/UartConnection.h"
#include "JZsdk_TaskManagement/TaskManagement.h"
/* Private constants ---------------------------------------------------------*/
#define MOTOR_FILE_PATH "/root/motor"
#define H3_H150ST_angle_PWM_MIN 1000
#define H3_H150ST_angle_PWM_MAX 2000
#define H3_H150ST_MOTOR_ADJUSTMENT 5 //云台微调值
/* Private types -------------------------------------------------------------*/
/* Private functions declaration ---------------------------------------------*/
static int H3_H150ST_motor_precise_adjustment_pitch =0;//默认H3微调值为0
static void *H3_H150ST_Motor_control(void *arg);
static void H3_H150ST_Write_MotorAdjustmentPitch(int MotorAdjustmentPitch);
static int H3_H150ST_Read_MotorAdjustmentPitch();
T_JZsdkReturnCode Gimbal_H3_H150ST_init_motor()
{
int Uart_fd = 0;
//1、串口初始化
Uart_fd = UartConnection_UartEnabled(GIMBAL_UART_NUM, GIMBAL_UART_BITRATE);
//2、串口接收初始化
Gimbal_H3_H150ST_UartDeal_Receive(Uart_fd);
//从文件中读出电机微调值
H3_H150ST_motor_precise_adjustment_pitch = H3_H150ST_Read_MotorAdjustmentPitch();
}
/**********
*
* 发送任务函数
*
* ***********/
static void JZsdk_Uart_UartSend_Task(void *data)
{
Gimbal_H3_H150ST_UartDeal_UartSend(data, 4);
}
/****************
*
*
* 发送函数
*
* ****************/
T_JZsdkReturnCode H150ST_UartSend(unsigned char *data, int num)
{
unsigned char *str = (unsigned char*)malloc(sizeof(data));
memcpy(str, data, sizeof(data));
T_JZsdkReturnCode ret = TaskManagement_SubmitTask(JZsdk_Uart_UartSend_Task, (void *)str);
if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
{
free(str);
return ret;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//设置角度
int H3_H150ST_Gimbal_SetAngle(int angle)
{
//调整为PWM值 1000~2000
int angle_PWM = 0;
if(angle>=0){
angle_PWM = H3_H150ST_angle_PWM_MIN;
}
else if(angle<=-900){
angle_PWM = H3_H150ST_angle_PWM_MAX;
}
else if(angle<0 && angle>-900)
{
angle_PWM= H3_H150ST_angle_PWM_MIN +(-angle)*(H3_H150ST_angle_PWM_MAX-H3_H150ST_angle_PWM_MIN)/900;
}
char send_angle[]={0x5a,0x00,0x00,0xa5};
send_angle[1]=(char )(angle_PWM);
send_angle[2]=(char )(angle_PWM>>8);
H150ST_UartSend(send_angle, 4);
}
//H150ST云台范围
T_JZsdkReturnCode H3_H150ST_SetGimbalRange(int Range)
{
uint8_t set_min_motor[]={0x4A,0x00,0x00,0xA4};
uint8_t set_max_motor[]={0x6A,0x00,0x00,0xA6};
if (Range == 0xFF)
{
printf("设置H150ST云台最大值\n");
Gimbal_H3_H150ST_UartDeal_UartSend(set_max_motor, 4);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
else if (Range == 0x00)
{
printf("设置H150ST云台最小值\n");
Gimbal_H3_H150ST_UartDeal_UartSend(set_min_motor, 4);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
}
//云台微调
T_JZsdkReturnCode Gimbal_H3_H150ST_set_PitchFineTuning(int Pitch)
{
//微调的角度值 提高Pitch
H3_H150ST_motor_precise_adjustment_pitch += Pitch;
//写入本地文件
H3_H150ST_Write_MotorAdjustmentPitch(H3_H150ST_motor_precise_adjustment_pitch);
return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//微调向上
void H3_H150ST_gimbal_up(void)
{
//微调的pwm值 提高5
H3_H150ST_motor_precise_adjustment_pitch = H3_H150ST_motor_precise_adjustment_pitch + H3_H150ST_MOTOR_ADJUSTMENT;
//写入本地文件
H3_H150ST_Write_MotorAdjustmentPitch(H3_H150ST_motor_precise_adjustment_pitch);
}
//向下微调
void H3_H150ST_gimbal_down(void)
{
//微调的pwm值 减少5
H3_H150ST_motor_precise_adjustment_pitch = H3_H150ST_motor_precise_adjustment_pitch - H3_H150ST_MOTOR_ADJUSTMENT;
//写入本地文件
H3_H150ST_Write_MotorAdjustmentPitch(H3_H150ST_motor_precise_adjustment_pitch);
}
//查询云台微调值
int Gimbal_H3_H150ST_CheckStatus_GimbalFineTuning(int *AdjustmentPitch)
{
*AdjustmentPitch = H3_H150ST_motor_precise_adjustment_pitch;
}
//从文件中读出电机微调值
static int H3_H150ST_Read_MotorAdjustmentPitch()
{
FILE *motor_file;
int MotorAdjustmentPitch = 0;
motor_file = fopen(MOTOR_FILE_PATH, "rb+");
if (motor_file == NULL)
{
motor_file = fopen(MOTOR_FILE_PATH, "wb+");
if (motor_file == NULL)
{
return 0;
}
}
else
{
int ret = fseek(motor_file, 0, SEEK_SET);
if (ret != 0) {
printf("Seek log count file error, ret: %d.\r\n", ret);
}
ret = fread((unsigned int *) &MotorAdjustmentPitch, 1, sizeof(unsigned int), motor_file);
if (ret != sizeof(unsigned int)) {
printf("Read motor weitiao error.\r\n");
}
else{
printf("Read motor weitiao=%d\n",MotorAdjustmentPitch);
}
}
fclose(motor_file);
return MotorAdjustmentPitch;
}
//写入电机微调值刀文件中
static void H3_H150ST_Write_MotorAdjustmentPitch(int MotorAdjustmentPitch)
{
//写入文件
FILE *motor_file;
motor_file = fopen(MOTOR_FILE_PATH, "wb+");
int ret = fwrite((unsigned int *) &MotorAdjustmentPitch, 1, sizeof(unsigned int),motor_file);
if (ret != sizeof(unsigned int)) {
printf("Write motor weitiao error.\r\n");
}
else{
printf("Write motor weitiao=%d\n",MotorAdjustmentPitch);
}
fclose(motor_file);
}
... ...
/**
********************************************************************
* @file GIMBAL_H3.h
* GIMBAL_H3的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef GIMBAL_H3_H150ST_H
#define GIMBAL_H3_H150ST_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
int H3_H150ST_Gimbal_SetAngle(int angle);
int Gimbal_H3_H150ST_CheckStatus_GimbalFineTuning(int *AdjustmentPitch);
T_JZsdkReturnCode Gimbal_H3_H150ST_init_motor();
T_JZsdkReturnCode H3_H150ST_SetGimbalRange(int Range);
T_JZsdkReturnCode Gimbal_H3_H150ST_set_PitchFineTuning(int Pitch);
#ifdef __cplusplus
}
#endif
#endif
... ...
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/time.h>
static void *UartDeal_rece(void *arg);
static void *UartDeal_send(void *arg);
static int Gimbal_Uart_fd = 0;
/******************************************************************
创建一个接收Gimbal的接收线程
******************************************************************/
int Gimbal_H3_H150ST_UartDeal_Receive(int Uart_fd)
{
int ret = 0;
pthread_t Uart_rece_task;
Gimbal_Uart_fd = Uart_fd;
pthread_attr_t task_attribute; //线程属性
pthread_attr_init(&task_attribute); //初始化线程属性
pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED); //设置线程属性
ret = pthread_create(&Uart_rece_task,&task_attribute,UartDeal_rece,NULL); //串口接收线程
if(ret != 0)
{
printf("创建展架串口接收线程失败!\n");
}
else{
printf("创建展架串口接收线程成功!\n");
}
}
static void *UartDeal_rece(void *arg)
{
char getbuf[1024];
int ret = 0;
fd_set fs_read;
struct timeval tv_timeout;
//FD_ZERO 将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化
//如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
FD_ZERO(&fs_read);
//FD_SET 用于在文件描述符集合中增加一个新的文件描述符。
FD_SET(Gimbal_Uart_fd, &fs_read);
//115200 / char 8 位 = 14400 个char数据
//tv_timeout.tv_sec = 6000;//(10*20/115200+2);
//tv_timeout.tv_usec = 0;
//2、正常接收
while(1)
{
//检查fs_read套节字是否有数据
select(Gimbal_Uart_fd+1, &fs_read, NULL, NULL, NULL);
usleep(10000);
//FD_ISSET 用于测试指定的文件描述符是否在该集合中。
//Gimbal_Uart_fd 是否在fsread中
if (FD_ISSET(Gimbal_Uart_fd, &fs_read))
{
//1、读取串口内容 ret 接收长度 getbuf 获取的字符
memset(getbuf,0,sizeof(getbuf)); //清空接收数组
ret = read(Gimbal_Uart_fd,getbuf,sizeof(getbuf));
}
}
}
/****************
*
*
* 发送函数
*
* ****************/
int Gimbal_H3_H150ST_UartDeal_UartSend(unsigned char *send, int num)
{
write(Gimbal_Uart_fd,send, num);
return 0;
}
... ...
/**
********************************************************************
* @file Gimbal_UartDeal.h
* Gimbal_UartDeal的头文件
*
*********************************************************************
*/
/* Define to prevent recursive inclusion 避免重定义 -------------------------------------*/
#ifndef GIMBAL_UART_DEAL_H
#define GIMBAL_UART_DEAL_H
/* Includes ------------------------------------------------------------------*/
#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* 常亮定义*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
int Gimbal_H3_H150ST_UartDeal_Receive(int Uart_fd);
int Gimbal_H3_H150ST_UartDeal_UartSend(unsigned char *send, int num);
#ifdef __cplusplus
}
#endif
#endif
... ...