/** \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; }
/** \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; }