Megaphone_RealTimeMP2.c 11.5 KB
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>


#include "JZsdkLib.h"
#include "Megaphone_InputAndOutput.h"
#include "../Megaphone_Music.h"
#include "version_choose.h"

static int ReadTimeMP2_StatusFlag = JZ_FLAGCODE_OFF;


//写入数据部分
static unsigned char Music_RealTimeMP2_WriteData_Loop[(255 + 1)][128];  //实时mp2缓冲输入池
static int Music_RealTimeMP2_WriteData_LoopHead	=	0;				//池数头
static int Music_RealTimeMP2_WriteData_LoopEnd	=	0;				//池数尾
static int Music_RealTimeMP2_WriteData_ResidueLenth; // 写入缓存池池子残余物长度
static int Music_RealTimeMP2_WriteFlag=0;//读取标志位0为停止,1为开始

pthread_mutex_t RealTimeMP2_WriteDataLock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  RealTimeMP2_WriteCond = PTHREAD_COND_INITIALIZER;

static void *Music_RealTimeMP2_WriteData_Task(void *arg);
static int Music_RealTimeMP2_WriteDataClear();
static int Music_RealTimeMP2_WriteDataToLoop(unsigned char *buf,int length);
static void Music_RealTimeMP2_WriteDataHeadReset();


static int Music_RealTimeMP2_WriteData_init();



T_JZsdkReturnCode Music_RealTimeMP2_start()
{
    //1、开启实时mp2模式
    ReadTimeMP2_StatusFlag = JZ_FLAGCODE_ON;

    //2、创建输入缓冲线程
    Music_RealTimeMP2_WriteData_init();

    //3、创建播放线程
    //Music_RealTimeMP2_Play_init();

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

T_JZsdkReturnCode Music_RealTimeMP2_trans(unsigned char *getdata, int len)
{

    Music_RealTimeMP2_WriteDataToLoop(getdata, len);

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

T_JZsdkReturnCode Music_RealTimeMP2_stop()
{
    ReadTimeMP2_StatusFlag = JZ_FLAGCODE_OFF;

    Music_RealTimeMP2_WriteFlag = JZ_FLAGCODE_OFF;

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS; 
}


/************************************************************************************************************************************************
 * 
 *      解码播放部分
 * 
 * 
*************************************************************************************************************************************************/


//解码opus并播放
static int Music_RealTimeMP2_PlayData(unsigned char *data,int len)
{
    unsigned char playFile[len + 9 + 2];

    printf("播放开始\n");


    //清空
    memset(playFile, 0, (len + 9 + 2));
    
    //帧头
    playFile[0] = 0x5a;
    playFile[1] = 0x5a;
    playFile[2] = 0x77;
    playFile[7] = 0x51;
    playFile[8] = 0x04;

    //帧数据
    memcpy(&playFile[9],data,len);
    len = len + 9 + 2;

    //帧尾
    playFile[len - 1] = 0x00;
    playFile[len] = 0x00;

    Music_SendFrame_FramePlay(playFile,len);

    printf("播放结束\n");

    return 0;
}



/************************************************************************************************************************************************
 * 
 *      写入缓冲池部分
 * 
 * 
*************************************************************************************************************************************************/
//写入数据部分初始化
static int Music_RealTimeMP2_WriteData_init()
{
	
	//清空写入数据池
	Music_RealTimeMP2_WriteDataClear();

	pthread_t WriteDataTask;
	pthread_attr_t task_attribute; //线程属性
	pthread_attr_init(&task_attribute);  //初始化线程属性
	pthread_attr_setdetachstate(&task_attribute, PTHREAD_CREATE_DETACHED);      //设置线程分离属性
	int opus_Protection = pthread_create(&WriteDataTask,&task_attribute,Music_RealTimeMP2_WriteData_Task,NULL);		//线程
	if(opus_Protection != 0)
	{
		printf("创建输入缓冲池线程线程失败!\n");
		ReadTimeMP2_StatusFlag = JZ_FLAGCODE_OFF;
		return -2;
	}
}

//输入缓冲池任务
static void *Music_RealTimeMP2_WriteData_Task(void *arg)
{

	int ret;
	printf("MP2实施喊话,输入数据缓冲线程建立\n");
	Music_RealTimeMP2_WriteFlag = JZ_FLAGCODE_ON;

#if PLATFORM_VERSION == PLATFORM_H3
	while(Music_RealTimeMP2_WriteFlag == JZ_FLAGCODE_ON)
	{
		pthread_mutex_lock(&RealTimeMP2_WriteDataLock);  // 获取互斥锁

		// 等待写入数据
        while (Music_RealTimeMP2_WriteData_LoopHead == Music_RealTimeMP2_WriteData_LoopEnd)
		{
            pthread_cond_wait(&RealTimeMP2_WriteCond, &RealTimeMP2_WriteDataLock);
        }

		if(Music_RealTimeMP2_WriteData_LoopHead != Music_RealTimeMP2_WriteData_LoopEnd)
		{

			printf("缓冲线程写入中\n");
	
			//将输入缓冲池的数据放入播放缓冲池
			Music_RealTimeMP2_PlayData(Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopHead], 128);
			printf("Music_RealTimeMP2_WriteData_LoopHead:%d\n",Music_RealTimeMP2_WriteData_LoopHead);
			Music_RealTimeMP2_WriteData_LoopHead ++;
			Music_RealTimeMP2_WriteDataHeadReset();

		}

		pthread_mutex_unlock(&RealTimeMP2_WriteDataLock);  // 释放互斥锁

	}
#elif PLATFORM_VERSION == PLATFORM_V3S
	while(Music_RealTimeMP2_WriteFlag == JZ_FLAGCODE_ON)
	{
		pthread_mutex_lock(&RealTimeMP2_WriteDataLock);  // 获取互斥锁

		if(Music_RealTimeMP2_WriteData_LoopHead != Music_RealTimeMP2_WriteData_LoopEnd)
		{
			printf("缓冲线程写入中\n");
	
			//将输入缓冲池的数据放入播放缓冲池
			Music_RealTimeMP2_PlayData(Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopHead], 128);
			printf("Music_RealTimeMP2_WriteData_LoopHead:%d\n",Music_RealTimeMP2_WriteData_LoopHead);
			Music_RealTimeMP2_WriteData_LoopHead ++;
			Music_RealTimeMP2_WriteDataHeadReset();
		}

		pthread_cond_signal(&RealTimeMP2_WriteCond);  // 发送信号通知播放线程可以开始播放
		pthread_mutex_unlock(&RealTimeMP2_WriteDataLock);  // 释放互斥锁

	}
#else
	printf("mp2实时语音未能识别到正常的板子型号");
#endif

}

//写入数据缓存池重置
static int Music_RealTimeMP2_WriteDataClear()
{
	Music_RealTimeMP2_WriteData_LoopHead=0;
	Music_RealTimeMP2_WriteData_LoopEnd=0;
	Music_RealTimeMP2_WriteData_ResidueLenth = 0;
}


// 写入池子头部到底了,重置池头
static void Music_RealTimeMP2_WriteDataHeadReset()
{
	if (Music_RealTimeMP2_WriteData_LoopHead >= 255)
	{
		Music_RealTimeMP2_WriteData_LoopHead = 0;
	}
}

//	写入池子尾部到底了,重置池尾
static void Music_RealTimeMP2_WriteDataEndReset()
{
	if (Music_RealTimeMP2_WriteData_LoopEnd >= 255)
	{
		Music_RealTimeMP2_WriteData_LoopEnd = 0;
	}
}



//写入数据进缓存池,以用于后续播放
static int Music_RealTimeMP2_WriteDataToLoop(unsigned char *buf,int length)
{

	int temp_lenth = 0;  //临时长度

	//判断输入的数据长度是否正常
	if (length <= 0)
	{
		printf("输入进缓冲池的数据长度有误:%d\n",length);
		return -1;
	}
	
#if PLATFORM_VERSION == PLATFORM_H3
	//写入处理
	//① 、检查池子当前组内有无剩余数据,如果池子当前组有剩  上次写入的语音数据, 接着往里面写入
	if (Music_RealTimeMP2_WriteData_ResidueLenth > 0) //如果残留物有长度
	{
		pthread_mutex_lock(&RealTimeMP2_WriteDataLock);  // 获取互斥锁

		//数据进池,每组128数据
		for(  ; Music_RealTimeMP2_WriteData_ResidueLenth < 128 ; Music_RealTimeMP2_WriteData_ResidueLenth ++)
		{
			Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopEnd] [Music_RealTimeMP2_WriteData_ResidueLenth] = buf [temp_lenth];
			temp_lenth ++;
		}
		Music_RealTimeMP2_WriteData_LoopEnd+=1;    //池尾后移一组
		Music_RealTimeMP2_WriteData_ResidueLenth = 0;       //残留物长度归0

		Music_RealTimeMP2_WriteDataEndReset(); //池满判断

        pthread_mutex_unlock(&RealTimeMP2_WriteDataLock);  // 释放互斥锁
        pthread_cond_signal(&RealTimeMP2_WriteCond);  // 发送信号通知播放线程可以开始播放

	}

	//②、从新的组处理数据
	//待处理数据超过128长度时
	while( (length - temp_lenth) >= 128)
	{	

		//数据进池,每组128数据
		//printf("往池子里的第%d号里写入数据\n",Music_RealTimeMP2_WriteData_LoopEnd);

		pthread_mutex_lock(&RealTimeMP2_WriteDataLock);  // 获取互斥锁
		
		for(int ucLen = 0 ; ucLen < 128 ; ucLen ++)
		{
			Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopEnd] [ucLen] = buf [temp_lenth];
			temp_lenth ++;
		}

		printf("携入loopend:%d\n",Music_RealTimeMP2_WriteData_LoopEnd);

		Music_RealTimeMP2_WriteData_LoopEnd+=1;  //池尾后移一组


		Music_RealTimeMP2_WriteDataEndReset(); //池满判断

        pthread_mutex_unlock(&RealTimeMP2_WriteDataLock);  // 释放互斥锁
		pthread_cond_signal(&RealTimeMP2_WriteCond);  // 发送信号通知播放线程可以开始播放

	}

#elif PLATFORM_VERSION == PLATFORM_V3S
	//写入处理
	//① 、检查池子当前组内有无剩余数据,如果池子当前组有剩  上次写入的语音数据, 接着往里面写入
	if (Music_RealTimeMP2_WriteData_ResidueLenth > 0) //如果残留物有长度
	{
		pthread_mutex_lock(&RealTimeMP2_WriteDataLock);  // 获取互斥锁

		//数据进池,每组128数据
		for(  ; Music_RealTimeMP2_WriteData_ResidueLenth < 128 ; Music_RealTimeMP2_WriteData_ResidueLenth ++)
		{
			Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopEnd] [Music_RealTimeMP2_WriteData_ResidueLenth] = buf [temp_lenth];
			temp_lenth ++;
		}
		Music_RealTimeMP2_WriteData_LoopEnd+=1;    //池尾后移一组
		Music_RealTimeMP2_WriteData_ResidueLenth = 0;       //残留物长度归0

		Music_RealTimeMP2_WriteDataEndReset(); //池满判断

		pthread_cond_wait(&RealTimeMP2_WriteCond, &RealTimeMP2_WriteDataLock);
        pthread_mutex_unlock(&RealTimeMP2_WriteDataLock);  // 释放互斥锁

	}

	//②、从新的组处理数据
	//待处理数据超过128长度时
	while( (length - temp_lenth) >= 128)
	{	

		//数据进池,每组128数据
		//printf("往池子里的第%d号里写入数据\n",Music_RealTimeMP2_WriteData_LoopEnd);

		pthread_mutex_lock(&RealTimeMP2_WriteDataLock);  // 获取互斥锁
		
		for(int ucLen = 0 ; ucLen < 128 ; ucLen ++)
		{
			Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopEnd] [ucLen] = buf [temp_lenth];
			temp_lenth ++;
		}

		printf("携入loopend:%d\n",Music_RealTimeMP2_WriteData_LoopEnd);

		Music_RealTimeMP2_WriteData_LoopEnd+=1;  //池尾后移一组


		Music_RealTimeMP2_WriteDataEndReset(); //池满判断

		pthread_cond_wait(&RealTimeMP2_WriteCond, &RealTimeMP2_WriteDataLock);
        pthread_mutex_unlock(&RealTimeMP2_WriteDataLock);  // 释放互斥锁

	}
#else
	printf("mp2实时语音传输未能识别到正常的板子型号");
#endif

	//③、如果长度还有剩,把数据存到池子内的新组,并记录残留物长度
	if( (length - temp_lenth) > 0)
	{
		for (   ; temp_lenth < length ; Music_RealTimeMP2_WriteData_ResidueLenth++)
		{
			Music_RealTimeMP2_WriteData_Loop[Music_RealTimeMP2_WriteData_LoopEnd] [Music_RealTimeMP2_WriteData_ResidueLenth] = buf [temp_lenth];
			temp_lenth ++;
		}	
	
	}

	return 0;
}


/************************************************************************************************************************************************
 * 
 *      状态相关
 * 
 * 
*************************************************************************************************************************************************/
/********************
 * 
 *  获取实时MP2模式
 * 
 * **************/
T_JZsdkReturnCode Music_RealTimeMP2_GetStatusFlag()
{
	return ReadTimeMP2_StatusFlag;
}