Ubuntu下使用Qt和ffmpeg,打开音频采集设备并读取数据

Ubuntu下使用Qt和ffmpeg,打开音频采集设备并读取数据

  1. 引入编译好的ffmpeg库文件和头文件。
    (1)在.pro文件中加入:
unix:!macx: LIBS += -L$$PWD/../../../usr/local/ffmpeg/lib/ 
-lavcodec -lavdevice -lavfilter -lavformat -lavutil -lswresample -lswscale

INCLUDEPATH += $$PWD/../../../usr/local/ffmpeg/include
DEPENDPATH += $$PWD/../../../usr/local/ffmpeg/include

即可引入库文件,库文件路径根据自己的编译路径修改,我的路径是/usr/local/ffmpeg。
(2)也可通过在Qt Creator中引入外部库文件的方式引入ffmpeg。

2.引入所需头文件

extern "C"
{
     
#include "libavdevice/avdevice.h"
#include "libavutil/avutil.h"
#include  "libavformat/avformat.h"
}

注意:ffmpeg是C语言编写的,C++环境下需要加上extern “C”,否则程序编译会报错。

  1. 打开设备
void MainWindow::openDevice()
{
     
    // 注册设备
    avdevice_register_all();

    // 获取采集格式
    AVInputFormat *inputFmt = av_find_input_format("alsa");

    int ret = 0;
    AVFormatContext *fmt_ctx = nullptr;
    char *deviceName = "hw:0,0";
    AVDictionary *options = nullptr;
    // 打开设备
    ret = avformat_open_input(&fmt_ctx, deviceName, inputFmt, &options);

    char errors[1024];
    if (ret < 0)
    {
     
        av_strerror(ret, errors, 1024);
        printf("Failed to open audio device, [%d]%s\n", ret, errors);
    }
}
  1. 从设备读取音频数据
  2. 增加头文件
#include "libavcodec/avcodec.h"

读取代码:

void MainWindow::openDeviceAndReadData()
{
     
    // 设置日志级别
    av_log_set_level(AV_LOG_DEBUG);
    // 注册设备
    avdevice_register_all();

    // 获取采集格式
    AVInputFormat *inputFmt = av_find_input_format("alsa");

    int ret = 0;
    AVFormatContext *fmt_ctx = nullptr;
    char *deviceName = "hw:0,0";
    AVDictionary *options = nullptr;
    // 打开设备
    ret = avformat_open_input(&fmt_ctx, deviceName, inputFmt, &options);

    char errors[1024] = {
     0};
    if (ret < 0)
    {
     
        av_strerror(ret, errors, 1024);
        printf("Failed to open audio device, [%d]%s\n", ret, errors);
        return;
    }

    int count = 0;
    AVPacket packet;

    av_init_packet(&packet);

    // 从设备读取数据
    while ((ret = av_read_frame(fmt_ctx, &packet) == 0) && count++ < 500)
    {
     
        av_log(NULL, AV_LOG_INFO, "Packet size: %d(%p), count = %d\n",
               packet.size, packet.data, count);

        // 释放packet空间
        av_packet_unref(&packet);
    }

    // 关闭设备,释放上下文空间
    avformat_close_input(&fmt_ctx);

    av_log(NULL, AV_LOG_DEBUG, "Finish!\n");

}

使用完上下文AVFormatContext 和AVPacket以后要注意释放空间,避免内存泄漏。

注:1. C语言和C++中手动分配的空间使用完以后要记得释放,避免内存泄漏,否则服务端程序不断申请内存空间而不释放,最终会导致程序崩溃。
2. 指针变量释放以后,要置为NULL,避免野指针。在多线程中,如果在线程1中的指针释放了其指向的内存地址,没有置为NULL,之后这块空间被线程2使用,而此时线程1中的指针依然可以访问并修改这块内存空间,如果线程1中的指针修改了内存内容,则会对线程2造成影响,产生不可估计的后果。

你可能感兴趣的:(ffmpeg基础篇,linux,ffmpeg,qt)