MP4、hls适配新代码
This commit is contained in:
parent
83a0ee8595
commit
6364b14762
|
|
@ -83,5 +83,15 @@ bool MediaSink::isAllTrackReady() const {
|
||||||
return _allTrackReady;
|
return _allTrackReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Track::Ptr MediaSink::getTrack(TrackType type) const {
|
||||||
|
lock_guard<mutex> lck(_mtx);
|
||||||
|
for (auto &pr : _track_map){
|
||||||
|
if(pr.second->getTrackType() == type){
|
||||||
|
return pr.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ public:
|
||||||
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
|
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
|
||||||
* @param track
|
* @param track
|
||||||
*/
|
*/
|
||||||
void addTrack(const Track::Ptr & track);
|
virtual void addTrack(const Track::Ptr & track);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -66,6 +66,14 @@ public:
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
bool isAllTrackReady() const ;
|
bool isAllTrackReady() const ;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取特定类型的Track
|
||||||
|
* @param type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Track::Ptr getTrack(TrackType type) const ;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* 某track已经准备好,其ready()状态返回true,
|
* 某track已经准备好,其ready()状态返回true,
|
||||||
|
|
@ -85,7 +93,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void onTrackFrame(const Frame::Ptr &frame) {};
|
virtual void onTrackFrame(const Frame::Ptr &frame) {};
|
||||||
private:
|
private:
|
||||||
mutex _mtx;
|
mutable mutex _mtx;
|
||||||
map<int,Track::Ptr> _track_map;
|
map<int,Track::Ptr> _track_map;
|
||||||
map<int,function<void()> > _trackReadyCallback;
|
map<int,function<void()> > _trackReadyCallback;
|
||||||
bool _allTrackReady = false;
|
bool _allTrackReady = false;
|
||||||
|
|
|
||||||
|
|
@ -131,12 +131,12 @@ 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, int type) {
|
void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp) {
|
||||||
if(_ui32LastStamp == 0){
|
if(_ui32LastStamp == 0){
|
||||||
_ui32LastStamp = timeStamp;
|
_ui32LastStamp = timeStamp;
|
||||||
}
|
}
|
||||||
int stampInc = timeStamp - _ui32LastStamp;
|
int stampInc = timeStamp - _ui32LastStamp;
|
||||||
|
auto type = ((uint8_t*)data)[4] & 0x1F;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 7: //SPS
|
case 7: //SPS
|
||||||
if (stampInc >= _ui32SegmentDuration * 1000) {
|
if (stampInc >= _ui32SegmentDuration * 1000) {
|
||||||
|
|
@ -182,5 +182,29 @@ bool HLSMaker::removets() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HLSMaker::onTrackFrame(const Frame::Ptr &frame) {
|
||||||
|
switch (frame->getCodecId()){
|
||||||
|
case CodecH264:{
|
||||||
|
if( frame->prefixSize() == 4){
|
||||||
|
inputH264(frame->data(), frame->size(),frame->stamp());
|
||||||
|
}else{
|
||||||
|
WarnL << "h264必须要有头4个字节的前缀";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CodecAAC:{
|
||||||
|
if( frame->prefixSize() == 7) {
|
||||||
|
inputAAC(frame->data(), frame->size(), frame->stamp());
|
||||||
|
}else{
|
||||||
|
WarnL << "adts必须要有头7个字节的adts头";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,19 @@
|
||||||
#ifndef HLSMAKER_H_
|
#ifndef HLSMAKER_H_
|
||||||
#define HLSMAKER_H_
|
#define HLSMAKER_H_
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include "TSMaker.h"
|
#include "TSMaker.h"
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
#include "Util/File.h"
|
#include "Util/File.h"
|
||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
#include <deque>
|
#include "Common/config.h"
|
||||||
|
#include "Common/MediaSink.h"
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
class HLSMaker {
|
class HLSMaker : public MediaSink{
|
||||||
public:
|
public:
|
||||||
HLSMaker(const string &strM3u8File,
|
HLSMaker(const string &strM3u8File,
|
||||||
uint32_t ui32BufSize = 64 * 1024,
|
uint32_t ui32BufSize = 64 * 1024,
|
||||||
|
|
@ -47,16 +48,28 @@ public:
|
||||||
|
|
||||||
virtual ~HLSMaker();
|
virtual ~HLSMaker();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* 某Track输出frame,在onAllTrackReady触发后才会调用此方法
|
||||||
|
* @param frame
|
||||||
|
*/
|
||||||
|
void onTrackFrame(const Frame::Ptr &frame) override ;
|
||||||
|
private:
|
||||||
//时间戳:参考频率1000
|
//时间戳:参考频率1000
|
||||||
void inputH264(void *pData,
|
void inputH264(void *pData,
|
||||||
uint32_t ui32Length,
|
uint32_t ui32Length,
|
||||||
uint32_t ui32TimeStamp,
|
uint32_t ui32TimeStamp);
|
||||||
int iType);
|
|
||||||
|
|
||||||
//时间戳:参考频率1000
|
//时间戳:参考频率1000
|
||||||
void inputAAC(void *pData,
|
void inputAAC(void *pData,
|
||||||
uint32_t ui32Length,
|
uint32_t ui32Length,
|
||||||
uint32_t ui32TimeStamp);
|
uint32_t ui32TimeStamp);
|
||||||
|
|
||||||
|
bool write_index_file(int iFirstSegment,
|
||||||
|
unsigned int uiLastSegment,
|
||||||
|
int iEnd);
|
||||||
|
|
||||||
|
bool removets();
|
||||||
private:
|
private:
|
||||||
TSMaker _ts;
|
TSMaker _ts;
|
||||||
string _strM3u8File;
|
string _strM3u8File;
|
||||||
|
|
@ -69,8 +82,7 @@ private:
|
||||||
uint32_t _ui32LastStamp;
|
uint32_t _ui32LastStamp;
|
||||||
std::deque<int> _iDurations;
|
std::deque<int> _iDurations;
|
||||||
|
|
||||||
bool write_index_file(int iFirstSegment, unsigned int uiLastSegment, int iEnd);
|
|
||||||
bool removets();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ namespace mediakit {
|
||||||
MediaRecorder::MediaRecorder(const string &strVhost_tmp,
|
MediaRecorder::MediaRecorder(const string &strVhost_tmp,
|
||||||
const string &strApp,
|
const string &strApp,
|
||||||
const string &strId,
|
const string &strId,
|
||||||
const std::shared_ptr<PlayerBase> &pPlayer,
|
|
||||||
bool enableHls,
|
bool enableHls,
|
||||||
bool enableMp4) {
|
bool enableMp4) {
|
||||||
|
|
||||||
|
|
@ -63,7 +62,7 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
|
||||||
|
|
||||||
if(enableMp4){
|
if(enableMp4){
|
||||||
auto mp4FilePath = recordPath + "/" + strVhost + "/" + recordAppName + "/" + strApp + "/" + strId + "/";
|
auto mp4FilePath = recordPath + "/" + strVhost + "/" + recordAppName + "/" + strApp + "/" + strId + "/";
|
||||||
_mp4Maker.reset(new Mp4Maker(mp4FilePath,strVhost,strApp,strId,pPlayer));
|
_mp4Maker.reset(new Mp4Maker(mp4FilePath,strVhost,strApp,strId));
|
||||||
}
|
}
|
||||||
#endif //ENABLE_MP4V2
|
#endif //ENABLE_MP4V2
|
||||||
}
|
}
|
||||||
|
|
@ -73,22 +72,22 @@ MediaRecorder::~MediaRecorder() {
|
||||||
|
|
||||||
void MediaRecorder::inputH264(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType) {
|
void MediaRecorder::inputH264(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType) {
|
||||||
if(_hlsMaker){
|
if(_hlsMaker){
|
||||||
_hlsMaker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
|
// _hlsMaker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_MP4V2
|
#ifdef ENABLE_MP4V2
|
||||||
if(_mp4Maker){
|
if(_mp4Maker){
|
||||||
_mp4Maker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
|
// _mp4Maker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
|
||||||
}
|
}
|
||||||
#endif //ENABLE_MP4V2
|
#endif //ENABLE_MP4V2
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaRecorder::inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp) {
|
void MediaRecorder::inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp) {
|
||||||
if(_hlsMaker){
|
if(_hlsMaker){
|
||||||
_hlsMaker->inputAAC(pData, ui32Length, ui32TimeStamp);
|
// _hlsMaker->inputAAC(pData, ui32Length, ui32TimeStamp);
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_MP4V2
|
#ifdef ENABLE_MP4V2
|
||||||
if(_mp4Maker){
|
if(_mp4Maker){
|
||||||
_mp4Maker->inputAAC(pData, ui32Length, ui32TimeStamp);
|
// _mp4Maker->inputAAC(pData, ui32Length, ui32TimeStamp);
|
||||||
}
|
}
|
||||||
#endif //ENABLE_MP4V2
|
#endif //ENABLE_MP4V2
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ public:
|
||||||
MediaRecorder(const string &strVhost,
|
MediaRecorder(const string &strVhost,
|
||||||
const string &strApp,
|
const string &strApp,
|
||||||
const string &strId,
|
const string &strId,
|
||||||
const std::shared_ptr<PlayerBase> &pPlayer,
|
|
||||||
bool enableHls = true,
|
bool enableHls = true,
|
||||||
bool enableMp4 = false);
|
bool enableMp4 = false);
|
||||||
virtual ~MediaRecorder();
|
virtual ~MediaRecorder();
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,8 @@ string timeStr(const char *fmt) {
|
||||||
Mp4Maker::Mp4Maker(const string& strPath,
|
Mp4Maker::Mp4Maker(const string& strPath,
|
||||||
const string &strVhost,
|
const string &strVhost,
|
||||||
const string &strApp,
|
const string &strApp,
|
||||||
const string &strStreamId,
|
const string &strStreamId) {
|
||||||
const PlayerBase::Ptr &pPlayer) {
|
|
||||||
DebugL << strPath;
|
DebugL << strPath;
|
||||||
_pPlayer = pPlayer;
|
|
||||||
_strPath = strPath;
|
_strPath = strPath;
|
||||||
|
|
||||||
/////record 业务逻辑//////
|
/////record 业务逻辑//////
|
||||||
|
|
@ -74,7 +72,8 @@ Mp4Maker::~Mp4Maker() {
|
||||||
closeFile();
|
closeFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType){
|
void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp){
|
||||||
|
auto iType = ((uint8_t*)pData)[0] & 0x1F;
|
||||||
switch (iType) {
|
switch (iType) {
|
||||||
case 1: //P
|
case 1: //P
|
||||||
case 5: { //IDR
|
case 5: { //IDR
|
||||||
|
|
@ -84,16 +83,14 @@ void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStam
|
||||||
if(iTimeInc == 0 || iTimeInc == 500){
|
if(iTimeInc == 0 || iTimeInc == 500){
|
||||||
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << _ui32LastVideoTime;
|
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << _ui32LastVideoTime;
|
||||||
}
|
}
|
||||||
_inputH264((char *) _strLastVideo.data(), _strLastVideo.size(), iTimeInc, _iLastVideoType);
|
inputH264_l((char *) _strLastVideo.data(), _strLastVideo.size(), iTimeInc);
|
||||||
}
|
}
|
||||||
//_strLastVideo.assign(("\x0\x0\x0\x2\x9\xf0"), 6);
|
|
||||||
uint32_t *p = (uint32_t *) pData;
|
uint32_t prefixe = htonl(ui32Length);
|
||||||
*p = htonl(ui32Length - 4);
|
_strLastVideo.assign((char *) &prefixe, 4);
|
||||||
_strLastVideo.assign((char *) pData, ui32Length);
|
_strLastVideo.append((char *)pData,ui32Length);
|
||||||
memcpy(pData, "\x00\x00\x00\x01", 4);
|
|
||||||
|
|
||||||
_ui32LastVideoTime = ui32TimeStamp;
|
_ui32LastVideoTime = ui32TimeStamp;
|
||||||
_iLastVideoType = iType;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -107,15 +104,16 @@ void Mp4Maker::inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp
|
||||||
if(iTimeInc == 0 || iTimeInc == 500){
|
if(iTimeInc == 0 || iTimeInc == 500){
|
||||||
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << _ui32LastAudioTime;
|
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << _ui32LastAudioTime;
|
||||||
}
|
}
|
||||||
_inputAAC((char *)_strLastAudio.data(), _strLastAudio.size(), iTimeInc);
|
inputAAC_l((char *) _strLastAudio.data(), _strLastAudio.size(), iTimeInc);
|
||||||
}
|
}
|
||||||
_strLastAudio.assign((char *)pData, ui32Length);
|
_strLastAudio.assign((char *)pData, ui32Length);
|
||||||
_ui32LastAudioTime = ui32TimeStamp;
|
_ui32LastAudioTime = ui32TimeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duration, int iType) {
|
void Mp4Maker::inputH264_l(void *pData, uint32_t ui32Length, uint32_t ui32Duration) {
|
||||||
GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Record::kFileSecond);
|
GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Record::kFileSecond);
|
||||||
|
|
||||||
|
auto iType = ((uint8_t*)pData)[0] & 0x1F;
|
||||||
if(iType == 5 && (_hMp4 == MP4_INVALID_FILE_HANDLE || _ticker.elapsedTime() > recordSec * 1000)){
|
if(iType == 5 && (_hMp4 == MP4_INVALID_FILE_HANDLE || _ticker.elapsedTime() > recordSec * 1000)){
|
||||||
//在I帧率处新建MP4文件
|
//在I帧率处新建MP4文件
|
||||||
//如果文件未创建或者文件超过10分钟则创建新文件
|
//如果文件未创建或者文件超过10分钟则创建新文件
|
||||||
|
|
@ -126,27 +124,21 @@ void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duratio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mp4Maker::_inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32Duration) {
|
void Mp4Maker::inputAAC_l(void *pData, uint32_t ui32Length, uint32_t ui32Duration) {
|
||||||
GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Record::kFileSecond);
|
GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Record::kFileSecond);
|
||||||
|
|
||||||
//todo(xzl) 修复此处
|
if (!_haveVideo && (_hMp4 == MP4_INVALID_FILE_HANDLE || _ticker.elapsedTime() > recordSec * 1000)) {
|
||||||
|
//在I帧率处新建MP4文件
|
||||||
//
|
//如果文件未创建或者文件超过10分钟则创建新文件
|
||||||
// if (!_pPlayer->containVideo() && (_hMp4 == MP4_INVALID_FILE_HANDLE || _ticker.elapsedTime() > recordSec * 1000)) {
|
createFile();
|
||||||
// //在I帧率处新建MP4文件
|
}
|
||||||
// //如果文件未创建或者文件超过10分钟则创建新文件
|
if (_hAudio != MP4_INVALID_TRACK_ID) {
|
||||||
// createFile();
|
auto duration = ui32Duration * _audioSampleRate /1000.0;
|
||||||
// }
|
MP4WriteSample(_hMp4, _hAudio, (uint8_t*)pData, ui32Length,duration,0,false);
|
||||||
// if (_hAudio != MP4_INVALID_TRACK_ID) {
|
}
|
||||||
// auto duration = ui32Duration * _pPlayer->getAudioSampleRate() /1000.0;
|
|
||||||
// MP4WriteSample(_hMp4, _hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mp4Maker::createFile() {
|
void Mp4Maker::createFile() {
|
||||||
if(!_pPlayer->isInited()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
closeFile();
|
closeFile();
|
||||||
|
|
||||||
auto strDate = timeStr("%Y-%m-%d");
|
auto strDate = timeStr("%Y-%m-%d");
|
||||||
|
|
@ -184,30 +176,38 @@ void Mp4Maker::createFile() {
|
||||||
_strFile = strFile;
|
_strFile = strFile;
|
||||||
_ticker.resetTime();
|
_ticker.resetTime();
|
||||||
|
|
||||||
//todo(xzl) 修复此处
|
auto videoTrack = dynamic_pointer_cast<H264Track>(getTrack(TrackVideo));
|
||||||
|
if(videoTrack){
|
||||||
|
auto &sps = videoTrack->getSps();
|
||||||
|
auto &pps = videoTrack->getPps();
|
||||||
|
_hVideo = MP4AddH264VideoTrack(_hMp4,
|
||||||
|
90000,
|
||||||
|
MP4_INVALID_DURATION,
|
||||||
|
videoTrack->getVideoWidth(),
|
||||||
|
videoTrack->getVideoHeight(),
|
||||||
|
sps[1],
|
||||||
|
sps[2],
|
||||||
|
sps[3],
|
||||||
|
3);
|
||||||
|
if(_hVideo != MP4_INVALID_TRACK_ID){
|
||||||
|
MP4AddH264SequenceParameterSet(_hMp4, _hVideo, (uint8_t *)sps.data(), sps.size());
|
||||||
|
MP4AddH264PictureParameterSet(_hMp4, _hVideo, (uint8_t *)pps.data(), pps.size());
|
||||||
|
}else{
|
||||||
|
WarnL << "添加视频通道失败:" << strFileTmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if(_pPlayer->containVideo()){
|
auto audioTrack = dynamic_pointer_cast<AACTrack>(getTrack(TrackAudio));
|
||||||
// auto &sps = _pPlayer->getSps();
|
if(audioTrack){
|
||||||
// auto &pps = _pPlayer->getPps();
|
_audioSampleRate = audioTrack->getAudioSampleRate();
|
||||||
// _hVideo = MP4AddH264VideoTrack(_hMp4, 90000, MP4_INVALID_DURATION,
|
_hAudio = MP4AddAudioTrack(_hMp4, _audioSampleRate, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
|
||||||
// _pPlayer->getVideoWidth(), _pPlayer->getVideoHeight(),
|
if (_hAudio != MP4_INVALID_TRACK_ID) {
|
||||||
// sps[5], sps[6], sps[7], 3);
|
auto &cfg = audioTrack->getAacCfg();
|
||||||
// if(_hVideo !=MP4_INVALID_TRACK_ID){
|
MP4SetTrackESConfiguration(_hMp4, _hAudio,(uint8_t *)cfg.data(), cfg.size());
|
||||||
// MP4AddH264SequenceParameterSet(_hMp4, _hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
|
}else{
|
||||||
// MP4AddH264PictureParameterSet(_hMp4, _hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
|
WarnL << "添加音频通道失败:" << strFileTmp;
|
||||||
// }else{
|
}
|
||||||
// WarnL << "添加视频通道失败:" << strFileTmp;
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if(_pPlayer->containAudio()){
|
|
||||||
// _hAudio = MP4AddAudioTrack(_hMp4, _pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
|
|
||||||
// if (_hAudio != MP4_INVALID_TRACK_ID) {
|
|
||||||
// auto &cfg = _pPlayer->getAudioCfg();
|
|
||||||
// MP4SetTrackESConfiguration(_hMp4, _hAudio,(uint8_t *)cfg.data(), cfg.size());
|
|
||||||
// }else{
|
|
||||||
// WarnL << "添加音频通道失败:" << strFileTmp;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mp4Maker::closeFile() {
|
void Mp4Maker::closeFile() {
|
||||||
|
|
@ -232,6 +232,26 @@ void Mp4Maker::closeFile() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mp4Maker::onTrackFrame(const Frame::Ptr &frame) {
|
||||||
|
switch (frame->getCodecId()){
|
||||||
|
case CodecH264:{
|
||||||
|
inputH264(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize(),frame->stamp());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CodecAAC:{
|
||||||
|
inputAAC(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize(),frame->stamp());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mp4Maker::onAllTrackReady() {
|
||||||
|
_haveVideo = getTrack(TrackVideo).operator bool();
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,14 @@
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Common/MediaSink.h"
|
||||||
|
#include "Player/Track.h"
|
||||||
|
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
class Mp4Info
|
class Mp4Info {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
time_t ui64StartedTime; //GMT标准时间,单位秒
|
time_t ui64StartedTime; //GMT标准时间,单位秒
|
||||||
time_t ui64TimeLen;//录像长度,单位秒
|
time_t ui64TimeLen;//录像长度,单位秒
|
||||||
|
|
@ -55,43 +57,54 @@ public:
|
||||||
string strStreamId;//流ID
|
string strStreamId;//流ID
|
||||||
string strVhost;//vhost
|
string strVhost;//vhost
|
||||||
};
|
};
|
||||||
class Mp4Maker {
|
class Mp4Maker : public MediaSink{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<Mp4Maker> Ptr;
|
typedef std::shared_ptr<Mp4Maker> Ptr;
|
||||||
Mp4Maker(const string &strPath,
|
Mp4Maker(const string &strPath,
|
||||||
const string &strVhost ,
|
const string &strVhost ,
|
||||||
const string &strApp,
|
const string &strApp,
|
||||||
const string &strStreamId,
|
const string &strStreamId);
|
||||||
const PlayerBase::Ptr &pPlayer);
|
|
||||||
virtual ~Mp4Maker();
|
virtual ~Mp4Maker();
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* 某Track输出frame,在onAllTrackReady触发后才会调用此方法
|
||||||
|
* @param frame
|
||||||
|
*/
|
||||||
|
void onTrackFrame(const Frame::Ptr &frame) override ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有Track准备好了
|
||||||
|
*/
|
||||||
|
void onAllTrackReady() override;
|
||||||
|
private:
|
||||||
|
void createFile();
|
||||||
|
void closeFile();
|
||||||
|
|
||||||
//时间戳:参考频率1000
|
//时间戳:参考频率1000
|
||||||
void inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType);
|
void inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp);
|
||||||
//时间戳:参考频率1000
|
//时间戳:参考频率1000
|
||||||
void inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp);
|
void inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp);
|
||||||
|
|
||||||
|
void inputH264_l(void *pData, uint32_t ui32Length, uint32_t ui64Duration);
|
||||||
|
void inputAAC_l(void *pData, uint32_t ui32Length, uint32_t ui64Duration);
|
||||||
private:
|
private:
|
||||||
MP4FileHandle _hMp4 = MP4_INVALID_FILE_HANDLE;
|
MP4FileHandle _hMp4 = MP4_INVALID_FILE_HANDLE;
|
||||||
MP4TrackId _hVideo = MP4_INVALID_TRACK_ID;
|
MP4TrackId _hVideo = MP4_INVALID_TRACK_ID;
|
||||||
MP4TrackId _hAudio = MP4_INVALID_TRACK_ID;
|
MP4TrackId _hAudio = MP4_INVALID_TRACK_ID;
|
||||||
PlayerBase::Ptr _pPlayer;
|
|
||||||
string _strPath;
|
string _strPath;
|
||||||
string _strFile;
|
string _strFile;
|
||||||
string _strFileTmp;
|
string _strFileTmp;
|
||||||
Ticker _ticker;
|
Ticker _ticker;
|
||||||
SmoothTicker _mediaTicker[2];
|
|
||||||
|
|
||||||
void createFile();
|
|
||||||
void closeFile();
|
|
||||||
void _inputH264(void *pData, uint32_t ui32Length, uint32_t ui64Duration, int iType);
|
|
||||||
void _inputAAC(void *pData, uint32_t ui32Length, uint32_t ui64Duration);
|
|
||||||
|
|
||||||
string _strLastVideo;
|
string _strLastVideo;
|
||||||
string _strLastAudio;
|
string _strLastAudio;
|
||||||
|
|
||||||
uint32_t _ui32LastVideoTime = 0;
|
uint32_t _ui32LastVideoTime = 0;
|
||||||
uint32_t _ui32LastAudioTime = 0;
|
uint32_t _ui32LastAudioTime = 0;
|
||||||
int _iLastVideoType = 0;
|
|
||||||
|
|
||||||
Mp4Info _info;
|
Mp4Info _info;
|
||||||
|
|
||||||
|
bool _haveVideo = false;
|
||||||
|
int _audioSampleRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
|
|
||||||
|
|
@ -238,21 +238,29 @@ public:
|
||||||
case 5:{
|
case 5:{
|
||||||
//I
|
//I
|
||||||
if(!_sps.empty()){
|
if(!_sps.empty()){
|
||||||
|
if(!_spsFrame){
|
||||||
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
||||||
insertFrame->timeStamp = frame->stamp();
|
insertFrame->timeStamp = frame->stamp();
|
||||||
insertFrame->type = 7;
|
insertFrame->type = 7;
|
||||||
insertFrame->buffer = _sps;
|
insertFrame->buffer.assign("\x0\x0\x0\x1");
|
||||||
insertFrame->iPrefixSize = 0;
|
insertFrame->buffer.append(_sps);
|
||||||
VideoTrack::inputFrame(insertFrame);
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_spsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
VideoTrack::inputFrame(_spsFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_pps.empty()){
|
if(!_pps.empty()){
|
||||||
|
if(!_ppsFrame){
|
||||||
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
||||||
insertFrame->timeStamp = frame->stamp();
|
insertFrame->timeStamp = frame->stamp();
|
||||||
insertFrame->type = 8;
|
insertFrame->type = 8;
|
||||||
insertFrame->buffer = _pps;
|
insertFrame->buffer.assign("\x0\x0\x0\x1");
|
||||||
insertFrame->iPrefixSize = 0;
|
insertFrame->buffer.append(_pps);
|
||||||
VideoTrack::inputFrame(insertFrame);
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_ppsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
VideoTrack::inputFrame(_ppsFrame);
|
||||||
}
|
}
|
||||||
VideoTrack::inputFrame(frame);
|
VideoTrack::inputFrame(frame);
|
||||||
}
|
}
|
||||||
|
|
@ -282,6 +290,8 @@ private:
|
||||||
int _width = 0;
|
int _width = 0;
|
||||||
int _height = 0;
|
int _height = 0;
|
||||||
float _fps = 0;
|
float _fps = 0;
|
||||||
|
H264Frame::Ptr _spsFrame;
|
||||||
|
H264Frame::Ptr _ppsFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ public:
|
||||||
void onGetMetaData(const AMFValue &_metadata) override {
|
void onGetMetaData(const AMFValue &_metadata) override {
|
||||||
try {
|
try {
|
||||||
_pParser.reset(new RtmpDemuxer(_metadata));
|
_pParser.reset(new RtmpDemuxer(_metadata));
|
||||||
_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),_pParser,_bEnableHls,_bEnableMp4));
|
_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),_bEnableHls,_bEnableMp4));
|
||||||
//todo(xzl) 修复此处
|
//todo(xzl) 修复此处
|
||||||
|
|
||||||
// _pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
|
// _pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public:
|
||||||
RtspMediaSource::onGetSDP(strSdp);
|
RtspMediaSource::onGetSDP(strSdp);
|
||||||
try {
|
try {
|
||||||
_pParser.reset(new RtspDemuxer(_sdpAttr));
|
_pParser.reset(new RtspDemuxer(_sdpAttr));
|
||||||
_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),_pParser,_bEnableHls,_bEnableMp4));
|
_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),_bEnableHls,_bEnableMp4));
|
||||||
//todo(xzl) 修复此处
|
//todo(xzl) 修复此处
|
||||||
// _pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
|
// _pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
|
||||||
// _pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
|
// _pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue