mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-05 02:38:10 +08:00
整理代码,添加265模板代码
This commit is contained in:
120
src/Extension/AAC.cpp
Normal file
120
src/Extension/AAC.cpp
Normal 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
266
src/Extension/AAC.h
Normal 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;
|
||||
}
|
||||
/**
|
||||
* 返回音频采样位数,一般为16或8
|
||||
* @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:
|
||||
/**
|
||||
* 解析2个字节的aac配置
|
||||
* @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
|
||||
226
src/Extension/Factory.cpp
Normal file
226
src/Extension/Factory.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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 "Factory.h"
|
||||
#include "RtmpMuxer/H264RtmpCodec.h"
|
||||
#include "RtmpMuxer/AACRtmpCodec.h"
|
||||
#include "RtspMuxer/H264RtpCodec.h"
|
||||
#include "RtspMuxer/AACRtpCodec.h"
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
Sdp::Ptr Factory::getSdpByTrack(const Track::Ptr &track) {
|
||||
switch (track->getCodecId()){
|
||||
case CodecH264:{
|
||||
H264Track::Ptr h264Track = dynamic_pointer_cast<H264Track>(track);
|
||||
if(!h264Track){
|
||||
WarnL << "该Track不是H264Track类型";
|
||||
return nullptr;
|
||||
}
|
||||
if(!h264Track->ready()){
|
||||
WarnL << "该Track未准备好";
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<H264Sdp>(h264Track->getSps(),h264Track->getPps());
|
||||
}
|
||||
|
||||
case CodecAAC:{
|
||||
AACTrack::Ptr aacTrack = dynamic_pointer_cast<AACTrack>(track);
|
||||
if(!aacTrack){
|
||||
WarnL << "该Track不是AACTrack类型";
|
||||
return nullptr;
|
||||
}
|
||||
if(!aacTrack->ready()){
|
||||
WarnL << "该Track未准备好";
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<AACSdp>(aacTrack->getAacCfg(),aacTrack->getAudioSampleRate());
|
||||
}
|
||||
default:
|
||||
WarnL << "暂不支持的CodecId:" << track->getCodecId();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
||||
if (strcasestr(track->_codec.data(), "mpeg4-generic") != nullptr) {
|
||||
string aac_cfg_str = FindField(track->_fmtp.c_str(), "config=", "\r\n");
|
||||
if (aac_cfg_str.size() != 4) {
|
||||
aac_cfg_str = FindField(track->_fmtp.c_str(), "config=", ";");
|
||||
}
|
||||
if (aac_cfg_str.size() != 4) {
|
||||
//延后获取adts头
|
||||
return std::make_shared<AACTrack>();
|
||||
}
|
||||
string aac_cfg;
|
||||
|
||||
unsigned int cfg1;
|
||||
sscanf(aac_cfg_str.substr(0, 2).c_str(), "%02X", &cfg1);
|
||||
cfg1 &= 0x00FF;
|
||||
aac_cfg.push_back(cfg1);
|
||||
|
||||
unsigned int cfg2;
|
||||
sscanf(aac_cfg_str.substr(2, 2).c_str(), "%02X", &cfg2);
|
||||
cfg2 &= 0x00FF;
|
||||
aac_cfg.push_back(cfg2);
|
||||
|
||||
return std::make_shared<AACTrack>(aac_cfg);
|
||||
}
|
||||
|
||||
if (strcasestr(track->_codec.data(), "h264") != nullptr) {
|
||||
string sps_pps = FindField(track->_fmtp.c_str(), "sprop-parameter-sets=", "\r\n");
|
||||
if(sps_pps.empty()){
|
||||
return std::make_shared<H264Track>();
|
||||
}
|
||||
string base64_SPS = FindField(sps_pps.c_str(), NULL, ",");
|
||||
string base64_PPS = FindField(sps_pps.c_str(), ",", NULL);
|
||||
if(base64_PPS.back() == ';'){
|
||||
base64_PPS.pop_back();
|
||||
}
|
||||
|
||||
auto sps = decodeBase64(base64_SPS);
|
||||
auto pps = decodeBase64(base64_PPS);
|
||||
return std::make_shared<H264Track>(sps,pps,0,0);
|
||||
}
|
||||
|
||||
WarnL << "暂不支持该sdp:" << track->_codec << " " << track->_fmtp;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
CodecId Factory::getCodecIdByAmf(const AMFValue &val){
|
||||
if (val.type() == AMF_STRING){
|
||||
auto str = val.as_string();
|
||||
if(str == "avc1"){
|
||||
return CodecH264;
|
||||
}
|
||||
if(str == "mp4a"){
|
||||
return CodecAAC;
|
||||
}
|
||||
WarnL << "暂不支持该Amf:" << str;
|
||||
return CodecInvalid;
|
||||
}
|
||||
|
||||
if (val.type() != AMF_NULL){
|
||||
auto type_id = val.as_integer();
|
||||
switch (type_id){
|
||||
case 7:{
|
||||
return CodecH264;
|
||||
}
|
||||
case 10:{
|
||||
return CodecAAC;
|
||||
}
|
||||
default:
|
||||
WarnL << "暂不支持该Amf:" << type_id;
|
||||
return CodecInvalid;
|
||||
}
|
||||
}
|
||||
WarnL << "暂不支持该Amf:" << val.type();
|
||||
return CodecInvalid;
|
||||
}
|
||||
|
||||
Track::Ptr Factory::getTrackByCodecId(CodecId codecId) {
|
||||
switch (codecId){
|
||||
case CodecH264:{
|
||||
return std::make_shared<H264Track>();
|
||||
}
|
||||
case CodecAAC:{
|
||||
return std::make_shared<AACTrack>();
|
||||
}
|
||||
default:
|
||||
WarnL << "暂不支持该CodecId:" << codecId;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Track::Ptr Factory::getTrackByAmf(const AMFValue &amf) {
|
||||
CodecId codecId = getCodecIdByAmf(amf);
|
||||
if(codecId == CodecInvalid){
|
||||
return nullptr;
|
||||
}
|
||||
return getTrackByCodecId(codecId);
|
||||
}
|
||||
|
||||
|
||||
RtpCodec::Ptr Factory::getRtpEncoderById(CodecId codecId,
|
||||
uint32_t ui32Ssrc,
|
||||
uint32_t ui32MtuSize,
|
||||
uint32_t ui32SampleRate,
|
||||
uint8_t ui8PlayloadType,
|
||||
uint8_t ui8Interleaved) {
|
||||
switch (codecId){
|
||||
case CodecH264:
|
||||
return std::make_shared<H264RtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
|
||||
case CodecAAC:
|
||||
return std::make_shared<AACRtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
|
||||
default:
|
||||
WarnL << "暂不支持该CodecId:" << codecId;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RtpCodec::Ptr Factory::getRtpDecoderById(CodecId codecId) {
|
||||
switch (codecId){
|
||||
case CodecH264:
|
||||
return std::make_shared<H264RtpDecoder>();
|
||||
case CodecAAC:
|
||||
return std::make_shared<AACRtpDecoder>();
|
||||
default:
|
||||
WarnL << "暂不支持该CodecId:" << codecId;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
|
||||
switch (track->getCodecId()){
|
||||
case CodecH264:
|
||||
return std::make_shared<H264RtmpEncoder>(track);
|
||||
case CodecAAC:
|
||||
return std::make_shared<AACRtmpEncoder>(track);
|
||||
default:
|
||||
WarnL << "暂不支持该CodecId:" << track->getCodecId();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AMFValue Factory::getAmfByCodecId(CodecId codecId) {
|
||||
switch (codecId){
|
||||
case CodecAAC:{
|
||||
return AMFValue("mp4a");
|
||||
}
|
||||
case CodecH264:{
|
||||
return AMFValue("avc1");
|
||||
}
|
||||
default:
|
||||
return AMFValue(AMF_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
144
src/Extension/Factory.h
Normal file
144
src/Extension/Factory.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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_FACTORY_H
|
||||
#define ZLMEDIAKIT_FACTORY_H
|
||||
|
||||
#include <string>
|
||||
#include "Rtmp/amf.h"
|
||||
#include "Extension/Track.h"
|
||||
#include "RtspMuxer/RtspSdp.h"
|
||||
#include "RtspMuxer/RtpCodec.h"
|
||||
#include "RtmpMuxer/RtmpCodec.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
class Factory {
|
||||
public:
|
||||
|
||||
/**
|
||||
* 根据CodecId获取Track,该Track的ready()状态一般都为false
|
||||
* @param codecId 编解码器id
|
||||
* @return
|
||||
*/
|
||||
static Track::Ptr getTrackByCodecId(CodecId codecId);
|
||||
|
||||
////////////////////////////////rtsp相关//////////////////////////////////
|
||||
/**
|
||||
* 根据sdp生成Track对象
|
||||
*/
|
||||
static Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track);
|
||||
|
||||
/**
|
||||
* 根据Track生成SDP对象
|
||||
* @param track 媒体信息
|
||||
* @return 返回sdp对象
|
||||
*/
|
||||
static Sdp::Ptr getSdpByTrack(const Track::Ptr &track);
|
||||
|
||||
|
||||
/**
|
||||
* 根据CodecId生成Rtp打包器
|
||||
* @param codecId
|
||||
* @param ui32Ssrc
|
||||
* @param ui32MtuSize
|
||||
* @param ui32SampleRate
|
||||
* @param ui8PlayloadType
|
||||
* @param ui8Interleaved
|
||||
* @return
|
||||
*/
|
||||
static RtpCodec::Ptr getRtpEncoderById(CodecId codecId,
|
||||
uint32_t ui32Ssrc,
|
||||
uint32_t ui32MtuSize,
|
||||
uint32_t ui32SampleRate,
|
||||
uint8_t ui8PlayloadType,
|
||||
uint8_t ui8Interleaved);
|
||||
|
||||
/**
|
||||
* 根据CodecId生成Rtp解包器
|
||||
* @param codecId
|
||||
* @param ui32SampleRate
|
||||
* @return
|
||||
*/
|
||||
static RtpCodec::Ptr getRtpDecoderById(CodecId codecId);
|
||||
|
||||
|
||||
////////////////////////////////rtmp相关//////////////////////////////////
|
||||
|
||||
/**
|
||||
* 根据amf对象获取响应的Track
|
||||
* @param amf rtmp metedata中的videocodecid或audiocodecid的值
|
||||
* @return
|
||||
*/
|
||||
static Track::Ptr getTrackByAmf(const AMFValue &amf);
|
||||
|
||||
/**
|
||||
* 根据amf对象获取相应的CodecId
|
||||
* @param val rtmp metedata中的videocodecid或audiocodecid的值
|
||||
* @return
|
||||
*/
|
||||
static CodecId getCodecIdByAmf(const AMFValue &val);
|
||||
|
||||
/**
|
||||
* 根据Track获取Rtmp的编解码器
|
||||
* @param track 媒体描述对象
|
||||
* @return
|
||||
*/
|
||||
static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track);
|
||||
|
||||
|
||||
/**
|
||||
* 根据codecId获取rtmp的codec描述
|
||||
* @param codecId
|
||||
* @return
|
||||
*/
|
||||
static AMFValue getAmfByCodecId(CodecId codecId);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#endif //ZLMEDIAKIT_FACTORY_H
|
||||
293
src/Extension/Frame.h
Normal file
293
src/Extension/Frame.h
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* 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_FRAME_H
|
||||
#define ZLMEDIAKIT_FRAME_H
|
||||
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include "Util/RingBuffer.h"
|
||||
#include "Network/Socket.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
typedef enum {
|
||||
CodecInvalid = -1,
|
||||
CodecH264 = 0,
|
||||
CodecH265,
|
||||
CodecAAC,
|
||||
CodecMax = 0x7FFF
|
||||
} CodecId;
|
||||
|
||||
typedef enum {
|
||||
TrackInvalid = -1,
|
||||
TrackVideo = 0,
|
||||
TrackAudio,
|
||||
TrackTitle,
|
||||
TrackMax = 0x7FFF
|
||||
} TrackType;
|
||||
|
||||
/**
|
||||
* 编码信息的抽象接口
|
||||
*/
|
||||
class CodecInfo {
|
||||
public:
|
||||
typedef std::shared_ptr<CodecInfo> Ptr;
|
||||
|
||||
CodecInfo(){}
|
||||
virtual ~CodecInfo(){}
|
||||
|
||||
/**
|
||||
* 获取音视频类型
|
||||
*/
|
||||
virtual TrackType getTrackType() const = 0;
|
||||
|
||||
/**
|
||||
* 获取编解码器类型
|
||||
*/
|
||||
virtual CodecId getCodecId() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 帧类型的抽象接口
|
||||
*/
|
||||
class Frame : public Buffer, public CodecInfo{
|
||||
public:
|
||||
typedef std::shared_ptr<Frame> Ptr;
|
||||
virtual ~Frame(){}
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
virtual uint32_t stamp() const = 0;
|
||||
|
||||
/**
|
||||
* 前缀长度,譬如264前缀为0x00 00 00 01,那么前缀长度就是4
|
||||
* aac前缀则为7个字节
|
||||
*/
|
||||
virtual uint32_t prefixSize() const = 0;
|
||||
|
||||
/**
|
||||
* 返回是否为关键帧
|
||||
* @return
|
||||
*/
|
||||
virtual bool keyFrame() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 循环池辅助类
|
||||
* @tparam T
|
||||
*/
|
||||
template <typename T>
|
||||
class ResourcePoolHelper{
|
||||
public:
|
||||
ResourcePoolHelper(int size = 8){
|
||||
_pool.setSize(size);
|
||||
}
|
||||
virtual ~ResourcePoolHelper(){}
|
||||
|
||||
std::shared_ptr<T> obtainObj(){
|
||||
return _pool.obtain();
|
||||
}
|
||||
private:
|
||||
ResourcePool<T> _pool;
|
||||
};
|
||||
|
||||
/**
|
||||
* 写帧接口的抽闲接口
|
||||
*/
|
||||
class FrameWriterInterface {
|
||||
public:
|
||||
typedef std::shared_ptr<FrameWriterInterface> Ptr;
|
||||
|
||||
FrameWriterInterface(){}
|
||||
virtual ~FrameWriterInterface(){}
|
||||
/**
|
||||
* 写入帧数据
|
||||
* @param frame 帧
|
||||
*/
|
||||
virtual void inputFrame(const Frame::Ptr &frame) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 写帧接口转function,辅助类
|
||||
*/
|
||||
class FrameWriterInterfaceHelper : public FrameWriterInterface {
|
||||
public:
|
||||
typedef std::shared_ptr<FrameWriterInterfaceHelper> Ptr;
|
||||
typedef std::function<void(const Frame::Ptr &frame)> onWriteFrame;
|
||||
|
||||
/**
|
||||
* inputFrame后触发onWriteFrame回调
|
||||
* @param cb
|
||||
*/
|
||||
FrameWriterInterfaceHelper(const onWriteFrame& cb){
|
||||
_writeCallback = cb;
|
||||
}
|
||||
virtual ~FrameWriterInterfaceHelper(){}
|
||||
/**
|
||||
* 写入帧数据
|
||||
* @param frame 帧
|
||||
*/
|
||||
void inputFrame(const Frame::Ptr &frame) override {
|
||||
_writeCallback(frame);
|
||||
}
|
||||
private:
|
||||
onWriteFrame _writeCallback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 帧环形缓存接口类
|
||||
*/
|
||||
class FrameRingInterface : public FrameWriterInterface{
|
||||
public:
|
||||
typedef RingBuffer<Frame::Ptr> RingType;
|
||||
typedef std::shared_ptr<FrameRingInterface> Ptr;
|
||||
|
||||
FrameRingInterface(){}
|
||||
virtual ~FrameRingInterface(){}
|
||||
|
||||
/**
|
||||
* 获取帧环形缓存
|
||||
* @return
|
||||
*/
|
||||
virtual RingType::Ptr getFrameRing() const = 0;
|
||||
|
||||
/**
|
||||
* 设置帧环形缓存
|
||||
* @param ring
|
||||
*/
|
||||
virtual void setFrameRing(const RingType::Ptr &ring) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 帧环形缓存
|
||||
*/
|
||||
class FrameRing : public FrameRingInterface{
|
||||
public:
|
||||
typedef std::shared_ptr<FrameRing> Ptr;
|
||||
|
||||
FrameRing(){
|
||||
}
|
||||
virtual ~FrameRing(){}
|
||||
|
||||
/**
|
||||
* 获取帧环形缓存
|
||||
* @return
|
||||
*/
|
||||
RingType::Ptr getFrameRing() const override {
|
||||
return _frameRing;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置帧环形缓存
|
||||
* @param ring
|
||||
*/
|
||||
void setFrameRing(const RingType::Ptr &ring) override {
|
||||
_frameRing = ring;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入数据帧
|
||||
* @param frame
|
||||
*/
|
||||
void inputFrame(const Frame::Ptr &frame) override{
|
||||
if(_frameRing){
|
||||
_frameRing->write(frame,frame->keyFrame());
|
||||
}
|
||||
}
|
||||
protected:
|
||||
RingType::Ptr _frameRing;
|
||||
};
|
||||
|
||||
/**
|
||||
* 支持代理转发的帧环形缓存
|
||||
*/
|
||||
class FrameRingInterfaceDelegate : public FrameRing {
|
||||
public:
|
||||
typedef std::shared_ptr<FrameRingInterfaceDelegate> Ptr;
|
||||
|
||||
FrameRingInterfaceDelegate(){}
|
||||
virtual ~FrameRingInterfaceDelegate(){}
|
||||
|
||||
void addDelegate(const FrameWriterInterface::Ptr &delegate){
|
||||
lock_guard<mutex> lck(_mtx);
|
||||
_delegateMap.emplace(delegate.get(),delegate);
|
||||
}
|
||||
|
||||
void delDelegate(void *ptr){
|
||||
lock_guard<mutex> lck(_mtx);
|
||||
_delegateMap.erase(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入帧数据
|
||||
* @param frame 帧
|
||||
*/
|
||||
void inputFrame(const Frame::Ptr &frame) override{
|
||||
FrameRing::inputFrame(frame);
|
||||
lock_guard<mutex> lck(_mtx);
|
||||
for(auto &pr : _delegateMap){
|
||||
pr.second->inputFrame(frame);
|
||||
}
|
||||
}
|
||||
private:
|
||||
mutex _mtx;
|
||||
map<void *,FrameWriterInterface::Ptr> _delegateMap;
|
||||
};
|
||||
|
||||
class FrameNoCopyAble : public Frame{
|
||||
public:
|
||||
typedef std::shared_ptr<FrameNoCopyAble> Ptr;
|
||||
char *data() const override{
|
||||
return buffer_ptr;
|
||||
}
|
||||
uint32_t size() const override {
|
||||
return buffer_size;
|
||||
}
|
||||
uint32_t stamp() const override {
|
||||
return timeStamp;
|
||||
}
|
||||
uint32_t prefixSize() const override{
|
||||
return iPrefixSize;
|
||||
}
|
||||
public:
|
||||
char *buffer_ptr;
|
||||
uint32_t buffer_size;
|
||||
uint32_t timeStamp;
|
||||
uint32_t iPrefixSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#endif //ZLMEDIAKIT_FRAME_H
|
||||
56
src/Extension/H264.cpp
Normal file
56
src/Extension/H264.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 "H264.h"
|
||||
#include "H264/SPSParser.h"
|
||||
#include "Util/logger.h"
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
|
||||
280
src/Extension/H264.h
Normal file
280
src/Extension/H264.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* 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_H264_H
|
||||
#define ZLMEDIAKIT_H264_H
|
||||
|
||||
#include "Frame.h"
|
||||
#include "Track.h"
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 264视频通道
|
||||
*/
|
||||
class H264Track : public VideoTrack{
|
||||
public:
|
||||
typedef std::shared_ptr<H264Track> Ptr;
|
||||
|
||||
/**
|
||||
* 不指定sps pps构造h264类型的媒体
|
||||
* 在随后的inputFrame中获取sps pps
|
||||
*/
|
||||
H264Track(){}
|
||||
/**
|
||||
* 构造h264类型的媒体
|
||||
* @param sps sps帧数据
|
||||
* @param pps pps帧数据
|
||||
* @param sps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||
* @param pps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||
*/
|
||||
H264Track(const string &sps,const string &pps,int sps_prefix_len = 4,int pps_prefix_len = 4){
|
||||
_sps = sps.substr(sps_prefix_len);
|
||||
_pps = pps.substr(pps_prefix_len);
|
||||
parseSps(_sps);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造h264类型的媒体
|
||||
* @param sps sps帧
|
||||
* @param pps pps帧
|
||||
*/
|
||||
H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps){
|
||||
if(sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264 ){
|
||||
throw std::invalid_argument("必须输入H264类型的帧");
|
||||
}
|
||||
_sps = string(sps->data() + sps->prefixSize(),sps->size() - sps->prefixSize());
|
||||
_pps = string(pps->data() + pps->prefixSize(),pps->size() - pps->prefixSize());
|
||||
parseSps(_sps);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回不带0x00 00 00 01头的sps
|
||||
* @return
|
||||
*/
|
||||
const string &getSps() const{
|
||||
return _sps;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回不带0x00 00 00 01头的pps
|
||||
* @return
|
||||
*/
|
||||
const string &getPps() const{
|
||||
return _pps;
|
||||
}
|
||||
|
||||
CodecId getCodecId() const override {
|
||||
return CodecH264;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回视频高度
|
||||
* @return
|
||||
*/
|
||||
int getVideoHeight() const override{
|
||||
return _width;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回视频宽度
|
||||
* @return
|
||||
*/
|
||||
int getVideoWidth() const override{
|
||||
return _height;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回视频fps
|
||||
* @return
|
||||
*/
|
||||
float getVideoFps() const override{
|
||||
return _fps;
|
||||
}
|
||||
|
||||
bool ready() override {
|
||||
return !_sps.empty() && !_pps.empty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 输入数据帧,并获取sps pps
|
||||
* @param frame 数据帧
|
||||
*/
|
||||
void inputFrame(const Frame::Ptr &frame) override{
|
||||
int type = (*((uint8_t *)frame->data() + frame->prefixSize())) & 0x1F;
|
||||
switch (type){
|
||||
case 7:{
|
||||
//sps
|
||||
bool flag = _sps.empty();
|
||||
_sps = string(frame->data() + frame->prefixSize(),frame->size() - frame->prefixSize());
|
||||
if(flag && _width == 0){
|
||||
parseSps(_sps);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:{
|
||||
//pps
|
||||
_pps = string(frame->data() + frame->prefixSize(),frame->size() - frame->prefixSize());
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:{
|
||||
//I
|
||||
if(!_sps.empty()){
|
||||
if(!_spsFrame)
|
||||
{
|
||||
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
||||
insertFrame->type = 7;
|
||||
insertFrame->timeStamp = frame->stamp();
|
||||
insertFrame->buffer.assign("\x0\x0\x0\x1",4);
|
||||
insertFrame->buffer.append(_sps);
|
||||
insertFrame->iPrefixSize = 4;
|
||||
_spsFrame = insertFrame;
|
||||
}
|
||||
_spsFrame->timeStamp = frame->stamp();
|
||||
VideoTrack::inputFrame(_spsFrame);
|
||||
}
|
||||
|
||||
if(!_pps.empty()){
|
||||
if(!_ppsFrame)
|
||||
{
|
||||
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
||||
insertFrame->type = 8;
|
||||
insertFrame->timeStamp = frame->stamp();
|
||||
insertFrame->buffer.assign("\x0\x0\x0\x1",4);
|
||||
insertFrame->buffer.append(_pps);
|
||||
insertFrame->iPrefixSize = 4;
|
||||
_ppsFrame = insertFrame;
|
||||
}
|
||||
_ppsFrame->timeStamp = frame->stamp();
|
||||
VideoTrack::inputFrame(_ppsFrame);
|
||||
}
|
||||
VideoTrack::inputFrame(frame);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:{
|
||||
//B or P
|
||||
VideoTrack::inputFrame(frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* 解析sps获取宽高fps
|
||||
* @param sps sps不含头数据
|
||||
*/
|
||||
void parseSps(const string &sps){
|
||||
getAVCInfo(sps,_width,_height,_fps);
|
||||
}
|
||||
Track::Ptr clone() override {
|
||||
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
|
||||
}
|
||||
private:
|
||||
string _sps;
|
||||
string _pps;
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
float _fps = 0;
|
||||
H264Frame::Ptr _spsFrame;
|
||||
H264Frame::Ptr _ppsFrame;
|
||||
};
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
|
||||
#endif //ZLMEDIAKIT_H264_H
|
||||
33
src/Extension/H265.cpp
Normal file
33
src/Extension/H265.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 "H265.h"
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
104
src/Extension/H265.h
Normal file
104
src/Extension/H265.h
Normal 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
130
src/Extension/Track.h
Normal 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;
|
||||
|
||||
/**
|
||||
* 返回音频采样位数,一般为16或8
|
||||
* @return
|
||||
*/
|
||||
virtual int getAudioSampleBit() const = 0;
|
||||
|
||||
/**
|
||||
* 返回音频通道数
|
||||
* @return
|
||||
*/
|
||||
virtual int getAudioChannel() const = 0;
|
||||
};
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#endif //ZLMEDIAKIT_TRACK_H
|
||||
Reference in New Issue
Block a user