📄 rtmp_amf_flv.c
字号:
/* TODOintrtmp_seek( access_t *p_access, int64_t i_pos ){ access_sys_t *p_sys = p_access->p_sys; rtmp_packet_t *rtmp_packet; rtmp_body_t *rtmp_body; uint8_t *tmp_buffer; uint64_t tmp_number; ssize_t i_ret;msg_Warn(p_access, "i_pos %lld", i_pos); // Build NetStream.seek call // rtmp_body = rtmp_body_new(); tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "seek" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_STRING + strlen( "seek" ) ); free( tmp_buffer ); tmp_number = 0; tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &tmp_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 );//TODO: convert i_pos to double and see if they are milliseconds tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &i_pos ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_sys->p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE, 0, RTMP_DATATYPE_INVOKE, RTMP_SRC_DST_DEFAULT, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); tmp_buffer = rtmp_encode_packet( p_access, rtmp_packet ); // Call NetStream.seek // i_ret = net_Write( p_access, p_sys->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_access, "failed call NetStream.seek" ); return -1; } free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); free( tmp_buffer ); // Receive TODO: see what // rtmp_packet = rtmp_read_net_packet( p_access, p_sys->fd ); free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet ); return 0;}*/rtmp_packet_t *rtmp_build_bytes_read( rtmp_control_thread_t *p_thread, uint32_t reply ){ rtmp_packet_t *rtmp_packet; rtmp_body_t *rtmp_body; uint8_t *tmp_buffer; /* Build bytes read packet */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = (uint8_t *) malloc( sizeof( uint32_t ) * sizeof( uint8_t ) ); if( !tmp_buffer ) return NULL; reply = hton32( reply ); memcpy( tmp_buffer, &reply, sizeof( uint32_t ) ); rtmp_body_append( rtmp_body, tmp_buffer, sizeof( uint32_t ) ); free( tmp_buffer ); rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL, 0, RTMP_CONTENT_TYPE_BYTES_READ, 0, rtmp_body ); free( rtmp_body->body ); free( rtmp_body ); return rtmp_packet;}rtmp_packet_t *rtmp_build_publish_start( rtmp_control_thread_t *p_thread ){ rtmp_packet_t *rtmp_packet; rtmp_body_t *rtmp_body; uint8_t *tmp_buffer; /* Build publish start event */ rtmp_body = rtmp_body_new( -1 ); tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "onStatus" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_STRING + strlen( "onStatus" ) ); free( tmp_buffer ); tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &p_thread->stream_server_id ); 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_OBJECT, NULL ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT ); free( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "level", AMF_DATATYPE_STRING, "status" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "level" ) + AMF_DATATYPE_SIZE_STRING + strlen( "status" ) ); free ( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "code", AMF_DATATYPE_STRING, "NetStream.Publish.Start" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "code" ) + AMF_DATATYPE_SIZE_STRING + strlen( "NetStream.Publish.Start" ) ); free ( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "description", AMF_DATATYPE_STRING, "" ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "description" ) + AMF_DATATYPE_SIZE_STRING + strlen( "" ) ); free ( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "details", AMF_DATATYPE_STRING, p_thread->psz_publish ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "details" ) + AMF_DATATYPE_SIZE_STRING + strlen( p_thread->psz_publish ) ); free ( tmp_buffer ); tmp_buffer = amf_encode_object_variable( "clientid", AMF_DATATYPE_NUMBER, &p_thread->stream_client_id ); rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "clientid" ) + 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 ); return rtmp_packet;}rtmp_packet_t *rtmp_build_flv_over_rtmp( rtmp_control_thread_t *p_thread, block_t *p_buffer ){ rtmp_packet_t *rtmp_packet; if( p_thread->flv_length_body > 0 ) { p_thread->flv_length_body -= p_buffer->i_buffer; rtmp_body_append( p_thread->flv_body, p_buffer->p_buffer, p_buffer->i_buffer ); if( p_thread->flv_length_body > 0 ) return NULL; } else { p_thread->flv_content_type = *p_buffer->p_buffer; p_buffer->p_buffer[0] = 0; p_thread->flv_length_body = ntoh32( *(uint32_t *) (p_buffer->p_buffer) ); p_buffer->p_buffer[3] = 0; p_thread->flv_timestamp = ntoh32( *(uint32_t *) (p_buffer->p_buffer + 3) ); } if( p_thread->flv_length_body > p_buffer->i_buffer - FLV_TAG_SIZE - FLV_TAG_PREVIOUS_TAG_SIZE ) { p_thread->flv_length_body -= p_buffer->i_buffer - FLV_TAG_SIZE - FLV_TAG_PREVIOUS_TAG_SIZE; rtmp_body_append( p_thread->flv_body, p_buffer->p_buffer + FLV_TAG_SIZE, p_buffer->i_buffer - FLV_TAG_SIZE ); return NULL; } else { rtmp_body_append( p_thread->flv_body, p_buffer->p_buffer + FLV_TAG_SIZE, p_thread->flv_length_body ); } rtmp_packet = rtmp_new_packet( p_thread, rtmp_get_stream_index( p_thread->flv_content_type ), p_thread->flv_timestamp, p_thread->flv_content_type, RTMP_SRC_DST_DEFAULT, p_thread->flv_body ); p_thread->flv_length_body = 0; rtmp_body_reset( p_thread->flv_body ); return rtmp_packet;}rtmp_packet_t *rtmp_read_net_packet( rtmp_control_thread_t *p_thread ){ int length_header; int stream_index; int bytes_left; uint8_t p_read[12]; rtmp_packet_t *rtmp_packet; ssize_t i_ret; for(;;) { i_ret = net_Read( p_thread, p_thread->fd, NULL, p_read, 1, true ); if( i_ret != 1 ) goto error; length_header = rtmp_decode_header_size( (vlc_object_t *) p_thread, p_read[0] & RTMP_HEADER_SIZE_MASK ); stream_index = p_read[0] & RTMP_HEADER_STREAM_INDEX_MASK; i_ret = net_Read( p_thread, p_thread->fd, NULL, p_read + 1, length_header - 1, true ); if( i_ret != length_header - 1 ) goto error; /* Update timestamp if not is an interchunk packet */ if( length_header == 1 && p_thread->rtmp_headers_recv[stream_index].body == NULL ) { p_thread->rtmp_headers_recv[stream_index].timestamp += p_thread->rtmp_headers_recv[stream_index].timestamp_relative; } /* Length 4 and 8 headers have relative timestamp */ if( length_header == 4 || length_header == 8 ) { p_read[0] = 0; p_thread->rtmp_headers_recv[stream_index].timestamp_relative = ntoh32( *(uint32_t *) p_read ); p_thread->rtmp_headers_recv[stream_index].timestamp += p_thread->rtmp_headers_recv[stream_index].timestamp_relative; } if( length_header >= 8 ) { p_read[3] = 0; p_thread->rtmp_headers_recv[stream_index].length_body = ntoh32( *(uint32_t *) (p_read + 3) ); p_thread->rtmp_headers_recv[stream_index].content_type = p_read[7]; } /* Length 12 headers have absolute timestamp */ if( length_header >= 12 ) { p_read[0] = 0; p_thread->rtmp_headers_recv[stream_index].timestamp = ntoh32( *(uint32_t *) p_read ); p_thread->rtmp_headers_recv[stream_index].src_dst = ntoh32( *(uint32_t *) (p_read + 8) ); } if( p_thread->rtmp_headers_recv[stream_index].body == NULL ) { p_thread->rtmp_headers_recv[stream_index].body = rtmp_body_new( p_thread->rtmp_headers_recv[stream_index].length_body ); } bytes_left = p_thread->rtmp_headers_recv[stream_index].body->length_buffer - p_thread->rtmp_headers_recv[stream_index].body->length_body; if( bytes_left > p_thread->chunk_size_recv ) bytes_left = p_thread->chunk_size_recv; i_ret = net_Read( p_thread, p_thread->fd, NULL, p_thread->rtmp_headers_recv[stream_index].body->body + p_thread->rtmp_headers_recv[stream_index].body->length_body, bytes_left, true ); if( i_ret != bytes_left ) goto error; p_thread->rtmp_headers_recv[stream_index].body->length_body += bytes_left; if( p_thread->rtmp_headers_recv[stream_index].length_body == p_thread->rtmp_headers_recv[stream_index].body->length_body ) { rtmp_packet = (rtmp_packet_t *) malloc( sizeof( rtmp_packet_t ) ); if( !rtmp_packet ) goto error; rtmp_packet->stream_index = stream_index; rtmp_packet->timestamp = p_thread->rtmp_headers_recv[stream_index].timestamp; rtmp_packet->timestamp_relative = p_thread->rtmp_headers_recv[stream_index].timestamp_relative; rtmp_packet->content_type = p_thread->rtmp_headers_recv[stream_index].content_type; rtmp_packet->src_dst = p_thread->rtmp_headers_recv[stream_index].src_dst; rtmp_packet->length_body = p_thread->rtmp_headers_recv[stream_index].length_body; rtmp_packet->body = p_thread->rtmp_headers_recv[stream_index].body; p_thread->rtmp_headers_recv[stream_index].body = NULL; return rtmp_packet; } }error: msg_Err( p_thread, "rtmp_read_net_packet: net_Read error"); return NULL;}voidrtmp_init_handler( rtmp_handler_t *rtmp_handler ){ rtmp_handler[RTMP_CONTENT_TYPE_CHUNK_SIZE] = rtmp_handler_chunk_size; rtmp_handler[RTMP_CONTENT_TYPE_UNKNOWN_02] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_BYTES_READ] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_PING] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_SERVER_BW] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_CLIENT_BW] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_UNKNOWN_07] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_AUDIO_DATA] = rtmp_handler_audio_data; rtmp_handler[RTMP_CONTENT_TYPE_VIDEO_DATA] = rtmp_handler_video_data; rtmp_handler[RTMP_CONTENT_TYPE_UNKNOWN_0A_0E] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_FLEX_STREAM] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_FLEX_SHARED_OBJECT] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_MESSAGE] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_NOTIFY] = rtmp_handler_notify; rtmp_handler[RTMP_CONTENT_TYPE_SHARED_OBJECT] = rtmp_handler_null; rtmp_handler[RTMP_CONTENT_TYPE_INVOKE] = rtmp_handler_invoke;}static voidrtmp_handler_null( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet ){ VLC_UNUSED(p_thread); free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet );}static voidrtmp_handler_chunk_size( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet ){ p_thread->chunk_size_recv = ntoh32( *(uint32_t *) (rtmp_packet->body->body) ); free( rtmp_packet->body->body ); free( rtmp_packet->body ); free( rtmp_packet );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -