RtmpParser.h 4.76 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * MIT License
xzl committed
3
 *
xiongziliang committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 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.
xzl committed
25 26 27 28 29
 */

#ifndef SRC_RTMP_RTMPPARSER_H_
#define SRC_RTMP_RTMPPARSER_H_

xiongzilaing committed
30 31
#include <functional>
#include <unordered_map>
xzl committed
32
#include "amf.h"
xiongzilaing committed
33
#include "Rtmp.h"
xzl committed
34 35 36
#include "Player/Player.h"
#include "Util/TimeTicker.h"
#include "Player/PlayerBase.h"
xiongzilaing committed
37

xzl committed
38 39 40
using namespace std;
using namespace ZL::Util;
using namespace ZL::Player;
xiongzilaing committed
41

42 43 44
#define H264_CODEC_ID 7
#define AAC_CODEC_ID 10

xzl committed
45 46 47 48 49 50 51 52 53
namespace ZL {
namespace Rtmp {

class RtmpParser : public PlayerBase{
public:
	typedef std::shared_ptr<RtmpParser> Ptr;
	RtmpParser(const AMFValue &val);
	virtual ~RtmpParser();

xiongziliang committed
54
	bool inputRtmp(const RtmpPacket::Ptr &pkt);
xzl committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

	void setOnVideoCB(const function<void(const H264Frame &frame)> &cb) override{
		lock_guard<recursive_mutex> lck(m_mtxCB);
		onVideo = cb;
	}
	void setOnAudioCB(const function<void(const AdtsFrame &frame)> &cb) override{
		lock_guard<recursive_mutex> lck(m_mtxCB);
		onAudio = cb;
	}

	int getVideoHeight() const override{
		return m_iVideoHeight;
	}

	int getVideoWidth() const override{
		return m_iVideoWidth;
	}

	float getVideoFps() const override{
		return m_fVideoFps;
	}

	int getAudioSampleRate() const override{
		return m_iSampleRate;
	}

	int getAudioSampleBit() const override{
		return m_iSampleBit;
	}

	int getAudioChannel() const override{
		return m_iChannel;
	}

	const string& getPps() const override{
		return m_strPPS;
	}

	const string& getSps() const override{
		return m_strSPS;
	}

	const string& getAudioCfg() const override{
		return m_strAudioCfg;
	}
	bool containAudio() const override{
101 102
        //音频只支持aac
		return m_iAudioCodecID == AAC_CODEC_ID;
xzl committed
103 104
	}
	bool containVideo () const override{
105 106
        //视频只支持264
		return m_iVideoCodecID == H264_CODEC_ID;
xzl committed
107 108
	}
	bool isInited() const override{
109 110 111 112 113 114 115 116 117 118
        if((m_iAudioCodecID | m_iVideoCodecID) == 0){
            //音视频codec_id都未获取到,说明还未初始化成功
            return false;
        }
        if((m_iAudioCodecID & m_iVideoCodecID) == 0 && m_ticker.elapsedTime() < 300){
            //音视频codec_id有其一未获取到,且最少分析300ms才能断定没有音频或视频
            return false;
        }
		if (m_iAudioCodecID && !m_strAudioCfg.size()) {
            //如果音频是aac但是还未获取aac config ,则未初始化成功
xzl committed
119 120
			return false;
		}
121 122 123
		if (m_iVideoCodecID && !m_strSPS.size()) {
            //如果视频是h264但是还未获取sps ,则未初始化成功
            return false;
xzl committed
124
		}
125
        //初始化成功
xzl committed
126 127 128 129 130 131 132 133 134
		return true;
	}
	float getDuration() const override{
		return m_fDuration;
	}
private:
	inline void onCheckMedia(const AMFValue &obj);

	//返回值:true 代表是i帧第一个rtp包
xiongziliang committed
135 136
	inline bool inputVideo(const RtmpPacket::Ptr &pkt);
	inline bool inputAudio(const RtmpPacket::Ptr &pkt);
xzl committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
	inline void _onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
	inline void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
	inline void onGetAAC(const char *pcData, int iLen, uint32_t ui32TimeStamp);
	//video
	H264Frame m_h264frame;
	//aduio
	AdtsFrame m_adts;

	int m_iSampleRate = 44100;
	int m_iSampleBit = 16;
	int m_iChannel = 1;

	string m_strSPS;
	string m_strPPS;
	string m_strAudioCfg;
	int m_iVideoWidth = 0;
	int m_iVideoHeight = 0;
	float m_fVideoFps = 0;
155 156 157
    //音视频codec_id初始为0代表尚未获取到
    int m_iAudioCodecID = 0;
    int m_iVideoCodecID = 0;
xzl committed
158
	float m_fDuration = 0;
159 160
    mutable Ticker m_ticker;
    function<void(const H264Frame &frame)> onVideo;
xzl committed
161 162 163
	function<void(const AdtsFrame &frame)> onAudio;
	recursive_mutex m_mtxCB;

164

xzl committed
165 166 167 168 169 170
};

} /* namespace Rtmp */
} /* namespace ZL */

#endif /* SRC_RTMP_RTMPPARSER_H_ */