读取USB摄像头的音频数据


之前的一直在操作USB摄像头的视频数据,如今需要读取USB摄像头的音频数据,进行音视频的合成。读取音频数据需要Linux层的ALSA驱动支持,应用层可以采用alsa-lib库,也可以采用tinyalsa库。我这里用的摄像头是罗技C920。

命令操作USB音频设备文件

可以通过alsa-lib库编译出的工具arecord查看USB的音频设备文件,命令:arecord -l

card 2: C920 [HD Pro Webcam C920], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

命令录制音频为WAV文件:arecord -D hw:2,0 -d 10 -f cd -r 32000 -c 2 -t wav test.wav,命令输出如下:

Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 32000 Hz, Stereo
既然提到wav文件,这里就不得不写一下wav文件的格式,以备后面查阅

wav文件格式解析

wav文件格式如下图所示:
在这里插入图片描述
wav文件分为RIFF区、format区、data区,下面进行详细说明

RIFF区

名称 偏移量 字节数 存储格式 内容
ChunkID 0x00 0x04 大端 RIFF(0x52494646)
ChunkSize 0x04 0x04 小端 文件总长度 - 8,不含ChunkID与ChunkSize的字节数
Format 0x08 0x04 大端 ‘WAVE’(0x57415645),文件格式名称
  • wav文件的开始均以’RIFF’为标识
  • ChunkSize:是整个文件的长度减去ChunkID和ChunkSize本身的长度
  • format:用‘WAVE’4个字符表示为wav格式的音频文件

fromat区

名称 偏移量 字节数 存储格式 内容
ChunkID 0x00 0x04 大端 fmt(0x666D7420)
ChunkSize 0x04 0x04 小端 0x10
AudioFormat 0x08 0x02 小端 数据格式,1表示PCM数据格式
NumChannel 0x0A 0x02 小端 音频通道数量
SampleRate 0x0C 0x04 小端 音频采样率
ByteRate 0x10 0x04 小端 每秒钟音频数据字节数
BlockAlign 0x14 0x02 小端 每个采样数据块字节数
BitsPerSample 0x16 0x02 小端 每个采样量化数据的位数
  • ChunkID:fromat区以fmt字符为标识
  • ChunkSize:表示该区块数据的长度,固定为16字节
  • AudioFormat:表示Data区块存储的音频数据的格式,PCM格式值为1
  • NumChannels:表示音频数据的声道数,1:单声道,2:双声道
  • SampleRate:表示音频数据的采样率
  • ByteRate:每秒数据字节数 = SampleRate * NumChannels * BitsPerSample / 8
  • BlockAlign:每个采样所需的字节数 = NumChannels * BitsPerSample / 8
  • BitsPerSample:每个采样存储的bit数,8:8bit,16:16bit,32:32bit,一般采用16位采样

常见音频数据格式:
在这里插入图片描述

data区

名称 偏移量 字节数 存储格式 内容
ChunkID 0x00 0x04 大端 data(0x64617461)
ChunkSize 0x04 0x04 小端 音频数据字节数
data 0x08 0x04 小端 实际的音频数据
  • wav文件的开始均以’RIFF’为标识
  • ChunkSize:是整个文件的长度减去ChunkID和ChunkSize本身的长度
  • format:用‘WAVE’4个字符表示为wav格式的音频文件

从以上可以看出,wav格式的文件起始部分占用44字节,经过以上命令保存的wav格式文件示例如下:

52 49 46 46 24 88 13 00 57 41 56 45 66 6D 74 20 10 00 00 00 01 00 02 00 00 7D 00 00 00 F4 01 00 04 00 10 00 64 61 74 61 00 88 13 00

gstreamer 合成音频为MP3文件

gst-launch-1.0 alsasrc device="hw:2,0" ! audioconvert ! imxmp3enc ! filesink location=mic.mp3
查看MP3文件信息如下:
在这里插入图片描述
这里遇到一个问题,当将USB的H264帧与音频进行合成时,最后视频文件在播放时视频会瞬间播放完成而且会花屏,而音频则数据播放与文件播放时长一致,这个问题还有待查明。
命令如下:
gst-launch-1.0 -e avimux name=mux1 ! filesink location=test.avi \ v4l2src device=/dev/video0 ! video/x-h264, framerate=30/1, width=640, height=360 ! mux1. \ alsasrc device=hw:2,0 ! audio/x-raw, rate=32000, channels=2, layout=interleaved, format=S16LE ! mux1.

用代码读取USB音频文件

使用代码有两种方式:

  • 使用alsa-lib库,
  • 使用tinyalsa-lib库

由于tinyalsa-lib库比较轻量,所以我使用这个库,其仅包含源文件limits.cmixer.cpcm.c;三个源代码文件以及头文件,因此可以直接将其添加到自己的工程文件中。
在读取USB设备的音频之前,必须先找出其对应的设备文件,USB摄像头会生成2种设备文件,分别是video类与Audio类。
如下代码首先定义一个USB摄像头的数据结构,以下定义的数据结构为我自己的工程应用中的简化版

#define USB_VIDEO_BUF_REQ_CNT			16
typedef struct camera_node
{
   
	struct list_head node;
	char id[16];
	int ch;

	//V4L2
	char devname[16];
	int fd;
	struct v4l2_format fmt;
	struct v4l2_streamparm parm;
	struct v4l2_requestbuffers req;
	struct buffer *buffers;
	int n_buffers;
	//ALSA
	int card;
	int device;
	unsigned int pcm_bytes_per_frame;
	struct pcm_config config;
	struct pcm *pcm;

	int thread_return_value;
	unsigned char ch_online;
	unsigned char thread_online;
	unsigned char fps;
	unsigned char has_audio;

	unsigned int width;
	unsigned int height;
	unsigned int bitrate;

	unsigned int audio_buf_head;
	unsigned char audio_buf[AUDIO_BUF_SIZE];
}camera_struct;

程序需要在/sys/class/video4linux目录查找视频设备的文件的信息,在/sys/class/sound目录查找音频设备文件的信息,代码如下:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sched.h>
#include <pthread.h>
#include <time.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <dirent.h>
#include <sys/poll.h>
#include <assert.h>

#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值