首页 > 其他分享 >FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放

FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放

时间:2024-05-04 11:44:53浏览次数:27  
标签:播放 FFmpeg 音频格式 音频 len 兼容 audio 256 out

​FFmpeg结合SDL可以播放音频文件,也能播放视频文件中的音频流,《FFmpeg开发实战:从零基础到短视频上线》一书第10章的示例程序playaudio.c支持播放mp3和aac两种格式的音频,却不支持播放其他格式的音频。

因为mp3和aac两个格式拥有标准的规范定义,比如mp3规定每帧音频固定包含1152个样本,而aac规定每帧音频固定包含1024个样本。在它们的解码器实例AVCodecContext中,即可从frame_size字段获取每帧音频的样本数量。
然而其他音频格式(如ogg、amr、wma等)的每帧样本数并不固定,从frame_size字段取到的样本数量为0,这不仅导致SDL初始化失败,还导致重采样过程异常。为了能够播放其他格式的音频,需要对playaudio.c做下列三处修改。
1、从解码器实例获取音频样本数时,如果发现frame_size为0,就要把样本数变量设为512(注意该数值必须为2的n次幂,如256、512、1024等),修改后的赋值代码如下所示:

int out_nb_samples = audio_decode_ctx->frame_size; // 输出的采样数量
if (out_nb_samples <= 0) {
    out_nb_samples = 512;
}

2、在遍历音频帧的时候,要重新计算实际的采样位数,以便确定多少音频数据送给扬声器。具体的计算过程是这样的:先调用swr_convert函数对音频重采样,该函数的返回值为输出的数据大小;这个输入大小乘以声道数量乘以音频样本的位深(位深表示每个音频样本占据几个字节),最终的乘积便是要送给扬声器的音频数据大小。详细的计算代码如下所示:

// 重采样。也就是把输入的音频数据根据指定的采样规格转换为新的音频数据输出
int swr_size = swr_convert(swr_ctx, // 音频采样器的实例
    &out_buff, MAX_AUDIO_FRAME_SIZE, // 输出的数据内容和数据大小
    (const uint8_t **) frame->data, frame->nb_samples); // 输入的数据内容和数据大小
audio_pos = (unsigned char *) out_buff; // 把音频数据同步到缓冲区位置
// 这里要计算实际的采样位数
audio_len = swr_size * out_channels * av_get_bytes_per_sample(out_sample_fmt);

3、SDL的音频回调函数当中,注意每次要凑足len个字节。鉴于重采样后的音频数据可能较大(主要是amr格式有这种情况),因此要按照len指定的长度切割数据,确保每次回调函数都刚好把长度为len的音频数据送往扬声器。修改后的回调代码如下所示:

// 回调函数,在获取音频数据后调用
void fill_audio(void *para, uint8_t *stream, int len) {
    SDL_memset(stream, 0, len); // 将缓冲区清零
    if (audio_len == 0) {
        return;
    }
    while (len > 0) { // 每次都要凑足len个字节才能退出循环
        int fill_len = (len > audio_len ? audio_len : len);
        // 将音频数据混合到缓冲区
        SDL_MixAudio(stream, audio_pos, fill_len, SDL_MIX_MAXVOLUME);
        audio_pos += fill_len;
        audio_len -= fill_len;
        len -= fill_len;
        stream += fill_len;
        if (audio_len == 0) { // 这里要延迟一会儿,避免一直占据IO资源
            SDL_Delay(1);
        }
    }
}

上述修改后的代码已经附在了《FFmpeg开发实战:从零基础到短视频上线》一书第10章的源码chapter10/playaudio2.c,这个c代码是playaudio.c的改进版,除了支持原来mp3和aac格式的音频播放,还支持ogg、amr、wma等格式的音频播放,以及asf、webm等视频文件的音频播放。
接着执行下面的编译命令。

gcc playaudio2.c -o playaudio2 -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -I/usr/local/sdl2/include -L/usr/local/sdl2/lib -lsdl2 -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswscale -lswresample -lpostproc -lm

编译完成后执行以下命令启动测试程序,期望播放音频文件ring.ogg。

./playaudio2 ../ring.ogg

程序运行完毕,发现控制台输出以下的日志信息。

Success open input_file ../ring.ogg.
out_sample_rate=11025, out_nb_samples=512
out_buffer_size=1024
256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256
Success play audio file.
Quit SDL.

同时电脑扬声器传来了两个“叮咚”的铃声,表示上述代码正确实现了播放ogg音频的功能。

标签:播放,FFmpeg,音频格式,音频,len,兼容,audio,256,out
From: https://www.cnblogs.com/aqi00/p/18132704

相关文章

  • ffmpeg常用API笔记
    1.ffmpeg日志系统<libavutil/log.h>1)av_log_set_level(AV_LOG_DEBUG)2)av_log(NULL,AV_LOG_INFO,"fmt...",op) 2.<libavformat/avformat.h>操作目录:1)avio_open_dir()打开一个目录。结构体AVIODirContext,表示目录的上下文信息。//参数1:上下文;参数2:要访问的目录的ur......
  • Linux下ffmpeg库的编译链接
    /usr/bin/ld:/usr/local/ffmpeg/lib/libavformat.a(aviobuf.o):infunction`ff_crc04C11DB7_update':/home/ann/FFmpeg/ffmpeg/libavformat/aviobuf.c:568:undefinedreferenceto`av_crc_get_table'/usr/bin/ld:/home/ann/FFmpeg/ffmpeg/libavformat/aviobuf......
  • FFmpeg常用命令案例记录
    音频转换mp3为ogg格式ffmpeg-iinput.mp3-c:alibvorbisoutput.ogg降低音量(例如50%)ffmpeg-iinput.mp3-af"volume=0.5"output.mp3视频转换mkv为mp4并进行无损压缩ffmpeg-iinput.mkv-c:vlibx264-crf18-presetslow-c:acopyoutput.mp4转换4K为10......
  • ffmpeg7.0常用命令笔记 windows下
    1.多媒体格式转换ffmpeg-iinput.mov-acodeccopy-vcodeccopyout.mp4 2.从多媒体文件中抽取音频ffmpeg-iinput.mov-vn-acodeccopyout.aac 3.从多媒体文件中抽取视频ffmpeg-iinput.mov-an-vcodeccopyout.h264 4.将多媒体文件解码为原始音频数据......
  • BOSHIDA AC/DC电源模块的电磁兼容性分析与方案设计
    BOSHIDAAC/DC电源模块的电磁兼容性分析与方案设计BOSHIDAAC/DC电源模块是一种将交流电转换为直流电的电源模块,常用于各种电子设备中。然而,由于电磁干扰可能会对设备的正常运行造成影响,因此需要对AC/DC电源模块的电磁兼容性进行分析和方案设计。 首先,我们需要对AC/DC电源模......
  • ffmpeg不同平台的一些编译脚本
    build-x86-64.sh:#!/bin/sh#编译后输出目录,在ffmpeg源码目录下的/android/arm64-v8aOUTPUT=$(pwd)/x86_64-linux/x64build(){./configure\--disable-x86asm\--prefix=$OUTPUT\--disable-static\--disable-debug\--disable-doc\--enable-shared\--en......
  • Could not find module '.../libtorchaudio_ffmpeg.pyd' | RuntimeError: StreamRea
    Windows中使用torchaudio.io.StreamReader时报错:FileNotFoundError:Couldnotfindmodule'D:\software\miniconda3\envs\pytorch\Lib\site-packages\torchaudio\lib\libtorchaudio_ffmpeg.pyd'(oroneofitsdependencies).Tryusingthefullpathwith......
  • 使用FFmpeg将视频的分辨率从1080p转换为2160p
    1.要使用FFmpeg将视频的分辨率从1080p转换为2160p(也称为4K),可以使用以下命令行代码:ffmpeg-iinput.mp4-s3840x2160-c:vlibx264-presetslow-crf20output.mp4这里的参数解释如下:-iinput.mp4:指定输入文件。-s3840x2160:设置输出视频的分辨率为3840像素宽和2160像素高......
  • FFmpeg开发笔记(十七)Windows环境给FFmpeg集成字幕库libass
    ​libass是一个适用于ASS和SSA格式(AdvancedSubstationAlpha/SubstationAlpha)的字幕渲染器,支持的字幕类型包括srt、ass等,凡是涉及到给视频画面添加字幕,均需事先集成libass。《FFmpeg开发实战:从零基础到短视频上线》一书的“7.3.1 Linux环境安装libass”介绍了如何在Linux环境......
  • 1. FFmpeg介绍
    FFmpeg介绍什么是FFmpeg?FFmpeg既是一款音视频编解码工具,同时也是一组音视频编解码开发套件,提供了丰富的命令行工具,以及音视频处理的调用接口。FFmpeg提供了多种媒体格式的封装和解封装,包括多种音视频编码,多种协议的流媒体,多种色彩格式转换,多种采样率转换,多种码率转换等。FFmpe......