精华内容
下载资源
问答
  • 一、quote(string[, safe])它返回一个字符串,其中所有的特殊字符都已被对URL友好的字符所代替(就像用%7E代替了~)举例:假设接口测试中,要向一个url发送一串json格式的报文,服务器要接收时会对json数据进行解析,...

    Python2 中urllib模块提供了一些函数操作URL本身。

    一、quote(string[, safe])

    它返回一个字符串,其中所有的特殊字符都已被对URL友好的字符所代替(就像用%7E代替了~)

    举例:假设接口测试中,要向一个url发送一串json格式的报文,服务器要接收时会对json数据进行解析,如果报文中有%@*?等特殊字符,很有可能服务器接收并解析后就不合法 出现空格等,我们可以使用这个函数将json数据编码。

    它对应的解码是unquote(string)。(结果跟网页版的urlencode是一样的)。

    二、quote_plus(string[,safe])。

    功能和quote差不多,但用+代替空格。对应的解码函数是unquote_plus(string)

    三、urlencode(query[,doseq])

    把映射(比如字典)或者包含两个元素的元组的序列——(key,value)这种形式——转换成URL格式编码的字符串,这样的字符串可以在CGI查询中使用。

    举例:当url地址含有中文,或者参数有中文的时候,url作为参数传递,需要处理一下。

    >> data ={'No': '01', 'Name': '燕子'}

    >> print(urlencode(data))

    结果:

    >>Name=%E7%87%95%E5%AD%90&No=01

    注意 它对应的解码 是没有decode函数的,对应的还是unquote(string)

    >>unquote("%E7%87%95%E5%AD%90")

    结果 >>燕子

    (python3中,以上介绍的函数在urllib.parse模块中)

    展开全文
  • LI代码的格式化:A).运用CSS格式化列表符: ul li{list-style-type:none;...list-style-image: url(/blog/images/icon.gif);}C).为了左对齐,可以用如下代码: ul{list-style-type:none;margin:0px;}D...

    LI代码的格式化:

    A).运用CSS格式化列表符: ul li{

    list-style-type:none;

    }

    B).如果你想将列表符换成图像,则: ul li{

    list-style-type:none;

    list-style-image: url(/blog/images/icon.gif);

    }

    C).为了左对齐,可以用如下代码: ul{

    list-style-type:none;

    margin:0px;

    }

    D).如果想给列表加背景色,可以用如下代码: ul{

    list-style-type: none;

    margin:0px;

    }

    ul li{

    background:#CCC;

    }

    E).如果想给列表加MOUSEOVER背景变色效果,可以用如下代码: ul{ list-style-type: none; margin:0px; }

    ul li a{ display:block; width: 100%; background:#ccc; }

    ul li a:hover{ background:#999; }说明:display:block;这一行必须要加的,这样才能块状显示!

    F).LI中的元素水平排列,关键FLOAT:LEFT: ul{

    list-style-type:none;

    width:100%;

    }

    ul li{

    width:80px;

    float:left;

    }

    • 的区别
    • 的参数设定(常用):

      例如:

    • type="square"

      只适用于非顺序清单,设定符号款式,其值有三种,如下,内定为 type="disc":

      符号 是当 type="disc" 时的列项符号。

      符号 if" width=10 height=10 border=0> 是当 type="circle" 时的列项符号。

      符号 是当 type="square" 时的列项符号。

      value="4"

      只适用于顺序清单,设定该一项的数目,其後各项将以此作为起始数目而递增,但前面各项则不受影响,其值只能是 1,2,3.. 等整数,没有内定值。

      • 称为无序清单标记。

      所谓无序清单就是在每一项前面加上 、、等符号,故又称符号清单。

      • 的参数设定(常用):

      例如:

      type="square"

      设定符号款式,其值有三种,如下,内定为 type="disc":

      符号 是当 type="disc" 时的列项符号。

      符号 是当 type="circle" 时的列项符号。

      符号 是当 type="square" 时的列项符号。

      • 是项目列表,
      • 是列表项,项目列表就是用符号来列的,所以你列出来默认的就是黑点啦,还有一个是
        1. 这个是编号列表,用数字来列的,也是用
        2. 做列表项
        3. 是 list item 即列表项,但列表有很两种,所以外面得有
          • 或者
          1. 用来区别无序列表(小点点)和有序列表(1,2,3...)。
    展开全文
  • 海康RTSP取流URL格式一、预览取流设备预览取流的RTSP URL有新老版本,2012年之前的设备(比如V2.0版本的Netra设备)支持老的取流格式,之后的设备新老取流格式都支持。老版本URL规定:rtsp://username:password@//ch/...

    海康RTSP取流URL格式

    一、预览取流

    设备预览取流的RTSP URL有新老版本,2012年之前的设备(比如V2.0版本的Netra设备)支持老的取流格式,之后的设备新老取流格式都支持。

    老版本

    URL规定:

    rtsp://username:password@//ch/

    注:VLC可以支持解析URL里的用户名密码,实际发给设备的RTSP请求不支持带用户名密码。

    举例说明:

    DS-9016HF-ST的IP通道01主码流:rtsp://admin:12345@172.6.22.106:554/h264/ch33/main/av_stream

    DS-9016HF-ST的模拟通道01子码流:rtsp://admin:12345@172.6.22.106:554/h264/ch1/sub/av_stream

    DS-9016HF-ST的零通道主码流(零通道无子码流):rtsp://admin:12345@172.6.22.106:554/h264/ch0/main/av_stream

    DS-2DF7274-A的第三码流: rtsp://admin:12345@172.6.10.11:554/h264/ch1/stream3/av_stream

    URL规定:

    rtsp://username:password@

    :/Streaming/Channels/(?parm1=value1&parm2-=value2…)

    注:VLC可以支持解析URL里的用户名密码,实际发给设备的RTSP请求不支持带用户名密码。

    详细描述:

    举例说明:

    DS-9632N-ST的IP通道01主码流:rtsp://admin:12345@172.6.22.234:554/Streaming/Channels/101?transportmode=unicast

    DS-9016HF-ST的IP通道01主码流:rtsp://admin:12345@172.6.22.106:554/Streaming/Channels/1701?transportmode=unicast

    DS-9016HF-ST的模拟通道01子码流:rtsp://admin:12345@172.6.22.106:554/Streaming/Channels/102?transportmode=unicast

    (单播):rtsp://admin:12345@172.6.22.106:554/Streaming/Channels/102?transportmode=multicast

    (多播):rtsp://admin:12345@172.6.22.106:554/Streaming/Channels/102 (?后面可省略,默认单播)

    DS-9016HF-ST的零通道主码流(零通道无子码流):rtsp://admin:12345@172.6.22.106:554/Streaming/Channels/001

    DS-2DF7274-A的第三码流:rtsp://admin:12345@172.6.10.11:554/Streaming/Channels/103

    注:前面老URL,NVR(>=64路的除外)的IP通道从33开始;新URL,通道号全部按顺序从1开始。

    URL规定:

    rtsp://username:password@

    :/Streaming/tracks/(?parm1=value1&parm2-=value2…)

    注:VLC可以支持解析URL里的用户名密码,实际发给设备的RTSP请求不支持带用户名密码。

    举例说明:

    DS-9016HF-ST的模拟通道01:rtsp://admin:12345@172.6.22.106:554/Streaming/tracks/101?starttime=20120802t063812z&endtime=20120802t064816z

    DS-9016HF-ST的IP通道01:rtsp://admin:12345@172.6.22.106:554/Streaming/tracks/1701?starttime=20131013t093812z&endtime=20131013t104816z

    表示以单播形式回放指定设备的通道中的录像文件,时间范围是starttime到endtime,

    其中starttime和endtime的格式要符合ISO 8601。具体格式是:

    YYYYMMDD”T”HHmmSS.fraction”Z” ,Y是年,M是月,D是日,T是时间分格符,H是小时,M是分,S是秒,Z是可选的、表示Zulu (GMT) 时间。

    VLC播放示例:

    媒体--》打开网络串流--》网络:

    rtsp://username:password@192.168.1.17:554/MPEG-4/ch1/main/av_stream

    Linux下编译eXosip2库以及测试

    原文作者:这个名字不知道有没有人用啊

    原文链接:https://blog.csdn.net/weixin_43272766/article/details/89899257

    环境:

    Ubuntu18.04 + libosip2-5.1.0 + libexosip2-5.1.0 + c-ares-1.15.0

    下载

    https://c-ares.haxx.se/      好像不使用也可以

    http://ftp.twaren.net/Unix/NonGNU//osip/

    http://ftp.yzu.edu.tw/nongnu/exosip/

    依次解压编译(注意顺序,exosip要在最后编译)

    tarxvf 对应压缩包名

    cd 解压出来的文件夹

    ./configuremake

    sudo make install

    测试

    #include #include#include#include

    using namespacestd;intmain()

    {

    eXosip_t*sip =eXosip_malloc();if(eXosip_init(sip) ==OSIP_SUCCESS)

    {

    cout<< "eXosip init ok" <

    }else{

    cout<< "exosip init fail" <

    }int ret = eXosip_listen_addr(sip, IPPROTO_UDP, NULL, 0, AF_INET, 0);if(ret ==OSIP_SUCCESS)

    {

    cout<< "exosiop listen addr success" <

    }elsecout<< "listen addr fail, ret:" << ret <

    eXosip_quit(sip);

    cout<< "test" <

    }

    编译运行

    g++ test.cpp -losip2 -leXosip2

    ./a.out

    uac.cpp

    #include #include#include#include#include#include#include

    int main(int argc,char *argv[])

    {

    struct eXosip_t*excontext;

    eXosip_event_t*je;

    osip_message_t*reg=NULL;

    osip_message_t*invite=NULL;

    osip_message_t*ack=NULL;

    osip_message_t*info=NULL;

    osip_message_t*message=NULL;intcall_id,dialog_id;inti,flag;int flag1=1;intiReturnCode;char identity[30]="sip:140@127.0.0.1"; //UAC1,端口是15060

    char registar[30]="sip:133@127.0.0.1:15061"; //UAS,端口是15061

    char source_call[30]="sip:140@127.0.0.1";char dest_call[30]="sip:133@127.0.0.1:15061";//identify和register这一组地址是和source和destination地址相同的//在这个例子中,uac和uas通信,则source就是自己的地址,而目的地址就是uac1的地址

    charcommand;char tmp[4096];

    std::cout<< "r 向服务器注册" <<:endl>

    std::cout<< "c 取消注册" <<:endl>

    std::cout<< "i 发起呼叫请求" <<:endl>

    std::cout<< "h 挂断" <<:endl>

    std::cout<< "q 推出程序" <<:endl>

    std::cout<< "s 执行方法INFO" <<:endl>

    std::cout<< "m 执行方法MESSAGE" <<:endl>

    excontext =eXosip_malloc();

    iReturnCode=eXosip_init(excontext);if (iReturnCode != 0)

    {

    printf("Can't initialize eXosip!\n");

    return-1;

    }else{

    printf("eXosip_init successfully!\n");

    }//绑定uac自己的端口15060,并进行端口监听

    iReturnCode = eXosip_listen_addr(excontext, IPPROTO_UDP, NULL, 15060, AF_INET, 0);if(iReturnCode!=0)

    {

    eXosip_quit(excontext);

    fprintf(stderr,"Couldn't initialize transport layer!\n");

    return-1;

    }while(true)

    {//输入命令

    std::cout << "Please input the command:" <<:endl>

    std::cin>>command;

    switch(command)

    {case 'r':

    std::cout<< "This modal is not completed!" <<:endl>

    break;case 'i'://INVITE,发起呼叫请求

    i=eXosip_call_build_initial_invite(excontext,&invite,dest_call,source_call,NULL,"This is a call for conversation");if(i!=0)

    {

    std::cout<< "Initial INVITE failed!" <<:endl>

    break;

    }//符合SDP格式,其中属性a是自定义格式,也就是说可以存放自己的信息,//但是只能有两列,比如帐户信息//但是经过测试,格式vot必不可少,原因未知,估计是协议栈在传输时需要检查的

    snprintf(tmp,4096,"v=0\r\n"

    "o=anonymous 0 0 IN IP4 0.0.0.0\r\n"

    "t=1 10\r\n"

    "a=username:rainfish\r\n"

    "a=password:123\r\n");

    osip_message_set_body(invite,tmp,strlen(tmp));

    osip_message_set_content_type(invite,"application/sdp");

    eXosip_lock(excontext);

    i=eXosip_call_send_initial_invite(excontext,invite); //invite SIP INVITE message to send

    eXosip_unlock(excontext);//发送了INVITE消息,等待应答

    flag1=1;while(flag1)

    {

    je=eXosip_event_wait(excontext,0,200); //Wait for an eXosip event//(超时时间秒,超时时间毫秒)

    if(je==NULL)

    {

    printf("No response or the time is over!\n");

    break;

    }

    switch(je->type) //可能会到来的事件类型

    {case EXOSIP_CALL_INVITE: //收到一个INVITE请求

    printf("a new invite received!\n");

    break;case EXOSIP_CALL_PROCEEDING: //收到100 trying消息,表示请求正在处理中

    printf("proceeding!\n");

    break;case EXOSIP_CALL_RINGING: //收到180 Ringing应答,表示接收到INVITE请求的UA

    printf("ringing!\n");

    printf("call_id is %d,dialog_id is %d \n",je->cid,je->did);

    break;case EXOSIP_CALL_ANSWERED: //收到200 OK,表示请求已经被成功接受,用户应答

    printf("ok!connected!\n");

    call_id=je->cid;

    dialog_id=je->did;

    printf("call_id is %d,dialog_id is %d \n",je->cid,je->did);//回送ack应答消息

    eXosip_call_build_ack(excontext,je->did,&ack);

    eXosip_call_send_ack(excontext,je->did,ack);

    flag1=0; //推出While循环

    break;case EXOSIP_CALL_CLOSED: //a BYE was received for this call

    printf("the other sid closed!\n");

    break;case EXOSIP_CALL_ACK: //ACK received for 200ok to INVITE

    printf("ACK received!\n");

    break;

    default://收到其他应答

    printf("other response!\n");

    break;

    }

    eXosip_event_free(je);//Free ressource in an eXosip event

    }

    break;case 'h': //挂断

    printf("Holded!\n");

    eXosip_lock(excontext);

    eXosip_call_terminate(excontext,call_id,dialog_id);

    eXosip_unlock(excontext);

    break;case 'c':

    printf("This modal is not commpleted!\n");

    break;case 's': //传输INFO方法

    eXosip_call_build_info(excontext,dialog_id,&info);

    snprintf(tmp,4096,"\nThis is a sip message(Method:INFO)");

    osip_message_set_body(info,tmp,strlen(tmp));//格式可以任意设定,text/plain代表文本信息;

    osip_message_set_content_type(info,"text/plain");

    eXosip_call_send_request(excontext,dialog_id,info);

    break;case 'm'://传输MESSAGE方法,也就是即时消息,和INFO方法相比,我认为主要区别是://MESSAGE不用建立连接,直接传输信息,而INFO消息必须在建立INVITE的基础上传输

    printf("the method : MESSAGE\n");

    eXosip_message_build_request(excontext,&message,"MESSAGE",dest_call,source_call,NULL);//内容,方法, to ,from ,route

    snprintf(tmp,4096,"This is a sip message(Method:MESSAGE)");

    osip_message_set_body(message,tmp,strlen(tmp));//假设格式是xml

    osip_message_set_content_type(message,"text/xml");

    eXosip_message_send_request(excontext,message);

    break;case 'q':

    eXosip_quit(excontext);

    printf("Exit the setup!\n");

    flag=0;

    break;

    }

    }

    return(0);

    }

    View Code

    uas.cpp

    # include # include# include# include# include#include#include

    //# include

    int main (int argc, char *argv[])

    {

    struct eXosip_t*excontext;

    eXosip_event_t*je =NULL;

    osip_message_t*ack =NULL;

    osip_message_t*invite =NULL;

    osip_message_t*answer =NULL;

    sdp_message_t*remote_sdp =NULL;intcall_id, dialog_id;inti,j,iReturnCode;int id;char sour_call[30] = "sip:140@127.0.0.1";char dest_call[30] = "sip:133@127.0.0.1:15060";//client ip

    charcommand;char tmp[4096];char localip[128];int pos = 0;//初始化sip

    excontext =eXosip_malloc();

    iReturnCode=eXosip_init(excontext);if (iReturnCode != 0)

    {

    printf ("Can't initialize eXosip!\n");

    return-1;

    }else{

    printf ("eXosip_init successfully!\n");

    }

    iReturnCode= eXosip_listen_addr(excontext,IPPROTO_UDP, NULL, 15061, AF_INET, 0);if (iReturnCode != 0)

    {

    eXosip_quit (excontext);

    fprintf (stderr,"eXosip_listen_addr error!\nCouldn't initialize transport layer!\n");

    }for(;;)

    {//侦听是否有消息到来

    je = eXosip_event_wait (excontext,0,50);//协议栈带有此语句,具体作用未知

    eXosip_lock (excontext);

    eXosip_default_action (excontext,je);//eXosip_automatic_refresh (excontext);

    eXosip_unlock (excontext);if (je == NULL)//没有接收到消息

    continue;//printf ("the cid is %s, did is %s/n", je->did, je->cid);

    switch (je->type)

    {case EXOSIP_MESSAGE_NEW://新的消息到来

    printf ("EXOSIP_MESSAGE_NEW!\n");if (MSG_IS_MESSAGE (je->request))//如果接受到的消息类型是MESSAGE

    {

    {

    osip_body_t*body;

    osip_message_get_body (je->request, 0, &body);

    printf ("I get the msg is: %s\n", body->body);//printf ("the cid is %s, did is %s/n", je->did, je->cid);

    }//按照规则,需要回复OK信息

    eXosip_message_build_answer (excontext,je->tid, 200,&answer);

    eXosip_message_send_answer (excontext,je->tid, 200,answer);

    }

    break;caseEXOSIP_CALL_INVITE://得到接收到消息的具体信息

    printf ("Received a INVITE msg from %s:%s, UserName is %s, password is %s\n",je->request->req_uri->host,

    je->request->req_uri->port, je->request->req_uri->username, je->request->req_uri->password);//得到消息体,认为该消息就是SDP格式.

    remote_sdp = eXosip_get_remote_sdp (excontext,je->did);

    call_id= je->cid;

    dialog_id= je->did;

    eXosip_lock (excontext);

    eXosip_call_send_answer (excontext,je->tid, 180, NULL);

    i= eXosip_call_build_answer (excontext,je->tid, 200, &answer);if (i != 0)

    {

    printf ("This request msg is invalid!Cann't response!\n");

    eXosip_call_send_answer (excontext,je->tid, 400, NULL);

    }else{

    snprintf (tmp,4096,"v=0\r\n"

    "o=anonymous 0 0 IN IP4 0.0.0.0\r\n"

    "t=1 10\r\n"

    "a=username:rainfish\r\n"

    "a=password:123\r\n");//设置回复的SDP消息体,下一步计划分析消息体//没有分析消息体,直接回复原来的消息,这一块做的不好。

    osip_message_set_body (answer, tmp, strlen(tmp));

    osip_message_set_content_type (answer,"application/sdp");

    eXosip_call_send_answer (excontext,je->tid, 200, answer);

    printf ("send 200 over!\n");

    }

    eXosip_unlock (excontext);//显示出在sdp消息体中的attribute 的内容,里面计划存放我们的信息

    printf ("the INFO is :\n");while (!osip_list_eol ( &(remote_sdp->a_attributes), pos))

    {

    sdp_attribute_t*at;

    at= (sdp_attribute_t *) osip_list_get ( &remote_sdp->a_attributes, pos);

    printf ("%s : %s\n", at->a_att_field, at->a_att_value);//这里解释了为什么在SDP消息体中属性a里面存放必须是两列

    pos++;

    }

    break;caseEXOSIP_CALL_ACK:

    printf ("ACK recieved!\n");//printf ("the cid is %s, did is %s/n", je->did, je->cid);

    break;caseEXOSIP_CALL_CLOSED:

    printf ("the remote hold the session!\n");//eXosip_call_build_ack(dialog_id, &ack);//eXosip_call_send_ack(dialog_id, ack);

    i = eXosip_call_build_answer (excontext,je->tid, 200, &answer);if (i != 0)

    {

    printf ("This request msg is invalid!Cann't response!\n");

    eXosip_call_send_answer (excontext,je->tid, 400, NULL);

    }else{

    eXosip_call_send_answer (excontext,je->tid, 200, answer);

    printf ("bye send 200 over!\n");

    }

    break;case EXOSIP_CALL_MESSAGE_NEW://至于该类型和EXOSIP_MESSAGE_NEW的区别,源代码这么解释的

    /*// request related events within calls (except INVITE)

    EXOSIP_CALL_MESSAGE_NEW, < announce new incoming request.

    // response received for request outside calls

    EXOSIP_MESSAGE_NEW, < announce new incoming request.

    我也不是很明白,理解是:EXOSIP_CALL_MESSAGE_NEW是一个呼叫中的新的消息到来,比如ring trying都算,所以在接受到后必须判断

    该消息类型,EXOSIP_MESSAGE_NEW而是表示不是呼叫内的消息到来。

    该解释有不妥地方,仅供参考。*/printf("EXOSIP_CALL_MESSAGE_NEW\n");if (MSG_IS_INFO(je->request) ) //如果传输的是INFO方法

    {

    eXosip_lock (excontext);

    i= eXosip_call_build_answer (excontext,je->tid, 200, &answer);if (i == 0)

    {

    eXosip_call_send_answer (excontext,je->tid, 200, answer);

    }

    eXosip_unlock (excontext);

    {

    osip_body_t*body;

    osip_message_get_body (je->request, 0, &body);

    printf ("the body is %s\n", body->body);

    }

    }

    break;

    default:

    printf ("Could not parse the msg!\n");

    }

    }

    }

    View Code

    编译并运行

    g++ uac.cpp -o uac -losip2 -leXosip2 -lpthread -losipparser2

    g++ uas.cpp -o uas -losip2 -leXosip2 -lpthread -losipparser2

    ./uas

    ./uac

    exosip对接海康摄像头

    #include #include#include#include#include#include#include

    static void RegisterSuccess(struct eXosip_t * peCtx,eXosip_event_t *je)

    {int iReturnCode = 0;

    osip_message_t* pSRegister =NULL;

    iReturnCode= eXosip_message_build_answer (peCtx,je->tid,200,&pSRegister);if ( iReturnCode == 0 && pSRegister !=NULL )

    {

    eXosip_lock(peCtx);

    eXosip_message_send_answer (peCtx,je->tid,200,pSRegister);

    eXosip_unlock(peCtx);//osip_message_free(pSRegister);

    }

    }void RegisterFailed(struct eXosip_t * peCtx,eXosip_event_t *je) {int iReturnCode = 0;

    osip_message_t* pSRegister =NULL;

    iReturnCode= eXosip_message_build_answer (peCtx,je->tid,401,&pSRegister);if ( iReturnCode == 0 && pSRegister !=NULL )

    {

    eXosip_lock(peCtx);

    eXosip_message_send_answer (peCtx,je->tid,401,pSRegister);

    eXosip_unlock(peCtx);

    }

    }int main(int argc,char *argv[])

    {struct eXosip_t *excontext;

    eXosip_event_t*je;

    osip_message_t*reg=NULL;

    osip_message_t*invite=NULL;

    osip_message_t*ack=NULL;

    osip_message_t*info=NULL;

    osip_message_t*message=NULL;intcall_id,dialog_id;inti,flag;int flag1=1;intiReturnCode;intregisterOk;char *p;char identity[30]="sip:140@127.0.0.1"; //UAC1,端口是15060

    char registar[30]="sip:133@127.0.0.1:15061"; //UAS,端口是15061

    char source_call[30]="sip:140@127.0.0.1";char dest_call[30]="sip:133@127.0.0.1:15061";//identify和register这一组地址是和source和destination地址相同的//在这个例子中,uac和uas通信,则source就是自己的地址,而目的地址就是uac1的地址

    charcommand;char tmp[4096];

    std::cout<< "r 向服务器注册" <<:endl>

    std::cout<< "c 取消注册" <<:endl>

    std::cout<< "i 发起呼叫请求" <<:endl>

    std::cout<< "h 挂断" <<:endl>

    std::cout<< "q 推出程序" <<:endl>

    std::cout<< "s 执行方法INFO" <<:endl>

    std::cout<< "m 执行方法MESSAGE" <<:endl>

    excontext =eXosip_malloc();

    iReturnCode=eXosip_init(excontext);if (iReturnCode != 0)

    {

    printf("Can't initialize eXosip!\n");return -1;

    }else{

    printf("eXosip_init successfully!\n");

    }//绑定uac自己的端口15060,并进行端口监听

    iReturnCode = eXosip_listen_addr(excontext, IPPROTO_UDP, NULL, 5060, AF_INET, 0);if(iReturnCode!=0)

    {

    eXosip_quit(excontext);

    fprintf(stderr,"Couldn't initialize transport layer!\n");return -1;

    }while(true)

    {

    eXosip_event_t*je =NULL;

    je= eXosip_event_wait (excontext, 0, 4);if (je ==NULL) {

    std::cout<< "event is null" <<:endl>

    osip_usleep(100000*50);continue;

    }switch (je->type) {caseEXOSIP_MESSAGE_NEW:

    {//printf("new msg method:%s\n", je->request->sip_method);

    if(MSG_IS_REGISTER(je->request)) {

    std::cout<< "msg body:" <<:endl>

    registerOk= 1;

    }else if(MSG_IS_MESSAGE(je->request)){

    osip_body_t*body =NULL;

    osip_message_get_body(je->request, 0, &body);if(body !=NULL) {

    p= strstr(body->body, "Keepalive");if(p !=NULL) {

    registerOk= 1;

    std::cout<< "msg body:" <<:endl>

    std::cout<< body->body <<:endl>

    }else{

    std::cout<< "msg body:" <<:endl>

    std::cout<< body->body <<:endl>

    }

    }else{

    std::cout<< "get body failed" <<:endl>

    }

    }else if(strncmp(je->request->sip_method, "BYE", 4) != 0){

    std::cout<< "unsupport new msg method :" << je->request->sip_method <<:endl>

    }

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_MESSAGE_ANSWERED:

    {

    printf("answered method:%s\n", je->request->sip_method);

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_CALL_ANSWERED:

    {

    osip_message_t*ack=NULL;

    call_id= je->cid;

    dialog_id= je->did;

    printf("call answered method:%s, call_id:%d, dialog_id:%d\n", je->request->sip_method, call_id, dialog_id);

    eXosip_call_build_ack(excontext, je->did, &ack);

    eXosip_lock(excontext);

    eXosip_call_send_ack(excontext, je->did, ack);

    eXosip_unlock(excontext);

    }break;caseEXOSIP_CALL_PROCEEDING:

    {

    printf("recv EXOSIP_CALL_PROCEEDING\n");

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_CALL_REQUESTFAILURE:

    {

    printf("recv EXOSIP_CALL_REQUESTFAILURE\n");

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_CALL_MESSAGE_ANSWERED:

    {

    printf("recv EXOSIP_CALL_MESSAGE_ANSWERED\n");

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_CALL_RELEASED:

    {

    printf("recv EXOSIP_CALL_RELEASED\n");

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_CALL_CLOSED:

    {

    printf("recv EXOSIP_CALL_CLOSED\n");

    RegisterSuccess(excontext, je);

    }break;caseEXOSIP_CALL_MESSAGE_NEW:

    {

    printf("recv EXOSIP_CALL_MESSAGE_NEW\n");

    RegisterSuccess(excontext, je);

    }break;default:

    {

    printf("##test,%s:%d, unsupport type:%d\n", __FILE__, __LINE__, je->type);

    RegisterSuccess(excontext, je);

    }break;

    }

    eXosip_event_free(je);

    }return(0);

    }

    View Code

    海康--》sip服务器发送注册包

    sip服务器--》 海康发送200包

    sip服务器--》 海康摄像头发送message保活包

    问题汇总:

    ./a.out: error while loading shared libraries: libeXosip2.so.12: cannot open shared object file: No such file or directory

    解决办法:

    sudo vim /etc/ld.so.conf

    末尾添加 /usr/local/lib

    保存退出,执行sudo ldconfig

    参考文档:

    exosip官网: http://savannah.nongnu.org/projects/exosip/

    oSIP官网:http://savannah.gnu.org/projects/osip/

    开发手册:https://wenku.baidu.com/view/88cb5112cc7931b765ce15b0.html?sxts=1570885286497

    eXosip开发手册 :https://blog.csdn.net/mantis_1984/article/details/52948216

    https://www.cnblogs.com/swing07/p/10862480.html

    https://blog.csdn.net/zzqgtt/article/details/87179815

    https://gitee.com/leixiaohua1020/simplest_librtmp_example

    https://github.com/ossrs/librtmp

    https://github.com/logisticpeach/librtp

    https://www.jianshu.com/p/cc7df89d98f4

    https://blog.csdn.net/wwyyxx26/article/details/15224879

    https://www.bbsmax.com/A/RnJWZqYEzq/

    https://www.cnblogs.com/codenow/p/4871704.html

    从海康7816的ps流里获取数据h264数据

    github: 作为上级域,可以对接海康、大华、宇视等gb28181平台,获取ps流,转换为标准h.264裸流

    http://www.voidcn.com/article/p-cimuzoim-bab.html

    https://blog.csdn.net/mo4776/article/details/78239344

    https://blog.csdn.net/wh8_2011/article/details/48415105

    python-librtmp

    https://www.jb51.net/article/165927.htm

    librtmp使用的是0.3.0,使用树莓派noir官方摄像头适配的。

    目的是能使用Python进行rtmp推流,方便在h264帧里加入弹幕等操作。通过wireshark抓ffmpeg的包一点点改动,最终可以在red5和斗鱼上推流了。

    #-- coding: utf-8 --#http://blog.csdn.net/luhanglei

    importpicameraimporttimeimporttracebackimportctypesfrom librtmp import *

    globalmeta_packetglobalstart_timeclass Writer(): #camera可以通过一个类文件的对象来输出,实现write方法即可

    conn = None #rtmp连接

    sps = None #记录sps帧,发过以后就不需要再发了(抓包看到ffmpeg是这样的)

    pps = None #同上

    sps_len = 0 #同上

    pps_len = 0 #同上

    time_stamp=0def __init__(self, conn):

    self.conn=conndefwrite(self, data):try:#寻找h264帧间隔符

    indexs =[]

    index=0

    data_len=len(data)while index < data_len - 3:if ord(data[index]) == 0x00 and ord(data[index + 1]) == 0x00 andord(

    data[index+ 2]) == 0x00 and ord(data[index + 3]) == 0x01:

    indexs.append(index)

    index= index + 3index= index + 1

    #寻找h264帧间隔符 完成

    #通过间隔符个数确定类型,树莓派摄像头的第一帧是sps+pps同时发的

    if len(indexs) == 1: #非sps pps帧

    buf = data[4: len(data)] #裁掉原来的头(00 00 00 01),把帧内容拿出来

    buf_len =len(buf)

    type= ord(buf[0]) & 0x1f

    if type == 0x05: #关键帧,根据wire shark抓包结果,需要拼装sps pps 帧内容 三部分,长度都用4个字节表示

    body0 = 0x17data_body_array=[bytes(bytearray(

    [body0,0x01, 0x00, 0x00, 0x00, (self.sps_len >> 24) & 0xff, (self.sps_len >> 16) & 0xff,

    (self.sps_len>> 8) & 0xff,

    self.sps_len& 0xff])), self.sps,

    bytes(bytearray(

    [(self.pps_len>> 24) & 0xff, (self.pps_len >> 16) & 0xff, (self.pps_len >> 8) & 0xff,

    self.pps_len& 0xff])),

    self.pps,

    bytes(bytearray(

    [(buf_len>> 24) & 0xff, (buf_len >> 16) & 0xff, (buf_len >> 8) & 0xff, (buf_len) & 0xff])),

    buf

    ]

    mbody= ''.join(data_body_array)

    time_stamp= 0 #第一次发出的时候,发时间戳0,此后发真时间戳

    if self.time_stamp !=0:

    time_stamp= int((time.time() - start_time) * 1000)

    packet_body= RTMPPacket(type=PACKET_TYPE_VIDEO, format=PACKET_SIZE_LARGE, channel=0x06,

    timestamp=time_stamp, body=mbody)

    packet_body.packet.m_nInfoField2= 1

    else: #非关键帧

    body0 = 0x27data_body_array=[bytes(bytearray(

    [body0,0x01, 0x00, 0x00, 0x00, (buf_len >> 24) & 0xff, (buf_len >> 16) & 0xff,

    (buf_len>> 8) & 0xff,

    (buf_len)& 0xff])), buf]

    mbody= ''.join(data_body_array)#if (self.time_stamp == 0):

    self.time_stamp = int((time.time() - start_time) * 1000)

    packet_body= RTMPPacket(type=PACKET_TYPE_VIDEO, format=PACKET_SIZE_MEDIUM, channel=0x06,

    timestamp=self.time_stamp, body=mbody)

    self.conn.send_packet(packet_body)elif len(indexs) == 2: #sps pps帧

    if self.sps is notNone:returndata_body_array= [bytes(bytearray([0x17, 0x00, 0x00, 0x00, 0x00, 0x01]))]

    sps= data[indexs[0] + 4: indexs[1]]

    sps_len=len(sps)

    pps= data[indexs[1] + 4: len(data)]

    pps_len=len(pps)

    self.sps=sps

    self.sps_len=sps_len

    self.pps=pps

    self.pps_len=pps_len

    data_body_array.append(sps[1:4])

    data_body_array.append(bytes(bytearray([0xff, 0xe1, (sps_len >> 8) & 0xff, sps_len & 0xff])))

    data_body_array.append(sps)

    data_body_array.append(bytes(bytearray([0x01, (pps_len >> 8) & 0xff, pps_len & 0xff])))

    data_body_array.append(pps)

    data_body= ''.join(data_body_array)

    body_packet= RTMPPacket(type=PACKET_TYPE_VIDEO, format=PACKET_SIZE_LARGE, channel=0x06,

    timestamp=0, body=data_body)

    body_packet.packet.m_nInfoField2= 1self.conn.send_packet(meta_packet, queue=True)

    self.conn.send_packet(body_packet, queue=True)exceptException, e:

    traceback.print_exc()defflush(self):pass

    def get_property_string(string): #返回两字节string长度及string

    length =len(string)return ''.join([chr((length >> 8) & 0xff), chr(length & 0xff), string])def get_meta_string(string): #按照meta packet要求格式返回bytes,带02前缀

    return ''.join([chr(0x02), get_property_string(string)])defget_meta_double(db):

    nums= [0x00]

    fp=ctypes.pointer(ctypes.c_double(db))

    cp=ctypes.cast(fp, ctypes.POINTER(ctypes.c_longlong))for i in range(7, -1, -1):

    nums.append((cp.contents.value>> (i * 8)) & 0xff)return ''.join(bytes(bytearray(nums)))defget_meta_boolean(isTrue):

    nums= [0x01]if(isTrue):

    nums.append(0x01)else:

    nums.append(0x00)return ''.join(bytes(bytearray(nums)))

    conn=RTMP('rtmp://192.168.199.154/oflaDemo/test', #推流地址

    live=True)

    librtmp.RTMP_EnableWrite(conn.rtmp)

    conn.connect()

    start_time=time.time()#拼装视频格式的数据包

    meta_body_array = [get_meta_string('@setDataFrame'), get_meta_string('onMetaData'),

    bytes(bytearray([0x08, 0x00, 0x00, 0x00, 0x06])), #两个字符串和ECMA array头,共计6个元素,注释掉了音频相关数据

    get_property_string('width'), get_meta_double(640.0),

    get_property_string('height'), get_meta_double(480.0),

    get_property_string('videodatarate'), get_meta_double(0.0),

    get_property_string('framerate'), get_meta_double(25.0),

    get_property_string('videocodecid'), get_meta_double(7.0),#get_property_string('audiodatarate'), get_meta_double(125.0),

    #get_property_string('audiosamplerate'), get_meta_double(44100.0),

    #get_property_string('audiosamplesize'), get_meta_double(16.0),

    #get_property_string('stereo'), get_meta_boolean(True),

    #get_property_string('audiocodecid'), get_meta_double(10.0),

    get_property_string('encoder'), get_meta_string('Lavf57.56.101'),

    bytes(bytearray([0x00, 0x00, 0x09]))

    ]

    meta_body= ''.join(meta_body_array)print meta_body.encode('hex')

    meta_packet= RTMPPacket(type=PACKET_TYPE_INFO, format=PACKET_SIZE_LARGE, channel=0x04,

    timestamp=0, body=meta_body)

    meta_packet.packet.m_nInfoField2= 1 #修改stream id

    stream = conn.create_stream(writeable=True)

    with picamera.PiCamera() as camera:

    camera.start_preview()

    time.sleep(2)

    camera.start_recording(Writer(conn), format='h264', resize=(640, 480), intra_period=25,

    quality=25) #开始录制,数据输出到Writer的对象里

    while True:#永远不停止

    time.sleep(60)

    camera.stop_recording()

    camera.stop_preview()

    srs-librtmp

    https://blog.csdn.net/ai2000ai/article/details/78329039

    SRS提供的librtmp

    应用场景

    librtmp的主要应用场景包括:

    播放RTMP流:譬如rtmpdump,将服务器的流读取后保存为flv文件。

    推流:提供推流到RTMP服务器。

    基于同步阻塞socket,客户端用可以了。

    arm:编译出来给arm-linux用,譬如某些设备上,采集后推送到RTMP服务器。

    不支持直接发布h.264裸码流,而srs-librtmp支持,参考:publish-h264-raw-data

    备注:关于链接ssl,握手协议,简单握手和复杂握手,参考RTMP握手协议

    备注:ARM上使用srs-librtmp需要交叉编译,参考srs-arm,即使用交叉编译环境编译srs-librtmp(可以不依赖于其他库,ssl/st都不需要)

    librtmp做Server

    群里有很多人问,librtmp如何做server,实在不胜其骚扰,所以单列一章。

    server的特点是会有多个客户端连接,至少有两个:一个推流连接,一个播放连接。所以server有两种策略:

    每个连接一个线程或进程:像apache。这样可以用同步socket来收发数据(同步简单)。坏处就是没法支持很高并发,1000个已经到顶了,得开1000个线程/进程啊。

    使用单进程,但是用异步socket:像nginx这样。好处就是能支持很高并发。坏处就是异步socket麻烦。

    rtmpdump提供的librtmp,当然是基于同步socket的。所以使用librtmp做server,只能采取第一种方法,即用多线程处理多个连接。多线程多麻烦啊!要锁,同步,而且还支持不了多少个。

    librtmp的定位就是客户端程序,偏偏要超越它的定位去使用,这种大约只有中国人才能这样“无所畏惧”。

    嵌入式设备上做rtmp server,当然可以用srs/crtmpd/nginx-rtmp,轮也轮不到librtmp。

    SRS为何提供librtmp

    srs提供的客户端srs-librtmp的定位和librtmp不一样,主要是:

    librtmp的代码确实很烂,毋庸置疑,典型的代码堆积。

    librtmp接口定义不良好,这个对比srs就可以看出,使用起来得看实现代码。

    没有实例:接口的使用最好提供实例,srs提供了publish/play/rtmpdump实例。

    最小依赖关系:srs调整了模块化,只取出了core/kernel/rtmp三个模块,其他代码没有编译到srs-librtmp中,避免了冗余。

    最少依赖库:srs-librtmp只依赖c/c++标准库(若需要复杂握手需要依赖openssl,srs也编译出来了,只需要加入链接即可)。

    不依赖st:srs-librtmp使用同步阻塞socket,没有使用st(st主要是服务器处理并发需要)。

    SRS提供了测速函数,直接调用srs-librtmp就可以完成到服务器的测速。参考:Bandwidth Test

    SRS提供了日志接口,可以获取服务器端的信息,譬如版本,对应的session id。参考:Tracable log

    SRS可以直接导出一个srs-librtmp的project,编译成.h和.a使用。或者导出为.h和.cpp,一个大文件。参考:export srs librtmp

    一句话,srs为何提供客户端开发库?因为rtmp客户端开发不方便,不直观,不简洁。

    Export Srs Librtmp

    SRS在2.0提供了导出srs-librtmp的编译选项,可以将srs-librtmp单独导出为project,单独编译生成.h和.a,方便在linux和windows平台编译。

    使用方法,导出为project,可以make成.h和.a:

    dir=/home/winlin/srs-librtmp &&

    rm -rf $dir &&

    ./configure --export-librtmp-project=$dir &&

    cd $dir && make &&

    ./objs/research/librtmp/srs_play rtmp://ossrs.net/live/livestream

    SRS将srs-librtmp导出为独立可以make的项目,生成.a静态库和.h头文件,以及生成了srs-librtmp的所有实例。

    还可以直接导出为一个文件,提供了简单的使用实例,其他实例参考research的其他例子:

    dir=/home/winlin/srs-librtmp &&

    rm -rf $dir &&

    ./configure --export-librtmp-single=$dir &&

    cd $dir && gcc example.c srs_librtmp.cpp -g -O0 -lstdc++ -o example &&

    strip example && ./example

    备注:导出目录支持相对目录和绝对目录。

    编译srs-librtmp

    编译SRS时,会自动编译srs-librtmp,譬如:

    ./configure --with-librtmp --without-ssl

    编译会生成srs-librtmp和对应的实例。

    备注:支持librtmp只需要打开--with-librtmp,但推荐打开--without-ssl,不依赖于ssl,对于一般客户端(不需要模拟flash)足够了。这样srs-librtmp不依赖于任何其他库,在x86/x64/arm等平台都可以编译和运行

    备注:就算打开了--with-ssl,srslibrtmp也只提供simple_handshake函数,不提供complex_handshake函数。所以推荐关闭ssl,不依赖于ssl,没有实际的用处。

    SRS编译成功后,用户就可以使用这些库开发

    Windows下编译srs-librtmp

    srs-librtmp可以只依赖于c++和socket,可以在windows下编译。

    先使用SRS导出srs-librtmp,然后在vs中编译,参考:export srs librtmp

    使用了一些linux的头文件,需要做一些portal。

    注意:srs-librtmp客户端推流和抓流,不需要ssl库。代码都是c++/stl,网络部分用的是同步socket。

    数据格式

    srs-librtmp提供了一系列接口函数,就数据按照一定格式发送到服务器,或者从服务器读取音视频数据。

    数据接口包括:

    读取数据包:int srs_read_packet(int* type, u_int32_t* timestamp, char** data, int* size)

    发送数据包:int srs_write_packet(int type, u_int32_t timestamp, char* data, int size)

    接口接受的的数据(char* data),音视频数据,格式为flv的Video/Audio数据。参考srs的doc目录的规范文件video_file_format_spec_v10_1.pdf

    音频数据格式参考:E.4.2.1 AUDIODATA,p76,譬如,aac编码的音频数据。

    视频数据格式参考:E.4.3.1 VIDEODATA,p78,譬如,h.264编码的视频数据。

    脚本数据格式参考:E.4.4.1 SCRIPTDATA,p80,譬如,onMetadata,流的信息(宽高,码率,分辨率等)

    数据类型(int type)定义如下(E.4.1 FLV Tag,page 75):

    音频:8 = audio,宏定义:SRS_RTMP_TYPE_AUDIO

    视频:9 = video,宏定义:SRS_RTMP_TYPE_VIDEO

    脚本数据:18 = script data,宏定义:SRS_RTMP_TYPE_SCRIPT

    其他的数据,譬如时间戳,都是通过参数接受和发送。

    另外,文档其他重要信息:

    flv文件头格式:E.2 The FLV header,p74。

    flv文件主体格式:E.3 The FLV File Body,p74。

    tag头格式:E.4.1 FLV Tag,p75。

    使用flv格式的原因:

    flv的格式足够简单。

    ffmpeg也是用的这种格式

    收到流后加上flv tag header,就可以直接保存为flv文件

    从flv文件解封装数据后,只要将tag的内容给接口就可以,flv的tag头很简单。

    Publish H.264 Raw Data

    SRS-librtmp支持发布h.264裸码流,直接调用api即可将数据发送给SRS。

    总结起来就是说,H264的裸码流(帧)转换RTMP时:

    dts和pts是不在h264流中的,外部给出。

    SPS和PPS在RTMP一个包里面发出去。

    RTMP包=5字节RTMP包头+H264头+H264数据,具体参考:SrsAvcAacCodec::video_avc_demux

    直接提供接口,发送h264数据,其中包含annexb的头:N[00] 00 00 01, where N>=0.

    加了一个直接发送h264裸码流的接口:

    /**

    * write h.264 raw frame over RTMP to rtmp server.

    * @param frames the input h264 raw data, encoded h.264 I/P/B frames data.

    * frames can be one or more than one frame,

    * each frame prefixed h.264 annexb header, by N[00] 00 00 01, where N>=0,

    * for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40)

    * about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211.

    * @paam frames_size the size of h264 raw data.

    * assert frames_size > 0, at least has 1 bytes header.

    * @param dts the dts of h.264 raw data.

    * @param pts the pts of h.264 raw data.

    *

    * @remark, user should free the frames.

    * @remark, the tbn of dts/pts is 1/1000 for RTMP, that is, in ms.

    * @remark, cts = pts - dts

    *

    * @return 0, success; otherswise, failed.

    */

    extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp,

    char* frames, int frames_size, u_int32_t dts, u_int32_t pts

    );

    里面的数据是:

    // SPS

    000000016742802995A014016E40

    // PPS

    0000000168CE3880

    // IFrame

    0000000165B8041014C038008B0D0D3A071.....

    // PFrame

    0000000141E02041F8CDDC562BBDEFAD2F.....

    调用时,可以SPS和PPS一起发,帧一次发一个:

    // SPS+PPS

    srs_h264_write_raw_frame('000000016742802995A014016E400000000168CE3880', size, dts, pts)

    // IFrame

    srs_h264_write_raw_frame('0000000165B8041014C038008B0D0D3A071......', size, dts, pts)

    // PFrame

    srs_h264_write_raw_frame('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts)

    调用时,可以一次发一次frame也行:

    // SPS

    srs_h264_write_raw_frame('000000016742802995A014016E4', size, dts, pts)

    // PPS

    srs_h264_write_raw_frame('00000000168CE3880', size, dts, pts)

    // IFrame

    srs_h264_write_raw_frame('0000000165B8041014C038008B0D0D3A071......', size, dts, pts)

    // PFrame

    srs_h264_write_raw_frame('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts)

    Publish Audio Raw Stream

    srs-librtmp提供了api可以将音频裸码流发布到SRS,支持AAC ADTS格式。

    API定义如下:

    /**

    * write an audio raw frame to srs.

    * not similar to h.264 video, the audio never aggregated, always

    * encoded one frame by one, so this api is used to write a frame.

    *

    * @param sound_format Format of SoundData. The following values are defined:

    * 0 = Linear PCM, platform endian

    * 1 = ADPCM

    * 2 = MP3

    * 3 = Linear PCM, little endian

    * 4 = Nellymoser 16 kHz mono

    * 5 = Nellymoser 8 kHz mono

    * 6 = Nellymoser

    * 7 = G.711 A-law logarithmic PCM

    * 8 = G.711 mu-law logarithmic PCM

    * 9 = reserved

    * 10 = AAC

    * 11 = Speex

    * 14 = MP3 8 kHz

    * 15 = Device-specific sound

    * Formats 7, 8, 14, and 15 are reserved.

    * AAC is supported in Flash Player 9,0,115,0 and higher.

    * Speex is supported in Flash Player 10 and higher.

    * @param sound_rate Sampling rate. The following values are defined:

    * 0 = 5.5 kHz

    * 1 = 11 kHz

    * 2 = 22 kHz

    * 3 = 44 kHz

    * @param sound_size Size of each audio sample. This parameter only pertains to

    * uncompressed formats. Compressed formats always decode

    * to 16 bits internally.

    * 0 = 8-bit samples

    * 1 = 16-bit samples

    * @param sound_type Mono or stereo sound

    * 0 = Mono sound

    * 1 = Stereo sound

    * @param timestamp The timestamp of audio.

    *

    * @example /trunk/research/librtmp/srs_aac_raw_publish.c

    * @example /trunk/research/librtmp/srs_audio_raw_publish.c

    *

    * @remark for aac, the frame must be in ADTS format.

    * @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS

    * @remark for aac, only support profile 1-4, AAC main/LC/SSR/LTP,

    * @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 23, 1.5.1.1 Audio object type

    *

    * @see https://github.com/ossrs/srs/issues/212

    * @see E.4.2.1 AUDIODATA of video_file_format_spec_v10_1.pdf

    *

    * @return 0, success; otherswise, failed.

    */

    extern int srs_audio_write_raw_frame(srs_rtmp_t rtmp,

    char sound_format, char sound_rate, char sound_size, char sound_type,

    char* frame, int frame_size, u_int32_t timestamp

    );

    /**

    * whether aac raw data is in adts format,

    * which bytes sequence matches '1111 1111 1111'B, that is 0xFFF.

    * @param aac_raw_data the input aac raw data, a encoded aac frame data.

    * @param ac_raw_size the size of aac raw data.

    *

    * @reamrk used to check whether current frame is in adts format.

    * @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS

    * @example /trunk/research/librtmp/srs_aac_raw_publish.c

    *

    * @return 0 false; otherwise, true.

    */

    extern srs_bool srs_aac_is_adts(char* aac_raw_data, int ac_raw_size);

    /**

    * parse the adts header to get the frame size,

    * which bytes sequence matches '1111 1111 1111'B, that is 0xFFF.

    * @param aac_raw_data the input aac raw data, a encoded aac frame data.

    * @param ac_raw_size the size of aac raw data.

    *

    * @return failed when <=0 failed; otherwise, ok.

    */

    extern int srs_aac_adts_frame_size(char* aac_raw_data, int ac_raw_size);

    调用实例参考#212,以及srs_audio_raw_publish.c和srs_aac_raw_publish.c,参考examples.

    srs-librtmp Examples

    SRS提供了实例sample,也会在编译srs-librtmp时自动编译:

    research/librtmp/srs_play.c:播放RTMP流实例。

    research/librtmp/srs_publish.c:推送RTMP流实例。

    research/librtmp/srs_ingest_flv.c:读取本地FLV文件并推送RTMP流实例。

    research/librtmp/srs_ingest_mp4.c:读取本地MP4文件并推送RTMP流实例。

    research/librtmp/srs_ingest_rtmp.c:读取RTMP流并推送RTMP流实例。

    research/librtmp/srs_bandwidth_check.c:带宽测试工具。

    research/librtmp/srs_flv_injecter.c:点播FLV关键帧注入文件。

    research/librtmp/srs_flv_parser.c:FLV文件查看工具。

    research/librtmp/srs_detect_rtmp.c:RTMP流检测工具。

    research/librtmp/srs_h264_raw_publish.c:H.264裸码流发布到SRS实例。

    research/librtmp/srs_audio_raw_publish.c: Audio裸码流发布到SRS实例。

    research/librtmp/srs_aac_raw_publish.c: Audio AAC ADTS裸码流发布到SRS实例。

    research/librtmp/srs_rtmp_dump.c: 将RTMP流录制成flv文件实例。

    ./objs/srs_ingest_hls: 将HLS流采集成RTMP推送给SRS。

    运行实例

    启动SRS:

    make && ./objs/srs -c srs.conf

    推流实例:

    make && ./objs/research/librtmp/objs/srs_publish rtmp://127.0.0.1:1935/live/livestream

    备注:推流实例发送的视频数据不是真正的视频数据,实际使用时,譬如从摄像头取出h.264裸码流,需要封装成接口要求的数据,然后调用接口发送出去。或者直接发送h264裸码流。

    播放实例:

    make && ./objs/research/librtmp/objs/srs_play rtmp://ossrs.net/live/livestreamsuck rtmp stream like rtmpdump

    展开全文
  • 1、什么是域名,什么是网站名,什么是URL举例:http://mail.163.com/index.html http://:这一个协议,叫做超文本传输协议(HyperText Tranfer Proctocol) mail:这个服务器名,代表着一个邮箱服务器...

    1、什么是域名,什么是网站名,什么是URL?

    举例:http://mail.163.com/index.html

    1. http://:这是一个协议,叫做超文本传输协议(HyperText Tranfer Proctocol)
    2. mail:这是个服务器名,代表着一个邮箱服务器(host)
    3. 163.com:这是一个域名,用来定位网站的独一无二的名字
    4. mail.163.com:这是一个网站名,有服务器名与域名组成。域名就像是一块地,而网站名就像是这块地上起的房子,也就是说域名只有一个,然后可以以此为基础创建多个网站。
    5. /index.html这是目录路径,正常来讲只需要输入http://mail.163.com/就会跳到这个页面上,因为当浏览器在当前目录下若没指定找寻文件,会自动地返回以indexdefault命名的默认文件。
    6. 这里没有显示端口,这是因为一般的网站服务器端口都是默认为80
    7. http://mail.163.com/index.html整一个就叫做URL,全称:Uniform/Universal Resourse Locator,统一资源定位符

    2、url的特殊字符

    学习使用GET传递数据方法的时候看到一连串url拼接,那么这些url特殊的字符都是什么呢?
    这些特殊字符因为都有特殊含义,所以假如要传送的数据包含这些字符,那么还得使用特定编码格式进行编码后在传送,编码格式为:% + 该字符的ASCII编码

    • +:在url中表示空格,编码为:%2B
    • 空格:在url中表示空格,在url中常用+号表示,编码为:%20
    • /:在url中用于分隔目录与子目录,编码为:%2F
    • ?:在url中用于分隔实际的url和参数,编码为:%3F
    • %:指定特定的字符,编码为:%25
    • #:表示书签,编码为%23
    • &:用于作为参数间的分隔符,编码为%26
    • =:用于指定参数的值,编码为%3D

    举例子,想要把this%is#te=st&o k?+/作为参数t传送给te.asp,则其URL为:

    te.asp?t=this%25is%23te%3Dst%26o%20k%3F%2B%2F

    3、URI与URL的区别

    引自这里

    理解URL与URI的区别,这里引入URN这个概念:

    • URI:Universal Resourse Identifier(统一资源标志符)
    • URL:Universal Resourse Locator(统一资源定位符)
    • URN:Universal Resourse Name(统一资源命名符)

    URI(标志符)可被视为定位符(URL),名称(URN)或两者兼备。
    而URN定义某事物的身份,URL提供查找该事物的方法。


    4、JPEG,PNG和GIF有什么不同?

    简单来说:

    • JPEG适合连续色调对象,比如照片;可以表达1600多万种颜色;是一个“有损”格式,即会因为缩小文件大小而丢掉图像信息
    • PNG最适合单色的图像和线条构成的图像,如logo;可以表达几百万种颜色。PNG有三种类型:PNG-8,PNG-24和PNG-32;属于“无损”格式;允许将颜色设置透明;文件相对JPEG大
    • **GIF**web最原始图像格式,只能表达256种颜色;作用与PNG差不多,只不过GIF只允许一种颜色设置为“透明”;文件相对JPEG大

    5、像素

    计算机显示屏是由数百万称为像素的点组成的,大多数的浏览器的欢度设置为800到1280像素之间,所以一般经验是将图像最大宽度设置为800像素,而一般的logo宽度存在100到200像素之间。

    转载于:https://www.cnblogs.com/AB786883603/p/8325422.html

    展开全文
  • 从后台splunk里面导出了几万条用户搜索记录(.csv格式),但全是百分号那种url码(GBK码),想把它转成中文看看都是什么。搜了一圈网上的工具,发现都只能一条一条转。好像可以用VB在excel里面写个程序但是好麻烦.......
  • 我不明白的什么需要通过先获得con对象才能通过con对象获得stmt后才能获得rt对象.不明白这种对象的调用原理..新手.才接触java没多久,,希望各位大神能帮忙解惑.说细致点..谢谢..最好能举例说明.. ---------------...
  • 在安卓项目里调用API接口:该API请求数据要求json格式,返回来的也json格式。 get请求举例url:xxx.api/user?userId=abc&password=123 post请求举例url:xxx.api/user ; apiParams: userId=abc&...
  • 1、什么是URL 1.1 基本介绍 URL的全称Uniform Resource Locator(统一资源定位符) 通过1个URL,能找到互联网上唯一的1个资源 URL就是资源的地址、位置,互联网上的每个资源都有一个唯一的URLURL的基本格式=...
  • 北向接口标准化工作北向接口设计(两类)北向接口与网络模型基于意图的业务模型描述基于意图的描述举例北向接口的实现什么是REST API?什么是REST?RESTful与REST API为什么需要RESTful?REST的几个重要概念URI 与 URL...
  • DOM全称document object model(文档对象模型),DOM用来干什么的呢?假设把你的文档看成一个单独的对象,DOM就是如何用HTML或者XML对这个对象进行操作和控制的标准。 面向对象的思想方法已经非常流行了,在编程...
  • Elasticsearch Search API

    2020-03-09 01:47:23
    1.什么是Elasticsearch Search API? 顾名思义就是Elasticsearch的搜索api 它可以分为两大类: 1. URI Search:在URL中使用查询参数 2. Request Body Search:使用elasticsearch提供的,基于 JSON格式的查询Domain的...
  • 举例如下: $first = 'Hello'; $second = "World"; $full1 = "$first $second"; # 产生 Hello World $full2 = '$first $second';# 产生 $first $second 可以将字符和数字利用运算符号连接起来。字符被转化成数字,...
  • 用Tomcat配置虚拟主机

    2018-01-14 23:18:53
    URL 格式: http://主机名(或IP地址):端口号/目录名称/资源名称 举例: http://www.it315.org/book/java.html 思考:http://www.it315.org/book/java.html中的www.it315.org代表一台计算机的地址,还是代表...
  • HTTP协议

    2020-05-19 17:22:08
    举例:当您在浏览器中输入URL时,实际上会向Web服务器发送HTTP命令,指示它获取并传输请求的Web页面,从而控制万维网工作,并且显示网页的格式。 注意事项: HTTP为无状态协议,就是每个命令的执行相互独立,那么
  • 上传图片第一次上传不显示,但是图片却存到磁盘里了,然后再次上传就显示了...然后磁盘多了一张不同名字想同的图片 <code class="language-javascript"> <link href=...各位老哥帮看一下是什么原因</p>
  • jpivot学习总结.doc

    2011-12-09 08:38:08
    controllerURL 否 String 链接到 JPivot Controller 的 URL ,该属性在一些复杂环境下比如 Portal 之类就很有用。 4.3. chooseQuery 从前面创建的若干个查询当中选择一个合适的查询(通过查询名称进行选择...
  • 并不是所有的用户都会中规中矩的输入符合要求的信息,你也不可能知道使用浏览器输入信息的是什么人,他们在想什么,做什么。你可以使用 CI 来防止输入不符合要求的信息。当然,你大可不必知道 CI 是如何在幕后为你...
  • 27、GC是什么? 为什么要有GC?  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象...
  • asp.net面试题

    2011-05-27 17:56:26
    分别是什么原理? 答:form认证,windows集成认证等,原理不清楚. 12.进程和线程分别怎么理解? 答:进程是老子,线程是儿子,没有老子就没有儿子,一个老子可以有多个儿子.一个儿子可以成为别人的儿子,一个老子也可以为...
  • 5.1 什么是文档对象模型 5.1.1 XML文档结构 5.1.2 为何使用DOM 5.1.3 DOM规范 5.1.4 现实世界中的DOM 5.1.5 特殊的XML DOM实例— HTML DOM 5.2 使用DOM 5.2.1 DOM API 5.2.2 客户端和服务器端 5.2.3 DOM在...
  • XML高级编程pdf

    2010-03-08 22:28:50
    5.1 什么是文档对象模型 5.1.1 XML文档结构 5.1.2 为何使用DOM 5.1.3 DOM规范 5.1.4 现实世界中的DOM 5.1.5 特殊的XML DOM实例— HTML DOM 5.2 使用DOM 5.2.1 DOM API 5.2.2 客户端和服务器端 5.2.3 DOM在...
  • 5.1 什么是文档对象模型 5.1.1 XML文档结构 5.1.2 为何使用DOM 5.1.3 DOM规范 5.1.4 现实世界中的DOM 5.1.5 特殊的XML DOM实例— HTML DOM 5.2 使用DOM 5.2.1 DOM API 5.2.2 客户端和服务器端 5.2.3 DOM在...
  • XML高级编程

    2015-01-14 10:02:15
    5.1 什么是文档对象模型 111 5.1.1 XML文档结构 111 5.1.2 为何使用DOM 113 5.1.3 DOM规范 115 5.1.4 现实世界中的DOM 116 5.1.5 特殊的XML DOM实例— HTML DOM 117 5.2 使用DOM 120 5.2.1 DOM API 120 5.2.2 ...
  • java 面试题 总结

    2009-09-16 08:45:34
    24、GC是什么? 为什么要有GC?  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象...
  • jsp九大内置对象

    2011-10-21 23:25:22
    Cookie以“关键字key=值value”的格式来保存记录的。  (2)创建一个Cookie对象  调用Cookie对象的构造函数就可以创建Cookie对象。Cookie对象的构造函数有两个字符串参数:Cookie名字和Cookie值。  例如:...
  • SSO-WebDemo

    2013-08-12 20:25:57
    如果举例说国内一著名的IT公司(名字隐去),内部共有60多个业务系统,这些系统包括两个不同版本的SAP的ERP系统,12个不同类型和版本的数据库系统,8个不同类型和版本的操作系统,以及使用了3种不同的防火墙技术,...

空空如也

空空如也

1 2 3
收藏数 42
精华内容 16
关键字:

url格式是什么举例