zoukankan      html  css  js  c++  java
  • android stagefright基本流程总结

    数据流的封装
    一、

    由数据源DataSource生成MediaExtractor。

    通过MediaExtractor::Create(dataSource)来实现。Create方法通过两步来生成相应的MediaExtractor:

    1、通过dataSource->sniff来探测数据类型

    2、生成相应的Extractor:

     1 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
     2              
     3             || !strcasecmp(mime, "audio/mp4")) {
     4              
     5             return new MPEG4Extractor(source);
     6              
     7             } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
     8              
     9             return new MP3Extractor(source, meta);
    10              
    11             } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
    12              
    13             || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
    14              
    15             return new AMRExtractor(source);
    16              
    17             } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) {
    18              
    19             return new WAVExtractor(source);
    20              
    21             } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) {
    22              
    23             return new OggExtractor(source);
    24              
    25             } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) {
    26              
    27             return new MatroskaExtractor(source);
    28              
    29             } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
    30              
    31             return new MPEG2TSExtractor(source);
    32              
    33             }

    二、

    接下来,通过以下代码把音视频轨道分离:

     1 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
     2              
     3             setVideoSource(extractor->getTrack(i));
     4              
     5             haveVideo = true;
     6              
     7             } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
     8              
     9             setAudioSource(extractor->getTrack(i));
    10              
    11             haveAudio = true;

    生成mVideoTrack和mAudioTrack两个MediaSource。

    三、

    到目前为止我们得到的这两个MediaSource只具有parser功能,没有decode功能。还需要对这两个MediaSource做进一步的包装:

     1 mVideoSource = OMXCodec::Create(
     2              
     3             mClient.interface(), mVideoTrack->getFormat(),
     4              
     5             false, // createEncoder
     6              
     7             mVideoTrack,
     8              
     9             NULL, flags);
    10              
    11             mAudioSource = OMXCodec::Create(
    12              
    13             mClient.interface(), mAudioTrack->getFormat(),
    14              
    15             false, // createEncoder
    16              
    17             mAudioTrack);

    这回又获取了两个MediaSource。它们具有parse和decode功能。当调用MediaSource.start()方法后,它的内部 就会开始从数据源获取数据并解析,等到缓冲区满后便停止。在AwesomePlayer里就可以调用MediaSource的read方法读取解码后的数 据。

    对于mVideoSource来说:

    读取的数据。

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

    交给显示模块进行渲染。

    1 mVideoRenderer->render(mVideoBuffer);

    对mAudioSource来说:

    用mAudioPlayer对mAudioSource进行封装,然后由mAudioPlayer负责读取数据和播放控制。

    AwesomePlayer流程
    URI,FD

    DataSource

    |

    mVideoTrack mAudioTrack//音视频数据流

    mAudioSource//音视频解码器

    | |

    mVideoBuffer mAudioPlayer

    上面示意了数据由源到最终解码后的流程。

    1、设置DataSource,数据源可以两种URI和FD。URI可以http://,rtsp://等。FD是一个本地文件描述符,能过FD,可以找到对应的文件。

    2、由DataSource生成MediaExtractor。通过sp extractor = MediaExtractor::Create(dataSource);来实现。 MediaExtractor::Create(dataSource)会根据不同的数据内容创建不同的数据读取对象。

    3、通过调用setVideoSource由MediaExtractor分解生成音频数据流(mAudioTrack)和视频数据流(mVideoTrack)。

    4、 onPrepareAsyncEvent()

    如果DataSource是URL的话,根据地址获取数据,并开始缓冲,直到获取到mVideoTrack和mAudioTrack。

    mVideoTrack和mAudioTrack通过调用initVideoDecoder()和initAudioDecoder()来生成mVideoSource和mAudioSource这两个音视频解码器。

    然后调用postBufferingEvent_l()提交事件开启缓冲。数据缓冲的执行函数是onBufferingUpdate()。

    缓冲区有足够的数据可以播放时,调用play_l()开始播放。play_l()中关键是调用了postVideoEvent_l(),提交了 mVideoEvent。这个事件执行时会调用函数onVideoEvent()。这个函数通过调用 mVideoSource->read(&mVideoBuffer, &options)进行视频解码。音频解码通过mAudioPlayer实现。

    视频解码器解码后通过mVideoSource->read读取一帧帧的数据,放到mVideoBuffer中,最后通过mVideoRenderer->render(mVideoBuffer)把视频数据发送到显示模块。

    当需要暂停或停止时,调用cancelPlayerEvents来提交事件用来停止解码,还可以选择是否继续缓冲数据。

  • 相关阅读:
    [HAOI2015] 数组游戏
    [HAOI2015] 数字串拆分
    [HAOI2015] 按位或
    [HAOI2009] 毛毛虫
    [HAOI2009] 巧克力
    [HAOI2011] Problem C
    [HAOI2011] 防线修建
    [HAOI2011] Problem A
    [HAOI2010] 最长公共子序列
    [HAOI2010] 工厂选址
  • 原文地址:https://www.cnblogs.com/shakin/p/4097144.html
Copyright © 2011-2022 走看看