mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-10-31 00:37:39 +08:00
初步完成H264 的 RTMP打包解包
This commit is contained in:
parent
3850ecec96
commit
6c9d50b04b
@ -65,6 +65,21 @@ public:
|
|||||||
virtual bool keyFrame() const = 0;
|
virtual bool keyFrame() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ResourcePoolHelper{
|
||||||
|
public:
|
||||||
|
ResourcePoolHelper(int size = 8){
|
||||||
|
_pool.setSize(size);
|
||||||
|
}
|
||||||
|
virtual ~ResourcePoolHelper(){}
|
||||||
|
|
||||||
|
std::shared_ptr<T> obtainObj(){
|
||||||
|
return _pool.obtain();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ResourcePool<T> _pool;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 帧环形缓存接口类
|
* 帧环形缓存接口类
|
||||||
*/
|
*/
|
||||||
|
@ -55,8 +55,8 @@ void AACRtpEncoder::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark
|
|||||||
uint32_t ts = htonl(m_ui32TimeStamp);
|
uint32_t ts = htonl(m_ui32TimeStamp);
|
||||||
uint16_t sq = htons(m_ui16Sequence);
|
uint16_t sq = htons(m_ui16Sequence);
|
||||||
uint32_t sc = htonl(m_ui32Ssrc);
|
uint32_t sc = htonl(m_ui32Ssrc);
|
||||||
auto pRtppkt = obtainRtp();
|
auto pRtppkt = ResourcePoolHelper<RtpPacket>::obtainObj();
|
||||||
auto &rtppkt = *(pRtppkt.get());
|
auto &rtppkt = *pRtppkt;
|
||||||
unsigned char *pucRtp = rtppkt.payload;
|
unsigned char *pucRtp = rtppkt.payload;
|
||||||
pucRtp[0] = '$';
|
pucRtp[0] = '$';
|
||||||
pucRtp[1] = m_ui8Interleaved;
|
pucRtp[1] = m_ui8Interleaved;
|
||||||
@ -93,7 +93,7 @@ AACRtpDecoder::AACRtpDecoder(uint32_t ui32SampleRate) {
|
|||||||
|
|
||||||
AACFrame::Ptr AACRtpDecoder::obtainFrame() {
|
AACFrame::Ptr AACRtpDecoder::obtainFrame() {
|
||||||
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
auto frame = m_framePool.obtain();
|
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
|
||||||
frame->aac_frame_length = 7;
|
frame->aac_frame_length = 7;
|
||||||
frame->iPrefixSize = 7;
|
frame->iPrefixSize = 7;
|
||||||
return frame;
|
return frame;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
/**
|
/**
|
||||||
* aac rtp转adts类
|
* aac rtp转adts类
|
||||||
*/
|
*/
|
||||||
class AACRtpDecoder : public RtpCodec {
|
class AACRtpDecoder : public RtpCodec , public ResourcePoolHelper<AACFrame> {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<AACRtpDecoder> Ptr;
|
typedef std::shared_ptr<AACRtpDecoder> Ptr;
|
||||||
|
|
||||||
@ -39,7 +39,6 @@ private:
|
|||||||
AACFrame::Ptr obtainFrame();
|
AACFrame::Ptr obtainFrame();
|
||||||
private:
|
private:
|
||||||
AACFrame::Ptr m_adts;
|
AACFrame::Ptr m_adts;
|
||||||
ResourcePool<AACFrame> m_framePool;
|
|
||||||
uint32_t m_sampleRate;
|
uint32_t m_sampleRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ H264RtpDecoder::H264RtpDecoder() {
|
|||||||
|
|
||||||
H264Frame::Ptr H264RtpDecoder::obtainFrame() {
|
H264Frame::Ptr H264RtpDecoder::obtainFrame() {
|
||||||
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
auto frame = m_framePool.obtain();
|
auto frame = ResourcePoolHelper<H264Frame>::obtainObj();
|
||||||
frame->buffer.clear();
|
frame->buffer.clear();
|
||||||
frame->iPrefixSize = 4;
|
frame->iPrefixSize = 4;
|
||||||
return frame;
|
return frame;
|
||||||
@ -174,7 +174,7 @@ void H264RtpEncoder::makeH264Rtp(const void* data, unsigned int len, bool mark,
|
|||||||
uint16_t sq = htons(m_ui16Sequence);
|
uint16_t sq = htons(m_ui16Sequence);
|
||||||
uint32_t sc = htonl(m_ui32Ssrc);
|
uint32_t sc = htonl(m_ui32Ssrc);
|
||||||
|
|
||||||
auto rtppkt = obtainRtp();
|
auto rtppkt = ResourcePoolHelper<RtpPacket>::obtainObj();
|
||||||
unsigned char *pucRtp = rtppkt->payload;
|
unsigned char *pucRtp = rtppkt->payload;
|
||||||
pucRtp[0] = '$';
|
pucRtp[0] = '$';
|
||||||
pucRtp[1] = m_ui8Interleaved;
|
pucRtp[1] = m_ui8Interleaved;
|
||||||
|
@ -13,7 +13,7 @@ using namespace ZL::Util;
|
|||||||
/**
|
/**
|
||||||
* h264 rtp解码类
|
* h264 rtp解码类
|
||||||
*/
|
*/
|
||||||
class H264RtpDecoder : public RtpCodec {
|
class H264RtpDecoder : public RtpCodec , public ResourcePoolHelper<H264Frame> {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<H264RtpDecoder> Ptr;
|
typedef std::shared_ptr<H264RtpDecoder> Ptr;
|
||||||
|
|
||||||
@ -40,7 +40,6 @@ private:
|
|||||||
H264Frame::Ptr obtainFrame();
|
H264Frame::Ptr obtainFrame();
|
||||||
private:
|
private:
|
||||||
H264Frame::Ptr m_h264frame;
|
H264Frame::Ptr m_h264frame;
|
||||||
ResourcePool<H264Frame> m_framePool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,7 +72,6 @@ public:
|
|||||||
typedef std::shared_ptr<RtpRing> Ptr;
|
typedef std::shared_ptr<RtpRing> Ptr;
|
||||||
|
|
||||||
RtpRing(){
|
RtpRing(){
|
||||||
//禁用缓存
|
|
||||||
_rtpRing = std::make_shared<RingType>();
|
_rtpRing = std::make_shared<RingType>();
|
||||||
}
|
}
|
||||||
virtual ~RtpRing(){}
|
virtual ~RtpRing(){}
|
||||||
@ -111,7 +110,6 @@ public:
|
|||||||
m_ui32MtuSize = ui32MtuSize;
|
m_ui32MtuSize = ui32MtuSize;
|
||||||
m_ui8PlayloadType = ui8PlayloadType;
|
m_ui8PlayloadType = ui8PlayloadType;
|
||||||
m_ui8Interleaved = ui8Interleaved;
|
m_ui8Interleaved = ui8Interleaved;
|
||||||
m_rtpPool.setSize(32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~RtpInfo(){}
|
virtual ~RtpInfo(){}
|
||||||
@ -141,10 +139,6 @@ public:
|
|||||||
uint32_t getMtuSize() const {
|
uint32_t getMtuSize() const {
|
||||||
return m_ui32MtuSize;
|
return m_ui32MtuSize;
|
||||||
}
|
}
|
||||||
protected:
|
|
||||||
RtpPacket::Ptr obtainRtp(){
|
|
||||||
return m_rtpPool.obtain();
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t m_ui32Ssrc;
|
uint32_t m_ui32Ssrc;
|
||||||
uint32_t m_ui32SampleRate;
|
uint32_t m_ui32SampleRate;
|
||||||
@ -153,10 +147,9 @@ protected:
|
|||||||
uint8_t m_ui8Interleaved;
|
uint8_t m_ui8Interleaved;
|
||||||
uint16_t m_ui16Sequence = 0;
|
uint16_t m_ui16Sequence = 0;
|
||||||
uint32_t m_ui32TimeStamp = 0;
|
uint32_t m_ui32TimeStamp = 0;
|
||||||
ResourcePool<RtpPacket> m_rtpPool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RtpCodec : public RtpRing, public FrameRingInterfaceDelegate , public CodecInfo{
|
class RtpCodec : public RtpRing, public FrameRingInterfaceDelegate , public CodecInfo , public ResourcePoolHelper<RtpPacket>{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<RtpCodec> Ptr;
|
typedef std::shared_ptr<RtpCodec> Ptr;
|
||||||
RtpCodec(){}
|
RtpCodec(){}
|
||||||
|
@ -188,6 +188,11 @@ public:
|
|||||||
const static int channel[] = { 1, 2 };
|
const static int channel[] = { 1, 2 };
|
||||||
return channel[flvStereoOrMono];
|
return channel[flvStereoOrMono];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的sps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
string getH264SPS() const {
|
string getH264SPS() const {
|
||||||
string ret;
|
string ret;
|
||||||
if (getMediaType() != 7) {
|
if (getMediaType() != 7) {
|
||||||
@ -210,6 +215,11 @@ public:
|
|||||||
ret.assign(strBuf.data() + 13, sps_size);
|
ret.assign(strBuf.data() + 13, sps_size);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的pps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
string getH264PPS() const {
|
string getH264PPS() const {
|
||||||
string ret;
|
string ret;
|
||||||
if (getMediaType() != 7) {
|
if (getMediaType() != 7) {
|
||||||
@ -258,4 +268,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
206
src/RtmpCodec/H264RtmpCodec.cpp
Normal file
206
src/RtmpCodec/H264RtmpCodec.cpp
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
//
|
||||||
|
// Created by xzl on 2018/10/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "H264RtmpCodec.h"
|
||||||
|
|
||||||
|
|
||||||
|
H264RtmpDecoder::H264RtmpDecoder() {
|
||||||
|
m_h264frame = obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
H264Frame::Ptr H264RtmpDecoder::obtainFrame() {
|
||||||
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
|
auto frame = obtainObj();
|
||||||
|
frame->buffer.clear();
|
||||||
|
frame->iPrefixSize = 4;
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) {
|
||||||
|
key_pos = decodeRtmp(rtmp);
|
||||||
|
RtmpCodec::inputRtmp(rtmp, key_pos);
|
||||||
|
return key_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
|
||||||
|
if (pkt->isCfgFrame()) {
|
||||||
|
//缓存sps pps,后续插入到I帧之前
|
||||||
|
m_strSPS = pkt->getH264SPS();
|
||||||
|
m_strPPS = pkt->getH264PPS();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_strSPS.size()) {
|
||||||
|
uint32_t iTotalLen = pkt->strBuf.size();
|
||||||
|
uint32_t iOffset = 5;
|
||||||
|
while(iOffset + 4 < iTotalLen){
|
||||||
|
uint32_t iFrameLen;
|
||||||
|
memcpy(&iFrameLen, pkt->strBuf.data() + iOffset, 4);
|
||||||
|
iFrameLen = ntohl(iFrameLen);
|
||||||
|
iOffset += 4;
|
||||||
|
if(iFrameLen + iOffset > iTotalLen){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
onGetH264_l(pkt->strBuf.data() + iOffset, iFrameLen, pkt->timeStamp);
|
||||||
|
iOffset += iFrameLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkt->isVideoKeyFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
|
||||||
|
switch (pcData[0] & 0x1F) {
|
||||||
|
case 5: {
|
||||||
|
//I frame
|
||||||
|
onGetH264(m_strSPS.data(), m_strSPS.length(), ui32TimeStamp);
|
||||||
|
onGetH264(m_strPPS.data(), m_strPPS.length(), ui32TimeStamp);
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
//I or P or B frame
|
||||||
|
onGetH264(pcData, iLen, ui32TimeStamp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//WarnL <<(int)(pcData[0] & 0x1F);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void H264RtmpDecoder::onGetH264(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
|
||||||
|
m_h264frame->type = pcData[0] & 0x1F;
|
||||||
|
m_h264frame->timeStamp = ui32TimeStamp;
|
||||||
|
m_h264frame->buffer.assign("\x0\x0\x0\x1", 4); //添加264头
|
||||||
|
m_h264frame->buffer.append(pcData, iLen);
|
||||||
|
|
||||||
|
//写入环形缓存
|
||||||
|
RtmpCodec::inputFrame(m_h264frame);
|
||||||
|
m_h264frame = obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
H264RtmpEncoder::H264RtmpEncoder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
|
||||||
|
RtmpCodec::inputFrame(frame);
|
||||||
|
|
||||||
|
auto pcData = frame->data() + frame->prefixSize();
|
||||||
|
auto iLen = frame->size() - frame->prefixSize();
|
||||||
|
auto type = ((uint8_t*)pcData)[0] & 0x1F;
|
||||||
|
|
||||||
|
switch (type){
|
||||||
|
case 7:{
|
||||||
|
//sps
|
||||||
|
if(m_sps.empty()){
|
||||||
|
m_sps = string(pcData,iLen);
|
||||||
|
if(!m_pps.empty()){
|
||||||
|
makeVideoConfigPkt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:{
|
||||||
|
//pps
|
||||||
|
if(m_pps.empty()){
|
||||||
|
m_pps = string(pcData,iLen);
|
||||||
|
if(!m_sps.empty()){
|
||||||
|
makeVideoConfigPkt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 5:{
|
||||||
|
//I or P or B frame
|
||||||
|
int8_t flags = 7; //h.264
|
||||||
|
bool is_config = false;
|
||||||
|
bool keyFrame = frame->keyFrame();
|
||||||
|
flags |= ((keyFrame ? FLV_KEY_FRAME : FLV_INTER_FRAME) << 4);
|
||||||
|
|
||||||
|
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
|
||||||
|
rtmpPkt->strBuf.push_back(flags);
|
||||||
|
rtmpPkt->strBuf.push_back(!is_config);
|
||||||
|
rtmpPkt->strBuf.append("\x0\x0\x0", 3);
|
||||||
|
auto size = htonl(iLen);
|
||||||
|
rtmpPkt->strBuf.append((char *) &size, 4);
|
||||||
|
rtmpPkt->strBuf.append(pcData, iLen);
|
||||||
|
|
||||||
|
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
|
||||||
|
rtmpPkt->chunkId = CHUNK_VIDEO;
|
||||||
|
rtmpPkt->streamId = STREAM_MEDIA;
|
||||||
|
rtmpPkt->timeStamp = frame->stamp();
|
||||||
|
rtmpPkt->typeId = MSG_VIDEO;
|
||||||
|
RtmpCodec::inputRtmp(rtmpPkt,keyFrame);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void H264RtmpEncoder::makeVideoConfigPkt() {
|
||||||
|
int8_t flags = 7; //h.264
|
||||||
|
flags |= (FLV_KEY_FRAME << 4);
|
||||||
|
bool is_config = true;
|
||||||
|
|
||||||
|
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
|
||||||
|
//////////header
|
||||||
|
rtmpPkt->strBuf.push_back(flags);
|
||||||
|
rtmpPkt->strBuf.push_back(!is_config);
|
||||||
|
rtmpPkt->strBuf.append("\x0\x0\x0", 3);
|
||||||
|
|
||||||
|
////////////sps
|
||||||
|
rtmpPkt->strBuf.push_back(1); // version
|
||||||
|
|
||||||
|
//DebugL<<hexdump(m_sps.data(), m_sps.size());
|
||||||
|
rtmpPkt->strBuf.push_back(m_sps[1]); // profile
|
||||||
|
rtmpPkt->strBuf.push_back(m_sps[2]); // compat
|
||||||
|
rtmpPkt->strBuf.push_back(m_sps[3]); // level
|
||||||
|
rtmpPkt->strBuf.push_back(0xff); // 6 bits reserved + 2 bits nal size length - 1 (11)
|
||||||
|
rtmpPkt->strBuf.push_back(0xe1); // 3 bits reserved + 5 bits number of sps (00001)
|
||||||
|
uint16_t size = m_sps.size();
|
||||||
|
size = htons(size);
|
||||||
|
rtmpPkt->strBuf.append((char *) &size, 2);
|
||||||
|
rtmpPkt->strBuf.append(m_sps);
|
||||||
|
|
||||||
|
/////////////pps
|
||||||
|
rtmpPkt->strBuf.push_back(1); // version
|
||||||
|
size = m_pps.size();
|
||||||
|
size = htons(size);
|
||||||
|
rtmpPkt->strBuf.append((char *) &size, 2);
|
||||||
|
rtmpPkt->strBuf.append(m_pps);
|
||||||
|
|
||||||
|
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
|
||||||
|
rtmpPkt->chunkId = CHUNK_VIDEO;
|
||||||
|
rtmpPkt->streamId = STREAM_MEDIA;
|
||||||
|
rtmpPkt->timeStamp = 0;
|
||||||
|
rtmpPkt->typeId = MSG_VIDEO;
|
||||||
|
RtmpCodec::inputRtmp(rtmpPkt, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
70
src/RtmpCodec/H264RtmpCodec.h
Normal file
70
src/RtmpCodec/H264RtmpCodec.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// Created by xzl on 2018/10/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_H264RTMPCODEC_H
|
||||||
|
#define ZLMEDIAKIT_H264RTMPCODEC_H
|
||||||
|
|
||||||
|
#include "RtmpCodec.h"
|
||||||
|
#include "Util/ResourcePool.h"
|
||||||
|
|
||||||
|
using namespace ZL::Rtmp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* h264 Rtmp解码类
|
||||||
|
*/
|
||||||
|
class H264RtmpDecoder : public RtmpCodec ,public ResourcePoolHelper<H264Frame> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H264RtmpDecoder> Ptr;
|
||||||
|
|
||||||
|
H264RtmpDecoder();
|
||||||
|
~H264RtmpDecoder() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入264 Rtmp包
|
||||||
|
* @param rtmp Rtmp包
|
||||||
|
* @param key_pos 此参数忽略之
|
||||||
|
*/
|
||||||
|
bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos = true) override;
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool decodeRtmp(const RtmpPacket::Ptr &Rtmp);
|
||||||
|
void onGetH264_l(const char *pcData, int iLen, uint32_t ui32TimeStamp);
|
||||||
|
void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
|
||||||
|
H264Frame::Ptr obtainFrame();
|
||||||
|
private:
|
||||||
|
H264Frame::Ptr m_h264frame;
|
||||||
|
string m_strSPS;
|
||||||
|
string m_strPPS;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 264 Rtmp打包类
|
||||||
|
*/
|
||||||
|
class H264RtmpEncoder : public H264RtmpDecoder, public ResourcePoolHelper<RtmpPacket> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H264RtmpEncoder> Ptr;
|
||||||
|
|
||||||
|
H264RtmpEncoder();
|
||||||
|
~H264RtmpEncoder() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入264帧,需要指出的是,必须输入sps pps帧
|
||||||
|
* @param frame 帧数据
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
private:
|
||||||
|
void makeVideoConfigPkt();
|
||||||
|
private:
|
||||||
|
string m_sps;
|
||||||
|
string m_pps;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_H264RTMPCODEC_H
|
5
src/RtmpCodec/RtmpCodec.cpp
Normal file
5
src/RtmpCodec/RtmpCodec.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by xzl on 2018/10/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "RtmpCodec.h"
|
86
src/RtmpCodec/RtmpCodec.h
Normal file
86
src/RtmpCodec/RtmpCodec.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// Created by xzl on 2018/10/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_RTMPCODEC_H
|
||||||
|
#define ZLMEDIAKIT_RTMPCODEC_H
|
||||||
|
|
||||||
|
#include "Rtmp/Rtmp.h"
|
||||||
|
#include "Player/Frame.h"
|
||||||
|
#include "Util/RingBuffer.h"
|
||||||
|
|
||||||
|
using namespace ZL::Util;
|
||||||
|
|
||||||
|
namespace ZL{
|
||||||
|
namespace Rtmp {
|
||||||
|
|
||||||
|
|
||||||
|
class RtmpRingInterface {
|
||||||
|
public:
|
||||||
|
typedef RingBuffer<RtmpPacket::Ptr> RingType;
|
||||||
|
typedef std::shared_ptr<RtmpRingInterface> Ptr;
|
||||||
|
|
||||||
|
RtmpRingInterface(){}
|
||||||
|
virtual ~RtmpRingInterface(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取rtmp环形缓存
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual RingType::Ptr getRtmpRing() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置rtmp环形缓存
|
||||||
|
* @param ring
|
||||||
|
*/
|
||||||
|
virtual void setRtmpRing(const RingType::Ptr &ring) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入rtmp包
|
||||||
|
* @param rtmp rtmp包
|
||||||
|
* @param key_pos 是否为关键帧
|
||||||
|
* @return 是否为关键帧
|
||||||
|
*/
|
||||||
|
virtual bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RtmpRing : public RtmpRingInterface {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<RtmpRing> Ptr;
|
||||||
|
|
||||||
|
RtmpRing(){
|
||||||
|
_rtmpRing = std::make_shared<RingType>();
|
||||||
|
}
|
||||||
|
virtual ~RtmpRing(){}
|
||||||
|
|
||||||
|
RingType::Ptr getRtmpRing() const override {
|
||||||
|
return _rtmpRing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRtmpRing(const RingType::Ptr &ring) override {
|
||||||
|
_rtmpRing = ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) override{
|
||||||
|
_rtmpRing->write(rtmp,key_pos);
|
||||||
|
return key_pos;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
RingType::Ptr _rtmpRing;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RtmpCodec : public RtmpRing, public FrameRingInterfaceDelegate , public CodecInfo{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<RtmpCodec> Ptr;
|
||||||
|
RtmpCodec(){}
|
||||||
|
virtual ~RtmpCodec(){}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace Rtmp
|
||||||
|
}//namespace ZL
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_RTMPCODEC_H
|
Loading…
Reference in New Issue
Block a user