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
[email protected]
https://ffmpeg.org/mailman/listinfo/libav-user

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

Reply via email to