Android多媒体

1.音频处理

作为多媒体处理的最基本的组成部分,音频处理在移动终端上十分复杂。音频的播放、记录、以及多种场景(如电话、音乐、提示音、录音等)的冲突、并发策略无疑增加了开发的难度。好在Google在设计Android时充分考虑了这些问你,在底层设计了一套围绕AndioFlinger、AudioPolicyManager的音频框架,使应用层的开发者可以忽略不同场景下的并发策略。通过这种方法,极大简化了音频应用的开发。

        在应用层,开发者可以调用MediaPlayer、MediaRecorder、SoundPool等进行音频的播放、记录以及游戏的特效音的制作等。在框架层,AudioFlinger、AudioPolicyManager、AudioService、AudioHardwareInterface构成了音频控制的基本骨架。框架层本身包括Java、C++两部分,并通过JNI进行通信,其中对服务的调用是基于C/S架构实现的。内核层提供不同音频设备的驱动和ALSA架构等。而音频本身的播放涉及的多媒体引擎是OpenCore和Stagefright。在默认情况下,OpenCore在Android2.2及以前版本中应用,而在较新的Android版本中,Stagefright则成了默认的多媒体引擎。

(1)音频播放

        根据播放方式的不同,Android为应用层提供了多个播放接口,如MediaPlayer、SoundPool、AudioTrack、AsyncPlayer、JetPlayer、ToneGenerator等,他们适合用于不同的场景。

1)基于MediaPlayer播放

      MediaPlayer具有非常强大的播放功能,对音频和视频的播放均提供了支持。为了保证播放期间系统的正常工作,需要设置android.permission.WAKE_LOCK权限。

      MediaPlayer支持的音频格式包括AAC、AMR、FLAC、MP3、MIDI、OGG、PCM等。考虑到MediaPlayer的复杂性,在原生层MediaPlayer有状态机控制。 对于背景音乐,将MediaPlayer封装在Service中即可实现。

       MediaPlayer支持元数据、音频文件、音频流等形式的源数据的播放。

       (1)播放元数据

                          所谓元数据即raw文件夹下的资源文件,调用方法如下:

                          mMediaPlayer=MediaPlayer.create(this, R.raw.test_cbr);

                          mMediaPlayer.start();

       (2)播放音频文件

                          对于本地文件,其数据源可以通过Uri来表示,在开始播放前需要设置播放类型并加载缓冲,示例如下:

                          Uri myUri=...;

                          MediaPlayer mediaPlayer=new MediaPlayer();

                          mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

                          mediaPlayer.setDataSource(getApplicationContext(), myUri);

                          mediaPlayer.prepare();    //加载缓冲

                          mediaPlayer.start();

       (3)播放流

                          MediaPlayer支持基于网络的流播放,其支持的网络协议包括RSTP(RTP、SDP)、HTTP渐进流(HTTP Progressive Streaming)、HTTP生活流(HTTP Live Streaming Draft Protocol,仅Honeycomb版本中用到)等。Android4.0开始支持HTTPS协议,在网络播放和本地播放上略有不同,示例如下:

                          String url="http://zhangmenshiting.baidu.com/***.mp3;

                          MediaPlayer mediaPlayer=new MediaPlayer();

                          mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

                          mediaPlayer.setDataSource(url);

                          mediaPlayer.prepareAsync();

                          ...

                          mediaPlayer.start();

                         需要说明的是,考虑到网络情况的复杂性,以及获取数据和解码可能耗时较长,不退将在播放流时通过prepare方法来加载缓冲,尤其不能再UI主线程中调用prepare方法。应通过prepareAsync方法将加载缓冲的工作放置在非UI主线程中进行,当准备工作完成时,MediaPlayer通过MediaPlayer.OnPreparedListener监听器可以监听到该事件。设置监听器的方法如mMediaPlayer.setOnPrepareListener(mPreparedListener);

                         通常在准备工作完成后开始进行播放。监听器处理加载缓冲结束的消息方法如下:

                                        MediaPlayer.OnPreParedListener mPreparedListener=new MediaPlayer.OnPreparedListener(){

                                                public void onPrepared(MediaPlayer mp){

                                                        ...

                                                        mediaPlayer.start();

                                                }

                                       }

                         当播放结束时,通过MediaPlayer.OnCompletionListener可以监听到播放结束的消息,示例如下:

                                        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){

                                               public void onCompletion(MediaPlayer mediaPlayer){

                                                       ...

                                               }

                                       });

     

 2)基于SoundPool播放

      SoundPool能够播放音频流的组合音,这对游戏应用而言显然非常有用。其对应的JNI接android_media_SoundPool.cpp。

      SoundPool可以通过APK包中的资源文件或文件系统中的文件将音频资源加载到内存中。在底层实现上,SoundPool通过媒体播放服务(MediaPlaybackService)可以将音频资源解码为一个16位的单声道或者立体声的PCM流,是应用避免了在回放过程中进行解码造成的延迟。

      除了回放过程中延迟小的优点外,SoundPool还能够对一定数量的音频进行同时播放。当要播放的音频流数量超过SoundPool所设定的最大值时,SoundPool将会停止已播放的一条低优先级的音频流。SoundPool对最大播放音频流数量的设置(默认为32),可以避免CPU过载和影响用户体验。

       对游戏等应用而言,MediaPlayer会使性能降低。在Android中,专门提供了SoundPool类来执行此类音频播放。SoundPool类占用的CPU资源较少、反应较快。

       和其他音频播放类相比,SoundPool类可以自行设置音频播放时的品质、音量、播放速率等,并且可以管理多个音频流,每个流均拥有自己独立的ID,对单个音频流的管理均是通过其ID来进行的。SoundPool类适用的场景包括应用程序中的声效(按键提示音、消息等)、游戏中密集而短暂的声音(如多个飞船同时爆炸)。

3)基于AudioTrack播放

       AudioTrack主要用于管理单个音频,这是一个较底层的音频播放方法,在构建AudioTrack时,需要指明流类型、采样率、通道配置、音频格式、缓冲大小、播放模式等参数。

 4)基于AsyncPlayer播放

      对于不希望阻塞当前线程的简单播放,可以考虑AsyncPlayer,从而使播放线程可以从容加载缓冲。虽然在底层依然是通过MediaPlayer进行播放的,但是AsyncPlayer支持的播放控制有限。

5)基于JetPlayer播放

     在Android中,还提供了对Jet播放的支持。它包括两部分:Jet播放器和Jet引擎。Jet常用于控制游戏的声音特效,采用MIDI格式。

6)基于ToneGenerator播放

     ToneGeneator提供了对DTMF音,以及呼叫监督音和专用音中规定音频的支持,

7)基于Ringtone播放

     Ringtone和RingtoneManager为铃声、提示音、闹钟等提供了快速播放及管理的接口。

(2)音频录制

     录音的方式相对播放而言比较简单,Android仅提供了MediaRecorder、AudioRecord两个用于音频录制。

     为了录制音频,必须设置音源、输出路径、录制格式等。其中音源由MediaRecorder.AudioSource统一定义。音源包括MIC、VOICE_UPLINK、VOICE_DOWNLINK、VOICE_CALL、CAMCORDER、VOICE_RECOGNITION和VOICE_COMMUNICATION(VOIP)。

     1)基于MediaRecorder录制

          MediaRecorder支持的音频编码包括AMR_NB、AMR_WB和AAC等,支持的输出格式包括AMR_NB、AMR_WB、MPEG_4、RAW_AMR和THREE_GPP等。

     2)基于AudioRecord录制

          AudioRecord支持ENCODING——PCM_16BIT和ENCODING_PCM_8BIT等编码,支持CHANNEL_IN_MONO、CHANNEL_IN_STEREO、CHANNEL_IN_LEFT和CHANNEL_IN_RIGHT等声道。

(3)音频管理

      音频管理主要是通过AudioManager来进行,通过AudioManager可以进行设备、音量、资源竞争、音效播放等方面的管理工作。

      1)设备管理

           AudioManager的强大主要体现在对蓝牙、扬声器、麦克风、耳机振动等音频相关设备的管理等方面。

      2)音量调整

           AudioManager支持对特定流或整体的音量调节。

      3)资源竞争

           在Froyo版本以前,没有对多个应用竞争有限的扬声器资源提供内置的处理策略,用户体验不佳,故在Froyo版本中,引入了Audio Focus策略来处理这一问题。

           当需要资源时,应用通过AudioManager的requestAudioFocus方法获得Audio Focus。一旦失去了Audio Focus,当前的播放会被剥夺资源。

      4)音效播放

           AudioManager还支持音效播放,方法为playSoundEffect。在播放音效前,必须调用loadSoundEffects方法,即创建一个SoundPool对象来执行实际的播放。

(4)音效处理

       在Android2.3中,对音频播放提供了更强大的音效支持,其实现位于android.media.audiofx包中。

       1)重低音

            BassBoost通过放大音频中的地拼音来实现重低音特效。重低音的细节有OpenSL ES 1.0.1定义。

      2)环绕音

            环绕音依赖于输出和输入通道的数量和类型,需要打开立体声通道。环绕音通过将音源放置于不同的位置,完美地再现了声音的质感和饱满度。在创建Virtualizer示例时,在音频框架层会同时创建一个环绕音引擎。环绕音的细节由OpenSL ES 1.0.1规范定义。

      3)均衡器

           均衡器是一种可以分别调节各种频率电信号放大量的电子设备,它通过对各种不同频率电信号的调节来补偿扬声器和声场的缺陷,补偿和修饰各种声源,以及提供其他特殊作用。一般均衡器仅能对高频、中频、低频三段频率电信号分别进行调节。

      4)混响

            混响是通过声音在不同路径上传播造成的反射叠加而产生的声音特效。

      5)可视化

           可视化分为两种情况:波形可视化和频率可视化。可视化的使用要求具备android.permission.RECORD_AUDIO全乡。在创建Visualizer示例时,将会同时在音频框架层创建一个可视化引擎。

2.视频处理

        在Android中,视频处理大致可以分为视频播放、视频记录和视频电话等3个部分,其中视频播放主要基于MediaPlayer进行,视频录制主要通过mediaRecorder进行,而视频电话则相对复杂。视频电话涉及多路视频、视频协议栈3G-324M等内容。

(1)视频播放

        在Android中,视频的播放有两种方案,一种是基于VideoView的,一种是基于SurfaceView的。基于VideoView的方案实现简单,但无法进行更多的个性化配置,不支持播放界面的动态变化;而基于SurfaceView的方案则具备更多的能力,但实现较复杂,多用于商业应用中。视频播放的部分参数受制于实际的硬件。

         1)视频状态机

              从视频播放的状态分析,除了正常播放、进度控制等外,视频播放还需要支持缓冲刷新等功能。

              视频播放的状态包括MEDIA_NOP、MEDIA_PREPARED、MEDIA_PLAYBACK_COMPLETE、MEDIA_BUFFERING_UPDATE、MEDIA_SEEK_COMPLETE、MEDIA_SET_VIDEO_SIZE、MEDIA_ERROR、MEDIA_INFO等。

              视频播放的进度控制和音频播放类似,这里不再详述,当缓冲发生更新时,通过OnBufferingUpdateListener监听器即可收到缓冲进度信息。

         2)基于SurfaceView的播放

              基于SurfaceView来播放视频可以充分利用系统的硬件加速能力,保障播放的流畅。Surface渲染是Android底层框架的一个重要技术,其管理由SurfaceFlinger进行。

         3)基于VideoView的播放

              VideoView事实上是对SurfaceView和MediaPlayer的一种封装,VideoView支持数据源的设置、播放状态控制、播放信息获取等。

(2)视频录制

          录制视频是主流移动终端的基本功能,随着硬件能力的提升,其支持的视频记录格式越来越多,主要有H263、H264 AVC等,相关的后缀有.3gp、.mp4、.ts等。录制视频的部分参数受制于实际的硬件配置。

          通过MediaRecord进行视频录制于进行音频录制的主要区别在于前者需要设置视频源,并且输出格式不同。为了录制视频,需要设置很多参数。

          MediaRecorder的许多方法间存在依赖关系,如setVideoSource方法和setAudioSource方法必须在setOutFormat方法前设置;通过setOrientationHint方法设置角度,必须在prepare方法前调用;通过setMaxDuration方法设置持续时间,则必须在setOutFormat方法后并在prepare方法前进行。在开发视频录制的应用前,必须了解这些依赖关系。

          在Android 4.0中,当完成一段视频的录制后,系统会广播android.hardware.action.NEW_VIDEO消息。

3.Camera服务

        Camera是目前最常见的业务之一,主要用于拍照、录像、预览、设置参数等,






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值