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