重新mp4录制

This commit is contained in:
xiongziliang
2019-08-01 18:49:04 +08:00
parent 12e1068a39
commit 383a14a76d
14 changed files with 470 additions and 417 deletions

View File

@@ -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;
}
} ;

View File

@@ -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;
};

View File

@@ -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;
}
}
};
/**

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -65,6 +65,7 @@ private:
H265Frame::Ptr obtainFrame();
private:
H265Frame::Ptr _h265frame;
int _lastSeq = 0;
};
/**