[Libav-user] Enconding and Resampling issue

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[Libav-user] Enconding and Resampling issue

Kevin Kouketsu

Hello,

 

I need to reencode and resample raw PCM 44.1KHz to AAC 48 KHz.

 

I’m really lost because have no much information about swr_convert.

 

What I’m doing until now is:

- Allocate AVCodecContext with encoder specifications:

 

void start_encoder(const AVFormatContext* formatContext, AVCodec*& encoderCodec, AVCodecContext*& encoderContext)

{

                encoderCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);

                if (encoderCodec == nullptr)

                               throw std::runtime_error("Could not find encoder for AAC");

 

                //stream->id = mpegtsFormatContext->nb_streams - 1;

                encoderContext = avcodec_alloc_context3(encoderCodec);

                if (!encoderCodec)

                               throw std::runtime_error("Could not allocate an encoding context.");

 

                auto codec = encoderCodec;

                auto c = encoderContext;

 

                // Configura o encoder.

                switch (codec->type)

                {

                case AVMEDIA_TYPE_AUDIO:

                               c->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;

                               c->bit_rate = 128000;

                               c->sample_rate = 48000;

 

                               // Garante que o samplerate de saída requisitado é aceito pelo encoder.

                               {

                                               bool supported{ false };

                                               if (codec->supported_samplerates)

                                               {

                                                               for (auto i = 0; codec->supported_samplerates[i]; i++)

                                                               {

                                                                               if (codec->supported_samplerates[i] == c->sample_rate)

                                                                               {

                                                                                              supported = true;

                                                                                              break;

                                                                               }

                                                               }

                                               }

 

                                               if (!supported)

                                                               throw std::invalid_argument("Sample rate not supported by encoder.");

                               }

 

                               c->channel_layout = AV_CH_LAYOUT_STEREO;

                               c->channels = av_get_channel_layout_nb_channels(c->channel_layout);

 

                               if (codec->channel_layouts)

                               {

                                               c->channel_layout = codec->channel_layouts[0];

                                               for (auto i = 0; codec->channel_layouts[i]; i++)

                                               {

                                                               if (codec->channel_layouts[i] == AV_CH_LAYOUT_STEREO)

                                                                               c->channel_layout = AV_CH_LAYOUT_STEREO;

                                               }

                               }

 

                               c->channels = av_get_channel_layout_nb_channels(c->channel_layout);

                               break;

 

                default:

                               break;

                }

 

                // Some formats want stream headers to be separate.

                if (formatContext->oformat->flags & AVFMT_GLOBALHEADER)

                               c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

 

                // open it

                AVDictionary* opt{ nullptr };

                check(avcodec_open2(c, codec, &opt));

}

- Allocating resampler contexto

 

void initialize_resampler(SwrContext*& resamplerCtx, AVCodecContext* encoder, AVFrame*& rawResampledAudioFrame, AVStream* audioFormatStream)

{

                int nb_samples = (encoder->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ? encoder->sample_rate : encoder->frame_size;

 

                int encoderFrameSize = encoder->channels * av_get_bytes_per_sample(encoder->sample_fmt) * encoder->frame_size;

                rawResampledAudioFrame = allocate_audioframe(encoder->sample_fmt, encoder->channel_layout, encoder->sample_rate, nb_samples);

 

                // Copy the stream parameters to the muxer

                check(avcodec_parameters_from_context(audioFormatStream->codecpar, encoder));

 

                // Create resampler context

                resamplerCtx = swr_alloc();

                if (resamplerCtx == nullptr)

                               throw std::runtime_error("Could not allocate resampler context");

 

                // Set options

                check(av_opt_set_int(resamplerCtx, "in_channel_count", 2, 0));

                check(av_opt_set_int(resamplerCtx, "in_sample_rate", 44100, 0));

                check(av_opt_set_sample_fmt(resamplerCtx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0));

                check(av_opt_set_int(resamplerCtx, "out_channel_count", encoder->channels, 0));

                check(av_opt_set_int(resamplerCtx, "out_sample_rate", encoder->sample_rate, 0));

                check(av_opt_set_sample_fmt(resamplerCtx, "out_sample_fmt", encoder->sample_fmt, 0));

 

                // initialize the resampling context

                check(swr_init(resamplerCtx));

}

 

- Allocating AVFrame to decodedFrame:

 

To get AVFrame, I’m sending to a decoder

 

                                               AVPacket input_packet;

                                               av_init_packet(&input_packet);

 

                                               while (av_read_frame(inputContext, &input_packet) >= 0)

                                               {

                                                               // Allocate data

                                                               uint8_t** convertedData = NULL;

                                                               if (av_samples_alloc_array_and_samples(&convertedData, NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0) < 0)

                                                                               throw - 20;

 

                                                               check(avcodec_send_packet(decoderContext, &input_packet));

                                                               check(avcodec_receive_frame(decoderContext, decodedFrame));

                                   }

 

As you can see, I’m Reading a frame from input (microfone), sending the packet to decoder to get AVFrame and what I have to do after?

 

I need to convert AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_S16 but I don’t know how.

 

My entire loop (doesn’t work):

                                               AVPacket input_packet;

                                               av_init_packet(&input_packet);

 

                                               while (av_read_frame(inputContext, &input_packet) >= 0)

                                               {

                                                               // Allocate data

                                                               uint8_t** convertedData = NULL;

                                                               if (av_samples_alloc_array_and_samples(&convertedData, NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0) < 0)

                                                                               throw - 20;

 

                                                               check(avcodec_send_packet(decoderContext, &input_packet));

                                                               check(avcodec_receive_frame(decoderContext, decodedFrame));

 

                                                               int outSamples = swr_convert(resamplerContext, convertedData, RAW_AUDIO_FRAME_SIZE, const_cast<const uint8_t**>(decodedFrame->data), decodedFrame->nb_samples);

                                                               check(outSamples);

 

                                                               av_init_packet(&pkt);

 

                                                               memcpy(&decodedFrame->data[0][0], convertedData, outSamples * sizeof STREAM_AUDIO_SAMPLE_TYPE * STREAM_AUDIO_CHANNELS);

                                                               auto in_stream = inputContext->streams[pkt.stream_index];

                                                               auto out_stream = outputContext->streams[pkt.stream_index];

 

                                                               //Convert PTS/DTS

                                                               pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));

                                                               pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));

                                                               pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);

                                                               pkt.pos = -1;

 

                                                               check(av_frame_make_writable(decodedFrame));

 

                                                               check(avcodec_send_frame(encoderContext, decodedFrame));

                                                               check(avcodec_receive_packet(encoderContext, &pkt));

 

                                                               check(av_interleaved_write_frame(outputContext, &pkt));

                                                               av_packet_unref(&pkt);

                                               }

 

Enviado do Email para Windows 10

 


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".