Пример #1
0
/**
    \fn goToTime
    \brief goToTime
*/
bool  ADM_audioStream::goToTime(uint64_t nbUs)
{
    if(access->canSeekTime()==true)
    {
        if( access->goToTime(nbUs)==true)
        {
           setDts(nbUs);
           return 1;
        }
        return 1;
    }
    ADM_assert(true==access->canSeekOffset());
    // Convert time to offset in bytes
    float f=nbUs*wavHeader.byterate;
    f/=1000;
    f/=1000; // in bytes
    if(access->setPos( (uint32_t)(f+0.5)))
    {
        // The seek might not be accurate, recompute the Dts
        // it is better to undershoot in most case
        uint64_t pos=access->getPos();
        // compute dts from pos & byterate
        float r=pos;
            r*=1000*1000;
            r/=wavHeader.byterate;
            setDts(r);
        return 1;
    }
    return false;
}
Пример #2
0
/**
        \fn getPacket
*/
uint8_t ADM_audioStream::getPacket(uint8_t *buffer,uint32_t *size, uint32_t sizeMax,uint32_t *nbSample,uint64_t *odts)
{
uint64_t dts=0;
    if(!access->getPacket(buffer,size,sizeMax,&dts)) return 0;
    // We got the packet
    // Try to guess the nbSample
    // if it is AAC, we hardcodec 1024 samples

    if(wavHeader.encoding==WAV_AAC)
    {
        *nbSample=1024;
        if(dts!=ADM_AUDIO_NO_DTS)
        {
            setDts(dts);
        }
        *odts=dts;
        return 1;
    }
    if(dts==ADM_AUDIO_NO_DTS)
    {
        *nbSample=512;
        ADM_warning("[audioStream] Cant guess nb sample, setting 512\n");
        *odts=ADM_AUDIO_NO_DTS;
        return 1;
    }
    //printf("[ADM_audioStream::get Packet : Size %u dts:%lu\n",size,dts);
    float f=dts-lastDts;
    f*=wavHeader.frequency;
    f/=1000;
    f/=1000;
    setDts(dts);
    *nbSample=(uint32_t)(f+0.5);
    *odts=dts;
    return 1;
}
/**
        \fn refill
*/
bool ADM_audioStreamBuffered::refill(void)
{
        // Shrink buffer...
        if(limit>ADM_AUDIOSTREAM_BUFFER_SIZE && start> 10*1024)
        {
            //printf("[Shrink]\n");
            memmove(buffer.at(0), buffer.at(start),limit-start);
            limit-=start;
            start=0;
        }
        uint64_t newDts;
        uint32_t size;
        ADM_assert(limit<(2*ADM_AUDIOSTREAM_BUFFER_SIZE-16));
        uint32_t toRead=2*ADM_AUDIOSTREAM_BUFFER_SIZE-limit-16;
        if(true!=access->getPacket(buffer.at(limit), &size, toRead,&newDts))
                return false;
        // We introduce a small error as there might be some bytes left in the buffer
        // By construction, the error should be minimal
        if(newDts!=ADM_AUDIO_NO_DTS)
        {
            if( abs(newDts-lastDts)>ADM_MAX_SKEW)
            {
                printf("[AudioStream] Warning skew in dts =%"PRId64", \n",(int64_t)newDts-(uint64_t)lastDts);
                printf("[AudioStream] Warning skew lastDts=%s \n",ADM_us2plain(lastDts));
                printf("[AudioStream] Warning skew newDts=%s  \n",ADM_us2plain(newDts));
                setDts(newDts);
            }
            // If we have a DTS and the buffer is empty, set the dts inconditionnaly
            if(!start) setDts(newDts); // Fixme allow a bit of error, not accumulating
        }
        limit+=size;
        ADM_assert(limit<ADM_AUDIOSTREAM_BUFFER_SIZE*2);
        return true;
}
/**
    \fn goToTime
    \brief goToTime
*/
bool         ADM_audioStreamPCM::goToTime(uint64_t nbUs)
{
    if(access->canSeekTime()==true)
    {
        if( access->goToTime(nbUs)==true)
        {
           setDts(nbUs);
           return 1;
        }
        return 1;
    }
    // If CBR we can use the default way
    return ADM_audioStream::goToTime(nbUs);
    
}
/**
    \fn goToTime
    \brief goToTime
*/
bool         ADM_audioStreamAC3::goToTime(uint64_t nbUs)
{
    if(access->canSeekTime()==true)
    {
        if( access->goToTime(nbUs)==true)
        {
           setDts(nbUs);
           limit=start=0;
           refill();
           return 1;
        }
        return 1;
    }
    // If CBR we can use the default way
    return ADM_audioStream::goToTime(nbUs);
    
}
/**
        \fn getPacket
*/
uint8_t ADM_audioStreamPCM::getPacket(uint8_t *obuffer,uint32_t *osize, 
                                      uint32_t sizeMax,uint32_t *nbSample,uint64_t *dts)
{
uint64_t thisDts=0;
    if(!access->getPacket(obuffer,osize,sizeMax,&thisDts)) return 0;

    int  sampleSize=2;
    if(wavHeader.bitspersample==8) sampleSize=1;
    uint32_t bytesPerSample=wavHeader.channels*sampleSize; 
//#warning fixme handle mono
    *nbSample=(uint32_t)(*osize/bytesPerSample);
    if(thisDts!=ADM_NO_PTS) 
            setDts(thisDts);
    *dts=lastDts;
//    printf(">>audioCore : PCM packet : %s\n",ADM_us2plain(*dts));
    advanceDtsBySample(*nbSample);
    return 1;
}
/**
    \fn goToTime
    \brief Audio Seek in ms

*/
bool ADM_edAudioTrackFromVideo::goToTime (uint64_t ustime)
{
  uint32_t seg;
  uint64_t segTime;
    ADM_info(" go to time %02.2f secs\n",((float)ustime)/1000000.);
    if(false==parent->_segments.convertLinearTimeToSeg(ustime,&seg,&segTime))
      {
        ADM_warning("Cannot convert %"PRIu64" to linear time\n",ustime/1000);
        return false;
      }
    ADM_info("=> seg %d, rel time %02.2f secs\n",(int)seg,((float)segTime)/1000000.);
    _SEGMENT *s=parent->_segments.getSegment(seg);
    ADM_audioStreamTrack *trk=getTrackAtVideoNumber(s->_reference);
    if(!trk)
      {
        ADM_warning("No audio for segment %"PRIu32"\n",seg);
        return false;
      }
    uint64_t seekTime;
    seekTime=segTime+s->_refStartTimeUs;
    ADM_Audiocodec *codec=trk->codec;
    if(codec)
    {
        codec->resetAfterSeek();
    }

    if(true==trk->stream->goToTime(seekTime))
    {
        _audioSeg=seg;
        setDts(ustime);
        packetBufferSize=0; // Flush PCM decoder
        return true;
    }
    ADM_warning("Go to time failed\n");
    return false;
}
/**
    \fn getPCMPacket
*/
bool         ADM_edAudioTrackExternal::getPCMPacket(float  *dest, uint32_t sizeMax, uint32_t *samples,uint64_t *odts)
{
uint32_t fillerSample=0;   // FIXME : Store & fix the DTS error correctly!!!!
uint32_t inSize;
bool      drop=false;
uint32_t outFrequency=codec->getOutputFrequency();
 vprintf("[PCMPacketExt]  request TRK %d:%x\n",0,(long int)0);
again:
    *samples=0;
    // Do we already have a packet ?
    if(!packetBufferSize)
    {
        if(!refillPacketBuffer())
        {
            ADM_warning("Cannot refill\n");
            return false;
        }
    }
    // We do now
    vprintf("[PCMPacketExt]  Packet size %d, Got %d samples, time code %08lu  lastDts=%08lu delta =%08ld\n",
                packetBufferSize,packetBufferSamples,packetBufferDts,lastDts,packetBufferDts-lastDts);


    // If lastDts is not initialized....
    if(lastDts==ADM_AUDIO_NO_DTS) setDts(packetBufferDts);
    vprintf("Last Dts=%s\n",ADM_us2plain(lastDts));
    //
    //  The packet is ok, decode it...
    //
    uint32_t nbOut=0; // Nb sample as seen by codec
    vprintf("externalPCM: Sending %d bytes to codec\n",packetBufferSize);
    if(!codec->run(packetBuffer, packetBufferSize, dest, &nbOut))
    {
            packetBufferSize=0; // consume
            ADM_warning("[PCMPacketExt::getPCMPacket] Track %d:%x : codec failed failed\n", 0,0);
            return false;
    }
    packetBufferSize=0; // consume

    // Compute how much decoded sample to compare with what demuxer said
    uint32_t decodedSample=nbOut;
    decodedSample/=wavHeader.channels;
    if(!decodedSample) goto again;
#define ADM_MAX_JITTER 5000  // in samples, due to clock accuracy, it can be +er, -er, + er, -er etc etc
    if(labs((int64_t)decodedSample-(int64_t)packetBufferSamples)>ADM_MAX_JITTER)
    {
        ADM_warning("[PCMPacketExt::getPCMPacket] Track %d:%x Demuxer was wrong %d vs %d samples!\n",
                    0,0,packetBufferSamples,decodedSample);
    }
    
    // Update infos
    *samples=(decodedSample);
    *odts=lastDts;
    vprintf("externalPCM: got %d samples, PTS is now %s\n",decodedSample,ADM_us2plain(*odts));
    advanceDtsByCustomSample(decodedSample,outFrequency);
    vprintf("[Composer::getPCMPacket] Track %d:%x Adding %u decoded, Adding %u filler sample,"
        " dts is now %lu\n", 0,(long int)0,  decodedSample,fillerSample,lastDts);
    ADM_assert(sizeMax>=(fillerSample+decodedSample)*wavHeader.channels);
    vprintf("[getPCMext] %d samples, dts=%s\n",*samples,ADM_us2plain(*odts));
    return true;
}