最近在研究使用开源librtmp库发布flash视频直播流,经过几天的折腾后,写了一个封装调用librtmp的类,时间紧迫没好好整理,仅供需要的朋友参考
头文件:RtmpStream.h
- #pragma once
-
- /// 对开源库rtmpdump的封装
-
- #include
- #include "common.h"
-
- struct RTMP;
- struct RTMPMetadata;
- struct RTMPPacket;
-
- class CRtmpStream
- {
- public:
- CRtmpStream(void);
- virtual ~CRtmpStream(void);
-
- public:
- /// 打开
- BOOL Open(const char * apUrl);
-
- /// 重新打开最近的连接
- BOOL Reopen();
-
- /// 关闭
- void Close();
-
- /// 是否打开
- inline BOOL IsOpened() const
- {
- return m_pHandle != NULL;
- }
-
- /// 发送元数据
- BOOL SendMetadata(const RTMPMetadata & astruMetadata);
-
- /// 发送AAC数据
- BOOL SendAACData(const void * apBuf, const unsigned int auBufLen, const unsigned int auTimestamp);
-
- /// 发送H264数据
- BOOL SendH264Data(const void * apBuf, const unsigned int auBufLen, const unsigned int auTimestamp,
- const BOOL abIsKey, const int aiOffset);
-
- private:
- void CloseStream();
-
- private:
- RTMP * m_pHandle;
- unsigned int m_uStartAudioTime;
- unsigned int m_uStartVideoTime;
- std::string m_strLastUrl;
- CCriticalSectionEx m_oLock;
- BOOL m_bIsLiving;
- };
实现:RtmpStream.cpp
- #include "stdafx.h"
- #include "RtmpStream.h"
- #include "rtmp/rtmp.h"
- #include "rtmp/flvpush.h"
- #include
- #include
-
- static class CInitSocket
- {
- public:
- CInitSocket()
- {
- #ifdef WIN32
- WSADATA wsa_data;
- WORD w_version_requested = MAKEWORD(2, 2);
- if ( WSAStartup(w_version_requested, &wsa_data) != 0 )
- {
- m_bResult = false;
- return;
- }
- //else if ( LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2 )
- //{
- // WSACleanup();
- // return false;
- //}
- #endif
- m_bResult = true;
- }
-
- ~CInitSocket()
- {
- #ifdef WIN32
- if ( m_bResult )
- {
- WSACleanup();
- }
- #endif
- }
-
- bool m_bResult;
-
- } s_oInitSocket;
-
-
- CRtmpStream::CRtmpStream(void)
- : m_pHandle(NULL)
- , m_bIsLiving(FALSE)
- , m_uStartAudioTime(0)
- , m_uStartVideoTime(0)
- {
- }
-
- CRtmpStream::~CRtmpStream(void)
- {
- Close();
- }
-
- BOOL CRtmpStream::Open(const char * apUrl)
- {
- CCriticalSectionHelperEx oDoLock(m_oLock);
-
- if ( m_bIsLiving )
- {
- return FALSE;
- }
-
- if ( IsOpened() )
- {
- return FALSE;
- }
-
- m_pHandle = RTMP_Alloc();
- if ( m_pHandle == NULL )
- {
- assert(FALSE);
- return FALSE;
- }
-
- RTMP_Init(m_pHandle);
-
- if ( !RTMP_SetupURL(m_pHandle, apUrl) )
- {
- Close();
- assert(FALSE);
- return FALSE;
- }
-
- RTMP_EnableWrite(m_pHandle);
-
- if ( !RTMP_Connect(m_pHandle, NULL) )
- {
- Close();
- assert(FALSE);
- return FALSE;
- }
-
- if ( !RTMP_ConnectStream(m_pHandle, 0) )
- {
- Close();
- assert(FALSE);
- return FALSE;
- }
-
- m_bIsLiving = TRUE;
- m_uStartAudioTime = 0;
- m_uStartVideoTime = 0;
-
- if ( m_strLastUrl.c_str() != apUrl )
- {
- m_strLastUrl = apUrl;
- }
-
- return TRUE;
- }
-
- /// 重新打开最近的连接
- BOOL CRtmpStream::Reopen()
- {
- return Open(m_strLastUrl.c_str());
- }
-
- void CRtmpStream::CloseStream()
- {
- if ( m_pHandle != NULL )
- {
- RTMP_Close(m_pHandle);
- ::Sleep(20);
- RTMP_Free(m_pHandle);
- m_pHandle = NULL;
- }
- }
-
- void CRtmpStream::Close()
- {
- CCriticalSectionHelperEx oDoLock(m_oLock);
-
- CloseStream();
-
- m_bIsLiving = FALSE;
- }
-
- /// 发送元数据
- BOOL CRtmpStream::SendMetadata(const RTMPMetadata & astruMetadata)
- {
- if ( !m_bIsLiving )
- {
- return FALSE;
- }
-
- CCriticalSectionHelperEx oDoLock(m_oLock);
-
- if ( !IsOpened() )
- {
- assert(FALSE);
- return FALSE;
- }
-
- if ( !RTMP_SendMetadata(m_pHandle, &astruMetadata) )
- {
- assert(FALSE);
- return FALSE;
- }
-
- return TRUE;
- }
-
- /// 发送AAC数据
- BOOL CRtmpStream::SendAACData(const void * apBuf, const unsigned int auBufLen, const unsigned int auTimestamp)
- {
- if ( !m_bIsLiving )
- {
- return FALSE;
- }
-
- if ( auBufLen == 0 )
- {
- return TRUE;
- }
-
- CCriticalSectionHelperEx oDoLock(m_oLock);
-
- if ( !IsOpened() )
- {
- return TRUE;
- }
-
- unsigned int uCurTimestamp;
- if ( m_uStartAudioTime )
- {
- // 有值
- uCurTimestamp = auTimestamp - m_uStartAudioTime;
- }
- else
- {
- // is 0
- uCurTimestamp = 1;
- m_uStartAudioTime = auTimestamp;
- }
-
- if ( !RTMP_SendAACData(m_pHandle, apBuf, auBufLen, uCurTimestamp) )
- {
- Close();
- Reopen();
-
- assert(FALSE);
- return FALSE;
- }
-
- return TRUE;
- }
-
- /// 发送H264数据
- BOOL CRtmpStream::SendH264Data(const void * apBuf, const unsigned int auBufLen, const unsigned int auTimestamp,
- const BOOL abIsKey, const int aiOffset)
- {
- if ( !m_bIsLiving )
- {
- return FALSE;
- }
-
- if ( auBufLen == 0 )
- {
- return TRUE;
- }
-
-
- CCriticalSectionHelperEx oDoLock(m_oLock);
-
- if ( !IsOpened() )
- {
- return TRUE;
- }
-
- unsigned int uCurTimestamp;
- if ( m_uStartVideoTime )
- {
- // 有值
- uCurTimestamp = auTimestamp - m_uStartVideoTime;
- }
- else
- {
- // is 0
- uCurTimestamp = 1;
- m_uStartVideoTime = auTimestamp;
- }
-
- if ( !RTMP_SendH264Data(m_pHandle, apBuf, auBufLen, uCurTimestamp, abIsKey, aiOffset) )
- {
- Close();
- Reopen();
-
- assert(FALSE);
- return FALSE;
- }
-
- return TRUE;
- }
调用顺序:
1、打开Open
2、发送元数据SendMetadata
3、发送音频AAC数据SendAACData或视频H264数据SendH264Data
4、Close
我的资源里有编译好的静态库和代码(使用mingw gcc编译,VC里也可直接使用)