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 //≤ªøº¬«◊÷Ω⁄∂‘∆Î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流的更多相关文章
- H264编码 封装成MP4格式 视频流 RTP封包
H264编码 封装成MP4格式 视频流 RTP封包 分类: 多媒体编程 2013-02-20 21:31 3067人阅读 ...
- 通过摄像机视频设备或者流媒体服务器SDK获取到数据转换成RTMP流实现网页/手机微信播放
写这篇博客主要是为了给新入门的流媒体开发者解惑,现在看到各种开发者的需求:网页播放RTSP摄像机.微信播放RTSP摄像机.网页播放摄像机SDK输出的视频流.网页播放第三方流媒体平台输出的视频流.包括G ...
- 使用Cordova框架把Webapp封装成Hybrid App实践——Android篇
公司没有IOS和没有安卓开发人员,前端后端都是需要自己玩前几天技术经理说有一个需求要把webapp封装成Hybrid App,现已完成.记录一下从中遇到的问题和需要用到的开发环境的配置 将Webapp ...
- .NET 同步与异步之封装成Task(五)
本随笔续接:.NET 实现并行的几种方式(四) 前篇随笔已经介绍了几种可以实现并发的方式,其中异步方法.是最简便的方式.而 异步方式是基于 Task 和 async修饰符和await运算符实现的. 换 ...
- 将HTML5封装成android应用APK文件的几种方法
越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...
- 将HTML5封装成android应用APK文件的几种方法(转载)
越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...
- 如何将Js代码封装成Jquery插件
很多相同的Jquery代码会在很多页面使用,每次都复制粘贴太麻烦了,不如封装成一个Jquery插件就方便了,至于影响网页的速度不,我就没有测试了哈. 代码如下 这是一个自定闪烁打印文字的Jquery特 ...
- 将Python脚本封装成exe可执行文件 转
将Python脚本封装成exe可执行文件 http://www.cnblogs.com/renzo/archive/2012/01/01/2309260.html cx_freeze是用来将 Pyt ...
- Asp.net Core中使用NLog,并封装成公共的日志方法
1.安装NLog "NLog.Extensions.Logging": "1.0.0-rtm-alpha4" 2.配置NLog public void Conf ...
随机推荐
- CSS基础知识摘要
元素分类 块级元素 什么是块级元素?在html中<div>. <p>.<h1>.<form>.<table>.<ul> 和 &l ...
- 团队作业4——第一次项目冲刺(Alpha版本)4.28
团队作业4--第一次项目冲刺(Alpha版本) Day seven: 会议照片 每日站立会议: 项目进展 今天是项目的Alpha敏捷冲刺的第七天,先大概整理下昨天已完成的任务以及今天计划完成的任务.今 ...
- 201521123033《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. answer: 1.2 选做:收集你认为有用的代码片段 2. 书面作业 本次作业题集集合 1.List中指定元 ...
- 201521123114 《Java程序设计》第7周学习总结
1. 本章学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 Q1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 public b ...
- 201521123070 《JAVA程序设计》第3周学习总结
1. 本章学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. http:/ ...
- 201521123097《Java程序设计》第十周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 1.finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中fin ...
- postman: 用于网页调试和发送Http请求的chrome插件
一 简介 Postman 是一款功能超级强大的用于发送 HTTP 请求的 Chrome插件 .做web页面开发和测试的人员应该是无人不晓无人不用!其主要特点 特点: 创建 + 测试:创建和发送任何的H ...
- 基于socket.io的实时在线选座系统
基于socket.io的实时在线选座系统(demo) 前言 前段时间公司做一个关于剧院的项目,遇到了这样一种情况. 在高并发多用户同时选座的情况下,假设A用户进入选座页面,正在选择座位,此时还没有提交 ...
- MapReduce执行过程
Mapper任务的执行过程: 第一阶段是把输入文件按照一定的标准分片(InputSplit),每个输入片的大小是固定的.默认情况下,输入片(InputSplit)的大小与数据块(Block)的大小是相 ...
- Tree--RedBlackTree详解(2 - 3 - 4Tree)(红黑树)
#topics h2 { background: #2B6695; color: #FFFFFF; font-family: "微软雅黑", "宋体", &qu ...