LibStageFright

http://wenku.baidu.com/link?url=k3jTV9Fiy1v5VFY5iqvGvpZmsBrUsVV3eviWGfWe-zw5_CDwsMqNP7cGSRf4rqryZ1WvW-CIQ3DITQoZVkzDw82UAio3scxosB4JkFABQoG

http://wenku.baidu.com/view/79451720a5e9856a56126084.html




---------------------------------


libmedia和libmediaplayerservice分析 
1) libmedia目录在frameworks/base/media/libmedia,为多媒体底层库,这里面的内容被
编译成libmedia.so在整个MediaPlayer运行中属于Client部分 
1.libmedia.so处于核心位置,主要实现对上层以及下层的接口类。对上层主要提供MediaPlayer类的接口,类libmedia_jni.so通过调用MediaPlayer类,提供对JAVA的接口。 2.另外一部分则通过Binder机制和libmediaplayerservice.so进行通讯。 
3.对stagefright,则定义了标准的IOMX接口。 Stagefirght通过该接口调用OpenMax插件。 
2)libmeidaplayerservice目录在frameworks/base/media/libmediaplayerservice为多媒体
服务部分,文件为mediaplayerservice.h和mediaplayerservice.cpp,这部分内容被编译成libmediaplayerservice.so在整个MediaPlayer运行中处于Server部分 
这部分通过继承libmedia.so的类,实现服务器的功能。对mediaplayer整个流程进行管理调度。 
通过stagefrightPlayer和stagefrightRecorder,调用到stagefirght框架中的音视频播放与录制功能。 
   




LibStageFright主要工作流程 
videoDecode 
1创建playerengine 
// 设置数据源,以及 audio sink 
MediaPlayer::SetDataSource(PATH_TO_FILE)->  MediaPlayerService::create-> 
MediaPlayerService::Client::setDataSource-> MediaPlayerService:: Client:: GetPlayerType-> MediaPlayerService:: Client::CreatePlayer-> StagefrightPlayer:: setAudioSink-> StagefrightPlayer:: setDataSource-> 
Create MediaPlayerImpl(AwesomePlayer)-> MediaPlayerImpl:: MediaPlayerImpl  PlayerType: 
PV_PLAYER--------------------(已经不使用,原本为创建OpenCore中的PVPlayer) SONIVOX_PLAYER----------- MidiFile()(MIDI 格式) STAGEFRIGHT_PLAYER----- StagefrightPlayer 
NU_PLAYER---------------------NuPlayer(流媒体播放器) 
TEST_PLAYER------------------- TestPlayerStub (only for ‘test’ and ‘eng’build) //以下为与openMax插件的初始化连接。 
AwesomePlayer:mClient.connect()-> OMXClient::connect-> 
MediaPlayerService::getOMX()-> 
OMXMaster::OMXMaster: addVendorPlugin ()-> addPlugin((*createOMXPlugin ())-> *createOMXPlugin (){ new TIOMXPlugin; } 
2.解析mUri指定的内容,根据header来确定对应的Extractor 
AwesomePlayer:: prepare() AwesomePlayer:: prepareAsync_l()-> 
在该函数中启动mQueue,作为EventHandler(stagefright使用event来进行驱动) AwesomePlayer::finishSetDataSource_l()-> 
MediaExtractor::create(datasource)-> 
3.使用extractor对文件做A/V分离(mVideoTrack/mAudioTrack) 
AwesomePlayer::setDataSource_l(extractor)-> AwesomePlayer::setVideoSource()-> AwesomePlayer::setAudioSource()-> 
mVideoTrack=source 






 




mAudioTrack=source 
4根据mVideoTrace中编码类型来选择video_decoder(mVideoSource) 
AwesomePlayer::initVideoDecoder()-> mVideoSource->start();(初始化解码器) OMXCodec::Create()-> 
根据编码类型去匹配codecs,将softwareCodec优先放在matchCodecs前面,优先匹配,即优先建立softWareCodec 
<MediaSource>softwareCodec=InstantiateSoftwareCodec(componentName, source)-> 如果没有匹配的softWareCodec则去调用hardware中实现的omx_codec omx->allocateNode(componentName...)-> sp<OMXCodec> codec = new OMXCodec(~)-> observer->setCodec(codec)-> 
err = codec->configureCodec(meta, flags)-> return codec. 
5.根据Codec类型选择Renderer 
AwesomePlayer::start-> postVideoEvent_l(); 
AwesomePlayer::onVideoEvent()-> 
mVideoSource->read()(&mVideoBuffer, &options)-> AwesomePlayer::initRenderer_l()-> 判断Codec类型, HardWare Codec: 
mVideoRenderer =new AwesomeNativeWindowRenderer(mSurface, rotationDegrees); AwesomeNativeWindowRenderer::render()(hook Called by EGL)-> HardWare Codec不需要进行ColorConvert操作,直接push到NativeWindow SoftWare Codec: 
mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta)-> mVideoRenderer = new SoftwareRenderer()-> SoftwareRenderer::render()-> AwesomePlayer::onVideoEvent()-> [Check Timestamp] 
mVideoRenderer->render(mVideoBuffer); 
6.Audio和Video同步 
Stagefright中Audio由CallBack驱动数据流,Video则在OnVideoEvent中获取Audio的timeStamp,进行同步。 Audio::fillBuffer()->      
mPositionTimeMediaUs为资料中的timestamp, mPositionTimeRealUs为播放资料的实际时间。  AwesomePlayer::onVideoEvent()-> 
mTimeSourceDeltaUs = realTimeUs- mediaTimeUs


LibStageFright主要工作流程 
videoDecode 
1创建playerengine 
// 设置数据源,以及 audio sink 
MediaPlayer::SetDataSource(PATH_TO_FILE)->  MediaPlayerService::create-> 
MediaPlayerService::Client::setDataSource-> MediaPlayerService:: Client:: GetPlayerType-> MediaPlayerService:: Client::CreatePlayer-> StagefrightPlayer:: setAudioSink-> StagefrightPlayer:: setDataSource-> 
Create MediaPlayerImpl(AwesomePlayer)-> MediaPlayerImpl:: MediaPlayerImpl  PlayerType: 
PV_PLAYER--------------------(已经不使用,原本为创建OpenCore中的PVPlayer) SONIVOX_PLAYER----------- MidiFile()(MIDI 格式) STAGEFRIGHT_PLAYER----- StagefrightPlayer 
NU_PLAYER---------------------NuPlayer(流媒体播放器) 
TEST_PLAYER------------------- TestPlayerStub (only for ‘test’ and ‘eng’build) //以下为与openMax插件的初始化连接。 
AwesomePlayer:mClient.connect()-> OMXClient::connect-> 
MediaPlayerService::getOMX()-> 
OMXMaster::OMXMaster: addVendorPlugin ()-> addPlugin((*createOMXPlugin ())-> *createOMXPlugin (){ new TIOMXPlugin; } 
2.解析mUri指定的内容,根据header来确定对应的Extractor 
AwesomePlayer:: prepare() AwesomePlayer:: prepareAsync_l()-> 
在该函数中启动mQueue,作为EventHandler(stagefright使用event来进行驱动) AwesomePlayer::finishSetDataSource_l()-> 
MediaExtractor::create(datasource)-> 
3.使用extractor对文件做A/V分离(mVideoTrack/mAudioTrack) 
AwesomePlayer::setDataSource_l(extractor)-> AwesomePlayer::setVideoSource()-> AwesomePlayer::setAudioSource()-> 
mVideoTrack=source 


mAudioTrack=source 
4根据mVideoTrace中编码类型来选择video_decoder(mVideoSource) 
AwesomePlayer::initVideoDecoder()-> mVideoSource->start();(初始化解码器) OMXCodec::Create()-> 
根据编码类型去匹配codecs,将softwareCodec优先放在matchCodecs前面,优先匹配,即优先建立softWareCodec 
<MediaSource>softwareCodec=InstantiateSoftwareCodec(componentName, source)-> 如果没有匹配的softWareCodec则去调用hardware中实现的omx_codec omx->allocateNode(componentName...)-> sp<OMXCodec> codec = new OMXCodec(~)-> observer->setCodec(codec)-> 
err = codec->configureCodec(meta, flags)-> return codec. 
5.根据Codec类型选择Renderer 
AwesomePlayer::start-> postVideoEvent_l(); 
AwesomePlayer::onVideoEvent()-> 
mVideoSource->read()(&mVideoBuffer, &options)-> AwesomePlayer::initRenderer_l()-> 判断Codec类型, HardWare Codec: 
mVideoRenderer =new AwesomeNativeWindowRenderer(mSurface, rotationDegrees); AwesomeNativeWindowRenderer::render()(hook Called by EGL)-> HardWare Codec不需要进行ColorConvert操作,直接push到NativeWindow SoftWare Codec: 
mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta)-> mVideoRenderer = new SoftwareRenderer()-> SoftwareRenderer::render()-> AwesomePlayer::onVideoEvent()-> [Check Timestamp] 
mVideoRenderer->render(mVideoBuffer); 
6.Audio和Video同步 
Stagefright中Audio由CallBack驱动数据流,Video则在OnVideoEvent中获取Audio的timeStamp,进行同步。 Audio::fillBuffer()->      
mPositionTimeMediaUs为资料中的timestamp, mPositionTimeRealUs为播放资料的实际时间。  AwesomePlayer::onVideoEvent()-> 
mTimeSourceDeltaUs = realTimeUs- mediaTimeUs


4根据mAudioTrace中编码类型来选择audio_decoder(mAudioSource) 
AwesomePlayer::initAudioDecoder()-> mAudioSource->start();(初始化解码器) OMXCodec::Create()-> 
根据编码类型去匹配codecs,将softwareCodec优先放在matchCodecs前面,优先匹配,即优先建立softWareCodec 
<MediaSource>softwareCodec=InstantiateSoftwareCodec(componentName, source)-> 如果没有匹配的softWareCodec则去调用Hardware中实现的omx_codec omx->allocateNode(componentName...)-> sp<OMXCodec> codec = new OMXCodec(~)-> observer->setCodec(codec)-> 
err = codec->configureCodec(meta, flags)-> return codec. 
5.创建AudioPlayer,解码并开启Audio output播放audio数据 
AwesomePlayer::play_l-> 
mAudioPlayer = new AudioPlayer(mAudioSink, this); mAudioPlayer->setSource(mAudioSource); mAudioPlayer->start 
mSource->read(&mFirstBuffer);(在audioplayer启动过程中,会先读取第一段需解码后的资料。) 
mAudioSink->open(..., &AudioPlayer::AudioSinkCallback, ...); AudioSinkCallback{ 
me->fillBuffer(buffer, size) } 
开启audio output,同时AudioPlayer将callback函数设给它,之后每次callback函数被调用,AudioPlayer便会去读取Audio decoder解码后的资料。) 

4根据mAudioTrace中编码类型来选择audio_decoder(mAudioSource) 
AwesomePlayer::initAudioDecoder()-> mAudioSource->start();(初始化解码器) OMXCodec::Create()-> 
根据编码类型去匹配codecs,将softwareCodec优先放在matchCodecs前面,优先匹配,即优先建立softWareCodec 
<MediaSource>softwareCodec=InstantiateSoftwareCodec(componentName, source)-> 如果没有匹配的softWareCodec则去调用Hardware中实现的omx_codec omx->allocateNode(componentName...)-> sp<OMXCodec> codec = new OMXCodec(~)-> observer->setCodec(codec)-> 
err = codec->configureCodec(meta, flags)-> return codec. 
5.创建AudioPlayer,解码并开启Audio output播放audio数据 
AwesomePlayer::play_l-> 
mAudioPlayer = new AudioPlayer(mAudioSink, this); mAudioPlayer->setSource(mAudioSource); mAudioPlayer->start 
mSource->read(&mFirstBuffer);(在audioplayer启动过程中,会先读取第一段需解码后的资料。) 
mAudioSink->open(..., &AudioPlayer::AudioSinkCallback, ...); AudioSinkCallback{ 
me->fillBuffer(buffer, size) } 
开启audio output,同时AudioPlayer将callback函数设给它,之后每次callback函数被调用,AudioPlayer便会去读取Audio decoder解码后的资料。) 

Audio & Video Recorder 
1. 创建Recorder 
mMediaRecorder = new MediaRecorder-> Mediaplayerservice->createMediaRecorder MediaRecorderClient.cpp: 
mRecorder=new StagefrightRecorder; 
2. 设置AudioSource &VideoSource&Profile 
Package/VideoCamero.java: 
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER)-> mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA)-> setOutputFormat(profile.fileFormat)-> 
setVideoFrameRate(profile.videoFrameRate)-> 
setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight)-> setVideoEncodingBitRate(profile.videoBitRate)-> setVideoEncoder(profile.videoCodec)-> 
mMediaRecorder.setMaxFileSize(maxFileSize)-> mMediaRecorder.prepare()-> 
以上函数最终调用的是 
frameworks/base/media/libmediaplayerservice/ StagefrightRecorder.cpp中的实现。 
3.根据设置的Audio &Video output format等内容,选择Writer以及Encoder。 
StagefrightRecorder::start()-> 
startMPEG4Recording()->(作为多媒体的Recorder,支持3gpp和mp4两种多媒体文件类型的的录制,默认类型为3gpp) 
startAMRRecording()->(作为单音频输出类型的Recorder,支持AMRNB和AMRWB两种)。 startAACRecording()->(未有具体实现,暂时不支持)。 
startRTPRecording()->(流媒体文件Recorder,stream over a socket) startMPEG2TSRecording()->(MPEG2TS类型的Recorder). (以MPEG4Recording的初始化为例) 
setupMPEG4Recording(mCaptureAuxVideo,…)-> 
sp<MediaWriter> writer = new MPEG4Writer(outputFd)-> 
MPEG4Writer::MPEG4Writer(int fd)(位于libstagefright下的实现) setupCameraSource(&cameraSource)-> StagefrightRecorder::setupVideoEncoder-> switch (mVideoEncoder)-> 
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263)->(根据设置的mVideoEncoder的值来设置MIMETYPE,目前支持三种Video的编码类型: MEDIA_MIMETYPE_VIDEO_H263、MEDIA_MIMETYPE_VIDEO_MPEG4、MEDIA_MIMETYPE_VIDEO_AVC)

sp<MediaSource> encoder = OMXCodec::Create(…)->(根据MIMETYPE以及videosource创建videoEncoder,创建过程和videoDecoder过程类型,只是其中VideoEncoder的值设为true,以及videosource的值设置未cameraSource,具体过程参考video/audio Decode) writer->addSource(encoder)->(将创建完成的videoEncoder加入Writer中。) setupAudioEncoder(writer)->(设置创建AudioEncoder,过程和VideoEncoder类似) sp<MediaSource> audioEncoder = createAudioSource()-> sp<MediaSource> audioEncoder =OMXCodec::Create(…)-> writer->addSource(audioEncoder)-> 
startTimeUs = systemTime() / 1000->(记录开始时间) setupMPEG4MetaData-> 
mWriter->start()(开始录制多媒体数据) 

Stagefright 已经实现的codec 
1)Extractor  
frameworks/base/media/libstagefrightStagefright/MediaExtractor.cpp 
中的OnCreate()函数,列出了所有的Extractor。


2) Codec 
frameworks/base/media/libstagefright/OMXCodec.cpp 
中的宏定义 
#define FACTORY_CREATE(name) 
#define FACTORY_CREATE_ENCODER(name) 
分别定义了所有的software Decoder和software Encoder。这些Decoder/Encoder也同样可以在InstantiateSoftwareEncoder()和InstantiateSoftwareCodec()中看到。所有software codec的实现代码在libstagefright/Codecs下。  
所有的Decoder/Encoder分别定义在数组 
static const CodecInfo kDecoderInfo[]和static const CodecInfo kEncoderInfo[]中 其中以OMX.开头的Codec均为Hardware Codec.




添加新的Extractor 
1) 在frameworks\base\media\libstagefright\MediaDefs.cpp中定义 
Mime类型,以MPGE4为例 
const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mpeg4"; 2) 在MediaExtractor.cpp,Create函数中加入 
if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)             || !strcasecmp(mime, "audio/mp4")) {         return new MPEG4Extractor(source); 3)在DataSource.cpp, RegisterDefaultSniffers()函数中注册Extractor.      RegisterSniffer(SniffMPEG4); 
4)在libstagefright和libstagefright\include文件夹下加入Extractor, 
MPEG4Extractor.cpp/MPEG4Extractor.h(需实现SniffMPEG4函数) 
5)以上步骤需要在已经实现了分离器的前提下所要做的添加工作,若要实现新的文件分离器,则需要参考MPEG4Extractor.cpp等已经实现的内容,所有分离器都是继承Extractor.cpp的。 
添加新的Decoder(software decoder) 
OMXCodec.cpp中(frameworks/base/media/libstagefright/) 1) 在#define FACTORY_CREATE(name) \ 
加入定义FACTORY_CREATE(M4vH263Decoder) 
2)在kDecoderInfo[]中定义Codec,如果是s/w Codec则命名时不以OMX开头,H/W Codec则以OMX开头。 
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" }, 若是S/W Codec 则同时还需要在 
InstantiateSoftwareCodec函数kFactoryInfo[]中加入定义: FACTORY_REF(M4vH263Decoder) 
3) 在codecs\加入Codec Node, 
M4VH263Decoder.cpp和M4VH263Decoder.h 
4) 在StagefrightMediaScanner.cpp中加入包含该编解码格式的媒体文件封装格式的定义。 
static bool FileHasAcceptableExtension(const char *extension) {     static const char *kValidExtensions[] = { 
        ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",         ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",         ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",         ".mkv", ".mka", ".webm", ".ts", ".fl" }; 
5)同理,以上步骤是在已经实现了Codec的前提下所做的源文件添加步骤,所有的软解码Codec均为MediaSource.cpp的子类,需要实现里面定义的接口函数。 
OpenMax Codecs 插件引用 
StageFright实现了对OpenCore中的实例openmax的调用。最终的实现都硬件编解码。在OMXCodec.cpp中的Create函数,初始化Codec时,通过设置codec类型为OMXCodec来引用openmax插件。sp<OMXCodec> codec = new OMXCodec(

omx, node, quirks, 
                    createEncoder, mime, componentName,                     source, nativeWindow); 
调用codec是通过componentName来对openmax中的组件名称进行匹配,如果成功,则返回OMX_HANDLETYPE,用于OMXCodec与Component之间的通信。因此要引用openmax中的
component,只需要将已经实现的componentName注册到OMXCodec的CodecInfo kDecoderInfo[]/CodecInfo kEncoderInfo[]中即可。 如:static const CodecInfo kDecoderInfo[] = { 
       { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" }, }  
Stagefright performance issue 
 
1. 由于stagefright,采用传统AV时间戳同步,时钟来源于Audio,同时Audio完全由
callback驱动数据流,Video的Decode,Render在同一线程工作,而两者耗时都比较大,容易造成Video显示滞后。 
2. 默认最大帧率为20,而最后录制的视频帧率实际值只能达到17/18帧,影响流畅度。 
 
Multimedia porting 
 
1).修正进度条不能根据用户点击位置进行音乐播放问题。 
Packages/apps/Music/src/com/android/music/MediaPlaybackActivity.java  
问题描述:在拖动seekbar过程中,music会根据当前进度条的位置播放音乐,停止拖动操作后,进度条并未准确停止在拖动结束的位置。 
问题原因:因为源代码中设有250ms的延迟以及拖动过程中的每隔250ms的seek动作; 问题解决:在拖动进度条过程中,music不会播放音乐(即不会去seek),仅当停止拖动后,程序根据此时拖动条的位置再seek musicsource,播放音乐。  
2).修正Gallery不能正确显示当前video size的问题. Frameworks/base/media/libstagefright/AwesomePlayer.cpp  
问题描述:播放較小videosize的视频源(如320*240),只显示原画面的左上角内容。 
问题原因:MPEG4Extractor解析trackheader,獲取kKeyDisplayWidth和kKeyDisplayHeight值,向上提交至AwesomePlayer,并作为video的width和height值,一直上报至AP,但是这两个值与真实videosize不符,AP以这两个值为参数,做相应的measure,然后将错误的结果上报给surface,surface以AP的错误计算结果对codec输出的image做拉伸,导致画面显示出现问题。 
问题解决:直接將codec解析得到的videosize提交至AwesomePlayer,并上报至AP,以保证AP在measure view size后得到准确的结果传给surface。

3).修正默认Video codec的profiles。 
Frameworks/base/media/libmedia/MediaProfiles.cpp 
Frameworks/base/media/libstagefright/CameraSource.cpp 
Frameworks/base/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp  
问题描述:默认Recorder录制的video显示效果不佳,视频流畅度不够好。 
问题原因:默认H263VideoEncoderCap与M4vVideoEncoderCap的MaxFrameRate为20,这样最后video的帧率只有17或者18fps。 
问题解决:将MaxFrameRate调整为30.这样实际得到的帧可以达到27fps-28fps左右。  
 4).增加PtrControl.cpp 
Frameworks/base/media/libstagefright/Android.mk Frameworks/base/media/libstagefright/PtrControl.cpp 
Frameworks/base/media/libstagefright/include/AwesomePlayer.h Frameworks/base/media/libstagefright/include/PtrControl.h 
Frameworks/base/media/libstagefright/include/PtrControlInterface.h 
支持链表操作。  
5).修正音视频同步问题 
Frameworks/base/media/libstagefright/AwesomePlayer.cpp 
Frameworks/base/media/libstagefright/include/AwesomePlayer.h 
Frameworks/base/media/libstagefright/codecs/m4v_h263/dec/M4VH263Decoder.cpp Frameworks/base/media/libstagefright/include/M4vH263Decoder.h  
问题描述:视频播放时,video的部分相对于audio会滞后。 
问题原因:stagefright框架中,videosource的Read和Render在同一线程中,串行执行。同时decode和Render的耗时都比较长,造成video的速度根不上audio,造成画面滞后。 问题解决:另起一个thread来做Render,达到并行的效果,减少总时间。 


Gallery Video playback接口调用流程 
1).在Gallery中的video播放器为MoviePlayer,在MovieActivity.java的OnCreate()函数中会有初始化: mPlayer = new MoviePlayer(rootView, this, intent.getData()) 
intent.getData()为传入的Uri。 
2).在MoviePlayer.java的构造函数中,起到播放作用的对象为mVideoView,在该构造函数中初始化: 
mVideoView = (VideoView) rootView.findViewById(R.id.surface_view) 之后调用 
mVideoView.setVideoURI(mUri);//将数据传入,同时创建MediaPlayer setVideoURI{ openVideo() } 
openVideo(){ 
mMediaPlayer = new MediaPlayer(); ~ } 
在该类中的播放控制,如start()、pause()、均调用的是mMediaPlayer.start();、 mMediaPlayer.pause(); 
之后的实际播放流程和Music相同,参见LibStageFright主要工作流程videoDecode。

Jpeg Encode流程 
在java层调用Camera拍照 
Package/apps/camera/src/com/android/camera/camera.java onShutterButtonClick(ShutterButton button){ doSnap() 
}//按下拍照按键的响应函数 capture() 
mCameraDevice.takePicture(...,new JpegPictureCallback(loc)) 
通过jni调用 
android_hardware_Camera_takePicture(... )//android_hardware_Camera.cpp Camera::takePicture()//Camera.cpp 
通过接口函数,与CameraService进行Binder通信 takePicture()//ICamera.cpp 
CameraService::Client::takePicture()//CameraService.cpp 
通过CameraHardwareInterface.h中定义的接口,调用Camera的HAL层。 virtual status_t    takePicture() = 0//CameraHardwareInterface.h CameraHardware::takePicture()//CameraHardware.cpp createThread(beginPictureThread, this)//创建拍照线程 CameraHardware::beginPictureThread() CameraHardware::pictureThread() mCamera.GrabJpegFrame() 
V4L2Camera::GrabJpegFrame//V4L2Camera.cpp V4L2Camera::saveYUYVtoJPEG 
{    //进行jpeg编码压缩转换 
struct jpeg_compress_struct cinfo;//标准libjpeg库调用,调用库文件位置 external/jepg下 
jpeg_create_compress (&cinfo); ~ }  
图像Decode流程 
在java层调用//以Gallery为例 
Package/app/Gallery3D/src/com/cooliris/media/UriTexture.java 
createFromUri(Uri,...)//传入Uri,返回值为Bitmap 
BitmapFactory.decodeStream(inputstream,...)//根据Uri创建输入流,根据inputstream,调用BitmapFactory中的解码函数 。(BitmapFactory.java) 
nativeDecodeStream(is,...)//通过jni调用BitmapFactory.cpp中的函数 doDecode(env, stream, padding, options, false); 
SkImageDecoder* decoder = SkImageDecoder::Factory(stream); SkImageDecoder::Factory(stream){ 
const DecodeReg* curr = DecodeReg::Head(); while (curr) {

codec = curr->factory()(stream); stream->rewind();         if (codec) { 
            return codec;         } 
        curr = curr->next(); #ifdef SK_ENABLE_LIBPNG 
codec = sk_libpng_dfactory(stream); stream->rewind();     if (codec) { 
        return codec;     } #endif 
    return NULL; } 
//DecodeReg为模板类SkTRegistry的一个实例,(除pngDecoder外)所有的Image Decoder均为SKImageDecdoder的子类。且都会实例化SkTRegistry。在Factory中,根据传入的stream遍历Decoder并返回合适的Decoder,若以上子类中没有,且宏SK_ENABLE_LIBPNG有定义,则去匹配PNGDecoder,若合适,则返回。(位于SkImageDecoder_Factory.cpp) //以Jpeg为例 
在SkImageDecoder_libjpeg.cpp中实例化SKTRegistry. 
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory); 
此时调用 
SkImageDecoder* DFactory(SkStream* stream){ return SkNEW(SkJPEGImageDecoder); } 
返回一个SKJPEGImageDecoder实例。 
之后在BitmapFactory.cpp中调用mDecoder->Decode(...) 最终调用 
SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 
 jpeg_decompress_struct  cinfo; jpeg_create_decompress(&cinfo); ... 
}//从函数中可以看到标准jpeg库的调用,函数位于SkImageDecoder_libjpeg.cpp中。  
All Image Codecs 
所有Image的Decoder均位于external/skia/src/images文件夹下 目前存在的编/解码器如下表所示:



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值