mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
解决多pps问题
解决某些流因为多pps而导致不能播放的问题.
This commit is contained in:
parent
08de795220
commit
f128b35b18
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||
@ -14,24 +14,24 @@
|
||||
using namespace toolkit;
|
||||
using namespace std;
|
||||
|
||||
namespace mediakit{
|
||||
namespace mediakit {
|
||||
|
||||
static bool getAVCInfo(const char *sps, size_t sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){
|
||||
static bool getAVCInfo(const char *sps, size_t sps_len, int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
|
||||
if (sps_len < 4) {
|
||||
return false;
|
||||
}
|
||||
T_GetBitContext tGetBitBuf;
|
||||
T_SPS tH264SpsInfo;
|
||||
memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
|
||||
memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo));
|
||||
tGetBitBuf.pu8Buf = (uint8_t*)sps + 1;
|
||||
memset(&tGetBitBuf, 0, sizeof(tGetBitBuf));
|
||||
memset(&tH264SpsInfo, 0, sizeof(tH264SpsInfo));
|
||||
tGetBitBuf.pu8Buf = (uint8_t *)sps + 1;
|
||||
tGetBitBuf.iBufSize = (int)(sps_len - 1);
|
||||
if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){
|
||||
if (0 != h264DecSeqParameterSet((void *)&tGetBitBuf, &tH264SpsInfo)) {
|
||||
return false;
|
||||
}
|
||||
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
|
||||
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
|
||||
//ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
|
||||
// ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -48,7 +48,8 @@ static const char *memfind(const char *buf, ssize_t len, const char *subbuf, ssi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void splitH264(const char *ptr, size_t len, size_t prefix, const std::function<void(const char *, size_t , size_t)> &cb) {
|
||||
void splitH264(
|
||||
const char *ptr, size_t len, size_t prefix, const std::function<void(const char *, size_t, size_t)> &cb) {
|
||||
auto start = ptr + prefix;
|
||||
auto end = ptr + len;
|
||||
size_t next_prefix;
|
||||
@ -78,7 +79,7 @@ void splitH264(const char *ptr, size_t len, size_t prefix, const std::function<v
|
||||
}
|
||||
}
|
||||
|
||||
size_t prefixSize(const char *ptr, size_t len){
|
||||
size_t prefixSize(const char *ptr, size_t len) {
|
||||
if (len < 4) {
|
||||
return 0;
|
||||
}
|
||||
@ -102,26 +103,26 @@ size_t prefixSize(const char *ptr, size_t len){
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
H264Track::H264Track(const string &sps,const string &pps,int sps_prefix_len,int pps_prefix_len){
|
||||
H264Track::H264Track(const string &sps, const string &pps, int sps_prefix_len, int pps_prefix_len) {
|
||||
_sps = sps.substr(sps_prefix_len);
|
||||
_pps = pps.substr(pps_prefix_len);
|
||||
onReady();
|
||||
}
|
||||
|
||||
H264Track::H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps){
|
||||
if(sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264 ){
|
||||
H264Track::H264Track(const Frame::Ptr &sps, const Frame::Ptr &pps) {
|
||||
if (sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264) {
|
||||
throw std::invalid_argument("必须输入H264类型的帧");
|
||||
}
|
||||
_sps = string(sps->data() + sps->prefixSize(),sps->size() - sps->prefixSize());
|
||||
_pps = string(pps->data() + pps->prefixSize(),pps->size() - pps->prefixSize());
|
||||
_sps = string(sps->data() + sps->prefixSize(), sps->size() - sps->prefixSize());
|
||||
_pps = string(pps->data() + pps->prefixSize(), pps->size() - pps->prefixSize());
|
||||
onReady();
|
||||
}
|
||||
|
||||
const string &H264Track::getSps() const{
|
||||
const string &H264Track::getSps() const {
|
||||
return _sps;
|
||||
}
|
||||
|
||||
const string &H264Track::getPps() const{
|
||||
const string &H264Track::getPps() const {
|
||||
return _pps;
|
||||
}
|
||||
|
||||
@ -155,7 +156,7 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) {
|
||||
//非I/B/P帧情况下,split一下,防止多个帧粘合在一起
|
||||
bool ret = false;
|
||||
splitH264(frame->data(), frame->size(), frame->prefixSize(), [&](const char *ptr, size_t len, size_t prefix) {
|
||||
H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame, (char *) ptr, len, prefix);
|
||||
H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame, (char *)ptr, len, prefix);
|
||||
if (inputFrame_l(sub_frame)) {
|
||||
ret = true;
|
||||
}
|
||||
@ -163,7 +164,7 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void H264Track::onReady(){
|
||||
void H264Track::onReady() {
|
||||
if (!getAVCInfo(_sps, _width, _height, _fps)) {
|
||||
_sps.clear();
|
||||
_pps.clear();
|
||||
@ -171,33 +172,39 @@ void H264Track::onReady(){
|
||||
}
|
||||
|
||||
Track::Ptr H264Track::clone() {
|
||||
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
|
||||
return std::make_shared<std::remove_reference<decltype(*this)>::type>(*this);
|
||||
}
|
||||
|
||||
bool H264Track::inputFrame_l(const Frame::Ptr &frame){
|
||||
int type = H264_TYPE( frame->data()[frame->prefixSize()]);
|
||||
bool H264Track::inputFrame_l(const Frame::Ptr &frame) {
|
||||
int type = H264_TYPE(frame->data()[frame->prefixSize()]);
|
||||
bool ret = true;
|
||||
switch (type) {
|
||||
case H264Frame::NAL_SPS: {
|
||||
_sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||
break;
|
||||
}
|
||||
case H264Frame::NAL_PPS: {
|
||||
_pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||
_insert_config_frame = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (_insert_config_frame && !frame->dropAble()) {
|
||||
if (!frame->keyFrame()) {
|
||||
const_cast<Frame::Ptr &>(frame) = std::make_shared<FrameCacheAble>(frame, true);
|
||||
}
|
||||
insertConfigFrame(frame);
|
||||
_insert_config_frame = false;
|
||||
case H264Frame::NAL_SPS: {
|
||||
_sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||
_latest_is_config_frame = true;
|
||||
ret = VideoTrack::inputFrame(frame);
|
||||
break;
|
||||
}
|
||||
case H264Frame::NAL_PPS: {
|
||||
_pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||
_latest_is_config_frame = true;
|
||||
ret = VideoTrack::inputFrame(frame);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// 避免识别不出关键帧
|
||||
if (_latest_is_config_frame && !frame->dropAble()) {
|
||||
if (!frame->keyFrame()) {
|
||||
const_cast<Frame::Ptr &>(frame) = std::make_shared<FrameCacheAble>(frame, true);
|
||||
}
|
||||
ret = VideoTrack::inputFrame(frame);
|
||||
break;
|
||||
}
|
||||
// 判断是否是I帧, 并且如果是,那判断前面是否插入过config帧, 如果插入过就不插入了
|
||||
if (frame->keyFrame() && !_latest_is_config_frame) {
|
||||
insertConfigFrame(frame);
|
||||
}
|
||||
_latest_is_config_frame = false;
|
||||
ret = VideoTrack::inputFrame(frame);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_width == 0 && ready()) {
|
||||
@ -206,20 +213,20 @@ bool H264Track::inputFrame_l(const Frame::Ptr &frame){
|
||||
return ret;
|
||||
}
|
||||
|
||||
void H264Track::insertConfigFrame(const Frame::Ptr &frame){
|
||||
if(!_sps.empty()){
|
||||
void H264Track::insertConfigFrame(const Frame::Ptr &frame) {
|
||||
if (!_sps.empty()) {
|
||||
auto spsFrame = FrameImp::create<H264Frame>();
|
||||
spsFrame->_prefix_size = 4;
|
||||
spsFrame->_buffer.assign("\x00\x00\x00\x01",4);
|
||||
spsFrame->_buffer.assign("\x00\x00\x00\x01", 4);
|
||||
spsFrame->_buffer.append(_sps);
|
||||
spsFrame->_dts = frame->dts();
|
||||
VideoTrack::inputFrame(spsFrame);
|
||||
}
|
||||
|
||||
if(!_pps.empty()){
|
||||
if (!_pps.empty()) {
|
||||
auto ppsFrame = FrameImp::create<H264Frame>();
|
||||
ppsFrame->_prefix_size = 4;
|
||||
ppsFrame->_buffer.assign("\x00\x00\x00\x01",4);
|
||||
ppsFrame->_buffer.assign("\x00\x00\x00\x01", 4);
|
||||
ppsFrame->_buffer.append(_pps);
|
||||
ppsFrame->_dts = frame->dts();
|
||||
VideoTrack::inputFrame(ppsFrame);
|
||||
@ -250,34 +257,28 @@ public:
|
||||
_printer << strTemp;
|
||||
_printer << "; sprop-parameter-sets=";
|
||||
memset(strTemp, 0, sizeof(strTemp));
|
||||
av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *) strSPS.data(), (int) strSPS.size());
|
||||
av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *)strSPS.data(), (int)strSPS.size());
|
||||
_printer << strTemp << ",";
|
||||
memset(strTemp, 0, sizeof(strTemp));
|
||||
av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *) strPPS.data(), (int) strPPS.size());
|
||||
av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *)strPPS.data(), (int)strPPS.size());
|
||||
_printer << strTemp << "\r\n";
|
||||
_printer << "a=control:trackID=" << (int) TrackVideo << "\r\n";
|
||||
_printer << "a=control:trackID=" << (int)TrackVideo << "\r\n";
|
||||
}
|
||||
|
||||
string getSdp() const {
|
||||
return _printer;
|
||||
}
|
||||
string getSdp() const { return _printer; }
|
||||
|
||||
CodecId getCodecId() const {
|
||||
return CodecH264;
|
||||
}
|
||||
CodecId getCodecId() const { return CodecH264; }
|
||||
|
||||
private:
|
||||
_StrPrinter _printer;
|
||||
};
|
||||
|
||||
Sdp::Ptr H264Track::getSdp() {
|
||||
if(!ready()){
|
||||
if (!ready()) {
|
||||
WarnL << getCodecName() << " Track未准备好";
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<H264Sdp>(getSps(), getPps(), getBitRate() / 1024);
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
|
||||
} // namespace mediakit
|
||||
|
Loading…
Reference in New Issue
Block a user