GB28181Process.cpp 4.08 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2 3
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
 *
4
 * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
xiongziliang committed
5 6 7 8 9 10 11 12 13 14 15
 *
 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
 */

#if defined(ENABLE_RTPPROXY)
#include "GB28181Process.h"
#include "Util/File.h"
#include "Http/HttpTSPlayer.h"
#include "Extension/CommonRtp.h"
16
#include "Extension/H264Rtp.h"
xiongziliang committed
17 18 19 20

namespace mediakit{

//判断是否为ts负载
21
static inline bool checkTS(const uint8_t *packet, size_t bytes){
xiongziliang committed
22 23 24 25 26 27 28 29 30 31 32
    return bytes % TS_PACKET_SIZE == 0 && packet[0] == TS_SYNC_BYTE;
}

GB28181Process::GB28181Process(const MediaInfo &media_info, MediaSinkInterface *interface) {
    assert(interface);
    _media_info = media_info;
    _interface = interface;
}

GB28181Process::~GB28181Process() {}

33
bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
xiongziliang committed
34 35 36 37
    return handleOneRtp(0, TrackVideo, 90000, (unsigned char *) data, data_len);
}

void GB28181Process::onRtpSorted(const RtpPacket::Ptr &rtp, int) {
xiongziliang committed
38
    auto pt = rtp->getHeader()->pt;
xiongziliang committed
39
    if (!_rtp_decoder) {
xiongziliang committed
40
        switch (pt) {
41 42 43 44 45 46 47
            case 98: {
                //H264负载
                _rtp_decoder = std::make_shared<H264RtpDecoder>();
                _interface->addTrack(std::make_shared<H264Track>());
                break;
            }
            default: {
xiongziliang committed
48 49
                if (pt != 33 && pt != 96) {
                    WarnL << "rtp payload type未识别(" << (int) pt << "),已按ts或ps负载处理";
50
                }
xiongziliang committed
51
                //ts或ps负载
52
                _rtp_decoder = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);
xiongziliang committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
                //设置dump目录
                GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
                if (!dump_dir.empty()) {
                    auto save_path = File::absolutePath(_media_info._streamid + ".mp2", dump_dir);
                    _save_file_ps.reset(File::create_file(save_path.data(), "wb"), [](FILE *fp) {
                        if (fp) {
                            fclose(fp);
                        }
                    });
                }
                break;
            }
        }

        //设置frame回调
        _rtp_decoder->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([this](const Frame::Ptr &frame) {
            onRtpDecode(frame);
        }));
    }

    //解码rtp
    _rtp_decoder->inputRtp(rtp, false);
}

77
const char *GB28181Process::onSearchPacketTail(const char *packet,size_t bytes){
xiongziliang committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    try {
        auto ret = _decoder->input((uint8_t *) packet, bytes);
        if (ret > 0) {
            return packet + ret;
        }
        return nullptr;
    } catch (std::exception &ex) {
        InfoL << "解析ps或ts异常: bytes=" << bytes
              << " ,exception=" << ex.what()
              << " ,hex=" << hexdump((uint8_t *) packet, bytes);
        if (remainDataSize() > 256 * 1024) {
            //缓存太多数据无法处理则上抛异常
            throw;
        }
        return nullptr;
    }
}

void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
97 98 99 100 101 102
    if (frame->getCodecId() == CodecH264) {
        //这是H264
        _interface->inputFrame(frame);
        return;
    }

xiongziliang committed
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    //这是TS或PS
    if (_save_file_ps) {
        fwrite(frame->data(), frame->size(), 1, _save_file_ps.get());
    }

    if (!_decoder) {
        //创建解码器
        if (checkTS((uint8_t *) frame->data(), frame->size())) {
            //猜测是ts负载
            InfoL << _media_info._streamid << " judged to be TS";
            _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
        } else {
            //猜测是ps负载
            InfoL << _media_info._streamid << " judged to be PS";
            _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
        }
    }

    if (_decoder) {
        HttpRequestSplitter::input(frame->data(), frame->size());
    }
}

}//namespace mediakit
127
#endif//defined(ENABLE_RTPPROXY)