static void* aacd_faad_init() { void *ret = NeAACDecOpen(); AACD_INFO( "init() FAAD2 capabilities: %d", NeAACDecGetCapabilities()); return ret; }
/** * Stops the service and frees resources. */ static void aacd_stop( AACDInfo *info ) { AACD_INFO( "stop() stopping native decoder" ); if (info == NULL) return; if (info->decoder) info->decoder->destroy( info ); if (info->buffer_block != NULL) { free( info->buffer_block ); info->buffer_block = NULL; info->bbsize = 0; } if (info->buffer_block2 != NULL) { free( info->buffer_block2 ); info->buffer_block = NULL; info->bbsize2 = 0; } if (info->samples != NULL) { free( info->samples ); info->samplesLen = 0; } JNIEnv *env = info->env; if (info->aacInfo) (*env)->DeleteGlobalRef( env, info->aacInfo ); if (info->reader) (*env)->DeleteGlobalRef( env, info->reader ); free( info ); }
/** * Starts the service - initializes resource. */ static AACDInfo* aacd_start( JNIEnv *env, AACDDecoder *decoder, jobject jreader, jobject aacInfo) { AACD_INFO( "start() starting native decoder - %s", decoder->name()); AACDInfo *info = (AACDInfo*) calloc( 1, sizeof( struct AACDInfo )); info->decoder = decoder; info->ext = info->decoder->init(); info->reader = (*env)->NewGlobalRef( env, jreader ); info->aacInfo = (*env)->NewGlobalRef( env, aacInfo ); return info; }
/** * 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 long aacd_opencoremp3_start( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size) { AACD_TRACE( "start() buffer=%x size=%d", (*(unsigned long*)buffer), buffer_size ); AACDOpenCoreMP3 *oc = (AACDOpenCoreMP3*) info->ext; tPVMP3DecoderExternal *pExt = oc->pExt; // prepare the first samples buffer: //pExt->pOutputBuffer = malloc(4096 * sizeof(int16_t)); pExt->pOutputBuffer = aacd_prepare_samples( info, 4096 ); pExt->outputFrameSize = 4096; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->crcEnabled = 0; pExt->equalizerType = flat; pvmp3_InitDecoder( oc->pExt, oc->pMem ); int32_t status; int frameDecoded = 0; int attempts = 16; int totalConsumed = 0; pExt->outputFrameSize = 0; /* pre-init search adts sync */ while (!frameDecoded && attempts--) { pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->outputFrameSize = 4096; status = pvmp3_framedecoder(pExt, oc->pMem); AACD_DEBUG( "start() Status[0]: %d - consumed %d bytes", status, pExt->inputBufferUsedLength ); totalConsumed += pExt->inputBufferUsedLength; if (status != NO_DECODING_ERROR) { AACD_ERROR( "start() frame decode error=%d", status ); if (!pExt->inputBufferUsedLength) { AACD_ERROR( "start() first frame cannot be decoded - trying to sync again" ); int move = buffer_size < 2048 ? (buffer_size >> 1) : 1024; buffer += move; buffer_size -= move; totalConsumed += move; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; ERROR_CODE err = pvmp3_frame_synch( oc->pExt, oc->pMem ); if (err == SYNCH_LOST_ERROR) { AACD_ERROR( "start() cannot re-sync the stream after next %d bytes, status=%d", move, err ); } else if (err != NO_DECODING_ERROR) { AACD_ERROR( "start() cannot sync the stream status=%d", err ); break; } else { totalConsumed += pExt->inputBufferUsedLength; AACD_INFO( "start() sync was successful - used bytes=%d", totalConsumed ); } } buffer -= pExt->inputBufferUsedLength; buffer_size -= pExt->inputBufferUsedLength; }
/** * 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); }