gpt4 book ai didi

c++ - libav 实时转码为 SFML SoundStream,乱码和噪音

转载 作者:行者123 更新时间:2023-12-04 23:20:22 24 4
gpt4 key购买 nike

我已经很接近了,但是使用输出示例格式或编解码器上下文似乎无法解决,也不知道从哪里开始。

#include <iostream>
#include <SFML/Audio.hpp>
#include "MyAudioStream.h"

extern "C"
{
#include <libavutil/opt.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/audio_fifo.h>
#include <libswresample/swresample.h>
}

void setupInput(AVFormatContext *input_format_context, AVCodecContext **input_codec_context, const char *streamURL)
{
// av_find_input_format("mp3");
avformat_open_input(&input_format_context, streamURL, NULL, NULL);
avformat_find_stream_info(input_format_context, NULL);

AVDictionary *metadata = input_format_context->metadata;
AVDictionaryEntry *name = av_dict_get(metadata, "icy-name", NULL, 0);
if (name != NULL)
{
std::cout << name->value << std::endl;
}
AVDictionaryEntry *title = av_dict_get(metadata, "StreamTitle", NULL, 0);
if (title != NULL)
{
std::cout << title->value << std::endl;
}

AVStream *stream = input_format_context->streams[0];
AVCodecParameters *codec_params = stream->codecpar;
AVCodec *codec = avcodec_find_decoder(codec_params->codec_id);
*input_codec_context = avcodec_alloc_context3(codec);

avcodec_parameters_to_context(*input_codec_context, codec_params);
avcodec_open2(*input_codec_context, codec, NULL);
}

void setupOutput(AVCodecContext *input_codec_context, AVCodecContext **output_codec_context)
{
AVCodec *output_codec = avcodec_find_encoder(AV_CODEC_ID_PCM_S16LE); // AV_CODEC_ID_PCM_S16LE ?? AV_CODEC_ID_PCM_S16BE
*output_codec_context = avcodec_alloc_context3(output_codec);
(*output_codec_context)->channels = 2;
(*output_codec_context)->channel_layout = av_get_default_channel_layout(2);
(*output_codec_context)->sample_rate = input_codec_context->sample_rate;
(*output_codec_context)->sample_fmt = output_codec->sample_fmts[0]; // AV_SAMPLE_FMT_S16 ??
avcodec_open2(*output_codec_context, output_codec, NULL);
}

void setupResampler(AVCodecContext *input_codec_context, AVCodecContext *output_codec_context, SwrContext **resample_context)
{
*resample_context = swr_alloc_set_opts(
*resample_context,
output_codec_context->channel_layout,
output_codec_context->sample_fmt,
output_codec_context->sample_rate,
input_codec_context->channel_layout,
input_codec_context->sample_fmt,
input_codec_context->sample_rate,
0, NULL);
swr_init(*resample_context);
}

MyAudioStream::MyAudioStream()
{
input_format_context = avformat_alloc_context();
resample_context = swr_alloc();
}

MyAudioStream::~MyAudioStream()
{
// clean up
avformat_close_input(&input_format_context);
avformat_free_context(input_format_context);
}

void MyAudioStream::load(const char *streamURL)
{

setupInput(input_format_context, &input_codec_context, streamURL);
setupOutput(input_codec_context, &output_codec_context);
setupResampler(input_codec_context, output_codec_context, &resample_context);

initialize(output_codec_context->channels, output_codec_context->sample_rate);
}

bool MyAudioStream::onGetData(Chunk &data)
{

// init
AVFrame *input_frame = av_frame_alloc();
AVPacket *input_packet = av_packet_alloc();
input_packet->data = NULL;
input_packet->size = 0;

// read
av_read_frame(input_format_context, input_packet);
avcodec_send_packet(input_codec_context, input_packet);
avcodec_receive_frame(input_codec_context, input_frame);

// convert
uint8_t *converted_input_samples = (uint8_t *)calloc(output_codec_context->channels, sizeof(*converted_input_samples));
av_samples_alloc(&converted_input_samples, NULL, output_codec_context->channels, input_frame->nb_samples, output_codec_context->sample_fmt, 0);
swr_convert(resample_context, &converted_input_samples, input_frame->nb_samples, (const uint8_t **)input_frame->extended_data, input_frame->nb_samples);

data.sampleCount = input_frame->nb_samples;
data.samples = (sf::Int16 *)converted_input_samples;

// av_freep(&converted_input_samples[0]);
// free(converted_input_samples);
av_packet_free(&input_packet);
av_frame_free(&input_frame);

return true;
}

void MyAudioStream::onSeek(sf::Time timeOffset)
{
// no op
}

sf::Int64 MyAudioStream::onLoop()
{
// no loop
return -1;
}

调用
#include <iostream>

#include "./MyAudioStream.h"

extern "C"
{
#include <libavutil/opt.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}

const char *streamURL = "http://s5radio.ponyvillelive.com:8026/stream.mp3";

int main(int, char **)
{

MyAudioStream myStream;

myStream.load(streamURL);

std::cout << "Hello, world!" << std::endl;

myStream.play();

while (myStream.getStatus() == MyAudioStream::Playing)
{
sf::sleep(sf::seconds(0.1f));
}

return 0;
}

最佳答案

我解决了。 swr_get_out_samples 返回的计数似乎是每个 channel 。设置sf::SoundStream::Chunk::sampleCount时我乘以2 ,如:

data.sampleCount = out_samples * 2;


那行得通。

关于c++ - libav 实时转码为 SFML SoundStream,乱码和噪音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68043944/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com