iOS 将视频流(h264)和音频流封装成PS流

Posted Mai Guangliang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 将视频流(h264)和音频流封装成PS流相关的知识,希望对你有一定的参考价值。

调用方法:

static  CPSPackager * testObjc = NULL;

static char *pszBuffer;

 testObjc = new CPSPackager();

 pszBuffer = new char[1024*1024];

-(NSData *)EncodeDataChangeToPSWithData:(NSData *)encodeData andType:(int)type{

 

    int size = (int)[encodeData length];

    

    int iCount = 0;

 

    char * encodeCharData = (char *)[encodeData bytes];

 

    switch (type) {

        case 1:{

            testObjc->Packet_I_frame(encodeCharData, size, pszBuffer, iCount, 25);

 

        }

            

            break;

        case 2:{

             testObjc->Packet_P_frame(encodeCharData, size, pszBuffer, iCount);

            

        }

 

            break;

        case 3:{

            

             testObjc->Packet_Audio_frame(encodeCharData, size, pszBuffer,iCount,true);

            

                     }

 

            break;

            

        default:

            break;

    }

    

    

  NSData *   PsData = [NSData dataWithBytes:pszBuffer length:iCount];

    

    return PsData;

    

 

}

 

 

 

下面是.h文件

#pragma once

 

#define PS_Packet_Start_Code_Len       4       

#define PS_Header_Len                  14      //≤a?o???÷Ω??‘??PS_Header

#define PS_Header_Len_aligned          20      //?o???÷Ω??‘????μ?PS_Header

 

#define MAX_PSBUFFER_SIZE 5106

#define MUX_RATE 0

 

#define FRAME_BUFFER_MAX    1024*1024*2 // μ?∏?H264÷°μ??ó¥?≥§??

 

//∑Ω∑?

#define OFFSET(x) (90000/x)

 

//¥ì??∑μa?

#define  PS_Error_OK              0

#define  PS_Error_Param          -1

#define  PS_Error_Stream         -2

#define  PS_Error_Format         -3

#define  PS_Error_H264           -4

#define  PS_Error_Pes_Len        -5

 

#if (defined(WIN32))

#define CALLBACK  __stdcall

#else

#define CALLBACK  

#endif

 

typedef void (CALLBACK * PSOutputCallBack)(char *pData, int size, unsigned long user);

 

class CFrameBuffer {

public:

CFrameBuffer() {

size = 0;

pBuffer = new char[FRAME_BUFFER_MAX];

pPSBuffer = new char[FRAME_BUFFER_MAX];

};

~CFrameBuffer() {

delete pBuffer;

delete pPSBuffer;

};

char *pBuffer;

char *pPSBuffer;

int size;

};

 

class CPSPackager {

public:

CPSPackager(void);

~CPSPackager(void);

 

bool create(PSOutputCallBack callback, unsigned long user);

void destroy();

 

 

PSOutputCallBack m_pFuncOutputCallBack;

unsigned long m_pUser;

public:

unsigned int m_nScrb;

unsigned int m_nDts;

unsigned int m_nVideoPts;

 

int m_nFrameRate;

bool m_bStarted;

CFrameBuffer m_buffer;

bool m_bFindFirstIFrame;

 

int Packet_I_frame(const char* pSrcBuf, int nSrcLen, char* pDestBuf, int& nDestLen, int nFrameRate);

int Packet_P_frame(const char* pSrcBuf, int nSrcLen, char* pDestBuf, int& nDestLen, bool addPSHeader = true);

int Packet_Audio_frame(const char* pSrcBuf, int nSrcLen, char* pDestBuf, int& nDestLen, bool addPSHeader = true);

int Packet_PS_header(char* pDestBuf, int& nLen, bool bAudio, bool bAligned = false);

int Packet_PS_map(char* pDestBuf, int& nLen);

int Packet_frame(const char* pSrcBuf , int nSrcLen , bool isVideo, char* pDestBuf, int& nLen);

int GeneratePacketsFromFrame(const char* pSrcBuf , int nSrcLen, bool isVideo , char* pDestBuf , int& nLen);

};

 

 

这里是cpp文件

#include "PSPackager.h"

#include "string.h"

#include <algorithm>

 

using namespace std;

 

static unsigned char DH_IDENTITY[4] = {0x64, 0x68, 0x61, 0x76};

static unsigned char H264_IDENTITY[4] = {0x00, 0x00, 0x00, 0x01};

static unsigned char H264_IDENTITY_IDR[5] = {0x00, 0x00, 0x00, 0x01, 0x67};

static unsigned char PS_header[PS_Packet_Start_Code_Len] = {0x00 , 0x00 , 0x01 , 0xBA};

// static unsigned char PS_System_Header[PS_Packet_Start_Code_Len] = {0x00 , 0x00 , 0x01 , 0xBB};

static unsigned char PS_Map_Header[PS_Packet_Start_Code_Len] = {0x00 , 0x00 , 0x01 , 0xBC};

static unsigned char PS_Audio_Pes_Header[PS_Packet_Start_Code_Len] = {0x00 , 0x00 , 0x01 , 0xC0};

static unsigned char PS_Video_Pes_Header[PS_Packet_Start_Code_Len] = {0x00 , 0x00 , 0x01 , 0xE0};

 

CPSPackager::CPSPackager(void) {

m_nScrb = 60000;

m_nDts = 0;

m_nVideoPts = 60000;

m_nFrameRate = 25;

 

m_bStarted = false;

m_bFindFirstIFrame = false;

 

m_pFuncOutputCallBack = NULL;

m_pUser = NULL;

}

 

CPSPackager::~CPSPackager(void) {

destroy();

}

 

bool CPSPackager::create(PSOutputCallBack callback, unsigned long user) {

if (callback == NULL)

return false;

 

m_pFuncOutputCallBack = callback;

m_pUser = user;

return false;

}

 

void CPSPackager::destroy() {

m_pFuncOutputCallBack = NULL;

m_pUser = NULL;

}

 

int CPSPackager::Packet_I_frame(const char* pSrcBuf, int nSrcLen, char* pDestBuf, int& nDestLen, int nFrameRate) {

if (NULL == pSrcBuf || NULL == pDestBuf)

return PS_Error_Param;

 

int nTempLen = 0;

int nTotalLen = 0;

 

if (m_nFrameRate != nFrameRate)

m_nFrameRate = nFrameRate ;

 

Packet_PS_header(pDestBuf, nTempLen, true, true);

nTotalLen += nTempLen;

Packet_PS_map(pDestBuf+nTotalLen, nTempLen);

nTotalLen += nTempLen;

 

GeneratePacketsFromFrame(pSrcBuf, nSrcLen, true, pDestBuf+nTotalLen, nTempLen);

nTotalLen += nTempLen;

nDestLen = nTotalLen;

return PS_Error_OK;

}

 

int CPSPackager::Packet_P_frame(const char* pSrcBuf , int nSrcLen, char* pDestBuf , int& nDestLen, bool addPSHeader) {

if ( NULL == pSrcBuf || NULL == pDestBuf )

return PS_Error_Param;

 

int nTempLen = 0;

int nTotalLen = 0;

 

if (addPSHeader) {

Packet_PS_header(pDestBuf , nTempLen , true, true);

nTotalLen += nTempLen;

}

 

GeneratePacketsFromFrame(pSrcBuf , nSrcLen , true, pDestBuf + nTotalLen , nTempLen);

nTotalLen += nTempLen;

nDestLen = nTotalLen;

 

return PS_Error_OK ;

}

 

int CPSPackager::Packet_Audio_frame(const char* pSrcBuf , int nSrcLen, char* pDestBuf , int& nDestLen, bool addPSHeader) {

if ( NULL == pSrcBuf || NULL == pDestBuf )

return PS_Error_Param;

 

int nTempLen = 0;

int nTotalLen = 0;

 

if (addPSHeader) {

Packet_PS_header(pDestBuf , nTempLen , true, true);

nTotalLen += nTempLen;

}

 

GeneratePacketsFromFrame(pSrcBuf , nSrcLen , false, pDestBuf + nTotalLen , nTempLen);

nTotalLen += nTempLen;

nDestLen = nTotalLen;

 

return PS_Error_OK ;

}

 

int CPSPackager::Packet_PS_header(char* pDestBuf, int& nLen , bool bVideo, bool bAligned /* = false */) {

if ( NULL == pDestBuf)

return PS_Error_Param;

 

char temp = 0x00;

memcpy( pDestBuf, PS_header , PS_Packet_Start_Code_Len);

 

if (bVideo)

m_nScrb = m_nVideoPts;

 

pDestBuf[4]=((0x38&(m_nScrb>>26))|0x44);

pDestBuf[4]=(pDestBuf[4]|((m_nScrb>>28)&0x03));

 

pDestBuf[5]=((m_nScrb>>20)&(0xFF));

temp = ((m_nScrb>>12)&(0xF8));

pDestBuf[6]=(temp|0x04|((m_nScrb>>13)&0x03));

 

pDestBuf[7]=((m_nScrb>>5)&(0xFF));

temp=((((m_nScrb&0x1f)<<3)&0xf8)|0x04);

 

//system_clock_reference_extension …???0  9∏?bit?o÷√?a??0 

pDestBuf[8]=(temp|0x03);

pDestBuf[9]=0x01;

 

pDestBuf[10]=(MUX_RATE>>14)&0xff;

pDestBuf[11]=(MUX_RATE>>6)&0xff;

pDestBuf[12]=(((MUX_RATE<<2)&0xfc)|0x03);

 

if ( !bAligned ) {

pDestBuf[13] = 0xF8;

nLen = PS_Header_Len;

} else {

pDestBuf[13] = 0xFE;

pDestBuf[14] = 0xFF;

pDestBuf[15] = 0xFF;

pDestBuf[16] = 0x00;

pDestBuf[17] = 0x00;

pDestBuf[18] = 0x00;

pDestBuf[19] = 0x00;

nLen = PS_Header_Len_aligned;

}

 

return PS_Error_OK;

}

 

int CPSPackager::Packet_PS_map(char* pDestBuf, int& nLen) {

if ( NULL == pDestBuf)

return PS_Error_Param;

 

memcpy( pDestBuf, PS_Map_Header , PS_Packet_Start_Code_Len);

 

pDestBuf[4] = 0x00;

pDestBuf[5] = 0x18;

 

pDestBuf[6] = 0xE1;

pDestBuf[7] = 0xFF;

 

pDestBuf[8] = 0x00;

pDestBuf[9] = 0x00;

 

pDestBuf[10] = 0x00;

pDestBuf[11] = 0x08;

 

//element_info

pDestBuf[12] = 0x1B;   //H.264

 

pDestBuf[13] = 0xE0;

pDestBuf[14] = 0x00;

pDestBuf[15] = 0x06;

 

//avc timming and hrd descriptor

pDestBuf[16] = 0x0a;

pDestBuf[17] = 0x04;

pDestBuf[18] = 0x65;

pDestBuf[19] = 0x6e;

pDestBuf[20] = 0x67;

pDestBuf[21] = 0x00;

 

pDestBuf[22] = 0x90;

pDestBuf[23] = 0xc0;

pDestBuf[24] = 0x00;

pDestBuf[25] = 0x00;

 

pDestBuf[26] = 0x00;

pDestBuf[27] = 0x00;

pDestBuf[28] = 0x00;

pDestBuf[29] = 0x00;

 

nLen = 30;

return PS_Error_OK;

}

 

int CPSPackager::Packet_frame(const char* pSrcBuf, int nSrcLen, bool isVideo, char* pDestBuf, int& nLen) {

if ( NULL == pSrcBuf || NULL == pDestBuf )

return PS_Error_Param;

 

int nTempLen = 0;

 

bool bIncreasePTS = false;

if (pSrcBuf[0] == 0x00 && 

pSrcBuf[1] == 0x00 && 

pSrcBuf[2] == 0x00 && 

pSrcBuf[3] == 0x01) {

 

unsigned char c5=pSrcBuf[4];

unsigned char c6=pSrcBuf[5];

 

if (((c5 & 0x1F) == 8) || ((c5 & 0x1F) == 5) || (c6 == 0x88 && (c5 & 0x1F) == 1))

bIncreasePTS = false;

else

bIncreasePTS = true;

}

 

if (isVideo)

memcpy( pDestBuf , PS_Video_Pes_Header , PS_Packet_Start_Code_Len);

else

memcpy( pDestBuf , PS_Audio_Pes_Header , PS_Packet_Start_Code_Len);

 

nTempLen = 8 + nSrcLen;

//PES∞?μ?≥§??

pDestBuf[4] = (nTempLen >> 8) & 0xFF;

pDestBuf[5] = nTempLen & 0xFF;

 

pDestBuf[6] = 0x88;

pDestBuf[8] = 0x05;

if (bIncreasePTS) {

m_nVideoPts += OFFSET(m_nFrameRate);

//PTS_DTS_flag = ‘10‘;

pDestBuf[7] = 0x80;

pDestBuf[9] = ((m_nVideoPts>>29)|0x21);

pDestBuf[10] = (m_nVideoPts>>22);

pDestBuf[11] = ((m_nVideoPts>>14)|0x01);

pDestBuf[12] = (m_nVideoPts>>7);

pDestBuf[13] = (((m_nVideoPts<<1)&0xFE)|0x01);

} else {

//PTS_DTS_flag = ‘00‘;

pDestBuf[7] = 0x00;

pDestBuf[9]  = 0xFF;

pDestBuf[10] = 0xFF;

pDestBuf[11] = 0xFF;

pDestBuf[12] = 0xFF;

pDestBuf[13] = 0xFE;

}

 

nTempLen = 14 ;

memcpy(pDestBuf + nTempLen , pSrcBuf , nSrcLen);

nLen = nTempLen + nSrcLen;

 

return PS_Error_OK;

}

 

int CPSPackager::GeneratePacketsFromFrame(const char* pSrcBuf, int nSrcLen, bool isVideo, char* pDestBuf, int& nLen) {

int nTotalLen = 0; 

int nPacketNalLen = 0;

int rest_len = nSrcLen;

int nNalCount = 0;

int nOldIndex = 0;

int nPacketCount = 0;

 

while( nSrcLen - nOldIndex > MAX_PSBUFFER_SIZE) {

Packet_frame(pSrcBuf + nOldIndex , MAX_PSBUFFER_SIZE , isVideo, pDestBuf + nTotalLen , nPacketNalLen );

 

nOldIndex += MAX_PSBUFFER_SIZE;

nTotalLen += nPacketNalLen;

nPacketCount++;

}

 

Packet_frame(pSrcBuf + nOldIndex , nSrcLen - nOldIndex , isVideo, pDestBuf + nTotalLen , nPacketNalLen);

 

nTotalLen += nPacketNalLen;

nPacketCount++;

nLen = nTotalLen;

 

return PS_Error_OK;

}

以上是关于iOS 将视频流(h264)和音频流封装成PS流的主要内容,如果未能解决你的问题,请参考以下文章

PS封装H264码流分析

GB/T28181-2016基于RTP的视音频数据封装和技术实现

笔记- iphone手机音频AAC视频H264推流 iphone手机推流最佳方案

FLV文件(H264 + AAC)格式超详细分析

FLV文件(H264 + AAC)格式超详细分析

PS流格式解析