mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-04 18:17:34 +08:00
重新mp4录制
This commit is contained in:
@@ -79,6 +79,10 @@ public:
|
||||
bool keyFrame() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
unsigned int syncword = 0; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始
|
||||
unsigned int id; //1 bslbf MPEG 标示符, 设置为1
|
||||
@@ -127,6 +131,10 @@ public:
|
||||
bool keyFrame() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
return false;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -117,6 +117,12 @@ public:
|
||||
*/
|
||||
virtual bool keyFrame() const = 0;
|
||||
|
||||
/**
|
||||
* 是否为配置帧,譬如sps pps vps
|
||||
* @return
|
||||
*/
|
||||
virtual bool configFrame() const = 0;
|
||||
|
||||
/**
|
||||
* 是否可以缓存
|
||||
*/
|
||||
@@ -371,6 +377,7 @@ public:
|
||||
_trackType = frame->getTrackType();
|
||||
_codec = frame->getCodecId();
|
||||
_key = frame->keyFrame();
|
||||
_config = frame->configFrame();
|
||||
}
|
||||
|
||||
virtual ~FrameCacheAble() = default;
|
||||
@@ -394,12 +401,17 @@ public:
|
||||
bool keyFrame() const override{
|
||||
return _key;
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
return _config;
|
||||
}
|
||||
private:
|
||||
Frame::Ptr _frame;
|
||||
BufferRaw::Ptr _buffer;
|
||||
TrackType _trackType;
|
||||
CodecId _codec;
|
||||
bool _key;
|
||||
bool _config;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -82,6 +82,16 @@ public:
|
||||
bool keyFrame() const override {
|
||||
return H264_TYPE(buffer[iPrefixSize]) == H264Frame::NAL_IDR;
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
switch(H264_TYPE(buffer[iPrefixSize]) ){
|
||||
case H264Frame::NAL_SPS:
|
||||
case H264Frame::NAL_PPS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public:
|
||||
uint32_t timeStamp;
|
||||
uint32_t ptsStamp = 0;
|
||||
@@ -118,6 +128,16 @@ public:
|
||||
bool keyFrame() const override {
|
||||
return H264_TYPE(_ptr[_prefixSize]) == H264Frame::NAL_IDR;
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
switch(H264_TYPE(_ptr[_prefixSize])){
|
||||
case H264Frame::NAL_SPS:
|
||||
case H264Frame::NAL_PPS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,6 +86,10 @@ public:
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
uint32_t pts() const override {
|
||||
return ptsStamp ? ptsStamp : timeStamp;
|
||||
}
|
||||
|
||||
uint32_t prefixSize() const override {
|
||||
return iPrefixSize;
|
||||
}
|
||||
@@ -99,7 +103,18 @@ public:
|
||||
}
|
||||
|
||||
bool keyFrame() const override {
|
||||
return isKeyFrame(type);
|
||||
return isKeyFrame(H265_TYPE(buffer[iPrefixSize]));
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
switch(H265_TYPE(buffer[iPrefixSize])){
|
||||
case H265Frame::NAL_VPS:
|
||||
case H265Frame::NAL_SPS:
|
||||
case H265Frame::NAL_PPS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isKeyFrame(int type) {
|
||||
@@ -117,9 +132,8 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
uint16_t sequence;
|
||||
uint32_t timeStamp;
|
||||
unsigned char type;
|
||||
uint32_t ptsStamp = 0;
|
||||
string buffer;
|
||||
uint32_t iPrefixSize = 4;
|
||||
};
|
||||
@@ -146,8 +160,18 @@ public:
|
||||
}
|
||||
|
||||
bool keyFrame() const override {
|
||||
int type = H265_TYPE(((uint8_t *) _ptr)[_prefixSize]);
|
||||
return H265Frame::isKeyFrame(type);
|
||||
return H265Frame::isKeyFrame(H265_TYPE(((uint8_t *) _ptr)[_prefixSize]));
|
||||
}
|
||||
|
||||
bool configFrame() const override{
|
||||
switch(H265_TYPE(((uint8_t *) _ptr)[_prefixSize])){
|
||||
case H265Frame::NAL_VPS:
|
||||
case H265Frame::NAL_SPS:
|
||||
case H265Frame::NAL_PPS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -328,7 +352,6 @@ private:
|
||||
}
|
||||
if(!_vps.empty()){
|
||||
auto vpsFrame = std::make_shared<H265Frame>();
|
||||
vpsFrame->type = H265Frame::NAL_VPS;
|
||||
vpsFrame->iPrefixSize = 4;
|
||||
vpsFrame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||
vpsFrame->buffer.append(_vps);
|
||||
@@ -337,7 +360,6 @@ private:
|
||||
}
|
||||
if (!_sps.empty()) {
|
||||
auto spsFrame = std::make_shared<H265Frame>();
|
||||
spsFrame->type = H265Frame::NAL_SPS;
|
||||
spsFrame->iPrefixSize = 4;
|
||||
spsFrame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||
spsFrame->buffer.append(_sps);
|
||||
@@ -347,7 +369,6 @@ private:
|
||||
|
||||
if (!_pps.empty()) {
|
||||
auto ppsFrame = std::make_shared<H265Frame>();
|
||||
ppsFrame->type = H265Frame::NAL_PPS;
|
||||
ppsFrame->iPrefixSize = 4;
|
||||
ppsFrame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||
ppsFrame->buffer.append(_pps);
|
||||
|
||||
@@ -99,56 +99,56 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
|
||||
// fragmentation unit (FU)
|
||||
FU fu;
|
||||
MakeFU(frame[2], fu);
|
||||
if (fu.S == 1) {
|
||||
//FU-A start
|
||||
if (fu.S) {
|
||||
//该帧的第一个rtp包
|
||||
_h265frame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||
_h265frame->buffer.push_back(fu.type << 1);
|
||||
_h265frame->buffer.push_back(0x01);
|
||||
_h265frame->buffer.append((char *) frame + 3, length - 3);
|
||||
_h265frame->type = fu.type;
|
||||
_h265frame->timeStamp = rtppack->timeStamp;
|
||||
_h265frame->sequence = rtppack->sequence;
|
||||
//该函数return时,保存下当前sequence,以便下次对比seq是否连续
|
||||
_lastSeq = rtppack->sequence;
|
||||
return (_h265frame->keyFrame()); //i frame
|
||||
}
|
||||
|
||||
if (rtppack->sequence != (uint16_t) (_h265frame->sequence + 1)) {
|
||||
if (rtppack->sequence != _lastSeq + 1 && rtppack->sequence != 0) {
|
||||
//中间的或末尾的rtp包,其seq必须连续(如果回环了则判定为连续),否则说明rtp丢包,那么该帧不完整,必须得丢弃
|
||||
_h265frame->buffer.clear();
|
||||
WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << _h265frame->sequence;
|
||||
WarnL << "rtp sequence不连续: " << rtppack->sequence << " != " << _lastSeq << " + 1,该帧被废弃";
|
||||
return false;
|
||||
}
|
||||
_h265frame->sequence = rtppack->sequence;
|
||||
if (fu.E == 1) {
|
||||
//FU-A end
|
||||
|
||||
if (!fu.E) {
|
||||
//该帧的中间rtp包
|
||||
_h265frame->buffer.append((char *) frame + 3, length - 3);
|
||||
_h265frame->timeStamp = rtppack->timeStamp;
|
||||
auto isIDR = _h265frame->keyFrame();
|
||||
onGetH265(_h265frame);
|
||||
return isIDR;
|
||||
//该函数return时,保存下当前sequence,以便下次对比seq是否连续
|
||||
_lastSeq = rtppack->sequence;
|
||||
return false;
|
||||
}
|
||||
//FU-A mid
|
||||
|
||||
//该帧最后一个rtp包
|
||||
_h265frame->buffer.append((char *) frame + 3, length - 3);
|
||||
return false;
|
||||
_h265frame->timeStamp = rtppack->timeStamp;
|
||||
auto key = _h265frame->keyFrame();
|
||||
onGetH265(_h265frame);
|
||||
return key;
|
||||
}
|
||||
|
||||
default: // 4.4.1. Single NAL Unit Packets (p24)
|
||||
//a full frame
|
||||
_h265frame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||
_h265frame->buffer.append((char *)frame, length);
|
||||
_h265frame->type = nal;
|
||||
_h265frame->timeStamp = rtppack->timeStamp;
|
||||
_h265frame->sequence = rtppack->sequence;
|
||||
auto isIDR = _h265frame->keyFrame();
|
||||
auto key = _h265frame->keyFrame();
|
||||
onGetH265(_h265frame);
|
||||
return (isIDR); //i frame
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) {
|
||||
//写入环形缓存
|
||||
auto lastSeq = _h265frame->sequence;
|
||||
RtpCodec::inputFrame(frame);
|
||||
_h265frame = obtainFrame();
|
||||
_h265frame->sequence = lastSeq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ private:
|
||||
H265Frame::Ptr obtainFrame();
|
||||
private:
|
||||
H265Frame::Ptr _h265frame;
|
||||
int _lastSeq = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user