整体流程就是通过创建VirtualDisplay,并且直接通过MediaCodec的Surface直接得到数据。通过MediaCodec得到编码完成之后的数据,进行flv格式的封装,最后通过rtmp协议进行发送。
后面,我们可以将编码后的数据进行让rtmp推流。
RTMP协议是RealTimeMessageProtocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing)和分包(packetizing)的问题。
一个RTMP连接以握手开始,双方分别发送大小固定的三个数据块
image
理论上来讲只要满足以上条件,如何安排6个Message的顺序都是可以的,但实际实现中为了在保证握手的身份验证功能的基础上尽量减少通信的次数,一般的发送顺序是这样的:
服务器在收到客户端发送的连接请求后发送如下信息:
主要是告诉客户端确认窗口大小,设置节点带宽,然后服务器把“连接”连接到指定的应用并返回结果,“网络连接成功”。并且返回流开始的的消息(StreamBegin0)。
推流流程
播流流程
image.png
这里就不赘述了。
需要将cs0和cs1的头部位置进行推流才能正常显示。并且必须作为第一条信息。
这里通过这方法读取cs0和cs1
publicstaticvoidfillFlvVideoTag(byte[]dst,intpos,booleanisAVCSequenceHeader,booleanisIDR,intreadDataLength){//FrameType&CodecIDdst[pos]=isIDR(byte)0x17:(byte)0x27;//AVCPacketTypedst[pos+1]=isAVCSequenceHeader(byte)0x00:(byte)0x01;//LAKETODOCompositionTimedst[pos+2]=0x00;dst[pos+3]=0x00;dst[pos+4]=0x00;if(!isAVCSequenceHeader){//NALUHEADERByteArrayTools.intToByteArrayFull(dst,pos+5,readDataLength);}}然后发送。
publicstaticRESFlvDatasendRealData(longtms,ByteBufferrealData){intrealDataLength=realData.remaining();intpacketLen=Packager.FLVPackager.FLV_VIDEO_TAG_LENGTH+Packager.FLVPackager.NALU_HEADER_LENGTH+realDataLength;byte[]finalBuff=newbyte[packetLen];realData.get(finalBuff,Packager.FLVPackager.FLV_VIDEO_TAG_LENGTH+Packager.FLVPackager.NALU_HEADER_LENGTH,realDataLength);intframeType=finalBuff[Packager.FLVPackager.FLV_VIDEO_TAG_LENGTH+Packager.FLVPackager.NALU_HEADER_LENGTH]&0x1F;Packager.FLVPackager.fillFlvVideoTag(finalBuff,0,false,frameType==5,realDataLength);RESFlvDataresFlvData=newRESFlvData();resFlvData.droppable=true;resFlvData.byteBuffer=finalBuff;resFlvData.size=finalBuff.length;resFlvData.dts=(int)tms;resFlvData.flvTagType=RESFlvData.FLV_RTMP_PACKET_TYPE_VIDEO;resFlvData.videoFrameType=frameType;returnresFlvData;//dataCollecter.collect(resFlvData,RESRtmpSender.FROM_VIDEO);}