修复ts/ps解析后组帧逻辑bug:#964

This commit is contained in:
ziyue 2021-07-07 11:02:05 +08:00
parent 9f9b3a5a64
commit 59131e3b0a
3 changed files with 35 additions and 35 deletions

@ -1 +1 @@
Subproject commit d6c920e5282984c8554f1383a9b9bedb14bc523d Subproject commit 0c8b237287ebba9cd1ab75076c787eccb7e65be5

View File

@ -165,6 +165,7 @@ static size_t constexpr kMaxFrameCacheSize = 100;
bool FrameMerger::willFlush(const Frame::Ptr &frame) const{ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
if (_frameCached.empty()) { if (_frameCached.empty()) {
//缓存为空
return false; return false;
} }
switch (_type) { switch (_type) {
@ -186,8 +187,12 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
case mp4_nal_size: case mp4_nal_size:
case h264_prefix: { case h264_prefix: {
if (!frameCacheHasVCL()) {
//缓存中没有有效的能解码的帧所以这次不flush
return false;
}
if (_frameCached.back()->dts() != frame->dts()) { if (_frameCached.back()->dts() != frame->dts()) {
//时间戳变化了 //时间戳变化了,立即flush
return true; return true;
} }
switch (frame->getCodecId()) { switch (frame->getCodecId()) {
@ -221,10 +226,6 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con
break; break;
} }
case h264_prefix: { case h264_prefix: {
if (shouldDrop(frame)) {
//h264头模式过滤无效的帧
break;
}
if (frame->prefixSize()) { if (frame->prefixSize()) {
merged.append(frame->data(), frame->size()); merged.append(frame->data(), frame->size());
} else { } else {
@ -234,10 +235,6 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con
break; break;
} }
case mp4_nal_size: { case mp4_nal_size: {
if (shouldDrop(frame)) {
//MP4头模式过滤无效的帧
break;
}
uint32_t nalu_size = (uint32_t) (frame->size() - frame->prefixSize()); uint32_t nalu_size = (uint32_t) (frame->size() - frame->prefixSize());
nalu_size = htonl(nalu_size); nalu_size = htonl(nalu_size);
merged.append((char *) &nalu_size, 4); merged.append((char *) &nalu_size, 4);
@ -273,42 +270,36 @@ bool FrameMerger::shouldDrop(const Frame::Ptr &frame) const{
} }
} }
bool FrameMerger::frameCacheHasVCL(List<Frame::Ptr> &frameCached) const { bool FrameMerger::frameCacheHasVCL() const {
bool hasVCL = false; bool has_vcl = false;
bool isH264OrH265 = false; bool is_h264_or_h265 = false;
frameCached.for_each([&hasVCL, &isH264OrH265](const Frame::Ptr &frame) { _frameCached.for_each([&](const Frame::Ptr &frame) {
switch (frame->getCodecId()) { switch (frame->getCodecId()) {
case CodecH264: { case CodecH264: {
auto type = H264_TYPE(frame->data()[frame->prefixSize()]); auto type = H264_TYPE(frame->data()[frame->prefixSize()]);
if (type >= H264Frame::NAL_B_P && type <= H264Frame::NAL_IDR) {
//有编码数据 //有编码数据
hasVCL = true; has_vcl = type >= H264Frame::NAL_B_P && type <= H264Frame::NAL_IDR;
} is_h264_or_h265 = true;
isH264OrH265 = true;
break; break;
} }
case CodecH265: { case CodecH265: {
//如果是新的一帧,前面的缓存需要输出
auto type = H265_TYPE(frame->data()[frame->prefixSize()]); auto type = H265_TYPE(frame->data()[frame->prefixSize()]);
if (type >= H265Frame::NAL_TRAIL_R && type <= H265Frame::NAL_RSV_IRAP_VCL23) {
//有编码数据 //有编码数据
hasVCL = true; has_vcl = type >= H265Frame::NAL_TRAIL_R && type <= H265Frame::NAL_RSV_IRAP_VCL23;
} is_h264_or_h265 = true;
isH264OrH265 = true;
break; break;
} }
default: default: break;
break;
} }
}); });
if (isH264OrH265) { if (is_h264_or_h265) {
return hasVCL; return has_vcl;
} }
return true; return true;
} }
void FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb) { void FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb) {
if (willFlush(frame) && frameCacheHasVCL(_frameCached)) { if (willFlush(frame)) {
Frame::Ptr back = _frameCached.back(); Frame::Ptr back = _frameCached.back();
Buffer::Ptr merged_frame = back; Buffer::Ptr merged_frame = back;
bool have_idr = back->keyFrame(); bool have_idr = back->keyFrame();
@ -323,15 +314,24 @@ void FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb) {
have_idr = true; have_idr = true;
} }
}); });
if (merged.empty()) {
_frameCached.clear();
return;
}
merged_frame = std::make_shared<BufferOffset<BufferLikeString> >(std::move(merged)); merged_frame = std::make_shared<BufferOffset<BufferLikeString> >(std::move(merged));
} }
cb(back->dts(), back->pts(), merged_frame, have_idr); cb(back->dts(), back->pts(), merged_frame, have_idr);
_frameCached.clear(); _frameCached.clear();
} }
switch (_type) {
case h264_prefix:
case mp4_nal_size: {
//h264头和mp4头模式过滤无效的帧
if (shouldDrop(frame)) {
return;
}
break;
}
default: break;
}
_frameCached.emplace_back(Frame::getCacheAbleFrame(frame)); _frameCached.emplace_back(Frame::getCacheAbleFrame(frame));
} }

View File

@ -477,7 +477,7 @@ private:
bool willFlush(const Frame::Ptr &frame) const; bool willFlush(const Frame::Ptr &frame) const;
void doMerge(BufferLikeString &buffer, const Frame::Ptr &frame) const; void doMerge(BufferLikeString &buffer, const Frame::Ptr &frame) const;
bool shouldDrop(const Frame::Ptr &frame) const; bool shouldDrop(const Frame::Ptr &frame) const;
bool frameCacheHasVCL(List<Frame::Ptr> &frameCached) const; bool frameCacheHasVCL() const;
private: private:
int _type; int _type;