【MediaFoundation】OpenCV VideoCapture 读取音频源码

2024-01-09 09:04

本文主要是介绍【MediaFoundation】OpenCV VideoCapture 读取音频源码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OpenCV 读取音频代码实例

在windows7 以及OpenCV4 过后可以使用 CAP_MSMF 读取音频,但是OpenCV没有播放音频的API。代码示例如下。 本文解析OpenCVCAP_MSMF 进行文件、设备的 音频读取,学习MediaFoundation 的使用。

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;int main(int argc, const char** argv)
{Mat videoFrame;Mat audioFrame;vector<vector<Mat>> audioData;VideoCapture cap;vector<int> params {    CAP_PROP_AUDIO_STREAM, 0,CAP_PROP_VIDEO_STREAM, -1,CAP_PROP_AUDIO_DATA_DEPTH, CV_32F   };//cap.open(file, CAP_MSMF, params);// 打开第一个音频输入设备cap.open(0, CAP_MSMF, params);if (!cap.isOpened()){cerr << "ERROR! Can't to open file: " + file << endl;return -1;}const int audioBaseIndex = (int)cap.get(CAP_PROP_AUDIO_BASE_INDEX);const int numberOfChannels = (int)cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS);cout << "CAP_PROP_AUDIO_DATA_DEPTH: " << depthToString((int)cap.get(CAP_PROP_AUDIO_DATA_DEPTH)) << endl;cout << "CAP_PROP_AUDIO_SAMPLES_PER_SECOND: " << cap.get(CAP_PROP_AUDIO_SAMPLES_PER_SECOND) << endl;cout << "CAP_PROP_AUDIO_TOTAL_CHANNELS: " << cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS) << endl;cout << "CAP_PROP_AUDIO_TOTAL_STREAMS: " << cap.get(CAP_PROP_AUDIO_TOTAL_STREAMS) << endl;int numberOfSamples = 0;int numberOfFrames = 0;audioData.resize(numberOfChannels);mfcap::AudioOutput audioOutput;audioOutput.Open((int)cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS),(int)cap.get(CAP_PROP_AUDIO_SAMPLES_PER_SECOND),16);for (;;){if (cap.grab()){//cap.retrieve(videoFrame);std::vector<const unsigned char*> planes;planes.resize(numberOfChannels);for (int nCh = 0; nCh < numberOfChannels; nCh++){cap.retrieve(audioFrame, audioBaseIndex+nCh);if (!audioFrame.empty()){audioData[nCh].push_back(audioFrame);//planes[nCh] = audioFrame.data + nCh * audioFrame.cols;}numberOfSamples+=audioFrame.cols;}} else { break; }}cout << "Number of audio samples: " << numberOfSamples << endl<< "Number of video frames: " << numberOfFrames << endl;return 0;
}

打开设备

bool CvCapture_MSMF::open(int index, const cv::VideoCaptureParameters* params)
{// 先重置环境close();if (index < 0)return false;if (params){// 开启硬件编解码加速,这里先省略,在后面的硬件加速上学习。configureHW(*params);/* configureStream 主要是配置是否捕获音频或视频流// 如果需要捕获音频流: audioStream = 0 否者 audioStream  = -1// 视频流同理,对应的变量为: videoStream*//* setAudioProperties // outputAudioFormat: 音频的位深, CV_16S 等// audioSamplesPerSecond 采样率// syncLastFrame: 是否需要音视频同步,OpenCV里面只支持视频文件的音视频同步*/if (!(configureStreams(*params) && setAudioProperties(*params)))return false;}// 仅支持打开音频流或者视频流,不能在一个对象里面打开或者都不打开。if (videoStream != -1 && audioStream != -1 || videoStream == -1 && audioStream == -1){CV_LOG_DEBUG(NULL, "Only one of the properties CAP_PROP_AUDIO_STREAM " << audioStream << " and " << CAP_PROP_VIDEO_STREAM << " must be different from -1");return false;}DeviceList devices;UINT32 count = 0;if (audioStream != -1)count = devices.read(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID);if (videoStream != -1)count = devices.read(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);if (count == 0 || static_cast<UINT32>(index) > count){CV_LOG_DEBUG(NULL, "Device " << index << " not found (total " << count << " devices)");return false;}_ComPtr<IMFAttributes> attr = getDefaultSourceConfig();_ComPtr<IMFSourceReaderCallback> cb = new SourceReaderCB();attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, cb.Get());_ComPtr<IMFMediaSource> src = devices.activateSource(index);if (!src.Get() || FAILED(MFCreateSourceReaderFromMediaSource(src.Get(), attr.Get(), &videoFileSource))){CV_LOG_DEBUG(NULL, "Failed to create source reader");return false;}isOpen = true;device_status = true;camid = index;readCallback = cb;duration = 0;if (configureOutput()){frameStep = captureVideoFormat.getFrameStep();}if (isOpen && !openFinalize_(params)){close();return false;}if (isOpen){if (audioStream != -1)if (!checkAudioProperties())return false;}return isOpen;
}

这篇关于【MediaFoundation】OpenCV VideoCapture 读取音频源码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/586595

相关文章

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

C#实现SHP文件读取与地图显示的完整教程

《C#实现SHP文件读取与地图显示的完整教程》在地理信息系统(GIS)开发中,SHP文件是一种常见的矢量数据格式,本文将详细介绍如何使用C#读取SHP文件并实现地图显示功能,包括坐标转换、图形渲染、平... 目录概述功能特点核心代码解析1. 文件读取与初始化2. 坐标转换3. 图形绘制4. 地图交互功能缩放

java读取excel文件为base64实现方式

《java读取excel文件为base64实现方式》文章介绍使用ApachePOI和EasyExcel处理Excel文件并转换为Base64的方法,强调EasyExcel适合大文件且内存占用低,需注意... 目录使用 Apache POI 读取 Excel 并转换为 Base64使用 EasyExcel 处

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3