zoukankan      html  css  js  c++  java
  • 音视频之播放PCM(七)

    使用命令行播放-ffplay

    可以使用ffplay播放我们在上面博客中录制好的PCm文件,测试一下是否录制成功。
    播放PCM需要指定相关参数: 

    • ar: 采样率
    • ac: 声道数
    • f: 采样格式
      • s16le: PCM signed 16-bit little-endian
      • 更多PCM的采样格式可以使用命令查看
        • Windows: ffmpeg -formats | findstr OCM
        • Mac: ffmpeg -formats | grep PCM

    播放命令如下:

    ffplay -ar 44100 -ac 2 -f s16le /Users/muzi/Desktop/out.pcm 

    借助SDL使用代码播放

    简介

    SDL全称 Simple DirectMedia Layer,是一个跨平台的C语言多媒体开发库。 

    • 支持Windows、Mac OSX、Linux、iOS、Android
    • 提供对音频、键盘、鼠标、游戏操纵杆、图形硬件的底层访问
    • 很多的视频播放软件、模拟器、受欢迎的游戏都在使用它
    • 目前最新的稳定版本是: 2.0.16
    • API文档: wiki

    安装环境

    brew官网可以看的出来:之前执行 brew install ffmpeg时,已经顺带安装了SDL,安装目录是: /usr/local/Cellar/sdl2。如果没有这个目录,就执行brew install sdl2进行安装即可。

    配置

    .pro文件

    win32 {
        SDL_HOME = /muzi
    }
    
    mac {
        SDL_HOME = /usr/local/Cellar/sdl2/2.0.16
    }
    
    INCLUDEPATH += $${SDL_HOME}/include
    
    LIBS += -L $${SDL_HOME}/lib 
            -lSDL2

    播放PCM

    初始化子系统

    SDL分成好多个子系统: 

    • Video: 显示和窗口管理
    • Audio: 音频设备管理
    • Joystick: 游戏摇杆控制
    • Timers: 定时器
    • ...

    目前只用到了音频功能,所以只需要通过SDL_init函数初始化Audio子系统即可。

    打开音频设备

    // 音频参数
        SDL_AudioSpec spec;
        // 采样率
        spec.freq = SAMPLE_RATE;
        // 采样格式 (s16le)
        spec.format = AUDIO_S16LSB;
        // 声道数
        spec.channels = CHANNELS;
        // 音频缓冲区的样本数量(这个值必须是2的幂)
        spec.samples = 1024;
        // 回调
        spec.callback = pull_audio_data;
        AudioBuffer buffer;
        spec.userdata = &buffer;
    
        // 打开设备
        if (SDL_OpenAudio(&spec, nullptr)) {
            qDebug() << "SDL_OpenAudio error" << SDL_GetError();
            // 清除所有的子系统
            SDL_Quit();
            return;
        }

    打开文件

    // 打开文件
        QFile file(FILENAME);
        if (!file.open(QFile::ReadOnly)) {
            qDebug() << "file open error" << FILENAME;
            // 关闭设备
            SDL_CloseAudio();
            // 清除所有的子系统
            SDL_Quit();
            return;
        }

    开始播放

    // 开始播放 (0是取消暂停)
        SDL_PauseAudio(0);
        qDebug() << BUFFER_SIZE << "BUFFER_SIZE";
        // 存放从文件中读取的数据
            Uint8 data[BUFFER_SIZE];
            while (!isInterruptionRequested()) {
                // 只要从文件中读取的音频数据,还没有填充完毕,就跳过
                if (buffer.len > 0) continue;
    
                buffer.len = file.read((char *) data, BUFFER_SIZE);
    
                // 文件数据已经读取完毕
                if (buffer.len <= 0) {
                    // 剩余的样本数量
                    int samples = buffer.pullLen / BYTES_PER_SAMPLE;
                    int ms = samples * 1000 / SAMPLE_RATE;
                    SDL_Delay(ms);
                    break;
                }
    
                // 读取到了文件数据
                buffer.data = data;
            }

    回调函数

    // 等待音频设备回调(会回调多次)
    void pull_audio_data(void *userdata,
                         Uint8 *stream, // 需要往stream中填充PCM数据
                         int len) { // 希望填充的大小(samples * format * channels / 8)
        qDebug() << "pull_audio_data" << len;
    
        // 清空stream (静音处理)
        SDL_memset(stream, 0 , len);
    
        // 取出AudioBuffer
        AudioBuffer *buffer = (AudioBuffer *)userdata;
    
        // 文件数据还没准备好
        if (buffer->len <= 0) return;
    
        // 取len、bufferLen的最小值(为了保证数据安全,防止指针越界)
        buffer->pullLen = (len > buffer->len) ? buffer->len : len;
    
        // 填充数据
        SDL_MixAudio(stream, buffer->data, buffer->pullLen, SDL_MIX_MAXVOLUME);
        buffer->data += buffer->pullLen;
        buffer->len -= buffer->pullLen;
    }

    释放资源

     // 关闭文件
        file.close();
    
        // 关闭设备
        SDL_CloseAudio();
    
        // 清除所有的子系统
        SDL_Quit();
  • 相关阅读:
    oldboy_09_03day_test1
    oldboy_09_03day
    java消息队列
    es6语法([...arr], set/map数据结构,数组扩展,箭头函数等)
    Angular 2 Expression Changed After It Has Been Checked Exception
    jQuery之Deferred对象详解
    js面向对象:Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
    Angular 4.x 动态创建组件
    JS中this的四种用法
    typescript主键自增长
  • 原文地址:https://www.cnblogs.com/muzichenyu/p/15494111.html
Copyright © 2011-2022 走看看