zoukankan      html  css  js  c++  java
  • 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 }

     不然播放出来的将会是这样

  • 相关阅读:
    Lubuntu"软件包 没有可安装的候选者"解决办法
    Django实现邮件发送功能
    Django2.0跨域请求配置
    Django 正向解析与反向解析
    python 反爬虫策略
    base64简单使用
    Selenium功能自动化测试工具
    Pandas之Dateframe 实现Excel读取与写入
    pillow与numpy实现图片素描化
    用Pyinstaller 实现py.转化为exe可执行文件----二维码实例
  • 原文地址:https://www.cnblogs.com/zzugyl/p/4282366.html
Copyright © 2011-2022 走看看