예제 #1
0
static void* aacd_faad_init()
{
    void *ret = NeAACDecOpen();
    AACD_INFO( "init() FAAD2 capabilities: %d", NeAACDecGetCapabilities());

    return ret;
}
예제 #2
0
파일: aac.c 프로젝트: amitkr/deadbeef
static int
mp4_track_get_info(mp4ff_t *mp4, int track, float *duration, int *samplerate, int *channels, int *totalsamples, int *mp4framesize) {
    int sr = -1;
    unsigned char*  buff = 0;
    unsigned int    buff_size = 0;
    mp4AudioSpecificConfig mp4ASC;
    mp4ff_get_decoder_config(mp4, track, &buff, &buff_size);
    if (buff) {
        int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
        sr = mp4ASC.samplingFrequency;
        if(rc < 0) {
            free (buff);
            trace ("aac: AudioSpecificConfig returned result=%d\n", rc);
            return -1;
        }
    }

    unsigned long srate;
    unsigned char ch;
    int samples;

    // init mp4 decoding
    NeAACDecHandle dec = NeAACDecOpen ();
    if (NeAACDecInit2(dec, buff, buff_size, &srate, &ch) < 0) {
        trace ("NeAACDecInit2 returned error\n");
        goto error;
    }
    *samplerate = srate;
    *channels = ch;
    samples = (int64_t)mp4ff_num_samples(mp4, track);
    
    NeAACDecClose (dec);
    dec = NULL;

    if (samples <= 0) {
        goto error;
    }

    int i_sample_count = samples;
    int i_sample;

    int64_t total_dur = 0;
    for( i_sample = 0; i_sample < i_sample_count; i_sample++ )
    {
        total_dur += mp4ff_get_sample_duration (mp4, track, i_sample);
    }
    if (totalsamples) {
        *totalsamples = total_dur * (*samplerate) / mp4ff_time_scale (mp4, track);
        *mp4framesize = (*totalsamples) / i_sample_count;
    }
    *duration = total_dur / (float)mp4ff_time_scale (mp4, track);

    return 0;
error:
    if (dec) {
        NeAACDecClose (dec);
    }
    free (buff);
    return -1;
}
예제 #3
0
bool TaudioCodecLibFAAD::init(const CMediaType &mt)
{
    dll = new Tdll(dllname, config);
    dll->loadFunction(NeAACDecOpen, "NeAACDecOpen");
    dll->loadFunction(NeAACDecClose, "NeAACDecClose");
    dll->loadFunction(NeAACDecInit2, "NeAACDecInit2");
    dll->loadFunction(NeAACDecAudioSpecificConfig, "NeAACDecAudioSpecificConfig");
    dll->loadFunction(NeAACDecDecode, "NeAACDecDecode");
    dll->loadFunction(NeAACDecGetErrorMessage, "NeAACDecGetErrorMessage");
    dll->loadFunction(NeAACDecGetCurrentConfiguration, "NeAACDecGetCurrentConfiguration");
    dll->loadFunction(NeAACDecSetConfiguration, "NeAACDecSetConfiguration");
    if (dll->ok) {
        m_decHandle = NeAACDecOpen();
        unsigned long SamplesPerSec = 0;
        unsigned char channels = 0;
        Textradata extradata(mt);
        if (NeAACDecInit2(m_decHandle, extradata.data, (unsigned long)extradata.size, &SamplesPerSec, &channels) < 0) {
            return false;
        }
        fmt.freq = SamplesPerSec;
        fmt.setChannels(channels);
        NeAACDecAudioSpecificConfig(extradata.data, (unsigned long)extradata.size, &info);
        NeAACDecConfigurationPtr c = NeAACDecGetCurrentConfiguration(m_decHandle);
        c->outputFormat = FAAD_FMT_FLOAT;
        fmt.sf = TsampleFormat::SF_FLOAT32;
        NeAACDecSetConfiguration(m_decHandle, c);
        inited = true;
        return true;
    } else {
        return false;
    }
}
예제 #4
0
파일: aac.cpp 프로젝트: Hellzed/xoreos
AACDecoder::AACDecoder(Common::SeekableReadStream *extraData, bool disposeExtraData) {
	// Open the library
	_handle = NeAACDecOpen();

	// Configure the library to our needs
	NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(_handle);
	conf->outputFormat = FAAD_FMT_16BIT; // We only support 16bit audio
	conf->downMatrix = 1;                // Convert from 5.1 to stereo if required
	NeAACDecSetConfiguration(_handle, conf);

	// Copy the extra data to a buffer
	extraData->seek(0);
	byte *extraDataBuf = new byte[extraData->size()];
	extraData->read(extraDataBuf, extraData->size());

	// Initialize with our extra data
	// NOTE: This code assumes the extra data is coming from an MPEG-4 file!
	int err = NeAACDecInit2(_handle, extraDataBuf, extraData->size(), &_rate, &_channels);
	delete[] extraDataBuf;

	if (err < 0)
		throw Common::Exception("Could not initialize AAC decoder: %s", NeAACDecGetErrorMessage(err));

	if (disposeExtraData)
		delete extraData;
}
예제 #5
0
int aac_init(struct sp* env){
	//initialize the aac specific structures
	struct aac_data* data = malloc(sizeof(struct aac_data)); //allocate private structures
	int buffer_size = FAAD_MIN_STREAMSIZE*8; //formerly used in the decode call
	//might not be necessary, it's the minimum amount of data needed to get the decoder to do something
	//hopefully faad acts like lame and internally buffers input until it can make a frame.
	//if not we'll need to internally buffer, by holding a buffer_size sized chunk of memory in aac_data
	//and then filling it
	int cap = NeAACDecGetCapabilities(); //we should do some bulletproofing here, but we won't now

	data->hAac = NeAACDecOpen();

	//Configure the decoder
	NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(data->hAac);
	conf->defObjectType = 2; //aac "MAIN"
	conf->defSampleRate = 44100;
	conf->outputFormat = 1;
	conf->downMatrix = 1;
	NeAACDecSetConfiguration(data->hAac, conf); //set the stuff
	// Initialise the library using one of the initialization functions
	unsigned long samplerate;
	unsigned char channels;
	int offset = NeAACDecInit(data->hAac, (unsigned char*)env->input, env->size, &samplerate, &channels);

	if (offset != 0) { //now how do i tell sp from here that audio data starts at index
		env->p.offset = offset; //communicate offset
		return SP_ABORT; //do something to notify of error
	}
	//shutup -Wunused-variable... i'll use them eventually
	(void)buffer_size;
	(void)cap;
	
	env->private_data = data;
	return SP_OK;
}
예제 #6
0
CAMLprim value ocaml_faad_open(value unit)
{
  CAMLparam0();
  CAMLlocal1(ret);
  NeAACDecHandle dh = NeAACDecOpen();
  NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(dh);

  conf->outputFormat = FAAD_FMT_FLOAT;
  NeAACDecSetConfiguration(dh, conf);

  ret  = caml_alloc_custom(&faad_dec_ops, sizeof(NeAACDecHandle), 0, 1);
  Dec_val(ret) = dh;

  CAMLreturn(ret);
}
예제 #7
0
//---------------------------------------------------------------------------
void File_Aac::libfaad()
{
    #if defined(MEDIAINFO_FAAD_YES) && defined(MEDIAINFO_MPEG4_YES)
        unsigned long samplerate;
        unsigned char channels;

        //Open the library
        if (hAac==NULL)
        {
            hAac = NeAACDecOpen();
            // Initialise the library using one of the initialization functions
            char err = NeAACDecInit2(hAac, (unsigned char *)DecSpecificInfoTag->Buffer, DecSpecificInfoTag->Buffer_Size, &samplerate, &channels);
            if (err != 0)
            {
                //
                // Handle error
                //
            }
        }

        //Decode the frame in buffer
        void* samplebuffer;
        NeAACDecFrameInfo hInfo;
        samplebuffer = NeAACDecDecode(hAac, &hInfo, (unsigned char *)Buffer, Buffer_Size);
        if ((hInfo.error == 0) && (hInfo.samples > 0))
        {
            //
            // do what you need to do with the decoded samples
            //
        }
        else if (hInfo.error != 0)
        {
            //
            // Some error occurred while decoding this frame
            //
        }
    #else
        //Filling
        Stream_Prepare(Stream_General);
        Fill(Stream_General, 0, General_Format, "AAC");
        Stream_Prepare(Stream_Audio);
        Fill(Stream_Audio, 0, Audio_Format, "AAC");
        Fill(Stream_Audio, 0, Audio_Codec, "AAC");

        Accept("AAC");
        Finish("AAC");
    #endif
}
예제 #8
0
파일: faad.c 프로젝트: videolan/vlc
/*****************************************************************************
 * DecodeBlock:
 *****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;

    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
    *pp_block = NULL;

    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
    {
        Flush( p_dec );
        if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) )
        {
            block_Release( p_block );
            return NULL;
        }
    }

    /* Remove ADTS header if we have decoder specific config */
    if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 )
    {
        if( p_block->p_buffer[0] == 0xff &&
                ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */
        {   /* ADTS header present */
            size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */
            i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 );
            /* FIXME: multiple blocks per frame */
            if( p_block->i_buffer > i_header_size )
            {
                p_block->p_buffer += i_header_size;
                p_block->i_buffer -= i_header_size;
            }
        }
    }

    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
        size_t  i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
        uint8_t *p_buffer     = realloc( p_sys->p_buffer, i_buffer_size );
        if( p_buffer )
        {
            p_sys->i_buffer_size = i_buffer_size;
            p_sys->p_buffer      = p_buffer;
        }
        else
        {
            p_block->i_buffer = 0;
        }
    }

    if( p_block->i_buffer > 0 )
    {
        memcpy( &p_sys->p_buffer[p_sys->i_buffer],
                p_block->p_buffer, p_block->i_buffer );
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 )
    {
        /* We have a decoder config so init the handle */
        unsigned long i_rate;
        unsigned char i_channels;

        if( NeAACDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                           p_dec->fmt_in.i_extra,
                           &i_rate, &i_channels ) >= 0 )
        {
            p_dec->fmt_out.audio.i_rate = i_rate;
            p_dec->fmt_out.audio.i_channels = i_channels;
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                  = pi_channels_guessed[i_channels];

            date_Init( &p_sys->date, i_rate, 1 );
        }
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
    {
        unsigned long i_rate;
        unsigned char i_channels;

        /* Init faad with the first frame */
        if( NeAACDecInit( p_sys->hfaad,
                          p_sys->p_buffer, p_sys->i_buffer,
                          &i_rate, &i_channels ) < 0 )
        {
            block_Release( p_block );
            return NULL;
        }

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
              = pi_channels_guessed[i_channels];
        date_Init( &p_sys->date, i_rate, 1 );
    }

    if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->date ) )
    {
        date_Set( &p_sys->date, p_block->i_pts );
    }
    else if( !date_Get( &p_sys->date ) )
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
        p_sys->i_buffer = 0;
        return NULL;
    }

    /* Decode all data */
    if( p_sys->i_buffer > 1)
    {
        void *samples;
        NeAACDecFrameInfo frame;
        block_t *p_out;

        samples = NeAACDecDecode( p_sys->hfaad, &frame,
                                  p_sys->p_buffer, p_sys->i_buffer );

        if( frame.error > 0 )
        {
            msg_Warn( p_dec, "%s", NeAACDecGetErrorMessage( frame.error ) );

            if( frame.error == 21 || frame.error == 12 )
            {
                /*
                 * Once an "Unexpected channel configuration change"
                 * or a "Invalid number of channels" error
                 * occurs, it will occurs afterwards, and we got no sound.
                 * Reinitialization of the decoder is required.
                 */
                unsigned long i_rate;
                unsigned char i_channels;
                NeAACDecHandle *hfaad;
                NeAACDecConfiguration *cfg,*oldcfg;

                oldcfg = NeAACDecGetCurrentConfiguration( p_sys->hfaad );
                hfaad = NeAACDecOpen();
                cfg = NeAACDecGetCurrentConfiguration( hfaad );
                if( oldcfg->defSampleRate )
                    cfg->defSampleRate = oldcfg->defSampleRate;
                cfg->defObjectType = oldcfg->defObjectType;
                cfg->outputFormat = oldcfg->outputFormat;
                NeAACDecSetConfiguration( hfaad, cfg );

                if( NeAACDecInit( hfaad, p_sys->p_buffer, p_sys->i_buffer,
                                  &i_rate,&i_channels ) < 0 )
                {
                    /* reinitialization failed */
                    NeAACDecClose( hfaad );
                    NeAACDecSetConfiguration( p_sys->hfaad, oldcfg );
                }
                else
                {
                    NeAACDecClose( p_sys->hfaad );
                    p_sys->hfaad = hfaad;
                    p_dec->fmt_out.audio.i_rate = i_rate;
                    p_dec->fmt_out.audio.i_channels = i_channels;
                    p_dec->fmt_out.audio.i_physical_channels
                        = p_dec->fmt_out.audio.i_original_channels
                          = pi_channels_guessed[i_channels];
                    date_Init( &p_sys->date, i_rate, 1 );
                }
            }

            /* Flush the buffer */
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
        {
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        if( frame.samples <= 0 )
        {
            msg_Warn( p_dec, "decoded zero sample" );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 1 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            else
            {
                /* Drop byte of padding */
                p_sys->i_buffer = 0;
            }
            block_Release( p_block );
            return NULL;
        }

        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
        {
            date_Init( &p_sys->date, frame.samplerate, 1 );
            date_Set( &p_sys->date, p_block->i_pts );
        }
        p_block->i_pts = VLC_TS_INVALID;  /* PTS is valid only once */

        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;

        /* Adjust stream info when dealing with SBR/PS */
        bool b_sbr = (frame.sbr == 1) || (frame.sbr == 2);
        if( p_sys->b_sbr != b_sbr || p_sys->b_ps != frame.ps )
        {
            const char *psz_ext = (b_sbr && frame.ps) ? "SBR+PS" :
                                  b_sbr ? "SBR" : "PS";

            msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)",
                     psz_ext, frame.channels, frame.samplerate );

            if( !p_dec->p_description )
                p_dec->p_description = vlc_meta_New();
            if( p_dec->p_description )
                vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext );

            p_sys->b_sbr = b_sbr;
            p_sys->b_ps = frame.ps;
        }

        /* Convert frame.channel_position to our own channel values */
        p_dec->fmt_out.audio.i_physical_channels = 0;
        const uint32_t nbChannels = frame.channels;
        unsigned j;
        for( unsigned i = 0; i < nbChannels; i++ )
        {
            /* Find the channel code */
            for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ )
            {
                if( frame.channel_position[i] == pi_channels_in[j] )
                    break;
            }
            if( j >= MAX_CHANNEL_POSITIONS )
            {
                msg_Warn( p_dec, "unknown channel ordering" );
                /* Invent something */
                j = i;
            }
            /* */
            p_sys->pi_channel_positions[i] = pi_channels_out[j];
            if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] )
                frame.channels--; /* We loose a duplicated channel */
            else
                p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j];
        }
        if ( nbChannels != frame.channels )
        {
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                  = pi_channels_guessed[nbChannels];
        }
        else
        {
            p_dec->fmt_out.audio.i_original_channels =
                p_dec->fmt_out.audio.i_physical_channels;
        }
        p_dec->fmt_out.audio.i_channels = nbChannels;
        if( decoder_UpdateAudioFormat( p_dec ) )
            p_out = NULL;
        else
            p_out = decoder_NewAudioBuffer( p_dec, frame.samples / nbChannels );
        if( p_out == NULL )
        {
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        p_out->i_pts = date_Get( &p_sys->date );
        p_out->i_length = date_Increment( &p_sys->date,
                                          frame.samples / nbChannels )
                          - p_out->i_pts;

        DoReordering( (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / nbChannels, nbChannels,
                      p_sys->pi_channel_positions );

        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
        {
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
        }

        block_Release( p_block );
        return p_out;
    }
    else
    {
        /* Drop byte of padding */
        p_sys->i_buffer = 0;
    }

    block_Release( p_block );
    return NULL;
}
예제 #9
0
파일: faad.c 프로젝트: videolan/vlc
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;
    NeAACDecConfiguration *cfg;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_MP4A )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ) ) == NULL )
        return VLC_ENOMEM;

    /* Open a faad context */
    if( ( p_sys->hfaad = NeAACDecOpen() ) == NULL )
    {
        msg_Err( p_dec, "cannot initialize faad" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* Misc init */
    date_Set( &p_sys->date, 0 );
    p_dec->fmt_out.i_cat = AUDIO_ES;

    p_dec->fmt_out.i_codec = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;

    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels = 0;

    if( p_dec->fmt_in.i_extra > 0 )
    {
        /* We have a decoder config so init the handle */
        unsigned long i_rate;
        unsigned char i_channels;

        if( NeAACDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                           p_dec->fmt_in.i_extra,
                           &i_rate, &i_channels ) < 0 )
        {
            msg_Err( p_dec, "Failed to initialize faad using extra data" );
            NeAACDecClose( p_sys->hfaad );
            free( p_sys );
            return VLC_EGENERIC;
        }

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
              = pi_channels_guessed[i_channels];
        date_Init( &p_sys->date, i_rate, 1 );
    }
    else
    {
        /* Will be initalised from first frame */
        p_dec->fmt_out.audio.i_rate = 0;
        p_dec->fmt_out.audio.i_channels = 0;
    }

    /* Set the faad config */
    cfg = NeAACDecGetCurrentConfiguration( p_sys->hfaad );
    if( p_dec->fmt_in.audio.i_rate )
        cfg->defSampleRate = p_dec->fmt_in.audio.i_rate;
    cfg->outputFormat = HAVE_FPU ? FAAD_FMT_FLOAT : FAAD_FMT_16BIT;
    NeAACDecSetConfiguration( p_sys->hfaad, cfg );

    /* buffer */
    p_sys->i_buffer = p_sys->i_buffer_size = 0;
    p_sys->p_buffer = NULL;

    p_sys->b_sbr = p_sys->b_ps = false;

    p_dec->pf_decode_audio = DecodeBlock;
    p_dec->pf_flush        = Flush;
    return VLC_SUCCESS;
}
예제 #10
0
파일: decode.c 프로젝트: khalidaw/vlc-speed
int decodeMP4file(char *sndfile, aac_dec_opt *opt)
{
    int track;
    unsigned long samplerate;
    unsigned char channels;
    void *sample_buffer;

    mp4ff_t *infile;
    FILE *mp4File;
    int sampleId, numSamples;

    audio_file *aufile;

    NeAACDecHandle hDecoder;
    NeAACDecFrameInfo frameInfo;

    unsigned char *buffer;
    int buffer_size;

    int first_time = 1;

    /* initialise the callback structure */
    mp4ff_callback_t *mp4cb = malloc(sizeof(mp4ff_callback_t));

    mp4File = fopen(opt->filename, "rb");
    mp4cb->read = read_callback;
    mp4cb->seek = seek_callback;
    mp4cb->user_data = mp4File;

    infile = mp4ff_open_read(mp4cb);
    if (!infile)
    {
        /* unable to open file */
        error_handler("Error opening file: %s\n", opt->filename);
        return 1;
    }

    if ((track = GetAACTrack(infile)) < 0)
    {
        error_handler("Unable to find correct AAC sound track in the MP4 file.\n");
        mp4ff_close(infile);
        free(mp4cb);
        fclose(mp4File);
        return 1;
    }

    buffer = NULL;
    buffer_size = 0;
    mp4ff_get_decoder_config(infile, track, &buffer, &buffer_size);

    hDecoder = NeAACDecOpen();

    if(NeAACDecInit2(hDecoder, buffer, buffer_size, &samplerate, &channels) < 0)
    {
        /* If some error initializing occured, skip the file */
        error_handler("Error initializing decoder library.\n");
        NeAACDecClose(hDecoder);
        mp4ff_close(infile);
        free(mp4cb);
        fclose(mp4File);
        return 1;
    }
    if (buffer)
        free(buffer);

    numSamples = mp4ff_num_samples(infile, track);

    for (sampleId = 0; sampleId < numSamples; sampleId++)
    {
        int rc;

        /* get access unit from MP4 file */
        buffer = NULL;
        buffer_size = 0;

        rc = mp4ff_read_sample(infile, track, sampleId, &buffer, &buffer_size);
        if (rc == 0)
        {
            error_handler("Reading from MP4 file failed.\n");
            NeAACDecClose(hDecoder);
            mp4ff_close(infile);
            free(mp4cb);
            fclose(mp4File);
            return 1;
        }

        sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, buffer, buffer_size);

        if (buffer)
            free(buffer);

        opt->progress_update((long)numSamples, sampleId);

        /* open the sound file now that the number of channels are known */
        if (first_time && !frameInfo.error)
        {
            if(opt->decode_mode == 0)
            {
                if (Set_WIN_Params (INVALID_FILEDESC, samplerate, SAMPLE_SIZE,
                                frameInfo.channels) < 0)
                {
                    error_handler("\nCan't access %s\n", "WAVE OUT");
                    NeAACDecClose(hDecoder);
                    mp4ff_close(infile);
                    free(mp4cb);
                    fclose(mp4File);
                    return (0);
                }
            }
            else
            {
                aufile = open_audio_file(sndfile, samplerate, frameInfo.channels,
                     opt->output_format, opt->file_type, aacChannelConfig2wavexChannelMask(&frameInfo));

                if (aufile == NULL)
                {
                    NeAACDecClose(hDecoder);
                    mp4ff_close(infile);
                    free(mp4cb);
                    fclose(mp4File);
                    return 0;
                }
            }
            first_time = 0;
        }

        if ((frameInfo.error == 0) && (frameInfo.samples > 0))
        {
            if(opt->decode_mode == 0)
                WIN_Play_Samples((short*)sample_buffer, frameInfo.channels*frameInfo.samples);
            else
                write_audio_file(aufile, sample_buffer, frameInfo.samples, 0);
        }

        if (frameInfo.error > 0)
        {
            error_handler("Error: %s\n",
            NeAACDecGetErrorMessage(frameInfo.error));
            break;
        }
        if(stop_decoding)
            break;
    }


    NeAACDecClose(hDecoder);


    mp4ff_close(infile);
    free(mp4cb);
    fclose(mp4File);

    if(opt->decode_mode == 0)
        WIN_Audio_close();
    else
    {
        if (!first_time)
            close_audio_file(aufile);
    }

    return frameInfo.error;
}
예제 #11
0
파일: faad.c 프로젝트: kfihihc/xmms2-devel
static gboolean
xmms_faad_init (xmms_xform_t *xform)
{
	xmms_faad_data_t *data;
	xmms_error_t error;

	NeAACDecConfigurationPtr config;
	gint bytes_read;
	gulong samplerate;
	guchar channels;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_faad_data_t, 1);
	data->outbuf = g_string_new (NULL);
	data->buffer_size = FAAD_BUFFER_SIZE;

	xmms_xform_private_data_set (xform, data);

	data->decoder = NeAACDecOpen ();
	config = NeAACDecGetCurrentConfiguration (data->decoder);
	config->defObjectType = LC;
	config->defSampleRate = 44100;
	config->outputFormat = FAAD_FMT_16BIT;
	config->downMatrix = 0;
	config->dontUpSampleImplicitSBR = 0;
	NeAACDecSetConfiguration (data->decoder, config);

	switch (config->outputFormat) {
	case FAAD_FMT_16BIT:
		data->sampleformat = XMMS_SAMPLE_FORMAT_S16;
		break;
	case FAAD_FMT_24BIT:
		/* we don't have 24-bit format to use in xmms2 */
		data->sampleformat = XMMS_SAMPLE_FORMAT_S32;
		break;
	case FAAD_FMT_32BIT:
		data->sampleformat = XMMS_SAMPLE_FORMAT_S32;
		break;
	case FAAD_FMT_FLOAT:
		data->sampleformat = XMMS_SAMPLE_FORMAT_FLOAT;
		break;
	case FAAD_FMT_DOUBLE:
		data->sampleformat = XMMS_SAMPLE_FORMAT_DOUBLE;
		break;
	}

	while (data->buffer_length < 8) {
		xmms_error_reset (&error);
		bytes_read = xmms_xform_read (xform,
		                              (gchar *) data->buffer + data->buffer_length,
		                              data->buffer_size - data->buffer_length,
		                              &error);
		data->buffer_length += bytes_read;

		if (bytes_read < 0) {
			xmms_log_error ("Error while trying to read data on init");
			goto err;
		} else if (bytes_read == 0) {
			XMMS_DBG ("Not enough bytes to check the AAC header");
			goto err;
		}
	}

	/* which type of file are we dealing with? */
	data->filetype = FAAD_TYPE_UNKNOWN;
	if (xmms_xform_auxdata_has_val (xform, "decoder_config")) {
		data->filetype = FAAD_TYPE_MP4;
	} else if (!strncmp ((char *) data->buffer, "ADIF", 4)) {
		data->filetype = FAAD_TYPE_ADIF;
	} else {
		int i;

		/* ADTS mpeg file can be a stream and start in the middle of a
		 * frame so we need to have extra loop check here */
		for (i=0; i<data->buffer_length-1; i++) {
			if (data->buffer[i] == 0xff && (data->buffer[i+1]&0xf6) == 0xf0) {
				data->filetype = FAAD_TYPE_ADTS;
				g_memmove (data->buffer, data->buffer+i, data->buffer_length-i);
				data->buffer_length -= i;
				break;
			}
		}
	}

	if (data->filetype == FAAD_TYPE_ADTS || data->filetype == FAAD_TYPE_ADIF) {
		bytes_read = NeAACDecInit (data->decoder, data->buffer,
		                          data->buffer_length, &samplerate,
		                          &channels);
	} else if (data->filetype == FAAD_TYPE_MP4) {
		const guchar *tmpbuf;
		gsize tmpbuflen;
		guchar *copy;

		if (!xmms_xform_auxdata_get_bin (xform, "decoder_config", &tmpbuf,
		                                 &tmpbuflen)) {
			XMMS_DBG ("AAC decoder config data found but it's wrong type! (something broken?)");
			goto err;
		}

		copy = g_memdup (tmpbuf, tmpbuflen);
		bytes_read = NeAACDecInit2 (data->decoder, copy, tmpbuflen,
		                           &samplerate, &channels);
		g_free (copy);
	}

	if (bytes_read < 0) {
		XMMS_DBG ("Error initializing decoder library.");
		goto err;
	}

	/* Get mediainfo and skip the possible header */
	xmms_faad_get_mediainfo (xform);
	g_memmove (data->buffer, data->buffer + bytes_read,
	           data->buffer_length - bytes_read);
	data->buffer_length -= bytes_read;

	data->samplerate = samplerate;
	data->channels = channels;

	/* Because for HE AAC files some versions of libfaad return the wrong
	 * samplerate in init, we have to do one read and let it decide the
	 * real parameters. After changing sample parameters and format is
	 * supported, this hack should be removed and handled in read instead. */
	{
		gchar tmpbuf[1024];

		xmms_error_reset (&error);
		bytes_read = xmms_faad_read (xform, tmpbuf, 1024, &error);
		if (bytes_read <= 0) {
			XMMS_DBG ("First read from faad decoder failed!");
			return FALSE;
		}
		g_string_prepend_len (data->outbuf, tmpbuf, bytes_read);
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             data->sampleformat,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->samplerate,
	                             XMMS_STREAM_TYPE_END);

	XMMS_DBG ("AAC decoder inited successfully!");

	return TRUE;

err:
	g_string_free (data->outbuf, TRUE);
	g_free (data);

	return FALSE;
}
예제 #12
0
/*	player thread; for every song a new thread is started
 *	@param audioPlayer structure
 *	@return PLAYER_RET_*
 */
void *BarPlayerThread (void *data) {
	struct audioPlayer *player = data;
	char extraHeaders[32];
	void *ret = PLAYER_RET_OK;
	#ifdef ENABLE_FAAD
	NeAACDecConfigurationPtr conf;
	#endif
	WaitressReturn_t wRet = WAITRESS_RET_ERR;

	/* init handles */
	player->waith.data = (void *) player;
	/* extraHeaders will be initialized later */
	player->waith.extraHeaders = extraHeaders;
	player->buffer = malloc (BAR_PLAYER_BUFSIZE);

	switch (player->audioFormat) {
		#ifdef ENABLE_FAAD
		case PIANO_AF_AACPLUS:
			player->aacHandle = NeAACDecOpen();
			/* set aac conf */
			conf = NeAACDecGetCurrentConfiguration(player->aacHandle);
			conf->outputFormat = FAAD_FMT_16BIT;
		    conf->downMatrix = 1;
			NeAACDecSetConfiguration(player->aacHandle, conf);

			player->waith.callback = BarPlayerAACCb;
			break;
		#endif /* ENABLE_FAAD */

		#ifdef ENABLE_MAD
		case PIANO_AF_MP3:
			mad_stream_init (&player->mp3Stream);
			mad_frame_init (&player->mp3Frame);
			mad_synth_init (&player->mp3Synth);

			player->waith.callback = BarPlayerMp3Cb;
			break;
		#endif /* ENABLE_MAD */

		default:
			/* FIXME: leaks memory */
			BarUiMsg (player->settings, MSG_ERR, "Unsupported audio format!\n");
			return PLAYER_RET_OK;
			break;
	}
	
	player->mode = PLAYER_INITIALIZED;

	/* This loop should work around song abortions by requesting the
	 * missing part of the song */
	do {
		snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n",
				player->bytesReceived);
		wRet = WaitressFetchCall (&player->waith);
	} while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT
			|| wRet == WAITRESS_RET_READ_ERR);

	/* If the song was played all the way through tag it. */
	if (wRet == WAITRESS_RET_OK) {
		BarFlyTag(&player->fly, player->settings);
	}

	switch (player->audioFormat) {
		#ifdef ENABLE_FAAD
		case PIANO_AF_AACPLUS:
			NeAACDecClose(player->aacHandle);
			free (player->sampleSize);
			break;
		#endif /* ENABLE_FAAD */

		#ifdef ENABLE_MAD
		case PIANO_AF_MP3:
			mad_synth_finish (&player->mp3Synth);
			mad_frame_finish (&player->mp3Frame);
			mad_stream_finish (&player->mp3Stream);
			break;
		#endif /* ENABLE_MAD */

		default:
			/* this should never happen: thread is aborted above */
			break;
	}

	if (player->aoError) {
		ret = (void *) PLAYER_RET_ERR;
	}

	ao_close(player->audioOutDevice);
	WaitressFree (&player->waith);
	free (player->buffer);

	player->mode = PLAYER_FINISHED_PLAYBACK;

	return ret;
}
예제 #13
0
파일: aac.c 프로젝트: vadmium/deadbeef
// returns -1 for error, 0 for mp4, 1 for aac
int
aac_probe (DB_FILE *fp, const char *fname, MP4FILE_CB *cb, float *duration, int *samplerate, int *channels, int *totalsamples, int *mp4track, MP4FILE *pmp4) {
    // try mp4
    trace ("aac_probe: pos=%lld, junk=%d\n", deadbeef->ftell (fp), ((aac_info_t*)cb->user_data)->junk);

    if (mp4track) {
        *mp4track = -1;
    }
    if (*pmp4) {
        *pmp4 = NULL;
    }
    *duration = -1;
#ifdef USE_MP4FF
    trace ("mp4ff_open_read\n");
    mp4ff_t *mp4 = mp4ff_open_read (cb);
#else
    MP4FileHandle mp4 = MP4ReadProvider (fname, 0, cb);
#endif
    if (!mp4) {
        trace ("not an mp4 file\n");
        return -1;
    }
    if (pmp4) {
        *pmp4 = mp4;
    }
#ifdef USE_MP4FF
    int ntracks = mp4ff_total_tracks (mp4);
    if (ntracks > 0) {
        trace ("m4a container detected, ntracks=%d\n", ntracks);
        int i = -1;
        trace ("looking for mp4 data...\n");
        int sr = -1;
        unsigned char*  buff = 0;
        unsigned int    buff_size = 0;
        for (i = 0; i < ntracks; i++) {
            mp4AudioSpecificConfig mp4ASC;
            mp4ff_get_decoder_config(mp4, i, &buff, &buff_size);
            if (buff) {
                int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
                sr = mp4ASC.samplingFrequency;
                if(rc < 0) {
                    free (buff);
                    buff = 0;
                    continue;
                }
                break;
            }
        }
        if (i != ntracks && buff) 
        {
            trace ("found audio track (%d)\n", i);
            // init mp4 decoding
            NeAACDecHandle dec = NeAACDecOpen ();
            unsigned long srate;
            unsigned char ch;
            if (NeAACDecInit2(dec, buff, buff_size, &srate, &ch) < 0) {
                trace ("NeAACDecInit2 returned error\n");
                goto error;
            }
            *samplerate = srate;
            *channels = ch;
            int samples = mp4ff_num_samples(mp4, i);
            samples = (int64_t)samples * srate / mp4ff_time_scale (mp4, i);
            int tsamples = samples;
            NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (dec);
            conf->dontUpSampleImplicitSBR = 1;
            NeAACDecSetConfiguration (dec, conf);
            mp4AudioSpecificConfig mp4ASC;
            int mp4framesize;
            if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0)
            {
                mp4framesize = 1024;
                if (mp4ASC.frameLengthFlag == 1) {
                    mp4framesize = 960;
                }
                // commented this out, since it fixes double-duration bug on
                // some mp4 files
                //if (mp4ASC.sbr_present_flag == 1) {
                //    mp4framesize *= 2;
                //}
            }
            else {
                trace ("NeAACDecAudioSpecificConfig failed, can't get mp4framesize\n");
                goto error;
            }
            tsamples *= mp4framesize;

            trace ("mp4 nsamples=%d, samplerate=%d, timescale=%d, duration=%lld\n", samples, *samplerate, mp4ff_time_scale(mp4, i), mp4ff_get_track_duration(mp4, i));
            *duration = (float)tsamples / (*samplerate);
            trace ("mp4 duration: %f (tsamples %d/samplerate %d)\n", *duration, tsamples, *samplerate);
            
            NeAACDecClose (dec);

            if (totalsamples) {
                *totalsamples = tsamples;
            }
            if (mp4track) {
                *mp4track = i;
            }
            if (!*pmp4) {
                mp4ff_close (mp4);
            }
            return 0;
error:
            NeAACDecClose (dec);
            free (buff);
            if (!*pmp4) {
                mp4ff_close (mp4);
            }
            return -1;
        }
        else {
            trace ("audio track not found\n");
            mp4ff_close (mp4);
            mp4 = NULL;
        }
        if (buff) {
            free (buff);
            buff = NULL;
        }

    }
#else
    MP4FileHandle mp4File = mp4;
    MP4TrackId trackId = MP4FindTrackId(mp4File, 0, "audio", 0);
    trace ("trackid: %d\n", trackId);
    uint32_t timeScale = MP4GetTrackTimeScale(mp4File, trackId);
    MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId);
    MP4SampleId numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId);
    u_int8_t* pConfig;
    uint32_t configSize = 0;
    bool res = MP4GetTrackESConfiguration(mp4File, trackId, &pConfig, &configSize);
    if (res && pConfig) {
        mp4AudioSpecificConfig mp4ASC;
        int rc = AudioSpecificConfig(pConfig, configSize, &mp4ASC);
        free (pConfig);
        if (rc >= 0) {
            *samplerate = mp4ASC.samplingFrequency;
            *channels = MP4GetTrackAudioChannels (mp4File, trackId);
//            int64_t duration = MP4ConvertFromTrackDuration (mp4File, trackId, trackDuration, timeScale);
            int samples = MP4GetTrackNumberOfSamples (mp4File, trackId) * 1024 * (*channels);
            trace ("mp4 nsamples=%d, timescale=%d, samplerate=%d\n", samples, timeScale, *samplerate);
            *duration = (float)samples / (*samplerate);

            if (totalsamples) {
                *totalsamples = samples;
            }
            if (mp4track) {
                *mp4track = trackId;
            }
            if (!*pmp4) {
                MP4Close (mp4);
            }
            return 0;
        }
    }
#endif
    if (*pmp4) {
        *pmp4 = NULL;
    }

    if (mp4) {
#if USE_MP4FF
        mp4ff_close (mp4);
#else
        MP4Close (mp4);
#endif
        mp4 = NULL;
    }
    trace ("mp4 track not found, looking for aac stream...\n");

    // not an mp4, try raw aac
#if USE_MP4FF
    deadbeef->rewind (fp);
#endif
    if (parse_aac_stream (fp, samplerate, channels, duration, totalsamples) == -1) {
        trace ("aac stream not found\n");
        return -1;
    }
    trace ("found aac stream\n");
    return 1;
}
예제 #14
0
bool DecoderAAC::initialize()
{
    m_bitrate = 0;
    m_totalTime = 0;

    if (!input())
    {
        qWarning("DecoderAAC: cannot initialize.  No input.");
        return false;
    }
    if (!m_input_buf)
        m_input_buf = new char[AAC_BUFFER_SIZE];
    m_input_at = 0;

    if (!input()->isOpen())
    {
        if (!input()->open(QIODevice::ReadOnly))
        {
            qWarning("DecoderAAC: %s", qPrintable(input()->errorString ()));
            return false;
        }
    }
    AACFile aac_file(input());
    if (!aac_file.isValid())
    {
        qWarning("DecoderAAC: unsupported AAC file");
        return false;
    }

    //skip id3 tag and partial frame
    if(aac_file.offset() > 0)
    {
        qDebug("DecoderAAC: header offset = %d bytes", aac_file.offset());

        char data[aac_file.offset()];
        input()->read(data, aac_file.offset());
    }

    m_totalTime = aac_file.length() * 1000;
    m_bitrate = aac_file.bitrate();

    if (!m_data)
        m_data = new aac_data;

    data()->handle = NeAACDecOpen();

    NeAACDecConfigurationPtr conf;
    conf = NeAACDecGetCurrentConfiguration(data()->handle);
    conf->downMatrix = 1;
    conf->defSampleRate = 44100;
    conf->dontUpSampleImplicitSBR = 0;
    conf->defObjectType = LC;
    conf->outputFormat = FAAD_FMT_16BIT;
    NeAACDecSetConfiguration(data()->handle, conf);

    m_input_at = input()->read((char *)m_input_buf, AAC_BUFFER_SIZE);

#ifdef FAAD_MODIFIED
    uint32_t freq = 0;
    uint8_t chan = 0;
#else
    unsigned long freq = 0;
    unsigned char chan = 0;
#endif
    int res = NeAACDecInit (data()->handle, (unsigned char*) m_input_buf, m_input_at, &freq, &chan);

    if (res < 0)
    {
        qWarning("DecoderAAC: NeAACDecInit() failed");
        return false;
    }
    if (!freq || !chan)
    {
        qWarning("DecoderAAC: invalid sound parameters");
        return false;
    }

    memmove(m_input_buf, m_input_buf + res, m_input_at - res);
    m_input_at -= res;
    configure(freq, chan, Qmmp::PCM_S16LE);
    qDebug("DecoderAAC: initialize succes");
    return true;
}
예제 #15
0
bool SoundSourceM4A::openDecoder() {
    DEBUG_ASSERT(m_hDecoder == nullptr); // not already opened

    m_hDecoder = NeAACDecOpen();
    if (m_hDecoder == nullptr) {
        qWarning() << "Failed to open the AAC decoder!";
        return false;
    }
    NeAACDecConfigurationPtr pDecoderConfig = NeAACDecGetCurrentConfiguration(
            m_hDecoder);
    pDecoderConfig->outputFormat = FAAD_FMT_FLOAT;
    if ((kChannelCountMono == m_audioSrcCfg.getChannelCount()) ||
            (kChannelCountStereo == m_audioSrcCfg.getChannelCount())) {
        pDecoderConfig->downMatrix = 1;
    } else {
        pDecoderConfig->downMatrix = 0;
    }

    pDecoderConfig->defObjectType = LC;
    if (!NeAACDecSetConfiguration(m_hDecoder, pDecoderConfig)) {
        qWarning() << "Failed to configure AAC decoder!";
        return false;
    }

    u_int8_t* configBuffer = nullptr;
    u_int32_t configBufferSize = 0;
    if (!MP4GetTrackESConfiguration(m_hFile, m_trackId, &configBuffer,
            &configBufferSize)) {
        // Failed to get mpeg-4 audio config... this is ok.
        // NeAACDecInit2() will simply use default values instead.
        qWarning() << "Failed to read the MP4 audio configuration."
                << "Continuing with default values.";
    }

    SAMPLERATE_TYPE samplingRate;
    unsigned char channelCount;
    if (0 > NeAACDecInit2(m_hDecoder, configBuffer, configBufferSize,
                    &samplingRate, &channelCount)) {
        free(configBuffer);
        qWarning() << "Failed to initialize the AAC decoder!";
        return false;
    } else {
        free(configBuffer);
    }

    // Calculate how many sample blocks we need to decode in advance
    // of a random seek in order to get the recommended number of
    // prefetch frames
    m_numberOfPrefetchSampleBlocks =
            (kNumberOfPrefetchFrames + (m_framesPerSampleBlock - 1)) /
            m_framesPerSampleBlock;

    setChannelCount(channelCount);
    setSamplingRate(samplingRate);
    setFrameCount(((m_maxSampleBlockId - kSampleBlockIdMin) + 1) * m_framesPerSampleBlock);

    // Resize temporary buffer for decoded sample data
    const SINT sampleBufferCapacity =
            frames2samples(m_framesPerSampleBlock);
    m_sampleBuffer.resetCapacity(sampleBufferCapacity);

    // Discard all buffered samples
    m_inputBufferLength = 0;

    // Invalidate current position(s) for the following seek operation
    m_curSampleBlockId = MP4_INVALID_SAMPLE_ID;
    m_curFrameIndex = getMaxFrameIndex();

    // (Re-)Start decoding at the beginning of the file
    seekSampleFrame(getMinFrameIndex());

    return m_curFrameIndex == getMinFrameIndex();
}
예제 #16
0
파일: aac_bsf.c 프로젝트: Rockbox/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    size_t n;
    int32_t bread;
    unsigned int frame_samples;
    uint32_t s = 0;
    unsigned char c = 0;
    long action = CODEC_ACTION_NULL;
    intptr_t param;
    unsigned char* buffer;
    NeAACDecFrameInfo frame_info;
    NeAACDecHandle decoder;
    NeAACDecConfigurationPtr conf;

    /* Clean and initialize decoder structures */
    if (codec_init()) {
        LOGF("FAAD: Codec init error\n");
        return CODEC_ERROR;
    }

    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    ci->seek_buffer(ci->id3->first_frame_offset);

    /* initialise the sound converter */
    decoder = NeAACDecOpen();

    if (!decoder) {
        LOGF("FAAD: Decode open error\n");
        return CODEC_ERROR;
    }

    conf = NeAACDecGetCurrentConfiguration(decoder);
    conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
    NeAACDecSetConfiguration(decoder, conf);

    buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);
    bread = NeAACDecInit(decoder, buffer, n, &s, &c);
    if (bread < 0) {
        LOGF("FAAD: DecInit: %ld, %d\n", bread, decoder->object_type);
        return CODEC_ERROR;
    }
    ci->advance_buffer(bread);

    if (ci->id3->offset > ci->id3->first_frame_offset) {
        /* Resume the desired (byte) position. */
        ci->seek_buffer(ci->id3->offset);
        NeAACDecPostSeekReset(decoder, 0);
        update_playing_time();
    } else if (ci->id3->elapsed) {
        action = CODEC_ACTION_SEEK_TIME;
        param = ci->id3->elapsed;
    } else {
        ci->set_elapsed(0);
        ci->set_offset(ci->id3->first_frame_offset);
    }

    /* The main decoding loop */
    while (1) {
        if (action == CODEC_ACTION_NULL)
            action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {
            /* Seek to the desired time position. */
            ci->seek_buffer(ci->id3->first_frame_offset + (uint32_t)((uint64_t)param * ci->id3->bitrate / 8));
            ci->set_elapsed((unsigned long)param);
            NeAACDecPostSeekReset(decoder, 0);
            ci->seek_complete();
        }

        action = CODEC_ACTION_NULL;

        /* Request the required number of bytes from the input buffer */
        buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);

        if (n == 0) /* End of Stream */
            break;

        /* Decode one block - returned samples will be host-endian */
        if (NeAACDecDecode(decoder, &frame_info, buffer, n) == NULL || frame_info.error > 0) {
            LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
            return CODEC_ERROR;
        }

        /* Advance codec buffer (no need to call set_offset because of this) */
        ci->advance_buffer(frame_info.bytesconsumed);

        /* Output the audio */
        ci->yield();
        frame_samples = frame_info.samples >> 1;
        ci->pcmbuf_insert(&decoder->time_out[0][0], &decoder->time_out[1][0], frame_samples);

        /* Update the elapsed-time indicator */
        update_playing_time();
    }

    LOGF("AAC: Decoding complete\n");
    return CODEC_OK;
}
예제 #17
0
파일: decoder_aac.c 프로젝트: Sparod/AirCat
int decoder_aac_open(struct decoder **decoder, const unsigned char *dec_config,
		     size_t dec_config_size, unsigned long *samplerate,
		     unsigned char *channels)
{
	NeAACDecConfigurationPtr config;
	struct decoder *dec;
	int ret;

	/* Alloc structure */
	*decoder = malloc(sizeof(struct decoder));
	if(*decoder == NULL)
		return -1;
	dec = *decoder;

	/* Init structure */
	dec->pcm_buffer = NULL;
	dec->pcm_length = 0;
	dec->pcm_remain = 0;

	/* Initialize faad */
	dec->hDec = NeAACDecOpen();

	/* Set the default object type and samplerate */
	config = NeAACDecGetCurrentConfiguration(dec->hDec);
#ifdef USE_FLOAT
	config->outputFormat = FAAD_FMT_FLOAT;
#else
	config->outputFormat = FAAD_FMT_24BIT;
#endif
	NeAACDecSetConfiguration(dec->hDec, config);

	/* PCM data remaining in output buffer */
	dec->pcm_remain = 0;

	/* Check if ADTS or ADIF header */
	if(dec_config != NULL &&
	  ((dec_config[0] == 0xFF && (dec_config[1] & 0xF6) == 0xF0) ||
	   memcmp(dec_config, "ADIF", 4) == 0))
	{
		/* Init decoder from frame */
		ret = NeAACDecInit(dec->hDec, (unsigned char *) dec_config,
				   dec_config_size, &dec->samplerate,
				   &dec->channels);
	}
	else
	{
		/* Init decoder */
		ret = NeAACDecInit2(dec->hDec, (unsigned char *) dec_config,
				    dec_config_size, &dec->samplerate,
				    &dec->channels);
	}

	/* Check init return */
	if(ret < 0)
	{
		NeAACDecClose(dec->hDec);
		dec->hDec = NULL;
		return -1;
	}

	/* Retunr samplerate and channels */
	if(samplerate != NULL)
		*samplerate = dec->samplerate;
	if(channels != NULL)
		*channels = dec->channels;

	return 0;
}
예제 #18
0
Result SoundSourceM4A::tryOpen(const AudioSourceConfig& audioSrcCfg) {
    DEBUG_ASSERT(MP4_INVALID_FILE_HANDLE == m_hFile);
    // open MP4 file, check for >= ver 1.9.1
    // From mp4v2/file.h:
    //  * On Windows, this should be a UTF-8 encoded string.
    //  * On other platforms, it should be an 8-bit encoding that is
    //  * appropriate for the platform, locale, file system, etc.
    //  * (prefer to use UTF-8 when possible).
#if MP4V2_PROJECT_version_hex <= 0x00010901
    m_hFile = MP4Read(getLocalFileName().toUtf8().constData(), 0);
#else
    m_hFile = MP4Read(getLocalFileName().toUtf8().constData());
#endif
    if (MP4_INVALID_FILE_HANDLE == m_hFile) {
        qWarning() << "Failed to open file for reading:" << getUrlString();
        return ERR;
    }

    m_trackId = findFirstAudioTrackId(m_hFile);
    if (MP4_INVALID_TRACK_ID == m_trackId) {
        qWarning() << "No AAC track found:" << getUrlString();
        return ERR;
    }

    // Read fixed sample duration.  If the sample duration is not
    // fixed (that is, if the number of frames per sample block varies
    // through the file), the call returns MP4_INVALID_DURATION. We
    // can't currently handle these.
    m_framesPerSampleBlock = MP4GetTrackFixedSampleDuration(m_hFile, m_trackId);
    if (MP4_INVALID_DURATION == m_framesPerSampleBlock) {
      qWarning() << "Unable to decode tracks with non-fixed sample durations: " << getUrlString();
      return ERR;
    }

    const MP4SampleId numberOfSamples =
            MP4GetTrackNumberOfSamples(m_hFile, m_trackId);
    if (0 >= numberOfSamples) {
        qWarning() << "Failed to read number of samples from file:" << getUrlString();
        return ERR;
    }
    m_maxSampleBlockId = kSampleBlockIdMin + (numberOfSamples - 1);

    // Determine the maximum input size (in bytes) of a
    // sample block for the selected track.
    const u_int32_t maxSampleBlockInputSize = MP4GetTrackMaxSampleSize(m_hFile,
            m_trackId);
    m_inputBuffer.resize(maxSampleBlockInputSize, 0);

    DEBUG_ASSERT(nullptr == m_hDecoder); // not already opened
    m_hDecoder = NeAACDecOpen();
    if (!m_hDecoder) {
        qWarning() << "Failed to open the AAC decoder!";
        return ERR;
    }
    NeAACDecConfigurationPtr pDecoderConfig = NeAACDecGetCurrentConfiguration(
            m_hDecoder);
    pDecoderConfig->outputFormat = FAAD_FMT_FLOAT;
    if ((kChannelCountMono == audioSrcCfg.channelCountHint) ||
            (kChannelCountStereo == audioSrcCfg.channelCountHint)) {
        pDecoderConfig->downMatrix = 1;
    } else {
        pDecoderConfig->downMatrix = 0;
    }

    pDecoderConfig->defObjectType = LC;
    if (!NeAACDecSetConfiguration(m_hDecoder, pDecoderConfig)) {
        qWarning() << "Failed to configure AAC decoder!";
        return ERR;
    }

    u_int8_t* configBuffer = nullptr;
    u_int32_t configBufferSize = 0;
    if (!MP4GetTrackESConfiguration(m_hFile, m_trackId, &configBuffer,
            &configBufferSize)) {
        /* failed to get mpeg-4 audio config... this is ok.
         * NeAACDecInit2() will simply use default values instead.
         */
        qWarning() << "Failed to read the MP4 audio configuration."
                << "Continuing with default values.";
    }

    SAMPLERATE_TYPE sampleRate;
    unsigned char channelCount;
    if (0 > NeAACDecInit2(m_hDecoder, configBuffer, configBufferSize,
                    &sampleRate, &channelCount)) {
        free(configBuffer);
        qWarning() << "Failed to initialize the AAC decoder!";
        return ERR;
    } else {
        free(configBuffer);
    }

    // Calculate how many sample blocks we need to decode in advance
    // of a random seek in order to get the recommended number of
    // prefetch frames
    m_numberOfPrefetchSampleBlocks  = (kNumberOfPrefetchFrames +
                                      (m_framesPerSampleBlock - 1)) / m_framesPerSampleBlock;

    setChannelCount(channelCount);
    setFrameRate(sampleRate);
    setFrameCount(((m_maxSampleBlockId - kSampleBlockIdMin) + 1) * m_framesPerSampleBlock);

    // Resize temporary buffer for decoded sample data
    const SINT sampleBufferCapacity =
            frames2samples(m_framesPerSampleBlock);
    m_sampleBuffer.resetCapacity(sampleBufferCapacity);

    // Invalidate current position to enforce the following
    // seek operation
    m_curFrameIndex = getMaxFrameIndex();

    // (Re-)Start decoding at the beginning of the file
    seekSampleFrame(getMinFrameIndex());

    return OK;
}
예제 #19
0
파일: aac.c 프로젝트: amitkr/deadbeef
static int
aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
    aac_info_t *info = (aac_info_t *)_info;

    deadbeef->pl_lock ();
    info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
    deadbeef->pl_unlock ();
    if (!info->file) {
        return -1;
    }

    // probe
    float duration = -1;
    int samplerate = -1;
    int channels = -1;
    int totalsamples = -1;

    info->junk = deadbeef->junk_get_leading_size (info->file);
    if (!info->file->vfs->is_streaming ()) {
        if (info->junk >= 0) {
            deadbeef->fseek (info->file, info->junk, SEEK_SET);
        }
        else {
            info->junk = 0;
        }
    }
    else {
        deadbeef->fset_track (info->file, it);
    }

    info->mp4track = -1;
    info->mp4reader.read = aac_fs_read;
    info->mp4reader.write = NULL;
    info->mp4reader.seek = aac_fs_seek;
    info->mp4reader.truncate = NULL;
    info->mp4reader.user_data = info;

    if (!info->file->vfs->is_streaming ()) {
        trace ("aac_init: mp4ff_open_read %s\n", deadbeef->pl_find_meta (it, ":URI"));
        info->mp4 = mp4ff_open_read (&info->mp4reader);
        if (info->mp4) {
            int ntracks = mp4ff_total_tracks (info->mp4);
            for (int i = 0; i < ntracks; i++) {
                if (mp4ff_get_track_type (info->mp4, i) != TRACK_AUDIO) {
                    continue;
                }
                int res = mp4_track_get_info (info->mp4, i, &duration, &samplerate, &channels, &totalsamples, &info->mp4framesize);
                if (res >= 0 && duration > 0) {
                    info->mp4track = i;
                    break;
                }
            }
            trace ("track: %d\n", info->mp4track);
            if (info->mp4track >= 0) {
                // prepare decoder
                int res = mp4_track_get_info (info->mp4, info->mp4track, &duration, &samplerate, &channels, &totalsamples, &info->mp4framesize);
                if (res != 0) {
                    trace ("aac: mp4_track_get_info(%d) returned error\n", info->mp4track);
                    return -1;
                }

                // init mp4 decoding
                info->mp4samples = mp4ff_num_samples(info->mp4, info->mp4track);
                info->dec = NeAACDecOpen ();
                unsigned long srate;
                unsigned char ch;
                unsigned char*  buff = 0;
                unsigned int    buff_size = 0;
                mp4AudioSpecificConfig mp4ASC;
                mp4ff_get_decoder_config (info->mp4, info->mp4track, &buff, &buff_size);
                if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) {
                    trace ("NeAACDecInit2 returned error\n");
                    free (buff);
                    return -1;
                }

                if (buff) {
                    free (buff);
                }
                trace ("aac: successfully initialized track %d\n", info->mp4track);
                _info->fmt.samplerate = samplerate;
                _info->fmt.channels = channels;
            }
            else {
                trace ("aac: track not found in mp4 container\n");
                mp4ff_close (info->mp4);
                info->mp4 = NULL;
            }
        }

        if (!info->mp4) {
            trace ("aac: looking for raw stream...\n");

            if (info->junk >= 0) {
                deadbeef->fseek (info->file, info->junk, SEEK_SET);
            }
            else {
                deadbeef->rewind (info->file);
            }
            int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples);
            if (offs == -1) {
                trace ("aac stream not found\n");
                return -1;
            }
            if (offs > info->junk) {
                info->junk = offs;
            }
            if (info->junk >= 0) {
                deadbeef->fseek (info->file, info->junk, SEEK_SET);
            }
            else {
                deadbeef->rewind (info->file);
            }
            trace ("found aac stream (junk: %d, offs: %d)\n", info->junk, offs);

            _info->fmt.channels = channels;
            _info->fmt.samplerate = samplerate;
        }
    }
    else {
        // sync before attempting to init
        int samplerate, channels;
        float duration;
        int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, NULL);
        if (offs < 0) {
            trace ("aac: parse_aac_stream failed\n");
            return -1;
        }
        if (offs > info->junk) {
            info->junk = offs;
        }
        trace("parse_aac_stream returned %x\n", offs);
        deadbeef->pl_replace_meta (it, "!FILETYPE", "AAC");
    }

//    duration = (float)totalsamples / samplerate;
//    deadbeef->pl_set_item_duration (it, duration);

    _info->fmt.bps = 16;
    _info->plugin = &plugin;

    if (!info->mp4) {
        trace ("NeAACDecOpen for raw stream\n");
        info->dec = NeAACDecOpen ();

        trace ("prepare for NeAACDecInit: fread %d from offs %lld\n", AAC_BUFFER_SIZE, deadbeef->ftell (info->file));
        info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file);

        NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
//        conf->dontUpSampleImplicitSBR = 1;
        NeAACDecSetConfiguration (info->dec, conf);
        unsigned long srate;
        unsigned char ch;
        trace ("NeAACDecInit (%d bytes)\n", info->remaining);
        int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch);
        trace ("NeAACDecInit returned samplerate=%d, channels=%d, consumed: %d\n", (int)srate, (int)ch, consumed);
        if (consumed < 0) {
            trace ("NeAACDecInit returned %d\n", consumed);
            return -1;
        }
        if (consumed > info->remaining) {
            trace ("NeAACDecInit consumed more than available! wtf?\n");
            return -1;
        }
        if (consumed == info->remaining) {
            info->remaining = 0;
        }
        else if (consumed > 0) {
            memmove (info->buffer, info->buffer + consumed, info->remaining - consumed);
            info->remaining -= consumed;
        }
        _info->fmt.channels = ch;
        _info->fmt.samplerate = srate;
    }

    if (!info->file->vfs->is_streaming ()) {
        if (it->endsample > 0) {
            info->startsample = it->startsample;
            info->endsample = it->endsample;
            plugin.seek_sample (_info, 0);
        }
        else {
            info->startsample = 0;
            info->endsample = totalsamples-1;
        }
    }
    if (_info->fmt.channels == 7) {
        _info->fmt.channels = 8;
    }

    trace ("totalsamples: %d, endsample: %d, samples-from-duration: %d, samplerate %d, channels %d\n", totalsamples-1, info->endsample, (int)deadbeef->pl_get_item_duration (it)*44100, _info->fmt.samplerate, _info->fmt.channels);

    for (int i = 0; i < _info->fmt.channels; i++) {
        _info->fmt.channelmask |= 1 << i;
    }
    info->noremap = 0;
    info->remap[0] = -1;
    trace ("init success\n");

    return 0;
}
예제 #20
0
static void *mp4Decode(void *args)
{
  FILE*		mp4file;

  pthread_mutex_lock(&mutex);
  seekPosition = -1;
  bPlaying = TRUE;

  if(!(mp4file = fopen(args, "rb"))){
    g_print("MP4!AAC - Can't open file\n");
    g_free(args);
    bPlaying = FALSE;
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);

  }
  mp4_get_file_type(mp4file);
  fseek(mp4file, 0, SEEK_SET);
  if(mp4cfg.file_type == FILE_MP4){// We are reading a MP4 file
    mp4ff_callback_t*	mp4cb;
    mp4ff_t*		infile;
    gint		mp4track;

    mp4cb = getMP4FF_cb(mp4file);
    if(!(infile = mp4ff_open_read(mp4cb))){
      g_print("MP4 - Can't open file\n");
      goto end;
    }

    if((mp4track = getAACTrack(infile)) < 0){
      /*
       * TODO: check here for others Audio format.....
       *
      */
      g_print("Unsupported Audio track type\n");
      g_free(args);
      fclose(mp4file);
      bPlaying = FALSE;
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }else{
      NeAACDecHandle	decoder;
      unsigned char	*buffer	= NULL;
      guint		bufferSize = 0;
      gulong		samplerate;
      guchar		channels;
      //guint		avgBitrate;
      //MP4Duration	duration;
      int		msDuration;
      int		numSamples;
      int		sampleID = 0;
      unsigned int	framesize;
      mp4AudioSpecificConfig mp4ASC;
      gchar		*xmmstitle;

      decoder = NeAACDecOpen();
      mp4ff_get_decoder_config(infile, mp4track, &buffer, &bufferSize);
      if(NeAACDecInit2(decoder, buffer, bufferSize, &samplerate, &channels)<0){
          goto end;
      }
      if(buffer){
	framesize = 1024;
	if(NeAACDecAudioSpecificConfig(buffer, bufferSize, &mp4ASC) >= 0){
	  if(mp4ASC.frameLengthFlag == 1) framesize = 960;
	  if(mp4ASC.sbr_present_flag == 1) framesize *= 2;
	}
	g_free(buffer);
      }
      if(channels == 0){
	g_print("Number of Channels not supported\n");
	goto end;
      }

      //duration = MP4GetTrackDuration(mp4file, mp4track);
      //msDuration = MP4ConvertFromTrackDuration(mp4file, mp4track,
      //				       duration,MP4_MSECS_TIME_SCALE);

      //msDuration = mp4ff_get_track_duration(infile, mp4track);
      //printf("%d\n", msDuration);

      //numSamples = MP4GetTrackNumberOfSamples(mp4file, mp4track);
      numSamples = mp4ff_num_samples(infile, mp4track);
      {
	float f = 1024.0;
	if(mp4ASC.sbr_present_flag == 1)
	  f = f * 2.0;
	msDuration = ((float)numSamples*(float)(f-1.0)/
		      (float)samplerate)*1000;
      }
      xmmstitle = getMP4title(infile, args);
      mp4_ip.output->open_audio(FMT_S16_NE, samplerate, channels);
      mp4_ip.output->flush(0);
      mp4_ip.set_info(xmmstitle, msDuration, -1, samplerate/1000, channels);
      g_print("MP4 - %d channels @ %ld Hz\n", channels, samplerate);

      while(bPlaying){
	void*			sampleBuffer;
	faacDecFrameInfo	frameInfo;
	gint			rc;

	if(seekPosition!=-1){
	  /*
	  duration = MP4ConvertToTrackDuration(mp4file,
					       mp4track,
					       seekPosition*1000,
					       MP4_MSECS_TIME_SCALE);
	  sampleID = MP4GetSampleIdFromTime(mp4file, mp4track, duration, 0);
          */
          float f = 1024.0;
	  if(mp4ASC.sbr_present_flag == 1)
	    f = f * 2.0;
          sampleID = (float)seekPosition*(float)samplerate/(float)(f-1.0);
	  mp4_ip.output->flush(seekPosition*1000);
	  seekPosition = -1;
	}
	buffer=NULL;
	bufferSize=0;
	rc = mp4ff_read_sample(infile, mp4track, sampleID++,
			       &buffer, &bufferSize);
	//g_print("%d/%d\n", sampleID-1, numSamples);
	if((rc==0) || (buffer== NULL)){
	  g_print("MP4: read error\n");
	  sampleBuffer = NULL;
	  sampleID=0;
	  mp4_ip.output->buffer_free();
            goto end;
	}else{
	  sampleBuffer = NeAACDecDecode(decoder, &frameInfo, buffer, bufferSize);
	  if(frameInfo.error > 0){
	    g_print("MP4: %s\n",
		    faacDecGetErrorMessage(frameInfo.error));
	    goto end;
	  }
	  if(buffer){
	    g_free(buffer); buffer=NULL; bufferSize=0;
	  }
	  while(bPlaying && mp4_ip.output->buffer_free()<frameInfo.samples<<1)
	    xmms_usleep(30000);
	}
	mp4_ip.add_vis_pcm(mp4_ip.output->written_time(),
			   FMT_S16_NE,
			   channels,
			   frameInfo.samples<<1,
			   sampleBuffer);
	mp4_ip.output->write_audio(sampleBuffer, frameInfo.samples<<1);
	if(sampleID >= numSamples){
          break;
	}
      }
      while(bPlaying && mp4_ip.output->buffer_playing() && mp4_ip.output->buffer_free()){
	xmms_usleep(10000);
      }
end:
      mp4_ip.output->close_audio();
      g_free(args);
      NeAACDecClose(decoder);
      if(infile) mp4ff_close(infile);
      if(mp4cb) g_free(mp4cb);
      bPlaying = FALSE;
      fclose(mp4file);
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }
  }else{
    // WE ARE READING AN AAC FILE
    FILE		*file = NULL;
    NeAACDecHandle	decoder = 0;
    guchar		*buffer = 0;
    gulong		bufferconsumed = 0;
    gulong		samplerate = 0;
    guchar		channels;
    gulong		buffervalid = 0;
    TitleInput*		input;
    gchar		*temp = g_strdup(args);
    gchar		*ext  = strrchr(temp, '.');
    gchar		*xmmstitle = NULL;
    NeAACDecConfigurationPtr config;

    if((file = fopen(args, "rb")) == 0){
      g_print("AAC: can't find file %s\n", args);
      bPlaying = FALSE;
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }
    if((decoder = NeAACDecOpen()) == NULL){
      g_print("AAC: Open Decoder Error\n");
      fclose(file);
      bPlaying = FALSE;
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }
    config = NeAACDecGetCurrentConfiguration(decoder);
    config->useOldADTSFormat = 0;
    NeAACDecSetConfiguration(decoder, config);
    if((buffer = g_malloc(BUFFER_SIZE)) == NULL){
      g_print("AAC: error g_malloc\n");
      fclose(file);
      bPlaying = FALSE;
      NeAACDecClose(decoder);
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }
    if((buffervalid = fread(buffer, 1, BUFFER_SIZE, file))==0){
      g_print("AAC: Error reading file\n");
      g_free(buffer);
      fclose(file);
      bPlaying = FALSE;
      NeAACDecClose(decoder);
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }
    XMMS_NEW_TITLEINPUT(input);
    input->file_name = g_basename(temp);
    input->file_ext = ext ? ext+1 : NULL;
    input->file_path = temp;
    if(!strncmp(buffer, "ID3", 3)){
      gint size = 0;

      fseek(file, 0, SEEK_SET);
      size = (buffer[6]<<21) | (buffer[7]<<14) | (buffer[8]<<7) | buffer[9];
      size+=10;
      fread(buffer, 1, size, file);
      buffervalid = fread(buffer, 1, BUFFER_SIZE, file);
    }
    xmmstitle = xmms_get_titlestring(xmms_get_gentitle_format(), input);
    if(xmmstitle == NULL)
      xmmstitle = g_strdup(input->file_name);
    if(temp) g_free(temp);
    if(input->performer) g_free(input->performer);
    if(input->album_name) g_free(input->album_name);
    if(input->track_name) g_free(input->track_name);
    if(input->genre) g_free(input->genre);
    g_free(input);
    bufferconsumed = NeAACDecInit(decoder,
				 buffer,
				 buffervalid,
				 &samplerate,
				 &channels);
    if(mp4_ip.output->open_audio(FMT_S16_NE,samplerate,channels) == FALSE){
      g_print("AAC: Output Error\n");
      g_free(buffer); buffer=0;
      faacDecClose(decoder);
      fclose(file);
      mp4_ip.output->close_audio();
      /*
      if(positionTable){
	g_free(positionTable); positionTable=0;
      }
      */
      g_free(xmmstitle);
      bPlaying = FALSE;
      pthread_mutex_unlock(&mutex);
      pthread_exit(NULL);
    }
    //if(bSeek){
    //mp4_ip.set_info(xmmstitle, lenght*1000, -1, samplerate, channels);
      //}else{
    mp4_ip.set_info(xmmstitle, -1, -1, samplerate, channels);
      //}
    mp4_ip.output->flush(0);

    while(bPlaying && buffervalid > 0){
      NeAACDecFrameInfo	finfo;
      unsigned long	samplesdecoded;
      char*		sample_buffer = NULL;
      /*
	if(bSeek && seekPosition!=-1){
	fseek(file, positionTable[seekPosition], SEEK_SET);
	bufferconsumed=0;
	buffervalid = fread(buffer, 1, BUFFER_SIZE, file);
	aac_ip.output->flush(seekPosition*1000);
	seekPosition=-1;
	}
      */
      if(bufferconsumed > 0){
	memmove(buffer, &buffer[bufferconsumed], buffervalid-bufferconsumed);
	buffervalid -= bufferconsumed;
	buffervalid += fread(&buffer[buffervalid], 1,
			     BUFFER_SIZE-buffervalid, file);
	bufferconsumed = 0;
      }
      sample_buffer = NeAACDecDecode(decoder, &finfo, buffer, buffervalid);
      if(finfo.error){
	config = NeAACDecGetCurrentConfiguration(decoder);
	if(config->useOldADTSFormat != 1){
	  NeAACDecClose(decoder);
	  decoder = NeAACDecOpen();
	  config = NeAACDecGetCurrentConfiguration(decoder);
	  config->useOldADTSFormat = 1;
	  NeAACDecSetConfiguration(decoder, config);
	  finfo.bytesconsumed=0;
	  finfo.samples = 0;
	  NeAACDecInit(decoder,
		      buffer,
		      buffervalid,
		      &samplerate,
		      &channels);
	}else{
	  g_print("FAAD2 Warning %s\n", NeAACDecGetErrorMessage(finfo.error));
	  buffervalid = 0;
	}
      }
      bufferconsumed += finfo.bytesconsumed;
      samplesdecoded = finfo.samples;
      if((samplesdecoded<=0) && !sample_buffer){
	g_print("AAC: error sample decoding\n");
	continue;
      }
      while(bPlaying && mp4_ip.output->buffer_free() < (samplesdecoded<<1)){
	xmms_usleep(10000);
      }
      mp4_ip.add_vis_pcm(mp4_ip.output->written_time(),
			 FMT_S16_LE, channels,
			 samplesdecoded<<1, sample_buffer);
      mp4_ip.output->write_audio(sample_buffer, samplesdecoded<<1);
    }
    while(bPlaying && mp4_ip.output->buffer_playing()){
      xmms_usleep(10000);
    }
    mp4_ip.output->buffer_free();
    mp4_ip.output->close_audio();
    bPlaying = FALSE;
    g_free(buffer);
    NeAACDecClose(decoder);
    g_free(xmmstitle);
    fclose(file);
    seekPosition = -1;
    /*
    if(positionTable){
      g_free(positionTable); positionTable=0;
    }
    */
    bPlaying = FALSE;
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);

  }
}
예제 #21
0
파일: player.c 프로젝트: jenikm/pianobar
/*	player thread; for every song a new thread is started
 *	@param audioPlayer structure
 *	@return PLAYER_RET_*
 */
void *BarPlayerThread (void *data) {
	struct audioPlayer *player = data;
	char extraHeaders[32];
	void *ret = PLAYER_RET_OK;
	#ifdef ENABLE_FAAD
	NeAACDecConfigurationPtr conf;
	#endif
	WaitressReturn_t wRet = WAITRESS_RET_ERR;

	/* init handles */
	pthread_mutex_init (&player->pauseMutex, NULL);
	player->waith.data = (void *) player;
	/* extraHeaders will be initialized later */
	player->waith.extraHeaders = extraHeaders;
	player->buffer = malloc (BAR_PLAYER_BUFSIZE);

	switch (player->audioFormat) {
		#ifdef ENABLE_FAAD
		case PIANO_AF_AACPLUS:
			player->aacHandle = NeAACDecOpen();
			/* set aac conf */
			conf = NeAACDecGetCurrentConfiguration(player->aacHandle);
			conf->outputFormat = FAAD_FMT_16BIT;
		    conf->downMatrix = 1;
			NeAACDecSetConfiguration(player->aacHandle, conf);

			player->waith.callback = BarPlayerAACCb;
			break;
		#endif /* ENABLE_FAAD */

		#ifdef ENABLE_MAD
		case PIANO_AF_MP3:
			mad_stream_init (&player->mp3Stream);
			mad_frame_init (&player->mp3Frame);
			mad_synth_init (&player->mp3Synth);

			player->waith.callback = BarPlayerMp3Cb;
			break;
		#endif /* ENABLE_MAD */

		default:
			BarUiMsg (player->settings, MSG_ERR, "Unsupported audio format!\n");
			ret = (void *) PLAYER_RET_HARDFAIL;
			goto cleanup;
			break;
	}
	
	player->mode = PLAYER_INITIALIZED;

	/* This loop should work around song abortions by requesting the
	 * missing part of the song */
	do {
		snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n",
				player->bytesReceived);
		wRet = WaitressFetchCall (&player->waith);
	} while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT
			|| wRet == WAITRESS_RET_READ_ERR);

	switch (player->audioFormat) {
		#ifdef ENABLE_FAAD
		case PIANO_AF_AACPLUS:
			NeAACDecClose(player->aacHandle);
			free (player->sampleSize);
			break;
		#endif /* ENABLE_FAAD */

		#ifdef ENABLE_MAD
		case PIANO_AF_MP3:
			mad_synth_finish (&player->mp3Synth);
			mad_frame_finish (&player->mp3Frame);
			mad_stream_finish (&player->mp3Stream);
			break;
		#endif /* ENABLE_MAD */

		default:
			/* this should never happen */
			assert (0);
			break;
	}

	if (player->aoError) {
		ret = (void *) PLAYER_RET_HARDFAIL;
	}

	/* Pandora sends broken audio url’s sometimes (“bad request”). ignore them. */
	if (wRet != WAITRESS_RET_OK && wRet != WAITRESS_RET_CB_ABORT) {
		BarUiMsg (player->settings, MSG_ERR, "Cannot access audio file: %s\n",
				WaitressErrorToStr (wRet));
		ret = (void *) PLAYER_RET_SOFTFAIL;
	}

cleanup:
	ao_close (player->audioOutDevice);
	WaitressFree (&player->waith);
	free (player->buffer);

	player->mode = PLAYER_FINISHED_PLAYBACK;

	return ret;
}
예제 #22
0
파일: aac.c 프로젝트: vadmium/deadbeef
static int
aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
    aac_info_t *info = (aac_info_t *)_info;

    info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
    if (!info->file) {
        return -1;
    }

    // probe
    float duration = -1;
    int samplerate = -1;
    int channels = -1;
    int totalsamples = -1;

    info->junk = deadbeef->junk_get_leading_size (info->file);
    if (!info->file->vfs->is_streaming ()) {
        if (info->junk >= 0) {
            deadbeef->fseek (info->file, info->junk, SEEK_SET);
        }
        else {
            info->junk = 0;
        }
    }
    else {
        deadbeef->fset_track (info->file, it);
    }

    info->mp4track = -1;
#if USE_MP4FF
    info->mp4reader.read = aac_fs_read;
    info->mp4reader.write = NULL;
    info->mp4reader.seek = aac_fs_seek;
    info->mp4reader.truncate = NULL;
    info->mp4reader.user_data = info;
#else
    info->mp4reader.open = aac_fs_open;
    info->mp4reader.seek = aac_fs_seek;
    info->mp4reader.read = aac_fs_read;
    info->mp4reader.write = NULL;
    info->mp4reader.close = aac_fs_close;
#endif

    if (!info->file->vfs->is_streaming ()) {
#ifdef USE_MP4FF
        trace ("aac_init: mp4ff_open_read %s\n", deadbeef->pl_find_meta (it, ":URI"));
        info->mp4file = mp4ff_open_read (&info->mp4reader);
        if (info->mp4file) {
            int ntracks = mp4ff_total_tracks (info->mp4file);
            if (ntracks > 0) {
                trace ("m4a container detected, ntracks=%d\n", ntracks);
                int i = -1;
                unsigned char*  buff = 0;
                unsigned int    buff_size = 0;
                for (i = 0; i < ntracks; i++) {
                    mp4AudioSpecificConfig mp4ASC;
                    mp4ff_get_decoder_config (info->mp4file, i, &buff, &buff_size);
                    if(buff){
                        int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
                        if(rc < 0)
                            continue;
                        break;
                    }
                }
                trace ("mp4 probe-buffer size: %d\n", buff_size);

                if (i != ntracks && buff) 
                {
                    trace ("mp4 track: %d\n", i);
                    int samples = mp4ff_num_samples(info->mp4file, i);
                    info->mp4samples = samples;
                    info->mp4track = i;

                    // init mp4 decoding
                    info->dec = NeAACDecOpen ();
                    unsigned long srate;
                    unsigned char ch;
                    if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) {
                        trace ("NeAACDecInit2 returned error\n");
                        free (buff);
                        return -1;
                    }
                    samplerate = srate;
                    channels = ch;
                    samples = (int64_t)samples * srate / mp4ff_time_scale (info->mp4file, i);
                    totalsamples = samples;
                    NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
                    conf->dontUpSampleImplicitSBR = 1;
                    NeAACDecSetConfiguration (info->dec, conf);
                    mp4AudioSpecificConfig mp4ASC;
                    if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0)
                    {
                        info->mp4framesize = 1024;
                        if (mp4ASC.frameLengthFlag == 1) {
                            info->mp4framesize = 960;
                        }
//                        if (mp4ASC.sbr_present_flag == 1) {
//                            info->mp4framesize *= 2;
//                        }
                    }
                    totalsamples *= info->mp4framesize;
                    duration = (float)totalsamples  / samplerate;
                }
                else {
                    mp4ff_close (info->mp4file);
                    info->mp4file = NULL;
                }
                if (buff) {
                    free (buff);
                }
            }
            else {
                mp4ff_close (info->mp4file);
                info->mp4file = NULL;
            }
        }
// {{{ libmp4v2 code
#else
        trace ("aac_init: MP4ReadProvider %s\n", deadbeef->pl_find_meta (it, ":URI"));
        info->mp4file = MP4ReadProvider (deadbeef->pl_find_meta (it, ":URI"), 0, &info->mp4reader);
        info->mp4track = MP4FindTrackId(info->mp4file, 0, "audio", 0);
        trace ("aac_init: MP4FindTrackId returned %d\n", info->mp4track);
        if (info->mp4track >= 0) {
            info->timescale = MP4GetTrackTimeScale(info->mp4file, info->mp4track);

            u_int8_t* pConfig;
            uint32_t configSize = 0;
            bool res = MP4GetTrackESConfiguration(info->mp4file, info->mp4track, &pConfig, &configSize);

            mp4AudioSpecificConfig mp4ASC;
            int rc = AudioSpecificConfig(pConfig, configSize, &mp4ASC);
            if (rc >= 0) {
                _info->samplerate = mp4ASC.samplingFrequency;
                _info->channels = MP4GetTrackAudioChannels (info->mp4file, info->mp4track);
                totalsamples = MP4GetTrackNumberOfSamples (info->mp4file, info->mp4track) * 1024 * _info->channels;

                // init mp4 decoding
                info->dec = NeAACDecOpen ();
                unsigned long srate;
                unsigned char ch;
                if (NeAACDecInit2(info->dec, pConfig, configSize, &srate, &ch) < 0) {
                    trace ("NeAACDecInit2 returned error\n");
                    return -1;
                }
                samplerate = srate;
                channels = ch;
                NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
                conf->dontUpSampleImplicitSBR = 1;
                NeAACDecSetConfiguration (info->dec, conf);
                mp4AudioSpecificConfig mp4ASC;
                if (NeAACDecAudioSpecificConfig(pConfig, configSize, &mp4ASC) >= 0)
                {
                    info->mp4framesize = 1024;
                    if (mp4ASC.frameLengthFlag == 1) {
                        info->mp4framesize = 960;
                    }
//                    if (mp4ASC.sbr_present_flag == 1) {
//                        info->mp4framesize *= 2;
//                    }
                }
                //totalsamples *= info->mp4framesize;
                free (pConfig);
                info->maxSampleSize = MP4GetTrackMaxSampleSize(info->mp4file, info->mp4track);
                info->samplebuffer = malloc (info->maxSampleSize);
                info->mp4sample = 1;
            }
            else {
                MP4Close (info->mp4file);
                info->mp4file = NULL;
            }
        }
        else {
            MP4Close (info->mp4file);
            info->mp4file = NULL;
        }
#endif
// }}}
        if (!info->mp4file) {
            trace ("mp4 track not found, looking for aac stream...\n");

            if (info->junk >= 0) {
                deadbeef->fseek (info->file, info->junk, SEEK_SET);
            }
            else {
                deadbeef->rewind (info->file);
            }
            int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples);
            if (offs == -1) {
                trace ("aac stream not found\n");
                return -1;
            }
            if (offs > info->junk) {
                info->junk = offs;
            }
            if (info->junk >= 0) {
                deadbeef->fseek (info->file, info->junk, SEEK_SET);
            }
            else {
                deadbeef->rewind (info->file);
            }
            trace ("found aac stream (junk: %d, offs: %d)\n", info->junk, offs);
        }

        _info->fmt.channels = channels;
        _info->fmt.samplerate = samplerate;
    }
    else {
        // sync before attempting to init
        int samplerate, channels;
        float duration;
        int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, NULL);
        if (offs < 0) {
            trace ("aac: parse_aac_stream failed\n");
            return -1;
        }
        if (offs > info->junk) {
            info->junk = offs;
        }
        trace("parse_aac_stream returned %x\n", offs);
        deadbeef->pl_replace_meta (it, "!FILETYPE", "AAC");
    }

//    duration = (float)totalsamples / samplerate;
//    deadbeef->pl_set_item_duration (it, duration);

    _info->fmt.bps = 16;
    _info->plugin = &plugin;

    if (!info->mp4file) {
        //trace ("NeAACDecGetCapabilities\n");
        //unsigned long caps = NeAACDecGetCapabilities();

        trace ("NeAACDecOpen\n");
        info->dec = NeAACDecOpen ();

        trace ("prepare for NeAACDecInit: fread %d from offs %lld\n", AAC_BUFFER_SIZE, deadbeef->ftell (info->file));
        info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file);

        NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
//        conf->dontUpSampleImplicitSBR = 1;
        NeAACDecSetConfiguration (info->dec, conf);
        unsigned long srate;
        unsigned char ch;
        trace ("NeAACDecInit (%d bytes)\n", info->remaining);
        int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch);
        trace ("NeAACDecInit returned samplerate=%d, channels=%d, consumed: %d\n", (int)srate, (int)ch, consumed);
        if (consumed < 0) {
            trace ("NeAACDecInit returned %d\n", consumed);
            return -1;
        }
        if (consumed > info->remaining) {
            trace ("NeAACDecInit consumed more than available! wtf?\n");
            return -1;
        }
        if (consumed == info->remaining) {
            info->remaining = 0;
        }
        else if (consumed > 0) {
            memmove (info->buffer, info->buffer + consumed, info->remaining - consumed);
            info->remaining -= consumed;
        }
        _info->fmt.channels = ch;
        _info->fmt.samplerate = srate;
    }

    if (!info->file->vfs->is_streaming ()) {
        if (it->endsample > 0) {
            info->startsample = it->startsample;
            info->endsample = it->endsample;
            plugin.seek_sample (_info, 0);
        }
        else {
            info->startsample = 0;
            info->endsample = totalsamples-1;
        }
    }
    trace ("totalsamples: %d, endsample: %d, samples-from-duration: %d\n", totalsamples-1, info->endsample, (int)deadbeef->pl_get_item_duration (it)*44100);

    for (int i = 0; i < _info->fmt.channels; i++) {
        _info->fmt.channelmask |= 1 << i;
    }
    info->noremap = 0;
    info->remap[0] = -1;
    trace ("init success\n");

    return 0;
}
예제 #23
0
파일: libaacdec.c 프로젝트: vitmod/libp
static int audio_decoder_init( 
#ifndef WIN32	
	audio_decoder_operations_t *adec_ops, 
#endif	
	char *outbuf, int *outlen, char *inbuf, int inlen, long *inbuf_consumed)
{
    unsigned long samplerate;
    unsigned char channels;
    int ret;
    NeAACDecConfigurationPtr config = NULL;
    char *in_buf;
    int  inbuf_size;
    in_buf = inbuf;
    inbuf_size = inlen;
    int nReadLen=0;
    FaadContext *gFaadCxt  =	(FaadContext*)adec_ops->pdecoder;
    int islatm = 0;
    if(!in_buf || !inbuf_size ||!outbuf){
		audio_codec_print(" input/output buffer null or input len is 0 \n");
   } 
retry:
//fixed to LATM aac frame header sync to speed up seek speed
#if  1
   if(adec_ops->nAudioDecoderType == ACODEC_FMT_AAC_LATM){
	islatm = 1;
	int nSeekNum = AACFindLATMSyncWord(in_buf,inbuf_size);
	if(nSeekNum == (inbuf_size-2)){
		audio_codec_print("[%s]%d bytes data not found latm sync header \n",__FUNCTION__,nSeekNum);	
	}
	else{
		audio_codec_print("[%s]latm seek sync header cost %d,total %d,left %d \n",__FUNCTION__,nSeekNum,inbuf_size,inbuf_size - nSeekNum);
	}
	inbuf_size = inbuf_size - nSeekNum;
	if(inbuf_size < (get_frame_size(gFaadCxt)+FRAME_SIZE_MARGIN)/*AAC_INPUTBUF_SIZE/2*/){
		audio_codec_print("[%s]input size %d at least %d ,need more data \n",__FUNCTION__,inbuf_size,(get_frame_size(gFaadCxt)+FRAME_SIZE_MARGIN));
		*inbuf_consumed = inlen-inbuf_size;
		return AAC_ERROR_NO_ENOUGH_DATA; 
	}		
    }
#endif
    gFaadCxt->hDecoder = NeAACDecOpen();
    config = NeAACDecGetCurrentConfiguration(gFaadCxt->hDecoder);
    config->defObjectType = LC;
    config->outputFormat = FAAD_FMT_16BIT;
    config->downMatrix = 0x01;
    config->useOldADTSFormat = 0;
    //config->dontUpSampleImplicitSBR = 1;
    NeAACDecSetConfiguration(gFaadCxt->hDecoder, config);
    if ((ret = NeAACDecInit(gFaadCxt->hDecoder, in_buf,inbuf_size, &samplerate, &channels,islatm)) < 0)
    {
    		in_buf += RSYNC_SKIP_BYTES;
		inbuf_size -= RSYNC_SKIP_BYTES;
		NeAACDecClose(gFaadCxt->hDecoder);
		gFaadCxt->hDecoder=NULL;
		if(inbuf_size < 0)
			inbuf_size = 0;
		audio_codec_print("init fail,inbuf_size %d \n",inbuf_size);
		if(inbuf_size <  (get_frame_size(gFaadCxt)+FRAME_SIZE_MARGIN)/*AAC_INPUTBUF_SIZE/2*/){
			audio_codec_print("input size %d at least %d ,need more data \n",inbuf_size,(get_frame_size(gFaadCxt)+FRAME_SIZE_MARGIN));
			*inbuf_consumed = inlen-inbuf_size;
			return AAC_ERROR_NO_ENOUGH_DATA;
		}
		goto retry;
    }
    audio_codec_print("init sucess cost %d\n",ret);	
    in_buf += ret;
    inbuf_size -= ret;
    *inbuf_consumed = inlen-	inbuf_size;
    NeAACDecStruct* hDecoder = (NeAACDecStruct*)(gFaadCxt->hDecoder);
    gFaadCxt->init_flag=1;
    gFaadCxt->gChannels=channels;
    gFaadCxt->gSampleRate=samplerate;
    audio_codec_print("[%s] Init OK adif_present :%d adts_present:%d latm_present:%d,sr %d,ch %d\n",__FUNCTION__,hDecoder->adif_header_present,hDecoder->adts_header_present,hDecoder->latm_header_present,samplerate,channels);
    return 0;
}
예제 #24
0
Result SoundSourceM4A::tryOpen(const AudioSourceConfig& audioSrcCfg) {
    DEBUG_ASSERT(MP4_INVALID_FILE_HANDLE == m_hFile);
    /* open MP4 file, check for >= ver 1.9.1 */
#if MP4V2_PROJECT_version_hex <= 0x00010901
    m_hFile = MP4Read(getLocalFileNameBytes().constData(), 0);
#else
    m_hFile = MP4Read(getLocalFileNameBytes().constData());
#endif
    if (MP4_INVALID_FILE_HANDLE == m_hFile) {
        qWarning() << "Failed to open file for reading:" << getUrlString();
        return ERR;
    }

    m_trackId = findFirstAudioTrackId(m_hFile);
    if (MP4_INVALID_TRACK_ID == m_trackId) {
        qWarning() << "No AAC track found:" << getUrlString();
        return ERR;
    }

    const MP4SampleId numberOfSamples =
            MP4GetTrackNumberOfSamples(m_hFile, m_trackId);
    if (0 >= numberOfSamples) {
        qWarning() << "Failed to read number of samples from file:" << getUrlString();
        return ERR;
    }
    m_maxSampleBlockId = kSampleBlockIdMin + (numberOfSamples - 1);

    // Determine the maximum input size (in bytes) of a
    // sample block for the selected track.
    const u_int32_t maxSampleBlockInputSize = MP4GetTrackMaxSampleSize(m_hFile,
            m_trackId);
    m_inputBuffer.resize(maxSampleBlockInputSize, 0);

    DEBUG_ASSERT(NULL == m_hDecoder); // not already opened
    m_hDecoder = NeAACDecOpen();
    if (!m_hDecoder) {
        qWarning() << "Failed to open the AAC decoder!";
        return ERR;
    }
    NeAACDecConfigurationPtr pDecoderConfig = NeAACDecGetCurrentConfiguration(
            m_hDecoder);
    pDecoderConfig->outputFormat = FAAD_FMT_FLOAT;
    if ((kChannelCountMono == audioSrcCfg.channelCountHint) ||
            (kChannelCountStereo == audioSrcCfg.channelCountHint)) {
        pDecoderConfig->downMatrix = 1;
    } else {
        pDecoderConfig->downMatrix = 0;
    }

    pDecoderConfig->defObjectType = LC;
    if (!NeAACDecSetConfiguration(m_hDecoder, pDecoderConfig)) {
        qWarning() << "Failed to configure AAC decoder!";
        return ERR;
    }

    u_int8_t* configBuffer = NULL;
    u_int32_t configBufferSize = 0;
    if (!MP4GetTrackESConfiguration(m_hFile, m_trackId, &configBuffer,
            &configBufferSize)) {
        /* failed to get mpeg-4 audio config... this is ok.
         * NeAACDecInit2() will simply use default values instead.
         */
        qWarning() << "Failed to read the MP4 audio configuration."
                << "Continuing with default values.";
    }

    SAMPLERATE_TYPE sampleRate;
    unsigned char channelCount;
    if (0 > NeAACDecInit2(m_hDecoder, configBuffer, configBufferSize,
                    &sampleRate, &channelCount)) {
        free(configBuffer);
        qWarning() << "Failed to initialize the AAC decoder!";
        return ERR;
    } else {
        free(configBuffer);
    }

    setChannelCount(channelCount);
    setFrameRate(sampleRate);
    setFrameCount(getFrameCountForSampleBlockId(m_maxSampleBlockId));

    // Resize temporary buffer for decoded sample data
    const SINT sampleBufferCapacity =
            frames2samples(kFramesPerSampleBlock);
    m_sampleBuffer.resetCapacity(sampleBufferCapacity);

    // Invalidate current position to enforce the following
    // seek operation
    m_curFrameIndex = getMaxFrameIndex();

    // (Re-)Start decoding at the beginning of the file
    seekSampleFrame(getMinFrameIndex());

    return OK;
}
예제 #25
0
파일: aac.c 프로젝트: console-tools/moc
static void *aac_open_internal (struct io_stream *stream, const char *fname)
{
	struct aac_data *data;
	NeAACDecConfigurationPtr neaac_cfg;
	unsigned char channels;
	unsigned long sample_rate;
	int n;

	/* init private struct */
	data = xcalloc (1, sizeof *data);
	data->decoder = NeAACDecOpen();

	/* set decoder config */
	neaac_cfg = NeAACDecGetCurrentConfiguration(data->decoder);
	neaac_cfg->outputFormat = FAAD_FMT_16BIT;	/* force 16 bit audio */
	neaac_cfg->downMatrix = 1;			/* 5.1 -> stereo */
	neaac_cfg->dontUpSampleImplicitSBR = 0;		/* upsample, please! */
	NeAACDecSetConfiguration(data->decoder, neaac_cfg);

	if (stream)
		data->stream = stream;
	else {
		data->stream = io_open (fname, 1);
		if (!io_ok(data->stream)) {
			decoder_error (&data->error, ERROR_FATAL, 0,
					"Can't open AAC file: %s", io_strerror(data->stream));
			return data;
		}
	}

	/* find a frame */
	if (buffer_fill_frame(data) <= 0) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"Not a valid (or unsupported) AAC file");
		return data;
	}

	/* in case of a bug, make sure there is at least some data
	 * in the buffer for NeAACDecInit() to work with.
	 */
	if (buffer_fill_min(data, 256) <= 0) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"AAC file/stream too short");
		return data;
	}

	/* init decoder, returns the length of the header (if any) */
	channels = (unsigned char)data->channels;
	sample_rate = data->sample_rate;
	n = NeAACDecInit (data->decoder, buffer_data(data), buffer_length(data),
		&sample_rate, &channels);
	data->channels = channels;
	data->sample_rate = (int)sample_rate;
	if (n < 0) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"libfaad can't open this stream");
		return data;
	}

	logit ("sample rate %dHz, channels %d", data->sample_rate, data->channels);
	if (!data->sample_rate || !data->channels) {
		decoder_error (&data->error, ERROR_FATAL, 0,
				"Invalid AAC sound parameters");
		return data;
	}

	/* skip the header */
	logit ("skipping header (%d bytes)", n);
	buffer_consume (data, n);

	/*NeAACDecInitDRM(data->decoder, data->sample_rate, data->channels);*/

	data->ok = 1;
	return data;
}
예제 #26
0
파일: decode.c 프로젝트: khalidaw/vlc-speed
int decodeAACfile(char *sndfile, int def_srate, aac_dec_opt *opt)
{
    int tagsize;
    unsigned long samplerate;
    unsigned char channels;
    void *sample_buffer;

    FILE *infile;

    audio_file *aufile;

    NeAACDecHandle hDecoder;
    NeAACDecFrameInfo frameInfo;
    NeAACDecConfigurationPtr config;

    int first_time = 1;


    /* declare variables for buffering */
    DEC_BUFF_VARS

    infile = fopen(opt->filename, "rb");
    if (infile == NULL)
    {
        /* unable to open file */
        error_handler("Error opening file: %s\n", opt->filename);
        return 1;
    }
    INIT_BUFF(infile)

    tagsize = id3v2_tag(buffer);
    if (tagsize)
    {
        UPDATE_BUFF_SKIP(tagsize)
    }

    hDecoder = NeAACDecOpen();

    /* Set the default object type and samplerate */
    /* This is useful for RAW AAC files */
    config = NeAACDecGetCurrentConfiguration(hDecoder);
    if (def_srate)
        config->defSampleRate = def_srate;
    config->defObjectType = opt->object_type;
    config->outputFormat = opt->output_format;

    NeAACDecSetConfiguration(hDecoder, config);

    if ((bytesconsumed = NeAACDecInit(hDecoder, buffer, bytes_in_buffer,
        &samplerate, &channels)) < 0)
    {
        /* If some error initializing occured, skip the file */
        error_handler("Error initializing decoder library.\n");
        END_BUFF
        NeAACDecClose(hDecoder);
        fclose(infile);
        return 1;
    }
    buffer_index += bytesconsumed;

    do
    {
        /* update buffer */
        UPDATE_BUFF_READ

        sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, buffer, bytes_in_buffer);

        /* update buffer indices */
        UPDATE_BUFF_IDX(frameInfo)

        if (frameInfo.error > 0)
        {
            error_handler("Error: %s\n",
            NeAACDecGetErrorMessage(frameInfo.error));
        }

        opt->progress_update((long)fileread, buffer_index);

        /* open the sound file now that the number of channels are known */
        if (first_time && !frameInfo.error)
        {
            if(opt->decode_mode == 0)
            {
                if (Set_WIN_Params (INVALID_FILEDESC, samplerate, SAMPLE_SIZE,
                                frameInfo.channels) < 0)
                {
                    error_handler("\nCan't access %s\n", "WAVE OUT");
                    END_BUFF
                    NeAACDecClose(hDecoder);
                    fclose(infile);
                    return (0);
                }
            }
            else
            {
                aufile = open_audio_file(sndfile, samplerate, frameInfo.channels,
                    opt->output_format, opt->file_type, aacChannelConfig2wavexChannelMask(&frameInfo));

                if (aufile == NULL)
                {
                    END_BUFF
                    NeAACDecClose(hDecoder);
                    fclose(infile);
                    return 0;
                }
            }
            first_time = 0;
        }

        if ((frameInfo.error == 0) && (frameInfo.samples > 0))
        {
            if(opt->decode_mode == 0)
                WIN_Play_Samples((short*)sample_buffer, frameInfo.channels*frameInfo.samples);
            else
                write_audio_file(aufile, sample_buffer, frameInfo.samples, 0);
        }

        if (buffer_index >= fileread)
            sample_buffer = NULL; /* to make sure it stops now */

        if(stop_decoding)
            break;

    } while (sample_buffer != NULL);

    NeAACDecClose(hDecoder);

    fclose(infile);

    if(opt->decode_mode == 0)
        WIN_Audio_close();
    else
    {
        if (!first_time)
            close_audio_file(aufile);
    }

    END_BUFF

    return frameInfo.error;
}
예제 #27
0
파일: player.c 프로젝트: dougt/mythpandora
/*	player thread; for every song a new thread is started
 *	@param aacPlayer structure
 *	@return NULL NULL NULL ...
 */
void *BarPlayerThread (void *data) {

	struct audioPlayer *player = data;
	char extraHeaders[25];
	void *ret = PLAYER_RET_OK;
	#ifdef ENABLE_FAAD
	NeAACDecConfigurationPtr conf;
	#endif
	WaitressReturn_t wRet = WAITRESS_RET_ERR;

	/* init handles */
	pthread_mutex_init (&player->pauseMutex, NULL);
	player->scale = computeReplayGainScale (player->gain);
	player->waith.data = (void *) player;
	/* extraHeaders will be initialized later */
	player->waith.extraHeaders = extraHeaders;

	switch (player->audioFormat) {
		#ifdef ENABLE_FAAD
		case PIANO_AF_AACPLUS:
			player->aacHandle = NeAACDecOpen();
			/* set aac conf */
			conf = NeAACDecGetCurrentConfiguration(player->aacHandle);
			conf->outputFormat = FAAD_FMT_16BIT;
		    conf->downMatrix = 1;
			NeAACDecSetConfiguration(player->aacHandle, conf);

			player->waith.callback = BarPlayerAACCb;
			break;
		#endif /* ENABLE_FAAD */

		#ifdef ENABLE_MAD
		case PIANO_AF_MP3:
		case PIANO_AF_MP3_HI:
			mad_stream_init (&player->mp3Stream);
			mad_frame_init (&player->mp3Frame);
			mad_synth_init (&player->mp3Synth);

			player->waith.callback = BarPlayerMp3Cb;
			break;
		#endif /* ENABLE_MAD */

		default:
		  printf("Unsupported audio format!\n");
			return PLAYER_RET_OK;
			break;
	}
	
	player->mode = PLAYER_INITIALIZED;

	/* This loop should work around song abortions by requesting the
	 * missing part of the song */
	do {
		snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n",
				player->bytesReceived);
		wRet = WaitressFetchCall (&player->waith);
	} while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT
			|| wRet == WAITRESS_RET_READ_ERR);

	switch (player->audioFormat) {
		#ifdef ENABLE_FAAD
		case PIANO_AF_AACPLUS:
			NeAACDecClose(player->aacHandle);
			break;
		#endif /* ENABLE_FAAD */

		#ifdef ENABLE_MAD
		case PIANO_AF_MP3:
		case PIANO_AF_MP3_HI:
			mad_synth_finish (&player->mp3Synth);
			mad_frame_finish (&player->mp3Frame);
			mad_stream_finish (&player->mp3Stream);
			break;
		#endif /* ENABLE_MAD */

		default:
			/* this should never happen: thread is aborted above */
			break;
	}
	if (player->aoError) {
		ret = (void *) PLAYER_RET_ERR;
	}

	if (player->audioOutDevice) 
	  ao_close(player->audioOutDevice);
	WaitressFree (&player->waith);
	#ifdef ENABLE_FAAD
	if (player->sampleSize != NULL) {
		free (player->sampleSize);
	}
	#endif /* ENABLE_FAAD */
	pthread_mutex_destroy (&player->pauseMutex);

	player->mode = PLAYER_FINISHED_PLAYBACK;

	return ret;
}
예제 #28
0
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;
  }
예제 #29
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    /* Note that when dealing with QuickTime/MPEG4 files, terminology is
     * a bit confusing. Files with sound are split up in chunks, where
     * each chunk contains one or more samples. Each sample in turn
     * contains a number of "sound samples" (the kind you refer to with
     * the sampling frequency).
     */
    size_t n;
    demux_res_t demux_res;
    stream_t input_stream;
    uint32_t sound_samples_done;
    uint32_t elapsed_time;
    int file_offset;
    int framelength;
    int lead_trim = 0;
    unsigned int frame_samples;
    unsigned int i;
    unsigned char* buffer;
    NeAACDecFrameInfo frame_info;
    NeAACDecHandle decoder;
    int err;
    uint32_t seek_idx = 0;
    uint32_t s = 0;
    uint32_t sbr_fac = 1;
    unsigned char c = 0;
    void *ret;
    intptr_t param;
    bool empty_first_frame = false;

    /* Clean and initialize decoder structures */
    memset(&demux_res , 0, sizeof(demux_res));
    if (codec_init()) {
        LOGF("FAAD: Codec init error\n");
        return CODEC_ERROR;
    }

    file_offset = ci->id3->offset;

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    stream_create(&input_stream,ci);

    ci->seek_buffer(ci->id3->first_frame_offset);

    /* if qtmovie_read returns successfully, the stream is up to
     * the movie data, which can be used directly by the decoder */
    if (!qtmovie_read(&input_stream, &demux_res)) {
        LOGF("FAAD: File init error\n");
        return CODEC_ERROR;
    }

    /* initialise the sound converter */
    decoder = NeAACDecOpen();

    if (!decoder) {
        LOGF("FAAD: Decode open error\n");
        return CODEC_ERROR;
    }

    NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
    conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
    NeAACDecSetConfiguration(decoder, conf);

    err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c);
    if (err) {
        LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
        return CODEC_ERROR;
    }

#ifdef SBR_DEC
    /* Check for need of special handling for seek/resume and elapsed time. */
    if (ci->id3->needs_upsampling_correction) {
        sbr_fac = 2;
    } else {
        sbr_fac = 1;
    }
#endif

    i = 0;
    
    if (file_offset > 0) {
        /* Resume the desired (byte) position. Important: When resuming SBR
         * upsampling files the resulting sound_samples_done must be expanded 
         * by a factor of 2. This is done via using sbr_fac. */
        if (m4a_seek_raw(&demux_res, &input_stream, file_offset,
                          &sound_samples_done, (int*) &i)) {
            sound_samples_done *= sbr_fac;
        } else {
            sound_samples_done = 0;
        }
        NeAACDecPostSeekReset(decoder, i);
    } else {
        sound_samples_done = 0;
    }

    elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
    ci->set_elapsed(elapsed_time);
    
    if (i == 0) 
    {
        lead_trim = ci->id3->lead_trim;
    }

    /* The main decoding loop */
    while (i < demux_res.num_sample_byte_sizes) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {
            /* Seek to the desired time position. Important: When seeking in SBR
             * upsampling files the seek_time must be divided by 2 when calling 
             * m4a_seek and the resulting sound_samples_done must be expanded 
             * by a factor 2. This is done via using sbr_fac. */
            if (m4a_seek(&demux_res, &input_stream,
                          (param/10/sbr_fac)*(ci->id3->frequency/100),
                          &sound_samples_done, (int*) &i)) {
                sound_samples_done *= sbr_fac;
                elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
                ci->set_elapsed(elapsed_time);
                seek_idx = 0;

                if (i == 0) 
                {
                    lead_trim = ci->id3->lead_trim;
                }
            }
            NeAACDecPostSeekReset(decoder, i);
            ci->seek_complete();
        }

        /* There can be gaps between chunks, so skip ahead if needed. It
         * doesn't seem to happen much, but it probably means that a 
         * "proper" file can have chunks out of order. Why one would want
         * that an good question (but files with gaps do exist, so who 
         * knows?), so we don't support that - for now, at least.
         */
        file_offset = m4a_check_sample_offset(&demux_res, i, &seek_idx);

        if (file_offset > ci->curpos)
        {
            ci->advance_buffer(file_offset - ci->curpos);
        }
        else if (file_offset == 0)
        {
            LOGF("AAC: get_sample_offset error\n");
            return CODEC_ERROR;
        }
        
        /* Request the required number of bytes from the input buffer */
        buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);

        /* Decode one block - returned samples will be host-endian */
        ret = NeAACDecDecode(decoder, &frame_info, buffer, n);

        /* NeAACDecDecode may sometimes return NULL without setting error. */
        if (ret == NULL || frame_info.error > 0) {
            LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
            return CODEC_ERROR;
        }

        /* Advance codec buffer (no need to call set_offset because of this) */
        ci->advance_buffer(frame_info.bytesconsumed);

        /* Output the audio */
        ci->yield();
        
        frame_samples = frame_info.samples >> 1;

        if (empty_first_frame)
        {
            /* Remove the first frame from lead_trim, under the assumption
             * that it had the same size as this frame
             */
            empty_first_frame = false;
            lead_trim -= frame_samples;

            if (lead_trim < 0)
            {
                lead_trim = 0;
            }
        }

        /* Gather number of samples for the decoded frame. */
        framelength = frame_samples - lead_trim;
        
        if (i == demux_res.num_sample_byte_sizes - 1)
        {
            // Size of the last frame
            const uint32_t sample_duration = (demux_res.num_time_to_samples > 0) ?
                demux_res.time_to_sample[demux_res.num_time_to_samples - 1].sample_duration :
                frame_samples;

            /* Currently limited to at most one frame of tail_trim.
             * Seems to be enough.
             */
            if (ci->id3->tail_trim == 0 && sample_duration < frame_samples)
            {
                /* Subtract lead_trim just in case we decode a file with only
                 * one audio frame with actual data (lead_trim is usually zero
                 * here).
                 */
                framelength = sample_duration - lead_trim;
            }
            else
            {
                framelength -= ci->id3->tail_trim;
            }
        }

        if (framelength > 0)
        {
            ci->pcmbuf_insert(&decoder->time_out[0][lead_trim],
                              &decoder->time_out[1][lead_trim],
                              framelength);
            sound_samples_done += framelength;
            /* Update the elapsed-time indicator */
            elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
            ci->set_elapsed(elapsed_time);
        }

        if (lead_trim > 0)
        {
            /* frame_info.samples can be 0 for frame 0. We still want to
             * remove it from lead_trim, so do that during frame 1.
             */
            if (0 == i && 0 == frame_info.samples)
            {
                empty_first_frame = true;
            }

            lead_trim -= frame_samples;

            if (lead_trim < 0)
            {
                lead_trim = 0;
            }
        }

        ++i;
    }

    LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done);
    return CODEC_OK;
}