树莓派sip视频电话-1:exosip2ctype+python使用硬件编解码

0.树莓派实现视频电话功能

树莓派python环境下可使用的模块有:pjsip,linphone,exosip2ctypesp,sipsimple

(1)pjsip(pjsua2+python)功能强大,但api较多,视频例子较少。主要是看到使用pjsip传输已经编码的视频,源码在github这篇文章,考虑到可以使用omx硬件编解码,但努力了几天,未成功。

(2)linphone有专门的raspberry的python模块,但没有实现omx硬件编解码,视频编码方式只有vp8,遗憾的放弃。

(3)exosip2ctypesp,是libexosip2的python封装,功能较简单,主要实现的是sip协议,rtp,编解码等未包含。根据exapmle中 代码修改,初步实现了树莓派sip客户端使用omx硬件编解码。依赖库太多了!!!

(4)sipsimple,没有安装成功。

-------------------------------------------------

1.安装python下的sip模块:exosip2ctypes

(1)sudo apt-get  install libexosip2

(2)依赖库较多,需使用python虚拟环境。virtualenv

           pip install virtualenv      安装虚拟环境

           virtualenv venv              创建虚拟环境

           source venv/bin/active 进入虚拟环境nm

(3)虚拟环境下,在源码包中pip install -r requirements-dev-lt_3.2.txt   安装依赖库,总之太多了。

(4)安装exosip2ctypes  python setup.py install

2.修改exosip2ctypes源代码;

(1)错误1:context.py

 def start(self, s=0, ms=50, event_executor=None):

        self.logger.info('<0x%x>start: >>> s=%s, ms=%s', id(self), s, ms)
        if self._is_running:
            raise RuntimeError("Context loop already started.")
        self._event_executor = event_executor or ThreadPoolExecutor()   =>   self._event_executor = event_executor or ThreadPoolExecutor(2)

(2)错误2:context.py

class Context(BaseContext, LoggerMixin):
    def __init__(self, event_callback=None):     =>def __init__(self, event_callback=None,contact_address=None):

(3)错误3:message.py

class OsipMessage:   =>  class OsipMessage(object):

3.树莓派代码

pc上安装ekiga软件与树莓派python程序建立视频通话:

(1)ekiga呼叫树莓派,先输入180回铃

(2)发送rtp视频编码: 这里使用了Camkit这个工具,github上有,感谢作者。需根据远端的sdp信息进行修改端口和IP地址。如果传过来的pt不为96,需修改rtppack这个文件。

(3)接受rtp视频编码:根据本端的sdp信息,创建sdp文件,使用omxplayer 播放这个sdp文件。

(4)输入200,建立链接。这时pc 上可以看到远端视频。

(5)问题1:omxplayer播放花屏,卡顿,不是带宽的问题,未知。

          问题2:暂时没有实现树莓派音频采集/编码/打包/发送,下步再研究。


import sys
import logging
import logging.config

from exosip2ctypes import initialize, Context, call, EventType

logging.basicConfig(
    level=logging.DEBUG, stream=sys.stdout,
    format='%(asctime)-15s [%(threadName)-10s] [%(levelname)-7s] %(name)s - %(message)s'
)

latest_event = None


def on_exosip_event(context, evt):
    global latest_event
    latest_event = evt

    if evt.type == EventType.call_invite:
        print('**********************************************************************************')
        logging.debug('[%s] on_call_invite', evt.did)
        logging.debug('call-id: %s', evt.request.call_id)
        # logging.debug("%s" % evt.request)
        logging.debug('[%s] from: %s', evt.did, evt.request.from_)
        logging.debug('[%s] allows: %s', evt.did, evt.request.allows)
        logging.debug('[%s] contacts: %s', evt.did, evt.request.contacts)
        for hname in ('User-Agent',):
            logging.debug('[%s] header["%s"]: %s', evt.did, hname, evt.request.get_headers(hname))

        print('**********************************************************************************')
        logging.debug('body: %s', evt.request.bodies[0])
        print('**********************************************************************************')
        logging.debug('body: %s', evt.request.bodies)
        print('**********************************************************************************')

    elif evt.type == EventType.call_cancelled:
        logging.debug('[%s] call_cancelled', evt.did)

    elif evt.type == EventType.call_closed:
        logging.debug('[%s] call_closed', evt.did)


initialize()
ctx = Context(event_callback=on_exosip_event)
# ctx.event_callback = on_exosip_event
#ctx.masquerade_contact('192.168.1.132', 5066)

print('listening...')
ctx.listen_on_address(address='192.168.1.132', port=5066)
print('starting...')

ctx.start()
print('started!')

while True:
    s = sys.stdin.readline().strip().lower()
    if s in ('q', 'quit'):
        ctx.stop()
        break
    elif s == 'ack':
        with ctx.lock:
            ctx.call_send_ack(latest_event.did)
    elif s in ('t', 'terminate'):
        with ctx.lock:
            ctx.call_terminate(latest_event.cid, latest_event.did)
    elif s.isdigit():
        status = int(s)
        if status == 200:
            with ctx.lock:
                msg = call.Answer(ctx, latest_event.tid, 200)
                msg.content_type = 'application/sdp'
                msg.add_body(
                    "v=0\r\n"
                    "o=- 0 0 IN IP4 192.168.1.132\r\n"
                    "s=No Name\r\n"
                    "c=IN IP4 192.168.1.132\r\n"
                    "t=0 0\r\n"
                    "a=tool:libavformat 57.25.10\r\n"
                    "m=audio 54000 RTP/AVP 0 8 101\r\n"
                    "a=rtpmap:0 PCMU/8000\r\n"
                    "a=rtpmap:8 PCMA/8000\r\n"
                    "a=rtpmap:101 telephone-event/8000\r\n"
                    "m=video 4002 RTP/AVP 96\r\n"
                    "a=rtpmap:96 H264/90000\r\n"
                   
                )
#                    "a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z01AM5p0FCNCAAEEugA9CQEeMGVA,aO48gA==; profile-level-id=4D4033\r\n"
#                    "a=fmtp:96 packetization-mode=1; sprop-parameter-sets=J01AKakYDwBE/LgDUBAQG2wrXvfAQA==,KN4JyA==; profile-level-id=4D4029\r\n"
#./ffmpeg -re -i 1.h264 -vcodec copy -f rtp -payload_type 103 rtp://192.168.1.132:5056
#ffplay -vcodec h264_mmal
                ctx.call_send_answer(answer=msg)
        else:
            with ctx.lock:
                ctx.call_send_answer(latest_event.tid, status)




  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在基于GBT28181的SIP协议组件开发中,SIP服务端流程是非常关键的一部分。本文将介绍如何使用eXosip2实现SIP服务端流程。 一、eXosip2简介 eXosip2是一个基于SIP标准的开源协议栈,它提供了一组API,可以用来实现SIP客户端和服务端。eXosip2具有高度的可移植性和灵活性,可以在不同平台上运行。eXosip2的主要特点包括: 1. 遵循SIP标准,功能齐全。 2. 支持IPv4和IPv6协议栈。 3. 支持TLS和SRTP协议。 4. 提供了一组易于使用的API,方便开发人员进行二次开发。 5. 可以在不同的平台上运行,包括Linux、Windows、Android等。 二、eXosip2的使用 1. 安装eXosip2库 首先需要安装eXosip2库,可以通过以下命令在Ubuntu下安装: sudo apt-get install libexosip2-dev 2. 初始化eXosip2 在使用eXosip2之前,需要初始化eXosip2库,这可以通过调用eXosip_init函数来实现。例如: eXosip_t *g_eXosipContext=NULL; g_eXosipContext = eXosip_malloc(); if (g_eXosipContext!=NULL) { iRet = eXosip_init(g_eXosipContext); } 3. 注册SIP服务器 使用eXosip2可以实现SIP服务器的注册,这可以通过调用eXosip_register_build函数构造注册消息,然后通过调用eXosip_register_send发送注册消息。例如: eXosip_event_t *pEvent = NULL; osip_message_t *pMsg = NULL; int iRet = 0; iRet = eXosip_register_build_initial_register(g_eXosipContext, "sip:192.168.1.100", "sip:192.168.1.100", "sip:192.168.1.100", 3600, &pMsg); if (iRet == 0) { iRet = eXosip_register_send_register(g_eXosipContext, pMsg); osip_message_free(pMsg); } 4. 接收SIP消息 使用eXosip2可以接收SIP消息,这可以通过调用eXosip_listen函数实现。例如: while (1) { iRet = eXosip_listen(g_eXosipContext, 0, &pEvent); if (iRet >= 0) { switch (pEvent->type) { case EXOSIP_REGISTRATION_SUCCESS: // 注册成功 break; case EXOSIP_REGISTRATION_FAILURE: // 注册失败 break; case EXOSIP_MESSAGE_NEW: // 收到新的SIP消息 break; } eXosip_event_free(pEvent); } } 5. 回复SIP消息 使用eXosip2可以回复SIP消息,这可以通过调用eXosip_message_build_response函数构造回复消息,然后通过调用eXosip_message_send_response发送回复消息。例如: osip_message_t *pMsg = NULL; int iRet = 0; iRet = eXosip_message_build_response(pEvent->tid, 200, &pMsg); if (iRet == 0) { iRet = eXosip_message_send_response(g_eXosipContext, pEvent->tid, 200, pMsg); osip_message_free(pMsg); } 三、总结 本文介绍了如何使用eXosip2实现SIP服务端流程。eXosip2是一个功能齐全、易于使用SIP协议栈,可以方便地实现SIP客户端和服务端。在GBT28181的SIP协议组件开发中,eXosip2是一个非常好的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值