gpt4 book ai didi

ffmpeg - 使用 FFmpeg 和 SDL_QueueAudio 播放视频中的声音会产生高音调的音频

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

我正在尝试使用 SDL2 和 FFmpeg 播放 mp4 文件中的音频,并使用 SDL_QueueAudio似乎比设置回调容易得多。

我找到的所有解决方案,无论是在这里还是在 dranger tutorials , 已弃用或使用回调。我尝试使用 ffmpeg 和 sdl 标签(没有很多)浏览所有问题,但无济于事。我尝试将 dranger 教程转换为使用未弃用的调用,但遇到了同样的问题。我正在使用 C、FFmpeg 4.1 和 SDL 2.0.9。

这是 AVCodecContext 和 AVCodec 的设置:

    int audioStream = -1;
for (i = 0; i < formatContext->nb_streams; i++) {
if (audioStream < 0 && formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStream = i;
}
}

AVCodecParameters *audioParams = formatContext->streams[audioStream]->codecpar;

AVCodec *audioCodec = avcodec_find_decoder(audioParams->codec_id);

AVCodecContext *audioCodecCtx = avcodec_alloc_context3(NULL);
avcodec_open2(audioCodecCtx, audioCodec, NULL);

SDL_Init(SDL_INIT_AUDIO)

SDL_AudioSpec desired, obtained;
SDL_zero(desired);
SDL_zero(obtained);
desired.freq = audioCodecCtx->sample_rate;
desired.format = AUDIO_F32SYS;
desired.channels = audioCodecCtx->channels;
desired.silence = 0;
desired.samples = AUDIO_BUFFER_SIZE;

SDL_AudioDeviceID audioDevice = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);

这是主要的数据包解码循环:

    while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == audioStream) {
if (!avcodec_send_packet(audioCodecCtx, &packet)) {
avcodec_receive_frame(audioCodecCtx, audioFrame);
SDL_QueueAudio(audioDevice, audioFrame->data[0], audioFrame->linesize[0]);
}
}
}

音频以正确的速度播放,但音调比实际高得多。我希望它听起来像在任何媒体播放器中一样。
编辑:我刚刚意识到测试视频有立体声音频,但我只是在排队 audioFrame.data[0] ,我认为这意味着我只播放一个 channel 。我试过排队 audioFrame.data[1]它也有数据,但它没有解决问题。我是正确的,如果是,我如何播放两个 channel ?

最佳答案

回答这个问题可能为时已晚,但我遇到了同样的问题,现在我找到了适合我的解决方案,所以我发布了这个。
这里的问题可能是,FFmpeg 解码的音频格式是 AV_SAMPLE_FMT_FLTP (float planer) 格式,其中 channel 单独存储,如 frame->data[0]frame->data[1] .
我们需要使用 swr_convert() 将其转换为将这些 channel 打包成一个数组的格式
这是我的解决方案。

  • SwrContext 设置

  • SwrContext *resampler = swr_alloc_set_opts(NULL, 
    audioCodecCtx->channel_layout,
    AV_SAMPLE_FMT_S16,
    44100,
    audioCodecCtx->channel_layout,
    audioCodecCtx->sample_fmt,
    audioCodecCtx->sample_rate,
    0,
    NULL);
    swr_init(resampler);
  • SDL 音频设置

  • SDL_AudioDeviceID dev;
    SDL_AudioSpec want, have;
    SDL_zero(want);
    SDL_zero(have);
    want.freq = 44100;
    want.channels = audioCodecCtx->channels;
    want.format = AUDIO_S16SYS;
    dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
    SDL_PauseAudioDevice(dev, 0);
    最后是解码循环
    int ret = 0;
    AVPacket *packet = av_packet_alloc();
    AVFrame *frame = av_frame_alloc();
    AVFrame *audioframe = av_frame_alloc();
    while (true){
    ret = av_read_frame(formatContext, packet);
    if (ret < 0) break;
    AVStream *stream = formatContext->streams[packet->stream_index];
    if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){
    ret = avcodec_send_packet(audioCodecCtx, packet);
    while (ret >= 0){
    ret = avcodec_receive_frame(audioCodecCtx, frame);
    if (ret >= 0){
    int dst_samples = frame->channels * av_rescale_rnd(
    swr_get_delay(resampler, frame->sample_rate)
    + frame->nb_samples,
    44100,
    frame->sample_rate,
    AV_ROUND_UP);
    uint8_t *audiobuf = NULL;
    ret = av_samples_alloc(&audiobuf,
    NULL,
    1,
    dst_samples,
    AV_SAMPLE_FMT_S16,
    1);
    dst_samples = frame->channels * swr_convert(
    resampler,
    &audiobuf,
    dst_samples,
    (const uint8_t**) frame->data,
    frame->nb_samples);
    ret = av_samples_fill_arrays(audioframe->data,
    audioframe->linesize,
    audiobuf,
    1,
    dst_samples,
    AV_SAMPLE_FMT_S16,
    1);
    SDL_QueueAudio(dev,
    audioframe->data[0],
    audioframe->linesize[0]);
    }
    }
    }
    }

    关于ffmpeg - 使用 FFmpeg 和 SDL_QueueAudio 播放视频中的声音会产生高音调的音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55438697/

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