Factory.cpp 8.12 KB
Newer Older
1 2 3
/*
 * MIT License
 *
xiongziliang committed
4
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * 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.
 */
26 27

#include "Factory.h"
xiongziliang committed
28 29 30 31 32
#include "H264Rtmp.h"
#include "AACRtmp.h"
#include "H264Rtp.h"
#include "AACRtp.h"
#include "H265Rtp.h"
33

xiongziliang committed
34 35
namespace mediakit{

xiongziliang committed
36
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
xiongziliang committed
37
    if (strcasecmp(track->_codec.data(), "mpeg4-generic") == 0) {
xiongziliang committed
38
        string aac_cfg_str = FindField(track->_fmtp.data(), "config=", nullptr);
39
        if (aac_cfg_str.empty()) {
xiongziliang committed
40
            aac_cfg_str = FindField(track->_fmtp.data(), "config=", ";");
41
        }
42
        if (aac_cfg_str.empty()) {
43 44
            //延后获取adts头
            return std::make_shared<AACTrack>();
45 46 47 48
        }
        string aac_cfg;

        unsigned int cfg1;
xiongziliang committed
49
        sscanf(aac_cfg_str.substr(0, 2).data(), "%02X", &cfg1);
50 51 52 53
        cfg1 &= 0x00FF;
        aac_cfg.push_back(cfg1);

        unsigned int cfg2;
xiongziliang committed
54
        sscanf(aac_cfg_str.substr(2, 2).data(), "%02X", &cfg2);
55 56 57 58 59 60
        cfg2 &= 0x00FF;
        aac_cfg.push_back(cfg2);

        return std::make_shared<AACTrack>(aac_cfg);
    }

xiongziliang committed
61
    if (strcasecmp(track->_codec.data(), "h264") == 0) {
xiongziliang committed
62
        string sps_pps = FindField(track->_fmtp.data(), "sprop-parameter-sets=", nullptr);
63 64 65
        if(sps_pps.empty()){
            return std::make_shared<H264Track>();
        }
xiongziliang committed
66 67
        string base64_SPS = FindField(sps_pps.data(), NULL, ",");
        string base64_PPS = FindField(sps_pps.data(), ",", NULL);
68 69 70 71 72 73 74 75 76
        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);
    }

xiongziliang committed
77
    if (strcasecmp(track->_codec.data(), "h265") == 0) {
78
        //a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA=
zqsong committed
79
        int pt, id;
xiongziliang committed
80
        char sprop_vps[128] = {0},sprop_sps[128] = {0},sprop_pps[128] = {0};
zqsong committed
81 82 83 84 85 86
        if (5 == sscanf(track->_fmtp.data(), "%d profile-id=%d; sprop-sps=%127[^;]; sprop-pps=%127[^;]; sprop-vps=%127[^;]", &pt, &id, sprop_sps,sprop_pps, sprop_vps)) {
            auto vps = decodeBase64(sprop_vps);
            auto sps = decodeBase64(sprop_sps);
            auto pps = decodeBase64(sprop_pps);
            return std::make_shared<H265Track>(vps,sps,pps,0,0,0);
        }
xiongziliang committed
87
        if (4 == sscanf(track->_fmtp.data(), "%d sprop-vps=%127[^;]; sprop-sps=%127[^;]; sprop-pps=%127[^;]", &pt, sprop_vps,sprop_sps, sprop_pps)) {
xiongziliang committed
88 89 90 91 92
            auto vps = decodeBase64(sprop_vps);
            auto sps = decodeBase64(sprop_sps);
            auto pps = decodeBase64(sprop_pps);
            return std::make_shared<H265Track>(vps,sps,pps,0,0,0);
        }
xiongziliang committed
93
        if (3 == sscanf(track->_fmtp.data(), "%d sprop-sps=%127[^;]; sprop-pps=%127[^;]", &pt,sprop_sps, sprop_pps)) {
xiongziliang committed
94 95 96
            auto sps = decodeBase64(sprop_sps);
            auto pps = decodeBase64(sprop_pps);
            return std::make_shared<H265Track>("",sps,pps,0,0,0);
97
        }
xiongziliang committed
98
        return std::make_shared<H265Track>();
99 100
    }

101 102 103

    WarnL << "暂不支持该sdp:" << track->_codec << " " << track->_fmtp;
    return nullptr;
104 105
}

106

107 108 109 110 111
Track::Ptr Factory::getTrackByCodecId(CodecId codecId) {
    switch (codecId){
        case CodecH264:{
            return std::make_shared<H264Track>();
        }
112 113 114
        case CodecH265:{
            return std::make_shared<H265Track>();
        }
115 116 117 118
        case CodecAAC:{
            return std::make_shared<AACTrack>();
        }
        default:
119
            WarnL << "暂不支持该CodecId:" << codecId;
120 121 122 123
            return nullptr;
    }
}

xiongziliang committed
124 125 126
RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
    GET_CONFIG(uint32_t,audio_mtu,Rtp::kAudioMtuSize);
    GET_CONFIG(uint32_t,video_mtu,Rtp::kVideoMtuSize);
xiongziliang committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140
    // ssrc不冲突即可,可以为任意的32位整形
    static atomic<uint32_t> s_ssrc(0);
    uint32_t ssrc = s_ssrc++;
    if(!ssrc){
        //ssrc不能为0
        ssrc = 1;
    }
    if(sdp->getTrackType() == TrackVideo){
        //视频的ssrc是偶数,方便调试
        ssrc = 2 * ssrc;
    }else{
        //音频ssrc是奇数
        ssrc = 2 * ssrc + 1;
    }
xiongziliang committed
141 142 143 144 145 146
    auto mtu = (sdp->getTrackType() == TrackVideo ? video_mtu : audio_mtu);
    auto sample_rate = sdp->getSampleRate();
    auto pt = sdp->getPlayloadType();
    auto interleaved = sdp->getTrackType() * 2;
    auto codec_id = sdp->getCodecId();
    switch (codec_id){
147
        case CodecH264:
xiongziliang committed
148
            return std::make_shared<H264RtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
149
        case CodecH265:
xiongziliang committed
150
            return std::make_shared<H265RtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
151
        case CodecAAC:
xiongziliang committed
152
            return std::make_shared<AACRtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
153
        default:
xiongziliang committed
154
            WarnL << "暂不支持该CodecId:" << codec_id;
155 156 157 158
            return nullptr;
    }
}

159 160
RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
    switch (track->getCodecId()){
161 162
        case CodecH264:
            return std::make_shared<H264RtpDecoder>();
163 164
        case CodecH265:
            return std::make_shared<H265RtpDecoder>();
165
        case CodecAAC:
166
            return std::make_shared<AACRtpDecoder>(track->clone());
167
        default:
168
            WarnL << "暂不支持该CodecId:" << track->getCodecId();
169 170 171 172
            return nullptr;
    }
}

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
/////////////////////////////rtmp相关///////////////////////////////////////////

Track::Ptr Factory::getTrackByAmf(const AMFValue &amf) {
    CodecId codecId = getCodecIdByAmf(amf);
    if(codecId == CodecInvalid){
        return nullptr;
    }
    return getTrackByCodecId(codecId);
}


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;
        }
210 211
    }else{
        WarnL << "Metedata不存在相应的Track";
212
    }
213

214 215 216 217
    return CodecInvalid;
}


218 219
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
    switch (track->getCodecId()){
xiongziliang committed
220
        case CodecH264:
221
            return std::make_shared<H264RtmpEncoder>(track);
xiongziliang committed
222
        case CodecAAC:
223
            return std::make_shared<AACRtmpEncoder>(track);
xiongziliang committed
224
        default:
225
            WarnL << "暂不支持该CodecId:" << track->getCodecId();
xiongziliang committed
226 227 228 229
            return nullptr;
    }
}

230 231 232 233 234 235 236 237 238 239 240 241
AMFValue Factory::getAmfByCodecId(CodecId codecId) {
    switch (codecId){
        case CodecAAC:{
            return AMFValue("mp4a");
        }
        case CodecH264:{
            return AMFValue("avc1");
        }
        default:
            return AMFValue(AMF_NULL);
    }
}
242

243

xiongziliang committed
244 245
}//namespace mediakit