Stagefright 之 Video Playback的流程

Stagefright之一

                                                                 ——Video Playback的流程


下面根据log分析Playback a video的流程。

ActivityManager:()

Starting: Intent{act=android.intent.action.VIEW dat=file:///sdcard/test.avi typ=video/* flg=0x4000000 cmp=com.estrongs.android.pop/.app.PopVideoPlayer}from pid 370

Starting: Intent{act=android.intent.action.VIEW dat=file:///sdcard/test.flac typ=audio/* flg=0x4000000 cmp=com.android.music/.AudioPreview} frompid 402

一. Java层:MediaPlayer.java

MediaPlayer mp = new MediaPlayer();

mp.setDataSource(context, uri);

mp.prepare();

mp.start();

 

二.JNI层

MediaPlayer-JNI(jni程序android_media_MediaPlayer.cpp)

{

       staticJNINativeMethod gMethods[] = {

{"setDataSource", "(Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDataSource},

   {"_setVideoSurface", "()V",  (void *)android_media_MediaPlayer_setVideoSurface},

{"prepare","()V",  (void*)android_media_MediaPlayer_prepare},

……

……

}

JNI文件中主要是一个映射表数组,在JNINativeMethod结构体中,

第一个变量:是Java中函数的名字。

第二个变量:用字符串是描述了函数的参数和返回值

第三个变量:是函数指针,指向C函数。

 

三.C层

1. MediaPlayer类  //对应java层的函数实现

继承于public BnMediaPlayerClient,public virtual IMediaDeathNotifier

BnMediaPlayerClient是个接口类,继承于public BnInterface<IMediaPlayerClient>;

IMediaDeathNotifier类中有函数getMediaPlayerService(),返回一个指向IMediaPlayerService的智能指针。

 

2. MediaPlayerService类

继承于public BnMediaPlayerService,此类是一个接口类,涉及到binder机制。

在MediaPlayerService类定义时候,在其内部又定义了三个类,class AudioOutput,class AudioCache,以及class Client

这里有个问题,从log上来看,就是在1中getMediaPlayerService()函数之后,只出现调用了class Client的构造函数的log,而没有调用MediaPlayerService的构造函数???

{

        getPlayerType(url)         //根据url起正确的player,默认Stagefrightplayer,rtsp                player type = 4       // STAGEFRIGHT_PLAYER

        caseSTAGEFRIGHT_PLAYER:   

        p = new StagefrightPlayer;

}

 

3.StagefrightPlayer类

继承于public MediaPlayerInterface

StagefrightPlayer是对AwesomePlayer类的一层封装,它的函数都是调用AwesomePlayer的成员函数,在其构造函数中,

{

mPlayer(new AwesomePlayer);

}

 

4.AwesomePlayer类

这个类就是video playback具体实现了。在它的构造函数中,

{     

        CHECK_EQ(mClient.connect(),OK);

 // register all OMX components (相关类有class client/ OMX /OMXMaster)

//跟过一下,在OMXMaster类实现中调用aomxcore .cpp的OMX_Init()函数

        AwesomeEventconstructor  //4个event实例

        reset();

        setListener();      //这个以后可以跟一下

}

 

video play 类的调用层次基本上就是上面介绍的几个。下面分析AwesomePlayer类的实现。

(1)设置数据源Setdatasource()                                  

/StagefrightPlayer:initCheck();

/StagefrightPlayer:setAudioSink();     //这个可以跟一下

              /AwesomePlayer: setAudioSink();

/MediaPlayerService:  setDataSource(url);

              /StagefrightPlayer:setDataSource(url)

                            /AwesomePlayer:setDataSource(url)

 

(2)启动mQueue,作为event handle

status_t AwesomePlayer::prepare_l()

{

 prepareAsync_l();

 while (mFlags & PREPARING)

  {

   mPreparedCondition.wait(mLock);

  }

}

 

status_t AwesomePlayer::prepareAsync_l()

{

 mQueue.start();

 mFlags |= PREPARING;

 mAsyncPrepareEvent = new AwesomeEvent(this, &AwesomePlayer::onPrepareAsyncEvent);

 mQueue.postEvent(mAsyncPrepareEvent);

}

 

(3) onPrepareAsyncEvent被触发

void AwesomePlayer::onPrepareAsyncEvent()

{

 finishSetDataSource_l();

 initVideoDecoder(); ...... (3.3)

 initAudioDecoder();

}

 

status_tAwesomePlayer::finishSetDataSource_l()

{

       //在这里会去打开文件

       // FileSource 类

       // mFile(fopen(filename,"rb"));

 

  dataSource= DataSource::CreateFromURI(mUri.string(), ...);

 sp<MediaExtractor> extractor =

                    MediaExtractor::Create(dataSource); ..... (3.1)

 return setDataSource_l(extractor); ......................... (3.2)

}

 

(3.1) 解析mUri所指定的video,并且根据其header来选择对应的extractor

              //Autodetected media mimetype, 取confidence值大的

              //实例化mimetype所对应的Extractor

              //通过spliter得到videotype和audiotype,以及相关parameter

 

sp<MediaExtractor>MediaExtractor::Create(const sp<DataSource> &source, ...)

{

 source->sniff(&tmp, ...);

 mime = tmp.string();

 

  if(!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)

  {

   return new MPEG4Extractor(source);

  }

 else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG))

  {

   return new MP3Extractor(source);

  }

  elseif(……)

}

 

(3.2) 使用extractor对视频做A/V的分离(mVideoTrack/mAudioTrack)

 

status_tAwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor)

{

  for(size_t i = 0; i < extractor->countTracks(); ++i)

  {

    sp<MetaData> meta =extractor->getTrackMetaData(i);

 

    CHECK(meta->findCString(kKeyMIMEType,&mime));

 

   if (!haveVideo && !strncasecmp(mime, "video/", 6))

    {

     setVideoSource(extractor->getTrack(i));

     haveVideo = true;

    }

   else if (!haveAudio && !strncasecmp(mime, "audio/",6))

    {

     setAudioSource(extractor->getTrack(i));

     haveAudio = true;

    }

  }

}

 

voidAwesomePlayer::setVideoSource(sp<MediaSource> source)

{

 mVideoTrack = source;

}

 

(3.3) 根据mVideoTrack中的编码类型来选择video decoder (mVideoSource)

 

//OsclSharedLibrary动态加载对应的OMX组件库

//allocateBuffersOnPort()   分配MediaBufferconstructor(buffer数目在omx组件中定义)

//包括 input port 和output port

 

status_t AwesomePlayer::initVideoDecoder()

{

 mVideoSource = OMXCodec::Create(mClient.interface(),

                                 mVideoTrack->getFormat(),

                                  false,

                                  mVideoTrack);

}

 

(4) 将mVideoEvent放入mQueue中,开始解码播放,并交由mVideoRenderer来显示

 

status_t AwesomePlayer::play_l()

{

 postVideoEvent_l();

}

 

voidAwesomePlayer::postVideoEvent_l(int64_t delayUs)

{

 mQueue.postEventWithDelay(mVideoEvent, delayUs);

}

 

void AwesomePlayer::onVideoEvent()

{

 mVideoSource->read(&mVideoBuffer, &options);

 [Check Timestamp]

  mVideoRenderer->render(mVideoBuffer);

  postVideoEvent_l();

}

 

其中:

OMXCodec:drainInputBuffer();    //是一个for(;;)

//trackisaudio

//AVIExtractor:read();

OMXCodec:fillOutputBuffer();

on_message();

 

OMXCodec:drainInputBuffer();

//trackisvideo

//AVIExtractor:read();

OMXCodec:fillOutputBuffer();

on_message();


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值