Пример #1
0
static int ffmpeg_decode(struct ffmpeg_file *file)
{
    if (file->pkt_decoded >= file->pkt->size) {
        int e = av_read_frame(file->format, file->pkt);
        if (e < 0) {
            return e;
        }
        file->pkt_decoded = 0;
    }

    int got_frame = 0;
    int e = avcodec_decode_audio4(file->codec, file->frame, &got_frame,
            file->pkt);
    if (e < 0) {
        return e;
    }
    if (!got_frame) {
        return 0;
    }
    file->pkt_decoded += e;

    AVFrame *frame = file->frame;
    int delay_nsamples = swr_get_delay(file->swr, file->codec->sample_rate);
    int dst_nsamples = av_rescale_rnd(delay_nsamples + frame->nb_samples,
            file->sample_rate, file->codec->sample_rate, AV_ROUND_UP);
    if (file->buf_nsamples < dst_nsamples) {
        if (file->buf) {
            av_freep(&file->buf[0]);
        }
        av_freep(&file->buf);
        int e = av_samples_alloc_array_and_samples(&file->buf, NULL,
                file->channels, file->sample_rate, file->sample_fmt, 0);
        if (e < 0) {
            return e;
        }
        file->buf_nsamples = dst_nsamples;
    }

    int ns = swr_convert(file->swr, file->buf, dst_nsamples,
            (const uint8_t**) frame->data, frame->nb_samples);
    int nb = av_samples_get_buffer_size(NULL, file->channels,
            ns, file->sample_fmt, 1);
    if (nb < 0) {
        return nb;
    }
    file->buf_len = nb;
    file->buf_offset = 0;
    if (file->frame->pts > 0) {
        file->time = file->frame->pts;
    }

    return nb;
}
Пример #2
0
static int config_output(AVFilterLink *outlink)
{
    AVFilterContext *ctx = outlink->src;
    AudioEchoContext *s = ctx->priv;
    float volume = 1.0;
    int i;

    for (i = 0; i < s->nb_echoes; i++) {
        s->samples[i] = s->delay[i] * outlink->sample_rate / 1000.0;
        s->max_samples = FFMAX(s->max_samples, s->samples[i]);
        volume += s->decay[i];
    }

    if (s->max_samples <= 0) {
        av_log(ctx, AV_LOG_ERROR, "Nothing to echo - missing delay samples.\n");
        return AVERROR(EINVAL);
    }
    s->fade_out = s->max_samples;

    if (volume * s->in_gain * s->out_gain > 1.0)
        av_log(ctx, AV_LOG_WARNING,
               "out_gain %f can cause saturation of output\n", s->out_gain);

    switch (outlink->format) {
    case AV_SAMPLE_FMT_DBLP:
        s->echo_samples = echo_samples_dblp;
        break;
    case AV_SAMPLE_FMT_FLTP:
        s->echo_samples = echo_samples_fltp;
        break;
    case AV_SAMPLE_FMT_S16P:
        s->echo_samples = echo_samples_s16p;
        break;
    case AV_SAMPLE_FMT_S32P:
        s->echo_samples = echo_samples_s32p;
        break;
    }


    if (s->delayptrs)
        av_freep(&s->delayptrs[0]);
    av_freep(&s->delayptrs);

    return av_samples_alloc_array_and_samples(&s->delayptrs, NULL,
            outlink->channels,
            s->max_samples,
            outlink->format, 0);
}
Пример #3
0
int create_channel_data( AVFrame *pFrame )
{
        //printf( "In Create Channel data : Thread 1\n" );
        int dst_nb_channels = av_get_channel_layout_nb_channels
                              ( AV_CH_LAYOUT_STEREO );
        int dst_linesize;
        int delay = swr_get_delay( gMedia->pSwrContext,
                                   pFrame->sample_rate );
        int dst_nb_samples = av_rescale_rnd( pFrame->nb_samples + delay,
                                             pFrame->sample_rate,
                                             pFrame->sample_rate,
                                             AV_ROUND_UP );
        //printf("Destination channels = %d\n",dst_nb_channels);
        //printf("Destination samples = %d\n",dst_nb_samples);
        int error_check = av_samples_alloc_array_and_samples
                          ( &gMedia->audio_buf,
                            &dst_linesize,
                            dst_nb_channels,
                            dst_nb_samples,
                            AV_SAMPLE_FMT_FLT,
                            1 );

        if ( error_check < 0 ) {
                fprintf( stderr, "Could not allocate destination samples\n" );
        }

        int data_size = av_samples_get_buffer_size
                        ( NULL,
                          pFrame->channels,
                          pFrame->nb_samples,
                          pFrame->format,
                          0 );
        /*      printf("Number of samples = %d\n",pFrame->nb_samples);
                printf("Number of bytes = %d\n",pFrame->nb_samples*2*4);
                printf("Linesize per channel is %d\n",pFrame->linesize[0]);
                printf("Calculated datasize is %d\n",data_size);
        */
        swr_convert( gMedia->pSwrContext,
                     ( uint8_t ** )( gMedia->audio_buf ) ,
                     pFrame->nb_samples,
                     ( const uint8_t ** )pFrame->data,
                     pFrame->nb_samples );
        return data_size;
}
Пример #4
0
static int config_input(AVFilterLink *inlink)
{
    AVFilterContext *ctx = inlink->dst;
    FlangerContext *s = ctx->priv;

    s->max_samples = (s->delay_min + s->delay_depth) * inlink->sample_rate + 2.5;
    s->lfo_length  = inlink->sample_rate / s->speed;
    s->delay_last  = av_calloc(inlink->channels, sizeof(*s->delay_last));
    s->lfo         = av_calloc(s->lfo_length, sizeof(*s->lfo));
    if (!s->lfo || !s->delay_last)
        return AVERROR(ENOMEM);

    ff_generate_wave_table(s->wave_shape, AV_SAMPLE_FMT_FLT, s->lfo, s->lfo_length,
                           floor(s->delay_min * inlink->sample_rate + 0.5),
                           s->max_samples - 2., 3 * M_PI_2);

    return av_samples_alloc_array_and_samples(&s->delay_buffer, NULL,
                                              inlink->channels, s->max_samples,
                                              inlink->format, 0);
}
Пример #5
0
int AudioEncode::open(AVCodecID codec_id, int flags)
{
    mCodec = avcodec_find_encoder(codec_id);
    if (!mCodec) {
        fprintf(stderr, "Couldn't find encoder: %s\n", avcodec_get_name(codec_id));
        return -1;
    }

    mCodecCtx = avcodec_alloc_context3(mCodec);
    if (!mCodecCtx) {
        fprintf(stderr, "allocate codec context failed.\n");
        return -1;
    }

    mFlags |= flags;
    mChannelNum = av_get_channel_layout_nb_channels(mChannelLayout);
    mMaxSamplesCount = mCodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 :
                       mCodecCtx->frame_size;
    mFifo = av_audio_fifo_alloc(mSampleFmt, mChannelNum, mMaxSamplesCount);

    av_samples_alloc_array_and_samples(&mData, NULL, mChannelNum,
                                       mMaxSamplesCount, mSampleFmt, 0);
    return 0;
}
Пример #6
0
int procAudioResampling(AVCodecContext * audio_dec_ctx,
	AVFrame * pAudioDecodeFrame,
	int out_sample_fmt,
	int out_channels,
	int out_sample_rate,
	uint8_t * audio_chunk)
{
	SwrContext * swr_ctx = NULL;
	int data_size = 0;
	int ret = 0;
	int64_t src_ch_layout = audio_dec_ctx->channel_layout;
	int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
	int dst_nb_channels = 0;
	int dst_linesize = 0;
	int src_nb_samples = 0;
	int dst_nb_samples = 0;
	int max_dst_nb_samples = 0;
	uint8_t **dst_data = NULL;
	int resampled_data_size = 0;

	swr_ctx = swr_alloc();
	if (!swr_ctx)
	{
		LOGD("swr_alloc error \n");
		return -1;
	}

	src_ch_layout = (audio_dec_ctx->channels ==
		av_get_channel_layout_nb_channels(audio_dec_ctx->channel_layout)) ?
		audio_dec_ctx->channel_layout :
		av_get_default_channel_layout(audio_dec_ctx->channels);

	if (out_channels == 1)
	{
		dst_ch_layout = AV_CH_LAYOUT_MONO;
		//LOGD("dst_ch_layout: AV_CH_LAYOUT_MONO\n");
	}
	else if (out_channels == 2)
	{
		dst_ch_layout = AV_CH_LAYOUT_STEREO;
		//LOGD("dst_ch_layout: AV_CH_LAYOUT_STEREO\n");
	}
	else
	{
		dst_ch_layout = AV_CH_LAYOUT_SURROUND;
		//LOGD("dst_ch_layout: AV_CH_LAYOUT_SURROUND\n");
	}

	if (src_ch_layout <= 0)
	{
		LOGD("src_ch_layout error \n");
		return -1;
	}

	src_nb_samples = pAudioDecodeFrame->nb_samples;
	if (src_nb_samples <= 0)
	{
		LOGD("src_nb_samples error \n");
		return -1;
	}

	av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
	av_opt_set_int(swr_ctx, "in_sample_rate", audio_dec_ctx->sample_rate, 0);
	av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);

	av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
	av_opt_set_int(swr_ctx, "out_sample_rate", out_sample_rate, 0);
	av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", (AVSampleFormat)out_sample_fmt, 0);

	if ((ret = swr_init(swr_ctx)) < 0) {
		LOGD("Failed to initialize the resampling context\n");
		return -1;
	}

	max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples,
		out_sample_rate, audio_dec_ctx->sample_rate, AV_ROUND_UP);
	if (max_dst_nb_samples <= 0)
	{
		LOGD("av_rescale_rnd error \n");
		return -1;
	}

	dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
	ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
		dst_nb_samples, (AVSampleFormat)out_sample_fmt, 0);
	if (ret < 0)
	{
		LOGD("av_samples_alloc_array_and_samples error \n");
		return -1;
	}


	dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, audio_dec_ctx->sample_rate) +
		src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate, AV_ROUND_UP);
	if (dst_nb_samples <= 0)
	{
		LOGD("av_rescale_rnd error \n");
		return -1;
	}
	if (dst_nb_samples > max_dst_nb_samples)
	{
		av_free(dst_data[0]);
		ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
			dst_nb_samples, (AVSampleFormat)out_sample_fmt, 1);
		max_dst_nb_samples = dst_nb_samples;
	}

	if (swr_ctx)
	{
		ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
			(const uint8_t **)pAudioDecodeFrame->data, pAudioDecodeFrame->nb_samples);
		if (ret < 0)
		{
			LOGD("swr_convert error \n");
			return -1;
		}

		resampled_data_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
			ret, (AVSampleFormat)out_sample_fmt, 1);
		if (resampled_data_size < 0)
		{
			LOGD("av_samples_get_buffer_size error \n");
			return -1;
		}
	}
	else
	{
		LOGD("swr_ctx null error \n");
		return -1;
	}

	//LOGD("resampled_data_size:%d",resampled_data_size);
	memcpy(audio_chunk, dst_data[0], resampled_data_size);

	if (dst_data)
	{
		av_freep(&dst_data[0]);
	}
	av_freep(&dst_data);
	dst_data = NULL;

	if (swr_ctx)
	{
		swr_free(&swr_ctx);
	}
	return resampled_data_size;
}
Пример #7
0
bool FFMpegLoader::open(qint64 &position) {
	if (!AbstractFFMpegLoader::open(position)) {
		return false;
	}

	int res = 0;
	char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };

	auto codecParams = fmtContext->streams[streamId]->codecpar;

	codecContext = avcodec_alloc_context3(nullptr);
	if (!codecContext) {
		LOG(("Audio Error: Unable to avcodec_alloc_context3 for file '%1', data size '%2'").arg(_file.name()).arg(_data.size()));
		return false;
	}
	if ((res = avcodec_parameters_to_context(codecContext, codecParams)) < 0) {
		LOG(("Audio Error: Unable to avcodec_parameters_to_context for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
		return false;
	}
	av_codec_set_pkt_timebase(codecContext, fmtContext->streams[streamId]->time_base);
	av_opt_set_int(codecContext, "refcounted_frames", 1, 0);

	if ((res = avcodec_open2(codecContext, codec, 0)) < 0) {
		LOG(("Audio Error: Unable to avcodec_open2 for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
		return false;
	}

	auto layout = codecParams->channel_layout;
	if (!layout) {
		auto channelsCount = codecParams->channels;
		switch (channelsCount) {
		case 1: layout = AV_CH_LAYOUT_MONO; break;
		case 2: layout = AV_CH_LAYOUT_STEREO; break;
		default: LOG(("Audio Error: Unknown channel layout for %1 channels.").arg(channelsCount)); break;
		}
	}
	inputFormat = codecContext->sample_fmt;
	switch (layout) {
	case AV_CH_LAYOUT_MONO:
		switch (inputFormat) {
		case AV_SAMPLE_FMT_U8:
		case AV_SAMPLE_FMT_U8P: fmt = AL_FORMAT_MONO8; sampleSize = 1; break;
		case AV_SAMPLE_FMT_S16:
		case AV_SAMPLE_FMT_S16P: fmt = AL_FORMAT_MONO16; sampleSize = sizeof(uint16); break;
		default:
			sampleSize = -1; // convert needed
		break;
		}
	break;
	case AV_CH_LAYOUT_STEREO:
		switch (inputFormat) {
		case AV_SAMPLE_FMT_U8: fmt = AL_FORMAT_STEREO8; sampleSize = 2; break;
		case AV_SAMPLE_FMT_S16: fmt = AL_FORMAT_STEREO16; sampleSize = 2 * sizeof(uint16); break;
		default:
			sampleSize = -1; // convert needed
		break;
		}
	break;
	default:
		sampleSize = -1; // convert needed
	break;
	}
	if (_samplesFrequency != 44100 && _samplesFrequency != 48000) {
		sampleSize = -1; // convert needed
	}

	if (sampleSize < 0) {
		swrContext = swr_alloc();
		if (!swrContext) {
			LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(_file.name()).arg(_data.size()));
			return false;
		}
		int64_t src_ch_layout = layout, dst_ch_layout = AudioToChannelLayout;
		srcRate = _samplesFrequency;
		AVSampleFormat src_sample_fmt = inputFormat, dst_sample_fmt = AudioToFormat;
		dstRate = (_samplesFrequency != 44100 && _samplesFrequency != 48000) ? Media::Player::kDefaultFrequency : _samplesFrequency;

		av_opt_set_int(swrContext, "in_channel_layout", src_ch_layout, 0);
		av_opt_set_int(swrContext, "in_sample_rate", srcRate, 0);
		av_opt_set_sample_fmt(swrContext, "in_sample_fmt", src_sample_fmt, 0);
		av_opt_set_int(swrContext, "out_channel_layout", dst_ch_layout, 0);
		av_opt_set_int(swrContext, "out_sample_rate", dstRate, 0);
		av_opt_set_sample_fmt(swrContext, "out_sample_fmt", dst_sample_fmt, 0);

		if ((res = swr_init(swrContext)) < 0) {
			LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
			return false;
		}

		sampleSize = AudioToChannels * sizeof(short);
		_samplesFrequency = dstRate;
		_samplesCount = av_rescale_rnd(_samplesCount, dstRate, srcRate, AV_ROUND_UP);
		position = av_rescale_rnd(position, dstRate, srcRate, AV_ROUND_DOWN);
		fmt = AL_FORMAT_STEREO16;

		maxResampleSamples = av_rescale_rnd(AVBlockSize / sampleSize, dstRate, srcRate, AV_ROUND_UP);
		if ((res = av_samples_alloc_array_and_samples(&dstSamplesData, 0, AudioToChannels, maxResampleSamples, AudioToFormat, 0)) < 0) {
			LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
			return false;
		}
	}
	if (position) {
		int64 ts = (position * fmtContext->streams[streamId]->time_base.den) / (_samplesFrequency * fmtContext->streams[streamId]->time_base.num);
		if (av_seek_frame(fmtContext, streamId, ts, AVSEEK_FLAG_ANY) < 0) {
			if (av_seek_frame(fmtContext, streamId, ts, 0) < 0) {
			}
		}
	}

	return true;
}
Пример #8
0
static void open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
    AVCodecContext *c;
    int ret;

    c = st->codec;

    /* allocate and init a re-usable frame */
    audio_frame = av_frame_alloc();
    if (!audio_frame) {
        fprintf(stderr, "Could not allocate audio frame\n");
        exit(1);
    }

    /* open it */
    ret = avcodec_open2(c, codec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
        exit(1);
    }

    /* init signal generator */
    t     = 0;
    tincr = 2 * M_PI * 110.0 / c->sample_rate;
    /* increment frequency by 110 Hz per second */
    tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;

    src_nb_samples = c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE ?
        10000 : c->frame_size;

    ret = av_samples_alloc_array_and_samples(&src_samples_data, &src_samples_linesize, c->channels,
                                             src_nb_samples, AV_SAMPLE_FMT_S16, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate source samples\n");
        exit(1);
    }

    /* compute the number of converted samples: buffering is avoided
     * ensuring that the output buffer will contain at least all the
     * converted input samples */
    max_dst_nb_samples = src_nb_samples;

    /* create resampler context */
    if (c->sample_fmt != AV_SAMPLE_FMT_S16) {
        swr_ctx = swr_alloc();
        if (!swr_ctx) {
            fprintf(stderr, "Could not allocate resampler context\n");
            exit(1);
        }

        /* set options */
        av_opt_set_int       (swr_ctx, "in_channel_count",   c->channels,       0);
        av_opt_set_int       (swr_ctx, "in_sample_rate",     c->sample_rate,    0);
        av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt",      AV_SAMPLE_FMT_S16, 0);
        av_opt_set_int       (swr_ctx, "out_channel_count",  c->channels,       0);
        av_opt_set_int       (swr_ctx, "out_sample_rate",    c->sample_rate,    0);
        av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt",     c->sample_fmt,     0);

        /* initialize the resampling context */
        if ((ret = swr_init(swr_ctx)) < 0) {
            fprintf(stderr, "Failed to initialize the resampling context\n");
            exit(1);
        }

        ret = av_samples_alloc_array_and_samples(&dst_samples_data, &dst_samples_linesize, c->channels,
                                                 max_dst_nb_samples, c->sample_fmt, 0);
        if (ret < 0) {
            fprintf(stderr, "Could not allocate destination samples\n");
            exit(1);
        }
    } else {
        dst_samples_data = src_samples_data;
    }
    dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, max_dst_nb_samples,
                                                  c->sample_fmt, 0);
}
int audioResampling(AVCodecContext *audio_dec_ctx, AVFrame *pAudioDecodeFrame,
                    int out_sample_fmt, int out_channels, int out_sample_rate, char *out_buf) {
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12");
    SwrContext *swr_ctx = NULL;
    int data_size = 0;
    int ret = 0;
    int64_t src_ch_layout = AV_CH_LAYOUT_STEREO; //初始化这样根据不同文件做调整
    int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO; //这里设定ok
    int dst_nb_channels = 0;
    int dst_linesize = 0;
    int src_nb_samples = 0;
    int dst_nb_samples = 0;
    int max_dst_nb_samples = 0;
    uint8_t **dst_data = NULL;
    int resampled_data_size = 0;
    //重新采样
    if (swr_ctx) {
        swr_free(&swr_ctx);
    }
    swr_ctx = swr_alloc();
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12-1");
    if (!swr_ctx) {
        printf("swr_alloc error \n");
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream13");
        return -1;
    }

    src_ch_layout = (audio_dec_ctx->channel_layout &&
                     audio_dec_ctx->channels ==
                     av_get_channel_layout_nb_channels(audio_dec_ctx->channel_layout)) ?
                    audio_dec_ctx->channel_layout :
                    av_get_default_channel_layout(audio_dec_ctx->channels);
    if (out_channels == 1) {
        dst_ch_layout = AV_CH_LAYOUT_MONO;
    }
    else if (out_channels == 2) {
        dst_ch_layout = AV_CH_LAYOUT_STEREO;
    }
    else {
        //可扩展
    }
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12-2");
    if (src_ch_layout <= 0) {
        printf("src_ch_layout error \n");
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream14");
        return -1;
    }
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12-3");
    src_nb_samples = pAudioDecodeFrame->nb_samples;
    if (src_nb_samples <= 0) {
        printf("src_nb_samples error \n");
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream15");
        return -1;
    }

    /* set options */
    av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
    av_opt_set_int(swr_ctx, "in_sample_rate", audio_dec_ctx->sample_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);

    av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
    av_opt_set_int(swr_ctx, "out_sample_rate", out_sample_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", (AVSampleFormat) out_sample_fmt, 0);
    swr_init(swr_ctx);
    max_dst_nb_samples = dst_nb_samples =
            av_rescale_rnd(src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate,
                           AV_ROUND_UP);
    if (max_dst_nb_samples <= 0) {
        printf("av_rescale_rnd error \n");
        return -1;
    }

    dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
    ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
                                             dst_nb_samples, (AVSampleFormat) out_sample_fmt, 0);
    if (ret < 0) {
        printf("av_samples_alloc_array_and_samples error \n");
        return -1;
    }


    dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, audio_dec_ctx->sample_rate) +
                                    src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate,
                                    AV_ROUND_UP);
    if (dst_nb_samples <= 0) {
        return -1;
    }
    if (dst_nb_samples > max_dst_nb_samples) {
        av_free(dst_data[0]);
        ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
                               dst_nb_samples, (AVSampleFormat) out_sample_fmt, 1);
        max_dst_nb_samples = dst_nb_samples;
    }
    data_size = av_samples_get_buffer_size(NULL, audio_dec_ctx->channels,
                                           pAudioDecodeFrame->nb_samples,
                                           audio_dec_ctx->sample_fmt, 1);
    if (data_size <= 0) {
        return -1;
    }
    resampled_data_size = data_size;
    if (swr_ctx) {
        ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
                          (const uint8_t **) pAudioDecodeFrame->data,
                          pAudioDecodeFrame->nb_samples);
        if (ret <= 0) {
            return -1;
        }

        resampled_data_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                         ret, (AVSampleFormat) out_sample_fmt, 1);
        if (resampled_data_size <= 0) {
            return -1;
        }
    }
    else {
        return -1;
    }
    //将值返回去
    memcpy(out_buf, dst_data[0], resampled_data_size);
    if (dst_data) {
        av_freep(&dst_data[0]);
    }
    av_freep(&dst_data);
    dst_data = NULL;

    if (swr_ctx) {
        swr_free(&swr_ctx);
    }
    return resampled_data_size;
}
	const CGEAudioFrameBufferData* CGEVideoDecodeHandler::getCurrentAudioFrame()
	{
		if(m_context->pSwrCtx == nullptr)
		{
			if(m_context->pAudioStream->codec->sample_fmt != AV_SAMPLE_FMT_S16)
			{
				m_context->pSwrCtx = swr_alloc();
				if(m_context->pSwrCtx == nullptr)
				{
					CGE_LOG_ERROR("Allocate resampler context failed!\n");
					return nullptr;
				}

				auto ctx = m_context->pSwrCtx;
				auto c = m_context->pAudioStream->codec;

				av_opt_set_int       (ctx, "in_channel_count",   c->channels,       0);
				av_opt_set_int       (ctx, "in_sample_rate",     c->sample_rate,    0);
				av_opt_set_sample_fmt(ctx, "in_sample_fmt",      c->sample_fmt, 0);
				av_opt_set_int       (ctx, "out_channel_count",  1,       0);
				av_opt_set_int       (ctx, "out_sample_rate",    c->sample_rate,    0);
				av_opt_set_sample_fmt(ctx, "out_sample_fmt",     AV_SAMPLE_FMT_S16,     0);

				int ret;

				if ((ret = swr_init(ctx)) < 0)
				{
					CGE_LOG_ERROR("Failed to initialize the resampling context: %d\n", ret);
					return nullptr;
				}

				m_context->maxDstNbSamples = c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE ?
			10000 : c->frame_size;

				ret = av_samples_alloc_array_and_samples(&m_context->dstSampleData, &m_context->dstSamplesLinesize, c->channels, m_context->maxDstNbSamples, c->sample_fmt, 0);

				if (ret < 0)
				{
					CGE_LOG_ERROR("Could not allocate destination samples\n");
					return nullptr;
				}

				m_context->dstSamplesSize = av_samples_get_buffer_size(NULL, c->channels, m_context->maxDstNbSamples, c->sample_fmt, 0);

			}
			else
			{
				CGE_LOG_ERROR("errorxxxx");
			}
		}

		int ret = swr_convert(m_context->pSwrCtx, m_context->dstSampleData, m_context->dstSamplesSize, (const uint8_t**)m_context->pAudioFrame->data, m_context->pAudioFrame->nb_samples);

		if(ret <= 0)
			return nullptr;

		m_cachedAudioFrame.timestamp = av_frame_get_best_effort_timestamp(m_context->pAudioFrame);
		m_cachedAudioFrame.data = m_context->dstSampleData[0];
		m_cachedAudioFrame.nbSamples = m_context->pAudioFrame->nb_samples;
		m_cachedAudioFrame.channels = 1;//av_frame_get_channels(m_context->pAudioFrame);
		m_cachedAudioFrame.bytesPerSample = 2;
		m_cachedAudioFrame.linesize = m_context->dstSamplesSize;
		m_cachedAudioFrame.format = CGE_SAMPLE_FMT_S16;
		return &m_cachedAudioFrame;
	}
bool ChildFFMpegLoader::open(qint64 &position) {
	int res = 0;
	char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };

	uint64_t layout = _parentData->context->channel_layout;
	_inputFormat = _parentData->context->sample_fmt;
	switch (layout) {
	case AV_CH_LAYOUT_MONO:
		switch (_inputFormat) {
		case AV_SAMPLE_FMT_U8:
		case AV_SAMPLE_FMT_U8P: _format = AL_FORMAT_MONO8; _sampleSize = 1; break;
		case AV_SAMPLE_FMT_S16:
		case AV_SAMPLE_FMT_S16P: _format = AL_FORMAT_MONO16; _sampleSize = sizeof(uint16); break;
		default:
			_sampleSize = -1; // convert needed
		break;
		}
	break;
	case AV_CH_LAYOUT_STEREO:
		switch (_inputFormat) {
		case AV_SAMPLE_FMT_U8: _format = AL_FORMAT_STEREO8; _sampleSize = 2; break;
		case AV_SAMPLE_FMT_S16: _format = AL_FORMAT_STEREO16; _sampleSize = 2 * sizeof(uint16); break;
		default:
			_sampleSize = -1; // convert needed
		break;
		}
	break;
	default:
		_sampleSize = -1; // convert needed
	break;
	}
	if (_parentData->frequency != 44100 && _parentData->frequency != 48000) {
		_sampleSize = -1; // convert needed
	}

	if (_sampleSize < 0) {
		_swrContext = swr_alloc();
		if (!_swrContext) {
			LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(file.name()).arg(data.size()));
			return false;
		}
		int64_t src_ch_layout = layout, dst_ch_layout = AudioToChannelLayout;
		_srcRate = _parentData->frequency;
		AVSampleFormat src_sample_fmt = _inputFormat, dst_sample_fmt = AudioToFormat;
		_dstRate = (_parentData->frequency != 44100 && _parentData->frequency != 48000) ? AudioVoiceMsgFrequency : _parentData->frequency;

		av_opt_set_int(_swrContext, "in_channel_layout", src_ch_layout, 0);
		av_opt_set_int(_swrContext, "in_sample_rate", _srcRate, 0);
		av_opt_set_sample_fmt(_swrContext, "in_sample_fmt", src_sample_fmt, 0);
		av_opt_set_int(_swrContext, "out_channel_layout", dst_ch_layout, 0);
		av_opt_set_int(_swrContext, "out_sample_rate", _dstRate, 0);
		av_opt_set_sample_fmt(_swrContext, "out_sample_fmt", dst_sample_fmt, 0);

		if ((res = swr_init(_swrContext)) < 0) {
			LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
			return false;
		}

		_sampleSize = AudioToChannels * sizeof(short);
		_parentData->frequency = _dstRate;
		_parentData->length = av_rescale_rnd(_parentData->length, _dstRate, _srcRate, AV_ROUND_UP);
		position = av_rescale_rnd(position, _dstRate, _srcRate, AV_ROUND_DOWN);
		_format = AL_FORMAT_STEREO16;

		_maxResampleSamples = av_rescale_rnd(AVBlockSize / _sampleSize, _dstRate, _srcRate, AV_ROUND_UP);
		if ((res = av_samples_alloc_array_and_samples(&_dstSamplesData, 0, AudioToChannels, _maxResampleSamples, AudioToFormat, 0)) < 0) {
			LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
			return false;
		}
	}

	return true;
}
Пример #12
0
int decode_frame_from_packet(State *state, AVPacket *aPacket, int *frame_size_ptr, int from_thread)
{
	int n;
	int16_t *samples;
	AVPacket *pkt = aPacket;
    AVFrame *decoded_frame = NULL;
    int got_frame = 0;
    
	int64_t src_ch_layout, dst_ch_layout;
	int src_rate, dst_rate;
	uint8_t **src_data = NULL, **dst_data = NULL;
	int src_nb_channels = 0, dst_nb_channels = 0;
	int src_linesize, dst_linesize;
	int src_nb_samples, dst_nb_samples, max_dst_nb_samples;
	enum AVSampleFormat src_sample_fmt, dst_sample_fmt;
	int dst_bufsize;
	const char *fmt;
	struct SwrContext *swr_ctx;
	double t;
    int ret;

    if (aPacket->stream_index == state->audio_stream) {
        	
    	if (!decoded_frame) {
    		if (!(decoded_frame = avcodec_alloc_frame())) {
    			__android_log_print(ANDROID_LOG_INFO, "TAG", "Could not allocate audio frame\n");
    	        return -2;
    		}
    	}
    	
    	if (avcodec_decode_audio4(state->audio_st->codec, decoded_frame, &got_frame, aPacket) < 0) {
    		__android_log_print(ANDROID_LOG_ERROR, "TAG", "avcodec_decode_audio4() decoded no frame");
    		return -2;
    	}
    	
    	int data_size = 0;
    	
    	if (got_frame) {
    		/* if a frame has been decoded, output it */
    		data_size = av_samples_get_buffer_size(NULL, state->audio_st->codec->channels,
    	    		decoded_frame->nb_samples,
    	    		state->audio_st->codec->sample_fmt, 1);
    	} else {
    		*frame_size_ptr = 0;
    	    return 0;
    	}
    	
        if (decoded_frame->format != AV_SAMPLE_FMT_S16) {
            src_nb_samples = decoded_frame->nb_samples;
            src_linesize = (int) decoded_frame->linesize;
            src_data = decoded_frame->data;
            
            if (decoded_frame->channel_layout == 0) {
            	decoded_frame->channel_layout = av_get_default_channel_layout(decoded_frame->channels);
            }
            
            /* create resampler context */
            swr_ctx = swr_alloc();
            if (!swr_ctx) {
            	//fprintf(stderr, "Could not allocate resampler context\n");
                //ret = AVERROR(ENOMEM);
                //goto end;
            }
            
            src_rate = decoded_frame->sample_rate;
            dst_rate = decoded_frame->sample_rate;
            src_ch_layout = decoded_frame->channel_layout;
            dst_ch_layout = decoded_frame->channel_layout;
            src_sample_fmt = decoded_frame->format;
            dst_sample_fmt = AV_SAMPLE_FMT_S16;
            
            av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
            av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout,  0);
            av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
            av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
            av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
            av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt,  0);
            
            /* initialize the resampling context */
            if ((ret = swr_init(swr_ctx)) < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Failed to initialize the resampling context\n");
            	//goto end;
            }

            /* allocate source and destination samples buffers */

            src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
            ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels,
            		src_nb_samples, src_sample_fmt, 0);
            if (ret < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Could not allocate source samples\n");
            	//goto end;
            }

            /* compute the number of converted samples: buffering is avoided
             * ensuring that the output buffer will contain at least all the
             * converted input samples */
            max_dst_nb_samples = dst_nb_samples =
            	av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

            /* buffer is going to be directly written to a rawaudio file, no alignment */
            dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
            ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
            		dst_nb_samples, dst_sample_fmt, 0);
            if (ret < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Could not allocate destination samples\n");
            	//goto end;
            }
            
            /* compute destination number of samples */
            dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) +
                                            src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
            
            /* convert to destination format */
            ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)decoded_frame->data, src_nb_samples);
            if (ret < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Error while converting\n");
                //goto end;
            }
            dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                     ret, dst_sample_fmt, 1);
            if (dst_bufsize < 0) {
                fprintf(stderr, "Could not get sample buffer size\n");
                //goto end;
            }
            
            samples = malloc(dst_bufsize);
    		memcpy(samples, dst_data[0], dst_bufsize);
    		data_size = dst_bufsize;
    		swr_free(&swr_ctx);
    	} else {
    		/* if a frame has been decoded, output it */
    	    data_size = av_samples_get_buffer_size(NULL, state->audio_st->codec->channels,
    	    		decoded_frame->nb_samples, state->audio_st->codec->sample_fmt, 1);
    		samples = malloc(data_size);
    		memcpy(samples, decoded_frame->data[0], data_size);
    	}
        
        *frame_size_ptr = data_size;
        
        // TODO add this call back!
        //*pts_ptr = pts;
        n = 2 * state->audio_st->codec->channels;
        state->audio_clock += (double)*frame_size_ptr /
        		(double)(n * state->audio_st->codec->sample_rate);

        /* if update, update the audio clock w/pts */
        if(pkt->pts != AV_NOPTS_VALUE) {
        	state->audio_clock = av_q2d(state->audio_st->time_base) * pkt->pts;
        }
    	
        //*frame_size_ptr = data_size;
        state->write_audio_callback(state->clazz, samples, data_size, from_thread);
        
    	avcodec_free_frame(&decoded_frame);
        
        free(samples);
        
    	return AUDIO_DATA_ID;
    }

    return 0;
}
//------------------------------------------------------------------------------
void videoDecodingThread(ThreadInfo* p_threadInfo)
{
    // Read ThreadInfo struct, then delete it
    FFmpegVideoPlayer* videoPlayer = p_threadInfo->videoPlayer;
    VideoInfo& videoInfo = videoPlayer->getVideoInfo();
    boost::mutex* playerMutex = p_threadInfo->playerMutex;
    boost::condition_variable* playerCondVar = p_threadInfo->playerCondVar;
    boost::mutex* decodeMutex = p_threadInfo->decodingMutex;
    boost::condition_variable* decodeCondVar = p_threadInfo->decodingCondVar;
    bool isLoop = p_threadInfo->isLoop;
    staticOgreLog = videoPlayer->getLog();
    delete p_threadInfo;
    
    // Initialize FFmpeg  
    av_register_all();
    av_log_set_callback(log_callback);
    av_log_set_level(AV_LOG_WARNING);
    
    // Initialize video decoding, filling the VideoInfo
    // Open the input file
    AVFormatContext* formatContext = NULL;
    const char* name = videoPlayer->getVideoFilename().c_str();
    if (avformat_open_input(&formatContext, name, NULL, NULL) < 0) 
    {
        videoInfo.error = "Could not open input: ";
        videoInfo.error.append(videoPlayer->getVideoFilename());
        playerCondVar->notify_all();
        return;
    }
    
    // Read stream information
    if (avformat_find_stream_info(formatContext, NULL) < 0) 
    {
        videoInfo.error = "Could not find stream information.";
        playerCondVar->notify_all();
        return;
    }
    
    // Get streams
    // Audio stream
    AVStream* audioStream = NULL;
    AVCodecContext* audioCodecContext = NULL;
    int audioStreamIndex = -1;
    if (!openCodecContext(formatContext, AVMEDIA_TYPE_AUDIO, videoInfo, audioStreamIndex)) 
    {
        // The error itself is set by openCodecContext
        playerCondVar->notify_all();
        return;
    }
    audioStream = formatContext->streams[audioStreamIndex];
    audioCodecContext = audioStream->codec;
    
    // Video stream
    AVStream* videoStream = NULL;
    AVCodecContext* videoCodecContext = NULL;
    int videoStreamIndex = -1;
    if (!openCodecContext(formatContext, AVMEDIA_TYPE_VIDEO, videoInfo, videoStreamIndex)) 
    {
        // The error itself is set by openCodecContext
        playerCondVar->notify_all();
        return;
    }
    videoStream = formatContext->streams[videoStreamIndex];
    videoCodecContext = videoStream->codec;
    
    // Dump information
    av_dump_format(formatContext, 0, videoPlayer->getVideoFilename().c_str(), 0);
    
    // Store useful information in VideoInfo struct
    double timeBase = ((double)audioStream->time_base.num) / (double)audioStream->time_base.den;
    videoInfo.audioDuration = audioStream->duration * timeBase;
    videoInfo.audioSampleRate = audioCodecContext->sample_rate;
    videoInfo.audioBitRate = audioCodecContext->bit_rate;
    videoInfo.audioNumChannels = 
            videoInfo.audioNumChannels > 0 ? videoInfo.audioNumChannels : audioCodecContext->channels;
    
    timeBase = ((double)videoStream->time_base.num) / (double)videoStream->time_base.den;
    videoInfo.videoDuration = videoStream->duration * timeBase;
    videoInfo.videoWidth = videoCodecContext->width;
    videoInfo.videoHeight = videoCodecContext->height;
    
    // If the a duration is below 0 seconds, something is very fishy. 
    // Use format duration instead, it's the best guess we have
    if (videoInfo.audioDuration < 0.0)
    {
        videoInfo.audioDuration = ((double)formatContext->duration) / AV_TIME_BASE;
    }
    if (videoInfo.videoDuration < 0.0)
    {
        videoInfo.videoDuration = ((double)formatContext->duration) / AV_TIME_BASE;
    }
 
    // Store the longer of both durations. This is what determines when looped videos
    // will begin anew
    videoInfo.longerDuration = videoInfo.videoDuration > videoInfo.audioDuration ? 
                                videoInfo.videoDuration : videoInfo.audioDuration;
            
    // Wake up video player
    videoInfo.infoFilled = true;
    playerCondVar->notify_all();
    
    // Initialize packet, set data to NULL, let the demuxer fill it
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = NULL;
    packet.size = 0;
    
    // Initialize SWS context
    SwsContext* swsContext = NULL;
    swsContext = sws_getCachedContext(swsContext,
                                videoInfo.videoWidth, videoInfo.videoHeight, videoCodecContext->pix_fmt, 
                                videoInfo.videoWidth, videoInfo.videoHeight, PIX_FMT_RGBA, 
                                SWS_BICUBIC, NULL, NULL, NULL);
    
    // Create destination picture
    AVFrame* destPic = avcodec_alloc_frame();
    avpicture_alloc((AVPicture*)destPic, PIX_FMT_RGBA, videoInfo.videoWidth, videoInfo.videoHeight);
    
    // Get the correct target channel layout
    uint64_t targetChannelLayout;
    // Keep the source layout
    if (audioCodecContext->channels == videoInfo.audioNumChannels)
    {
        targetChannelLayout = audioCodecContext->channel_layout;
    }
    // Or determine a new one
    else
    {
        switch (videoInfo.audioNumChannels)
        {
            case 1:
                targetChannelLayout = AV_CH_LAYOUT_MONO;
                break;
                
            case 2:
                targetChannelLayout = AV_CH_LAYOUT_STEREO;
                break;
                
            default:
                targetChannelLayout = audioCodecContext->channel_layout;
                break;
        }
    }
    
    // Initialize SWR context
    SwrContext* swrContext = swr_alloc_set_opts(NULL, 
                targetChannelLayout, AV_SAMPLE_FMT_FLT, audioCodecContext->sample_rate,
                audioCodecContext->channel_layout, audioCodecContext->sample_fmt, audioCodecContext->sample_rate, 
                0, NULL);
    int result = swr_init(swrContext);
    if (result != 0) 
    {
        videoInfo.error = "Could not initialize swr context: " + boost::lexical_cast<std::string>(result);
        playerCondVar->notify_all();
        return;
    }
    
    // Create destination sample buffer
    uint8_t** destBuffer = NULL;
    int destBufferLinesize;
    av_samples_alloc_array_and_samples( &destBuffer,
                                        &destBufferLinesize,
                                        videoInfo.audioNumChannels,
                                        2048,
                                        AV_SAMPLE_FMT_FLT,
                                        0);
    
    // Main decoding loop
    // Read the input file frame by frame
    AVFrame* frame = NULL;
    while (av_read_frame(formatContext, &packet) >= 0) 
    {
        // Only start decoding when at least one of the buffers is not full
        while (videoPlayer->getVideoBufferIsFull() && videoPlayer->getAudioBufferIsFull())
        {
            boost::unique_lock<boost::mutex> lock(*decodeMutex);
            boost::chrono::steady_clock::time_point const timeOut = 
                boost::chrono::steady_clock::now() + boost::chrono::milliseconds((int)videoPlayer->getBufferTarget() * 1000);
            decodeCondVar->wait_until(lock, timeOut);
            
            if (videoInfo.decodingAborted)
            {
                break;
            }
        }
            
        // Break if the decoding was aborted
        if (videoInfo.decodingAborted)
        {
            break;
        }
        
        // Initialize frame
        if (!frame) 
        {
            if (!(frame = avcodec_alloc_frame())) 
            {
                videoInfo.error = "Out of memory.";
                return;
            }
        } 
        else
        {
            avcodec_get_frame_defaults(frame);
        }
        
        // Decode the packet
        AVPacket orig_pkt = packet;
        do 
        {
            int decoded = 0;
            if (packet.stream_index == audioStreamIndex)
            {
                decoded = decodeAudioPacket(packet, audioCodecContext, audioStream, frame, swrContext,
                                            destBuffer, destBufferLinesize, videoPlayer, videoInfo, isLoop);
            }
            else if (packet.stream_index == videoStreamIndex)
            {
                decoded = decodeVideoPacket(packet, videoCodecContext, videoStream, frame, swsContext, 
                                            (AVPicture*)destPic, videoPlayer, videoInfo, isLoop);
            }
            else
            {
                // This means that we have a stream that is neither our video nor audio stream
                // Just skip the package
                break;
            }
            
            // decoded will be negative on an error
            if (decoded < 0)
            {
                // The error itself is set by the decode functions
                playerCondVar->notify_all();
                return;
            }
            
            // Increment data pointer, subtract from size
            packet.data += decoded;
            packet.size -= decoded;
        } while (packet.size > 0);
        
        av_free_packet(&orig_pkt);
    }
    
    // We're done. Close everything
    avcodec_free_frame(&frame);
    avpicture_free((AVPicture*)destPic);
    avcodec_free_frame(&destPic);
    avcodec_close(videoCodecContext);
    avcodec_close(audioCodecContext);
    sws_freeContext(swsContext);
    av_freep(&destBuffer[0]);
    swr_free(&swrContext);
    avformat_close_input(&formatContext);
    
    videoInfo.audioDuration = videoInfo.audioDecodedDuration;
    videoInfo.decodingDone = videoInfo.decodingAborted ? false : true;
}
Пример #14
0
int main(int argc, char **argv)
{
    int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND;
    int src_rate = 48000, dst_rate = 44100;
    uint8_t **src_data = NULL, **dst_data = NULL;
    int src_nb_channels = 0, dst_nb_channels = 0;
    int src_linesize, dst_linesize;
    int src_nb_samples = 1024, dst_nb_samples, max_dst_nb_samples;
    enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL, dst_sample_fmt = AV_SAMPLE_FMT_S16;
    const char *dst_filename = NULL;
    FILE *dst_file;
    int dst_bufsize;
    const char *fmt;
    struct SwrContext *swr_ctx;
    double t;
    int ret;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s output_file\n"
                "API example program to show how to resample an audio stream with libswresample.\n"
                "This program generates a series of audio frames, resamples them to a specified "
                "output format and rate and saves them to an output file named output_file.\n",
            argv[0]);
        exit(1);
    }
    dst_filename = argv[1];

    dst_file = fopen(dst_filename, "wb");
    if (!dst_file) {
        fprintf(stderr, "Could not open destination file %s\n", dst_filename);
        exit(1);
    }

    /* create resampler context */
    swr_ctx = swr_alloc();
    if (!swr_ctx) {
        fprintf(stderr, "Could not allocate resampler context\n");
        ret = AVERROR(ENOMEM);
        goto end;
    }

    /* set options */
    av_opt_set_int(swr_ctx, "in_channel_layout",    src_ch_layout, 0);
    av_opt_set_int(swr_ctx, "in_sample_rate",       src_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);

    av_opt_set_int(swr_ctx, "out_channel_layout",    dst_ch_layout, 0);
    av_opt_set_int(swr_ctx, "out_sample_rate",       dst_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);

    /* initialize the resampling context */
    if ((ret = swr_init(swr_ctx)) < 0) {
        fprintf(stderr, "Failed to initialize the resampling context\n");
        goto end;
    }

    /* allocate source and destination samples buffers */

    src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
    ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels,
                                             src_nb_samples, src_sample_fmt, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate source samples\n");
        goto end;
    }

    /* compute the number of converted samples: buffering is avoided
     * ensuring that the output buffer will contain at least all the
     * converted input samples */
    max_dst_nb_samples = dst_nb_samples =
        av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

    /* buffer is going to be directly written to a rawaudio file, no alignment */
    dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
    ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
                                             dst_nb_samples, dst_sample_fmt, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate destination samples\n");
        goto end;
    }

    t = 0;
    do {
        /* generate synthetic audio */
        fill_samples((double *)src_data[0], src_nb_samples, src_nb_channels, src_rate, &t);

        /* compute destination number of samples */
        dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) +
                                        src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
        if (dst_nb_samples > max_dst_nb_samples) {
            av_free(dst_data[0]);
            ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
                                   dst_nb_samples, dst_sample_fmt, 1);
            if (ret < 0)
                break;
            max_dst_nb_samples = dst_nb_samples;
        }

        /* convert to destination format */
        ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples);
        if (ret < 0) {
            fprintf(stderr, "Error while converting\n");
            goto end;
        }
        dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                 ret, dst_sample_fmt, 1);
        if (dst_bufsize < 0) {
            fprintf(stderr, "Could not get sample buffer size\n");
            goto end;
        }
        printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
        fwrite(dst_data[0], 1, dst_bufsize, dst_file);
    } while (t < 10);

    if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0)
        goto end;
    fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n"
            "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n",
            fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename);

end:
    if (dst_file)
        fclose(dst_file);

    if (src_data)
        av_freep(&src_data[0]);
    av_freep(&src_data);

    if (dst_data)
        av_freep(&dst_data[0]);
    av_freep(&dst_data);

    swr_free(&swr_ctx);
    return ret < 0;
}
Пример #15
0
    bool MpegLoader::open() 
    {
        if (!BaseMpegLoader::open())
            return false;

        int res = 0;

        av_opt_set_int(FmtContext_->streams[StreamId_]->codec, "refcounted_frames", 1, 0);
        if ((res = avcodec_open2(FmtContext_->streams[StreamId_]->codec, Codec_, 0)) < 0)
            return false;

        CodecContext_ = FmtContext_->streams[StreamId_]->codec;

        uint64_t layout = CodecContext_->channel_layout;
        InputFormat_ = CodecContext_->sample_fmt;
        switch (layout) {
        case AV_CH_LAYOUT_MONO:
            switch (InputFormat_) 
            {
            case AV_SAMPLE_FMT_U8:
            case AV_SAMPLE_FMT_U8P: 
                Fmt_ = AL_FORMAT_MONO8; 
                SampleSize_ = 1; 
                break;

            case AV_SAMPLE_FMT_S16:
            case AV_SAMPLE_FMT_S16P: 
                Fmt_ = AL_FORMAT_MONO16; 
                SampleSize_ = sizeof(quint16); 
                break;

            default:
                SampleSize_ = -1;
                break;
            }
            break;

        case AV_CH_LAYOUT_STEREO:
            switch (InputFormat_) 
            {
            case AV_SAMPLE_FMT_U8: 
                Fmt_ = AL_FORMAT_STEREO8; 
                SampleSize_ = 2; 
                break;

            case AV_SAMPLE_FMT_S16: 
                Fmt_ = AL_FORMAT_STEREO16; 
                SampleSize_ = 2 * sizeof(quint16); 
                break;

            default:
                SampleSize_ = -1;
                break;
            }
            break;

        default:
            SampleSize_ = -1;
            break;
        }

        if (Freq_ != 44100 && Freq_ != 48000)
            SampleSize_ = -1;

        if (SampleSize_ < 0) 
        {
            SwrContext_ = swr_alloc();
            if (!SwrContext_)
                return false;

            int64_t src_ch_layout = layout, dst_ch_layout = OutChannelLayout;
            SrcRate_ = Freq_;
            AVSampleFormat src_sample_fmt = InputFormat_, dst_sample_fmt = OutFormat;
            DstRate_ = (Freq_ != 44100 && Freq_ != 48000) ? OutFrequency : Freq_;

            av_opt_set_int(SwrContext_, "in_channel_layout", src_ch_layout, 0);
            av_opt_set_int(SwrContext_, "in_sample_rate", SrcRate_, 0);
            av_opt_set_sample_fmt(SwrContext_, "in_sample_fmt", src_sample_fmt, 0);
            av_opt_set_int(SwrContext_, "out_channel_layout", dst_ch_layout, 0);
            av_opt_set_int(SwrContext_, "out_sample_rate", DstRate_, 0);
            av_opt_set_sample_fmt(SwrContext_, "out_sample_fmt", dst_sample_fmt, 0);

            if ((res = swr_init(SwrContext_)) < 0)
                return false;

            SampleSize_ = OutChannels * sizeof(short);
            Freq_ = DstRate_;
            Len_ = av_rescale_rnd(Len_, DstRate_, SrcRate_, AV_ROUND_UP);
            Fmt_ = AL_FORMAT_STEREO16;

            MaxResampleSamples_ = av_rescale_rnd(BlockSize / SampleSize_, DstRate_, SrcRate_, AV_ROUND_UP);
            if ((res = av_samples_alloc_array_and_samples(&OutSamplesData_, 0, OutChannels, MaxResampleSamples_, OutFormat, 0)) < 0)
                return false;
        }

        return true;
    }
Пример #16
0
//音频线程
void *audio_thread(void *minstance){
	playInstance *instance = (playInstance *)minstance;
	LOGE("音频线程开启\n");

	JNIEnv *audioEnv;
	(*(instance->gJavaVm))->AttachCurrentThread(instance->gJavaVm,&audioEnv,NULL);
	jclass javacls = (*audioEnv)->GetObjectClass(audioEnv,instance->gJavaobj);
	jmethodID play = (*audioEnv)->GetMethodID(audioEnv,javacls,"playSound","([BI)V");

	struct timespec time;
	time.tv_sec=10;//网络不好最多等10秒
	time.tv_nsec=0;
	struct threadmsg msg;
	int packet_count = 0;

	while(1){
		if(instance->stop){
			break;
		}
		msg.data=NULL;

		AVPacket pavpacket;
		thread_queue_get(instance->audio_queue,&time,&msg);

		if(msg.msgtype==-1){//正常退出
			break;
		}

		if(msg.data ==NULL){
			LOGE("音频线程空循环\n");
			continue;
		}

		packet_count++;
		if(packet_count == 1){//拿到第一个音频包
			instance->vs->audio_start_time = av_gettime();
			LOGE("音频开始时间 %lld\n",instance->vs->audio_start_time);
		}

		AVPacket *packet_p = msg.data;
		pavpacket = *packet_p;
		uint8_t ** dst_data;

		//延时同步
		int64_t pkt_pts = pavpacket.pts;
		double show_time = pkt_pts * (instance->vs->audio_time_base);
		int64_t show_time_micro = show_time * 1000000;
		int64_t played_time = av_gettime() - instance->vs->audio_start_time;
		int64_t delta_time = show_time_micro - played_time;
		if(delta_time< -(0.2 * 1000000)){
			av_free_packet(packet_p);
			av_free(msg.data);
			LOGE("声音跳帧\n");
			continue;
		}else if(delta_time>0){
			av_usleep(delta_time);
		}

		int len =0;
		int dst_linesize;
		while(pavpacket.size>0){
			int got_frame=0;

			len = avcodec_decode_audio4(instance->vs->aCodecCtx,instance->vs->audio_decode_frame,&got_frame,&pavpacket);
			if(len<0){
				LOGE("audio decode return wrong");								
				break;
			}
			//音频转化
			av_samples_alloc_array_and_samples(&dst_data,&dst_linesize,1,(instance->vs->audio_decode_frame)->nb_samples,AV_SAMPLE_FMT_S16,0);
			swr_convert(instance->vs->swr_ctx,dst_data,(instance->vs->audio_decode_frame)->nb_samples,(const uint8_t **)&(instance->vs->audio_decode_frame->data[0]),(instance->vs->audio_decode_frame)->nb_samples);

			pavpacket.size -= len;
			pavpacket.data += len;

			if(got_frame){
				jbyte *bytes = (*audioEnv)->GetByteArrayElements(audioEnv, instance->global_aarray, NULL);
				memcpy(bytes,*dst_data,dst_linesize);
				(*audioEnv)->ReleaseByteArrayElements(audioEnv, instance->global_aarray, bytes, 0);
				(*audioEnv)->CallVoidMethod(audioEnv,instance->gJavaobj,play,instance->global_aarray,dst_linesize);
			}
			av_free(dst_data[0]);
		}
		av_free_packet(packet_p);
		av_free(msg.data);
	}
	(*(instance->gJavaVm))->DetachCurrentThread(instance->gJavaVm);
	LOGE("音频线程退出\n");
	return NULL;
}
Пример #17
0
int decode_frame_from_packet(VideoState *is, AVFrame decoded_frame)
{
	int64_t src_ch_layout, dst_ch_layout;
	int src_rate, dst_rate;
	uint8_t **src_data = NULL, **dst_data = NULL;
	int src_nb_channels = 0, dst_nb_channels = 0;
	int src_linesize, dst_linesize;
	int src_nb_samples, dst_nb_samples, max_dst_nb_samples;
	enum AVSampleFormat src_sample_fmt, dst_sample_fmt;
	int dst_bufsize;
	int ret;

	src_nb_samples = decoded_frame.nb_samples;
	src_linesize = (int) decoded_frame.linesize;
	src_data = decoded_frame.data;

	if (decoded_frame.channel_layout == 0) {
		decoded_frame.channel_layout = av_get_default_channel_layout(decoded_frame.channels);
	}

	src_rate = decoded_frame.sample_rate;
	dst_rate = decoded_frame.sample_rate;
	src_ch_layout = decoded_frame.channel_layout;
	dst_ch_layout = decoded_frame.channel_layout;
	src_sample_fmt = decoded_frame.format;
	dst_sample_fmt = AV_SAMPLE_FMT_S16;

	av_opt_set_int(is->sws_ctx_audio, "in_channel_layout", src_ch_layout, 0);
	av_opt_set_int(is->sws_ctx_audio, "out_channel_layout", dst_ch_layout,  0);
	av_opt_set_int(is->sws_ctx_audio, "in_sample_rate", src_rate, 0);
	av_opt_set_int(is->sws_ctx_audio, "out_sample_rate", dst_rate, 0);
	av_opt_set_sample_fmt(is->sws_ctx_audio, "in_sample_fmt", src_sample_fmt, 0);
	av_opt_set_sample_fmt(is->sws_ctx_audio, "out_sample_fmt", dst_sample_fmt,  0);

	/* initialize the resampling context */
	if ((ret = swr_init(is->sws_ctx_audio)) < 0) {
		fprintf(stderr, "Failed to initialize the resampling context\n");
		return -1;
	}

	/* allocate source and destination samples buffers */
	src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
	ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate source samples\n");
		return -1;
	}

	/* compute the number of converted samples: buffering is avoided
	 * ensuring that the output buffer will contain at least all the
	 * converted input samples */
	max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

	/* buffer is going to be directly written to a rawaudio file, no alignment */
	dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
	ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate destination samples\n");
		return -1;
	}

	/* compute destination number of samples */
	dst_nb_samples = av_rescale_rnd(swr_get_delay(is->sws_ctx_audio, src_rate) + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

	/* convert to destination format */
	ret = swr_convert(is->sws_ctx_audio, dst_data, dst_nb_samples, (const uint8_t **)decoded_frame.data, src_nb_samples);
	if (ret < 0) {
		fprintf(stderr, "Error while converting\n");
		return -1;
	}

	dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, ret, dst_sample_fmt, 1);
	if (dst_bufsize < 0) {
		fprintf(stderr, "Could not get sample buffer size\n");
		return -1;
	}

	memcpy(is->audio_buf, dst_data[0], dst_bufsize);

	if (src_data) {
		av_freep(&src_data[0]);
	}
	av_freep(&src_data);

	if (dst_data) {
		av_freep(&dst_data[0]);
	}
	av_freep(&dst_data);

	return dst_bufsize;
}
Пример #18
0
int initializeMuxer(const char *formatName, const char *fileName, PCAST_CONFIGURATION config) {
    AVOutputFormat *format;
    AVCodec *audCodec;
    int ret;

    av_register_all();
    avformat_network_init();

    hasWrittenStreamHeader = 0;
    spsLength = 0;
    ppsLength = 0;

    pthread_mutex_init(&streamLock, NULL);
    
    format = av_guess_format(formatName, fileName, NULL);
    if (format == NULL) {
        fprintf(stderr, "av_guess_format() failed\n");
        return -1;
    }
    
    formatContext = avformat_alloc_context();
    if (formatContext == NULL) {
        fprintf(stderr, "avformat_alloc_context() failed\n");
        return -2;
    }
    
    // Initialize the AVFormatContext
    formatContext->oformat = format;
    strcpy(formatContext->filename, fileName);

    if (config->muxEnableFlags & ENABLE_VIDEO) {
        // Add the video stream
        videoStream = avformat_new_stream(formatContext, NULL);
        if (videoStream == NULL) {
            fprintf(stderr, "avformat_new_stream() #1 failed\n");
            return -3;
        }

        // Configure the video codec
        videoCodecCtx = videoStream->codec;
        videoCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
        videoCodecCtx->codec_id = AV_CODEC_ID_H264;
        videoCodecCtx->bit_rate = 0;
        videoCodecCtx->width = config->width;
        videoCodecCtx->height = config->height;
        videoCodecCtx->time_base.den = config->frameRate;
        videoCodecCtx->time_base.num = 1;
        videoCodecCtx->gop_size = config->frameRate * config->iFrameInterval;
        videoCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
    }

    if (config->muxEnableFlags & ENABLE_AUDIO) {
        audCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
        if (audCodec == NULL) {
            fprintf(stderr, "avcodec_find_encoder failed\n");
            return -4;
        }

        // Add the audio stream
        audioStream = avformat_new_stream(formatContext, audCodec);
        if (audioStream == NULL) {
            fprintf(stderr, "avformat_new_stream() #2 failed\n");
            return -5;
        }

        // Configure the audio codec
        audioCodecCtx = audioStream->codec;
        audioCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
        audioCodecCtx->codec_id = AV_CODEC_ID_AAC;
        audioCodecCtx->bit_rate = config->audioBitrate;
        audioCodecCtx->sample_rate = 44100;
        audioCodecCtx->channels = config->audioChannels;
        audioCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
        audioCodecCtx->profile = FF_PROFILE_AAC_LOW;
        audioCodecCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;

        ret = avcodec_open2(audioCodecCtx, audCodec, NULL);
        if (ret < 0) {
            fprintf(stderr, "avcodec_open2() failed: %d\n", ret);
            return ret;
        }

        srcSamplesCount = audioCodecCtx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE ?
            10000 : audioCodecCtx->frame_size;

        ret = av_samples_alloc_array_and_samples(&srcSamplesData, &srcSamplesLinesize,
            audioCodecCtx->channels, srcSamplesCount, audioCodecCtx->sample_fmt, 0);
        if (ret < 0) {
            fprintf(stderr, "av_samples_alloc_array_and_samples() failed: %d\n", ret);
            return ret;
        }

        // Our input is 16-bit signed samples so we'll need a resampler to convert to FP
        swrContext = swr_alloc();
        if (swrContext == NULL) {
            fprintf(stderr, "swr_alloc() failed\n");
            return -1;
        }

        av_opt_set_int(swrContext, "in_channel_count", audioCodecCtx->channels, 0);
        av_opt_set_int(swrContext, "in_sample_rate", audioCodecCtx->sample_rate, 0);
        av_opt_set_int(swrContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
        av_opt_set_int(swrContext, "out_channel_count", audioCodecCtx->channels, 0);
        av_opt_set_int(swrContext, "out_sample_rate", audioCodecCtx->sample_rate, 0);
        av_opt_set_int(swrContext, "out_sample_fmt", audioCodecCtx->sample_fmt, 0);

        ret = swr_init(swrContext);
        if (ret < 0) {
            fprintf(stderr, "swr_init() failed: %d\n", ret);
            return ret;
        }

        maxDstSamplesCount = srcSamplesCount;
        ret = av_samples_alloc_array_and_samples(&dstSamplesData, &dstSamplesLinesize, audioCodecCtx->channels,
            maxDstSamplesCount, audioCodecCtx->sample_fmt, 0);
        if (ret < 0) {
            fprintf(stderr, "av_samples_alloc_array_and_samples() failed: %d\n", ret);
            return ret;
        }

        dstSamplesSize = av_samples_get_buffer_size(NULL, audioCodecCtx->channels, maxDstSamplesCount,
            audioCodecCtx->sample_fmt, 0);
    }
    
    if (format->flags & AVFMT_GLOBALHEADER) {
        if (videoCodecCtx != NULL) {
            videoCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
        if (audioCodecCtx != NULL) {
            audioCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
    }
    
    if ((format->flags & AVFMT_NOFILE) == 0) {
        if ((ret = avio_open(&formatContext->pb, fileName, AVIO_FLAG_WRITE)) < 0) {
            fprintf(stderr, "avio_open() failed: %d\n", ret);
            return -4;
        }
    }
    
    return 0;
}
Пример #19
0
int bl_audio_decode(
		char const * const filename,
		struct bl_song * const song) {
	int ret;
	// Contexts and libav variables
	AVPacket avpkt;
	AVFormatContext* context;
	int audio_stream;
	AVCodecContext* codec_context = NULL;
	AVCodec *codec = NULL;
	AVFrame *decoded_frame = NULL;
	struct SwrContext *swr_ctx;

	// Size of the samples
	uint64_t size = 0;

	// Dictionary to fetch tags
	AVDictionaryEntry *tags_dictionary;

	// Planar means channels are interleaved in data section
	// See MP3 vs FLAC for instance.
	int is_planar;

	// Pointer to beginning of music data
	int8_t *beginning;
	// Received frame holder
	int got_frame;
	// Position in the data buffer
	int index;
	// Initialize AV lib
	av_register_all();
	context = avformat_alloc_context();

	av_log_set_level(AV_LOG_QUIET);

	// Open input file
	if (avformat_open_input(&context, filename, NULL, NULL) < 0) {
		fprintf(stderr, "Couldn't open file: %s. Error %d encountered.\n", filename, errno);
		return BL_UNEXPECTED;
	}

	// Search for a valid stream
	if (avformat_find_stream_info(context, NULL) < 0) {
		fprintf(stderr, "Couldn't find stream information\n");
		return BL_UNEXPECTED;
	}

	// Get audio stream
	audio_stream = av_find_best_stream(context, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
	if (audio_stream < 0) {
		fprintf(stderr, "Couldn't find a suitable audio stream\n");
		return BL_UNEXPECTED;
	}
	// Find associated codec
	codec_context = context->streams[audio_stream]->codec;
	if (!codec_context) {
		fprintf(stderr, "Codec not found!\n");
		return BL_UNEXPECTED;
	}
	if (avcodec_open2(codec_context, codec, NULL) < 0) {
		fprintf(stderr, "Could not open codec\n");
		return BL_UNEXPECTED;
	}

	// Fill song properties
	song->filename = malloc(strlen(filename) + 1);
	strcpy(song->filename, filename);

	song->sample_rate = codec_context->sample_rate;
	song->duration = (uint64_t)(context->duration) / ((uint64_t)AV_TIME_BASE);
	song->bitrate = context->bit_rate;
	song->not_s16 = 0;
	song->nb_bytes_per_sample = av_get_bytes_per_sample(codec_context->sample_fmt);
	song->channels = codec_context->channels;

	// Get number of samples
	size = (
		((uint64_t)(context->duration) * (uint64_t)song->sample_rate) /
		((uint64_t)AV_TIME_BASE)
		) *
		song->channels *
		song->nb_bytes_per_sample;

	// Estimated number of samples
	song->nSamples = (
		(
		((uint64_t)(context->duration) * (uint64_t)song->sample_rate) /
		((uint64_t)AV_TIME_BASE)
		) *
		song->channels
	);

	// Allocate sample_array
	if((song->sample_array = calloc(size, 1)) == NULL) {
		fprintf(stderr, "Could not allocate enough memory\n");
		return BL_UNEXPECTED;
	}

	beginning = song->sample_array;
	index = 0;

	// If the song is in a floating-point format or int32, prepare the conversion to int16
	if(codec_context->sample_fmt != AV_SAMPLE_FMT_S16 &&
		codec_context->sample_fmt != AV_SAMPLE_FMT_S16P) {
		song->not_s16 = 1;
		song->nb_bytes_per_sample = 2;
	
		swr_ctx = swr_alloc();
		av_opt_set_int(swr_ctx, "in_channel_layout", codec_context->channel_layout, 0);
		av_opt_set_int(swr_ctx, "in_sample_rate", codec_context->sample_rate, 0);
		av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", codec_context->sample_fmt, 0);

		av_opt_set_int(swr_ctx, "out_channel_layout", codec_context->channel_layout, 0);
		av_opt_set_int(swr_ctx, "out_sample_rate", codec_context->sample_rate, 0);
		av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
		if((ret = swr_init(swr_ctx)) < 0) {
			fprintf(stderr, "Could not allocate resampler context\n");
			return BL_UNEXPECTED;
		}
	}

    // Zero initialize tags
	song->artist = NULL;
	song->title = NULL;
	song->album = NULL;
	song->tracknumber = NULL;

	// Initialize tracknumber tag
	tags_dictionary = av_dict_get(context->metadata, "track", NULL, 0);
	if (tags_dictionary!= NULL) {
		song->tracknumber = malloc(strlen(tags_dictionary->value) + 1);
		strcpy(song->tracknumber, tags_dictionary->value);
		song->tracknumber[strcspn(song->tracknumber, "/")] = '\0';
	} 
	else {
		song->tracknumber = malloc(1 * sizeof(char));
		strcpy(song->tracknumber, "");
	}

    // Initialize title tag
    tags_dictionary = av_dict_get(context->metadata, "title", NULL, 0);
	if (tags_dictionary!= NULL) {
		song->title = malloc(strlen(tags_dictionary->value) + 1);
		strcpy(song->title, tags_dictionary->value);
	}
	else {
		song->title = malloc(12 * sizeof(char));
		strcpy(song->title, "<no title>");
	}

	// Initialize artist tag
	tags_dictionary = av_dict_get(context->metadata, "ARTIST", NULL, 0);
	if (tags_dictionary!= NULL) {
		song->artist= malloc(strlen(tags_dictionary->value) + 1);
		strcpy(song->artist, tags_dictionary->value);
	}
	else {
		song->artist= malloc(12 * sizeof(char));
		strcpy(song->artist, "<no artist>");
	}

	// Initialize album tag
	tags_dictionary = av_dict_get(context->metadata, "ALBUM", NULL, 0);
	if (tags_dictionary!= NULL) {
		song->album= malloc(strlen(tags_dictionary->value) + 1);
		strcpy(song->album, tags_dictionary->value);
	}
	else {
		song->album= malloc(11 * sizeof(char));
		strcpy(song->album, "<no album>");
	}

	// Initialize genre tag
	tags_dictionary = av_dict_get(context->metadata, "genre", NULL, 0);
	if (tags_dictionary!= NULL) {
		song->genre= malloc(strlen(tags_dictionary->value) + 1);
		strcpy(song->genre, tags_dictionary->value);
	}
	else {
		song->genre = malloc(11 * sizeof(char));
		strcpy(song->genre, "<no genre>");
	}

	// Planar means channels are not interleaved
	is_planar = av_sample_fmt_is_planar(codec_context->sample_fmt);

	// Read the whole data and copy them into a huge buffer
	av_init_packet(&avpkt);
	while(av_read_frame(context, &avpkt) >= 0) {
		if(avpkt.stream_index == audio_stream) {
			got_frame = 0;

			// If decoded frame has not been allocated yet
			if (!decoded_frame) {
				// Try to allocate it
				decoded_frame = av_frame_alloc();
				if(!decoded_frame) {
					fprintf(stderr, "Could not allocate audio frame\n");
					return BL_UNEXPECTED;
				}
			}
			else {
				// Else, unreference it and reset fields
				av_frame_unref(decoded_frame);
			}

			int length = avcodec_decode_audio4(codec_context,
				decoded_frame,
				&got_frame,
				&avpkt);
			if(length < 0) {
				avpkt.size = 0;
			}

			av_packet_unref(&avpkt);

			// Copy decoded data into a huge array
			if(got_frame) {
				size_t data_size = av_samples_get_buffer_size(
					NULL,
					codec_context->channels,
					decoded_frame->nb_samples,
					codec_context->sample_fmt,
				1);

				if((index * song->nb_bytes_per_sample + data_size) > size) {
					int8_t *ptr;
					ptr = realloc(beginning, size + data_size);
					if(ptr != NULL) {
						beginning = ptr;
						size += data_size;
						song->nSamples += data_size / song->nb_bytes_per_sample;
					}
					else
						break;
				}
				int8_t *p = beginning + (index * song->nb_bytes_per_sample);

				// If the song isn't in a 16-bit format, convert it to
				if(song->not_s16 == 1) {
					uint8_t **out_buffer;
					int buff_size;
					buff_size = av_samples_alloc_array_and_samples(&out_buffer, decoded_frame->linesize,
						song->channels, decoded_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
					ret = swr_convert(swr_ctx, out_buffer, buff_size,
						(const uint8_t**)decoded_frame->extended_data, decoded_frame->nb_samples);
					if(ret < 0) {
						fprintf(stderr, "Error while converting from floating-point to int\n");
						return BL_UNEXPECTED;
					}
					memcpy((index * song->nb_bytes_per_sample) + beginning,
						out_buffer[0], buff_size);
					av_freep(&out_buffer[0]);
					free(out_buffer);
					index += buff_size / song->nb_bytes_per_sample;
				}
				else if(1 == is_planar) {
					for (int i = 0;
						i < (decoded_frame->nb_samples * song->nb_bytes_per_sample);
						i += song->nb_bytes_per_sample) {
						for (int j = 0; j < codec_context->channels; ++j) {
							for (int k = 0; k < song->nb_bytes_per_sample; ++k) {
								*p = ((int8_t*)(decoded_frame->extended_data[j]))[i + k];
								++p;
							}
						}
					}
					index += data_size / song->nb_bytes_per_sample;
				}
				else if (0 == is_planar) {
					memcpy((index * song->nb_bytes_per_sample) + beginning,
						decoded_frame->extended_data[0],
						data_size);
					index += data_size / song->nb_bytes_per_sample;
				}
			}
		}
		else {
			// Dropping packets that do not belong to the audio stream
			// (such as album cover)
			av_packet_unref(&avpkt);
		}
	}
	song->sample_array = beginning;

	// Free memory
	avpkt.data = NULL;
	avpkt.size = 0;

	// Use correct number of samples after decoding
	song->nSamples = index; 
	
	// Read the end of audio, as precognized in http://ffmpeg.org/pipermail/libav-user/2015-August/008433.html
	do {
		avcodec_decode_audio4(codec_context, decoded_frame, &got_frame, &avpkt);
	} while(got_frame);
	// Free memory
	if(song->not_s16)
		swr_free(&swr_ctx);
	avcodec_close(codec_context);
	av_frame_unref(decoded_frame);
	# if LIBAVUTIL_VERSION_MAJOR > 51
	av_frame_free(&decoded_frame);
	#endif
	av_packet_unref(&avpkt);
	avformat_close_input(&context);

	return BL_OK;
}