yasea浅析
1 简介
Yasea是一个Android流媒体客户端。 它将来自摄像机和麦克风的YUV和PCM数据编码为H.264 / AAC,封装在FLV中并通过RTMP传输。
这篇文章的目的是初步了解yasea的流程,为后续优化做铺垫。
分支:
- master:主分支,被我修改后,支持min SDK 18.
- non-gpuimage:
- android-16: Android API 16+.
- aac-hev2: for Youtube live broadcast that is not compatible with conventional flash media players.
特性:
2 工程结构
- app模块:
- MainActivity:主页
- AndroidManifest.xml:声明权限
- library模块:
- cpp:用Android.mk方式编译C/C++
- libenc:jni中间层代码
- libx264:用于H264软编码
- libyuv:包括YUV缩放和转换功能。
- com.coremedia.iso:封装MP4
- com.github.faucamp.simplertmp:SimpleRtmp是用于实现RTMP客户端的简单Java库。
- com.googlecode.mp4parser:封装MP4
- com.seu.magicfilter:滤镜
- net.ossrs.yasea:UI层和业务逻辑层
3 总流程
打开camera,在预览的view加滤镜。在SrsPublisher预览回调,在libenc和libyuv进行YUV转换,用x264软编码或MediaCodec硬编码 ,在SrsMp4Muxer保存MP4,SrsFlvMuxer发送RTMP。
4 功能
预览
- SrsCameraView:主页,自定义view,初始化camera分辨率、旋转,加滤镜,获取视频原始数据,是RGBA格式。
转换YUV和编码
- SrsEncoder:声明native方法,转换和编码。我的手机支持COLOR_FormatYUV420SemiPlanar编码,所以要把yuv转成NV12。
- YUV转换:
- onSurfaceCreated - onSurfaceChanged - onDrawFrame - mGLIntBufferCache.add, 缓存
- mGLIntBufferCache.poll - onGetRgbaFrame - hwRgbaFrame - libenc_RGBAToNV12 - convert_to_i420 - ConvertToI420 - I420Scale - ConvertFromI420
- 视频编码:onProcessedYuvFrame - onEncodedAnnexbFrame - vencoder.queueInputBuffer - vencoder.dequeueOutputBuffer - onEncodedAnnexbFrame
- 音频编码:onGetPcmFrame - aencoder.queueInputBuffer - aencoder.dequeueOutputBuffer - onEncodedAacFrame
保存MP4
- SrsMp4Muxer:封装MP4?
- 视频流:onEncodedAnnexbFrame - writeSampleData - writeVideoSample - writeFrameByte - frameCache.add,record - frameCache.poll - writeSampleData,finishMovie
- 音频流:onEncodedAacFrame - writeSampleData - writeAudioSample - 同上
发送RTMP
- SrsPublisher:各种业务逻辑、开关。
- SrsFlvMuxer:to POST the h.264/avc annexb frame over RTMP.
- SrsFlvFrame:the muxed flv frame.
- SrsAllocator.Allocation:分配字节
- SrsRawH264Stream:the raw h.264 stream, in annexb.
- SrsFlv:remux the annexb to flv tags.
- 连接RTMP发送视频流:startPublish - mFlvMuxer.start- connect - publisher.publish - mFlvTagCache.poll - sendFlvTag - publisher.publishVideoData
- 发送前缓存视频流:onEncodedAnnexbFrame - writeSampleData - writeVideoSample - writeH264SpsPps - writeRtmpPacket - flvTagCacheAdd - mFlvTagCache.add
- 发送前缓存音频流:onEncodedAacFrame - writeSampleData - writeAudioSample - writeRtmpPacket - 同上
FAQ
- 为什么要封装flv?
- 为什么要RGBA转I420再转NV12,而不是直接RGBA转NV12?
- 可以不加滤镜吗?解:看non-gpuimage分支。
- ……
参考
begeekmyfriend/yasea: RTMP live streaming client for Android
https://github.com/begeekmyfriend/yasea
SEA(适用于Android的流编码器)通过HTTP-FLV将实时流发布到SRS。
ossrs/srs-sea at feature/deprecated
https://github.com/ossrs/srs-sea/tree/feature/deprecated
yasea 基于 MediaCodec 硬编码 · Issue #31 · begeekmyfriend/yasea
https://github.com/begeekmyfriend/yasea/issues/31
请问摄像头返回的最初的NV21格式的数据在哪里 · Issue #752 · begeekmyfriend/yasea
https://github.com/begeekmyfriend/yasea/issues/752