mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
支持pts/dts
This commit is contained in:
parent
68da7c2fb7
commit
a12ed95aa4
@ -63,7 +63,7 @@ public:
|
||||
uint32_t size() const override {
|
||||
return aac_frame_length;
|
||||
}
|
||||
uint32_t stamp() const override {
|
||||
uint32_t dts() const override {
|
||||
return timeStamp;
|
||||
}
|
||||
uint32_t prefixSize() const override{
|
||||
|
@ -82,9 +82,28 @@ public:
|
||||
typedef std::shared_ptr<Frame> Ptr;
|
||||
virtual ~Frame(){}
|
||||
/**
|
||||
* 时间戳
|
||||
* 时间戳,已经废弃,请使用dts() 、pts()接口
|
||||
*/
|
||||
virtual uint32_t stamp() const = 0;
|
||||
inline uint32_t stamp() const {
|
||||
return dts();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 返回解码时间戳,单位毫秒
|
||||
* @return
|
||||
*/
|
||||
virtual uint32_t dts() const = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 返回显示时间戳,单位毫秒
|
||||
* @return
|
||||
*/
|
||||
virtual uint32_t pts() const {
|
||||
return dts();
|
||||
}
|
||||
|
||||
/**
|
||||
* 前缀长度,譬如264前缀为0x00 00 00 01,那么前缀长度就是4
|
||||
@ -271,7 +290,7 @@ public:
|
||||
uint32_t size() const override {
|
||||
return buffer_size;
|
||||
}
|
||||
uint32_t stamp() const override {
|
||||
uint32_t dts() const override {
|
||||
return timeStamp;
|
||||
}
|
||||
uint32_t prefixSize() const override{
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
uint32_t size() const override {
|
||||
return buffer.size();
|
||||
}
|
||||
uint32_t stamp() const override {
|
||||
uint32_t dts() const override {
|
||||
return timeStamp;
|
||||
}
|
||||
uint32_t prefixSize() const override{
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
uint32_t stamp() const override {
|
||||
uint32_t dts() const override {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
|
@ -132,17 +132,18 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
|
||||
return true;
|
||||
}
|
||||
|
||||
void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp) {
|
||||
void HLSMaker::inputH264(const Frame::Ptr &frame) {
|
||||
auto dts = frame->dts();
|
||||
if(_ui32LastStamp == 0){
|
||||
_ui32LastStamp = timeStamp;
|
||||
_ui32LastStamp = dts;
|
||||
}
|
||||
int stampInc = timeStamp - _ui32LastStamp;
|
||||
auto type = H264_TYPE(((uint8_t*)data)[4]);
|
||||
int stampInc = dts - _ui32LastStamp;
|
||||
auto type = H264_TYPE(((uint8_t*)(frame->data() + frame->prefixSize()))[0]);
|
||||
|
||||
switch (type) {
|
||||
case H264Frame::NAL_SPS: //SPS
|
||||
if (stampInc >= _ui32SegmentDuration * 1000) {
|
||||
_ui32LastStamp = timeStamp;
|
||||
_ui32LastStamp = dts;
|
||||
//关闭文件
|
||||
_ts.clear();
|
||||
auto strTmpFileName = StrPrinter << _strOutputPrefix << '-' << (++_ui64TsCnt) << ".ts" << endl;
|
||||
@ -160,22 +161,22 @@ void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp) {
|
||||
}
|
||||
case H264Frame::NAL_B_P: //P
|
||||
//insert aud frame before p and SPS frame
|
||||
if(timeStamp != _ui32LastFrameStamp){
|
||||
_ts.inputH264("\x0\x0\x0\x1\x9\xf0", 6, timeStamp * 90);
|
||||
if(dts != _ui32LastFrameStamp){
|
||||
_ts.inputH264("\x0\x0\x0\x1\x9\xf0", 6, dts * 90L , frame->pts() * 90L);
|
||||
}
|
||||
case H264Frame::NAL_IDR: //IDR
|
||||
case H264Frame::NAL_PPS: //PPS
|
||||
_ts.inputH264((char *) data, length, timeStamp * 90);
|
||||
_ts.inputH264(frame->data(), frame->size(), dts * 90L , frame->pts() * 90L);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_ui32LastFrameStamp = timeStamp;
|
||||
_ui32LastFrameStamp = dts;
|
||||
}
|
||||
|
||||
void HLSMaker::inputAAC(void *data, uint32_t length, uint32_t timeStamp) {
|
||||
_ts.inputAAC((char *) data, length, timeStamp * 90);
|
||||
void HLSMaker::inputAAC(const Frame::Ptr &frame) {
|
||||
_ts.inputAAC(frame->data(), frame->size(), frame->dts() * 90L , frame->pts() * 90L);
|
||||
}
|
||||
|
||||
bool HLSMaker::removets() {
|
||||
@ -192,7 +193,7 @@ void HLSMaker::onTrackFrame(const Frame::Ptr &frame) {
|
||||
switch (frame->getCodecId()){
|
||||
case CodecH264:{
|
||||
if( frame->prefixSize() != 0){
|
||||
inputH264(frame->data(), frame->size(),frame->stamp());
|
||||
inputH264(frame);
|
||||
}else{
|
||||
WarnL << "h264必须要有头4个或3个字节的前缀";
|
||||
}
|
||||
@ -200,7 +201,7 @@ void HLSMaker::onTrackFrame(const Frame::Ptr &frame) {
|
||||
break;
|
||||
case CodecAAC:{
|
||||
if( frame->prefixSize() == 7) {
|
||||
inputAAC(frame->data(), frame->size(), frame->stamp());
|
||||
inputAAC(frame);
|
||||
}else{
|
||||
WarnL << "adts必须要有头7个字节的adts头";
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "Util/logger.h"
|
||||
#include "Common/config.h"
|
||||
#include "Common/MediaSink.h"
|
||||
#include "Extension/Frame.h"
|
||||
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
@ -55,15 +57,8 @@ protected:
|
||||
*/
|
||||
void onTrackFrame(const Frame::Ptr &frame) override ;
|
||||
private:
|
||||
//时间戳:参考频率1000
|
||||
void inputH264(void *pData,
|
||||
uint32_t ui32Length,
|
||||
uint32_t ui32TimeStamp);
|
||||
|
||||
//时间戳:参考频率1000
|
||||
void inputAAC(void *pData,
|
||||
uint32_t ui32Length,
|
||||
uint32_t ui32TimeStamp);
|
||||
void inputH264(const Frame::Ptr &frame);
|
||||
void inputAAC(const Frame::Ptr &frame);
|
||||
|
||||
bool write_index_file(int iFirstSegment,
|
||||
unsigned int uiLastSegment,
|
||||
|
@ -278,7 +278,7 @@ void TSMaker::TsHeader2buffer(TsPacketHeader* pTsHeader, unsigned char* pucBuffe
|
||||
|
||||
}
|
||||
|
||||
void TSMaker::WriteAdaptive_flags_Head( Ts_Adaptation_field * pTsAdaptationField, uint64_t ui64VideoPts) {
|
||||
void TSMaker::WriteAdaptive_flags_Head( Ts_Adaptation_field * pTsAdaptationField, uint64_t ui64VideoDts) {
|
||||
//填写自适应段
|
||||
pTsAdaptationField->discontinuty_indicator = 0;
|
||||
pTsAdaptationField->random_access_indicator = 0;
|
||||
@ -290,7 +290,7 @@ void TSMaker::WriteAdaptive_flags_Head( Ts_Adaptation_field * pTsAdaptationField
|
||||
pTsAdaptationField->adaptation_field_extension_flag = 0;
|
||||
|
||||
//需要自己算
|
||||
pTsAdaptationField->pcr = ui64VideoPts * 300;
|
||||
pTsAdaptationField->pcr = ui64VideoDts * 300;
|
||||
pTsAdaptationField->adaptation_field_length = 7; //占用7位
|
||||
|
||||
pTsAdaptationField->opcr = 0;
|
||||
@ -298,14 +298,14 @@ void TSMaker::WriteAdaptive_flags_Head( Ts_Adaptation_field * pTsAdaptationField
|
||||
pTsAdaptationField->private_data_len = 0;
|
||||
}
|
||||
|
||||
int TSMaker::inputH264(const char* pcData, uint32_t ui32Len, uint64_t ui64Time) {
|
||||
int TSMaker::inputH264(const char* pcData, uint32_t ui32Len, uint64_t ui64Dts , uint64_t ui64Pts) {
|
||||
if (m_pOutVideoTs == NULL) {
|
||||
return false;
|
||||
}
|
||||
m_pVideo_pes->ES = const_cast<char *>(pcData);
|
||||
m_pVideo_pes->ESlen = ui32Len;
|
||||
Ts_Adaptation_field ts_adaptation_field_Head;
|
||||
WriteAdaptive_flags_Head(&ts_adaptation_field_Head, ui64Time); //填写自适应段标志帧头
|
||||
WriteAdaptive_flags_Head(&ts_adaptation_field_Head, ui64Dts); //填写自适应段标志帧头
|
||||
m_pVideo_pes->packet_start_code_prefix = 0x000001;
|
||||
m_pVideo_pes->stream_id = TS_H264_STREAM_ID; //E0~EF表示是视频的,C0~DF是音频,H264-- E0
|
||||
m_pVideo_pes->marker_bit = 0x02;
|
||||
@ -322,12 +322,12 @@ int TSMaker::inputH264(const char* pcData, uint32_t ui32Len, uint64_t ui64Time)
|
||||
m_pVideo_pes->PES_CRC_flag = 0x00;
|
||||
m_pVideo_pes->PES_extension_flag = 0x00;
|
||||
m_pVideo_pes->PES_header_data_length = 0x0A; //后面的数据包括了PTS和 DTS所占的字节数
|
||||
PES2TS(m_pVideo_pes, TS_H264_PID, &ts_adaptation_field_Head, ui64Time);
|
||||
PES2TS(m_pVideo_pes, TS_H264_PID, &ts_adaptation_field_Head, ui64Dts , ui64Pts);
|
||||
m_pVideo_pes->ESlen = 0;
|
||||
return ui32Len;
|
||||
}
|
||||
|
||||
int TSMaker::inputAAC(const char* pcData, uint32_t ui32Len, uint64_t ui64Pts) {
|
||||
int TSMaker::inputAAC(const char* pcData, uint32_t ui32Len, uint64_t ui64Dts , uint64_t ui64Pts) {
|
||||
if (m_pOutVideoTs == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@ -351,7 +351,7 @@ int TSMaker::inputAAC(const char* pcData, uint32_t ui32Len, uint64_t ui64Pts) {
|
||||
m_pAudio_pes->PES_CRC_flag = 0x00;
|
||||
m_pAudio_pes->PES_extension_flag = 0x00;
|
||||
m_pAudio_pes->PES_header_data_length = 0x0A; //后面的数据包括了PTS
|
||||
PES2TS(m_pAudio_pes, TS_AAC_PID, &ts_adaptation_field_Head, ui64Pts);
|
||||
PES2TS(m_pAudio_pes, TS_AAC_PID, &ts_adaptation_field_Head,ui64Dts,ui64Pts);
|
||||
m_pAudio_pes->ESlen = 0;
|
||||
return ui32Len;
|
||||
}
|
||||
@ -468,7 +468,7 @@ void TSMaker::CreateAdaptive_Ts(Ts_Adaptation_field * pTsAdaptationField, unsign
|
||||
}
|
||||
return;
|
||||
}
|
||||
void TSMaker::PES2TS(TsPes * pTsPes, unsigned int uiPID, Ts_Adaptation_field * pTsAdaptationFieldHead, uint64_t ui64Dts) {
|
||||
void TSMaker::PES2TS(TsPes * pTsPes, unsigned int uiPID, Ts_Adaptation_field * pTsAdaptationFieldHead, uint64_t ui64Dts ,uint64_t ui64Pts) {
|
||||
TsPacketHeader ts_header;
|
||||
unsigned int uiAdaptiveLength = 0; //要填写0XFF的长度
|
||||
unsigned int uiFirstPacketLoadLength = 188 - 4 - 1 - pTsAdaptationFieldHead->adaptation_field_length - 19; //分片包的第一个包的负载长度
|
||||
@ -529,18 +529,18 @@ void TSMaker::PES2TS(TsPes * pTsPes, unsigned int uiPID, Ts_Adaptation_field * p
|
||||
| pTsPes->PES_CRC_flag << 1 | pTsPes->PES_extension_flag;
|
||||
pucTSBuf += 8;
|
||||
switch (pTsPes->PTS_DTS_flags) {
|
||||
case 0x03: //both pts and ui64Dts
|
||||
case 0x03: //both pts and dts
|
||||
pucTSBuf[6] = (((0x1 << 4) | ((ui64Dts >> 29) & 0x0E) | 0x01) & 0xff);
|
||||
pucTSBuf[7] = (((((ui64Dts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
|
||||
pucTSBuf[8] = ((((ui64Dts >> 14) & 0xfffe) | 0x01) & 0xff);
|
||||
pucTSBuf[9] = ((((ui64Dts << 1) & 0xfffe) | 0x01) >> 8) & 0xff;
|
||||
pucTSBuf[10] = (((ui64Dts << 1) & 0xfffe) | 0x01) & 0xff;
|
||||
case 0x02: //pts only
|
||||
pucTSBuf[1] = (((0x3 << 4) | ((ui64Dts >> 29) & 0x0E) | 0x01) & 0xff);
|
||||
pucTSBuf[2] = (((((ui64Dts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
|
||||
pucTSBuf[3] = ((((ui64Dts >> 14) & 0xfffe) | 0x01) & 0xff);
|
||||
pucTSBuf[4] = (((((ui64Dts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);
|
||||
pucTSBuf[5] = ((((ui64Dts << 1) & 0xfffe) | 0x01) & 0xff);
|
||||
pucTSBuf[1] = (((0x3 << 4) | ((ui64Pts >> 29) & 0x0E) | 0x01) & 0xff);
|
||||
pucTSBuf[2] = (((((ui64Pts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
|
||||
pucTSBuf[3] = ((((ui64Pts >> 14) & 0xfffe) | 0x01) & 0xff);
|
||||
pucTSBuf[4] = (((((ui64Pts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);
|
||||
pucTSBuf[5] = ((((ui64Pts << 1) & 0xfffe) | 0x01) & 0xff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -239,8 +239,8 @@ public:
|
||||
TSMaker();
|
||||
virtual ~TSMaker();
|
||||
bool init(const string &strFilename, uint32_t ui32BufSize);
|
||||
int inputH264(const char *pcData, uint32_t ui32Len, uint64_t ui64Time);
|
||||
int inputAAC(const char *pcData, uint32_t ui32Len, uint64_t ui64Time);
|
||||
int inputH264(const char *pcData, uint32_t ui32Len, uint64_t ui64Dts , uint64_t ui64Pts);
|
||||
int inputAAC(const char *pcData, uint32_t ui32Len, uint64_t ui64Dts , uint64_t ui64Pts);
|
||||
void clear();
|
||||
private:
|
||||
string m_strFilename;
|
||||
@ -260,7 +260,7 @@ private:
|
||||
void WriteAdaptive_flags_Head(Ts_Adaptation_field * pAdaptationField, uint64_t ui64VideoPts);
|
||||
void WriteAdaptive_flags_Tail(Ts_Adaptation_field * pAdaptationField); //填写自适应段标志帧尾的
|
||||
|
||||
void PES2TS(TsPes * pPes, unsigned int uiPID, Ts_Adaptation_field * pAdaptationField, uint64_t ui64Pts);
|
||||
void PES2TS(TsPes * pPes, unsigned int uiPID, Ts_Adaptation_field * pAdaptationField, uint64_t ui64Dts ,uint64_t ui64Pts );
|
||||
void CreateAdaptive_Ts(Ts_Adaptation_field * pAdaptationField, unsigned char * pcTs, unsigned int uiAdaptiveLength);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user