Factory.cpp 9.1 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
#include "RtmpMuxer/H264RtmpCodec.h"
#include "RtmpMuxer/AACRtmpCodec.h"
#include "RtspMuxer/H264RtpCodec.h"
#include "RtspMuxer/AACRtpCodec.h"
32
#include "RtspMuxer/H265RtpCodec.h"
33

xiongziliang committed
34 35
namespace mediakit{

36 37 38 39 40
Sdp::Ptr Factory::getSdpByTrack(const Track::Ptr &track) {
    switch (track->getCodecId()){
        case CodecH264:{
            H264Track::Ptr h264Track = dynamic_pointer_cast<H264Track>(track);
            if(!h264Track){
41 42 43 44 45
                WarnL << "该Track不是H264Track类型";
                return nullptr;
            }
            if(!h264Track->ready()){
                WarnL << "该Track未准备好";
46 47 48 49 50
                return nullptr;
            }
            return std::make_shared<H264Sdp>(h264Track->getSps(),h264Track->getPps());
        }

51 52 53 54 55 56 57 58 59 60
        case CodecH265:{
            H265Track::Ptr h265Track = dynamic_pointer_cast<H265Track>(track);
            if(!h265Track){
                WarnL << "该Track不是H265Track类型";
                return nullptr;
            }
            if(!h265Track->ready()){
                WarnL << "该Track未准备好";
                return nullptr;
            }
xiongziliang committed
61
            return std::make_shared<H265Sdp>(h265Track->getVps(),h265Track->getSps(),h265Track->getPps());
62 63
        }

64 65 66
        case CodecAAC:{
            AACTrack::Ptr aacTrack = dynamic_pointer_cast<AACTrack>(track);
            if(!aacTrack){
67 68 69 70 71
                WarnL << "该Track不是AACTrack类型";
                return nullptr;
            }
            if(!aacTrack->ready()){
                WarnL << "该Track未准备好";
72 73 74 75 76
                return nullptr;
            }
            return std::make_shared<AACSdp>(aacTrack->getAacCfg(),aacTrack->getAudioSampleRate());
        }
        default:
77
            WarnL << "暂不支持的CodecId:" << track->getCodecId();
78 79 80 81 82
            return nullptr;
    }
}


xiongziliang committed
83
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
xiongziliang committed
84
    if (strcasecmp(track->_codec.data(), "mpeg4-generic") == 0) {
xiongziliang committed
85
        string aac_cfg_str = FindField(track->_fmtp.data(), "config=", nullptr);
86
        if (aac_cfg_str.size() != 4) {
xiongziliang committed
87
            aac_cfg_str = FindField(track->_fmtp.data(), "config=", ";");
88 89
        }
        if (aac_cfg_str.size() != 4) {
90 91
            //延后获取adts头
            return std::make_shared<AACTrack>();
92 93 94 95
        }
        string aac_cfg;

        unsigned int cfg1;
xiongziliang committed
96
        sscanf(aac_cfg_str.substr(0, 2).data(), "%02X", &cfg1);
97 98 99 100
        cfg1 &= 0x00FF;
        aac_cfg.push_back(cfg1);

        unsigned int cfg2;
xiongziliang committed
101
        sscanf(aac_cfg_str.substr(2, 2).data(), "%02X", &cfg2);
102 103 104 105 106 107
        cfg2 &= 0x00FF;
        aac_cfg.push_back(cfg2);

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

xiongziliang committed
108
    if (strcasecmp(track->_codec.data(), "h264") == 0) {
xiongziliang committed
109
        string sps_pps = FindField(track->_fmtp.data(), "sprop-parameter-sets=", nullptr);
110 111 112
        if(sps_pps.empty()){
            return std::make_shared<H264Track>();
        }
xiongziliang committed
113 114
        string base64_SPS = FindField(sps_pps.data(), NULL, ",");
        string base64_PPS = FindField(sps_pps.data(), ",", NULL);
115 116 117 118 119 120 121 122 123
        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
124
    if (strcasecmp(track->_codec.data(), "h265") == 0) {
125 126
        //a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA=
        int pt;
xiongziliang committed
127
        char sprop_vps[128] = {0},sprop_sps[128] = {0},sprop_pps[128] = {0};
xiongziliang committed
128
        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
129 130 131 132 133
            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
134
        if (3 == sscanf(track->_fmtp.data(), "%d sprop-sps=%127[^;]; sprop-pps=%127[^;]", &pt,sprop_sps, sprop_pps)) {
xiongziliang committed
135 136 137
            auto sps = decodeBase64(sprop_sps);
            auto pps = decodeBase64(sprop_pps);
            return std::make_shared<H265Track>("",sps,pps,0,0,0);
138
        }
xiongziliang committed
139
        return std::make_shared<H265Track>();
140 141
    }

142 143 144

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

147

148 149 150 151 152
Track::Ptr Factory::getTrackByCodecId(CodecId codecId) {
    switch (codecId){
        case CodecH264:{
            return std::make_shared<H264Track>();
        }
153 154 155
        case CodecH265:{
            return std::make_shared<H265Track>();
        }
156 157 158 159
        case CodecAAC:{
            return std::make_shared<AACTrack>();
        }
        default:
160
            WarnL << "暂不支持该CodecId:" << codecId;
161 162 163 164
            return nullptr;
    }
}

165
RtpCodec::Ptr Factory::getRtpEncoderById(CodecId codecId,
166 167 168 169 170
                                         uint32_t ui32Ssrc,
                                         uint32_t ui32MtuSize,
                                         uint32_t ui32SampleRate,
                                         uint8_t ui8PlayloadType,
                                         uint8_t ui8Interleaved) {
171 172 173
    switch (codecId){
        case CodecH264:
            return std::make_shared<H264RtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
174 175
        case CodecH265:
            return std::make_shared<H265RtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
176 177 178
        case CodecAAC:
            return std::make_shared<AACRtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
        default:
179
            WarnL << "暂不支持该CodecId:" << codecId;
180 181 182 183
            return nullptr;
    }
}

184 185
RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
    switch (track->getCodecId()){
186 187
        case CodecH264:
            return std::make_shared<H264RtpDecoder>();
188 189
        case CodecH265:
            return std::make_shared<H265RtpDecoder>();
190
        case CodecAAC:
191
            return std::make_shared<AACRtpDecoder>(track->clone());
192
        default:
193
            WarnL << "暂不支持该CodecId:" << track->getCodecId();
194 195 196 197
            return nullptr;
    }
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
/////////////////////////////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;
        }
235 236
    }else{
        WarnL << "Metedata不存在相应的Track";
237
    }
238

239 240 241 242
    return CodecInvalid;
}


243 244
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
    switch (track->getCodecId()){
xiongziliang committed
245
        case CodecH264:
246
            return std::make_shared<H264RtmpEncoder>(track);
xiongziliang committed
247
        case CodecAAC:
248
            return std::make_shared<AACRtmpEncoder>(track);
xiongziliang committed
249
        default:
250
            WarnL << "暂不支持该CodecId:" << track->getCodecId();
xiongziliang committed
251 252 253 254
            return nullptr;
    }
}

255 256 257 258 259 260 261 262 263 264 265 266
AMFValue Factory::getAmfByCodecId(CodecId codecId) {
    switch (codecId){
        case CodecAAC:{
            return AMFValue("mp4a");
        }
        case CodecH264:{
            return AMFValue("avc1");
        }
        default:
            return AMFValue(AMF_NULL);
    }
}
267

268

xiongziliang committed
269 270
}//namespace mediakit