mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-29 22:55:52 +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.
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
@ -14,24 +14,24 @@
|
|||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
using namespace std;
|
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) {
|
if (sps_len < 4) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
T_GetBitContext tGetBitBuf;
|
T_GetBitContext tGetBitBuf;
|
||||||
T_SPS tH264SpsInfo;
|
T_SPS tH264SpsInfo;
|
||||||
memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
|
memset(&tGetBitBuf, 0, sizeof(tGetBitBuf));
|
||||||
memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo));
|
memset(&tH264SpsInfo, 0, sizeof(tH264SpsInfo));
|
||||||
tGetBitBuf.pu8Buf = (uint8_t*)sps + 1;
|
tGetBitBuf.pu8Buf = (uint8_t *)sps + 1;
|
||||||
tGetBitBuf.iBufSize = (int)(sps_len - 1);
|
tGetBitBuf.iBufSize = (int)(sps_len - 1);
|
||||||
if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){
|
if (0 != h264DecSeqParameterSet((void *)&tGetBitBuf, &tH264SpsInfo)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
|
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
|
||||||
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
|
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
|
||||||
//ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
|
// ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,8 @@ static const char *memfind(const char *buf, ssize_t len, const char *subbuf, ssi
|
|||||||
return NULL;
|
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 start = ptr + prefix;
|
||||||
auto end = ptr + len;
|
auto end = ptr + len;
|
||||||
size_t next_prefix;
|
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) {
|
if (len < 4) {
|
||||||
return 0;
|
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);
|
_sps = sps.substr(sps_prefix_len);
|
||||||
_pps = pps.substr(pps_prefix_len);
|
_pps = pps.substr(pps_prefix_len);
|
||||||
onReady();
|
onReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
H264Track::H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps){
|
H264Track::H264Track(const Frame::Ptr &sps, const Frame::Ptr &pps) {
|
||||||
if(sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264 ){
|
if (sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264) {
|
||||||
throw std::invalid_argument("必须输入H264类型的帧");
|
throw std::invalid_argument("必须输入H264类型的帧");
|
||||||
}
|
}
|
||||||
_sps = string(sps->data() + sps->prefixSize(),sps->size() - sps->prefixSize());
|
_sps = string(sps->data() + sps->prefixSize(), sps->size() - sps->prefixSize());
|
||||||
_pps = string(pps->data() + pps->prefixSize(),pps->size() - pps->prefixSize());
|
_pps = string(pps->data() + pps->prefixSize(), pps->size() - pps->prefixSize());
|
||||||
onReady();
|
onReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
const string &H264Track::getSps() const{
|
const string &H264Track::getSps() const {
|
||||||
return _sps;
|
return _sps;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string &H264Track::getPps() const{
|
const string &H264Track::getPps() const {
|
||||||
return _pps;
|
return _pps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) {
|
|||||||
//非I/B/P帧情况下,split一下,防止多个帧粘合在一起
|
//非I/B/P帧情况下,split一下,防止多个帧粘合在一起
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
splitH264(frame->data(), frame->size(), frame->prefixSize(), [&](const char *ptr, size_t len, size_t prefix) {
|
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)) {
|
if (inputFrame_l(sub_frame)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@ -163,7 +164,7 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void H264Track::onReady(){
|
void H264Track::onReady() {
|
||||||
if (!getAVCInfo(_sps, _width, _height, _fps)) {
|
if (!getAVCInfo(_sps, _width, _height, _fps)) {
|
||||||
_sps.clear();
|
_sps.clear();
|
||||||
_pps.clear();
|
_pps.clear();
|
||||||
@ -171,33 +172,39 @@ void H264Track::onReady(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Track::Ptr H264Track::clone() {
|
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){
|
bool H264Track::inputFrame_l(const Frame::Ptr &frame) {
|
||||||
int type = H264_TYPE( frame->data()[frame->prefixSize()]);
|
int type = H264_TYPE(frame->data()[frame->prefixSize()]);
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case H264Frame::NAL_SPS: {
|
case H264Frame::NAL_SPS: {
|
||||||
_sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
_sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
break;
|
_latest_is_config_frame = true;
|
||||||
}
|
ret = VideoTrack::inputFrame(frame);
|
||||||
case H264Frame::NAL_PPS: {
|
break;
|
||||||
_pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
}
|
||||||
_insert_config_frame = true;
|
case H264Frame::NAL_PPS: {
|
||||||
break;
|
_pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
}
|
_latest_is_config_frame = true;
|
||||||
|
ret = VideoTrack::inputFrame(frame);
|
||||||
default:
|
break;
|
||||||
if (_insert_config_frame && !frame->dropAble()) {
|
}
|
||||||
if (!frame->keyFrame()) {
|
default:
|
||||||
const_cast<Frame::Ptr &>(frame) = std::make_shared<FrameCacheAble>(frame, true);
|
// 避免识别不出关键帧
|
||||||
}
|
if (_latest_is_config_frame && !frame->dropAble()) {
|
||||||
insertConfigFrame(frame);
|
if (!frame->keyFrame()) {
|
||||||
_insert_config_frame = false;
|
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()) {
|
if (_width == 0 && ready()) {
|
||||||
@ -206,20 +213,20 @@ bool H264Track::inputFrame_l(const Frame::Ptr &frame){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void H264Track::insertConfigFrame(const Frame::Ptr &frame){
|
void H264Track::insertConfigFrame(const Frame::Ptr &frame) {
|
||||||
if(!_sps.empty()){
|
if (!_sps.empty()) {
|
||||||
auto spsFrame = FrameImp::create<H264Frame>();
|
auto spsFrame = FrameImp::create<H264Frame>();
|
||||||
spsFrame->_prefix_size = 4;
|
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->_buffer.append(_sps);
|
||||||
spsFrame->_dts = frame->dts();
|
spsFrame->_dts = frame->dts();
|
||||||
VideoTrack::inputFrame(spsFrame);
|
VideoTrack::inputFrame(spsFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_pps.empty()){
|
if (!_pps.empty()) {
|
||||||
auto ppsFrame = FrameImp::create<H264Frame>();
|
auto ppsFrame = FrameImp::create<H264Frame>();
|
||||||
ppsFrame->_prefix_size = 4;
|
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->_buffer.append(_pps);
|
||||||
ppsFrame->_dts = frame->dts();
|
ppsFrame->_dts = frame->dts();
|
||||||
VideoTrack::inputFrame(ppsFrame);
|
VideoTrack::inputFrame(ppsFrame);
|
||||||
@ -250,34 +257,28 @@ public:
|
|||||||
_printer << strTemp;
|
_printer << strTemp;
|
||||||
_printer << "; sprop-parameter-sets=";
|
_printer << "; sprop-parameter-sets=";
|
||||||
memset(strTemp, 0, sizeof(strTemp));
|
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 << ",";
|
_printer << strTemp << ",";
|
||||||
memset(strTemp, 0, sizeof(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 << strTemp << "\r\n";
|
||||||
_printer << "a=control:trackID=" << (int) TrackVideo << "\r\n";
|
_printer << "a=control:trackID=" << (int)TrackVideo << "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
string getSdp() const {
|
string getSdp() const { return _printer; }
|
||||||
return _printer;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecId getCodecId() const {
|
CodecId getCodecId() const { return CodecH264; }
|
||||||
return CodecH264;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_StrPrinter _printer;
|
_StrPrinter _printer;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sdp::Ptr H264Track::getSdp() {
|
Sdp::Ptr H264Track::getSdp() {
|
||||||
if(!ready()){
|
if (!ready()) {
|
||||||
WarnL << getCodecName() << " Track未准备好";
|
WarnL << getCodecName() << " Track未准备好";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return std::make_shared<H264Sdp>(getSps(), getPps(), getBitRate() / 1024);
|
return std::make_shared<H264Sdp>(getSps(), getPps(), getBitRate() / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
} // namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user