/// ±àÂë int32_t CAacDecoder::Decodec(const char* pSrcBuffer, uint32_t nSrcBuffSize, char* pDestBuffer, uint32_t nDestBufferSize) { int32_t nResult = 0; if(NULL != m_hHandleDecoder) { if(!m_bIsInitDec) { unsigned long nSamplesRate = 0; unsigned char nChannel = 0; faacDecInit(m_hHandleDecoder, (unsigned char*)pSrcBuffer, nSrcBuffSize, &nSamplesRate, &nChannel); m_bIsInitDec = TRUE; } if(m_bIsInitDec) { char* pSampleBuffer = (char*)NeAACDecDecode2(m_hHandleDecoder, &m_aacFrameInfo, (unsigned char*)pSrcBuffer, nSrcBuffSize, (void**)&pDestBuffer, nDestBufferSize); if(NULL != pSampleBuffer && m_aacFrameInfo.error == 0 && m_aacFrameInfo.samples > 0) { nResult = m_aacFrameInfo.samples * m_aacFrameInfo.channels; if(nResult > nDestBufferSize) { nResult = 0; } } } } return nResult; }
static int aacd_faad_decode( AACDCommonInfo *cinfo, void *ext, unsigned char *buffer, unsigned long buffer_size, jshort *jsamples, jint outLen ) { NeAACDecFrameInfo frame; jshort *ljsamples = jsamples; NeAACDecDecode2( ext, &frame, buffer, buffer_size, (void**)&jsamples, outLen*2 ); if (ljsamples != jsamples) { AACD_WARN( "NeAACDecDecode CHANGE jsamples !!!"); } cinfo->frame_bytesconsumed = frame.bytesconsumed; cinfo->frame_samples = frame.samples; if (frame.error != 0) { AACD_ERROR( "NeAACDecDecode bytesleft=%d, error: %s", buffer_size, NeAACDecGetErrorMessage(frame.error)); } return frame.error; }
DecoderStatus AacDecoder::process(Packet*packet){ FXlong fs = packet->stream_position; FXbool eos = packet->flags&FLAG_EOS; long unsigned int samplerate; FXuchar channels; NeAACDecFrameInfo frame; if (packet->flags&AAC_FLAG_CONFIG) { handle = NeAACDecOpen(); if (NeAACDecInit2(handle,packet->data(),packet->size(),&samplerate,&channels)<0){ packet->unref(); return DecoderError; } return DecoderOk; } else { buffer.append(packet->data(),packet->size()); packet->unref(); if (handle==NULL) { handle = NeAACDecOpen(); long n = NeAACDecInit(handle,buffer.data(),buffer.size(),&samplerate,&channels); if (n<0) return DecoderError; else if (n>0) buffer.readBytes(n); af.set(AP_FORMAT_S16,samplerate,channels); engine->output->post(new ConfigureEvent(af,Codec::AAC)); } } if (buffer.size()<FAAD_MIN_STREAMSIZE*2) { return DecoderOk; } do { if (out==NULL){ out = engine->decoder->get_output_packet(); if (out==NULL) return DecoderInterrupted; out->af = af; out->stream_position = fs; out->stream_length = packet->stream_length; } void * outbuffer = out->ptr(); NeAACDecDecode2(handle,&frame,buffer.data(),buffer.size(),&outbuffer,out->availableFrames()*out->af.framesize()); if (frame.bytesconsumed>0) { buffer.readBytes(frame.bytesconsumed); } if (frame.error > 0) { GM_DEBUG_PRINT("[aac] error %d (%ld): %s\n",frame.error,frame.bytesconsumed,faacDecGetErrorMessage(frame.error)); } if (frame.samples) { fs+=(frame.samples/frame.channels); out->wroteFrames((frame.samples/frame.channels)); if (out->availableFrames()==0) { engine->output->post(out); out=NULL; } } } while(buffer.size()>(2*FAAD_MIN_STREAMSIZE) && frame.bytesconsumed); if (eos) { if (out) { engine->output->post(out); out=NULL; } engine->output->post(new ControlEvent(End,packet->stream)); } return DecoderOk; }
SINT SoundSourceM4A::readSampleFrames( SINT numberOfFrames, CSAMPLE* sampleBuffer) { DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); const SINT numberOfFramesTotal = math_min( numberOfFrames, getMaxFrameIndex() - m_curFrameIndex); const SINT numberOfSamplesTotal = frames2samples(numberOfFramesTotal); CSAMPLE* pSampleBuffer = sampleBuffer; SINT numberOfSamplesRemaining = numberOfSamplesTotal; while (0 < numberOfSamplesRemaining) { if (!m_sampleBuffer.isEmpty()) { // Consume previously decoded sample data const SampleBuffer::ReadableChunk readableChunk( m_sampleBuffer.readFromHead(numberOfSamplesRemaining)); if (pSampleBuffer) { SampleUtil::copy(pSampleBuffer, readableChunk.data(), readableChunk.size()); pSampleBuffer += readableChunk.size(); } m_curFrameIndex += samples2frames(readableChunk.size()); DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfSamplesRemaining >= readableChunk.size()); numberOfSamplesRemaining -= readableChunk.size(); if (0 == numberOfSamplesRemaining) { break; // exit loop } } // All previously decoded sample data has been consumed now DEBUG_ASSERT(m_sampleBuffer.isEmpty()); if (0 == m_inputBufferLength) { // Fill input buffer from file if (isValidSampleBlockId(m_curSampleBlockId)) { // Read data for next sample block into input buffer u_int8_t* pInputBuffer = &m_inputBuffer[0]; u_int32_t inputBufferLength = m_inputBuffer.size(); // in/out parameter if (!MP4ReadSample(m_hFile, m_trackId, m_curSampleBlockId, &pInputBuffer, &inputBufferLength, NULL, NULL, NULL, NULL)) { qWarning() << "Failed to read MP4 input data for sample block" << m_curSampleBlockId << "(" << "min =" << kSampleBlockIdMin << "," << "max =" << m_maxSampleBlockId << ")"; break; // abort } ++m_curSampleBlockId; m_inputBufferLength = inputBufferLength; m_inputBufferOffset = 0; } } DEBUG_ASSERT(0 <= m_inputBufferLength); if (0 == m_inputBufferLength) { break; // EOF } // NOTE(uklotzde): The sample buffer for NeAACDecDecode2 has to // be big enough for a whole block of decoded samples, which // contains up to kFramesPerSampleBlock frames. Otherwise // we need to use a temporary buffer. CSAMPLE* pDecodeBuffer; // in/out parameter SINT decodeBufferCapacity; const SINT decodeBufferCapacityMin = frames2samples(kFramesPerSampleBlock); if (pSampleBuffer && (decodeBufferCapacityMin <= numberOfSamplesRemaining)) { // Decode samples directly into sampleBuffer pDecodeBuffer = pSampleBuffer; decodeBufferCapacity = numberOfSamplesRemaining; } else { // Decode next sample block into temporary buffer const SINT writeToTailCount = math_max( numberOfSamplesRemaining, decodeBufferCapacityMin); const SampleBuffer::WritableChunk writableChunk( m_sampleBuffer.writeToTail(writeToTailCount)); pDecodeBuffer = writableChunk.data(); decodeBufferCapacity = writableChunk.size(); } DEBUG_ASSERT(decodeBufferCapacityMin <= decodeBufferCapacity); NeAACDecFrameInfo decFrameInfo; void* pDecodeResult = NeAACDecDecode2( m_hDecoder, &decFrameInfo, &m_inputBuffer[m_inputBufferOffset], m_inputBufferLength, reinterpret_cast<void**>(&pDecodeBuffer), decodeBufferCapacity * sizeof(*pDecodeBuffer)); // Verify the decoding result if (0 != decFrameInfo.error) { qWarning() << "AAC decoding error:" << decFrameInfo.error << NeAACDecGetErrorMessage(decFrameInfo.error) << getUrlString(); break; // abort } DEBUG_ASSERT(pDecodeResult == pDecodeBuffer); // verify the in/out parameter // Verify the decoded sample data for consistency if (getChannelCount() != decFrameInfo.channels) { qWarning() << "Corrupt or unsupported AAC file:" << "Unexpected number of channels" << decFrameInfo.channels << "<>" << getChannelCount(); break; // abort } if (getFrameRate() != SINT(decFrameInfo.samplerate)) { qWarning() << "Corrupt or unsupported AAC file:" << "Unexpected sample rate" << decFrameInfo.samplerate << "<>" << getFrameRate(); break; // abort } // Consume input data m_inputBufferLength -= decFrameInfo.bytesconsumed; m_inputBufferOffset += decFrameInfo.bytesconsumed; // Consume decoded output data const SINT numberOfSamplesDecoded = decFrameInfo.samples; DEBUG_ASSERT(numberOfSamplesDecoded <= decodeBufferCapacity); SINT numberOfSamplesRead; if (pDecodeBuffer == pSampleBuffer) { numberOfSamplesRead = math_min(numberOfSamplesDecoded, numberOfSamplesRemaining); pSampleBuffer += numberOfSamplesRead; } else { m_sampleBuffer.readFromTail(decodeBufferCapacity - numberOfSamplesDecoded); const SampleBuffer::ReadableChunk readableChunk( m_sampleBuffer.readFromHead(numberOfSamplesRemaining)); numberOfSamplesRead = readableChunk.size(); if (pSampleBuffer) { SampleUtil::copy(pSampleBuffer, readableChunk.data(), numberOfSamplesRead); pSampleBuffer += numberOfSamplesRead; } } // The decoder might decode more samples than actually needed // at the end of the file! When the end of the file has been // reached decoding can be restarted by seeking to a new // position. DEBUG_ASSERT(numberOfSamplesDecoded >= numberOfSamplesRead); m_curFrameIndex += samples2frames(numberOfSamplesRead); DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfSamplesRemaining >= numberOfSamplesRead); numberOfSamplesRemaining -= numberOfSamplesRead; } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfSamplesTotal >= numberOfSamplesRemaining); return samples2frames(numberOfSamplesTotal - numberOfSamplesRemaining); }