librtmp推流使用aac编码音频的html5和flash播放问题
公司项目中使用rtmp推流,音频编码aac、视频编码H264。
windows和android平台都没有发现问题。
然而在IOS版本的APP中发现几个问题:
1. 推流后flash播放异常
2. IOS平台微信分享后html5播放异常
但是在PC上播放正常,android平台上html5播放正常。
经过两天的钻研,发现问题如下:
1. rtmp建立连接的时候先发送音视频相关参数。或者第一帧发送的数据应该如下:
1 m_pPacketAudio->m_nChannel = 0x04; 2 m_pPacketAudio->m_headerType = RTMP_PACKET_SIZE_LARGE; 3 m_pPacketAudio->m_nTimeStamp = 0; 4 m_pPacketAudio->m_nInfoField2 = m_pRtmp->m_stream_id; 5 m_pPacketAudio->m_hasAbsTimestamp = 0; 6 7 char * szBodyBufferAudio = m_pPacketAudio->m_body; 8 /* 9 [UB4]:10,soundformat:aac 10 [UB2]:3,sample reate,44k 11 [UB1]:1,bitspersample,16bit 12 [UB1]:1,channel,2 13 */ 14 szBodyBufferAudio[ 0] = 0xAF; 15 //AACPacketType,[UI8],0:AAC sequence header 16 szBodyBufferAudio[ 1] = 0x00; 17 //AudioSpecificConfig,2 byte 18 //for AAC LE 19 //44k ,2-ch aac-lc 20 szBodyBufferAudio[ 2] = 0x12; 21 szBodyBufferAudio[ 3] = 0x10; 22 m_pPacketAudio->m_nBodySize = 4; 23 m_pPacketAudio->m_packetType = RTMP_PACKET_TYPE_AUDIO; 24 RTMP_SendPacket(m_pRtmp, m_pPacketAudio, 0);
2. 后面的音视频流发送rtmp时,写法如下:
1 if(dwType == PACKET_VIDEO) 2 { 3 // ...... 4 //RTMP_SendPacket(m_pRtmp, m_pPacketVideo, 0); 5 // ...... 6 } 7 else if(dwType == PACKET_AUDIO) 8 { 9 char * szBodyBufferAudio = m_pPacketAudio->m_body; 10 /* [UB4]:10,soundformat:aac 11 [UB2]:3,sample reate,44k 12 [UB1]:1,bitspersample,16bit 13 [UB1]:1,channel,2 14 */ 15 16 // 以下两行是最关键的两行 17 lDataSize -= 7; 18 pFrameData += 7; 19 szBodyBufferAudio[ 0] = 0xAF; 20 //AACPacketType,[UI8],1:Raw AAC frame data 21 szBodyBufferAudio[ 1] = 0x01; 22 m_pPacketAudio->m_nBodySize = lDataSize + 2; 23 m_pPacketAudio->m_nChannel = 0x04; 24 m_pPacketAudio->m_headerType = RTMP_PACKET_SIZE_MEDIUM; 25 m_pPacketAudio->m_nInfoField2 = m_pRtmp->m_stream_id; 26 m_pPacketAudio->m_hasAbsTimestamp = 0; 27 //memcpy(szBodyBufferAudio + 2, pFrameData, lDataSize); 28 //RTMP_SendPacket(m_pRtmp, m_pPacketAudio, 0); 29 30 CMQueueUnit* pQu = m_pSendBuffer->StartWrite(); 31 if(pQu) 32 { 33 MByte* pBuf = pQu->GetBuf(); 34 if(pBuf){ 35 memcpy(pBuf, m_pPacketAudio, sizeof(RTMPPacket)); 36 ((RTMPPacket*)pBuf)->m_body = (char*)(pBuf + sizeof(RTMPPacket) + RTMP_MAX_HEADER_SIZE); 37 memcpy(((RTMPPacket*)pBuf)->m_body, szBodyBufferAudio, 2); 38 memcpy(((RTMPPacket*)pBuf)->m_body + 2, pFrameData, lDataSize); 39 m_pSendBuffer->EndWrite(pQu, TRUE); 40 } 41 else 42 m_pSendBuffer->EndWrite(pQu, FALSE); 43 } 44 45 #ifdef WIN32 46 m_dwRemainTimes += (21995464); 47 m_pPacketAudio->m_nTimeStamp += 23; 48 #elif defined __IPHONE__ 49 m_dwRemainTimes += (21995464); 50 m_pPacketAudio->m_nTimeStamp += 23; 51 #else 52 m_dwRemainTimes += (21995464/2); 53 m_pPacketAudio->m_nTimeStamp += 11; 54 #endif 55 if(m_dwRemainTimes>100000000) 56 { 57 m_pPacketAudio->m_nTimeStamp += 1; 58 m_dwRemainTimes -= 100000000; 59 } 60 61 m_dwOldTimeStamp = CMHelpFunc::GetCurTimeStamp(); 62 }
3. 视频编码后的数据,处理如下。
那几句一定要注释 不然flash和Html5播放不出视频。
1 if( lOutSize == 0 || lOutSize > m_lVFrameOutBuffSize ) 2 { 3 LOGE( "Encoding one video frame failed 2 (%d)", res ); 4 res = MV2_ERR_MEDIASTREAM_VIDEOENCODE; 5 return res; 6 } 7 else 8 { 9 MByte * pRawData = m_pVFrameOutBuff; 10 11 // 以下几句一定要注释 12 // if(bIsSyncFrame)//first frame ,skip sps/pps header,length is 22,NAL header,length:4 13 // { 14 // lOutSize -= 26; 15 // pRawData += 26; 16 // m_bFirstVF = MFalse; 17 // } 18 // else 19 // { 20 // /*just skip NAL Header: 4 byte*/ 21 // lOutSize -= 4; 22 // pRawData += 4; 23 // } 24 25 if( m_pRtmp ) 26 res = m_pRtmp->SendMediaData( pRawData, lOutSize, PACKET_VIDEO, bIsSyncFrame ); 27 }
不然播放出来的将会是这样
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。