MediaRecorder类介绍 方法已经翻译成中文了

2024-05-14 20:08

本文主要是介绍MediaRecorder类介绍 方法已经翻译成中文了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自http://blog.csdn.net/mark_dev/article/details/7249415

1 类得介绍... 2

2 嵌套、关联的类... 2

3 主要方法:... 3

4 流程分析... 8

一、 java层... 8

1、java应用层... 9

2、JAVAFramework层... 10

3、JAVA本地调用部分(JNI):... 10

二、 多媒体底层库... 10

1、ImediaRecorder.cpp. 10

2、Mediarecorder.cpp. 11

3、多媒体服务部分... 12

三、Opencore. 13

四、audioflinger层和audiorecord. 14

1、AudioRecord. 14

2、AudioFlinger 16

五、 硬件抽象层... 18

5主要能设置列举... 20

 

1 类得介绍

它用来记录音频和视频,记录控制基于一个简单的状态机,下边的图片是整个流程

 

2 嵌套、关联的类

 

class

MediaRecorder.AudioEncoder

定义音频编码

class

MediaRecorder.AudioSource

定义声音资源

interface

MediaRecorder.OnErrorListener

Interface definition for a callback to be invoked when an error occurs while recording. 

interface

MediaRecorder.OnInfoListener

Interface definition for a callback to be invoked when an error occurs while recording. 

class

MediaRecorder.OutputFormat

定义输出格式

class

MediaRecorder.VideoEncoder

定义视频编码

class

MediaRecorder.VideoSource

定义视频source

 

 

 

 

 

3 主要方法:

final static int

getAudioSourceMax()

Gets the maximum value for audio sources.

获取音频信号源的最高值。

 

int

getMaxAmplitude()

Returns the maximum absolute amplitude that was sampled since the last call to this method.

最后调用这个方法采样的时候返回最大振幅的绝对值

void

prepare()

Prepares the recorder to begin capturing and encoding data.

准备recorder 开始捕获和编码数据

void

release()

Releases resources associated with this MediaRecorder object.

发布与此MediaRecorder对象关联的资源

void

reset()

Restarts the MediaRecorder to its idle state.

重新启动mediarecorder到空闲状态

void

setAudioChannels(int numChannels)

Sets the number of audio channels for recording.

设置录制的音频通道数。

 

void

setAudioEncoder(int audio_encoder)

Sets the audio encoder to be used for recording.

设置audio的编码格式

void

setAudioEncodingBitRate(int bitRate)

Sets the audio encoding bit rate for recording.

设置录制的音频编码比特率

 

void

setAudioSamplingRate(int samplingRate)

Sets the audio sampling rate for recording.

设置录制的音频采样率。

 

void

setAudioSource(int audio_source)

Sets the audio source to be used for recording.

设置用于录制的音源。

 

void

setAuxiliaryOutputFile(String path)

Pass in the file path for the auxiliary time lapse video.

辅助时间的推移视频文件的路径传递。

void

setAuxiliaryOutputFile(FileDescriptor fd)

Pass in the file descriptor for the auxiliary time lapse video.

在文件描述符传递的辅助时间的推移视频

 

void

setCamera(Camera c)

Sets a Camera to use for recording.

设置一个recording的摄像头

void

setCaptureRate(double fps)

Set video frame capture rate.

设置视频帧的捕获率

void

setMaxDuration(int max_duration_ms)

Sets the maximum duration (in ms) of the recording session.

设置记录会话的最大持续时间(毫秒)

void

setMaxFileSize(long max_filesize_bytes)

Sets the maximum filesize (in bytes) of the recording session.

设置记录会话的最大大小(以字节为单位)

void

setOnErrorListener(MediaRecorder.OnErrorListener l)

Register a callback to be invoked when an error occurs while recording.

注册一个回调被调用发生错误时,同时录制

void

setOnInfoListener(MediaRecorder.OnInfoListener listener)

Register a callback to be invoked when an informational event occurs while recording.

注册要同时记录一个信息事件发生时调用的回调。

 

void

setOrientationHint(int degrees)

Sets the orientation hint for output video playback.

设置输出的视频播放的方向提示

void

setOutputFile(FileDescriptor fd)

Pass in the file descriptor of the file to be written.

传递要写入的文件的文件描述符

void

setOutputFile(String path)

Sets the path of the output file to be produced.

设置输出文件的路径

void

setOutputFormat(int output_format)

Sets the format of the output file produced during recording.

设置在录制过程中产生的输出文件的格式

 

void

setPreviewDisplay(Surface sv)

Sets a Surface to show a preview of recorded media (video).

表面设置显示记录媒体(视频)的预览

void

setProfile(CamcorderProfile profile)

Uses the settings from a CamcorderProfile object for recording.

从一个记录CamcorderProfile对象的使用设置

void

setVideoEncoder(int video_encoder)

Sets the video encoder to be used for recording.

设置视频编码器,用于录制

void

setVideoEncodingBitRate(int bitRate)

Sets the video encoding bit rate for recording.

设置录制的视频编码比特率。

 

void

setVideoFrameRate(int rate)

Sets the frame rate of the video to be captured.

设置要捕获的视频帧速率

void

setVideoSize(int width, int height)

Sets the width and height of the video to be captured.

设置要捕获的视频的宽度和高度

void

setVideoSource(int video_source)

Sets the video source to be used for recording.

开始捕捉和编码数据到setOutputFile(指定的文件)

void

start()

Begins capturing and encoding data to the file specified with setOutputFile().

 

void

stop()

Stops recording.

停止recording

 

 

视频编码格式:default,H263,H264,MPEG_4_SP

获得视频资源:default,CAMERA

音频编码格式:default,AAC,AMR_NB,AMR_WB,

获得音频资源:defalut,camcorder,mic,voice_call,voice_communication,voice_downlink, voice_recognition,  voice_uplink;

输出方式:amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp.

 

 

4 流程分析

一、 java层

media recorder state machine:

1、java应用层

java应用层主要是一些接口的调用,它并没有具体功能代码的实现,java应用层的代码路径为:

android/packages/apps/SoundRecorder/src/com/android/soundrecorder/

该目录下有文件: SoundRecorder.java Recorder.java VUMeter.java

soundrecorder.java是程序的入口文件,我们在可以在里面设置文件输出编码格式的格式,现在系统默认支持两种格式amr和3gpp格式。设置代码如下:

mRequestedType =AUDIO_3GPP; //02 AUDIO_AMR;

接着运行mRecorder = new Recorder();创建一个Recorder类。Recorder类在Recorder.java中定义。

Recorder的startRecording方法启动了java层的录音。startRecording方法中首先创建一个Mediarecorder的类,然后调用Mediarecorder的方法完成设置audio源、设置输出文件格式、audio编码格式、设置输出文件,然后检查MediaRecorder是否准备好了。如果准备好就启动。如果没有准备好就抛出异常然后重新设置MediaRecorder和释放MediaRecorder。代码如下所示:

mRecorder = new MediaRecorder();

mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

mRecorder.setOutputFormat(outputfileformat);

mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

mRecorder.setOutputFile(mSampleFile.getAbsolutePath());

// Handle IOException

try {

mRecorder.prepare();

} catch(IOException exception) {

setError(INTERNAL_ERROR);

mRecorder.reset();

mRecorder.release();

mRecorder = null;

return;

}

mRecorder.start();

2、JAVA Framework层

Java的framework层代码位于:

frameworks/base/media/java/android/media/MediaRecorder.java

它没有具体的实现只是一个接口而已。

3、JAVA本地调用部分(JNI):

frameworks/base/media/jni/android_media_MediaRecorder.cpp

jni层的只是实现了方法的注册,为java层调用C++程序提供一种注册。

这三给部分的程序会编译成一个libmedia_jni.so库,java层序的调用都是调用该库中的接口。具体的实现要要在我们的多媒体底层库。

二、 多媒体底层库

1、ImediaRecorder.cpp

Imediarecorder.cpp文件中实现了BP功能。BP和BN是通过binder来通信的。Bp主要是用来处理java层传下来的服务请求。然后通过transact将处理请求传给bn(通过binder)。其接口如下所示:

class BpMediaRecorder: public BpInterface

{

BpMediaRecorder(const sp& impl) : BpInterface(impl) {}

status_t setCamera(const sp& camera);

status_t setPreviewSurface(const sp& surface);

status_t init();

status_t setVideoSource(int vs);

status_t setAudioSource(int as);

status_t setOutputFormat(int of);

status_t setAudioEncoder(int ae);

status_t setOutputFile(const char* path);

status_t prepare();

status_t getMaxAmplitude(int* max);

…………………………

}

上面的每个函数中都用transact方法来向bn发出请求。然后调用return reply.readInt32();将从bn返回的数据传送个他们的调用函数。

2、Mediarecorder.cpp

Bn的实现是在Mediarecorder.cpp文件中。BN是用来处理bp的请求,当bn将数将处理完后将数据通过transact传给回bp(通过binder)。MediaRecorder.cpp文件的实现方法与ImediaRecorder,cpp对应,主要是用来接收ImediaRecorder发送过来的请求。

MediaRecorder::MediaRecorder()

{ LOGV("constructor");

sp sm = defaultServiceManager();

sp binder;

do {

binder =sm->getService(String16("media.player"));

if (binder != NULL) {

break;

}

usleep(500000); // 0.5 s

} while(true);

sp service = interface_cast(binder);

if (service != NULL) {

mMediaRecorder = service->createMediaRecorder(getpid());

}

if (mMediaRecorder != NULL) {

mCurrentState = MEDIA_RECORDER_IDLE;

}

doCleanUp();

}

该文件操作的方法是mMediaRecorder的方法,它主要是同过binder机制将请求传输送给mediarecorder的服务进程。

3、多媒体服务部分

mediaRecorder的服务文件是MediaRecorderClient.cpp,它主要调用的是PVMediaRecorder的实现方法,在此请求opencore的服务。

MediaRecorderClient::MediaRecorderClient(pid_t pid)

{

LOGV("Client constructor");

mPid = pid;

mRecorder = new PVMediaRecorder();

}

三、Opencore

我们先从pvmediarecorder.cpp文件分析。

在PVMediaRecorder中首先创建一个AuthorDriverWrapper的对象。PVMediaRecorder将它的方法通过author_command包装。然后通过AuthorDriverWrapper的enqueueCommand将命令发送请求队列中。

PVMediaRecorder的setOutputFile方法会打开我们上面指定的文件路径下的文件,为写文件作好准备。代码如下:

int fd = open(path, O_RDWR | O_CREAT );

接着分析authordriver.cpp文件

AuthorDriverWrapper::AuthorDriverWrapper()

{

mAuthorDriver = new AuthorDriver();

}

我们在AuthorDriverWrapper首先创建一个AuthorDriver的对象.。我们来看AuthorDriverWrapper的enqueueCommand方法,可以看到,我们在pvmediarecorder中调用的enqueuecommand实际上调用的是authordriver的enqueuecommand方法。

status_t AuthorDriverWrapper::enqueueCommand(author_command*ac, media_completion_f comp, void *cookie)

{ if (mAuthorDriver) {

return mAuthorDriver->enqueueCommand(ac, comp, cookie);

}

return NO_INIT;

}

四、audioflinger层和audiorecord

1、AudioRecord

音频系统的对外接口是AudioRecord,它通过iBinder来远程调用Audioflinger的openRecorder函数。AudioRecord构造函数如下:

1:AudioRecord

AudioRecord::AudioRecord(

int streamType,

uint32_t sampleRate,

int format,

int channelCount,

int frameCount,

uint32_t flags,

callback_t cbf,

void* user,

int notificationFrames)

: mStatus(NO_INIT)

{

log_wj("ENTERIN::--%s---%s---\n",__FILE__,__FUNCTION__);

mStatus = set(streamType, sampleRate, format, channelCount,

frameCount, flags, cbf, user, notificationFrames);

}

调用:

status_t AudioRecord::set(int streamType,

uint32_t sampleRate,

int format,

int channelCount,

int frameCount,

uint32_t flags,

callback_t cbf,

void* user,

int notificationFrames,

bool threadCanCallJava)

{

const sp& audioFlinger = AudioSystem::get_audio_flinger();

//获取缓存大小,间接调用我们修改过该函数(经过三次调用中转),返回值为//channelCount*320

AudioSystem::getInputBufferSize(sampleRate, format,channelCount, &inputBuffSizeInBytes);

//远程调用audioFlinger的openrecord函数,openRecord相当于audioflinger为audioRecord

//开辟相应的服务窗口

sp record = audioFlinger->openRecord(getpid(),streamType,

sampleRate, format,

channelCount,

frameCount,

((uint16_t)flags) << 16,

&status);

//创建一个线程用来处理

mClientRecordThread = new ClientRecordThread(*this,threadCanCallJava);

}

AudioRecord相当于一个代理,它的线程是用来处理其它客户的请求。

2、AudioFlinger

sp AudioFlinger::openRecord(

pid_t pid,

int streamType,

uint32_t sampleRate,

int format,

int channelCount,

int frameCount,

uint32_t flags,

status_t *status)

{

// AudioRecord线程

if (mAudioRecordThread == 0) {

LOGE("Audio record thread not started");

lStatus = NO_INIT;

goto Exit;

}

// add client to list

{ // scope for mLock

Mutex::Autolock _l(mLock);

wclient = mClients.valueFor(pid);

if (wclient != NULL) {

client = wclient.promote();

} else {

client = new Client(this, pid);

mClients.add(pid, client);

}

// create new record track. The record track uses one trackin mHardwareMixerThread by //convention.

//生成一个recordTrack用来作为数据的中转(audioflinger与audiorecord之间)。

//他们使用audio_track_cblk_t数据结构来传输数据。

recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread,client, streamType, sampleRate, format, channelCount, frameCount, flags);

if (recordTrack->getCblk() == NULL) {

recordTrack.clear();

lStatus = NO_MEMORY;

goto Exit;

}

// return to handle to client------我们的audiorecord。

recordHandle = new RecordHandle(recordTrack);

}

AudioRecord和AudioFlinger操作的都是RecordTrack实例,AudioRecord通过它的执行控制操作(start/stop)和读取操作(read)。Audiorecord的start/stop操作可以理解为一个开关,控制的是AudiorecordThread的运行与否。

Audioflinger则负责从音频设备读取数据放置到audio_track_cblk_t数据结构中。

Audioflinger对数据的读取在AudioFlinger::AudioRecordThread::threadLoop()函数中。在第一次启动的时候会打开一个AudioStreamIn的对象,并设置参数。

input =mAudioHardware->openInputStream(mRecordTrack->format(),

mRecordTrack->channelCount(),mRecordTrack->sampleRate(),

&mStartStatus,

(AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags>> 16));

读取数据的代码如下:

if (LIKELY(mRecordTrack->getNextBuffer(&buffer) ==NO_ERROR&&

(int)buffer.frameCount == inFrameCount) ) {

ssize_t bytesRead = input->read(buffer.raw,inBufferSize);

mRecordTrack->releaseBuffer(&buffer);

mRecordTrack->overflow();

}

首先从audio_track_cblk_t取得缓冲区,然后调用input的read方法读取数据,最后释放缓冲区,检查是否溢出。

五、 硬件抽象层

硬件抽象层主要实现了AudioStreamInALSA和AudioStreamOutALSA两个类,这两个类又会调用该文件下的ALSAStreamOps类的方法。AudioStreamInALSA是录音部分调用的路径。在AudioStreamInALSA的构造函数中会对alsa进行一些初始化参数设置。AudioStreamInALSA的read方法是最主要的方法,audioflinger层的read调用就是对AudioStreamInALSA的read的调用。由于录音部分出现单声道和双声道数据传输的问题,修改read方法如下,即可实现了录音功能正常,避免了在编码的时候修改数据时其他编码仍不能工作的弊端。

ssize_t AudioStreamInALSA::read(void *buffer, ssize_tbytes)

{ snd_pcm_sframes_t n;

status_t err;

short int *tmp1,*tmp2;

int i;

AutoMutex lock(mLock);

tmp1=(short int *)malloc(bytes*2);

n = snd_pcm_readi(mHandle, tmp1,snd_pcm_bytes_to_frames(mHandle, bytes*2));

if (n < 0 && mHandle) {

n = snd_pcm_recover(mHandle, n, 0);

}

tmp2=(short int *)buffer;

for(i=0;i

{

tmp2[i]=tmp1[2*i];

}

free(tmp1);

return static_cast(n/2);

}

snd_pcm_readi调用的是alsa库函数,跟踪执行最终会调用alsa库下的snd_pcm_hw_readi函数。snd_pcm_hw_readi会调用err = ioctl(fd,SNDRV_PCM_IOCTL_READI_FRAMES, &xferi);最终与kernel相联系。

 

 

 

5主要能设置列举

1 setAudioChannels(int numChannels) 设置录制的音频通道数。

2 setAudioEncoder(int audio_encoder) 设置audio的编码格式

3 setAudioEncodingBitRate(int bitRate)  设置录制的音频编码比特率

4 setAudioSamplingRate(int samplingRate) 设置录制的音频采样率。

5 setAudioSource(int audio_source) 设置用于录制的音源。

6 setAuxiliaryOutputFile(String path)  辅助时间的推移视频文件的路径传递。

7 setAuxiliaryOutputFile(FileDescriptor fd)在文件描述符传递的辅助时间的推移视频

8 setCamera(Camera c) 设置一个recording的摄像头

9 setCaptureRate(double fps) 设置视频帧的捕获率

10 setMaxDuration(int max_duration_ms) 设置记录会话的最大持续时间(毫秒)

11 setMaxFileSize(long max_filesize_bytes) 设置记录会话的最大大小(以字节为单位)

12 setOutputFile(FileDescriptor fd) 传递要写入的文件的文件描述符

13 setOutputFile(String path)  设置输出文件的路径

14 setOutputFormat(int output_format) 设置在录制过程中产生的输出文件的格式

15 setPreviewDisplay(Surface sv) 表面设置显示记录媒体(视频)的预览

16 setVideoEncoder(int video_encoder) 设置视频编码器,用于录制

17 setVideoEncodingBitRate(int bitRate) 设置录制的视频编码比特率。

18 setVideoFrameRate(int rate) 设置要捕获的视频帧速率

19 setVideoSize(int width, int height) 设置要捕获的视频的宽度和高度

20 setVideoSource(int video_source)  开始捕捉和编码数据到setOutputFile(指定的文件)

 

 

 

视频编码格式:default,H263,H264,MPEG_4_SP

获得视频资源:default,CAMERA

音频编码格式:default,AAC,AMR_NB,AMR_WB,

获得音频资源:defalut,camcorder,mic,voice_call,voice_communication,voice_downlink,

voice_recognition,  voice_uplink;

输出方式:amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp.


这篇关于MediaRecorder类介绍 方法已经翻译成中文了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

SpringBoot日志配置SLF4J和Logback的方法实现

《SpringBoot日志配置SLF4J和Logback的方法实现》日志记录是不可或缺的一部分,本文主要介绍了SpringBoot日志配置SLF4J和Logback的方法实现,文中通过示例代码介绍的非... 目录一、前言二、案例一:初识日志三、案例二:使用Lombok输出日志四、案例三:配置Logback一

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语

CentOS 7部署主域名服务器 DNS的方法

《CentOS7部署主域名服务器DNS的方法》文章详细介绍了在CentOS7上部署主域名服务器DNS的步骤,包括安装BIND服务、配置DNS服务、添加域名区域、创建区域文件、配置反向解析、检查配置... 目录1. 安装 BIND 服务和工具2.  配置 BIND 服务3 . 添加你的域名区域配置4.创建区域

mss32.dll文件丢失怎么办? 电脑提示mss32.dll丢失的多种修复方法

《mss32.dll文件丢失怎么办?电脑提示mss32.dll丢失的多种修复方法》最近,很多电脑用户可能遇到了mss32.dll文件丢失的问题,导致一些应用程序无法正常启动,那么,如何修复这个问题呢... 在电脑常年累月的使用过程中,偶尔会遇到一些问题令人头疼。像是某个程序尝试运行时,系统突然弹出一个错误提

电脑提示找不到openal32.dll文件怎么办? openal32.dll丢失完美修复方法

《电脑提示找不到openal32.dll文件怎么办?openal32.dll丢失完美修复方法》openal32.dll是一种重要的系统文件,当它丢失时,会给我们的电脑带来很大的困扰,很多人都曾经遇到... 在使用电脑过程中,我们常常会遇到一些.dll文件丢失的问题,而openal32.dll的丢失是其中比较