基于linux下的音视频采集与传输.docx

上传人:b****1 文档编号:1976846 上传时间:2023-05-02 格式:DOCX 页数:89 大小:114.02KB
下载 相关 举报
基于linux下的音视频采集与传输.docx_第1页
第1页 / 共89页
基于linux下的音视频采集与传输.docx_第2页
第2页 / 共89页
基于linux下的音视频采集与传输.docx_第3页
第3页 / 共89页
基于linux下的音视频采集与传输.docx_第4页
第4页 / 共89页
基于linux下的音视频采集与传输.docx_第5页
第5页 / 共89页
基于linux下的音视频采集与传输.docx_第6页
第6页 / 共89页
基于linux下的音视频采集与传输.docx_第7页
第7页 / 共89页
基于linux下的音视频采集与传输.docx_第8页
第8页 / 共89页
基于linux下的音视频采集与传输.docx_第9页
第9页 / 共89页
基于linux下的音视频采集与传输.docx_第10页
第10页 / 共89页
基于linux下的音视频采集与传输.docx_第11页
第11页 / 共89页
基于linux下的音视频采集与传输.docx_第12页
第12页 / 共89页
基于linux下的音视频采集与传输.docx_第13页
第13页 / 共89页
基于linux下的音视频采集与传输.docx_第14页
第14页 / 共89页
基于linux下的音视频采集与传输.docx_第15页
第15页 / 共89页
基于linux下的音视频采集与传输.docx_第16页
第16页 / 共89页
基于linux下的音视频采集与传输.docx_第17页
第17页 / 共89页
基于linux下的音视频采集与传输.docx_第18页
第18页 / 共89页
基于linux下的音视频采集与传输.docx_第19页
第19页 / 共89页
基于linux下的音视频采集与传输.docx_第20页
第20页 / 共89页
亲,该文档总共89页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

基于linux下的音视频采集与传输.docx

《基于linux下的音视频采集与传输.docx》由会员分享,可在线阅读,更多相关《基于linux下的音视频采集与传输.docx(89页珍藏版)》请在冰点文库上搜索。

基于linux下的音视频采集与传输.docx

基于linux下的音视频采集与传输

摘要:

在LINUX下实现对音频和视频的采集,并编写Socket程序将采集到的音频文件在两台主机的进程之间进行传输。

关键字:

LINUX音频、视频采集Socket传输

项目简介

本项目将分成三部分来分别实现,分别为Linux下视频的采集、Linux下音频的采集、Linux下Socket传输的实现。

下面将分别介绍各部分具体的实现过程。

Linux下视频采集

1、背景介绍

V4L,其全称是Video4Linux(VideoforLinux),是在linux内核中关于视频设备的API接口,涉及开关视频设备、采集并处理视频图像信息。

V4L从2.1.x版本的内核中开始出现。

现在出现Video4Linux2(VideoforLinuxTwo),简称V4L2。

很显然,他是V4L的改进版,修复了第一代的部分设计bug。

从2.5.x开始,V4L2就被集成到内核里面去了。

尽管如此,还是有一部分设备的驱动不支持新版本的V4L2,所以,有时候我们会看到V4L跟V4L2同时出现在代码里面。

Linux系统中,视频设备被当作一个设备文件来看待,设备文件存放在/dev目录下,完整路径的设备文件名为:

/dev/video0.

2、视频采集基本步骤

视频采集基本步骤流程:

打开设备->检查和设置设备属性->设置帧格式->设置一种输入输出方法(缓冲区管理)->循环获取数据->关闭设备。

其中打开视频设备非常简单,在V4L2中,视频设备被看做一个文件。

使用open函数打开这个设备,打开这个设备有两种模式即阻塞模式和非阻塞模式。

主要实现代码为:

用非阻塞模式打开摄像头设备代码为

intcameraFd;

cameraFd=open("/dev/video0",O_RDWR|O_NONBLOCK);

用阻塞模式打开摄像头设备,上述代码变为:

cameraFd=open("/dev/video0",O_RDWR);

应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。

3、Linux视频设备驱动常用控制命令使用说明

设置视频设备属性通过ioctl来进行设置,ioctl有三个参数,分别是fd,cmd,和parameter,表示设备描述符,控制命令和控制命令参数。

Linux视频设备驱动接口V4L2支持的常用控制命令如下:

控制命令VIDIOC_ENUM_FMT

功能:

获取当前视频设备支持的视频格式。

参数说明:

参数类型为V4L2的视频格式描述符类型structv4l2_fmtdesc

返回值说明:

执行成功时,函数返回值为0;structv4l2_fmtdesc结构体中的.pixelformat和.description成员返回当前视频设备所支持的视频格式;

使用举例:

structv4l2_fmtdescfmt;

memset(&fmt,0,sizeof(fmt));

fmt.index=0;

fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

while((ret=ioctl(dev,VIDIOC_ENUM_FMT,&fmt))==0){

fmt.index++;

printf("{pixelformat=''%c%c%c%c'',description=''%s''}\n",

fmt.pixelformat&0xFF,(fmt.pixelformat>>8)&0xFF,

(fmt.pixelformat>>16)&0xFF,(fmt.pixelformat>>24)&0xFF,

fmt.description);

}

控制命令VIDIOC_QUERYCAP

功能:

查询视频设备的功能;

参数说明:

参数类型为V4L2的能力描述类型structv4l2_capability;

返回值说明:

执行成功时,函数返回值为0;函数执行成功后,structv4l2_capability结构体变量中的返回当前视频设备所支持的功能;例如支持视频捕获功能V4L2_CAP_VIDEO_CAPTURE、V4L2_CAP_STREAMING等。

使用举例:

structv4l2_capabilitycap;

iret=ioctl(fd_usbcam,VIDIOC_QUERYCAP,&cap);

if(iret<0)

{

printf("getvidieocapabilityerror,errorcode:

%d\n",errno);

return;

}

执行完VIDIOC_QUERYCAP命令后,cap变量中包含了该视频设备的能力信息,程序中通过检查cap中的设备能力信息来判断设备是否支持某项功能。

控制命令VIDIOC_S_FMT

功能:

设置视频设备的视频数据格式,例如设置视频图像数据的长、宽,图像格式(JPEG、YUYV格式);

参数说明:

参数类型为V4L2的视频数据格式类型structv4l2_format;

返回值说明:

执行成功时,函数返回值为0;

使用举例:

structv4l2_formattv4l2_format;

tv4l2_format.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

tv4l2_format.fmt.pix.width=img_width;

tv4l2_format.fmt.pix.height=img_height;

tv4l2_format.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;

tv4l2_format.fmt.pix.field=V4L2_FIELD_INTERLACED;

iret=ioctl(fd_usbcam,VIDIOC_S_FMT,&tv4l2_format);

控制命令VIDIOC_REQBUFS

功能:

请求V4L2驱动分配视频缓冲区(申请V4L2视频驱动分配内存),V4L2是视频设备的驱动层,位于内核空间,所以通过VIDIOC_REQBUFS控制命令字申请的内存位于内核空间,应用程序不能直接访问,需要通过调用mmap内存映射函数把内核空间内存映射到用户空间后,应用程序通过访问用户空间地址来访问内核空间。

参数说明:

参数类型为V4L2的申请缓冲区数据结构体类型structv4l2_requestbuffers;

返回值说明:

执行成功时,函数返回值为0;V4L2驱动层分配好了视频缓冲区;

使用举例:

structv4l2_requestbufferstV4L2_reqbuf;

memset(&tV4L2_reqbuf,0,sizeof(structv4l2_requestbuffers));

tV4L2_reqbuf.count=1;

tV4L2_reqbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

tV4L2_reqbuf.memory=V4L2_MEMORY_MMAP;

iret=ioctl(fd_usbcam,VIDIOC_REQBUFS,&tV4L2_reqbuf);

注意:

VIDIOC_REQBUFS会修改tV4L2_reqbuf的count值,tV4L2_reqbuf的count值返回实际申请成功的视频缓冲区数目;

控制命令VIDIOC_QUERYBUF

功能:

查询已经分配的V4L2的视频缓冲区的相关信息,包括视频缓冲区的使用状态、在内核空间的偏移地址、缓冲区长度等。

在应用程序设计中通过调VIDIOC_QUERYBUF来获取内核空间的视频缓冲区信息,然后调用函数mmap把内核空间地址映射到用户空间,这样应用程序才能够访问位于内核空间的视频缓冲区。

参数说明:

参数类型为V4L2缓冲区数据结构类型structv4l2_buffer;

返回值说明:

执行成功时,函数返回值为0;structv4l2_buffer结构体变量中保存了指令的缓冲区的相关信息;

一般情况下,应用程序中调用VIDIOC_QUERYBUF取得了内核缓冲区信息后,紧接着调用mmap函数把内核空间地址映射到用户空间,方便用户空间应用程序的访问。

使用举例:

structv4l2_buffertV4L2buf;

memset(&tV4L2buf,0,sizeof(structv4l2_buffer));

tV4L2buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

tV4L2buf.memory=V4L2_MEMORY_MMAP;

tV4L2buf.index=i;

iret=ioctl(fd_usbcam,VIDIOC_QUERYBUF,&tV4L2buf);

AppBufLength=tV4L2buf.length;

AppBufStartAddr=mmap(NULL/*startanywhere*/,

tV4L2buf.length,

PROT_READ|PROT_WRITE/*accessprivilege*/,

MAP_SHARED/*recommended*/,

fd_usbcam,tV4L2buf.m.offset);

上述代码在通过调用VIDIOC_QUERYBUF取得内核空间的缓冲区信息后,接着调用mmap函数把内核空间缓冲区映射到用户空间。

控制命令VIDIOC_QBUF

功能:

投放一个空的视频缓冲区到视频缓冲区输入队列中;

参数说明:

参数类型为V4L2缓冲区数据结构类型structv4l2_buffer;

返回值说明:

执行成功时,函数返回值为0;函数执行成功后,指令(指定)的视频缓冲区进入视频输入队列,在启动视频设备拍摄图像时,相应的视频数据被保存到视频输入队列相应的视频缓冲区中。

使用举例:

structv4l2_buffertV4L2buf;

memset(&tV4L2buf,0,sizeof(structv4l2_buffer));

tV4L2buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

tV4L2buf.memory=V4L2_MEMORY_MMAP;

tV4L2buf.index=i;

iret=ioctl(fd_usbcam,VIDIOC_QBUF,&tV4L2buf);

控制命令VIDIOC_STREAMON

功能:

启动视频采集命令,应用程序调用VIDIOC_STREAMON启动视频采集命令后,视频设备驱动程序开始采集视频数据,并把采集到的视频数据保存到视频驱动的视频缓冲区中。

参数说明:

参数类型为V4L2的视频缓冲区类型enumv4l2_buf_type;

返回值说明:

执行成功时,函数返回值为0;函数执行成功后,视频设备驱动程序开始采集视频数据,此时应用程序一般通过调用select函数来判断一帧视频数据是否采集完成,当视频设备驱动完成一帧视频数据采集并保存到视频缓冲区中时,select函数返回,应用程序接着可以读取视频数据;否则select函数阻塞直到视频数据采集完成。

使用举例:

enumv4l2_buf_typev4l2type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

fd_setfds;

structtimevaltv;

iret=ioctl(fd_usbcam,VIDIOC_STREAMON,&v4l2type);

FD_ZERO(&fds);

FD_SET(fd_usbcam,&fds);

tv.tv_sec=2;/*Timeout.*/

tv.tv_usec=0;

iret=select(fd_usbcam+1,&fds,NULL,NULL,&tv);

控制命令VIDIOC_DQBUF

功能:

从视频缓冲区的输出队列中取得一个已经保存有一帧视频数据的视频缓冲区;

参数说明:

参数类型为V4L2缓冲区数据结构类型structv4l2_buffer

返回值说明:

执行成功时,函数返回值为0;函数执行成功后,相应的内核视频缓冲区中保存有当前拍摄到的视频数据,应用程序可以通过访问用户空间来读取该视频数据。

(前面已经通过调用函数mmap做了用户空间和内核空间的内存映射).

使用举例:

structv4l2_buffertV4L2buf;

memset(&tV4L2buf,0,sizeof(structv4l2_buffer));

tV4L2buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

tV4L2buf.memory=V4L2_MEMORY_MMAP;

iret=ioctl(fd_usbcam,VIDIOC_DQBUF,&tV4L2buf);

Sasoritattoo注释:

VIDIOC_DQBUF命令结果使从队列删除的缓冲帧信息传给了此tVL2buf。

V4L2_buffer结构体的作用就相当于申请的缓冲帧的代理,找缓冲帧的都要先问问它,通过它来联系缓冲帧,起了中间桥梁的作用。

控制命令VIDIOC_STREAMOFF

功能:

停止视频采集命令,应用程序调用VIDIOC_STREAMOFF停止视频采集命令后,视频设备驱动程序不在采集视频数据。

参数说明:

参数类型为V4L2的视频缓冲区类型enumv4l2_buf_type;

返回值说明:

执行成功时,函数返回值为0;函数执行成功后,视频设备停止采集视频数据。

使用举例:

enumv4l2_buf_typev4l2type;

v4l2type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

iret=ioctl(fd_usbcam,VIDIOC_STREAMOFF,&v4l2type);

4、YUYV转换为RGB

由于摄像头支持的视频格式为YUYV,不能直接显示,所以将其转换为RGB格式,以方便下一步的图片保存以及视频保存。

像素转换算法如下:

r=y+(1.370705*(v-128));

g=y-(0.698001*(v-128))-(0.337633*(u-128));

b=y+(1.732446*(u-128));

if(r>255)r=255;

if(g>255)g=255;

if(b>255)b=255;

if(r<0)r=0;

if(g<0)g=0;

if(b<0)b=0;

pixel[0]=r*220/256;

pixel[1]=g*220/256;

pixel[2]=b*220/256;

Linux下音频采集

1、背景介绍

(1)ALSA

ALSA是AdvancedLinuxSoundArchitecture,高级Linux声音架构的简称,它在Linux操作系统上提供了音频和MIDI(MusicalInstrumentDigitalInterface,音乐设备数字化接口)的支持。

在2.6系列内核中,ALSA已经成为默认的声音子系统,用来替换2.4系列内核中的OSS(OpenSoundSystem,开放声音系统)。

ALSA的主要特性包括:

高效地支持从消费类入门级声卡到专业级音频设备所有类型的音频接口,完全模块化的设计,支持对称多处理(SMP)和线程安全,对OSS的向后兼容,以及提供了用户空间的alsa-lib库来简化应用程序的开发。

ALSA是一个完全开放源代码的音频驱动程序集,除了像OSS那样提供了一组内核驱动程序模块之外,ALSA还专门为简化应用程序的编写提供了相应的函数库,与OSS提供的基于ioctl的原始编程接口相比,ALSA函数库使用起来要更加方便一些。

利用该函数库,开发人员可以方便快捷的开发出自己的应用程序,细节则留给函数库内部处理。

当然ALSA也提供了类似于OSS的系统接口,不过ALSA的开发者建议应用程序开发者使用音频函数库而不是驱动程序的API。

(2)音频采集概念

数码音频系统是通过将声波波形转换成一连串的二进制数据来再现原始声音的,实现这个步骤使用的设备是模/数转换器(A/D)它以每秒上万次的速率对声波进行采样,每一次采样都记录下了原始模拟声波在某一时刻的状态,称之为样本。

将一串的样本连接起来,就可以描述一段声波了,把每一秒钟所采样的数目称为采样频率或采率,单位为HZ(赫兹)。

采样频率越高所能描述的声波频率就越高。

采样率决定声音频率的范围(相当于音调),可以用数字波形表示。

以波形表示的频率范围通常被称为带宽。

要正确理解音频采样可以分为采样的位数和采样的频率。

(3)主要参数

①采样位数

采样位数可以理解为采集卡处理声音的解析度。

这个数值越大,解析度就越高,录制和回放的声音就越真实。

我们首先要知道:

电脑中的声音文件是用数字0和1来表示的。

所以在电脑上录音的本质就是把模拟声音信号转换成数字信号。

反之,在播放时则是把数字信号还原成模拟声音信号输出。

采集卡的位是指采集卡在采集和播放声音文件时所使用数字声音信号的二进制位数。

采集卡的位客观地反映了数字声音信号对输入声音信号描述的准确程度。

8位代表2的8次方--256,16位则代表2的16次方--64K。

比较一下,一段相同的音乐信息,16位声卡能把它分为64K个精度单位进行处理,而8位声卡只能处理256个精度单位,造成了较大的信号损失,最终的采样效果自然是无法相提并论的。

如今市面上所有的主流产品都是16位的采集卡,而并非有些无知商家所鼓吹的64位乃至128位,他们将采集卡的复音概念与采样位数概念混淆在了一起。

如今功能最为强大的采集卡系列采用的EMU10K1芯片虽然号称可以达到32位,但是它只是建立在DirectSound加速基础上的一种多音频流技术,其本质还是一块16位的声卡。

应该说16位的采样精度对于电脑多媒体音频而言已经绰绰有余了。

②采样频率

数码音频系统是通过将声波波形转换成一连串的二进制数据来再现原始声音的,实现这个步骤使用的设备是模/数转换器(A/D)它以每秒上万次的速率对声波进行采样,每一次采样都记录下了原始模拟声波在某一时刻的状态,称之为样本。

将一串的样本连接起来,就可以描述一段声波了,把每一秒钟所采样的数目称为采样频率或采率,单位为HZ(赫兹)。

采样频率越高所能描述的声波频率就越高。

采样频率是指录音设备在一秒钟内对声音信号的采样次数,采样频率越高声音的还原就越真实越自然。

在当今的主流采集卡上,采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级,22.05KHz只能达到FM广播的声音品质,44.1KHz则是理论上的CD音质界限,48KHz则更加精确一些。

对于高于48KHz的采样频率人耳已无法辨别出来了,所以在电脑上没有多少使用价值。

5kHz的采样率仅能达到人们讲话的声音质量。

11kHz的采样率是播放小段声音的最低标准,是CD音质的四分之一。

22kHz采样率的声音可以达到CD音质的一半,目前大多数网站都选用这样的采样率。

44kHz的采样率是标准的CD音质,可以达到很好的听觉效果。

③位速

位速是指在一个数据流中每秒钟能通过的信息量。

您可能看到过音频文件用“128–KbpsMP3”或“64–KbpsWMA”进行描述的情形。

Kbps表示“每秒千位数”,因此数值越大表示数据越多:

128–KbpsMP3音频文件包含的数据量是64–KbpsWMA文件的两倍,并占用两倍的空间。

(不过在这种情况下,这两种文件听起来没什么两样。

原因是什么呢?

有些文件格式比其他文件能够更有效地利用数据,64–KbpsWMA文件的音质与128–KbpsMP3的音质相同。

)需要了解的重要一点是,位速越高,信息量越大,对这些信息进行解码的处理量就越大,文件需要占用的空间也就越多。

为项目选择适当的位速取决于播放目标:

如果您想把制作的VCD放在DVD播放器上播放,那么视频必须是1150Kbps,音频必须是224Kbps。

典型的206MHzPocketPC支持的MPEG视频可达到400Kbps—超过这个限度播放时就会出现异常。

(4)ALSA体系结构

ALSAAPI可以分解成以下几个主要的接口:

1控制接口:

提供管理声卡注册和请求可用设备的通用功能

2PCM接口:

管理数字音频回放(playback)和录音(capture)的接口。

本文后续总结重点放在这个接口上,因为它是开发数字音频程序最常用到的接口。

3RawMIDI接口:

支持MIDI(MusicalInstrumentDigitalInterface),标准的电子乐器。

这些API提供对声卡上MIDI总线的访问。

这个原始接口基于MIDI事件工作,由程序员负责管理协议以及时间处理。

4定时器(Timer)接口:

为同步音频事件提供对声卡上时间处理硬件的访问。

5时序器(Sequencer)接口

6混音器(Mixer)接口

2、声音缓存和数据传输

每个声卡都有一个硬件缓存区来保存记录下来的样本。

当缓存区足够满时,声卡将产生一个中断。

内核声卡驱动然后使用直接内存(DMA)访问通道将样本传送到内存中的应用程序缓存区。

类似地,对于回放,任何应用程序使用DMA将自己的缓存区数据传送到声卡的硬件缓存区中。

这样硬件缓存区是环缓存。

也就是说当数据到达缓存区末尾时将重新回到缓存区的起始位置。

ALSA维护一个指针来指向硬件缓存以及应用程序缓存区中数据操作的当前位置。

  应用程序缓存区的大小可以通过ALSA库函数调用来控制。

缓存区可以很大,一次传输操作可能会导致不可接受的延迟,我们把它称为延时(latency)。

为了解决这个问题,ALSA将缓存区拆分成一系列周期(period)(OSS/Free中叫片断fragments)。

ALSA以period为单元来传送数据。

一个周期(period)存储一些帧(frames)。

每一帧包含时间上一个点所抓取的样本。

对于立体声设备,一个帧会包含两个信道上的样本。

其分解过程:

一个缓存区分解成周期,然后是帧,然后是样本。

左右信道信息被交替地存储在一个帧内。

这称为交错(interleaved)模式。

在非交错模式中,一个信道的所有样本数据存储在另外一个信道的数据之后。

OverandUnderRun

  当一个声卡活动时,数据总是连续地在硬件缓存区和应用程序缓存区间传输。

但是也有例外。

在录音例子中,如果应用程序读取数据不够快,循环缓存区将会被新的数据覆盖。

这种数据的丢失被称为overrun.在回放例子中,如果应用程序写入数据到缓存区中的速度不够快,缓存区将会"饿死"。

这样的错误被称为"underrun"。

在ALSA文档中,有时将这两种情形统称为"XRUN"。

适当地设计应用程序可以最小化XRUN并且可以从中恢复过来。

使用PCM的程序通常类似下面的伪代码:

打开

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2