修复split 264/265相关逻辑的bug

This commit is contained in:
xiongziliang 2020-04-30 10:00:55 +08:00
parent 1067c5a2d3
commit b649372873
3 changed files with 50 additions and 59 deletions

View File

@ -44,20 +44,32 @@ const char *memfind(const char *buf, int len, const char *subbuf, int sublen) {
return NULL; return NULL;
} }
void splitH264(const char *ptr, int len, const std::function<void(const char *, int)> &cb) { void splitH264(const char *ptr, int len, int prefix, const std::function<void(const char *, int, int)> &cb) {
auto nal = ptr; auto start = ptr + prefix;
auto end = ptr + len; auto end = ptr + len;
while(true) { int next_prefix;
auto next_nal = memfind(nal + 3,end - nal - 3,"\x0\x0\x1",3); while (true) {
if(next_nal){ auto next_start = memfind(start, end - start, "\x00\x00\x01", 3);
if(*(next_nal - 1) == 0x00){ if (next_start) {
next_nal -= 1; //找到下一帧
if (*(next_start - 1) == 0x00) {
//这个是00 00 00 01开头
next_start -= 1;
next_prefix = 4;
} else {
//这个是00 00 01开头
next_prefix = 3;
} }
cb(nal,next_nal - nal); //记得加上本帧prefix长度
nal = next_nal; cb(start - prefix, next_start - start + prefix, prefix);
//搜索下一帧末尾的起始位置
start = next_start + next_prefix;
//记录下一帧的prefix长度
prefix = next_prefix;
continue; continue;
} }
cb(nal,end - nal); //未找到下一帧,这是最后一帧
cb(start - prefix, end - start + prefix, prefix);
break; break;
} }
} }
@ -65,13 +77,22 @@ void splitH264(const char *ptr, int len, const std::function<void(const char *,
#if 0 #if 0
//splitH264函数测试程序 //splitH264函数测试程序
static onceToken s_token([](){ static onceToken s_token([](){
{
char buf[] = "\x00\x00\x00\x01\x12\x23\x34\x45\x56" char buf[] = "\x00\x00\x00\x01\x12\x23\x34\x45\x56"
"\x00\x00\x00\x01\x12\x23\x34\x45\x56" "\x00\x00\x00\x01\x23\x34\x45\x56"
"\x00\x00\x00\x01\x12\x23\x34\x45\x56" "\x00\x00\x00\x01x34\x45\x56"
"\x00\x00\x01\x12\x23\x34\x45\x56"; "\x00\x00\x01\x12\x23\x34\x45\x56";
splitH264(buf, sizeof(buf) - 1, [](const char *ptr, int len){ splitH264(buf, sizeof(buf) - 1, 4, [](const char *ptr, int len, int prefix) {
cout << hexdump(ptr, len) << endl; cout << prefix << " " << hexdump(ptr, len) << endl;
}); });
}
{
char buf[] = "\x00\x00\x00\x01\x12\x23\x34\x45\x56";
splitH264(buf, sizeof(buf) - 1, 4, [](const char *ptr, int len, int prefix) {
cout << prefix << " " << hexdump(ptr, len) << endl;
});
}
}); });
#endif //0 #endif //0

View File

@ -20,7 +20,7 @@ using namespace toolkit;
namespace mediakit{ namespace mediakit{
bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
void splitH264(const char *ptr, int len, const std::function<void(const char *, int)> &cb); void splitH264(const char *ptr, int len, int prefix, const std::function<void(const char *, int, int)> &cb);
/** /**
* 264 * 264
@ -243,24 +243,9 @@ public:
int type = H264_TYPE(*((uint8_t *)frame->data() + frame->prefixSize())); int type = H264_TYPE(*((uint8_t *)frame->data() + frame->prefixSize()));
if(type == H264Frame::NAL_SPS || type == H264Frame::NAL_SEI){ if(type == H264Frame::NAL_SPS || type == H264Frame::NAL_SEI){
//有些设备会把SPS PPS IDR帧当做一个帧打包所以我们要split一下 //有些设备会把SPS PPS IDR帧当做一个帧打包所以我们要split一下
bool first_frame = true; splitH264(frame->data(), frame->size(), frame->prefixSize(), [&](const char *ptr, int len, int prefix) {
splitH264(frame->data() + frame->prefixSize(), H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame, (char *)ptr, len, prefix);
frame->size() - frame->prefixSize(),
[&](const char *ptr, int len){
if(first_frame){
H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame,
frame->data(),
len + frame->prefixSize(),
frame->prefixSize());
inputFrame_l(sub_frame); inputFrame_l(sub_frame);
first_frame = false;
}else{
H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame,
(char *)ptr,
len ,
3);
inputFrame_l(sub_frame);
}
}); });
} else{ } else{
inputFrame_l(frame); inputFrame_l(frame);

View File

@ -246,26 +246,11 @@ public:
void inputFrame(const Frame::Ptr &frame) override{ void inputFrame(const Frame::Ptr &frame) override{
int type = H265_TYPE(*((uint8_t *)frame->data() + frame->prefixSize())); int type = H265_TYPE(*((uint8_t *)frame->data() + frame->prefixSize()));
if(frame->configFrame()){ if(frame->configFrame()){
bool first_frame = true; splitH264(frame->data(), frame->size(), frame->prefixSize(), [&](const char *ptr, int len, int prefix){
splitH264(frame->data() + frame->prefixSize(), H265FrameInternal::Ptr sub_frame = std::make_shared<H265FrameInternal>(frame, (char*)ptr, len, prefix);
frame->size() - frame->prefixSize(),
[&](const char *ptr, int len){
if(first_frame){
H265FrameInternal::Ptr sub_frame = std::make_shared<H265FrameInternal>(frame,
frame->data(),
len + frame->prefixSize(),
frame->prefixSize());
inputFrame_l(sub_frame); inputFrame_l(sub_frame);
first_frame = false;
}else{
H265FrameInternal::Ptr sub_frame = std::make_shared<H265FrameInternal>(frame,
(char *)ptr,
len ,
3);
inputFrame_l(sub_frame);
}
}); });
}else{ } else {
inputFrame_l(frame); inputFrame_l(frame);
} }
} }