使用librtmp捕获摄像机并发布视频 [英] capture camera and publish video with librtmp

查看:201
本文介绍了使用librtmp捕获摄像机并发布视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力在nginx rtmp服务器上发布视频.在我的nginx配置中,有以下几行:

I am struggling to publish video on nginx rtmp server. In my nginx config I have following lines:

rtmp {
        server {

    access_log /var/log/nginx/rtmp-access-streaming.log;

                listen 1935;
        #       wait_key on;
                wait_video on;
                chunk_size 4096;

                application live {
                        live on;
                        allow publish all;
                #       deny publish all;
                        allow play all;
                        record off;
                }

                # video on demand for flv files

                application vod {
                    play /home/ulterior/Record;
                }
        }

到目前为止,视频点播工作还可以,问题是发布实时流.

Video on demand work OK so far, the problem is publish live streams.

我使用以下代码连接librtmp:

I connect with librtmp with following code:

    char *rtmp_output = NULL;
    const char *rtmp_url = "rtmp://127.0.0.1/live/streamName flashver=FMLE/3.0\20(compatible;\20FMSc/1.0)";

    if (rtmp_url) {
        rtmp_output = malloc( strlen( rtmp_url )+1 );
        strncpy( rtmp_output, rtmp_url, strlen( rtmp_url ));
        rtmp_output[ strlen( rtmp_url ) ] = '\0';

        printf( "RTMP output to: %s\n", rtmp_output);
        printf( "sizeof rtmp %d bytes\n", sizeof(RTMP) );
        hRtmp->rtmp = calloc(1, sizeof(RTMP));
        memset(hRtmp->rtmp, 0x00, sizeof(RTMP));

        printf("created rtmp %p\n", hRtmp->rtmp );
    }

    if (hRtmp->rtmp) {

        printf("setting rtmp\n" );

        RTMP_LogSetLevel(RTMP_LOGWARNING);
        RTMP_LogSetCallback(rtmp_log);

        RTMP_Init(hRtmp->rtmp);
        if (!RTMP_SetupURL(hRtmp->rtmp, rtmp_output)) {
            printf("error RTMP_SetupURL\n" ); 
            goto cleanup;
        }

        hRtmp->rtmp->Link.protocol |= RTMP_FEATURE_WRITE;
        if (!RTMP_Connect(hRtmp->rtmp, NULL) ) {
            printf("error RTMP_Connect\n" );
            goto cleanup;
        }

        if( !RTMP_ConnectStream(hRtmp->rtmp, 0) ) {
            printf("error RTMP_Connect stream\n" );
            goto cleanup;
        }


    RTMPPacket packet={0};  
{

    uint8_t rtmp_buffer[2048];

    memset(&packet,0,sizeof(RTMPPacket));  
    packet.m_nChannel = 0x04;  
    packet.m_headerType = RTMP_PACKET_SIZE_LARGE;  
    packet.m_nTimeStamp = 0;  
    packet.m_nInfoField2 = hRtmp->rtmp->m_stream_id;  
    packet.m_hasAbsTimestamp = 0;  
    packet.m_body =(char *) rtmp_buffer;  
    char * szTmp=(char *)rtmp_buffer;  
    packet.m_packetType = RTMP_PACKET_TYPE_INFO;  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string(szTmp, "@setDataFrame" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string(szTmp, "onMetaData" );  
    szTmp=put_byte(szTmp, AMF_OBJECT );  
    szTmp=put_amf_string( szTmp, "author" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "" );  
    szTmp=put_amf_string( szTmp, "copyright" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "" );  
    szTmp=put_amf_string( szTmp, "description" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "" );  
    szTmp=put_amf_string( szTmp, "keywords" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "" );  
    szTmp=put_amf_string( szTmp, "rating" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "" );  
    szTmp=put_amf_string( szTmp, "presetname" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "Custom" );  
    szTmp=put_amf_string( szTmp, "width" );  
    szTmp=put_amf_double( szTmp, 640.0 );//p264Param->i_width );  
    szTmp=put_amf_string( szTmp, "width" );  
    szTmp=put_amf_double( szTmp, 640.0 );//p264Param->i_width );  
    szTmp=put_amf_string( szTmp, "height" );  
    szTmp=put_amf_double( szTmp, 480.0 );//p264Param->i_height );  
    szTmp=put_amf_string( szTmp, "framerate" );  
    szTmp=put_amf_double( szTmp, 25.0 );//(double)p264Param->i_fps_num / p264Param->i_fps_den );  
    szTmp=put_amf_string( szTmp, "videocodecid" );  
    szTmp=put_byte(szTmp, AMF_STRING );  
    szTmp=put_amf_string( szTmp, "avc1" );  
    szTmp=put_amf_string( szTmp, "videodatarate" );  
    szTmp=put_amf_double( szTmp, 1500.0 );//p264Param->rc.i_bitrate );   
    szTmp=put_amf_string( szTmp, "avclevel" ); 

    szTmp=put_amf_double( szTmp, 1.0 );//p264Param->i_level_idc );   
    szTmp=put_amf_string( szTmp, "avcprofile" );  
    szTmp=put_amf_double( szTmp, 0x42 );   
    szTmp=put_amf_string( szTmp, "videokeyframe_frequency" );  
    szTmp=put_amf_double( szTmp, 8.0 );   
    szTmp=put_amf_string( szTmp, "" );  
    szTmp=put_byte( szTmp, AMF_OBJECT_END );  
    packet.m_nBodySize=szTmp-(char *)rtmp_buffer;  

    printf( "sending %d as header\n", packet.m_nBodySize );

    hex_dump_internal( packet.m_body, packet.m_nBodySize );

    RTMP_SendPacket(hRtmp->rtmp,&packet,1);  
}

这似乎也可以正常工作,没有错误:

This appears to work too, without errors:

rtmp set, sending header
sending 307 as header
00000000  02 00 0d 40 73 65 74 44 61 74 61 46 72 61 6d 65 ...@setDataFrame
00000010  02 00 0a 6f 6e 4d 65 74 61 44 61 74 61 03 00 06 ...onMetaData...
00000020  61 75 74 68 6f 72 02 00 00 00 09 63 6f 70 79 72 author.....copyr
00000030  69 67 68 74 02 00 00 00 0b 64 65 73 63 72 69 70 ight.....descrip
00000040  74 69 6f 6e 02 00 00 00 08 6b 65 79 77 6f 72 64 tion.....keyword
00000050  73 02 00 00 00 06 72 61 74 69 6e 67 02 00 00 00 s.....rating....
00000060  0a 70 72 65 73 65 74 6e 61 6d 65 02 00 06 43 75 .presetname...Cu
00000070  73 74 6f 6d 00 05 77 69 64 74 68 00 40 84 00 00 stom..width.@...
00000080  00 00 00 00 00 05 77 69 64 74 68 00 40 84 00 00 ......width.@...
00000090  00 00 00 00 00 06 68 65 69 67 68 74 00 40 7e 00 ......height.@~.
000000a0  00 00 00 00 00 00 09 66 72 61 6d 65 72 61 74 65 .......framerate
000000b0  00 40 39 00 00 00 00 00 00 00 0c 76 69 64 65 6f .@9........video
000000c0  63 6f 64 65 63 69 64 02 00 04 61 76 63 31 00 0d codecid...avc1..
000000d0  76 69 64 65 6f 64 61 74 61 72 61 74 65 00 40 97 videodatarate.@.
000000e0  70 00 00 00 00 00 00 08 61 76 63 6c 65 76 65 6c p.......avclevel
000000f0  00 3f f0 00 00 00 00 00 00 00 0a 61 76 63 70 72 .?.........avcpr
00000100  6f 66 69 6c 65 00 40 50 80 00 00 00 00 00 00 17 ofile.@P........
00000110  76 69 64 65 6f 6b 65 79 66 72 61 6d 65 5f 66 72 videokeyframe_fr
00000120  65 71 75 65 6e 63 79 00 40 20 00 00 00 00 00 00 equency.@ ......
00000130  00 00 09                                        ...
RTMPLOG=t
    : fd=41708, size=196735
header sent

我正在以NALU格式发送数据,我看到它正在写入服务器,但是同一个librtmp无法理解该流:

I am sending the data in NALU format, I see it being written to server, but the same librtmp fails to understand the stream:

rtmpdump -r rtmp://127.0.0.1/live/streamName -o test --debug &
[2] 2502
root@a13-OLinuXino:/home/ulterior# RTMPDump v2.4
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
DEBUG: Protocol : RTMP
DEBUG: Hostname : 127.0.0.1
DEBUG: Port     : 1935
DEBUG: Playpath : streamName
DEBUG: tcUrl    : rtmp://127.0.0.1:1935/live
DEBUG: app      : live
DEBUG: live     : no
DEBUG: timeout  : 30 sec
DEBUG: Setting buffer time to: 36000000ms
Connecting ...
DEBUG: RTMP_Connect1, ... connected, handshaking
DEBUG: HandShake: Type Answer   : 03
DEBUG: HandShake: Server Uptime : 12857710
DEBUG: HandShake: FMS Version   : 0.0.0.0
DEBUG: HandShake: Handshaking finished....
DEBUG: RTMP_Connect1, handshaked
DEBUG2: RTMP_SendPacket: fd=5, size=197
DEBUG2:   0000:  03 00 00 00 00 00 c5 14  00 00 00 00               ............      
DEBUG2:   0000:  02 00 07 63 6f 6e 6e 65  63 74 00 3f f0 00 00 00   ...connect.?....  
DEBUG2:   0010:  00 00 00 03 00 03 61 70  70 02 00 04 6c 69 76 65   ......app...live  
DEBUG2:   0020:  00 08 66 6c 61 73 68 56  65 72 02 00 0e 4c 4e 58   ..flashVer...LNX  
DEBUG2:   0030:  20 31 30 2c 30 2c 33 32  2c 31 38 00 05 74 63 55    10,0,32,18..tcU  
DEBUG2:   0040:  72 6c 02 00 1a 72 74 6d  70 3a 2f 2f 31 32 37 2e   rl...rtmp://127.  
DEBUG2:   0050:  30 2e 30 2e 31 3a 31 39  33 35 2f 6c 69 76 65 00   0.0.1:1935/live.  
DEBUG2:   0060:  04 66 70 61 64 01 00 00  0c 63 61 70 61 62 69 6c   .fpad....capabil  
DEBUG2:   0070:  69 74 69 65 73 00 40 2e  00 00 00 00 00 00 00 0b   ities.@.........  
DEBUG2:   0000:  c3                                                 .                 
DEBUG2:   0000:  61 75 64 69 6f 43 6f 64  65 63 73 00 40 a8 ee 00   audioCodecs.@...  
DEBUG2:   0010:  00 00 00 00 00 0b 76 69  64 65 6f 43 6f 64 65 63   ......videoCodec  
DEBUG2:   0020:  73 00 40 6f 80 00 00 00  00 00 00 0d 76 69 64 65   s.@o........vide  
DEBUG2:   0030:  6f 46 75 6e 63 74 69 6f  6e 00 3f f0 00 00 00 00   oFunction.?.....  
DEBUG2:   0040:  00 00 00 00 09                                     .....             
DEBUG: Invoking connect
INFO: Connected...
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  02 00 00 00 00 00 04 05  00 00 00 00               ............      
DEBUG2:   0000:  00 4c 4b 40                                        .LK@              
DEBUG: HandleServerBW: server BW = 5000000
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  02 00 00 00 00 00 05 06  00 00 00 00               ............      
DEBUG2:   0000:  00 4c 4b 40 02                                     .LK@.             
DEBUG: HandleClientBW: client BW = 5000000 2
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  02 00 00 00 00 00 04 01  00 00 00 00               ............      
DEBUG2:   0000:  00 00 10 00                                        ....              
DEBUG: HandleChangeChunkSize, received: chunk size change to 4096
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  03 00 00 00 00 00 be 14  00 00 00 00               ............      
DEBUG2:   0000:  02 00 07 5f 72 65 73 75  6c 74 00 3f f0 00 00 00   ..._result.?....  
DEBUG2:   0010:  00 00 00 03 00 06 66 6d  73 56 65 72 02 00 0d 46   ......fmsVer...F  
DEBUG2:   0020:  4d 53 2f 33 2c 30 2c 31  2c 31 32 33 00 0c 63 61   MS/3,0,1,123..ca  
DEBUG2:   0030:  70 61 62 69 6c 69 74 69  65 73 00 40 3f 00 00 00   pabilities.@?...  
DEBUG2:   0040:  00 00 00 00 00 09 03 00  05 6c 65 76 65 6c 02 00   .........level..  
DEBUG2:   0050:  06 73 74 61 74 75 73 00  04 63 6f 64 65 02 00 1d   .status..code...  
DEBUG2:   0060:  4e 65 74 43 6f 6e 6e 65  63 74 69 6f 6e 2e 43 6f   NetConnection.Co  
DEBUG2:   0070:  6e 6e 65 63 74 2e 53 75  63 63 65 73 73 00 0b 64   nnect.Success..d  
DEBUG2:   0080:  65 73 63 72 69 70 74 69  6f 6e 02 00 15 43 6f 6e   escription...Con  
DEBUG2:   0090:  6e 65 63 74 69 6f 6e 20  73 75 63 63 65 65 64 65   nection succeede  
DEBUG2:   00a0:  64 2e 00 0e 6f 62 6a 65  63 74 45 6e 63 6f 64 69   d...objectEncodi  
DEBUG2:   00b0:  6e 67 00 00 00 00 00 00  00 00 00 00 00 09         ng............    
DEBUG: RTMP_ClientPacket, received: invoke 190 bytes
DEBUG: (object begin)
DEBUG: Property: <Name:           no-name., STRING: _result>
DEBUG: Property: <Name:           no-name., NUMBER: 1.00>
DEBUG: Property: <Name:           no-name., OBJECT>
DEBUG: (object begin)
DEBUG: Property: <Name:             fmsVer, STRING: FMS/3,0,1,123>
DEBUG: Property: <Name:       capabilities, NUMBER: 31.00>
DEBUG: (object end)
DEBUG: Property: <Name:           no-name., OBJECT>
DEBUG: (object begin)
DEBUG: Property: <Name:              level, STRING: status>
DEBUG: Property: <Name:               code, STRING: NetConnection.Connect.Success>
DEBUG: Property: <Name:        description, STRING: Connection succeeded.>
DEBUG: Property: <Name:     objectEncoding, NUMBER: 0.00>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <connect>
DEBUG2: RTMP_SendPacket: fd=5, size=4
DEBUG2:   0000:  02 00 00 00 00 00 04 05  00 00 00 00               ............      
DEBUG2:   0000:  00 4c 4b 40                                        .LK@              
DEBUG: sending ctrl. type: 0x0003
DEBUG2: RTMP_SendPacket: fd=5, size=10
DEBUG2:   0000:  42 00 00 00 00 00 0a 04                            B.......          
DEBUG2:   0000:  00 03 00 00 00 00 00 00  01 2c                     .........,        
DEBUG2: RTMP_SendPacket: fd=5, size=25
DEBUG2:   0000:  43 00 00 00 00 00 19 14                            C.......          
DEBUG2:   0000:  02 00 0c 63 72 65 61 74  65 53 74 72 65 61 6d 00   ...createStream.  
DEBUG2:   0010:  40 00 00 00 00 00 00 00  05                        @........         
DEBUG: Invoking createStream
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  03 00 00 00 00 00 1d 14  00 00 00 00               ............      
DEBUG2:   0000:  02 00 07 5f 72 65 73 75  6c 74 00 40 00 00 00 00   ..._result.@....  
DEBUG2:   0010:  00 00 00 05 00 3f f0 00  00 00 00 00 00            .....?.......     
DEBUG: RTMP_ClientPacket, received: invoke 29 bytes
DEBUG: (object begin)
DEBUG: Property: <Name:           no-name., STRING: _result>
DEBUG: Property: <Name:           no-name., NUMBER: 2.00>
DEBUG: Property: NULL
DEBUG: Property: <Name:           no-name., NUMBER: 1.00>
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <createStream>
DEBUG: SendPlay, seekTime=0, stopTime=0, sending play: streamName
DEBUG2: RTMP_SendPacket: fd=5, size=39
DEBUG2:   0000:  08 00 00 00 00 00 27 14  01 00 00 00               ......'.....      
DEBUG2:   0000:  02 00 04 70 6c 61 79 00  40 08 00 00 00 00 00 00   ...play.@.......  
DEBUG2:   0010:  05 02 00 0a 73 74 72 65  61 6d 4e 61 6d 65 00 00   ....streamName..  
DEBUG2:   0020:  00 00 00 00 00 00 00                               .......           
DEBUG: Invoking play
DEBUG: sending ctrl. type: 0x0003
DEBUG2: RTMP_SendPacket: fd=5, size=10
DEBUG2:   0000:  c2                                                 .                 
DEBUG2:   0000:  00 03 00 00 00 01 02 25  51 00                     .......%Q.        
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  05 00 00 00 00 00 60 14  01 00 00 00               ......`.....      
DEBUG2:   0000:  02 00 08 6f 6e 53 74 61  74 75 73 00 00 00 00 00   ...onStatus.....  
DEBUG2:   0010:  00 00 00 00 05 03 00 05  6c 65 76 65 6c 02 00 06   ........level...  
DEBUG2:   0020:  73 74 61 74 75 73 00 04  63 6f 64 65 02 00 14 4e   status..code...N  
DEBUG2:   0030:  65 74 53 74 72 65 61 6d  2e 50 6c 61 79 2e 53 74   etStream.Play.St  
DEBUG2:   0040:  61 72 74 00 0b 64 65 73  63 72 69 70 74 69 6f 6e   art..description  
DEBUG2:   0050:  02 00 0a 53 74 61 72 74  20 6c 69 76 65 00 00 09   ...Start live...  
DEBUG: RTMP_ClientPacket, received: invoke 96 bytes
DEBUG: (object begin)
DEBUG: Property: <Name:           no-name., STRING: onStatus>
DEBUG: Property: <Name:           no-name., NUMBER: 0.00>
DEBUG: Property: NULL
DEBUG: Property: <Name:           no-name., OBJECT>
DEBUG: (object begin)
DEBUG: Property: <Name:              level, STRING: status>
DEBUG: Property: <Name:               code, STRING: NetStream.Play.Start>
DEBUG: Property: <Name:        description, STRING: Start live>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <onStatus>
DEBUG: HandleInvoke, onStatus: NetStream.Play.Start
Starting download at: 0.000 kB
DEBUG2: RTMP_ReadPacket: fd=5
DEBUG2:   0000:  05 00 00 00 00 00 18 12  01 00 00 00               ............      
DEBUG2:   0000:  02 00 11 7c 52 74 6d 70  53 61 6d 70 6c 65 41 63   ...|RtmpSampleAc  
DEBUG2:   0010:  63 65 73 73 01 01 01 01                            cess....          
DEBUG: RTMP_ClientPacket, received: notify 24 bytes
DEBUG: (object begin)
DEBUG: Property: <Name:           no-name., STRING: |RtmpSampleAccess>
DEBUG: Property: <Name:           no-name., BOOLEAN:    TRUE>
DEBUG: Property: <Name:           no-name., BOOLEAN:    TRUE>
DEBUG: (object end)
DEBUG2: RTMP_ReadPacket: fd=5

root@a13-OLinuXino:/home/ulterior# DEBUG: RTMPSockBuf_Fill, recv returned -1. GetSockError(): 11 (Resource temporarily unavailable)
ERROR: RTMP_ReadPacket, failed to read RTMP packet header

有人知道这种方法有什么问题吗?我想念什么吗?我找到了某种参考,我应该从服务器读回用于ping请求的数据包?欢迎任何帮助.

Anybody got a clue whats wrong with this approach? Am I missing something? I found some kind of references that I should be reading back packets from server for ping requests? Any help is welcome..

推荐答案

对于您当前的问题,您使用过....

As for your current issue, have you used....

RTMP_EnableWrite(r);

RTMP_EnableWrite(r);

这篇关于使用librtmp捕获摄像机并发布视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆