void Parser::InitResampler() { swr_ctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(cdc_ctx_out->channels), cdc_ctx_out->sample_fmt, cdc_ctx_out->sample_rate, channelLayoutIn, (AVSampleFormat)sampleFormatIn, sampleRateIn, 0,0); if(!swr_ctx) throw ContextCreatorException() << errno_code(MIR_ERR_ALLOC_SWR_CONTEXT); // set options av_opt_set_int(swr_ctx, "in_channel_layout", channelLayoutIn, 0); av_opt_set_int(swr_ctx, "in_sample_rate", sampleRateIn, 0); av_opt_set_int(swr_ctx, "in_bit_rate", bitRateIn, 0); av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", (AVSampleFormat)sampleFormatIn, 0); av_opt_set_int(swr_ctx, "out_channel_layout", cdc_ctx_out->channel_layout, 0); av_opt_set_int(swr_ctx, "out_sample_rate", cdc_ctx_out->sample_rate, 0); av_opt_set_int(swr_ctx, "out_bit_rate", cdc_ctx_out->bit_rate, 0); av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", cdc_ctx_out->sample_fmt, 0); if (swr_init(swr_ctx) < 0) throw ContextCreatorException() << errno_code(MIR_ERR_INIT_SWR_CONTEXT); }
struct SwrContext * av_swr_alloc(int in_ch,int in_rate,enum AVSampleFormat in_fmt, int out_ch,int out_rate,enum AVSampleFormat out_fmt) { int ret; struct SwrContext * swr = swr_alloc(); if (!swr) { av_log(NULL, AV_LOG_FATAL, "Could not allocate resampler context.\n"); return NULL; } /* set options */ av_opt_set_int(swr, "in_channel_count", in_ch, 0); av_opt_set_int(swr, "in_sample_rate", in_rate, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", in_fmt, 0); av_opt_set_int(swr, "out_channel_count", out_ch, 0); av_opt_set_int(swr, "out_sample_rate", out_rate, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", out_fmt, 0); /* initialize the resampling context */ if ((ret = swr_init(swr)) < 0) { av_log(NULL, AV_LOG_FATAL, "Failed to initialize the resampling context\n"); return NULL; } return swr; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_resample_t* s = (af_resample_t*)af->setup; af_data_t *data= (af_data_t*)arg; int out_rate, test_output_res; // helpers for checking input format switch(cmd){ case AF_CONTROL_REINIT: if((af->data->rate == data->rate) || (af->data->rate == 0)) return AF_DETACH; af->data->nch = data->nch; if (af->data->nch > AF_NCH) af->data->nch = AF_NCH; af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; af->mul = (double)af->data->rate / data->rate; af->delay = af->data->nch * s->filter_length / FFMIN(af->mul, 1); // *bps*.5 if (s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length || s->ctx_phase_shift != s->phase_shift || s->ctx_linear != s->linear || s->ctx_cutoff != s->cutoff) { swr_free(&s->swrctx); if((s->swrctx=swr_alloc()) == NULL) return AF_ERROR; av_opt_set_int(s->swrctx, "out_sample_rate", af->data->rate, 0); av_opt_set_int(s->swrctx, "in_sample_rate", data->rate, 0); av_opt_set_int(s->swrctx, "filter_size", s->filter_length, 0); av_opt_set_int(s->swrctx, "phase_shift", s->phase_shift, 0); av_opt_set_int(s->swrctx, "linear_interp", s->linear, 0); av_opt_set_double(s->swrctx, "cutoff", s->cutoff, 0); av_opt_set_sample_fmt(s->swrctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_sample_fmt(s->swrctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(s->swrctx, "in_channel_count", af->data->nch, 0); av_opt_set_int(s->swrctx, "out_channel_count", af->data->nch, 0); if(swr_init(s->swrctx) < 0) return AF_ERROR; s->ctx_out_rate = af->data->rate; s->ctx_in_rate = data->rate; s->ctx_filter_size = s->filter_length; s->ctx_phase_shift = s->phase_shift; s->ctx_linear = s->linear; s->ctx_cutoff = s->cutoff; } // hack to make af_test_output ignore the samplerate change out_rate = af->data->rate; af->data->rate = data->rate; test_output_res = af_test_output(af, (af_data_t*)arg); af->data->rate = out_rate; return test_output_res; case AF_CONTROL_COMMAND_LINE:{ s->cutoff= 0.0; sscanf((char*)arg,"%d:%d:%d:%d:%lf", &af->data->rate, &s->filter_length, &s->linear, &s->phase_shift, &s->cutoff); if(s->cutoff <= 0.0) s->cutoff= FFMAX(1.0 - 6.5/(s->filter_length+8), 0.80); return AF_OK; } case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: af->data->rate = *(int*)arg; return AF_OK; } return AF_UNKNOWN; }
static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg) { AVCodecContext *c; int nb_samples; int ret; AVDictionary *opt = NULL; c = ost->st->codec; /* open it */ av_dict_copy(&opt, opt_arg, 0); ret = avcodec_open2(c, codec, &opt); av_dict_free(&opt); if (ret < 0) { fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret)); exit(1); } /* init signal generator */ ost->t = 0; ost->tincr = 2 * M_PI * 110.0 / c->sample_rate; /* increment frequency by 110 Hz per second */ ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) nb_samples = 10000; else nb_samples = c->frame_size; ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples); ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout, c->sample_rate, nb_samples); /* create resampler context */ ost->swr_ctx = swr_alloc(); if (!ost->swr_ctx) { fprintf(stderr, "Could not allocate resampler context\n"); exit(1); } /* set options */ av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); /* initialize the resampling context */ if ((ret = swr_init(ost->swr_ctx)) < 0) { fprintf(stderr, "Failed to initialize the resampling context\n"); exit(1); } }
bool FFMPEGer::open_audio(AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg){ AVCodecContext *c; int nb_samples; int ret; AVDictionary *opt = NULL; c = ost->st->codec; /* open it */ av_dict_copy(&opt, opt_arg, 0); ret = avcodec_open2(c, codec, &opt); av_dict_free(&opt); if (ret < 0) { ALOGE("Could not open audio codec: %s", av_err2str(ret)); return false; } if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) nb_samples = 10000; else nb_samples = c->frame_size; ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples); ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout, c->sample_rate, nb_samples); /* create resampler context */ ost->swr_ctx = swr_alloc(); if (!ost->swr_ctx) { ALOGE("Could not allocate resampler context"); return false; } /* set options */ av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); /* initialize the resampling context */ ret = swr_init(ost->swr_ctx); if (ret < 0){ ALOGE("Failed to initialize the resampling context"); return false; } return true; }
value ffmpeg_stream_new_audio(value ctx, value audio_info_) { CAMLparam2(ctx, audio_info_); CAMLlocal1(stream); AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_AAC); stream = caml_alloc_tuple(StreamSize); int ret; Stream_aux_direct_val(stream) = caml_alloc_custom(&streamaux_ops, sizeof(struct StreamAux), 0, 1); Stream_aux_val(stream)->type = Val_int(STREAM_AUDIO); Stream_context_direct_val(stream) = ctx; Stream_aux_val(stream)->avstream = avformat_new_stream(Context_val(ctx)->fmtCtx, codec); Stream_aux_val(stream)->avstream->codec->codec_id = AV_CODEC_ID_AAC; Stream_aux_val(stream)->avstream->codec->sample_rate = Int_val(Field(audio_info_, 0)); Stream_aux_val(stream)->avstream->codec->channels = Int_val(Field(audio_info_, 1)); Stream_aux_val(stream)->avstream->codec->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; Stream_aux_val(stream)->avstream->codec->channel_layout = AV_CH_LAYOUT_STEREO; //Stream_aux_val(stream)->avstream->codec->channels = av_get_channel_layout_nb_channels(Stream_aux_val(stream)->avstream->codec->channel_layout); if (Context_val(ctx)->fmtCtx->oformat->flags & AVFMT_GLOBALHEADER) { Stream_aux_val(stream)->avstream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } Stream_aux_val(stream)->avstream->time_base = (AVRational) {1, 10000}; AVDictionary* codecOpts = NULL; AVCodecContext* codecCtx = Stream_aux_val(stream)->avstream->codec; caml_enter_blocking_section(); ret = avcodec_open2(codecCtx, codec, &codecOpts); raise_and_leave_blocking_section_if_not(ret >= 0, ExnOpen, ret); caml_leave_blocking_section(); if (Stream_aux_val(stream)->avstream->codec->sample_fmt != AV_SAMPLE_FMT_S16) { Stream_aux_val(stream)->swrCtx = swr_alloc(); assert(Stream_aux_val(stream)->swrCtx); av_opt_set_int (Stream_aux_val(stream)->swrCtx, "in_channel_count", Stream_aux_val(stream)->avstream->codec->channels, 0); av_opt_set_int (Stream_aux_val(stream)->swrCtx, "in_sample_rate", Stream_aux_val(stream)->avstream->codec->sample_rate, 0); av_opt_set_sample_fmt(Stream_aux_val(stream)->swrCtx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int (Stream_aux_val(stream)->swrCtx, "out_channel_count", Stream_aux_val(stream)->avstream->codec->channels, 0); av_opt_set_int (Stream_aux_val(stream)->swrCtx, "out_sample_rate", Stream_aux_val(stream)->avstream->codec->sample_rate, 0); av_opt_set_sample_fmt(Stream_aux_val(stream)->swrCtx, "out_sample_fmt", Stream_aux_val(stream)->avstream->codec->sample_fmt, 0); } CAMLreturn((value) stream); }
static void OpenAudio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg, int sample_rate) { AVCodecContext *c = NULL; int nb_samples = 0; int ret = 0; AVDictionary *opt = NULL; c = ost->st->codec; // コーデックを初期化 av_dict_copy(&opt, opt_arg, 0); ret = avcodec_open2(c, codec, &opt); av_dict_free(&opt); if (ret < 0) { fprintf(stderr, "Could not open audio codec: %s\n", MakeErrorString(ret)); return; } if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) nb_samples = 10000; else nb_samples = c->frame_size; ost->frame = AllocAudioFrame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples); ost->tmp_frame = AllocAudioFrame(AV_SAMPLE_FMT_S16, c->channel_layout, sample_rate, nb_samples/(c->sample_rate/sample_rate)); // サンプル変換部 ost->swr_ctx = swr_alloc(); if (!ost->swr_ctx) { fprintf(stderr, "Could not allocate resampler context\n"); return; } // 音声フォーマットの設定 av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); av_opt_set_int (ost->swr_ctx, "in_sample_rate", sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); // サンプル変換部を初期化 if ((ret = swr_init(ost->swr_ctx)) < 0) { fprintf(stderr, "Failed to initialize the resampling context\n"); return; } }
int ffmpeg_open_codec(struct ffmpeg_file *file) { AVStream *s = file->format->streams[file->stream]; AVCodec *decoder = avcodec_find_decoder(s->codec->codec_id); if (avcodec_open2(s->codec, decoder, NULL) < 0) { return -1; } file->codec = s->codec; file->pkt = av_malloc(sizeof(AVPacket)); av_init_packet(file->pkt); av_packet_unref(file->pkt); file->time = 0; file->frame = av_frame_alloc(); if (!file->frame) { return -1; } file->swr = swr_alloc(); if (!file->swr) { return -1; } av_opt_set_int(file->swr, "in_channel_count", file->codec->channels, 0); av_opt_set_int(file->swr, "out_channel_count", file->channels, 0); av_opt_set_int(file->swr, "in_channel_layout", file->codec->channel_layout, 0); av_opt_set_int(file->swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(file->swr, "in_sample_rate", file->codec->sample_rate, 0); av_opt_set_int(file->swr, "out_sample_rate", file->sample_rate, 0); av_opt_set_sample_fmt(file->swr, "in_sample_fmt", file->codec->sample_fmt, 0); av_opt_set_sample_fmt(file->swr, "out_sample_fmt", file->sample_fmt, 0); swr_init(file->swr); if (!swr_is_initialized(file->swr)) { return -1; } return 0; }
BOOL CVideoLivRecord::open_audio(AVStream *st, AVCodec* codec, AVDictionary* opt) { AVCodecContext * avcc = st->codec; int nb_samples; int ret; AVDictionary* opt_dst = NULL;//必须初始化为空。 av_dict_copy(&opt_dst, opt, 0); ret = avcodec_open2(avcc, codec, &opt_dst); av_dict_free(&opt_dst); if (ret < 0){ log("[CVideoLivRecord::open_audio] -- avcodec_open2() error"); return FALSE; } m_t = 0; m_tincr = 2 * M_PI * 110.0 / avcc->sample_rate; m_tincr2 = 2 * M_PI * 110.0 / avcc->sample_rate / avcc->sample_rate; if (avcc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE){ nb_samples = 10000; } else { nb_samples = avcc->frame_size; } m_pAudioFrame = alloc_audio_frame(avcc->sample_fmt, avcc->channel_layout, avcc->sample_rate, nb_samples); m_pAudioBkFrame = alloc_audio_frame(AV_SAMPLE_FMT_S16, avcc->channel_layout, avcc->sample_rate, nb_samples); m_pAudioSwrctx = swr_alloc(); if (!m_pAudioSwrctx){ log("[CVideoLivRecord::open_audio] -- swr_alloc() error"); return FALSE; } av_opt_set_int (m_pAudioSwrctx, "in_channel_count", avcc->channels, 0); av_opt_set_int (m_pAudioSwrctx, "in_sample_rate", avcc->sample_rate, 0); av_opt_set_sample_fmt(m_pAudioSwrctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int (m_pAudioSwrctx, "out_channel_count", avcc->channels, 0); av_opt_set_int (m_pAudioSwrctx, "out_sample_rate", avcc->sample_rate, 0); av_opt_set_sample_fmt(m_pAudioSwrctx, "out_sample_fmt", avcc->sample_fmt, 0); if (swr_init(m_pAudioSwrctx) < 0){ log("[CVideoLivRecord::open_audio] -- swr_init() error"); return FALSE; } return TRUE; }
int frame_puller_open_audio(frame_puller **o_fp, const char *path, int output_sample_rate) { *o_fp = NULL; int ret; frame_puller *fp; if ((ret = _frame_puller_new(&fp, path)) < 0) return ret; fp->type = FRAME_PULLER_AUDIO; if ((ret = _frame_puller_init(fp, AVMEDIA_TYPE_AUDIO)) < 0) return ret; fp->output_sample_rate = output_sample_rate > 0 ? output_sample_rate : fp->codec_ctx->sample_rate; fp->sample_scale_rate = (double)fp->output_sample_rate / (double)fp->codec_ctx->sample_rate; // Initialize the libswresample context for audio resampling. // > Create the buffer for the converted frame to store data fp->frame = av_frame_alloc(); fp->frame->format = AV_SAMPLE_FMT_S16P; fp->frame->channel_layout = fp->codec_ctx->channel_layout; fp->frame->sample_rate = fp->output_sample_rate; if ((fp->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) || !strcmp(fp->codec->name, "pcm_mulaw")) fp->frame->nb_samples = 4096; else fp->frame->nb_samples = fp->sample_scale_rate * fp->codec_ctx->frame_size; av_log(NULL, AV_LOG_INFO, "frame_puller: number of samples per frame = %d\n", fp->frame->nb_samples); if ((ret = av_frame_get_buffer(fp->frame, 0)) < 0) return ret; // > Create the SwrContext fp->libsw.swr_ctx = swr_alloc(); if (!fp->libsw.swr_ctx) { av_log(NULL, AV_LOG_ERROR, "frame_puller: Cannot initialize audio resampling library" "(possibly caused by insufficient memory)\n"); return AVERROR_UNKNOWN; } // > Provide options for the SwrContext av_opt_set_channel_layout(fp->libsw.swr_ctx, "in_channel_layout", fp->codec_ctx->channel_layout, 0); av_opt_set_channel_layout(fp->libsw.swr_ctx, "out_channel_layout", fp->codec_ctx->channel_layout, 0); av_opt_set_int(fp->libsw.swr_ctx, "in_sample_rate", fp->codec_ctx->sample_rate, 0); av_opt_set_int(fp->libsw.swr_ctx, "out_sample_rate", fp->output_sample_rate, 0); av_opt_set_sample_fmt(fp->libsw.swr_ctx, "in_sample_fmt", fp->codec_ctx->sample_fmt, 0); av_opt_set_sample_fmt(fp->libsw.swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16P, 0); // > Fully initialize the SwrContext if ((ret = swr_init(fp->libsw.swr_ctx)) < 0) return ret; // For use in @ref frame_puller_last_time. fp->frame->pts = -233333; *o_fp = fp; return 0; }
void AudioResampleImpl::initResampler() { m_resampler.reset(swr_alloc(), [](SwrContext * context){ swr_free(&context); }); assert(m_from.isValid()); assert(m_to.isValid()); av_opt_set_int(m_resampler.get(), "in_channel_layout", av_get_default_channel_layout(m_from.channelCount()), 0); /// @todo Дополнить раскладкой AudioFormat av_opt_set_int(m_resampler.get(), "out_channel_layout", av_get_default_channel_layout(m_to.channelCount()), 0); av_opt_set_int(m_resampler.get(), "in_sample_rate", m_from.sampleRate(), 0); av_opt_set_int(m_resampler.get(), "out_sample_rate", m_to.sampleRate(), 0); av_opt_set_sample_fmt(m_resampler.get(), "in_sample_fmt", m_from.sampleFormat(), 0); av_opt_set_sample_fmt(m_resampler.get(), "out_sample_fmt", m_to.sampleFormat(), 0); /// Non planar int res = swr_init(m_resampler.get()); if (res != 0) throw FFException(res); }
void ensureAudioPostProcess() { if (host.state < CodecBoxDecoderState::Metadata) return; if (swr) return; swr = swr_alloc(); JIF(!swr, "failed to alloc audio resampler."); av_opt_set_channel_layout(swr, "in_channel_layout", audioCodecContext->channel_layout, 0); av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(swr, "in_sample_rate", audioCodecContext->sample_rate, 0); av_opt_set_int(swr, "out_sample_rate", host.sampleRate, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", audioCodecContext->sample_fmt, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); JIF(swr_init(swr), "failed to init audio resampler."); return; err: host.state = CodecBoxDecoderState::Failed; close(); }
int AudioResampler::InitAudioResampling(IN const std::shared_ptr<MediaFrame>& _pFrame) { // for fdkaac encoder, input samples should be PCM signed16le, otherwise do resampling if (_pFrame->AvFrame()->format != sampleFormat) { #ifdef LOG_TRADITIONAL loginfo("input sample_format=%d, need sample_format=%d, initiate resampling", #else loginfo("input sample_format={} need sample_format={}, initiate resampling", #endif _pFrame->AvFrame()->format, sampleFormat); pSwr_ = swr_alloc(); av_opt_set_int(pSwr_, "in_channel_layout", av_get_default_channel_layout(_pFrame->AvFrame()->channels), 0); av_opt_set_int(pSwr_, "out_channel_layout", av_get_default_channel_layout(nChannel), 0); av_opt_set_int(pSwr_, "in_sample_rate", _pFrame->AvFrame()->sample_rate, 0); av_opt_set_int(pSwr_, "out_sample_rate", nSampleRate, 0); av_opt_set_sample_fmt(pSwr_, "in_sample_fmt", static_cast<AVSampleFormat>(_pFrame->AvFrame()->format), 0); av_opt_set_sample_fmt(pSwr_, "out_sample_fmt", sampleFormat, 0); if (swr_init(pSwr_) != 0) { logerror("could not initiate resampling"); return -1; } }
void FFMS_AudioSource::SetOutputFormat(FFMS_ResampleOptions const& opt) { if (opt.SampleRate != AP.SampleRate) throw FFMS_Exception(FFMS_ERROR_RESAMPLING, FFMS_ERROR_UNSUPPORTED, "Sample rate changes are currently unsupported."); #ifndef FFMS_RESAMPLING_ENABLED if (opt.SampleFormat != AP.SampleFormat || opt.SampleRate != AP.SampleRate || opt.ChannelLayout != AP.ChannelLayout) throw FFMS_Exception(FFMS_ERROR_RESAMPLING, FFMS_ERROR_UNSUPPORTED, "FFMS was not built with resampling enabled. The only supported conversion is interleaving planar audio."); #endif #ifdef WITH_AVRESAMPLE if (opt.SampleFormat != AP.SampleFormat || opt.ChannelLayout != AP.ChannelLayout) throw FFMS_Exception(FFMS_ERROR_RESAMPLING, FFMS_ERROR_UNSUPPORTED, "FFMS was not built with FFMPEG resampling enabled."); #endif // Cache stores audio in the output format, so clear it and reopen the file Cache.clear(); PacketNumber = 0; ReopenFile(); FlushBuffers(CodecContext); BytesPerSample = av_get_bytes_per_sample(static_cast<AVSampleFormat>(opt.SampleFormat)) * av_get_channel_layout_nb_channels(opt.ChannelLayout); NeedsResample = opt.SampleFormat != (int)CodecContext->sample_fmt || opt.SampleRate != AP.SampleRate || opt.ChannelLayout != AP.ChannelLayout || opt.ForceResample; #ifdef FFMS_RESAMPLING_ENABLED if (!NeedsResample) return; FFResampleContext newContext; SetOptions(opt, newContext, resample_options); av_opt_set_int(newContext, "in_sample_rate", AP.SampleRate, 0); av_opt_set_int(newContext, "in_sample_fmt", CodecContext->sample_fmt, 0); av_opt_set_int(newContext, "in_channel_layout", AP.ChannelLayout, 0); av_opt_set_int(newContext, "out_sample_rate", opt.SampleRate, 0); #ifdef WITH_SWRESAMPLE av_opt_set_channel_layout(newContext, "out_channel_layout", opt.ChannelLayout, 0); av_opt_set_sample_fmt(newContext, "out_sample_fmt", (AVSampleFormat)opt.SampleFormat, 0); #endif if (ffms_open(newContext)) throw FFMS_Exception(FFMS_ERROR_RESAMPLING, FFMS_ERROR_UNKNOWN, "Could not open avresample context"); newContext.swap(ResampleContext); #endif }
/** * Allocates and initializes the SwrContext so that we don't have to deal with planar sample formats. * * @param env JNIEnv * @param aio FFAudioIO * @return a negative value should an error occur */ static int init_swr(JNIEnv *env, FFAudioIO *aio) { int res = 0; aio->swr_context = swr_alloc(); if (!aio->swr_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate swr context."); goto bail; } av_opt_set_sample_fmt(aio->swr_context, "in_sample_fmt", aio->stream->codecpar->format, 0); // make sure we get interleaved/packed output av_opt_set_sample_fmt(aio->swr_context, "out_sample_fmt", av_get_packed_sample_fmt(aio->stream->codecpar->format), 0); // keep everything else the way it was... av_opt_set_int(aio->swr_context, "in_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "out_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "in_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "out_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "in_sample_rate", aio->stream->codecpar->sample_rate, 0); av_opt_set_int(aio->swr_context, "out_sample_rate", aio->stream->codecpar->sample_rate, 0); res = swr_init(aio->swr_context); if (res < 0) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not initialize swr context"); goto bail; } //fprintf(stderr, "init_swr: dither context: %d\n", aio->swr_context->dither); //fprintf(stderr, "init_swr: output sample bits: %d\n", aio->swr_context->dither.output_sample_bits); bail: return res; }
void ACapsConvertElement::iStream(const QbPacket &packet) { if (!packet.caps().isValid() || packet.caps().mimeType() != "audio/x-raw" || this->state() != ElementStatePlaying) return; // Input Format AVSampleFormat iSampleFormat = av_get_sample_fmt(packet.caps().property("format").toString().toStdString().c_str()); int iNChannels = packet.caps().property("channels").toInt(); int64_t iChannelLayout = av_get_channel_layout(packet.caps().property("layout").toString().toStdString().c_str()); int iNPlanes = av_sample_fmt_is_planar(iSampleFormat)? iNChannels: 1; int iSampleRate = packet.caps().property("rate").toInt(); int iNSamples = packet.caps().property("samples").toInt(); if (iNSamples < 1) iNSamples = 1024; bool sameMimeType = packet.caps().mimeType() == this->m_caps.mimeType(); // Output Format AVSampleFormat oSampleFormat = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("format"))? av_get_sample_fmt(this->m_caps.property("format").toString().toStdString().c_str()): iSampleFormat; int oNChannels = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("channels"))? this->m_caps.property("channels").toInt(): iNChannels; int64_t oChannelLayout = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("layout"))? av_get_channel_layout(this->m_caps.property("layout").toString().toStdString().c_str()): iChannelLayout; int oSampleRate = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("rate"))? this->m_caps.property("rate").toInt(): iSampleRate; QVector<uint8_t *> iData(iNPlanes); int iLineSize; if (av_samples_fill_arrays(&iData.data()[0], &iLineSize, (const uint8_t *) packet.buffer().data(), iNChannels, iNSamples, iSampleFormat, 1) < 0) return; QbCaps caps1(packet.caps()); QbCaps caps2(this->m_curInputCaps); caps1.setProperty("samples", QVariant()); caps2.setProperty("samples", QVariant()); if (caps1 != caps2) { // create resampler context this->m_resampleContext = SwrContextPtr(swr_alloc(), this->deleteSwrContext); if (!this->m_resampleContext) return; // set options av_opt_set_int(this->m_resampleContext.data(), "in_channel_layout", iChannelLayout, 0); av_opt_set_int(this->m_resampleContext.data(), "in_sample_rate", iSampleRate, 0); av_opt_set_sample_fmt(this->m_resampleContext.data(), "in_sample_fmt", iSampleFormat, 0); av_opt_set_int(this->m_resampleContext.data(), "out_channel_layout", oChannelLayout, 0); av_opt_set_int(this->m_resampleContext.data(), "out_sample_rate", oSampleRate, 0); av_opt_set_sample_fmt(this->m_resampleContext.data(), "out_sample_fmt", oSampleFormat, 0); // initialize the resampling context if (swr_init(this->m_resampleContext.data()) < 0) return; this->m_curInputCaps = packet.caps(); } // compute destination number of samples int oNSamples = av_rescale_rnd(swr_get_delay(this->m_resampleContext.data(), iSampleRate) + iNSamples, oSampleRate, iSampleRate, AV_ROUND_UP); // buffer is going to be directly written to a rawaudio file, no alignment int oNPlanes = av_sample_fmt_is_planar(oSampleFormat)? oNChannels: 1; QVector<uint8_t *> oData(oNPlanes); int oLineSize; int oBufferSize = av_samples_get_buffer_size(&oLineSize, oNChannels, oNSamples, oSampleFormat, 1); QSharedPointer<uchar> oBuffer(new uchar[oBufferSize]); if (!oBuffer) return; if (av_samples_fill_arrays(&oData.data()[0], &oLineSize, (const uint8_t *) oBuffer.data(), oNChannels, oNSamples, oSampleFormat, 1) < 0) return; // convert to destination format if (swr_convert(this->m_resampleContext.data(), oData.data(), oNSamples, (const uint8_t **) iData.data(), iNSamples) < 0) return; const char *format = av_get_sample_fmt_name(oSampleFormat); char layout[256]; av_get_channel_layout_string(layout, sizeof(layout), oNChannels, oChannelLayout); QString caps = QString("audio/x-raw," "format=%1," "channels=%2," "rate=%3," "layout=%4," "samples=%5").arg(format) .arg(oNChannels) .arg(oSampleRate) .arg(layout) .arg(oNSamples); QbPacket oPacket(caps, oBuffer, oBufferSize); oPacket.setPts(packet.pts()); oPacket.setDuration(packet.duration()); oPacket.setTimeBase(packet.timeBase()); oPacket.setIndex(packet.index()); emit this->oStream(oPacket); }
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; }
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 = alloc_samples_array_and_data(&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 = alloc_samples_array_and_data(&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); 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; }
/** * Re-configures SwrContext and Encoder to match the provided target_format. * * @param env JNIEnv * @param object stream instance this call stems from, i.e. a FFCodecInputStream * @param target_format target AudioFormat * @param aio_pointer Pointer to the FFAudioIO struct of the FFNativePeerInputStream that opened the file/stream * @return pointer to the FFAudioIO struct that was given as parameter */ JNIEXPORT jlong JNICALL Java_com_tagtraum_ffsampledsp_FFCodecInputStream_open(JNIEnv *env, jobject object, jobject target_format, jlong aio_pointer) { int res = 0; enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_NONE; int out_channel_layout = AV_CH_LAYOUT_STEREO; int is_float = 0; int is_signed = 0; AVCodec *encoder = NULL; int dither_method = SWR_DITHER_NONE; int output_sample_bits = 0; init_ids(env); FFAudioIO *aio = (FFAudioIO*)(intptr_t)aio_pointer; jfloat sample_rate = (*env)->CallFloatMethod(env, target_format, getSampleRate_MID); jint sample_size_in_bits = (*env)->CallIntMethod(env, target_format, getSampleSizeInBits_MID); jint channels = (*env)->CallIntMethod(env, target_format, getChannels_MID); jboolean big_endian = (*env)->CallBooleanMethod(env, target_format, isBigEndian_MID); jobject encoding = (*env)->CallObjectMethod(env, target_format, getEncoding_MID); jstring jencoding_name = (jstring)(*env)->CallObjectMethod(env, encoding, toString_MID); const char *encoding_name = (*env)->GetStringUTFChars(env, jencoding_name, NULL); is_float = strcmp("PCM_FLOAT", encoding_name) == 0; is_signed = strcmp("PCM_SIGNED", encoding_name) == 0; (*env)->ReleaseStringUTFChars(env, jencoding_name, encoding_name); #ifdef DEBUG fprintf(stderr, "encoding = %s\n", encoding_name); fprintf(stderr, "signed = %d\n", is_signed); fprintf(stderr, "float = %d\n", is_float); fprintf(stderr, "bits = %d\n", (int)sample_size_in_bits); #endif if (sample_size_in_bits <= 8) { out_sample_fmt = AV_SAMPLE_FMT_U8; } else if (sample_size_in_bits <=16) { out_sample_fmt = AV_SAMPLE_FMT_S16; } else if (sample_size_in_bits <= 32 && is_float) { out_sample_fmt = AV_SAMPLE_FMT_FLT; } else if (sample_size_in_bits <=32) { out_sample_fmt = AV_SAMPLE_FMT_S32; } else if (sample_size_in_bits <= 64 && is_float) { out_sample_fmt = AV_SAMPLE_FMT_DBL; } else { fprintf(stderr, "Will use 64 bit PCM_FLOAT even though it might not have been desired.\n"); out_sample_fmt = AV_SAMPLE_FMT_DBL; } if (aio->stream->codecpar->channels == channels) { out_channel_layout = aio->stream->codecpar->channel_layout; } else if (channels == 1) { out_channel_layout = AV_CH_LAYOUT_MONO; } else if (channels == 2) { out_channel_layout = AV_CH_LAYOUT_STEREO; } else { fprintf(stderr, "Undetermined channel layout, will use stereo.\n"); channels = 2; } if (aio->stream->codecpar->bits_per_coded_sample > sample_size_in_bits) { dither_method = SWR_DITHER_TRIANGULAR; output_sample_bits = sample_size_in_bits; } #ifdef DEBUG fprintf(stderr, "setting out format to: %d\n", out_sample_fmt); #endif // remove default setup if (aio->swr_context) { swr_free(&aio->swr_context); } // allocate new aio->swr_context = swr_alloc(); if (!aio->swr_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate swr context."); goto bail; } // standard stuff from input av_opt_set_sample_fmt(aio->swr_context, "in_sample_fmt", aio->stream->codecpar->format, 0); av_opt_set_int(aio->swr_context, "in_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "in_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "in_sample_rate", aio->stream->codecpar->sample_rate, 0); // custom stuff av_opt_set_int(aio->swr_context, "out_channel_layout", out_channel_layout, 0); av_opt_set_int(aio->swr_context, "out_channel_count", channels, 0); av_opt_set_int(aio->swr_context, "out_sample_rate", (int)round(sample_rate), 0); av_opt_set_sample_fmt(aio->swr_context, "out_sample_fmt", out_sample_fmt, 0); av_opt_set_int(aio->swr_context, "dither_method", dither_method, 0); av_opt_set_int(aio->swr_context, "output_sample_bits", output_sample_bits, 0); res = swr_init(aio->swr_context); if (res < 0) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not re-initialize swr context."); goto bail; } #ifdef DEBUG fprintf(stderr, "open codec: dither method : %d\n", dither_method); fprintf(stderr, "open codec: output sample bits: %d\n", aio->swr_context->dither.output_sample_bits); #endif // re-adjust encoder encoder = ff_find_encoder(out_sample_fmt, sample_size_in_bits, big_endian, is_signed); if (!encoder) { res = AVERROR(EINVAL); throwIOExceptionIfError(env, res, "Could not find suitable encoder."); goto bail; } res = ff_init_encoder(env, aio, encoder); if (res < 0) { goto bail; } bail: return (jlong)(intptr_t)aio; }
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; }
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; }
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; }
Chroma::Result Chroma::operator() (const QString& filename) { std::shared_ptr<AVFormatContext> formatCtx; { AVFormatContext *formatCtxRaw = nullptr; if (avformat_open_input (&formatCtxRaw, filename.toLatin1 ().constData (), nullptr, nullptr)) throw std::runtime_error ("error opening file"); formatCtx.reset (formatCtxRaw, [] (AVFormatContext *ctx) { avformat_close_input (&ctx); }); } { QMutexLocker locker (&CodecMutex_); if (avformat_find_stream_info (formatCtx.get (), nullptr) < 0) throw std::runtime_error ("could not find stream"); } AVCodec *codec = nullptr; const auto streamIndex = av_find_best_stream (formatCtx.get (), AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); if (streamIndex < 0) throw std::runtime_error ("could not find audio stream"); auto stream = formatCtx->streams [streamIndex]; bool codecOpened = false; std::shared_ptr<AVCodecContext> codecCtx (stream->codec, [&codecOpened] (AVCodecContext *ctx) { if (codecOpened) avcodec_close (ctx); }); { QMutexLocker locker (&CodecMutex_); if (avcodec_open2 (codecCtx.get (), codec, nullptr) < 0) throw std::runtime_error ("couldn't open the codec"); } codecOpened = true; if (codecCtx->channels <= 0) throw std::runtime_error ("no channels found"); std::shared_ptr<SwrContext> swr; if (codecCtx->sample_fmt != AV_SAMPLE_FMT_S16) { swr.reset (swr_alloc (), [] (SwrContext *ctx) { if (ctx) swr_free (&ctx); }); av_opt_set_int (swr.get (), "in_channel_layout", codecCtx->channel_layout, 0); av_opt_set_int (swr.get (), "out_channel_layout", codecCtx->channel_layout, 0); av_opt_set_int (swr.get (), "in_sample_rate", codecCtx->sample_rate, 0); av_opt_set_int (swr.get (), "out_sample_rate", codecCtx->sample_rate, 0); av_opt_set_sample_fmt (swr.get (), "in_sample_fmt", codecCtx->sample_fmt, 0); av_opt_set_sample_fmt (swr.get (), "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); swr_init (swr.get ()); } AVPacket packet; av_init_packet (&packet); const int maxLength = 120; auto remaining = maxLength * codecCtx->channels * codecCtx->sample_rate; chromaprint_start (Ctx_, codecCtx->sample_rate, codecCtx->channels); std::shared_ptr<AVFrame> frame (av_frame_alloc (), [] (AVFrame *frame) { av_frame_free (&frame); }); auto maxDstNbSamples = 0; uint8_t *dstData [1] = { nullptr }; std::shared_ptr<void> dstDataGuard (nullptr, [&dstData] (void*) { if (dstData [0]) av_freep (&dstData [0]); }); while (true) { if (av_read_frame (formatCtx.get (), &packet) < 0) break; std::shared_ptr<void> guard (nullptr, [&packet] (void*) { if (packet.data) av_free_packet (&packet); }); if (packet.stream_index != streamIndex) continue; av_frame_unref (frame.get ()); int gotFrame = false; auto consumed = avcodec_decode_audio4 (codecCtx.get (), frame.get (), &gotFrame, &packet); if (consumed < 0 || !gotFrame) continue; uint8_t **data = nullptr; if (swr) { if (frame->nb_samples > maxDstNbSamples) { if (dstData [0]) av_freep (&dstData [0]); int linesize = 0; if (av_samples_alloc (dstData, &linesize, codecCtx->channels, frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) throw std::runtime_error ("cannot allocate memory for resampling"); } if (swr_convert (swr.get (), dstData, frame->nb_samples, const_cast<const uint8_t**> (frame->data), frame->nb_samples) < 0) throw std::runtime_error ("cannot resample audio"); data = dstData; } else data = frame->data; auto length = std::min (remaining, frame->nb_samples * codecCtx->channels); if (!chromaprint_feed (Ctx_, data [0], length)) throw std::runtime_error ("cannot feed data"); bool finished = false; if (maxLength) { remaining -= length; if (remaining <= 0) finished = true; } if (finished) break; } if (!chromaprint_finish (Ctx_)) throw std::runtime_error ("fingerprint calculation failed"); char *fingerprint = 0; if (!chromaprint_get_fingerprint (Ctx_, &fingerprint)) throw std::runtime_error ("unable to get fingerprint"); QByteArray result (fingerprint); chromaprint_dealloc (fingerprint); const double divideFactor = 1. / av_q2d (stream->time_base); const double duration = stream->duration / divideFactor; return { result, static_cast<int> (duration) }; }
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; }
int audio_decode_frame(VideoState *is) { int len1, data_size = 0; AVPacket *pkt = &is->audio_pkt; for(;;) { while(is->audio_pkt_size > 0) { int got_frame = 0; len1 = avcodec_decode_audio4(is->audio_st->codec, &is->audio_frame, &got_frame, pkt); if(len1 < 0) { /* if error, skip frame */ is->audio_pkt_size = 0; break; } if (got_frame) { /* data_size = av_samples_get_buffer_size ( NULL, is->audio_st->codec->channels, is->audio_frame.nb_samples, is->audio_st->codec->sample_fmt, 1 ); memcpy(is->audio_buf, is->audio_frame.data[0], data_size); */ data_size =av_samples_get_buffer_size ( NULL, is->audio_st->codec->channels, is->audio_frame.nb_samples, AV_SAMPLE_FMT_S16, 0 ); if (!swr_ctx) { swr_ctx = swr_alloc(); if (!swr_ctx) { printf("Could not allocate swr context\n"); exit(1); } /* set options */ av_opt_set_int(swr_ctx, "in_channel_layout", is->audio_st->codec->channel_layout, 0); av_opt_set_int(swr_ctx, "in_sample_rate", is->audio_st->codec->sample_rate, 0); av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", is->audio_st->codec->sample_fmt, 0); av_opt_set_int(swr_ctx, "out_channel_layout", is->audio_st->codec->channel_layout, 0); av_opt_set_int(swr_ctx, "out_sample_rate", is->audio_st->codec->sample_rate, 0); av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); if (swr_init(swr_ctx) < 0) { printf("Failed to initialize the resampling context\n"); exit(1); } decode_buffer = (uint8_t*) malloc(data_size); } int ret = swr_convert(swr_ctx, &decode_buffer, is->audio_frame.nb_samples, (const uint8_t **) &is->audio_frame.data[0], is->audio_frame.nb_samples); if (ret < 0) { printf("Error while converting\n"); break; } memcpy(is->audio_buf, decode_buffer, data_size); } is->audio_pkt_data += len1; is->audio_pkt_size -= len1; if(data_size <= 0) { /* No data yet, get more frames */ continue; } /* We have data, return it and come back for more later */ return data_size; } if(pkt->data) av_free_packet(pkt); if(is->quit) { return -1; } /* next packet */ if(packet_queue_get(&is->audioq, pkt, 1) < 0) { return -1; } is->audio_pkt_data = pkt->data; is->audio_pkt_size = pkt->size; } }
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 frame_pusher_open(frame_pusher **o_fp, const char *path, int aud_samplerate, AVRational vid_framerate, int width, int height, int vid_bitrate) { *o_fp = NULL; int ret; frame_pusher *fp = (frame_pusher *)av_malloc(sizeof(frame_pusher)); // Guess the format AVOutputFormat *ofmt = av_guess_format(NULL, path, NULL); if (!ofmt) { ofmt = av_oformat_next(NULL); // Use the first format available av_log(NULL, AV_LOG_WARNING, "Unsupported container format. Using %s instead.\n", ofmt->name); // TODO: Add the extension to the path. } av_log(NULL, AV_LOG_INFO, "Using format %s\n", ofmt->name); // Open output file AVIOContext *io_ctx; if ((ret = avio_open2(&io_ctx, path, AVIO_FLAG_WRITE, NULL, NULL)) < 0) return ret; // Create the format context fp->fmt_ctx = avformat_alloc_context(); fp->fmt_ctx->oformat = ofmt; fp->fmt_ctx->pb = io_ctx; // > Create the streams. Here we simply create one for video and one for audio. // >> The audio stream AVCodec *aud_codec = avcodec_find_encoder(AV_CODEC_ID_AAC); fp->aud_stream = avformat_new_stream(fp->fmt_ctx, aud_codec); fp->aud_stream->id = 0; fp->aud_stream->codec->codec_id = AV_CODEC_ID_AAC; fp->aud_stream->codec->bit_rate = 64000; fp->aud_stream->codec->sample_rate = fp->aud_samplerate = aud_samplerate; // >>> http://stackoverflow.com/questions/22989838 // >>> TODO: Add an option to set the codec and the sample format. fp->aud_stream->codec->sample_fmt = fp->aud_stream->codec->codec->sample_fmts[0]; fp->aud_stream->codec->channel_layout = AV_CH_LAYOUT_STEREO; fp->aud_stream->codec->channels = 2; fp->aud_stream->codec->time_base = fp->aud_stream->time_base = (AVRational){1, aud_samplerate}; // >> The video stream AVCodec *vid_codec = avcodec_find_encoder(AV_CODEC_ID_H264); fp->vid_stream = avformat_new_stream(fp->fmt_ctx, vid_codec); fp->vid_width = fp->vid_stream->codec->width = width; fp->vid_height = fp->vid_stream->codec->height = height; fp->vid_stream->id = 1; // >>> * ATTENTION: fp->vid_stream->codec is an (AVCodecContext *) rather than (AVCodec *)! fp->vid_stream->codec->codec_id = AV_CODEC_ID_H264; fp->vid_stream->codec->bit_rate = vid_bitrate > 0 ? vid_bitrate : 1200000; fp->vid_stream->codec->pix_fmt = AV_PIX_FMT_YUV420P; fp->vid_stream->codec->gop_size = 24; fp->vid_stream->codec->time_base = fp->vid_stream->time_base = (AVRational){vid_framerate.den, vid_framerate.num}; // >> Enable experimental codecs such as AAC fp->aud_stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; fp->vid_stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; // >> Some formats want stream headers to be separate. // >> XXX: MPEG-4 doesn't have AVFMT_GLOBALHEADER in its format flags?? //if (fp->fmt_ctx->flags & AVFMT_GLOBALHEADER) fp->aud_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; fp->vid_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; if ((ret = avcodec_open2(fp->aud_stream->codec, aud_codec, NULL)) < 0) return ret; if ((ret = avcodec_open2(fp->vid_stream->codec, vid_codec, NULL)) < 0) return ret; // Trigger a full initialization on the format context and write the header. avformat_write_header(fp->fmt_ctx, NULL); // Miscellaneous initializations fp->first_packet = 1; fp->last_aud_pts = fp->last_vid_pts = 0; fp->nb_aud_buffered_samples = 0; // > Video fp->vid_frame = av_frame_alloc(); fp->pict_bufsize = avpicture_get_size(AV_PIX_FMT_YUV420P, width, height); fp->pict_buf = (uint8_t *)av_malloc(fp->pict_bufsize); // >> Assign the video frame with the allocated buffer avpicture_fill((AVPicture *)fp->vid_frame, fp->pict_buf, AV_PIX_FMT_YUV420P, width, height); fp->sws_ctx = sws_getContext( width, height, PIX_FMT_RGB24, width, height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); // > Audio fp->aud_frame = av_frame_alloc(); fp->aud_buf = av_frame_alloc(); fp->aud_buf->format = fp->aud_frame->format = fp->aud_stream->codec->sample_fmt; fp->aud_buf->channel_layout = fp->aud_frame->channel_layout = fp->aud_stream->codec->channel_layout; fp->aud_buf->sample_rate = fp->aud_frame->sample_rate = fp->aud_stream->codec->sample_rate; if (aud_codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) { fp->nb_aud_samples_per_frame = 4096; av_log(NULL, AV_LOG_INFO, "frame_pusher: codec has variable frame size capability\n"); } else fp->nb_aud_samples_per_frame = fp->aud_stream->codec->frame_size; fp->aud_buf->nb_samples = fp->aud_frame->nb_samples = fp->nb_aud_samples_per_frame; av_log(NULL, AV_LOG_INFO, "frame_pusher: number of samples per frame = %d\n", fp->nb_aud_samples_per_frame); if ((ret = av_frame_get_buffer(fp->aud_frame, 0)) < 0) return ret; if ((ret = av_frame_get_buffer(fp->aud_buf, 0)) < 0) return ret; // >> The audio resampling context fp->swr_ctx = swr_alloc(); if (!fp->swr_ctx) { av_log(NULL, AV_LOG_ERROR, "frame_pusher: Cannot initialize audio resampling library" "(possibly caused by insufficient memory)\n"); return AVERROR_UNKNOWN; } av_opt_set_channel_layout(fp->swr_ctx, "in_channel_layout", fp->aud_stream->codec->channel_layout, 0); av_opt_set_channel_layout(fp->swr_ctx, "out_channel_layout", fp->aud_stream->codec->channel_layout, 0); av_opt_set_int(fp->swr_ctx, "in_sample_rate", fp->aud_stream->codec->sample_rate, 0); av_opt_set_int(fp->swr_ctx, "out_sample_rate", fp->aud_stream->codec->sample_rate, 0); av_opt_set_sample_fmt(fp->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_sample_fmt(fp->swr_ctx, "out_sample_fmt", fp->aud_stream->codec->sample_fmt, 0); if ((ret = swr_init(fp->swr_ctx)) < 0) return ret; *o_fp = fp; return 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; }
int main (int argc, char **argv){ int ret = 0, got_frame; AVFormatContext *ofmt_ctx = NULL; AVOutputFormat *ofmt = NULL; uint8_t *sample_buf; if (argc != 4 && argc != 5) { fprintf(stderr, "input 1.source file:%s\n" "2.output_video\n" "3.output_audio\n" "4.mux video file(Optional)\n" "\n", argv[0]); exit(1); } src_filename = argv[1]; video_dst_filename = argv[2]; audio_dst_filename = argv[3]; //optional mux to any type video if(argc == 5){ out_filename = argv[4]; } /* register all formats and codecs */ av_register_all(); //for network stream avformat_network_init(); ret = init_input(); if(ret){ goto end; } ret = init_video_out_context(); if(ret){ goto end; } ret = init_audio_out_context(sample_buf); if(ret){ goto end; }else{ int aud_buffer_size; //alloc frame and packet AudFrame = av_frame_alloc(); AudFrame->nb_samples = AudCodecCtx->frame_size; AudFrame->format = AudCodecCtx->sample_fmt; AudFrame->channel_layout = AudCodecCtx->channel_layout; aud_buffer_size = av_samples_get_buffer_size(NULL, AudCodecCtx->channels,AudCodecCtx->frame_size,AudCodecCtx->sample_fmt, 1); sample_buf = (uint8_t *)av_malloc(aud_buffer_size); avcodec_fill_audio_frame(AudFrame, AudCodecCtx->channels, AudCodecCtx->sample_fmt,(const uint8_t*)sample_buf, aud_buffer_size, 1); av_new_packet(&AudPkt,aud_buffer_size); } if(argc == 5){ //alloc memory avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); if (!ofmt_ctx) { printf( "Could not create output context\n"); ret = AVERROR_UNKNOWN; return 1; } ofmt = ofmt_ctx->oformat; ret = init_output(ofmt_ctx); if(ret){ printf("Init output ERROR\n"); goto end; } } if (!(ofmt->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE); if (ret < 0) { printf( "Could not open output file '%s'", out_filename); goto end; } } ret = avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { printf( "Error occurred when opening output file\n"); goto end; } //this will fill up by decoder(|read frame|->packet->|decoder|->frame) frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate frame\n"); ret = AVERROR(ENOMEM); goto end; } if (video_stream) printf("Demuxing video from file '%s' into '%s'\n", src_filename, video_dst_filename); if (audio_stream) printf("Demuxing audio from file '%s' into '%s'\n", src_filename, audio_dst_filename); //Write video Header avformat_write_header(pFormatCtx,NULL); //Write audio Header avformat_write_header(AudFormatCtx,NULL); //alloc packet to get copy from pkt av_new_packet(&epkt,picture_size); /*setup the convert parameter *due to input sample format AV_SAMPLE_FMT_FLTP *can't be converted to AV_SAMPLE_FMT_S16 *which only accepted by the aac encoder */ swr = swr_alloc(); av_opt_set_int(swr, "in_channel_layout", audio_dec_ctx->channel_layout, 0); av_opt_set_int(swr, "out_channel_layout", AudCodecCtx->channel_layout, 0); av_opt_set_int(swr, "in_sample_rate", audio_dec_ctx->sample_rate, 0); av_opt_set_int(swr, "out_sample_rate", AudCodecCtx->sample_rate, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); swr_init(swr); /*start read frames from the file */ while (av_read_frame(fmt_ctx, &pkt) >= 0) { //do demux & decode -> encode -> output h264 & aac file ret = decode_packet(); if (ret < 0) break; if(argc == 5){ remux_packet(ofmt_ctx,&pkt); } av_free_packet(&pkt); } /* flush cached frames */ pkt.data = NULL; pkt.size = 0; //Flush Encoder int retfe = flush_encoder(pFormatCtx,0); if (retfe < 0) { printf("Flushing encoder failed\n"); return -1; } //Flush Encoder ret = flush_encoder(pFormatCtx,0); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } //Write video trailer av_write_trailer(pFormatCtx); //Write audio Trailer av_write_trailer(AudFormatCtx); //Write remux Trailer if(argc == 5){ av_write_trailer(ofmt_ctx); } printf("Output succeeded!!!!\n"); end: //free remux if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_close(ofmt_ctx->pb); avformat_free_context(ofmt_ctx); //free audio if (audio_st){ avcodec_close(audio_st->codec); av_free(AudFrame); av_free(sample_buf); } avio_close(AudFormatCtx->pb); avformat_free_context(AudFormatCtx); //free video if (video_st){ avcodec_close(video_st->codec); av_free(pFrame); av_free(picture_buf); } avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); //free decode avcodec_close(video_dec_ctx); avcodec_close(audio_dec_ctx); avformat_close_input(&fmt_ctx); if (video_dst_file) fclose(video_dst_file); if (audio_dst_file) fclose(audio_dst_file); av_frame_free(&frame); return ret < 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; }