EasyPlayer-RTSP播放器是一套RTSP专用的播放器,包括有:Windows(支持IE插件,npapi插件)、Android、iOS三个平台,是区别于市面上大部分的通用播放器,EasyPlayer-RTSP更加精炼、更加专注,具备低延时和高RTSP协议兼容性,编码数据解析等方面,都有非常大的优势。

EasyPlayer-RTSP-Win中录像采用GPAC的MP4Box库来封装MP4,下面我将简单介绍MP4的封装调用流程和需要注意的点

一、GPAC库的编译,GPAC是跨平台的库,windows和linux都能很方便多编译,再次不做过多赘述,大家可去GPAC官网或者Github上下载;

二、创建MP4

bool EasyMP4Writer::CreateMP4File(char*filename,int flag)
{SaveFile();m_audiostartimestamp=-1;m_videostartimestamp=-1;if(filename==NULL){char filename2[256]={0};sprintf(filename2,"%d-gpac%d.mp4",time(NULL),rand());p_file=gf_isom_open(filename2,GF_ISOM_OPEN_WRITE,NULL);//打开文件}elsep_file=gf_isom_open(filename,GF_ISOM_OPEN_WRITE,NULL);//打开文件if (p_file==NULL){return false;}gf_isom_set_brand_info(p_file,GF_ISOM_BRAND_MP42,0);//if(flag&ZOUTFILE_FLAG_VIDEO)//{//    m_videtrackid=gf_isom_new_track(p_file,0,GF_ISOM_MEDIA_VISUAL,1000);// gf_isom_set_track_enabled(p_file,m_videtrackid,1);//}//if(flag&ZOUTFILE_FLAG_AUDIO)//{//    m_audiotrackid=gf_isom_new_track(p_file,0,GF_ISOM_MEDIA_AUDIO,1000);// gf_isom_set_track_enabled(p_file,m_audiotrackid,1);//}m_nCreateFileFlag = flag;return true;
}

创建MP4很简单,调用gf_isom_open函数就能轻松搞定,gf_isom_set_brand_info函数设置当前写MP4的版本为MP4V2;值得注意的地方是:

1>. 创建文件之前需要对所有的参数进行初始化,以及如果文件正在写入则需要将其关闭,这个操作主要是32位程序写的MP4文件大于4G可能出现不能播放的问题,为了方便写MP4文件进行分片,这个将在系列文章后续中进行讲解;
2>. 大家可以看到上段代码有屏蔽了部分代码flag&ZOUTFILE_FLAG_VIDEO和flag&ZOUTFILE_FLAG_AUDIO的判断,这两段代码是用来在MP4文件中创建音频轨和视频轨(默认各只创建一个),请注意:如果这里已经创建了音频和视频轨,然而后续的写入过程中如果只写音频或者视频的话,某些播放器可能是播不出来的(比如windows自带的播放器),所以,如果只写音频的话只需要创建音频轨就可以了,视频同理。

三、写入视频H264的SPS和PPS头信息

bool EasyMP4Writer::WriteH264SPSandPPS(unsigned char*sps,int spslen,unsigned char*pps,int ppslen,int width,int height)
{   if (m_nCreateFileFlag&ZOUTFILE_FLAG_VIDEO){m_videtrackid = gf_isom_new_track(p_file, 0, GF_ISOM_MEDIA_VISUAL, 1000);gf_isom_set_track_enabled(p_file, m_videtrackid, 1);}else{return false;}p_videosample=gf_isom_sample_new();p_videosample->data=(char*)malloc(1024*1024);p_config=gf_odf_avc_cfg_new();   gf_isom_avc_config_new(p_file,m_videtrackid,p_config,NULL,NULL,&i_videodescidx);gf_isom_set_visual_info(p_file,m_videtrackid,i_videodescidx,width,height);GF_AVCConfigSlot m_slotsps={0};GF_AVCConfigSlot m_slotpps={0};p_config->configurationVersion = 1;p_config->AVCProfileIndication = sps[1];p_config->profile_compatibility = sps[2];p_config->AVCLevelIndication = sps[3];m_slotsps.size=spslen;m_slotsps.data=(char*)malloc(spslen);memcpy(m_slotsps.data,sps,spslen); gf_list_add(p_config->sequenceParameterSets,&m_slotsps);m_slotpps.size=ppslen;m_slotpps.data=(char*)malloc(ppslen);memcpy(m_slotpps.data,pps,ppslen);gf_list_add(p_config->pictureParameterSets,&m_slotpps);gf_isom_avc_config_update(p_file,m_videtrackid,1,p_config);free(m_slotsps.data);free(m_slotpps.data);return true;
}

首先,通过gf_odf_avc_cfg_new()创建一个设置AVC信息的配置结构p_config,然后对结构中指定的信息,如:长,宽,SPS和PPS等关键参数写入配置结构,调用gf_isom_avc_config_update函数写入参数信息;当然这里只是H264格式的参数设置,像其他的格式比如H265的设置也类似,这将在后续系列中进行讲解;

四、写入音频AAC头信息

//写入AAC信息

bool EasyMP4Writer::WriteAACInfo(unsigned char*info,int len, int nSampleRate, int nChannel, int nBitsPerSample)
{if (m_nCreateFileFlag&ZOUTFILE_FLAG_AUDIO){m_audiotrackid = gf_isom_new_track(p_file, 0, GF_ISOM_MEDIA_AUDIO, 1000);gf_isom_set_track_enabled(p_file, m_audiotrackid, 1);}else{return false;}p_audiosample=gf_isom_sample_new();p_audiosample->data=(char*)malloc(1024*10);GF_ESD*esd=  gf_odf_desc_esd_new(0);esd->ESID=gf_isom_get_track_id(p_file,m_audiotrackid);esd->OCRESID=gf_isom_get_track_id(p_file,m_audiotrackid);esd->decoderConfig->streamType=0x05;esd->decoderConfig->objectTypeIndication=0x40;//0x40;esd->slConfig->timestampResolution=1000;//1000;//时间单元   esd->decoderConfig->decoderSpecificInfo=(GF_DefaultDescriptor*)gf_odf_desc_new(GF_ODF_DSI_TAG);esd->decoderConfig->decoderSpecificInfo->data=(char*)malloc(len);memcpy(esd->decoderConfig->decoderSpecificInfo->data,info,len);esd->decoderConfig->decoderSpecificInfo->dataLength=len;GF_Err gferr=gf_isom_new_mpeg4_description(p_file, m_audiotrackid, esd,  NULL, NULL, &i_audiodescidx);if (gferr!=0){
//      TRACE("mpeg4_description:%d\n",gferr);}gferr=gf_isom_set_audio_info(p_file,m_audiotrackid,i_audiodescidx, nSampleRate,nChannel, nBitsPerSample);//44100 2 16if (gferr!=0){
//      TRACE("gf_isom_set_audio:%d\n",gferr);}free(esd->decoderConfig->decoderSpecificInfo->data);return true;
}

调几个 API就搞定了,一如既往的简单–!,这里说一下一些关键参数的配置:
1> esd->decoderConfig->streamType=0x05,这里的0x05标示为AAC,当然还指出其他的类型,如MP3,AC3等等,具体可查询MP4BOX相关文档获取;
2> 函数出入的头两个参数大家看起来有点费解,这里表示的是音频解码参数组合的一个串,具体格式解析如下:(这个本来想单独开一篇博客来专门阐述的,但是鉴于没多少内容就在这里一并表述出来)
看下面代码段:

     //      前五位为 AAC object types  LOW          2//         接着4位为 码率index        16000        8//       采样标志标准://    static unsigned long tnsSupportedSamplingRates[13] = //音频采样率标准(标志),下标为写入标志//  { 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0 };//         接着4位为 channels 个数                 2//       最后3位用0补齐//      应打印出的正确2进制形式为  00010 | 1000 | 0010 | 000//                                   2       8      2//  BYTE ubDecInfoBuff[] =  {0x12,0x10};//00010 0100 0010 000//音频采样率标准(标志),下标为写入标志unsigned long tnsSupportedSamplingRates[13] = { 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0 };int nI = 0;for ( nI = 0; nI<13; nI++){if (tnsSupportedSamplingRates[nI] == sample_rate ){break;}}unsigned char ucDecInfoBuff[2] = {0x12,0x10};//unsigned short  nDecInfo = (1<<12) | (nI << 7) | (channels<<3);int nSize = sizeof(unsigned short);memcpy(ucDecInfoBuff, &nDecInfo, nSize);SWAP(ucDecInfoBuff[0], ucDecInfoBuff[1]);int unBuffSize = sizeof(ucDecInfoBuff)*sizeof(unsigned char);

大家看懂了吧,比如现在有个表示解码信息的串为 00010 | 0100 | 0010 | 000 ,那么它则表示为AAC-LC 44100采样率 双声道音频,是不是很好理解呢!!!

五、解析H264帧写入MP4

下面用文字描述,分三步走:
1> 解析H264 nal头,获取SPS和PPS, 因为我们已经通过设置函数设置了SPS和PPS等解码关键信息,所以我们写入文件时,H264帧将转换为AVC格式,什么意思,就是说将以00000001以及000001开头的NAL单元转换为以该NAL单元的长度来填满该四个字节(注意:所有的H264帧中的0x00000001和0x000001都要替换成NAL的长度,否则未替换的部分解码会花屏),默认三个字节的000001也用四个字节补齐,这主要是见于一帧多NAL的情况,这里有疑问我将在后续系列文章中讲解;
2> 写入SPS和PPS头;
3> 写入以NAL长度为头四个字节的AVC帧,具体实现如下:
//写入一帧,前四字节为该帧NAL长度

bool EasyMP4Writer::WriteVideoFrame(unsigned char*data,int len,bool keyframe,long timestamp)
{       if (!p_videosample){return false;}if (m_videostartimestamp==-1&&keyframe){m_videostartimestamp=timestamp;}if (m_videostartimestamp!=-1){p_videosample->IsRAP=keyframe;p_videosample->dataLength=len;memcpy(p_videosample->data,data,len);p_videosample->DTS=timestamp-m_videostartimestamp;p_videosample->CTS_Offset=0;  GF_Err gferr=gf_isom_add_sample(p_file,m_videtrackid,i_videodescidx,p_videosample);            if (gferr==-1){p_videosample->DTS=timestamp-m_videostartimestamp+15;gf_isom_add_sample(p_file,m_videtrackid,i_videodescidx,p_videosample);}}return true;
}

六、AAC写入MP4(是否带ADTS头)

同写视频类似,写音频同样要先写如音频解码参数,上文已经分析过如何写解码参数,这里只需把解码参数信息组织成串,通过WriteAACInfo()函数写入即可。
写音频数据,实现和视频一样,调用gf_isom_add_sample函数即可;
需要注意:因为我们已经写入了音频解码信息,那么如果AAC数据中带有ADTS头,则需要去掉则7个字节的头,否则可能部分播放器不能正常播放,ADTS头以 0xFFF 开始;

七、写入MP4封装头,保存文件

保存文件,释放缓存和系统资源:
//保存文件

bool EasyMP4Writer::SaveFile()
{if (m_psps){delete m_psps;m_psps = NULL;}if (m_ppps){delete m_ppps;m_ppps = NULL;}m_spslen=0;m_ppslen=0;if (m_pvps){delete m_pvps;m_pvps = NULL;}m_vpslen = 0;m_audiostartimestamp=-1;m_videostartimestamp=-1;if (p_file){gf_isom_close(p_file);p_file=NULL;}if(p_config){//  delete p_config->pictureParameterSets;p_config->pictureParameterSets=NULL;// delete p_config->sequenceParameterSets;p_config->sequenceParameterSets=NULL;gf_odf_avc_cfg_del(p_config);p_config=NULL;}if (p_hevc_config){gf_odf_hevc_cfg_del(p_hevc_config);p_hevc_config = NULL;}if(    p_audiosample){if(  p_audiosample->data){free(p_audiosample->data);p_audiosample->data=NULL;}gf_isom_sample_del(&p_audiosample);p_audiosample=NULL;}if(  p_videosample){if(  p_videosample->data){free(p_videosample->data);p_videosample->data=NULL;}gf_isom_sample_del(&p_videosample);p_audiosample=NULL;}m_bwriteaudioinfo = false;m_bwritevideoinfo = false;return true;
}

RTSP播放器高RTSP兼容推流网页无插件流媒体播放器EasyPlayer-RTSP关于MP4的封装调用流程介绍相关推荐

  1. 多功能流媒体播放器实现网页无插件直播之EasyPlayer.js如何实现播放完自动循环播放

    EasyPlayer-Android播放器是一款可针对RTSP.RTMP.RTSP&RTMP协议进行过优化的流媒体播放器,其中我们引以为傲的两个技术优势就是起播速度快和播放延迟低.最近我们遇到 ...

  2. 海康大华等摄像头RTSP低延迟(1秒以内)网页无插件播放解决方案

    简介 监控摄像头网页无插件播放解决方案虽然很多,但是或多或少会有一定的延迟,其中网上使用最多的是RTSP转RTMP推流的方式,这种延迟一般十秒左右,优化的好的话能达到五秒,但是依旧算不上实时.本文提供 ...

  3. RTSP安防网络摄像头/海康大华硬盘录像机/NVR网页无插件低延时播放流媒体服务器EasyNVR页面显示网络请求失败问题

    进入移动互联网时代以来,企业微信公众号已成为除官网以外非常重要的宣传渠道,当3.2亿直播用户与9亿微信用户的势能累加,在微信上开启直播已成为越来越多企业的必然选择. 青犀团队研发的EasyNVR核心在 ...

  4. html5 无插件视频播放器,多功能流媒体播放器网页无插件直播EasyPlayer.js如何实现播放完自动循环播放...

    原标题:多功能流媒体播放器网页无插件直播EasyPlayer.js如何实现播放完自动循环播放 EasyPlayer-Android播放器是一款可针对RTSP.RTMP.RTSP&RTMP协议进 ...

  5. 网页无插件视频流媒体播放器EasyPlayer.JS切换多清晰度码流播放报错,该如何调试?

    EasyPlayer是一款流媒体播放器系列项目,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放.支持本地文件播放,支持本地抓拍.本地录像.播放旋转.多屏播放.倍 ...

  6. 流媒体服务器+终端(android,ios,web),如何从海康平台上拉流接入RTSP安防网络摄像头/海康大华硬盘录像机网页无插件直播流媒体服务器EasyNVR?...

    背景需求 随着雪亮工程.明厨亮灶.手机看店.智慧幼儿园监控等行业开始将传统的安防摄像头进行互联网.微信直播,我们知道摄像头直播的春天了.将安防摄像头或NVR上的视频流转成互联网直播常用的RTMP.HT ...

  7. 新版RTSP协议网络摄像头网页无插件直播平台EasyNVR如何自定义通道的背景音乐?

    EasyNVR网页无插件直播平台经过多次的修正和改良,已经成为一套成熟的流媒体视频云服务平台,能够满足安防.智慧城市.教育等不同场景的应用需求. 目前,最新版本的EasyNVR支持自定义背景音乐,用户 ...

  8. 视频在html不能播放器,网页无插件直播H265编码视频播放器EasyPlayer网页播放器不能播放怎么处理?...

    原标题:网页无插件直播H265编码视频播放器EasyPlayer网页播放器不能播放怎么处理? EasyPlayer播放器系列项目提供了非常简单易用的SDK及API接口,用户通过API调用就可以非常快速 ...

  9. 安防RTSP无插件直播方案及RTSP配置规则

    LiveNVR搭建无插件直播方案时,采用行业标准的通用协议RTSP/Onvif接入摄像机IPC摄像机 / NVR硬盘录像机设备:Onvif是摄像机的发现与控制管理协议,Onvif用到的流媒体协议也是R ...

最新文章

  1. if null 锁 java_史上最全 Java 中各种锁的介绍
  2. different application signatures解决方法
  3. WPF 提供了以下关键帧动画类[msdn]
  4. 理解图像中卷积操作的含义
  5. Visual Studio 2008 和 .NET Framework 3.5 Service Pack 1 Beta 发布
  6. cisco 两个设备之间测试吞吐量的一个方法
  7. stm8s003程序跑飞_微信小程序只玩跳一跳?OUT啦!带你玩更好玩的微信小游戏!...
  8. jeesite导出Excel Minimum column number is 0
  9. 诗与远方:无题(二十八)- 曾经写给妹子的一首诗
  10. hdu 4027 Can you answer these queries?
  11. 苹果mac绘图软件:AutoCAD
  12. 吴恩达机器学习视频学习笔记(3)
  13. 社交APP软件开发流程解析
  14. 完整卸载SQL Server2008
  15. 几个国内的 apple 相关社区
  16. 第六讲 幂级数的收敛半径和收敛域
  17. 如何计算变量或数据类型所占内存空间的大小
  18. 基于 RTS 超低延时直播优化强互动场景体验
  19. 教师职业道德与专业发展
  20. ROS学习——rotors仿真下载与运行

热门文章

  1. windows10系统修改c盘Users目录中的中文名称
  2. 山东理工大学ACM平台题答案 2561 九九乘法表
  3. 《On Java》介绍
  4. 基于数字电路交通灯信号灯控制系统设计-基于单片机病房温度监测与呼叫系统设计-基于STM32的无线蓝牙心电监护仪系统设计-基于STM32的智能蓝牙温控风扇控制设计-基于STM32的智能温室控制系统设计
  5. Chrome的隐身模式
  6. cos三次方积分_cosx的四次方如何积分?
  7. 如何将此电脑放到桌面上(windows10版本)
  8. SQLServer 自定义函数 日期计算月初/月末/年初/年末/季初/季末
  9. Unity-tweak-tool插件
  10. 支持向量机 实战电信运营商 -客户流失预警