音频播放 via FFmpeg

FFmpeg 简介

FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用 LGPL 或 GPL 许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频 / 视频编解码库 libavcodec,为了保证高可移植性和编解码质量,libavcodec 里很多 code 都是从头开发的。

FFmpeg 在 Linux 平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括 Windows、Mac OS X 等。这个项目最早由 Fabrice Bellard 发起,2004 年至 2015 年间由 Michael Niedermayer 主要负责维护。许多 FFmpeg 的开发人员都来自 MPlayer 项目,而且当前 FFmpeg 也是放在 MPlayer 项目组的服务器上。项目的名称来自 MPEG 视频编码标准,前面的 “FF” 代表 “Fast Forward”。

FFmpeg 命令行播放音频

FFmpeg 提供了现成的程序 ffplay 用命令行的方式对音频进行播放。

>ffplay.exe "D:\You're Beautiful.mp3"
ffplay version 3.3.3 Copyright (c) 2003-2017 the FFmpeg developers
Input #0, mp3, from 'D:\You're Beautiful.mp3':
  Metadata:
    … …
    artist          : James Blunt
    title           : You're Beautiful
    date            : 2006
  Duration: 00:03:24.30, start: 0.025057, bitrate: 192 kb/s
    Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 192 kb/s
    Metadata:
      encoder       : LAME3.96r
  10.58 M-A:  0.000 fd=0 aq=27KB vq=0KB sq=0B f=0/0 ← 此处是正在播放的音频信息,会实时变化

FFmpeg + SDL 播放音频

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用 C 语言写成。SDL 提供了数种控制图像、声音、输入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X 等)的应用软件。目前 SDL 多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

我们将利用 FFmpeg 进行解码,然后用 SDL 进行播放。

在播放前,可以在控制台输入 ffmpeg -formats 查看支持的音视频格式(muxers / demuxers):

> ffmpeg -formats
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 8.2.1 (GCC) 20181017
  libavformat    58. 20.100 / 58. 20.100
  ... ...
File formats:
 D. = Demuxing supported
 .E = Muxing supported
 --
 D  3dostr          3DO STR
  E 3g2             3GP2 (3GPP2 file format)
  E 3gp             3GP (3GPP file format)
 D  4xm             4X Technologies
  E a64             a64 - video for Commodore 64
 D  aa              Audible AA format files
 D  aac             raw ADTS AAC (Advanced Audio Coding)
 DE ac3             raw AC-3
 D  acm             Interplay ACM
 D  act             ACT Voice file format
 D  adf             Artworx Data Format
 D  adp             ADP
 D  ads             Sony PS2 ADS
  E adts            ADTS AAC (Advanced Audio Coding)
 DE adx             CRI ADX
 ... ...

输入ffmpeg -codecs 可以查看支持的编解码器:

> ffmpeg.exe -codecs
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 8.2.1 (GCC) 20181017
  libavcodec     58. 35.100 / 58. 35.100
  ... ...
Codecs:
 D..... = Decoding supported
 .E.... = Encoding supported
 ..V... = Video codec
 ..A... = Audio codec
 ..S... = Subtitle codec
 ...I.. = Intra frame-only codec
 ....L. = Lossy compression
 .....S = Lossless compression
 -------
 D.VI.S 012v                 Uncompressed 4:2:2 10-bit
 D.V.L. 4xm                  4X Movie
 D.VI.S 8bps                 QuickTime 8BPS video
 .EVIL. a64_multi            Multicolor charset for Commodore 64 (encoders: a64multi )
 .EVIL. a64_multi5           Multicolor charset for Commodore 64, extended with 5th color (colram) (encoders: a64multi5 )
 D.V..S aasc                 Autodesk RLE
 D.VIL. aic                  Apple Intermediate Codec
 DEVI.S alias_pix            Alias/Wavefront PIX image
 DEVIL. amv                  AMV Video
 D.V.L. anm                  Deluxe Paint Animation
 D.V.L. ansi                 ASCII/ANSI art
 DEV..S apng                 APNG (Animated Portable Network Graphics) image
 DEVIL. asv1                 ASUS V1
 DEVIL. asv2                 ASUS V2
... ...

播放流程

FFmpeg + SDL audio playback

播放代码

音频播放需要匹配解码后的音频格式和 Render 要求的音频格式,这个过程就是重采样(resampling),在 音频采集 via FFmpeg 这篇博文中有做过简单介绍。在 FFmpeg中,有两种方法进行重采样:

  1. 使用 resampler (SwrContext)
  2. 使用 filter (AVFilterGraph)
    盗用 DShow 中的 Filter Graph ╭∩╮(︶︿︶)╭∩╮

本文中的代码基于 FFmpeg 4.1。

  1. 以下是使用 resampler 进行播放的概要代码,略去各个函数的具体实现和资源释放
    audio_stream_idx = open_input_file(audio_file, AVMEDIA_TYPE_AUDIO, &fmt_ctx, &dec_ctx);
    hr = init_resampler(dec_ctx, OUT_CHANNELS, OUT_SAMPLE_FMT, OUT_SAMPLE_RATE, &resample_ctx);
    hr = init_fifo(&g_fifo, OUT_SAMPLE_FMT, OUT_CHANNELS);
    
    hr = sdl_helper.init(sdl_fill_audio);
    hr = sdl_helper.run();    
    
    g_out_audio_info.channels = OUT_CHANNELS;
    g_out_audio_info.channel_layout = av_get_default_channel_layout(OUT_CHANNELS);
    g_out_audio_info.sample_format = OUT_SAMPLE_FMT;
    g_out_audio_info.sample_rate = OUT_SAMPLE_RATE;
    g_out_audio_info.frame_size = OUT_FRAME_SIZE;
    
    while (_kbhit() == 0) {
   
   
        hr = audio_process(fmt_ctx, dec_ctx, &g_out_audio_info, g_fifo, 
                resample_ctx, audio_stream_idx, &g_finished, NULL, on_audio_proc);
        if (g_finished)
            break;
    }
  1. 以下是使用 filter 进行播放的概要代码,略去各个函数的具体实现和资源释放
    audio_stream_idx = open_input_file(audio_file, AVMEDIA_TYPE_AUDIO, &fmt_ctx, &dec_ctx);
    
    sprintf_s(filter_descr, "aresample=%d,aformat=sample_fmts=s16:channel_layouts=%s", 
        OUT_SAMPLE_RATE, OUT_CHANNELS == 1 ? "mono" : "stereo");
    hr = aud_filter.init(dec_ctx, fmt_ctx->streams[audio_stream_idx]->time_base, filter_descr);
    
    hr = init_fifo(&g_fifo, OUT_SAMPLE_FMT, OUT_CHANNELS);
    
    hr = sdl_helper.init(sdl_fill_audio);
    hr = sdl_helper.run();    
    
    g_out_audio_info.channels =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值