调用方法:

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      //≤ªøº¬«◊÷Ω⁄∂‘∆ÎPS_Header

#define PS_Header_Len_aligned          20      //øº¬«◊÷Ω⁄∂‘∆Μ¬µƒPS_Header

#define MAX_PSBUFFER_SIZE 5106

#define MUX_RATE 0

#define FRAME_BUFFER_MAX    1024*1024*2 // µ•∏ˆH264÷°µƒ◊Ó¥Û≥§∂»

//∑Ω∑®

#define OFFSET(x) (90000/x)

//¥ÌŒÛ∑µªÿ

#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∂º÷√ŒªŒ™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流的更多相关文章

  1. H264编码 封装成MP4格式 视频流 RTP封包

    H264编码 封装成MP4格式 视频流 RTP封包         分类:             多媒体编程              2013-02-20 21:31     3067人阅读    ...

  2. 通过摄像机视频设备或者流媒体服务器SDK获取到数据转换成RTMP流实现网页/手机微信播放

    写这篇博客主要是为了给新入门的流媒体开发者解惑,现在看到各种开发者的需求:网页播放RTSP摄像机.微信播放RTSP摄像机.网页播放摄像机SDK输出的视频流.网页播放第三方流媒体平台输出的视频流.包括G ...

  3. 使用Cordova框架把Webapp封装成Hybrid App实践——Android篇

    公司没有IOS和没有安卓开发人员,前端后端都是需要自己玩前几天技术经理说有一个需求要把webapp封装成Hybrid App,现已完成.记录一下从中遇到的问题和需要用到的开发环境的配置 将Webapp ...

  4. .NET 同步与异步之封装成Task(五)

    本随笔续接:.NET 实现并行的几种方式(四) 前篇随笔已经介绍了几种可以实现并发的方式,其中异步方法.是最简便的方式.而 异步方式是基于 Task 和 async修饰符和await运算符实现的. 换 ...

  5. 将HTML5封装成android应用APK文件的几种方法

    越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...

  6. 将HTML5封装成android应用APK文件的几种方法(转载)

    越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...

  7. 如何将Js代码封装成Jquery插件

    很多相同的Jquery代码会在很多页面使用,每次都复制粘贴太麻烦了,不如封装成一个Jquery插件就方便了,至于影响网页的速度不,我就没有测试了哈. 代码如下 这是一个自定闪烁打印文字的Jquery特 ...

  8. 将Python脚本封装成exe可执行文件 转

    将Python脚本封装成exe可执行文件 http://www.cnblogs.com/renzo/archive/2012/01/01/2309260.html  cx_freeze是用来将 Pyt ...

  9. Asp.net Core中使用NLog,并封装成公共的日志方法

    1.安装NLog "NLog.Extensions.Logging": "1.0.0-rtm-alpha4" 2.配置NLog public void Conf ...

随机推荐

  1. 团队作业8——Beta 阶段冲刺4th day

    团队作业8--Beta 阶段冲刺4rd day 一.当天站立式会议   二.每个人的工作 (1)昨天已完成的工作(具体在表格中) 添加了支付功能,并且对支付功能进行了测试 (2)今天计划完成的工作(具 ...

  2. list后台转化为JSON的方法ajax

    导入alibaba的fastJson包 后台: protected void doGet(HttpServletRequest request, HttpServletResponse respons ...

  3. 201521123119《Java程序设计》第4周学习总结

    1. 本周学习总结 2.书面作业 1.注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图) 2.面向对象设计(大作业1,非常重要) 2.1 将在网上商城 ...

  4. 201521123037 《Java程序设计》第2周学习总结

    1. 本周学习总结 初步学会分析使用命令提示符进行编译的命令 了解使用import引入不同包的类 学会码云与eclipse的连接 使用Array和String函数编写程序 2. 书面作业 1. 使用E ...

  5. phpcms总结(转)

    转自:http://www.cnblogs.com/zuzwn/p/3649536.html文件目录结构 根目录 | – api 接口文件目录 | – caches 缓存文件目录 | – config ...

  6. Nim函数调用的几种形

    Nim函数调用的几种形式 Nim 转载条件:如果你需要转载本文,你需要做到完整转载本文所有的内容,不得删改文内的作者名字与链接.否则拒绝转载. 关于nim的例行介绍: Nim 是一门静态编译型的系统级 ...

  7. Java I/O 从0到1 - 第Ⅰ滴血 File

    前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...

  8. 01快速入门-04-Map、Set和iterable(ES6)

    1.Map 我们知道,在JS中其实对象的方式就跟Java中的Map极为相似,即键值对的方式.JS中,key必须是字符串,实际上Number等值作为key也是合理的,所以为了解决这个问题,在最新的ES6 ...

  9. 监控-CPU使用率

    原始脚本来自TG,自己对部分脚本做了调整,分享出来仅供参考,请勿整篇Copy! 使用以下语句获取[CPU使用率] USE [DBA_Monitor] GO /****** 对象: StoredProc ...

  10. eclipse Maven新建一个项目并使用

      安装参考这篇博文eclipse配置maven + 创建maven项目(三)  打开pom.xml 试着添加MySQL的JDBC驱动 添加如下配置, <dependency> <g ...