Example #1
0
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);
}