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".