作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经很接近了,但是使用输出示例格式或编解码器上下文似乎无法解决,也不知道从哪里开始。
#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/
我是一名优秀的程序员,十分优秀!