Exemple #1
0
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);
}