bool CBufferAccumulator::AddPacket(const BYTE* PacketData, int DataSize, int PacketCounter, bool IsLastPacket) { if(m_LastPacketCounter == 0) { //first packet if(PacketCounter != 1) { LogEvent(LE_ERROR, "CBufferAccumulator::AddPacket(), first packet counter is not 1 [counter %d]", PacketCounter); return false; } return AppendPacket(PacketData, DataSize, PacketCounter, IsLastPacket); } else { //subsequent packets bool IsSequentialPacket = (PacketCounter == m_LastPacketCounter + 1); if(!IsSequentialPacket) { LogEvent(LE_ERROR, "CBufferAccumulator::AddPacket(), packet not sequential [incoming %d] [last %d]", PacketCounter, m_LastPacketCounter); return false; } return AppendPacket(PacketData, DataSize, PacketCounter, IsLastPacket); } }
//==================================================================================================================== // Append data to the list creating packet as necessary and filling TempData //==================================================================================================================== void cSoundBlockList::AppendData(int64_t Position,int16_t *Data,int64_t DataLen) { u_int8_t *CurData=(u_int8_t *)Data; // Cut data to Packet while ((DataLen+CurrentTempSize>=SoundPacketSize)) { #if defined(LIBAV) && (LIBAVVERSIONINT<=8) u_int8_t *Packet=(u_int8_t *)av_malloc(SoundPacketSize+8); #else u_int8_t *Packet=NULL; int out_linesize=0; av_samples_alloc(&Packet,&out_linesize,Channels,SoundPacketSize+8,SampleFormat,1); #endif if (Packet) { if (CurrentTempSize>0) { // Use previously data store in TempData int DataToUse=SoundPacketSize-CurrentTempSize; memcpy(Packet,TempData,CurrentTempSize); memcpy(Packet+CurrentTempSize,CurData,DataToUse); DataLen -=DataToUse; CurData +=DataToUse; CurrentTempSize=0; } else { // Construct a full packet memcpy(Packet,CurData,SoundPacketSize); DataLen-=SoundPacketSize; CurData+=SoundPacketSize; } AppendPacket(Position,(int16_t *)Packet); Position+=(double(SoundPacketSize/2*Channels)/double(SamplingRate))*AV_TIME_BASE; } } if (DataLen>0) { // Store a partial packet in temp buffer // Store data left to TempData memcpy(TempData+CurrentTempSize,CurData,DataLen); CurrentTempSize+=DataLen; } }
//==================================================================================================================== // Synchronize sound to a wanted position //==================================================================================================================== void cSoundBlockList::AdjustSoundPosition(int64_t WantedPosition) { if (Adjusted) return; Mutex.lock(); Adjusted=true; if (List.count()==0) { for (int i=0;i<NbrPacketForFPS;i++) AppendPacket(WantedPosition,NULL,true); } else if (CurrentPosition>WantedPosition) { int64_t BlockDuration=(double(SoundPacketSize)/(SampleBytes*Channels*SamplingRate))*AV_TIME_BASE; while (CurrentPosition>WantedPosition) { CurrentPosition-=BlockDuration; PrependPacket(CurrentPosition,NULL,true); } } else if (CurrentPosition<WantedPosition-50000) { while (CurrentPosition<WantedPosition-50000) { int16_t *Packet=DetachFirstPacket(true); if (Packet) av_free(Packet); else break; } } Mutex.unlock(); }
//==================================================================================================================== // Append a packet to the end of the list by mixing 2 packet // Note : the 2 packet are free during process //==================================================================================================================== void cSoundBlockList::MixAppendPacket(int64_t Position,int16_t *PacketA,int16_t *PacketB,bool NoLock) { int32_t mix; if ((PacketA==NULL)&&(PacketB==NULL)) AppendNullSoundPacket(Position,NoLock); else if ((PacketA!=NULL)&&(PacketB==NULL)) AppendPacket(Position,PacketA,NoLock); else if ((PacketA==NULL)&&(PacketB!=NULL)) AppendPacket(Position,PacketB,NoLock); else { // Mix the 2 sources buffer using the first buffer as destination int16_t *Buf1=PacketA; int16_t *Buf2=PacketB; for (int j=0;j<SoundPacketSize/2;j++) { mix=*(Buf1)+*(Buf2++); if (mix>32767) mix=32767; else if (mix<-32768) mix=-32768; // Adjust if necessary (16 bits) *(Buf1++)=int16_t(mix); } av_free(PacketB); // Free the second buffer AppendPacket(Position,PacketA,NoLock); } }
//==================================================================================================================== // Append a packet of null sound to the end of the list //==================================================================================================================== void cSoundBlockList::AppendNullSoundPacket(int64_t Position,bool NoLock) { AppendPacket(Position,NULL,NoLock); }