mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-15 20:45:57 +08:00
统一帧合并逻辑
This commit is contained in:
@@ -140,4 +140,102 @@ const char *CodecInfo::getCodecName() {
|
||||
TrackType CodecInfo::getTrackType() {
|
||||
return mediakit::getTrackType(getCodecId());
|
||||
}
|
||||
|
||||
static size_t constexpr kMaxFrameCacheSize = 100;
|
||||
|
||||
bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
|
||||
if (_frameCached.empty()) {
|
||||
return false;
|
||||
}
|
||||
switch (_type) {
|
||||
case none : {
|
||||
//frame不是完整的帧,我们合并为一帧
|
||||
bool new_frame = false;
|
||||
switch (frame->getCodecId()) {
|
||||
case CodecH264:
|
||||
case CodecH265: {
|
||||
//如果是新的一帧,前面的缓存需要输出
|
||||
new_frame = frame->prefixSize();
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return new_frame || _frameCached.back()->dts() != frame->dts() || _frameCached.size() > kMaxFrameCacheSize;
|
||||
}
|
||||
|
||||
case mp4_nal_size:
|
||||
case h264_prefix: {
|
||||
if (_frameCached.back()->dts() != frame->dts()) {
|
||||
//时间戳变化了
|
||||
return true;
|
||||
}
|
||||
if (frame->getCodecId() == CodecH264 &&
|
||||
H264_TYPE(frame->data()[frame->prefixSize()]) == H264Frame::NAL_B_P) {
|
||||
//如果是264的b/p帧,那么也刷新输出
|
||||
return true;
|
||||
}
|
||||
return _frameCached.size() > kMaxFrameCacheSize;
|
||||
}
|
||||
default: /*不可达*/ assert(0); return true;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) const{
|
||||
switch (_type) {
|
||||
case none : {
|
||||
merged.append(frame->data(), frame->size());
|
||||
break;
|
||||
}
|
||||
case h264_prefix: {
|
||||
if (frame->prefixSize()) {
|
||||
merged.append(frame->data(), frame->size());
|
||||
} else {
|
||||
merged.append("\x00\x00\x00\x01", 4);
|
||||
merged.append(frame->data(), frame->size());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case mp4_nal_size: {
|
||||
uint32_t nalu_size = (uint32_t) (frame->size() - frame->prefixSize());
|
||||
nalu_size = htonl(nalu_size);
|
||||
merged.append((char *) &nalu_size, 4);
|
||||
merged.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||
break;
|
||||
}
|
||||
default: /*不可达*/ assert(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb) {
|
||||
if (willFlush(frame)) {
|
||||
Frame::Ptr back = _frameCached.back();
|
||||
Buffer::Ptr merged_frame = back;
|
||||
bool have_idr = back->keyFrame();
|
||||
|
||||
if (_frameCached.size() != 1 || _type == mp4_nal_size) {
|
||||
//在MP4模式下,一帧数据也需要在前添加nalu_size
|
||||
BufferLikeString merged;
|
||||
merged.reserve(back->size() + 1024);
|
||||
_frameCached.for_each([&](const Frame::Ptr &frame) {
|
||||
doMerge(merged, frame);
|
||||
if (frame->keyFrame()) {
|
||||
have_idr = true;
|
||||
}
|
||||
});
|
||||
merged_frame = std::make_shared<BufferOffset<BufferLikeString> >(std::move(merged));
|
||||
}
|
||||
cb(back->dts(), back->pts(), merged_frame, have_idr);
|
||||
_frameCached.clear();
|
||||
}
|
||||
_frameCached.emplace_back(Frame::getCacheAbleFrame(frame));
|
||||
}
|
||||
|
||||
FrameMerger::FrameMerger(int type) {
|
||||
_type = type;
|
||||
}
|
||||
|
||||
void FrameMerger::clear() {
|
||||
_frameCached.clear();
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
Reference in New Issue
Block a user