日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 封装 SPS / PPS 数据包 )

發(fā)布時(shí)間:2025/6/17 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 封装 SPS / PPS 数据包 ) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 一、 基本封裝數(shù)據(jù)格式說(shuō)明
  • 二、 封裝 SPS PPS 數(shù)據(jù)總體說(shuō)明
  • 三、 封裝頭數(shù)據(jù)
  • 四、 封裝 SPS 數(shù)據(jù)
  • 五、 封裝 PPS 數(shù)據(jù)
  • 六、 設(shè)置 RTMP 數(shù)據(jù)包其它參數(shù)
  • 七、 SPS PPS 數(shù)據(jù)封裝代碼示例



Android 直播推流流程 : 手機(jī)采集視頻 / 音頻數(shù)據(jù) , 視頻數(shù)據(jù)使用 H.264 編碼 , 音頻數(shù)據(jù)使用 AAC 編碼 , 最后將音視頻數(shù)據(jù)都打包到 RTMP 數(shù)據(jù)包中 , 使用 RTMP 協(xié)議上傳到 RTMP 服務(wù)器中 ;


Android 端中主要完成手機(jī)端采集視頻數(shù)據(jù)操作 , 并將視頻數(shù)據(jù)傳遞給 JNI , 在 NDK 中使用 x264 將圖像轉(zhuǎn)為 H.264 格式的視頻 , 最后將 H.264 格式的視頻打包到 RTMP 數(shù)據(jù)包中 , 上傳到 RTMP 服務(wù)器中 ;


本篇博客中介紹如下內(nèi)容 , Java 層將 Camera 采集的 NV21 格式的數(shù)據(jù)傳入 JNI 層 , 在 JNI 中使用 x264 編碼器將 NV21 圖像數(shù)據(jù)編碼為 H.264 視頻數(shù)據(jù) ;


本篇博客中主要封裝 AVC 序列頭數(shù)據(jù) , 將 幀類(lèi)型 , AVC 數(shù)據(jù)類(lèi)型 , 合成時(shí)間 , 版本信息 , 編碼規(guī)格 , NALU 長(zhǎng)度 , SPS 個(gè)數(shù) , SPS 長(zhǎng)度 , SPS 數(shù)據(jù) , PPS 個(gè)數(shù) , PPS 長(zhǎng)度 , PPS 數(shù)據(jù) , 封裝到 RTMP 包中 ;





一、 基本封裝數(shù)據(jù)格式說(shuō)明



1 . 這是完整的視頻標(biāo)簽數(shù)據(jù)內(nèi)容 : 這是 FLV 中完整視頻標(biāo)簽數(shù)據(jù) ;

0x00000182 : 09 00 00 2E 00 00 00 00 0x0000018a : 00 00 00 17 00 00 00 00 0x00000192 : 01 64 00 32 FF E1 00 19 0x0000019a : 67 64 00 32 AC D9 80 78 0x000001a2 : 02 27 E5 84 00 00 03 00 0x000001aa : 04 00 00 1F 40 3C 60 C6 0x000001b2 : 68 01 00 05 68 E9 7B 2C 0x000001ba : 8B 00 00 00 39

2 . 標(biāo)簽頭 : 111111 個(gè)字節(jié)是標(biāo)簽頭數(shù)據(jù) , 存儲(chǔ)有 標(biāo)簽類(lèi)型 , 標(biāo)簽數(shù)據(jù)大小 , 時(shí)間戳 , 時(shí)間戳擴(kuò)展位 , 流編號(hào) 等 111111 字節(jié)信息 ;

0x00000182 : 09 00 00 2E 00 00 00 00 0x0000018a : 00 00 00

3 . 標(biāo)簽數(shù)據(jù) ( 重點(diǎn) ) : 這就是本篇博客要封裝的內(nèi)容 , 基本上是封裝一個(gè)格式一模一樣的 RTMP 數(shù)據(jù)包 ,

17 00 00 00 00 0x00000192 : 01 64 00 32 FF E1 00 19 0x0000019a : 67 64 00 32 AC D9 80 78 0x000001a2 : 02 27 E5 84 00 00 03 00 0x000001aa : 04 00 00 1F 40 3C 60 C6 0x000001b2 : 68 01 00 05 68 E9 7B 2C 0x000001ba : 8B 00 00 00 39

參考博客 : 參考之前的兩篇分析 RTMP 數(shù)據(jù)格式的博客 , 分析了與 RTMP 格式幾乎一致的 FLV 視頻數(shù)據(jù)格式 ;

  • 【Android RTMP】RTMP 數(shù)據(jù)格式 ( FLV 視頻格式分析 | 文件頭 Header 分析 | 標(biāo)簽 Tag 分析 | 視頻標(biāo)簽 Tag 數(shù)據(jù)分析 )

  • 【Android RTMP】RTMP 數(shù)據(jù)格式 ( FLV 視頻格式分析 | AVC 序列頭格式解析 )


這兩篇博客一定要 , 并且明白 FLV 視頻標(biāo)簽數(shù)據(jù)格式 , 才能看懂今天寫(xiě)的 RTMP 數(shù)據(jù)包封裝的內(nèi)容 ;





二、 封裝 SPS PPS 數(shù)據(jù)總體說(shuō)明



1 . 數(shù)據(jù)示例 :

17 00 00 00 00 0x00000192 : 01 64 00 32 FF E1 00 19 0x0000019a : 67 64 00 32 AC D9 80 78 0x000001a2 : 02 27 E5 84 00 00 03 00 0x000001aa : 04 00 00 1F 40 3C 60 C6 0x000001b2 : 68 01 00 05 68 E9 7B 2C 0x000001ba : 8B 00 00 00 39
  • 17 幀類(lèi)型, 1 字節(jié)
  • 00 數(shù)據(jù)類(lèi)型, 1 字節(jié)
  • 00 00 00 合成時(shí)間, 3 字節(jié)
  • 01 版本信息, 1 字節(jié)
  • 64 00 32 編碼規(guī)則, 3 字節(jié)
  • FF NALU 長(zhǎng)度, 1 字節(jié)
  • E1 SPS 個(gè)數(shù), 1 字節(jié)
  • 00 19 SPS 長(zhǎng)度, 2 字節(jié)

截止到當(dāng)前位置有 13 字節(jié)數(shù)據(jù)

  • spsLen 字節(jié)數(shù)據(jù), 這里是 25 字節(jié)
67 64 00 32 AC D9 80 78 0x000001a2 : 02 27 E5 84 00 00 03 00 0x000001aa : 04 00 00 1F 40 3C 60 C6 0x000001b2 : 68
  • 01 PPS 個(gè)數(shù), 1 字節(jié)
  • 00 05 PPS 長(zhǎng)度, 2 字節(jié)
  • ppsLen 字節(jié)的 PPS 數(shù)據(jù)
68 E9 7B 2C 0x000001ba : 8B
  • 后面的 00 00 00 39 是視頻標(biāo)簽的總長(zhǎng)度 , 這里在 RTMP 標(biāo)簽中可以不用封裝 ;


2 . 計(jì)算整個(gè) SPS 和 PPS 數(shù)據(jù)的大小 :


① 封裝頭 : 幀類(lèi)型 , 數(shù)據(jù)類(lèi)型 , 合成時(shí)間 , 版本信息 , 編碼規(guī)則 , NALU 長(zhǎng)度 , 總共有 101010 字節(jié) ;

② 封裝 SPS 數(shù)據(jù) : SPS 個(gè)數(shù) , SPS 長(zhǎng)度 , SPS 數(shù)據(jù) , 分別有 1+2+spsLen1 + 2 + spsLen1+2+spsLen 字節(jié) ;

③ 封裝 PPS 數(shù)據(jù) : PPS 個(gè)數(shù) , PPS 長(zhǎng)度 , PPS 數(shù)據(jù) , 分別有 1+2+ppsLen1 + 2 + ppsLen1+2+ppsLen 字節(jié) ;

int rtmpPackagesize = 10 + 3 + spsLen + 3 + ppsLen;



三、 封裝頭數(shù)據(jù)



向 RTMP 數(shù)據(jù)包中 , 封裝 幀類(lèi)型 , 數(shù)據(jù)類(lèi)型 , 合成時(shí)間 , 版本信息 , 編碼規(guī)則 , NALU 長(zhǎng)度 , 總共有 101010 字節(jié) ;

// 幀類(lèi)型數(shù)據(jù) : 分為兩部分;// 前 4 位表示幀類(lèi)型, 1 表示關(guān)鍵幀, 2 表示普通幀// 后 4 位表示編碼類(lèi)型, 7 表示 AVC 視頻編碼rtmpPacket->m_body[nextPosition++] = 0x17;// 數(shù)據(jù)類(lèi)型, 00 表示 AVC 序列頭rtmpPacket->m_body[nextPosition++] = 0x00;// 合成時(shí)間, 一般設(shè)置 00 00 00rtmpPacket->m_body[nextPosition++] = 0x00;rtmpPacket->m_body[nextPosition++] = 0x00;rtmpPacket->m_body[nextPosition++] = 0x00;// 版本信息rtmpPacket->m_body[nextPosition++] = 0x01;// 編碼規(guī)格rtmpPacket->m_body[nextPosition++] = sps[1];rtmpPacket->m_body[nextPosition++] = sps[2];rtmpPacket->m_body[nextPosition++] = sps[3];// NALU 長(zhǎng)度rtmpPacket->m_body[nextPosition++] = 0xFF;



四、 封裝 SPS 數(shù)據(jù)



將 SPS 數(shù)據(jù)封裝到 RTMP 數(shù)據(jù)包中 , 包含 SPS 個(gè)數(shù) , SPS 長(zhǎng)度 , SPS 數(shù)據(jù) ;

// SPS 個(gè)數(shù)rtmpPacket->m_body[nextPosition++] = 0xE1;// SPS 長(zhǎng)度, 占 2 字節(jié)// 設(shè)置長(zhǎng)度的高位rtmpPacket->m_body[nextPosition++] = (spsLen >> 8) & 0xFF;// 設(shè)置長(zhǎng)度的低位rtmpPacket->m_body[nextPosition++] = spsLen & 0xFF;// 拷貝 SPS 數(shù)據(jù)// 將 SPS 數(shù)據(jù)拷貝到 rtmpPacket->m_body[nextPosition] 地址中memcpy(&rtmpPacket->m_body[nextPosition], sps, spsLen);// 累加 SPS 長(zhǎng)度信息nextPosition += spsLen;



五、 封裝 PPS 數(shù)據(jù)



將 PPS 數(shù)據(jù)封裝到 RTMP 數(shù)據(jù)包中 , 包含 PPS 個(gè)數(shù) , PPS 長(zhǎng)度 , PPS 數(shù)據(jù) ;

// PPS 個(gè)數(shù)rtmpPacket->m_body[nextPosition++] = 0x01;// PPS 數(shù)據(jù)的長(zhǎng)度, 占 2 字節(jié)// 設(shè)置長(zhǎng)度的高位rtmpPacket->m_body[nextPosition++] = (ppsLen >> 8) & 0xFF;// 設(shè)置長(zhǎng)度的低位rtmpPacket->m_body[nextPosition++] = (ppsLen) & 0xFF;// 拷貝 SPS 數(shù)據(jù)memcpy(&rtmpPacket->m_body[nextPosition], pps, ppsLen);



六、 設(shè)置 RTMP 數(shù)據(jù)包其它參數(shù)



設(shè)置 RTMP 包類(lèi)型 , RTMP 包長(zhǎng)度 , RTMP 通道 , 時(shí)間戳 等信息 ;

// 設(shè)置 RTMP 包類(lèi)型, 視頻類(lèi)型數(shù)據(jù)rtmpPacket->m_packetType = RTMP_PACKET_TYPE_VIDEO;// 設(shè)置 RTMP 包長(zhǎng)度rtmpPacket->m_nBodySize = rtmpPackagesize;// 分配 RTMP 通道, 隨意分配rtmpPacket->m_nChannel = 10;// 設(shè)置視頻時(shí)間戳, 如果是 SPP PPS 數(shù)據(jù), 沒(méi)有時(shí)間戳rtmpPacket->m_nTimeStamp = 0;// 設(shè)置絕對(duì)時(shí)間, 對(duì)于 SPS PPS 賦值 0 即可rtmpPacket->m_hasAbsTimestamp = 0;// 設(shè)置頭類(lèi)型, 隨意設(shè)置一個(gè)rtmpPacket->m_headerType = RTMP_PACKET_SIZE_MEDIUM;



七、 SPS PPS 數(shù)據(jù)封裝代碼示例



/*** 將 SPS / PPS 數(shù)據(jù)發(fā)送到 RTMP 服務(wù)器端* @param sps SPS 數(shù)據(jù)* @param pps PPS 數(shù)據(jù)* @param spsLen SPS 長(zhǎng)度* @param ppsLen PPS 長(zhǎng)度*/ void VedioChannel::sendSpsPpsToRtmpServer(uint8_t *sps, uint8_t *pps, int spsLen, int ppsLen) {// 創(chuàng)建 RTMP 數(shù)據(jù)包, 將數(shù)據(jù)都存入該 RTMP 數(shù)據(jù)包中RTMPPacket *rtmpPacket = new RTMPPacket;/*計(jì)算整個(gè) SPS 和 PPS 數(shù)據(jù)的大小數(shù)據(jù)示例 :17 00 00 00 000x00000192 : 01 64 00 32 FF E1 00 190x0000019a : 67 64 00 32 AC D9 80 780x000001a2 : 02 27 E5 84 00 00 03 000x000001aa : 04 00 00 1F 40 3C 60 C60x000001b2 : 68 01 00 05 68 E9 7B 2C0x000001ba : 8B 00 00 00 3917 幀類(lèi)型, 1 字節(jié)00 數(shù)據(jù)類(lèi)型, 1 字節(jié)00 00 00 合成時(shí)間, 3 字節(jié)01 版本信息, 1 字節(jié)64 00 32 編碼規(guī)則, 3 字節(jié)FF NALU 長(zhǎng)度, 1 字節(jié)E1 SPS 個(gè)數(shù), 1 字節(jié)00 19 SPS 長(zhǎng)度, 2 字節(jié)截止到當(dāng)前位置有 13 字節(jié)數(shù)據(jù)spsLen 字節(jié)數(shù)據(jù), 這里是 25 字節(jié)67 64 00 32 AC D9 80 780x000001a2 : 02 27 E5 84 00 00 03 000x000001aa : 04 00 00 1F 40 3C 60 C60x000001b2 : 6801 PPS 個(gè)數(shù), 1 字節(jié)00 05 PPS 長(zhǎng)度, 2 字節(jié)ppsLen 字節(jié)的 PPS 數(shù)據(jù)68 E9 7B 2C0x000001ba : 8B后面的 00 00 00 39 是視頻標(biāo)簽的總長(zhǎng)度這里再 RTMP 標(biāo)簽中可以不用封裝*/int rtmpPackagesize = 10 + 3 + spsLen + 3 + ppsLen;// 為 RTMP 數(shù)據(jù)包分配內(nèi)存RTMPPacket_Alloc(rtmpPacket, rtmpPackagesize);// 記錄下一個(gè)要寫(xiě)入數(shù)據(jù)的索引位置int nextPosition = 0;// 幀類(lèi)型數(shù)據(jù) : 分為兩部分;// 前 4 位表示幀類(lèi)型, 1 表示關(guān)鍵幀, 2 表示普通幀// 后 4 位表示編碼類(lèi)型, 7 表示 AVC 視頻編碼rtmpPacket->m_body[nextPosition++] = 0x17;// 數(shù)據(jù)類(lèi)型, 00 表示 AVC 序列頭rtmpPacket->m_body[nextPosition++] = 0x00;// 合成時(shí)間, 一般設(shè)置 00 00 00rtmpPacket->m_body[nextPosition++] = 0x00;rtmpPacket->m_body[nextPosition++] = 0x00;rtmpPacket->m_body[nextPosition++] = 0x00;// 版本信息rtmpPacket->m_body[nextPosition++] = 0x01;// 編碼規(guī)格rtmpPacket->m_body[nextPosition++] = sps[1];rtmpPacket->m_body[nextPosition++] = sps[2];rtmpPacket->m_body[nextPosition++] = sps[3];// NALU 長(zhǎng)度rtmpPacket->m_body[nextPosition++] = 0xFF;// SPS 個(gè)數(shù)rtmpPacket->m_body[nextPosition++] = 0xE1;// SPS 長(zhǎng)度, 占 2 字節(jié)// 設(shè)置長(zhǎng)度的高位rtmpPacket->m_body[nextPosition++] = (spsLen >> 8) & 0xFF;// 設(shè)置長(zhǎng)度的低位rtmpPacket->m_body[nextPosition++] = spsLen & 0xFF;// 拷貝 SPS 數(shù)據(jù)// 將 SPS 數(shù)據(jù)拷貝到 rtmpPacket->m_body[nextPosition] 地址中memcpy(&rtmpPacket->m_body[nextPosition], sps, spsLen);// 累加 SPS 長(zhǎng)度信息nextPosition += spsLen;// PPS 個(gè)數(shù)rtmpPacket->m_body[nextPosition++] = 0x01;// PPS 數(shù)據(jù)的長(zhǎng)度, 占 2 字節(jié)// 設(shè)置長(zhǎng)度的高位rtmpPacket->m_body[nextPosition++] = (ppsLen >> 8) & 0xFF;// 設(shè)置長(zhǎng)度的低位rtmpPacket->m_body[nextPosition++] = (ppsLen) & 0xFF;// 拷貝 SPS 數(shù)據(jù)memcpy(&rtmpPacket->m_body[nextPosition], pps, ppsLen);// 設(shè)置 RTMP 包類(lèi)型, 視頻類(lèi)型數(shù)據(jù)rtmpPacket->m_packetType = RTMP_PACKET_TYPE_VIDEO;// 設(shè)置 RTMP 包長(zhǎng)度rtmpPacket->m_nBodySize = rtmpPackagesize;// 分配 RTMP 通道, 隨意分配rtmpPacket->m_nChannel = 10;// 設(shè)置視頻時(shí)間戳, 如果是 SPP PPS 數(shù)據(jù), 沒(méi)有時(shí)間戳rtmpPacket->m_nTimeStamp = 0;// 設(shè)置絕對(duì)時(shí)間, 對(duì)于 SPS PPS 賦值 0 即可rtmpPacket->m_hasAbsTimestamp = 0;// 設(shè)置頭類(lèi)型, 隨意設(shè)置一個(gè)rtmpPacket->m_headerType = RTMP_PACKET_SIZE_MEDIUM; }

總結(jié)

以上是生活随笔為你收集整理的【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 封装 SPS / PPS 数据包 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。