鑒於很多網友找我要ortp的示例代碼,因此,今天抽空把相關資料整理了一下,寫了一個windows版的ortp示例程序,發布在這裡供網友們參考吧。
編譯及運行環境:VS2008,windows
編程語言:c/c++,ortp庫為c語言封裝,我用c++對其進行了進一步封裝,如果需要c語言的封裝接口,只需要把類中相關函數提取出來即可使用。
ortp庫:ortp-0.9.1由於是以前寫的代碼,故用的ortp庫比較老,但不影響使用和學習,我附件中的工程中已經把ortp-0.9.1庫文件添加進去了)
整個測試代碼在工程的附件中,大家下載後直接編譯後,在Debug目錄下打開2個本程序,一個選擇Client,一個選擇Server,即可看到測試效果。
下面,我的相關代碼發布如下附件中有完整的工程)。
一、ORTP接收端封裝類
- //////////////////////////////////////////////////////////////////////////
- // COPYRIGHT NOTICE
- // Copyright (c) 2011, 華中科技大學 盧俊版權聲明)
- // All rights reserved.
- //
- /// @file CortpClient.h
- /// @brief ortp客戶端類聲明文件
- ///
- /// 實現和提供ortp的客戶端應用接口
- ///
- /// @version 1.0
- /// @author 盧俊
- /// @date 2011/11/03
- //
- //
- // 修訂說明:
- //////////////////////////////////////////////////////////////////////////
- #ifndef CORTPCLIENT_H_
- #define CORTPCLIENT_H_
- #include <ortp/ortp.h>
- #include <string>
- /**
- * COrtpClient ortp客戶端管理類
- *
- * 負責封裝和提供ortp相關接口
- */
- class COrtpClient
- {
- public:
- /** 構造函數/析構函數
- *
- * 在創建/銷毀該類對象時自動調用
- */
- COrtpClient();
- ~COrtpClient();
- /** ORTP模塊的初始化
- *
- * 在整個系統最開始調用,負責ORTP庫的初始化
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- static bool init();
- /** ORTP模塊的逆初始化
- *
- * 在系統退出前調用,負責ORTP庫的釋放
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- static bool deInit();
- /** 創建RTP接收會話
- *
- * 負責產生RTP接收端會話,監聽服務器端的數據
- * @param: const char * localip 本地ip地址
- * @param: int localport 本地監聽端口
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- bool create(const char * localip, int localport );
- /** 獲取接收到的rtp包
- *
- * 將接收到的rtp數據包取出
- * @param: char * pBuffer
- * @param: int & len
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- bool get_recv_data( char *pBuffer, int &len );
- private:
- RtpSession *m_pSession; /** rtp會話句柄 */
- long m_curTimeStamp; /** 當前時間戳 */
- int m_timeStampInc; /** 時間戳增量 */
- };
- #endif // CortpClient_H_
- //////////////////////////////////////////////////////////////////////////
- // COPYRIGHT NOTICE
- // Copyright (c) 2011, 華中科技大學 盧俊版權聲明)
- // All rights reserved.
- //
- /// @file CortpClient.cpp
- /// @brief ortp客戶端類實現文件
- ///
- /// 實現和提供ortp的客戶端應用接口
- ///
- /// @version 1.0
- /// @author lujun
- /// @date 2011/11/03
- //
- //
- // 修訂說明:
- //////////////////////////////////////////////////////////////////////////
- #include "CortpClient.h"
- /* the payload type define */
- #define PAYLOAD_TYPE_VIDEO 34
- /* RTP video Send time stamp increase */
- #define VIDEO_TIME_STAMP_INC 3600
- /** 從rtp接收緩沖區一次讀取的字節數 */
- #define READ_RECV_PER_TIME 1024
- COrtpClient::COrtpClient()
- {
- m_pSession = NULL;
- m_timeStampInc = 0;
- m_curTimeStamp = 0;
- }
- COrtpClient::~COrtpClient()
- {
- if (!m_pSession)
- {
- rtp_session_destroy(m_pSession);
- }
- }
- bool COrtpClient::init()
- {
- int ret;
- WSADATA wsaData;
- /** 初始化winsocket */
- if ( WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
- {
- return false;
- }
- ortp_init();
- ortp_scheduler_init();
- return true;
- }
- bool COrtpClient::deInit()
- {
- ortp_exit();
- if (WSACleanup() == SOCKET_ERROR)
- {
- return false;
- }
- return true;
- }
- bool COrtpClient::create( const char * localip, int localport )
- {
- if ( m_pSession != NULL)
- {
- return false;
- }
- /** 創建新會話 */
- m_pSession = rtp_session_new(RTP_SESSION_RECVONLY);
- if ( !m_pSession)
- {
- return false;
- }
- /** 配置相關參數 */
- rtp_session_set_scheduling_mode(m_pSession,1);
- rtp_session_set_blocking_mode(m_pSession,1);
- rtp_session_set_local_addr(m_pSession,localip,localport);
- rtp_session_enable_adaptive_jitter_compensation(m_pSession,1);
- rtp_session_set_jitter_compensation(m_pSession,40);
- rtp_session_set_payload_type(m_pSession,PAYLOAD_TYPE_VIDEO);
- m_timeStampInc = VIDEO_TIME_STAMP_INC;
- return true;
- }
- bool COrtpClient::get_recv_data( char *pBuffer, int &len )
- {
- int recvBytes = 0;
- int totalBytes = 0;
- int have_more = 1;
- while(have_more)
- {
- if ( totalBytes+READ_RECV_PER_TIME > len )
- {
- /** 緩沖區大小不夠 */
- return false;
- }
- recvBytes = rtp_session_recv_with_ts(m_pSession,pBuffer+totalBytes,READ_RECV_PER_TIME,m_curTimeStamp,&have_more);
- if (recvBytes <= 0)
- {
- break;
- }
- totalBytes += recvBytes;
- }
- /** 判斷是否讀取到數據 */
- if (totalBytes == 0)
- {
- return false;
- }
- /** 記錄有效字節數 */
- len = totalBytes;
- /** 時間戳增加 */
- m_curTimeStamp += m_timeStampInc;
- return true;
- }
二、ORTP發送端封裝類
- //////////////////////////////////////////////////////////////////////////
- // COPYRIGHT NOTICE
- // Copyright (c) 2011, 華中科技大學 盧俊版權聲明)
- // All rights reserved.
- //
- /// @file CortpServer.h
- /// @brief ortp服務器類聲明文件
- ///
- /// 實現和提供ortp的服務器端應用接口
- ///
- /// @version 1.0
- /// @author 盧俊
- /// @date 2011/11/03
- //
- //
- // 修訂說明:
- //////////////////////////////////////////////////////////////////////////
- #ifndef CORTPSERVER_H_
- #define CORTPSERVER_H_
- #include <ortp/ortp.h>
- /**
- * COrtpServer RTP發送類
- *
- * 負責使用RTP協議進行數據的發送
- */
- class COrtpServer
- {
- public:
- /** 構造函數
- *
- * 該函數為該類的構造函數,在創建該類對象時自動調用
- */
- COrtpServer();
- /** 析構函數
- *
- * 該函數執行析構操作,由系統自動調用
- */
- ~COrtpServer();
- /** ORTP模塊的初始化
- *
- * 在整個系統最開始調用,負責ORTP庫的初始化
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- static bool init();
- /** ORTP模塊的逆初始化
- *
- * 在系統退出前調用,負責ORTP庫的釋放
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- static bool deInit();
- /** 創建RTP接收會話
- *
- * 負責產生RTP接收端會話,監聽服務器端的數據
- * @param: const char * destIP 目的地址的IP
- * @param: int destport 目的地址的監聽端口號
- * @return: bool 是否成功
- * @note:
- * @see:
- */
- bool create(const char * destIP, int destport );
- /** 發送RTP數據
- *
- * 將指定的buffer中的數據發送到客戶端
- * @param: unsigned char * buffer 需要發送的數據
- * @param: int len 有效字節數
- * @return: int 實際發送的字節數
- * @note:
- * @see:
- */
- int send_data( unsigned char *buffer, int len );
- private:
- RtpSession *m_pSession; /** rtp會話句柄 */
- long m_curTimeStamp; /** 當前時間戳 */
- int m_timeStampInc; /** 時間戳增量 */
- char *m_ssrc; /** 數據源標識 */
- };
- #endif // COrtpServer_H_
- //////////////////////////////////////////////////////////////////////////
- // COPYRIGHT NOTICE
- // Copyright (c) 2011, 華中科技大學 盧俊版權聲明)
- // All rights reserved.
- //
- /// @file CortpServer.cpp
- /// @brief ortp服務器類實現文件
- ///
- /// 實現和提供ortp的服務器端應用接口
- ///
- /// @version 1.0
- /// @author lujun
- /// @date 2011/11/03
- //
- //
- // 修訂說明:
- //////////////////////////////////////////////////////////////////////////
- #include "COrtpServer.h"
- /* the payload type define */
- #define PAYLOAD_TYPE_VIDEO 34
- /* RTP video Send time stamp increase */
- #define VIDEO_TIME_STAMP_INC 3600
- COrtpServer::COrtpServer()
- {
- m_ssrc = NULL;
- m_pSession = NULL;
- m_timeStampInc = 0;
- m_curTimeStamp = 0;
- }
- COrtpServer::~COrtpServer()
- {
- if (!m_pSession)
- {
- rtp_session_destroy(m_pSession);
- }
- }
- bool COrtpServer::init()
- {
- int ret;
- WSADATA wsaData;
- /** 初始化winsocket */
- if ( WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
- {
- return false;
- }
- ortp_init();
- ortp_scheduler_init();
- return true;
- }
- bool COrtpServer::deInit()
- {
- ortp_exit();
- if (WSACleanup() == SOCKET_ERROR)
- {
- return false;
- }
- return true;
- }
- bool COrtpServer::create( const char * destIP, int destport )
- {
- m_ssrc = getenv("SSRC");
- m_pSession = rtp_session_new(RTP_SESSION_SENDONLY);
- rtp_session_set_scheduling_mode(m_pSession,1);
- rtp_session_set_blocking_mode(m_pSession,1);
- rtp_session_set_remote_addr(m_pSession,destIP,destport);
- if(m_ssrc != NULL)
- {
- rtp_session_set_ssrc(m_pSession,atoi(m_ssrc));
- }
- rtp_session_set_payload_type(m_pSession,PAYLOAD_TYPE_VIDEO);
- m_timeStampInc = VIDEO_TIME_STAMP_INC;
- return true;
- }
- int COrtpServer::send_data( unsigned char *buffer, int len )
- {
- int sendBytes = 0;
- /** 強轉 */
- const char *sendBuffer = (const char*)buffer;
- sendBytes = rtp_session_send_with_ts(m_pSession,sendBuffer,len,m_curTimeStamp);
- if ( sendBytes > 0)
- {
- m_curTimeStamp += m_timeStampInc; /** 增加時間戳 */
- }
- return sendBytes;
- }
三、測試程序
- //////////////////////////////////////////////////////////////////////////
- // COPYRIGHT NOTICE
- // Copyright (c) 2011, 華中科技大學 盧俊 版權聲明)
- // All rights reserved.
- //
- /// @file main.cpp
- /// @brief ortp測試文件
- ///
- /// 測試ortp發送結構體
- ///
- /// @version 1.0
- /// @author 盧俊
- /// @e-mail [email protected]
- /// @date 2011/10/19
- //
- //
- // 修訂說明:
- //////////////////////////////////////////////////////////////////////////
- #include <iostream>
- #include "COrtpClient.h"
- #include "COrtpServer.h"
- /** 本地IP地址 */
- const char * LOCAL_IP_ADDR = "127.0.0.1";
- /** 本地監聽端口 */
- const int LOCAL_RTP_PORT = 8000;
- /** 目的監聽端口 */
- const int DEST_RTP_PORT = 8000;
- /** 目的IP地址 */
- const char * DEST_IP_ADDR = "127.0.0.1";
- /** 一次發送的數據長度 */
- const int SEND_LEN_PER_TIME = 8*1024;
- /** 接收緩沖區的總大小 */
- const int RECV_BUFFER_LEN = 10*1024;
- /** 一次接收的數據長度 */
- const int RECV_LEN_PER_TIME = 1024;
- bool ortpServer()
- {
- COrtpServer ortpServer;
- COrtpServer::init();
- if (!ortpServer.create(DEST_IP_ADDR,DEST_RTP_PORT))
- {
- std::cout << "ortpServer.create fail!\n";
- getchar();
- getchar();
- return false;
- }
- unsigned char * buffer = new unsigned char[SEND_LEN_PER_TIME];
- while (1)
- {
- if ( ortpServer.send_data(buffer,SEND_LEN_PER_TIME) <= 0)
- {
- std::cout << "send fail!\n";
- }
- Sleep(100);
- std::cout << "send bytes\n";
- }
- delete [] buffer;
- COrtpClient::deInit();
- return true;
- }
- bool ortpClient()
- {
- COrtpClient ortpClient;
- COrtpClient::init();
- if (!ortpClient.create(LOCAL_IP_ADDR,LOCAL_RTP_PORT))
- {
- std::cout << "ortpClient.create fail!\n";
- getchar();
- getchar();
- return false;
- }
- char *buffer = new char[RECV_BUFFER_LEN];
- while(1)
- {
- int len = RECV_BUFFER_LEN;
- if (!ortpClient.get_recv_data(buffer,len))
- {
- Sleep(10);
- continue;
- }
- std::cout << "successful recv,data len =" << len << std::endl;
- }
- COrtpClient::deInit();
- delete [] buffer;
- return true;
- }
- void main()
- {
- std::cout << "enter num,1 ->client, 2->server! \n";
- int num;
- std::cin >> num;
- while(1)
- {
- if (num == 1)
- {
- ortpClient();
- break;
- }
- else if (num == 2)
- {
- ortpServer();
- break;
- }
- else
- {
- std::cout << "please input 1 or 2 !\n";
- }
- }
- getchar();
- getchar();
- }
有關ORTP的介紹、RTP的介紹、RTP的負載類型和時間戳的含義等理論性的東西,都可以在我博客中的其他文章中找到,以上就是整個工程的代碼,注釋不是很多,因為有些地方我也不是特別清楚,比如jitter、scheduling什麼的,如果有什麼其他疑問歡迎留言或者E-mail來信交流。
本文出自 “對影成三人” 博客,請務必保留此出處http://ticktick.blog.51cto.com/823160/704891