整理代码,添加265模板代码

This commit is contained in:
xiongziliang 2018-10-30 14:59:42 +08:00
parent 27bc19dd64
commit 4cb74454c0
37 changed files with 1100 additions and 538 deletions

View File

@ -32,7 +32,6 @@
#include <functional> #include <functional>
#include "Util/util.h" #include "Util/util.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "Player/Player.h"
#include "Common/MultiMediaSourceMuxer.h" #include "Common/MultiMediaSourceMuxer.h"
using namespace std; using namespace std;

View File

@ -29,8 +29,8 @@
#include <mutex> #include <mutex>
#include <memory> #include <memory>
#include "Player/Frame.h" #include "Extension/Frame.h"
#include "Player/Track.h" #include "Extension/Track.h"
using namespace std; using namespace std;
using namespace toolkit; using namespace toolkit;

120
src/Extension/AAC.cpp Normal file
View File

@ -0,0 +1,120 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "AAC.h"
namespace mediakit{
void writeAdtsHeader(const AACFrame &hed, uint8_t *pcAdts) {
pcAdts[0] = (hed.syncword >> 4 & 0xFF); //8bit
pcAdts[1] = (hed.syncword << 4 & 0xF0); //4 bit
pcAdts[1] |= (hed.id << 3 & 0x08); //1 bit
pcAdts[1] |= (hed.layer << 1 & 0x06); //2bit
pcAdts[1] |= (hed.protection_absent & 0x01); //1 bit
pcAdts[2] = (hed.profile << 6 & 0xC0); // 2 bit
pcAdts[2] |= (hed.sf_index << 2 & 0x3C); //4bit
pcAdts[2] |= (hed.private_bit << 1 & 0x02); //1 bit
pcAdts[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit
pcAdts[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit
pcAdts[3] |= (hed.original << 5 & 0x20); //1 bit
pcAdts[3] |= (hed.home << 4 & 0x10); //1 bit
pcAdts[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit
pcAdts[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit
pcAdts[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit
pcAdts[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit
pcAdts[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit
pcAdts[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit
pcAdts[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit
pcAdts[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit
}
string makeAdtsConfig(const uint8_t *pcAdts){
if (!(pcAdts[0] == 0xFF && (pcAdts[1] & 0xF0) == 0xF0)) {
return "";
}
// Get and check the 'profile':
unsigned char profile = (pcAdts[2] & 0xC0) >> 6; // 2 bits
if (profile == 3) {
return "";
}
// Get and check the 'sampling_frequency_index':
unsigned char sampling_frequency_index = (pcAdts[2] & 0x3C) >> 2; // 4 bits
if (samplingFrequencyTable[sampling_frequency_index] == 0) {
return "";
}
// Get and check the 'channel_configuration':
unsigned char channel_configuration = ((pcAdts[2] & 0x01) << 2)
| ((pcAdts[3] & 0xC0) >> 6); // 3 bits
unsigned char audioSpecificConfig[2];
unsigned char const audioObjectType = profile + 1;
audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1);
audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3);
return string((char *)audioSpecificConfig,2);
}
void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) {
uint8_t cfg1 = strAudioCfg[0];
uint8_t cfg2 = strAudioCfg[1];
int audioObjectType;
int sampling_frequency_index;
int channel_configuration;
audioObjectType = cfg1 >> 3;
sampling_frequency_index = ((cfg1 & 0x07) << 1) | (cfg2 >> 7);
channel_configuration = (cfg2 & 0x7F) >> 3;
adts.syncword = 0x0FFF;
adts.id = 0;
adts.layer = 0;
adts.protection_absent = 1;
adts.profile = audioObjectType - 1;
adts.sf_index = sampling_frequency_index;
adts.private_bit = 0;
adts.channel_configuration = channel_configuration;
adts.original = 0;
adts.home = 0;
adts.copyright_identification_bit = 0;
adts.copyright_identification_start = 0;
adts.aac_frame_length = 7;
adts.adts_buffer_fullness = 2047;
adts.no_raw_data_blocks_in_frame = 0;
}
void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){
iSampleRate = samplingFrequencyTable[adts.sf_index];
iChannel = adts.channel_configuration;
}
}//namespace mediakit

266
src/Extension/AAC.h Normal file
View File

@ -0,0 +1,266 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZLMEDIAKIT_AAC_H
#define ZLMEDIAKIT_AAC_H
#include "Frame.h"
#include "Track.h"
namespace mediakit{
class AACFrame;
unsigned const samplingFrequencyTable[16] = { 96000, 88200,
64000, 48000,
44100, 32000,
24000, 22050,
16000, 12000,
11025, 8000,
7350, 0, 0, 0 };
void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts);
void writeAdtsHeader(const AACFrame &adts, uint8_t *pcAdts) ;
string makeAdtsConfig(const uint8_t *pcAdts);
void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel);
/**
* aac帧adts头
*/
class AACFrame : public Frame {
public:
typedef std::shared_ptr<AACFrame> Ptr;
char *data() const override{
return (char *)buffer;
}
uint32_t size() const override {
return aac_frame_length;
}
uint32_t stamp() const override {
return timeStamp;
}
uint32_t prefixSize() const override{
return iPrefixSize;
}
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return CodecAAC;
}
bool keyFrame() const override {
return false;
}
public:
unsigned int syncword; //12 bslbf 同步字The bit string 1111 1111 1111说明一个ADTS帧的开始
unsigned int id; //1 bslbf MPEG 标示符, 设置为1
unsigned int layer; //2 uimsbf Indicates which layer is used. Set to 00
unsigned int protection_absent; //1 bslbf 表示是否误码校验
unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC如01 Low Complexity(LC)--- AACLC
unsigned int sf_index; //4 uimsbf 表示使用的采样率下标
unsigned int private_bit; //1 bslbf
unsigned int channel_configuration; //3 uimsbf 表示声道数
unsigned int original; //1 bslbf
unsigned int home; //1 bslbf
//下面的为改变的参数即每一帧都不同
unsigned int copyright_identification_bit; //1 bslbf
unsigned int copyright_identification_start; //1 bslbf
unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block
unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流
//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧.
//所以说number_of_raw_data_blocks_in_frame == 0
//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
unsigned int no_raw_data_blocks_in_frame; //2 uimsfb
unsigned char buffer[2 * 1024 + 7];
uint16_t sequence;
uint32_t timeStamp;
uint32_t iPrefixSize = 7;
} ;
class AACFrameNoCopyAble : public FrameNoCopyAble {
public:
typedef std::shared_ptr<AACFrameNoCopyAble> Ptr;
AACFrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 7){
buffer_ptr = ptr;
buffer_size = size;
timeStamp = stamp;
iPrefixSize = prefixeSize;
}
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return CodecAAC;
}
bool keyFrame() const override {
return false;
}
} ;
/**
* aac音频通道
*/
class AACTrack : public AudioTrack{
public:
typedef std::shared_ptr<AACTrack> Ptr;
/**
* adts头信息
* inputFrame中获取adts头信息
*/
AACTrack(){}
/**
* aac类型的媒体
* @param aac_cfg aac两个字节的配置信息
*/
AACTrack(const string &aac_cfg){
if(aac_cfg.size() != 2){
throw std::invalid_argument("adts配置必须为2个字节");
}
_cfg = aac_cfg;
parseAacCfg(_cfg);
}
/**
* aac类型的媒体
* @param adts_header adts头7
* @param adts_header_len adts头长度7
*/
AACTrack(const char *adts_header,int adts_header_len = 7){
if(adts_header_len < 7){
throw std::invalid_argument("adts头必须不少于7个字节");
}
_cfg = makeAdtsConfig((uint8_t*)adts_header);
parseAacCfg(_cfg);
}
/**
* aac类型的媒体
* @param aac_frame_with_adts adts头的aac帧
*/
AACTrack(const Frame::Ptr &aac_frame_with_adts){
if(aac_frame_with_adts->getCodecId() != CodecAAC || aac_frame_with_adts->prefixSize() < 7){
throw std::invalid_argument("必须输入带adts头的aac帧");
}
_cfg = makeAdtsConfig((uint8_t*)aac_frame_with_adts->data());
parseAacCfg(_cfg);
}
/**
* aac两个字节的配置
* @return
*/
const string &getAacCfg() const{
return _cfg;
}
/**
*
* @return
*/
CodecId getCodecId() const override{
return CodecAAC;
}
/**
* aac_cfg前是无效的Track
* @return
*/
bool ready() override {
return !_cfg.empty();
}
/**
*
* @return
*/
int getAudioSampleRate() const override{
return _sampleRate;
}
/**
* 168
* @return
*/
int getAudioSampleBit() const override{
return _sampleBit;
}
/**
*
* @return
*/
int getAudioChannel() const override{
return _channel;
}
/**
* ,aac_cfg
* @param frame
*/
void inputFrame(const Frame::Ptr &frame) override{
if(_cfg.empty() && frame->prefixSize() >= 7){
//7个字节的adts头
_cfg = makeAdtsConfig(reinterpret_cast<const uint8_t *>(frame->data()));
parseAacCfg(_cfg);
}
AudioTrack::inputFrame(frame);
}
private:
/**
* 2aac配置
* @param aac_cfg
*/
void parseAacCfg(const string &aac_cfg){
AACFrame aacFrame;
makeAdtsHeader(aac_cfg,aacFrame);
getAACInfo(aacFrame,_sampleRate,_channel);
}
Track::Ptr clone() override {
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
}
private:
string _cfg;
int _sampleRate = 0;
int _sampleBit = 16;
int _channel = 0;
};
}//namespace mediakit
#endif //ZLMEDIAKIT_AAC_H

View File

@ -29,7 +29,7 @@
#include <string> #include <string>
#include "Rtmp/amf.h" #include "Rtmp/amf.h"
#include "Player/Track.h" #include "Extension/Track.h"
#include "RtspMuxer/RtspSdp.h" #include "RtspMuxer/RtspSdp.h"
#include "RtspMuxer/RtpCodec.h" #include "RtspMuxer/RtpCodec.h"
#include "RtmpMuxer/RtmpCodec.h" #include "RtmpMuxer/RtmpCodec.h"

View File

@ -40,6 +40,7 @@ namespace mediakit{
typedef enum { typedef enum {
CodecInvalid = -1, CodecInvalid = -1,
CodecH264 = 0, CodecH264 = 0,
CodecH265,
CodecAAC, CodecAAC,
CodecMax = 0x7FFF CodecMax = 0x7FFF
} CodecId; } CodecId;
@ -261,106 +262,6 @@ private:
map<void *,FrameWriterInterface::Ptr> _delegateMap; map<void *,FrameWriterInterface::Ptr> _delegateMap;
}; };
/**
* 264
*/
class H264Frame : public Frame {
public:
typedef std::shared_ptr<H264Frame> Ptr;
char *data() const override{
return (char *)buffer.data();
}
uint32_t size() const override {
return buffer.size();
}
uint32_t stamp() const override {
return timeStamp;
}
uint32_t prefixSize() const override{
return iPrefixSize;
}
TrackType getTrackType() const override{
return TrackVideo;
}
CodecId getCodecId() const override{
return CodecH264;
}
bool keyFrame() const override {
return type == 5;
}
public:
uint16_t sequence;
uint32_t timeStamp;
unsigned char type;
string buffer;
uint32_t iPrefixSize = 4;
};
/**
* aac帧adts头
*/
class AACFrame : public Frame {
public:
typedef std::shared_ptr<AACFrame> Ptr;
char *data() const override{
return (char *)buffer;
}
uint32_t size() const override {
return aac_frame_length;
}
uint32_t stamp() const override {
return timeStamp;
}
uint32_t prefixSize() const override{
return iPrefixSize;
}
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return CodecAAC;
}
bool keyFrame() const override {
return false;
}
public:
unsigned int syncword; //12 bslbf 同步字The bit string 1111 1111 1111说明一个ADTS帧的开始
unsigned int id; //1 bslbf MPEG 标示符, 设置为1
unsigned int layer; //2 uimsbf Indicates which layer is used. Set to 00
unsigned int protection_absent; //1 bslbf 表示是否误码校验
unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC如01 Low Complexity(LC)--- AACLC
unsigned int sf_index; //4 uimsbf 表示使用的采样率下标
unsigned int private_bit; //1 bslbf
unsigned int channel_configuration; //3 uimsbf 表示声道数
unsigned int original; //1 bslbf
unsigned int home; //1 bslbf
//下面的为改变的参数即每一帧都不同
unsigned int copyright_identification_bit; //1 bslbf
unsigned int copyright_identification_start; //1 bslbf
unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block
unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流
//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧.
//所以说number_of_raw_data_blocks_in_frame == 0
//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
unsigned int no_raw_data_blocks_in_frame; //2 uimsfb
unsigned char buffer[2 * 1024 + 7];
uint16_t sequence;
uint32_t timeStamp;
uint32_t iPrefixSize = 7;
} ;
class FrameNoCopyAble : public Frame{ class FrameNoCopyAble : public Frame{
public: public:
typedef std::shared_ptr<FrameNoCopyAble> Ptr; typedef std::shared_ptr<FrameNoCopyAble> Ptr;
@ -384,53 +285,7 @@ public:
}; };
class H264FrameNoCopyAble : public FrameNoCopyAble {
public:
typedef std::shared_ptr<H264FrameNoCopyAble> Ptr;
H264FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){
buffer_ptr = ptr;
buffer_size = size;
timeStamp = stamp;
iPrefixSize = prefixeSize;
}
TrackType getTrackType() const override{
return TrackVideo;
}
CodecId getCodecId() const override{
return CodecH264;
}
bool keyFrame() const override {
return (buffer_ptr[iPrefixSize] & 0x1F) == 5;
}
};
class AACFrameNoCopyAble : public FrameNoCopyAble {
public:
typedef std::shared_ptr<AACFrameNoCopyAble> Ptr;
AACFrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 7){
buffer_ptr = ptr;
buffer_size = size;
timeStamp = stamp;
iPrefixSize = prefixeSize;
}
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return CodecAAC;
}
bool keyFrame() const override {
return false;
}
} ;
}//namespace mediakit }//namespace mediakit

View File

@ -24,29 +24,33 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef SRC_PLAYER_PLAYER_H_
#define SRC_PLAYER_PLAYER_H_
#include <string> #include "H264.h"
#include "Frame.h" #include "H264/SPSParser.h"
#include "Util/logger.h"
using namespace toolkit;
using namespace std; namespace mediakit{
using namespace mediakit;
unsigned const samplingFrequencyTable[16] = { 96000, 88200, bool getAVCInfo(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
64000, 48000, return getAVCInfo(strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps);
44100, 32000, }
24000, 22050, bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){
16000, 12000, T_GetBitContext tGetBitBuf;
11025, 8000, T_SPS tH264SpsInfo;
7350, 0, 0, 0 }; memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo));
tGetBitBuf.pu8Buf = (uint8_t*)sps + 1;
tGetBitBuf.iBufSize = sps_len - 1;
if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){
return false;
}
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
//ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
return true;
}
void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts); }//namespace mediakit
void writeAdtsHeader(const AACFrame &adts, uint8_t *pcAdts) ;
string makeAdtsConfig(const uint8_t *pcAdts);
void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel);
bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
#endif /* SRC_PLAYER_PLAYER_H_ */

View File

@ -24,107 +24,82 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef ZLMEDIAKIT_TRACK_H #ifndef ZLMEDIAKIT_H264_H
#define ZLMEDIAKIT_TRACK_H #define ZLMEDIAKIT_H264_H
#include <memory>
#include <string>
#include "Frame.h" #include "Frame.h"
#include "Util/RingBuffer.h" #include "Track.h"
#include "Rtsp/Rtsp.h"
#include "Player.h"
using namespace toolkit;
namespace mediakit{ namespace mediakit{
/** bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
* bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
*/
class Track : public FrameRingInterfaceDelegate , public CodecInfo{
public:
typedef std::shared_ptr<Track> Ptr;
Track(){}
virtual ~Track(){}
/**
* sps pps等信息
* @return
*/
virtual bool ready() = 0;
/**
*
*
*
* @return
*/
virtual Track::Ptr clone() = 0;
/**
*
*
* @param that
*/
Track(const Track &that){}
};
/** /**
* Track类fps信息 * 264
*/ */
class VideoTrack : public Track { class H264Frame : public Frame {
public: public:
typedef std::shared_ptr<VideoTrack> Ptr; typedef std::shared_ptr<H264Frame> Ptr;
TrackType getTrackType() const override { return TrackVideo;}; char *data() const override{
return (char *)buffer.data();
}
uint32_t size() const override {
return buffer.size();
}
uint32_t stamp() const override {
return timeStamp;
}
uint32_t prefixSize() const override{
return iPrefixSize;
}
/** TrackType getTrackType() const override{
* return TrackVideo;
* @return }
*/
virtual int getVideoHeight() const = 0;
/** CodecId getCodecId() const override{
* return CodecH264;
* @return }
*/
virtual int getVideoWidth() const = 0;
/** bool keyFrame() const override {
* fps return type == 5;
* @return }
*/ public:
virtual float getVideoFps() const = 0; uint16_t sequence;
uint32_t timeStamp;
unsigned char type;
string buffer;
uint32_t iPrefixSize = 4;
}; };
/**
* Track派生类 class H264FrameNoCopyAble : public FrameNoCopyAble {
*/
class AudioTrack : public Track {
public: public:
typedef std::shared_ptr<AudioTrack> Ptr; typedef std::shared_ptr<H264FrameNoCopyAble> Ptr;
TrackType getTrackType() const override { return TrackAudio;}; H264FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){
buffer_ptr = ptr;
buffer_size = size;
timeStamp = stamp;
iPrefixSize = prefixeSize;
}
/** TrackType getTrackType() const override{
* return TrackVideo;
* @return }
*/
virtual int getAudioSampleRate() const = 0;
/** CodecId getCodecId() const override{
* 168 return CodecH264;
* @return }
*/
virtual int getAudioSampleBit() const = 0;
/** bool keyFrame() const override {
* return (buffer_ptr[iPrefixSize] & 0x1F) == 5;
* @return }
*/
virtual int getAudioChannel() const = 0;
}; };
/** /**
* 264 * 264
*/ */
@ -298,135 +273,8 @@ private:
H264Frame::Ptr _ppsFrame; H264Frame::Ptr _ppsFrame;
}; };
/**
* aac音频通道
*/
class AACTrack : public AudioTrack{
public:
typedef std::shared_ptr<AACTrack> Ptr;
/**
* adts头信息
* inputFrame中获取adts头信息
*/
AACTrack(){}
/**
* aac类型的媒体
* @param aac_cfg aac两个字节的配置信息
*/
AACTrack(const string &aac_cfg){
if(aac_cfg.size() != 2){
throw std::invalid_argument("adts配置必须为2个字节");
}
_cfg = aac_cfg;
parseAacCfg(_cfg);
}
/**
* aac类型的媒体
* @param adts_header adts头7
* @param adts_header_len adts头长度7
*/
AACTrack(const char *adts_header,int adts_header_len = 7){
if(adts_header_len < 7){
throw std::invalid_argument("adts头必须不少于7个字节");
}
_cfg = makeAdtsConfig((uint8_t*)adts_header);
parseAacCfg(_cfg);
}
/**
* aac类型的媒体
* @param aac_frame_with_adts adts头的aac帧
*/
AACTrack(const Frame::Ptr &aac_frame_with_adts){
if(aac_frame_with_adts->getCodecId() != CodecAAC || aac_frame_with_adts->prefixSize() < 7){
throw std::invalid_argument("必须输入带adts头的aac帧");
}
_cfg = makeAdtsConfig((uint8_t*)aac_frame_with_adts->data());
parseAacCfg(_cfg);
}
/**
* aac两个字节的配置
* @return
*/
const string &getAacCfg() const{
return _cfg;
}
/**
*
* @return
*/
CodecId getCodecId() const override{
return CodecAAC;
}
/**
* aac_cfg前是无效的Track
* @return
*/
bool ready() override {
return !_cfg.empty();
}
/**
*
* @return
*/
int getAudioSampleRate() const override{
return _sampleRate;
}
/**
* 168
* @return
*/
int getAudioSampleBit() const override{
return _sampleBit;
}
/**
*
* @return
*/
int getAudioChannel() const override{
return _channel;
}
/**
* ,aac_cfg
* @param frame
*/
void inputFrame(const Frame::Ptr &frame) override{
if(_cfg.empty() && frame->prefixSize() >= 7){
//7个字节的adts头
_cfg = makeAdtsConfig(reinterpret_cast<const uint8_t *>(frame->data()));
parseAacCfg(_cfg);
}
AudioTrack::inputFrame(frame);
}
private:
/**
* 2aac配置
* @param aac_cfg
*/
void parseAacCfg(const string &aac_cfg){
AACFrame aacFrame;
makeAdtsHeader(aac_cfg,aacFrame);
getAACInfo(aacFrame,_sampleRate,_channel);
}
Track::Ptr clone() override {
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
}
private:
string _cfg;
int _sampleRate = 0;
int _sampleBit = 16;
int _channel = 0;
};
}//namespace mediakit }//namespace mediakit
#endif //ZLMEDIAKIT_TRACK_H
#endif //ZLMEDIAKIT_H264_H

View File

@ -24,8 +24,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "Frame.h" #include "H265.h"
namespace mediakit{ namespace mediakit{
}
}//namespace mediakit

104
src/Extension/H265.h Normal file
View File

@ -0,0 +1,104 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZLMEDIAKIT_H265_H
#define ZLMEDIAKIT_H265_H
#include "Frame.h"
#include "Track.h"
namespace mediakit{
/**
* 265
*/
class H265Frame : public Frame {
public:
typedef std::shared_ptr<H265Frame> Ptr;
char *data() const override{
return (char *)buffer.data();
}
uint32_t size() const override {
return buffer.size();
}
uint32_t stamp() const override {
return timeStamp;
}
uint32_t prefixSize() const override{
return iPrefixSize;
}
TrackType getTrackType() const override{
return TrackVideo;
}
CodecId getCodecId() const override{
return CodecH265;
}
bool keyFrame() const override {
return type == 5;
}
public:
uint16_t sequence;
uint32_t timeStamp;
unsigned char type;
string buffer;
uint32_t iPrefixSize = 4;
};
class H265FrameNoCopyAble : public FrameNoCopyAble {
public:
typedef std::shared_ptr<H265FrameNoCopyAble> Ptr;
H265FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){
buffer_ptr = ptr;
buffer_size = size;
timeStamp = stamp;
iPrefixSize = prefixeSize;
}
TrackType getTrackType() const override{
return TrackVideo;
}
CodecId getCodecId() const override{
return CodecH265;
}
bool keyFrame() const override {
return (buffer_ptr[iPrefixSize] & 0x1F) == 5;
}
};
}//namespace mediakit
#endif //ZLMEDIAKIT_H265_H

130
src/Extension/Track.h Normal file
View File

@ -0,0 +1,130 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZLMEDIAKIT_TRACK_H
#define ZLMEDIAKIT_TRACK_H
#include <memory>
#include <string>
#include "Frame.h"
#include "Util/RingBuffer.h"
#include "Rtsp/Rtsp.h"
using namespace toolkit;
namespace mediakit{
/**
*
*/
class Track : public FrameRingInterfaceDelegate , public CodecInfo{
public:
typedef std::shared_ptr<Track> Ptr;
Track(){}
virtual ~Track(){}
/**
* sps pps等信息
* @return
*/
virtual bool ready() = 0;
/**
*
*
*
* @return
*/
virtual Track::Ptr clone() = 0;
/**
*
*
* @param that
*/
Track(const Track &that){}
};
/**
* Track类fps信息
*/
class VideoTrack : public Track {
public:
typedef std::shared_ptr<VideoTrack> Ptr;
TrackType getTrackType() const override { return TrackVideo;};
/**
*
* @return
*/
virtual int getVideoHeight() const = 0;
/**
*
* @return
*/
virtual int getVideoWidth() const = 0;
/**
* fps
* @return
*/
virtual float getVideoFps() const = 0;
};
/**
* Track派生类
*/
class AudioTrack : public Track {
public:
typedef std::shared_ptr<AudioTrack> Ptr;
TrackType getTrackType() const override { return TrackAudio;};
/**
*
* @return
*/
virtual int getAudioSampleRate() const = 0;
/**
* 168
* @return
*/
virtual int getAudioSampleBit() const = 0;
/**
*
* @return
*/
virtual int getAudioChannel() const = 0;
};
}//namespace mediakit
#endif //ZLMEDIAKIT_TRACK_H

View File

@ -34,6 +34,9 @@
#include "Util/mini.h" #include "Util/mini.h"
#include "Util/util.h" #include "Util/util.h"
#include "Util/NoticeCenter.h" #include "Util/NoticeCenter.h"
#include "Extension/H264.h"
#include "Extension/AAC.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {

View File

@ -38,7 +38,7 @@
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "Common/MediaSink.h" #include "Common/MediaSink.h"
#include "Player/Track.h" #include "Extension/Track.h"
using namespace toolkit; using namespace toolkit;

View File

@ -29,7 +29,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "Player.h"
#include "PlayerBase.h" #include "PlayerBase.h"
#include "Rtsp/RtspPlayer.h" #include "Rtsp/RtspPlayer.h"
#include "Rtmp/RtmpPlayer.h" #include "Rtmp/RtmpPlayer.h"

View File

@ -1,135 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <cstring>
#include "Player.h"
#include "H264/SPSParser.h"
#include "Util/logger.h"
using namespace toolkit;
void writeAdtsHeader(const AACFrame &hed, uint8_t *pcAdts) {
pcAdts[0] = (hed.syncword >> 4 & 0xFF); //8bit
pcAdts[1] = (hed.syncword << 4 & 0xF0); //4 bit
pcAdts[1] |= (hed.id << 3 & 0x08); //1 bit
pcAdts[1] |= (hed.layer << 1 & 0x06); //2bit
pcAdts[1] |= (hed.protection_absent & 0x01); //1 bit
pcAdts[2] = (hed.profile << 6 & 0xC0); // 2 bit
pcAdts[2] |= (hed.sf_index << 2 & 0x3C); //4bit
pcAdts[2] |= (hed.private_bit << 1 & 0x02); //1 bit
pcAdts[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit
pcAdts[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit
pcAdts[3] |= (hed.original << 5 & 0x20); //1 bit
pcAdts[3] |= (hed.home << 4 & 0x10); //1 bit
pcAdts[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit
pcAdts[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit
pcAdts[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit
pcAdts[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit
pcAdts[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit
pcAdts[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit
pcAdts[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit
pcAdts[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit
}
string makeAdtsConfig(const uint8_t *pcAdts){
if (!(pcAdts[0] == 0xFF && (pcAdts[1] & 0xF0) == 0xF0)) {
return "";
}
// Get and check the 'profile':
unsigned char profile = (pcAdts[2] & 0xC0) >> 6; // 2 bits
if (profile == 3) {
return "";
}
// Get and check the 'sampling_frequency_index':
unsigned char sampling_frequency_index = (pcAdts[2] & 0x3C) >> 2; // 4 bits
if (samplingFrequencyTable[sampling_frequency_index] == 0) {
return "";
}
// Get and check the 'channel_configuration':
unsigned char channel_configuration = ((pcAdts[2] & 0x01) << 2)
| ((pcAdts[3] & 0xC0) >> 6); // 3 bits
unsigned char audioSpecificConfig[2];
unsigned char const audioObjectType = profile + 1;
audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1);
audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3);
return string((char *)audioSpecificConfig,2);
}
void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) {
uint8_t cfg1 = strAudioCfg[0];
uint8_t cfg2 = strAudioCfg[1];
int audioObjectType;
int sampling_frequency_index;
int channel_configuration;
audioObjectType = cfg1 >> 3;
sampling_frequency_index = ((cfg1 & 0x07) << 1) | (cfg2 >> 7);
channel_configuration = (cfg2 & 0x7F) >> 3;
adts.syncword = 0x0FFF;
adts.id = 0;
adts.layer = 0;
adts.protection_absent = 1;
adts.profile = audioObjectType - 1;
adts.sf_index = sampling_frequency_index;
adts.private_bit = 0;
adts.channel_configuration = channel_configuration;
adts.original = 0;
adts.home = 0;
adts.copyright_identification_bit = 0;
adts.copyright_identification_start = 0;
adts.aac_frame_length = 7;
adts.adts_buffer_fullness = 2047;
adts.no_raw_data_blocks_in_frame = 0;
}
void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){
iSampleRate = samplingFrequencyTable[adts.sf_index];
iChannel = adts.channel_configuration;
}
bool getAVCInfo(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
return getAVCInfo(strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps);
}
bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){
T_GetBitContext tGetBitBuf;
T_SPS tH264SpsInfo;
memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo));
tGetBitBuf.pu8Buf = (uint8_t*)sps + 1;
tGetBitBuf.iBufSize = sps_len - 1;
if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){
return false;
}
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
//ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
return true;
}

View File

@ -31,13 +31,12 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <functional> #include <functional>
#include "Player.h"
#include "Network/Socket.h" #include "Network/Socket.h"
#include "Util/mini.h" #include "Util/mini.h"
#include "Util/RingBuffer.h" #include "Util/RingBuffer.h"
#include "Common/MediaSource.h" #include "Common/MediaSource.h"
#include "Frame.h" #include "Extension/Frame.h"
#include "Track.h" #include "Extension/Track.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {

View File

@ -24,7 +24,6 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "Player/Player.h"
#include "Common/config.h" #include "Common/config.h"
#include "PlayerProxy.h" #include "PlayerProxy.h"
#include "Util/mini.h" #include "Util/mini.h"

View File

@ -23,7 +23,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
#include <Player/Player.h>
#include "AACRtmpCodec.h" #include "AACRtmpCodec.h"
namespace mediakit{ namespace mediakit{

View File

@ -28,7 +28,8 @@
#define ZLMEDIAKIT_AACRTMPCODEC_H #define ZLMEDIAKIT_AACRTMPCODEC_H
#include "RtmpCodec.h" #include "RtmpCodec.h"
#include "Player/Track.h" #include "Extension/Track.h"
#include "Extension/AAC.h"
namespace mediakit{ namespace mediakit{
/** /**

View File

@ -28,8 +28,9 @@
#define ZLMEDIAKIT_H264RTMPCODEC_H #define ZLMEDIAKIT_H264RTMPCODEC_H
#include "RtmpCodec.h" #include "RtmpCodec.h"
#include "Player/Track.h" #include "Extension/Track.h"
#include "Util/ResourcePool.h" #include "Util/ResourcePool.h"
#include "Extension/H264.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit{ namespace mediakit{

View File

@ -28,7 +28,7 @@
#define ZLMEDIAKIT_RTMPCODEC_H #define ZLMEDIAKIT_RTMPCODEC_H
#include "Rtmp/Rtmp.h" #include "Rtmp/Rtmp.h"
#include "Player/Frame.h" #include "Extension/Frame.h"
#include "Util/RingBuffer.h" #include "Util/RingBuffer.h"
using namespace toolkit; using namespace toolkit;

View File

@ -25,7 +25,7 @@
*/ */
#include "RtmpDemuxer.h" #include "RtmpDemuxer.h"
#include "Common/Factory.h" #include "Extension/Factory.h"
namespace mediakit { namespace mediakit {

View File

@ -31,7 +31,6 @@
#include <unordered_map> #include <unordered_map>
#include "Rtmp/amf.h" #include "Rtmp/amf.h"
#include "Rtmp/Rtmp.h" #include "Rtmp/Rtmp.h"
#include "Player/Player.h"
#include "Player/PlayerBase.h" #include "Player/PlayerBase.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "RtmpCodec.h" #include "RtmpCodec.h"

View File

@ -30,9 +30,9 @@
#include "RtmpMuxer/H264RtmpCodec.h" #include "RtmpMuxer/H264RtmpCodec.h"
#include "RtmpMuxer/AACRtmpCodec.h" #include "RtmpMuxer/AACRtmpCodec.h"
#include "Util/base64.h" #include "Util/base64.h"
#include "Player/Track.h" #include "Extension/Track.h"
#include "Rtmp/amf.h" #include "Rtmp/amf.h"
#include "Common/Factory.h" #include "Extension/Factory.h"
namespace mediakit { namespace mediakit {

View File

@ -28,7 +28,7 @@
#define ZLMEDIAKIT_RTMPMUXER_H #define ZLMEDIAKIT_RTMPMUXER_H
#include "RtmpMetedata.h" #include "RtmpMetedata.h"
#include "Player/Frame.h" #include "Extension/Frame.h"
#include "Common/MediaSink.h" #include "Common/MediaSink.h"
namespace mediakit{ namespace mediakit{

View File

@ -32,7 +32,7 @@
#include <unordered_map> #include <unordered_map>
#include "Common/config.h" #include "Common/config.h"
#include "Util/util.h" #include "Util/util.h"
#include "Player/Frame.h" #include "Extension/Frame.h"
using namespace std; using namespace std;
using namespace toolkit; using namespace toolkit;

View File

@ -28,7 +28,7 @@
#define ZLMEDIAKIT_AACRTPCODEC_H #define ZLMEDIAKIT_AACRTPCODEC_H
#include "RtpCodec.h" #include "RtpCodec.h"
#include "Extension/AAC.h"
namespace mediakit{ namespace mediakit{
/** /**
* aac rtp转adts类 * aac rtp转adts类

View File

@ -29,6 +29,7 @@
#include "RtpCodec.h" #include "RtpCodec.h"
#include "Util/ResourcePool.h" #include "Util/ResourcePool.h"
#include "Extension/H264.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit{ namespace mediakit{

View File

@ -0,0 +1,265 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "H265RtpCodec.h"
namespace mediakit{
typedef struct {
unsigned forbidden_zero_bit :1;
unsigned nal_ref_idc :2;
unsigned type :5;
} NALU;
typedef struct {
unsigned S :1;
unsigned E :1;
unsigned R :1;
unsigned type :5;
} FU;
bool MakeNalu(uint8_t in, NALU &nal) {
nal.forbidden_zero_bit = in >> 7;
if (nal.forbidden_zero_bit) {
return false;
}
nal.nal_ref_idc = (in & 0x60) >> 5;
nal.type = in & 0x1f;
return true;
}
bool MakeFU(uint8_t in, FU &fu) {
fu.S = in >> 7;
fu.E = (in >> 6) & 0x01;
fu.R = (in >> 5) & 0x01;
fu.type = in & 0x1f;
if (fu.R != 0) {
return false;
}
return true;
}
H265RtpDecoder::H265RtpDecoder() {
_h265frame = obtainFrame();
}
H265Frame::Ptr H265RtpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<H265Frame>::obtainObj();
frame->buffer.clear();
frame->iPrefixSize = 4;
return frame;
}
bool H265RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) {
key_pos = decodeRtp(rtp);
RtpCodec::inputRtp(rtp, key_pos);
return key_pos;
}
bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
/**
* h265帧类型
* Type==1:P/B frame
* Type==5:IDR frame
* Type==6:SEI frame
* Type==7:SPS frame
* Type==8:PPS frame
*/
const uint8_t *frame = (uint8_t *) rtppack->payload + rtppack->offset;
int length = rtppack->length - rtppack->offset;
NALU nal;
MakeNalu(*frame, nal);
if (nal.type >= 0 && nal.type < 24) {
//a full frame
_h265frame->buffer.assign("\x0\x0\x0\x1", 4);
_h265frame->buffer.append((char *)frame, length);
_h265frame->type = nal.type;
_h265frame->timeStamp = rtppack->timeStamp;
_h265frame->sequence = rtppack->sequence;
auto isIDR = _h265frame->type == 5;
onGetH265(_h265frame);
return (isIDR); //i frame
}
if (nal.type == 28) {
//FU-A
FU fu;
MakeFU(frame[1], fu);
if (fu.S == 1) {
//FU-A start
char tmp = (nal.forbidden_zero_bit << 7 | nal.nal_ref_idc << 5 | fu.type);
_h265frame->buffer.assign("\x0\x0\x0\x1", 4);
_h265frame->buffer.push_back(tmp);
_h265frame->buffer.append((char *)frame + 2, length - 2);
_h265frame->type = fu.type;
_h265frame->timeStamp = rtppack->timeStamp;
_h265frame->sequence = rtppack->sequence;
return (_h265frame->type == 5); //i frame
}
if (rtppack->sequence != (uint16_t)(_h265frame->sequence + 1)) {
_h265frame->buffer.clear();
WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << _h265frame->sequence;
return false;
}
_h265frame->sequence = rtppack->sequence;
if (fu.E == 1) {
//FU-A end
_h265frame->buffer.append((char *)frame + 2, length - 2);
_h265frame->timeStamp = rtppack->timeStamp;
auto isIDR = _h265frame->type == 5;
onGetH265(_h265frame);
return isIDR;
}
//FU-A mid
_h265frame->buffer.append((char *)frame + 2, length - 2);
return false;
}
WarnL << "不支持的rtp类型:" << nal.type << " " << rtppack->sequence;
return false;
// 29 FU-B 单NAL单元B模式
// 24 STAP-A 单一时间的组合包
// 25 STAP-B 单一时间的组合包
// 26 MTAP16 多个时间的组合包
// 27 MTAP24 多个时间的组合包
// 0 udef
// 30 udef
// 31 udef
}
void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) {
//写入环形缓存
RtpCodec::inputFrame(frame);
_h265frame = obtainFrame();
}
////////////////////////////////////////////////////////////////////////
H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc,
uint32_t ui32MtuSize,
uint32_t ui32SampleRate,
uint8_t ui8PlayloadType,
uint8_t ui8Interleaved) :
RtpInfo(ui32Ssrc,
ui32MtuSize,
ui32SampleRate,
ui8PlayloadType,
ui8Interleaved) {
}
void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) {
RtpCodec::inputFrame(frame);
GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Rtp::kCycleMS);
auto pcData = frame->data() + frame->prefixSize();
auto uiStamp = frame->stamp();
auto iLen = frame->size() - frame->prefixSize();
uiStamp %= cycleMS;
int iSize = _ui32MtuSize - 2;
if (iLen > iSize) { //超过MTU
const unsigned char s_e_r_Start = 0x80;
const unsigned char s_e_r_Mid = 0x00;
const unsigned char s_e_r_End = 0x40;
//获取帧头数据1byte
unsigned char naluType = *((unsigned char *) pcData) & 0x1f; //获取NALU的5bit 帧类型
unsigned char nal_ref_idc = *((unsigned char *) pcData) & 0x60; //获取NALU的2bit 帧重要程度 00 可以丢 11不能丢
//nal_ref_idc = 0x60;
//组装FU-A帧头数据 2byte
unsigned char f_nri_type = nal_ref_idc + 28;//F为0 1bit,nri上面获取到2bit,28为FU-A分片类型5bit
unsigned char s_e_r_type = naluType;
bool bFirst = true;
bool mark = false;
int nOffset = 1;
while (!mark) {
if (iLen < nOffset + iSize) { //是否拆分结束
iSize = iLen - nOffset;
mark = true;
s_e_r_type = s_e_r_End + naluType;
} else {
if (bFirst == true) {
s_e_r_type = s_e_r_Start + naluType;
bFirst = false;
} else {
s_e_r_type = s_e_r_Mid + naluType;
}
}
memcpy(_aucSectionBuf, &f_nri_type, 1);
memcpy(_aucSectionBuf + 1, &s_e_r_type, 1);
memcpy(_aucSectionBuf + 2, (unsigned char *) pcData + nOffset, iSize);
nOffset += iSize;
makeH265Rtp(_aucSectionBuf, iSize + 2, mark, uiStamp);
}
} else {
makeH265Rtp(pcData, iLen, true, uiStamp);
}
}
void H265RtpEncoder::makeH265Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) {
uint16_t ui16RtpLen = len + 12;
uint32_t ts = htonl((_ui32SampleRate / 1000) * uiStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
auto rtppkt = ResourcePoolHelper<RtpPacket>::obtainObj();
unsigned char *pucRtp = rtppkt->payload;
pucRtp[0] = '$';
pucRtp[1] = _ui8Interleaved;
pucRtp[2] = ui16RtpLen >> 8;
pucRtp[3] = ui16RtpLen & 0x00FF;
pucRtp[4] = 0x80;
pucRtp[5] = (mark << 7) | _ui8PlayloadType;
memcpy(&pucRtp[6], &sq, 2);
memcpy(&pucRtp[8], &ts, 4);
//ssrc
memcpy(&pucRtp[12], &sc, 4);
//playload
memcpy(&pucRtp[16], data, len);
rtppkt->PT = _ui8PlayloadType;
rtppkt->interleaved = _ui8Interleaved;
rtppkt->mark = mark;
rtppkt->length = len + 16;
rtppkt->sequence = _ui16Sequence;
rtppkt->timeStamp = uiStamp;
rtppkt->ssrc = _ui32Ssrc;
rtppkt->type = TrackVideo;
rtppkt->offset = 16;
uint8_t type = ((uint8_t *) (data))[0] & 0x1F;
RtpCodec::inputRtp(rtppkt,type == 7);
_ui16Sequence++;
_ui32TimeStamp = uiStamp;
}
}//namespace mediakit

View File

@ -0,0 +1,104 @@
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZLMEDIAKIT_H265RTPCODEC_H
#define ZLMEDIAKIT_H265RTPCODEC_H
#include "RtpCodec.h"
#include "Util/ResourcePool.h"
#include "Extension/H265.h"
using namespace toolkit;
namespace mediakit{
/**
* h265 rtp解码类
*/
class H265RtpDecoder : public RtpCodec , public ResourcePoolHelper<H265Frame> {
public:
typedef std::shared_ptr<H265RtpDecoder> Ptr;
H265RtpDecoder();
~H265RtpDecoder() {}
/**
* 265 rtp包
* @param rtp rtp包
* @param key_pos
*/
bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override;
TrackType getTrackType() const override{
return TrackVideo;
}
CodecId getCodecId() const override{
return CodecH265;
}
private:
bool decodeRtp(const RtpPacket::Ptr &rtp);
void onGetH265(const H265Frame::Ptr &frame);
H265Frame::Ptr obtainFrame();
private:
H265Frame::Ptr _h265frame;
};
/**
* 265 rtp打包类
*/
class H265RtpEncoder : public H265RtpDecoder ,public RtpInfo{
public:
typedef std::shared_ptr<H265RtpEncoder> Ptr;
/**
* @param ui32Ssrc ssrc
* @param ui32MtuSize mtu大小
* @param ui32SampleRate 90000
* @param ui8PlayloadType pt类型
* @param ui8Interleaved rtsp interleaved
*/
H265RtpEncoder(uint32_t ui32Ssrc,
uint32_t ui32MtuSize = 1400,
uint32_t ui32SampleRate = 90000,
uint8_t ui8PlayloadType = 96,
uint8_t ui8Interleaved = TrackVideo * 2);
~H265RtpEncoder() {}
/**
* 265
* @param frame
*/
void inputFrame(const Frame::Ptr &frame) override;
private:
void makeH265Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
private:
unsigned char _aucSectionBuf[1600];
};
}//namespace mediakit{
#endif //ZLMEDIAKIT_H265RTPCODEC_H

View File

@ -29,7 +29,7 @@
#include "RtspDemuxer.h" #include "RtspDemuxer.h"
#include "Util/base64.h" #include "Util/base64.h"
#include "H264/SPSParser.h" #include "H264/SPSParser.h"
#include "Common/Factory.h" #include "Extension/Factory.h"
using namespace std; using namespace std;

View File

@ -29,7 +29,6 @@
#include <unordered_map> #include <unordered_map>
#include "Rtsp/Rtsp.h" #include "Rtsp/Rtsp.h"
#include "Player/Player.h"
#include "Player/PlayerBase.h" #include "Player/PlayerBase.h"
#include "Util/TimeTicker.h" #include "Util/TimeTicker.h"
#include "RtspMuxer/RtpCodec.h" #include "RtspMuxer/RtpCodec.h"

View File

@ -25,7 +25,7 @@
*/ */
#include "RtspMuxer.h" #include "RtspMuxer.h"
#include "Common/Factory.h" #include "Extension/Factory.h"
namespace mediakit { namespace mediakit {

View File

@ -28,7 +28,7 @@
#define ZLMEDIAKIT_RTSPMUXER_H #define ZLMEDIAKIT_RTSPMUXER_H
#include "RtspSdp.h" #include "RtspSdp.h"
#include "Player/Frame.h" #include "Extension/Frame.h"
#include "Common/MediaSink.h" #include "Common/MediaSink.h"
namespace mediakit{ namespace mediakit{

View File

@ -24,7 +24,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "RtspSdp.h" #include "RtspSdp.h"
#include "Common/Factory.h" #include "Extension/Factory.h"
namespace mediakit{ namespace mediakit{

View File

@ -29,7 +29,7 @@
#include "RtspMuxer/H264RtpCodec.h" #include "RtspMuxer/H264RtpCodec.h"
#include "RtspMuxer/AACRtpCodec.h" #include "RtspMuxer/AACRtpCodec.h"
#include "Util/base64.h" #include "Util/base64.h"
#include "Player/Track.h" #include "Extension/Track.h"
namespace mediakit { namespace mediakit {