/** * Searches for ADTS 0xfff header. * Returns the offset of ADTS frame. */ int aacd_adts_sync(unsigned char *buffer, int len) { int pos = 0; len -= 3; AACD_TRACE( "probe() start len=%d", len ); while (pos < len) { if (*buffer != 0xff) { buffer++; pos++; } else if ((*(++buffer) & 0xf6) == 0xf0) { AACD_TRACE( "probe() found ADTS start at offset %d", pos ); return pos; } else pos++; } AACD_WARN( "probe() could not find ADTS start" ); return -1; }
/** * Creates a new ByteIOContext. */ static ByteIOContext* aacd_ff_create_byteioctx( AACDFFmpegInfo *ff ) { int buffer_size = ff->cinfo->bbsize; unsigned char *buffer = av_mallocz( buffer_size ); ByteIOContext *pb = av_alloc_put_byte( buffer, buffer_size, 0, ff, aacd_ff_io_read_packet, NULL, NULL); if (!pb) { av_free( buffer ); AACD_WARN( "create_byteioctx(): ByteIOContext could not be created" ); } return pb; }
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; }
/** * A wrapper method which reads packets. * It only reads them from the internal pre-fetched buffer in AACDCommonInfo. */ static int aacd_ff_io_read_packet( void *opaque, uint8_t *buf, int buf_size) { AACD_TRACE( "io_read_packet() start" ); AACDFFmpegInfo *ff = (AACDFFmpegInfo*) opaque; AACDCommonInfo *cinfo = ff->cinfo; if (cinfo->bytesleft < buf_size) { // Let's cheat now: AACDArrayInfo *ainfo = (AACDArrayInfo*) cinfo; if (!aacda_read_buffer( ainfo )) { AACD_INFO( "io_read_packet() EOF detected" ); } } int len = buf_size < cinfo->bytesleft ? buf_size : cinfo->bytesleft; if (!len) { AACD_WARN( "read_packet(): no bytes left, returning 0" ); return 0; } memcpy( buf, cinfo->buffer, len ); cinfo->buffer += len; cinfo->bytesleft -= len; ff->bytesconsumed += len; AACD_TRACE( "io_read_packet() stop" ); return len; }
static long aacd_opencore_start( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size) { AACD_TRACE( "start() buffer=%x size=%d", (*(unsigned long*)buffer), buffer_size ); AACDOpenCore *oc = (AACDOpenCore*) info->ext; tPVMP4AudioDecoderExternal *pExt = oc->pExt; pExt->remainderBits = 0; pExt->frameLength = 0; // prepare the first samples buffer: //pExt->pOutputBuffer = malloc(4096 * sizeof(int16_t)); //pExt->pOutputBuffer_plus = pExt->pOutputBuffer + 2048; pExt->pOutputBuffer = aacd_prepare_samples( info, 4096 ); pExt->pOutputBuffer_plus = pExt->pOutputBuffer + 2048; int32_t status; int frameDecoded = 0; int attempts = 16; /* pre-init search adts sync */ while (pExt->frameLength == 0 && attempts--) { pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; status = PVMP4AudioDecoderConfig(pExt, oc->pMem); AACD_DEBUG( "start() Status[0]: %d", status ); if (status != MP4AUDEC_SUCCESS) { status = PVMP4AudioDecodeFrame(pExt, oc->pMem); AACD_DEBUG( "start() Status[1]: %d", status ); buffer -= pExt->inputBufferUsedLength; buffer_size -= pExt->inputBufferUsedLength; if (MP4AUDEC_SUCCESS == status) { AACD_DEBUG( "start() frameLength: %d\n", pExt->frameLength); frameDecoded = 1; continue; } } if (buffer_size <= PVMP4AUDIODECODER_INBUFSIZE) break; } if (!frameDecoded) { AACD_INFO( "start() No stream info available - trying to decode a frame" ); if (buffer_size >= PVMP4AUDIODECODER_INBUFSIZE) status = PVMP4AudioDecodeFrame(pExt, oc->pMem); else AACD_WARN( "start() Input buffer too small" ); } //free( pExt->pOutputBuffer ); if (status != MP4AUDEC_SUCCESS) { AACD_ERROR( "start() init failed status=%d", status ); return -1; } AACD_DEBUG( "start() bytesconsumed=%d", pExt->inputBufferUsedLength ); int streamType = -1; if ((pExt->extendedAudioObjectType == MP4AUDIO_AAC_LC) || (pExt->extendedAudioObjectType == MP4AUDIO_LTP)) { streamType = AAC; } else if (pExt->extendedAudioObjectType == MP4AUDIO_SBR) { streamType = AACPLUS; } else if (pExt->extendedAudioObjectType == MP4AUDIO_PS) { streamType = ENH_AACPLUS; } AACD_DEBUG( "start() streamType=%d", streamType ); if ((AAC == streamType) && (2 == pExt->aacPlusUpsamplingFactor)) { AACD_INFO( "start() DisableAacPlus" ); PVMP4AudioDecoderDisableAacPlus(pExt, oc->pMem); } info->samplerate = pExt->samplingRate; info->channels = pExt->desiredChannels; oc->frameSamplesFactor = pExt->desiredChannels; if (2 == pExt->aacPlusUpsamplingFactor) oc->frameSamplesFactor *= 2; info->frame_bytesconsumed = pExt->inputBufferUsedLength; info->frame_samples = pExt->frameLength * oc->frameSamplesFactor; return pExt->inputBufferUsedLength; }
static int aacd_ffwma_decode( AACDCommonInfo *cinfo, void *ext, unsigned char *buffer, unsigned long buffer_size, jshort *jsamples, jint outLen ) { AACD_TRACE( "decode() start" ); AACDFFmpegInfo *ff = (AACDFFmpegInfo*) ext; AVFormatContext *ic = ff->avfctx; AVPacket *avpkt = ff->avpkt; AVPacket *pkt = ff->pkt; ff->bytesconsumed = 0; #ifdef AACD_LOGLEVEL_TRACE ic->debug = FF_FDEBUG_TS; #endif while (!pkt->size) { AACD_TRACE( "decode() calling av_read_frame..." ); int err = av_read_frame( ic, avpkt ); AACD_TRACE( "decode() av_read_frame returned: %d", err ); if (err < 0) { AACD_ERROR( "decode() cannot read av frame" ); return AACD_DECODE_EOF; } if (avpkt->stream_index == ff->audio_stream_index) { pkt->data = avpkt->data; pkt->size = avpkt->size; break; } // TODO: delete packet's buffer ? AACD_TRACE( "decode() : freeing packet's data" ); av_freep( &avpkt->data ); } AACD_TRACE( "decode() packet demuxed, will decode..." ); AVCodecContext *avctx = ic->streams[ff->audio_stream_index]->codec; AVCodec *codec = avctx->codec; AACD_DEBUG( "decode() frame_size=%d", avctx->frame_size ); // aac_decode_frame int outSize = outLen * 2; int consumed = (*codec->decode)( avctx, jsamples, &outSize, pkt ); if (consumed <= 0) { AACD_ERROR( "decode() cannot decode frame pkt->size=%d, outSize=%d, error: %d", pkt->size, outSize, consumed ); if ( cinfo->frame_samples < outLen * 3 / 2 ) { AACD_WARN( "decode() trying to obtain large output buffer" ); return AACD_DECODE_OUTPUT_NEEDED; } pkt->size = 0; return AACD_DECODE_OTHER; } pkt->data += consumed; pkt->size -= consumed; cinfo->frame_bytesconsumed = consumed; //cinfo->frame_samples = avctx->frame_size * avctx->channels; cinfo->frame_samples = (outSize >> 1); AACD_TRACE( "decode() stop - consumed %d, pkt->size=%d", consumed, pkt->size ); return AACD_DECODE_OK; }
/** * Decodes the stream - one round until the output buffer is (almost) filled. */ static void aacd_decode( AACDInfo *info, jshort *samples, jint outLen ) { AACD_DEBUG( "decode() start" ); info->round_frames = 0; info->round_bytesconsumed = 0; info->round_samples = 0; do { // check if input buffer is filled: if (info->bytesleft <= info->frame_max_bytesconsumed) { AACD_TRACE( "decode() reading input buffer" ); aacd_read_buffer( info ); if (info->bytesleft <= info->frame_max_bytesconsumed) { AACD_INFO( "decode() detected end-of-file" ); break; } } AACD_TRACE( "decode() frame - frames=%d, consumed=%d, samples=%d, bytesleft=%d, frame_maxconsumed=%d, frame_samples=%d, outLen=%d", info->round_frames, info->round_bytesconsumed, info->round_samples, info->bytesleft, info->frame_max_bytesconsumed, info->frame_samples, outLen); int attempts = 10; do { if (!info->decoder->decode( info, info->buffer, info->bytesleft, samples, outLen )) break; AACD_WARN( "decode() failed to decode a frame" ); AACD_DEBUG( "decode() failed to decode a frame - frames=%d, consumed=%d, samples=%d, bytesleft=%d, frame_maxconsumed=%d, frame_samples=%d, outLen=%d", info->round_frames, info->round_bytesconsumed, info->round_samples, info->bytesleft, info->frame_max_bytesconsumed, info->frame_samples, outLen); if (info->bytesleft <= info->frame_max_bytesconsumed) { aacd_read_buffer( info ); if (info->bytesleft <= info->frame_max_bytesconsumed) { AACD_INFO( "decode() detected end-of-file after partial frame error" ); attempts = 0; break; } } int pos = info->decoder->sync( info, info->buffer+1, info->bytesleft-1 ); if (pos >= 0) { info->buffer += pos+1; info->bytesleft -= pos+1; } else { int move = info->bytesleft < 2048 ? (info->bytesleft >> 1) : 1024; info->buffer += move; info->bytesleft -= move; } } while (--attempts > 0); if ( !attempts ) { AACD_WARN( "decode() failed after several attempts"); break; } info->round_frames++; info->round_bytesconsumed += info->frame_bytesconsumed; info->bytesleft -= info->frame_bytesconsumed; info->buffer += info->frame_bytesconsumed; if (info->frame_bytesconsumed > info->frame_max_bytesconsumed) { info->frame_max_bytesconsumed_exact = info->frame_bytesconsumed; info->frame_max_bytesconsumed = info->frame_bytesconsumed * 3 / 2; } samples += info->frame_samples; outLen -= info->frame_samples; info->round_samples += info->frame_samples; } while (outLen >= info->frame_samples ); AACD_DEBUG( "decode() round - frames=%d, consumed=%d, samples=%d, bytesleft=%d, frame_maxconsumed=%d, frame_samples=%d, outLen=%d", info->round_frames, info->round_bytesconsumed, info->round_samples, info->bytesleft, info->frame_max_bytesconsumed, info->frame_samples, outLen); }