📄 rtmp_amf_flv.c
字号:
return -1; } /* Check handshake */ if( p_read[0] != RTMP_HANDSHAKE ) { msg_Err( p_this, "first byte in handshake received corrupt" ); return -1; } for(i = 8; i < RTMP_HANDSHAKE_BODY_SIZE; i++ ) if( p_write[i + 1] != p_read[i + 1 + RTMP_HANDSHAKE_BODY_SIZE] ) { msg_Err( p_this, "body handshake received corrupt" ); return -1; } /* Acknowledge handshake */ i_ret = net_Write( p_this, fd, NULL, p_read + 1, RTMP_HANDSHAKE_BODY_SIZE ); if( i_ret != RTMP_HANDSHAKE_BODY_SIZE ) { msg_Err( p_this, "failed to acknowledge handshake" ); return -1; } return 0;}intrtmp_connect_active( rtmp_control_thread_t *p_thread ){ rtmp_packet_t *rtmp_packet; rtmp_body_t *rtmp_body; uint8_t *tmp_buffer; char *tmp_url; ssize_t i_ret; /* Build NetConnection.connect call */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "connect" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_STRING + strlen( "connect" ) ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_OBJECT, NULL ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "app", AMF_DATATYPE_STRING, p_thread->psz_application ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "app" ) + AMF_DATATYPE_SIZE_STRING + strlen( p_thread->psz_application ) ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "flashVer", AMF_DATATYPE_STRING, "LNX 9,0,48,0" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "flashVer" ) + AMF_DATATYPE_SIZE_STRING + strlen( "LNX 9,0,48,0" ) ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "swfUrl", AMF_DATATYPE_STRING, "file:///mac.flv" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "swfUrl" ) + AMF_DATATYPE_SIZE_STRING + strlen( "file:///mac.flv" ) ); free( tmp_buffer ); tmp_url = (char *) malloc( strlen( "rtmp://") + strlen( p_thread->url.psz_buffer ) + 1 ); if( !tmp_url ) { free( rtmp_body->body ); free( rtmp_body ); return -1; } sprintf( tmp_url, "rtmp://%s", p_thread->url.psz_buffer ); tmp_buffer = amf_encode_object_variable( "tcUrl", AMF_DATATYPE_STRING, tmp_url ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "tcUrl" ) + AMF_DATATYPE_SIZE_STRING + strlen( tmp_url ) ); free( tmp_url ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "fpad", AMF_DATATYPE_BOOLEAN, &AMF_BOOLEAN_FALSE ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "fpad" ) + AMF_DATATYPE_SIZE_BOOLEAN ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "audioCodecs", AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_AUDIOCODECS ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "audioCodecs" ) + AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "videoCodecs", AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_VIDEOCODECS ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "videoCodecs" ) + AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "videoFunction", AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_VIDEOFUNCTION ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "videoFunction" ) + AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "pageUrl", AMF_DATATYPE_STRING, "file:///mac.html" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "pageUrl" ) + AMF_DATATYPE_SIZE_STRING + strlen( "file:///mac.html" ) ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "objectEncoding", AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_OBJECTENCODING ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "objectEncoding" ) + AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_element ( AMF_DATATYPE_END_OF_OBJECT, NULL ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE, 0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet ); /* Call NetConnection.connect */ i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded ); if( i_ret != rtmp_packet->length_encoded ) { free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); msg_Err( p_thread, "failed send call NetConnection.connect" ); return -1; } free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); /* Wait for NetConnection.connect result */ vlc_mutex_lock( &p_thread->lock ); vlc_cond_wait( &p_thread->wait, &p_thread->lock ); vlc_mutex_unlock( &p_thread->lock ); if( p_thread->result_connect ) { msg_Err( p_thread, "failed call NetConnection.connect" ); return -1; } /* Force control thread to stop if receive NetStream.play call and wait is not ready */ vlc_mutex_lock( &p_thread->lock ); /* Build NetStream.createStream call */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "createStream" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_STRING + strlen( "createStream" ) ); free( tmp_buffer ); p_thread->stream_client_id = RTMP_DEFAULT_STREAM_CLIENT_ID; tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &AMF_CALL_STREAM_CLIENT_NUMBER ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE, 0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet ); /* Call NetStream.createStream */ i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded ); if( i_ret != rtmp_packet->length_encoded ) { free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); msg_Err( p_thread, "failed send call NetStream.createStream" ); return -1; } free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer );/*TODO: read server stream number*/ /* Build ping packet */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = rtmp_encode_ping( RTMP_PING_BUFFER_TIME_CLIENT, RTMP_SRC_DST_CONNECT_OBJECT, RTMP_TIME_CLIENT_BUFFER, 0 ); rtmp_body_append( rtmp_body, tmp_buffer, RTMP_PING_SIZE_BUFFER_TIME_CLIENT ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL, 0, RTMP_CONTENT_TYPE_PING, 0, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet ); /* Send ping packet */ i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded ); if( i_ret != rtmp_packet->length_encoded ) { free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); msg_Err( p_thread, "failed send ping BUFFER_TIME_CLIENT" ); return -1; } free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); /* Build NetStream.play call */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "play" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_STRING + strlen( "play" ) ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &AMF_CALL_NETSTREAM_PLAY ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, p_thread->psz_media ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_STRING + strlen( p_thread->psz_media ) ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE, 0, RTMP_CONTENT_TYPE_INVOKE, RTMP_SRC_DST_DEFAULT, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet ); /* Call NetStream.play */ i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded ); if( i_ret != rtmp_packet->length_encoded ) { free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); msg_Err( p_thread, "failed send call NetStream.play" ); return -1; } free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); /* Build ping packet */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = rtmp_encode_ping( RTMP_PING_BUFFER_TIME_CLIENT, RTMP_SRC_DST_CONNECT_OBJECT2, RTMP_TIME_CLIENT_BUFFER, 0 ); rtmp_body_append( rtmp_body, tmp_buffer, RTMP_PING_SIZE_BUFFER_TIME_CLIENT ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL, 0, RTMP_CONTENT_TYPE_PING, 0, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet ); /* Send ping packet */ i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded ); if( i_ret != rtmp_packet->length_encoded ) { free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); msg_Err( p_thread, "failed send ping BUFFER_TIME_CLIENT" ); return -1; } free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); /* Wait for NetStream.play.start result */ vlc_cond_wait( &p_thread->wait, &p_thread->lock ); vlc_mutex_unlock( &p_thread->lock ); if( p_thread->result_play ) { msg_Err( p_thread, "failed call NetStream.play" ); return -1; } /* Next packet is the beginning of flv stream */ msg_Dbg( p_thread, "next packet is the beginning of flv stream" ); return 0;}intrtmp_connect_passive( rtmp_control_thread_t *p_thread ){ /* Force control thread to stop if receive NetStream.play call and wait is not ready */ vlc_mutex_lock( &p_thread->lock ); /* Wait for NetStream.play.start result */ vlc_cond_wait( &p_thread->wait, &p_thread->lock ); vlc_mutex_unlock( &p_thread->lock ); if( p_thread->result_play ) { msg_Err( p_thread, "failed call NetStream.play" ); return -1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -