⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtmp_amf_flv.c

📁 vlc源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * rtmp_amf_flv.c: RTMP, AMF and FLV over RTMP implementation. ***************************************************************************** * Copyright (C) URJC - LADyR - Luis Lopez Fernandez * * Author: Miguel Angel Cabrera Moya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * RTMP header: ******************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_access.h>#include <vlc_network.h> /* DOWN: #include <network.h> */#include <vlc_url.h>#include <vlc_block.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include "rtmp_amf_flv.h"/* header length (including itself) */const uint8_t RTMP_HEADER_SIZE_MASK = 0xC0;const uint8_t RTMP_HEADER_SIZE_12 = 0x00; const uint8_t RTMP_HEADER_SIZE_8 = 0x40;const uint8_t RTMP_HEADER_SIZE_4 = 0x80;const uint8_t RTMP_HEADER_SIZE_1 = 0xC0;/* streams */const uint8_t RTMP_HEADER_STREAM_MAX = 64;const uint8_t RTMP_HEADER_STREAM_INDEX_MASK = 0x3F;/* handshake */const uint8_t RTMP_HANDSHAKE = 0x03;const uint16_t RTMP_HANDSHAKE_BODY_SIZE = 1536;/* content types */const uint8_t RTMP_CONTENT_TYPE_CHUNK_SIZE = 0x01;const uint8_t RTMP_CONTENT_TYPE_UNKNOWN_02 = 0x02;const uint8_t RTMP_CONTENT_TYPE_BYTES_READ = 0x03;const uint8_t RTMP_CONTENT_TYPE_PING = 0x04;const uint8_t RTMP_CONTENT_TYPE_SERVER_BW = 0x05;const uint8_t RTMP_CONTENT_TYPE_CLIENT_BW = 0x06;const uint8_t RTMP_CONTENT_TYPE_UNKNOWN_07 = 0x07;const uint8_t RTMP_CONTENT_TYPE_AUDIO_DATA = 0x08;const uint8_t RTMP_CONTENT_TYPE_VIDEO_DATA = 0x09;const uint8_t RTMP_CONTENT_TYPE_UNKNOWN_0A_0E = 0x0A;const uint8_t RTMP_CONTENT_TYPE_FLEX_STREAM = 0x0F;const uint8_t RTMP_CONTENT_TYPE_FLEX_SHARED_OBJECT = 0x10;const uint8_t RTMP_CONTENT_TYPE_MESSAGE = 0x11;const uint8_t RTMP_CONTENT_TYPE_NOTIFY = 0x12;const uint8_t RTMP_CONTENT_TYPE_SHARED_OBJECT = 0x13;const uint8_t RTMP_CONTENT_TYPE_INVOKE = 0x14;/* shared object datatypes */const uint8_t RTMP_SHARED_OBJECT_DATATYPE_CONNECT = 0x01;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_DISCONNECT = 0x02;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_SET_ATTRIBUTE = 0x03;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_UPDATE_DATA = 0x04;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_UPDATE_ATTRIBUTE = 0x05;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_SEND_MESSAGE = 0x06;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_STATUS = 0x07;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_CLEAR_DATA = 0x08;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_DELETE_DATA = 0x09;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_DELETE_ATTRIBUTE = 0x0A;const uint8_t RTMP_SHARED_OBJECT_DATATYPE_INITIAL_DATA = 0x0B;/* pings */const uint16_t RTMP_PING_CLEAR_STREAM = 0x0000;const uint16_t RTMP_PING_CLEAR_PLAYING_BUFFER = 0x0001;const uint16_t RTMP_PING_BUFFER_TIME_CLIENT = 0x0003;const uint16_t RTMP_PING_RESET_STREAM = 0x0004;const uint16_t RTMP_PING_CLIENT_FROM_SERVER = 0x0006;const uint16_t RTMP_PING_PONG_FROM_CLIENT = 0x0007;/* pings sizes */const uint8_t RTMP_PING_SIZE_CLEAR_STREAM = 6;const uint8_t RTMP_PING_SIZE_CLEAR_PLAYING_BUFFER = 6;const uint8_t RTMP_PING_SIZE_BUFFER_TIME_CLIENT = 10;const uint8_t RTMP_PING_SIZE_RESET_STREAM = 6;/*const uint8_t RTMP_PING_SIZE_CLIENT_FROM_SERVER = 0x0006; TODOconst uint8_t RTMP_PING_SIZE_PONG_FROM_CLIENT = 0x0007;*//* default values */const uint8_t RTMP_DEFAULT_STREAM_INDEX_CONTROL = 0x02;const uint8_t RTMP_DEFAULT_STREAM_INDEX_INVOKE = 0x03;const uint8_t RTMP_DEFAULT_STREAM_INDEX_NOTIFY = 0x04;const uint8_t RTMP_DEFAULT_STREAM_INDEX_VIDEO_DATA = 0x05;const uint8_t RTMP_DEFAULT_STREAM_INDEX_AUDIO_DATA = 0x06;const uint32_t RTMP_DEFAULT_CHUNK_SIZE = 128;const double RTMP_DEFAULT_STREAM_CLIENT_ID = 1.0;const double RTMP_DEFAULT_STREAM_SERVER_ID = 1.0;/* misc */const uint16_t MAX_EMPTY_BLOCKS = 200; /* empty blocks in fifo for media*/const uint16_t RTMP_BODY_SIZE_ALLOC = 1024;const uint32_t RTMP_TIME_CLIENT_BUFFER = 2000; /* miliseconds */const uint32_t RTMP_SERVER_BW = 0x00000200;const uint32_t RTMP_SRC_DST_CONNECT_OBJECT = 0x00000000;const uint32_t RTMP_SRC_DST_CONNECT_OBJECT2 = 0x00000001;const uint32_t RTMP_SRC_DST_DEFAULT = 0x01000000;const uint64_t RTMP_AUDIOCODECS = 0x4083380000000000;const uint64_t RTMP_VIDEOCODECS = 0x405f000000000000;const uint64_t RTMP_VIDEOFUNCTION = 0x3ff0000000000000;/***************************************************************************** * AMF header: ******************************************************************************//* boolean constants */const uint8_t AMF_BOOLEAN_FALSE = 0x00;const uint8_t AMF_BOOLEAN_TRUE = 0x01;/* datatypes */const uint8_t AMF_DATATYPE_NUMBER = 0x00;const uint8_t AMF_DATATYPE_BOOLEAN = 0x01;const uint8_t AMF_DATATYPE_STRING = 0x02;const uint8_t AMF_DATATYPE_OBJECT = 0x03;const uint8_t AMF_DATATYPE_MOVIE_CLIP = 0x04;const uint8_t AMF_DATATYPE_NULL = 0x05;const uint8_t AMF_DATATYPE_UNDEFINED = 0x06;const uint8_t AMF_DATATYPE_REFERENCE = 0x07;const uint8_t AMF_DATATYPE_MIXED_ARRAY = 0x08;const uint8_t AMF_DATATYPE_END_OF_OBJECT = 0x09;const uint8_t AMF_DATATYPE_ARRAY = 0x0A;const uint8_t AMF_DATATYPE_DATE = 0x0B;const uint8_t AMF_DATATYPE_LONG_STRING = 0x0C;const uint8_t AMF_DATATYPE_UNSUPPORTED = 0x0D;const uint8_t AMF_DATATYPE_RECORDSET = 0x0E;const uint8_t AMF_DATATYPE_XML = 0x0F;const uint8_t AMF_DATATYPE_TYPED_OBJECT = 0x10;const uint8_t AMF_DATATYPE_AMF3_DATA = 0x11;/* datatypes sizes */const uint8_t AMF_DATATYPE_SIZE_NUMBER = 9;const uint8_t AMF_DATATYPE_SIZE_BOOLEAN = 2;const uint8_t AMF_DATATYPE_SIZE_STRING = 3;const uint8_t AMF_DATATYPE_SIZE_OBJECT = 1;const uint8_t AMF_DATATYPE_SIZE_NULL = 1;const uint8_t AMF_DATATYPE_SIZE_OBJECT_VARIABLE = 2;const uint8_t AMF_DATATYPE_SIZE_MIXED_ARRAY = 5;const uint8_t AMF_DATATYPE_SIZE_END_OF_OBJECT = 3;/* amf remote calls */const uint64_t AMF_CALL_NETCONNECTION_CONNECT = 0x3FF0000000000000;const uint64_t AMF_CALL_NETCONNECTION_CONNECT_AUDIOCODECS = 0x4083380000000000;const uint64_t AMF_CALL_NETCONNECTION_CONNECT_VIDEOCODECS = 0x405F000000000000;const uint64_t AMF_CALL_NETCONNECTION_CONNECT_VIDEOFUNCTION = 0x3FF0000000000000;const uint64_t AMF_CALL_NETCONNECTION_CONNECT_OBJECTENCODING = 0x0;const double AMF_CALL_STREAM_CLIENT_NUMBER = 3.0;const double AMF_CALL_ONBWDONE = 2.0; const uint64_t AMF_CALL_NETSTREAM_PLAY = 0x0;/***************************************************************************** * FLV header: ******************************************************************************/const uint8_t FLV_HEADER_SIGNATURE[3] = { 0x46, 0x4C, 0x56 }; /* always "FLV" */const uint8_t FLV_HEADER_VERSION = 0x01;const uint8_t FLV_HEADER_AUDIO = 0x04;const uint8_t FLV_HEADER_VIDEO = 0x01;const uint32_t FLV_HEADER_SIZE = 0x00000009; /* always 9 for known FLV files */const uint32_t FLV_TAG_FIRST_PREVIOUS_TAG_SIZE = 0x00000000;const uint8_t FLV_TAG_PREVIOUS_TAG_SIZE = 4;const uint8_t FLV_TAG_SIZE = 11;/* audio stereo types */const uint8_t FLV_AUDIO_STEREO_MASK = 0x01;const uint8_t FLV_AUDIO_STEREO_MONO = 0x00;const uint8_t FLV_AUDIO_STEREO_STEREO = 0x01;/* audio size */const uint8_t FLV_AUDIO_SIZE_MASK = 0x02;const uint8_t FLV_AUDIO_SIZE_8_BIT = 0x00;const uint8_t FLV_AUDIO_SIZE_16_BIT = 0x02;/* audio rate */const uint8_t FLV_AUDIO_RATE_MASK = 0x0C;const uint8_t FLV_AUDIO_RATE_5_5_KHZ = 0x00;const uint8_t FLV_AUDIO_RATE_11_KHZ = 0x04;const uint8_t FLV_AUDIO_RATE_22_KHZ = 0x08;const uint8_t FLV_AUDIO_RATE_44_KHZ = 0x0C;/* audio codec types */const uint8_t FLV_AUDIO_CODEC_ID_MASK = 0xF0;const uint8_t FLV_AUDIO_CODEC_ID_UNCOMPRESSED = 0x00;const uint8_t FLV_AUDIO_CODEC_ID_ADPCM = 0x10;const uint8_t FLV_AUDIO_CODEC_ID_MP3 = 0x20;const uint8_t FLV_AUDIO_CODEC_ID_NELLYMOSER_8KHZ_MONO = 0x50;const uint8_t FLV_AUDIO_CODEC_ID_NELLYMOSER = 0x60;/* video codec types */const uint8_t FLV_VIDEO_CODEC_ID_MASK = 0x0F;const uint8_t FLV_VIDEO_CODEC_ID_SORENSEN_H263 = 0x02;const uint8_t FLV_VIDEO_CODEC_ID_SCREEN_VIDEO = 0x03;const uint8_t FLV_VIDEO_CODEC_ID_ON2_VP6 = 0x04;const uint8_t FLV_VIDEO_CODEC_ID_ON2_VP6_ALPHA = 0x05;const uint8_t FLV_VIDEO_CODEC_ID_SCREEN_VIDEO_2 = 0x06;/* video frame types */const uint8_t FLV_VIDEO_FRAME_TYPE_MASK = 0xF0;const uint8_t FLV_VIDEO_FRAME_TYPE_KEYFRAME = 0x10;const uint8_t FLV_VIDEO_FRAME_TYPE_INTER_FRAME = 0x20;const uint8_t FLV_VIDEO_FRAME_TYPE_DISPOSABLE_INTER_FRAME = 0x30;/***************************************************************************** * static RTMP functions: ******************************************************************************/static void rtmp_handler_null       ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static void rtmp_handler_chunk_size ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static void rtmp_handler_invoke     ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static void rtmp_handler_audio_data ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static void rtmp_handler_video_data ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static void rtmp_handler_notify     ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static rtmp_packet_t *rtmp_new_packet( rtmp_control_thread_t *p_thread, uint8_t stream_index, uint32_t timestamp, uint8_t content_type, uint32_t src_dst, rtmp_body_t *body );static block_t *rtmp_new_block( rtmp_control_thread_t *p_thread, uint8_t *buffer, int32_t length_buffer );static rtmp_packet_t *rtmp_encode_onBWDone( rtmp_control_thread_t *p_thread, double number );static rtmp_packet_t *rtmp_encode_server_bw( rtmp_control_thread_t *p_thread, uint32_t number );static rtmp_packet_t *rtmp_encode_NetConnection_connect_result( rtmp_control_thread_t *p_thread, double number );static rtmp_packet_t *rtmp_encode_createStream_result( rtmp_control_thread_t *p_thread, double stream_client, double stream_server );static rtmp_packet_t *rtmp_encode_ping_reset_stream( rtmp_control_thread_t *p_thread );static rtmp_packet_t *rtmp_encode_ping_clear_stream( rtmp_control_thread_t *p_thread, uint32_t src_dst );static rtmp_packet_t *rtmp_encode_NetStream_play_reset_onStatus( rtmp_control_thread_t *p_thread, char *psz_media );static rtmp_packet_t *rtmp_encode_NetStream_play_start_onStatus( rtmp_control_thread_t *p_thread, char *psz_media );static uint8_t rtmp_encode_header_size( vlc_object_t *p_this, uint8_t header_size );static uint8_t rtmp_decode_header_size( vlc_object_t *p_this, uint8_t header_size );static uint8_t rtmp_get_stream_index( uint8_t content_type );static void rtmp_body_append( rtmp_body_t *rtmp_body, uint8_t *buffer, uint32_t length );static uint8_t *rtmp_encode_ping( uint16_t type, uint32_t src_dst, uint32_t third_arg, uint32_t fourth_arg );/***************************************************************************** * static AMF functions: ******************************************************************************/static uint8_t *amf_encode_element( uint8_t element, const void *value );static uint8_t *amf_encode_object_variable( const char *key, uint8_t element, const void *value );static double amf_decode_number( uint8_t **buffer );static int amf_decode_boolean( uint8_t **buffer );static char *amf_decode_string( uint8_t **buffer );static char *amf_decode_object( uint8_t **buffer );/***************************************************************************** * static FLV functions: ******************************************************************************/static void flv_rebuild( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );static void flv_get_metadata_audio( rtmp_control_thread_t *p_thread, rtmp_packet_t *packet_audio, uint8_t *stereo, uint8_t *audiosamplesize, uint32_t *audiosamplerate, uint8_t *audiocodecid );static void flv_get_metadata_video( rtmp_control_thread_t *p_thread, rtmp_packet_t *packet_video, uint8_t *videocodecid, uint8_t *frametype );static rtmp_packet_t *flv_build_onMetaData( access_t *p_access, uint64_t duration, uint8_t stereo, uint8_t audiosamplesize, uint32_t audiosamplerate, uint8_t audiocodecid, uint8_t videocodecid );/***************************************************************************** * RTMP implementation: ******************************************************************************/intrtmp_handshake_passive( vlc_object_t *p_this, int fd ){    uint8_t p_read[RTMP_HANDSHAKE_BODY_SIZE + 1];    uint8_t p_write[RTMP_HANDSHAKE_BODY_SIZE * 2 + 1];    ssize_t i_ret;    int i;    /* Receive handshake */    i_ret = net_Read( p_this, fd, NULL, p_read, RTMP_HANDSHAKE_BODY_SIZE + 1, true );    if( i_ret != RTMP_HANDSHAKE_BODY_SIZE + 1 )    {        msg_Err( p_this, "failed to receive handshake" );        return -1;    }    /* Check handshake */    if ( p_read[0] != RTMP_HANDSHAKE )    {        msg_Err( p_this, "first byte in handshake corrupt" );        return -1;    }    /* Answer handshake */    p_write[0] = RTMP_HANDSHAKE;    memset( p_write + 1, 0, RTMP_HANDSHAKE_BODY_SIZE );    memcpy( p_write + 1 + RTMP_HANDSHAKE_BODY_SIZE, p_read + 1, RTMP_HANDSHAKE_BODY_SIZE );    /* Send handshake*/    i_ret = net_Write( p_this, fd, NULL, p_write, RTMP_HANDSHAKE_BODY_SIZE * 2 + 1 );    if( i_ret != RTMP_HANDSHAKE_BODY_SIZE * 2 + 1 )    {        msg_Err( p_this, "failed to send handshake" );        return -1;    }    /* Receive acknowledge */    i_ret = net_Read( p_this, fd, NULL, p_read, RTMP_HANDSHAKE_BODY_SIZE, true );    if( i_ret != RTMP_HANDSHAKE_BODY_SIZE )    {        msg_Err( p_this, "failed to receive acknowledge" );        return -1;    }    /* Check acknowledge */    for(i = 8; i < RTMP_HANDSHAKE_BODY_SIZE; i++ )        if( p_write[i + 1] != p_read[i] )        {            msg_Err( p_this, "body acknowledge received corrupt" );            return -1;        }    return 0;}intrtmp_handshake_active( vlc_object_t *p_this, int fd ){    uint8_t p_read[RTMP_HANDSHAKE_BODY_SIZE * 2 + 1];    uint8_t p_write[RTMP_HANDSHAKE_BODY_SIZE + 1];    ssize_t i_ret;    int i;    p_write[0] = RTMP_HANDSHAKE;    for( i = 0; i < RTMP_HANDSHAKE_BODY_SIZE; i++ )        p_write[i + 1] = i & 0xFF;    /* Send handshake*/    i_ret = net_Write( p_this, fd, NULL, p_write, RTMP_HANDSHAKE_BODY_SIZE + 1 );    if( i_ret != RTMP_HANDSHAKE_BODY_SIZE + 1 )    {        msg_Err( p_this, "failed to send handshake" );        return -1;    }    /* Receive handshake */    i_ret = net_Read( p_this, fd, NULL, p_read, RTMP_HANDSHAKE_BODY_SIZE * 2 + 1, true );    if( i_ret != RTMP_HANDSHAKE_BODY_SIZE * 2 + 1 )    {        msg_Err( p_this, "failed to receive handshake" );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -