/** * The MIT License (MIT) * * Copyright (c) 2013-2017 SRS(ossrs) * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef SRS_LIB_RTMP_HPP #define SRS_LIB_RTMP_HPP /** * srs-librtmp is a librtmp like library, * used to play/publish rtmp stream from/to rtmp server. * socket: use sync and block socket to connect/recv/send data with server. * depends: no need other libraries; depends on ssl if use srs_complex_handshake. * thread-safe: no */ /************************************************************* ************************************************************** * Windows SRS-LIBRTMP pre-declare ************************************************************** *************************************************************/ // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213 #ifdef _WIN32 // include windows first. #include // the type used by this header for windows. typedef unsigned long long u_int64_t; typedef u_int64_t uint64_t; typedef long long int64_t; typedef unsigned int u_int32_t; typedef u_int32_t uint32_t; typedef int int32_t; typedef unsigned char u_int8_t; typedef u_int8_t uint8_t; typedef char int8_t; typedef unsigned short u_int16_t; typedef u_int16_t uint16_t; typedef short int16_t; typedef int64_t ssize_t; struct iovec { void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfer */ }; // for pid. typedef int pid_t; pid_t getpid(void); #endif #include #include #ifdef __cplusplus extern "C"{ #endif /** * The schema of RTMP url, the following are legal urls: * srs_url_schema_normal: rtmp://vhost:port/app/stream * srs_url_schema_via : rtmp://ip:port/vhost/app/stream * srs_url_schema_vis : rtmp://ip:port/app/stream?vhost=xxx * srs_url_schema_vis2 : rtmp://ip:port/app/stream?domain=xxx */ enum srs_url_schema { // Forbidden. srs_url_schema_forbidden = 0, // Normal RTMP URL, the vhost put in host field, using DNS to resolve the server ip. // For example, rtmp://vhost:port/app/stream srs_url_schema_normal, // VIA(vhost in app), the vhost put in app field. // For example, rtmp://ip:port/vhost/app/stream srs_url_schema_via, // VIS(vhost in stream), the vhost put in query string, keyword use vhost=xxx. // For example, rtmp://ip:port/app/stream?vhost=xxx srs_url_schema_vis, // VIS, keyword use domain=xxx. // For example, rtmp://ip:port/app/stream?domain=xxx srs_url_schema_vis2 }; // typedefs typedef int srs_bool; /************************************************************* ************************************************************** * srs-librtmp version ************************************************************** *************************************************************/ extern int srs_version_major(); extern int srs_version_minor(); extern int srs_version_revision(); /************************************************************* ************************************************************** * RTMP protocol context ************************************************************** *************************************************************/ // the RTMP handler. typedef void* srs_rtmp_t; typedef void* srs_amf0_t; /** * Create a RTMP handler. * @param url The RTMP url, for example, rtmp://localhost/live/livestream * @remark default timeout to 30s if not set by srs_rtmp_set_timeout. * @remark default schema to srs_url_schema_normal, use srs_rtmp_set_schema to change it. * * @return a rtmp handler, or NULL if error occured. */ extern srs_rtmp_t srs_rtmp_create(const char* url); /** * set socket timeout * @param recv_timeout_ms the timeout for receiving messages in ms. * @param send_timeout_ms the timeout for sending message in ms. * @remark user can set timeout once srs_rtmp_create/srs_rtmp_create2, * or before srs_rtmp_handshake or srs_rtmp_dns_resolve to connect to server. * @remark default timeout to 30s if not set by srs_rtmp_set_timeout. * * @return 0, success; otherswise, failed. */ extern int srs_rtmp_set_timeout(srs_rtmp_t rtmp, int recv_timeout_ms, int send_timeout_ms); /** * close and destroy the rtmp stack. * @remark, user should never use the rtmp again. */ extern void srs_rtmp_destroy(srs_rtmp_t rtmp); /************************************************************* ************************************************************** * RTMP protocol stack ************************************************************** *************************************************************/ /** * connect and handshake with server * category: publish/play * previous: rtmp-create * next: connect-app * * @return 0, success; otherswise, failed. */ /** * simple handshake specifies in rtmp 1.0, * not depends on ssl. */ /** * srs_rtmp_handshake equals to invoke: * srs_rtmp_dns_resolve() * srs_rtmp_connect_server() * srs_rtmp_do_simple_handshake() * user can use these functions if needed. */ extern int srs_rtmp_handshake(srs_rtmp_t rtmp); // parse uri, create socket, resolve host extern int srs_rtmp_dns_resolve(srs_rtmp_t rtmp); // connect socket to server extern int srs_rtmp_connect_server(srs_rtmp_t rtmp); // do simple handshake over socket. extern int srs_rtmp_do_simple_handshake(srs_rtmp_t rtmp); // do complex handshake over socket. extern int srs_rtmp_do_complex_handshake(srs_rtmp_t rtmp); /** * set the args of connect packet for rtmp. * @param args, the extra amf0 object args. * @remark, all params can be NULL to ignore. * @remark, user should never free the args for we directly use it. */ extern int srs_rtmp_set_connect_args(srs_rtmp_t rtmp, const char* tcUrl, const char* swfUrl, const char* pageUrl, srs_amf0_t args); /** * Set the schema of URL when connect to tcUrl by srs_rtmp_connect_app. * @param schema, The schema of URL, @see srs_url_schema. * @return 0, success; otherswise, failed. */ extern int srs_rtmp_set_schema(srs_rtmp_t rtmp, enum srs_url_schema schema); /** * Connect to RTMP tcUrl(Vhost/App), similar to flash AS3 NetConnection.connect(tcUrl). * @remark When connected to server, user can retrieve informations from RTMP handler, * for example, use srs_rtmp_get_server_id to get server ip/pid/cid. * @return 0, success; otherswise, failed. */ extern int srs_rtmp_connect_app(srs_rtmp_t rtmp); /** * Retrieve server ip from RTMP handler. * @Param ip A NULL terminated string specifies the server ip. * @Param pid An int specifies the PID of server. -1 is no PID information. * @Param cid An int specifies the CID of connection. -1 is no CID information. * @remark For SRS, ip/pid/cid is the UUID of a client. For other server, these values maybe unknown. * @remark When connected to server by srs_rtmp_connect_app, the information is ready to be retrieved. * @return 0, success; otherswise, failed. */ extern int srs_rtmp_get_server_id(srs_rtmp_t rtmp, char** ip, int* pid, int* cid); /** * Retrieve server signature from RTMP handler. * @Param sig A NULL terminated string specifies the server signature. * @remark When connected to server by srs_rtmp_connect_app, the information is ready to be retrieved. * @return 0, success; otherswise, failed. */ extern int srs_rtmp_get_server_sig(srs_rtmp_t rtmp, char** sig); /** * Retrieve server version from RTMP handler, which in major.minor.revision.build format. * @remark When connected to server by srs_rtmp_connect_app, the information is ready to be retrieved. * @return 0, success; otherswise, failed. */ extern int srs_rtmp_get_server_version(srs_rtmp_t rtmp, int* major, int* minor, int* revision, int* build); /** * play a live/vod stream. * category: play * previous: connect-app * next: destroy * @return 0, success; otherwise, failed. */ extern int srs_rtmp_play_stream(srs_rtmp_t rtmp); /** * publish a live stream. * category: publish * previous: connect-app * next: destroy * @return 0, success; otherwise, failed. */ extern int srs_rtmp_publish_stream(srs_rtmp_t rtmp); /** * do bandwidth check with srs server. * * bandwidth info: * @param start_time, output the start time, in ms. * @param end_time, output the end time, in ms. * @param play_kbps, output the play/download kbps. * @param publish_kbps, output the publish/upload kbps. * @param play_bytes, output the play/download bytes. * @param publish_bytes, output the publish/upload bytes. * @param play_duration, output the play/download test duration, in ms. * @param publish_duration, output the publish/upload test duration, in ms. * * @return 0, success; otherswise, failed. */ extern int srs_rtmp_bandwidth_check(srs_rtmp_t rtmp, int64_t* start_time, int64_t* end_time, int* play_kbps, int* publish_kbps, int* play_bytes, int* publish_bytes, int* play_duration, int* publish_duration); /** * E.4.1 FLV Tag, page 75 */ // 8 = audio #define SRS_RTMP_TYPE_AUDIO 8 // 9 = video #define SRS_RTMP_TYPE_VIDEO 9 // 18 = script data #define SRS_RTMP_TYPE_SCRIPT 18 /** * read a audio/video/script-data packet from rtmp stream. * @param type, output the packet type, macros: * SRS_RTMP_TYPE_AUDIO, FlvTagAudio * SRS_RTMP_TYPE_VIDEO, FlvTagVideo * SRS_RTMP_TYPE_SCRIPT, FlvTagScript * otherswise, invalid type. * @param timestamp, in ms, overflow in 50days * @param data, the packet data, according to type: * FlvTagAudio, @see "E.4.2.1 AUDIODATA" * FlvTagVideo, @see "E.4.3.1 VIDEODATA" * FlvTagScript, @see "E.4.4.1 SCRIPTDATA" * User can free the packet by srs_rtmp_free_packet. * @param size, size of packet. * @return the error code. 0 for success; otherwise, error. * * @remark: for read, user must free the data. * @remark: for write, user should never free the data, even if error. * @example /trunk/research/librtmp/srs_play.c * @example /trunk/research/librtmp/srs_publish.c * * @return 0, success; otherswise, failed. */ extern int srs_rtmp_read_packet(srs_rtmp_t rtmp, char* type, uint32_t* timestamp, char** data, int* size); // @Param data User should never free it anymore. extern int srs_rtmp_write_packet(srs_rtmp_t rtmp, char type, uint32_t timestamp, char* data, int size); /** * Free the packet allocated by srs_rtmp_read_packet. */ extern void srs_rtmp_free_packet(char* data); /** * whether type is script data and the data is onMetaData. */ extern srs_bool srs_rtmp_is_onMetaData(char type, char* data, int size); /************************************************************* ************************************************************** * audio raw codec ************************************************************** *************************************************************/ /** * 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 ISO_IEC_14496-3-AAC-2001.pdf, page 75, 1.A.2.2 ADTS * @remark for aac, only support profile 1-4, AAC main/LC/SSR/LTP, * @see ISO_IEC_14496-3-AAC-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, uint32_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 ISO_IEC_14496-3-AAC-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); /************************************************************* ************************************************************** * h264 raw codec ************************************************************** *************************************************************/ /** * 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 ISO_IEC_14496-10-AVC-2003.pdf, page 211. * @param 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 * @remark, use srs_h264_startswith_annexb to check whether frame is annexb format. * @example /trunk/research/librtmp/srs_h264_raw_publish.c * @see https://github.com/ossrs/srs/issues/66 * * @return 0, success; otherswise, failed. * for dvbsp error, @see srs_h264_is_dvbsp_error(). * for duplictated sps error, @see srs_h264_is_duplicated_sps_error(). * for duplictated pps error, @see srs_h264_is_duplicated_pps_error(). */ /** For the example file: http://winlinvip.github.io/srs.release/3rdparty/720p.h264.raw The data sequence is: // SPS 000000016742802995A014016E40 // PPS 0000000168CE3880 // IFrame 0000000165B8041014C038008B0D0D3A071..... // PFrame 0000000141E02041F8CDDC562BBDEFAD2F..... User can send the SPS+PPS, then each frame: // SPS+PPS srs_h264_write_raw_frames('000000016742802995A014016E400000000168CE3880', size, dts, pts) // IFrame srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) // PFrame srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) User also can send one by one: // SPS srs_h264_write_raw_frames('000000016742802995A014016E4', size, dts, pts) // PPS srs_h264_write_raw_frames('00000000168CE3880', size, dts, pts) // IFrame srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts) // PFrame srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts) */ extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, uint32_t dts, uint32_t pts); /** * whether error_code is dvbsp(drop video before sps/pps/sequence-header) error. * * @see https://github.com/ossrs/srs/issues/203 * @example /trunk/research/librtmp/srs_h264_raw_publish.c * @remark why drop video? * some encoder, for example, ipcamera, will send sps/pps before each IFrame, * so, when error and reconnect the rtmp, the first video is not sps/pps(sequence header), * this will cause SRS server to disable HLS. */ extern srs_bool srs_h264_is_dvbsp_error(int error_code); /** * whether error_code is duplicated sps error. * * @see https://github.com/ossrs/srs/issues/204 * @example /trunk/research/librtmp/srs_h264_raw_publish.c */ extern srs_bool srs_h264_is_duplicated_sps_error(int error_code); /** * whether error_code is duplicated pps error. * * @see https://github.com/ossrs/srs/issues/204 * @example /trunk/research/librtmp/srs_h264_raw_publish.c */ extern srs_bool srs_h264_is_duplicated_pps_error(int error_code); /** * whether h264 raw data starts with the annexb, * which bytes sequence matches N[00] 00 00 01, where N>=0. * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. * @paam h264_raw_size the size of h264 raw data. * @param pnb_start_code output the size of start code, must >=3. * NULL to ignore. * * @reamrk used to check whether current frame is in annexb format. * @example /trunk/research/librtmp/srs_h264_raw_publish.c * * @return 0 false; otherwise, true. */ extern srs_bool srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code); /************************************************************* ************************************************************* * MP4 muxer and demuxer. * @example /trunk/research/librtmp/srs_ingest_mp4.c ************************************************************* *************************************************************/ typedef void* srs_mp4_t; // The sample struct of mp4. typedef struct { // The handler type, it's SrsMp4HandlerType. uint32_t handler_type; // The dts in milliseconds. uint32_t dts; // The codec id. // video: SrsVideoCodecId. // audio: SrsAudioCodecId. uint16_t codec; // The frame trait, some characteristic: // video: SrsVideoAvcFrameTrait. // audio: SrsAudioAacFrameTrait. uint16_t frame_trait; // The video pts in milliseconds. Ignore for audio. uint32_t pts; // The video frame type, it's SrsVideoAvcFrameType. uint16_t frame_type; // The audio sample rate, it's SrsAudioSampleRate. uint8_t sample_rate; // The audio sound bits, it's SrsAudioSampleBits. uint8_t sound_bits; // The audio sound type, it's SrsAudioChannels. uint8_t channels; // The size of sample payload in bytes. uint32_t nb_sample; // The output sample data, user must free it by srs_mp4_free_sample. uint8_t* sample; } srs_mp4_sample_t; /** * Open mp4 file for muxer(write) or demuxer(read). * @return A MP4 demuxer, NULL if failed. */ extern srs_mp4_t srs_mp4_open_read(const char* file); /** * Close the MP4 demuxer. */ extern void srs_mp4_close(srs_mp4_t mp4); /** * Initialize mp4 demuxer in non-seek mode. * @remark Only support non-seek mode, that is fmp4 or moov before mdata. * For the live streaming, we must feed stream frame by frame. */ extern int srs_mp4_init_demuxer(srs_mp4_t mp4); /** * Read a sample form mp4. * @remark User can use srs_mp4_sample_to_flv_tag to convert mp4 sampel to flv tag. * Use the srs_mp4_to_flv_tag_size to calc the flv tag data size to alloc. */ extern int srs_mp4_read_sample(srs_mp4_t mp4, srs_mp4_sample_t* sample); /** * Free the allocated mp4 sample. */ extern void srs_mp4_free_sample(srs_mp4_sample_t* sample); /** * Calc the size of flv tag, for the mp4 sample to convert to. */ extern int32_t srs_mp4_sizeof(srs_mp4_t mp4, srs_mp4_sample_t* sample); /** * Covert mp4 sample to flv tag. */ extern int srs_mp4_to_flv_tag(srs_mp4_t mp4, srs_mp4_sample_t* sample, char* type, uint32_t* time, char* data, int32_t size); /* error code */ /* whether the error code indicates EOF */ extern srs_bool srs_mp4_is_eof(int error_code); /************************************************************* ************************************************************** * flv codec * @example /trunk/research/librtmp/srs_flv_injecter.c * @example /trunk/research/librtmp/srs_flv_parser.c * @example /trunk/research/librtmp/srs_ingest_flv.c * @example /trunk/research/librtmp/srs_ingest_rtmp.c ************************************************************** *************************************************************/ typedef void* srs_flv_t; /** * Open FLV file in demux mode. * @return A FLV demuxer, NULL if failed. */ extern srs_flv_t srs_flv_open_read(const char* file); /** * Open FlV file in mux mode. * @return A FLV muxer, NULL if failed. */ extern srs_flv_t srs_flv_open_write(const char* file); /** * Close the FLV demuxer or muxer. */ extern void srs_flv_close(srs_flv_t flv); /** * read the flv header. 9bytes header. * @param header, @see E.2 The FLV header, flv_v10_1.pdf in SRS doc. * 3bytes, signature, "FLV", * 1bytes, version, 0x01, * 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present. * 4bytes, dataoffset, 0x09, The length of this header in bytes * * @return 0, success; otherswise, failed. * @remark, drop the 4bytes zero previous tag size. */ extern int srs_flv_read_header(srs_flv_t flv, char header[9]); /** * read the flv tag header, 1bytes tag, 3bytes data_size, * 4bytes time, 3bytes stream id. * @param ptype, output the type of tag, macros: * SRS_RTMP_TYPE_AUDIO, FlvTagAudio * SRS_RTMP_TYPE_VIDEO, FlvTagVideo * SRS_RTMP_TYPE_SCRIPT, FlvTagScript * @param pdata_size, output the size of tag data. * @param ptime, output the time of tag, the dts in ms. * * @return 0, success; otherswise, failed. * @remark, user must ensure the next is a tag, srs never check it. */ extern int srs_flv_read_tag_header(srs_flv_t flv, char* ptype, int32_t* pdata_size, uint32_t* ptime); /** * read the tag data. drop the 4bytes previous tag size * @param data, the data to read, user alloc and free it. * @param size, the size of data to read, get by srs_flv_read_tag_header(). * @remark, srs will ignore and drop the 4bytes previous tag size. */ extern int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size); /** * write the flv header. 9bytes header. * @param header, @see E.2 The FLV header, flv_v10_1.pdf in SRS doc. * 3bytes, signature, "FLV", * 1bytes, version, 0x01, * 1bytes, flags, UB[5] 0, UB[1] audio present, UB[1] 0, UB[1] video present. * 4bytes, dataoffset, 0x09, The length of this header in bytes * * @return 0, success; otherswise, failed. * @remark, auto write the 4bytes zero previous tag size. */ extern int srs_flv_write_header(srs_flv_t flv, char header[9]); /** * write the flv tag to file. * * @return 0, success; otherswise, failed. * @remark, auto write the 4bytes zero previous tag size. */ /* write flv tag to file, auto write the 4bytes previous tag size */ extern int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int size); /** * get the tag size, for flv injecter to adjust offset, * size = tag_header(11B) + data_size + previous_tag(4B) * @return the size of tag. */ extern int srs_flv_size_tag(int data_size); /* file stream */ /* file stream tellg to get offset */ extern int64_t srs_flv_tellg(srs_flv_t flv); /* seek file stream, offset is form the start of file */ extern void srs_flv_lseek(srs_flv_t flv, int64_t offset); /* error code */ /* whether the error code indicates EOF */ extern srs_bool srs_flv_is_eof(int error_code); /* media codec */ /** * whether the video body is sequence header * @param data, the data of tag, read by srs_flv_read_tag_data(). * @param size, the size of tag, read by srs_flv_read_tag_data(). */ extern srs_bool srs_flv_is_sequence_header(char* data, int32_t size); /** * whether the video body is keyframe * @param data, the data of tag, read by srs_flv_read_tag_data(). * @param size, the size of tag, read by srs_flv_read_tag_data(). */ extern srs_bool srs_flv_is_keyframe(char* data, int32_t size); /************************************************************* ************************************************************** * amf0 codec * @example /trunk/research/librtmp/srs_ingest_flv.c * @example /trunk/research/librtmp/srs_ingest_rtmp.c ************************************************************** *************************************************************/ /* the output handler. */ typedef double srs_amf0_number; /** * parse amf0 from data. * @param nparsed, the parsed size, NULL to ignore. * @return the parsed amf0 object. NULL for error. * @remark user must free the parsed or created object by srs_amf0_free. */ extern srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed); extern srs_amf0_t srs_amf0_create_string(const char* value); extern srs_amf0_t srs_amf0_create_number(srs_amf0_number value); extern srs_amf0_t srs_amf0_create_ecma_array(); extern srs_amf0_t srs_amf0_create_strict_array(); extern srs_amf0_t srs_amf0_create_object(); extern srs_amf0_t srs_amf0_ecma_array_to_object(srs_amf0_t ecma_arr); extern void srs_amf0_free(srs_amf0_t amf0); /* size and to bytes */ extern int srs_amf0_size(srs_amf0_t amf0); extern int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size); /* type detecter */ extern srs_bool srs_amf0_is_string(srs_amf0_t amf0); extern srs_bool srs_amf0_is_boolean(srs_amf0_t amf0); extern srs_bool srs_amf0_is_number(srs_amf0_t amf0); extern srs_bool srs_amf0_is_null(srs_amf0_t amf0); extern srs_bool srs_amf0_is_object(srs_amf0_t amf0); extern srs_bool srs_amf0_is_ecma_array(srs_amf0_t amf0); extern srs_bool srs_amf0_is_strict_array(srs_amf0_t amf0); /* value converter */ extern const char* srs_amf0_to_string(srs_amf0_t amf0); extern srs_bool srs_amf0_to_boolean(srs_amf0_t amf0); extern srs_amf0_number srs_amf0_to_number(srs_amf0_t amf0); /* value setter */ extern void srs_amf0_set_number(srs_amf0_t amf0, srs_amf0_number value); /* object value converter */ extern int srs_amf0_object_property_count(srs_amf0_t amf0); extern const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_object_property_value_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_object_property(srs_amf0_t amf0, const char* name); extern void srs_amf0_object_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value); extern void srs_amf0_object_clear(srs_amf0_t amf0); /* ecma array value converter */ extern int srs_amf0_ecma_array_property_count(srs_amf0_t amf0); extern const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index); extern srs_amf0_t srs_amf0_ecma_array_property(srs_amf0_t amf0, const char* name); extern void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value); /* strict array value converter */ extern int srs_amf0_strict_array_property_count(srs_amf0_t amf0); extern srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index); extern void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value); /************************************************************* ************************************************************** * utilities ************************************************************** *************************************************************/ /** * get the current system time in ms. * use gettimeofday() to get system time. */ extern int64_t srs_utils_time_ms(); /** * get the send bytes. */ extern int64_t srs_utils_send_bytes(srs_rtmp_t rtmp); /** * get the recv bytes. */ extern int64_t srs_utils_recv_bytes(srs_rtmp_t rtmp); /** * parse the dts and pts by time in header and data in tag, * or to parse the RTMP packet by srs_rtmp_read_packet(). * * @param time, the timestamp of tag, read by srs_flv_read_tag_header(). * @param type, the type of tag, read by srs_flv_read_tag_header(). * @param data, the data of tag, read by srs_flv_read_tag_data(). * @param size, the size of tag, read by srs_flv_read_tag_header(). * @param ppts, output the pts in ms, * * @return 0, success; otherswise, failed. * @remark, the dts always equals to @param time. * @remark, the pts=dts for audio or data. * @remark, video only support h.264. */ extern int srs_utils_parse_timestamp(uint32_t time, char type, char* data, int size, uint32_t* ppts); /** * whether the flv tag specified by param type is ok. * @return true when tag is video/audio/script-data; otherwise, false. */ extern srs_bool srs_utils_flv_tag_is_ok(char type); extern srs_bool srs_utils_flv_tag_is_audio(char type); extern srs_bool srs_utils_flv_tag_is_video(char type); extern srs_bool srs_utils_flv_tag_is_av(char type); /** * get the CodecID of video tag. * Codec Identifier. The following values are defined: * 2 = Sorenson H.263 * 3 = Screen video * 4 = On2 VP6 * 5 = On2 VP6 with alpha channel * 6 = Screen video version 2 * 7 = AVC * @return the code id. 0 for error. */ extern char srs_utils_flv_video_codec_id(char* data, int size); /** * get the AVCPacketType of video tag. * The following values are defined: * 0 = AVC sequence header * 1 = AVC NALU * 2 = AVC end of sequence (lower level NALU sequence ender is * not required or supported) * @return the avc packet type. -1(0xff) for error. */ extern char srs_utils_flv_video_avc_packet_type(char* data, int size); /** * get the FrameType of video tag. * Type of video frame. The following values are defined: * 1 = key frame (for AVC, a seekable frame) * 2 = inter frame (for AVC, a non-seekable frame) * 3 = disposable inter frame (H.263 only) * 4 = generated key frame (reserved for server use only) * 5 = video info/command frame * @return the frame type. 0 for error. */ extern char srs_utils_flv_video_frame_type(char* data, int size); /** * get the SoundFormat of audio tag. * 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. * @return the sound format. -1(0xff) for error. */ extern char srs_utils_flv_audio_sound_format(char* data, int size); /** * get the SoundRate of audio tag. * Sampling rate. The following values are defined: * 0 = 5.5 kHz * 1 = 11 kHz * 2 = 22 kHz * 3 = 44 kHz * @return the sound rate. -1(0xff) for error. */ extern char srs_utils_flv_audio_sound_rate(char* data, int size); /** * get the SoundSize of audio tag. * 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 * @return the sound size. -1(0xff) for error. */ extern char srs_utils_flv_audio_sound_size(char* data, int size); /** * get the SoundType of audio tag. * Mono or stereo sound * 0 = Mono sound * 1 = Stereo sound * @return the sound type. -1(0xff) for error. */ extern char srs_utils_flv_audio_sound_type(char* data, int size); /** * get the AACPacketType of audio tag. * The following values are defined: * 0 = AAC sequence header * 1 = AAC raw * @return the aac packet type. -1(0xff) for error. */ extern char srs_utils_flv_audio_aac_packet_type(char* data, int size); /************************************************************* ************************************************************** * human readable print. ************************************************************** *************************************************************/ /** * human readable print * @param pdata, output the heap data, NULL to ignore. * user must use srs_amf0_free_bytes to free it. * @return return the *pdata for print. NULL to ignore. */ extern char* srs_human_amf0_print(srs_amf0_t amf0, char** pdata, int* psize); /** * convert the flv tag type to string. * SRS_RTMP_TYPE_AUDIO to "Audio" * SRS_RTMP_TYPE_VIDEO to "Video" * SRS_RTMP_TYPE_SCRIPT to "Data" * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_tag_type2string(char type); /** * get the codec id string. * H.263 = Sorenson H.263 * Screen = Screen video * VP6 = On2 VP6 * VP6Alpha = On2 VP6 with alpha channel * Screen2 = Screen video version 2 * H.264 = AVC * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_video_codec_id2string(char codec_id); /** * get the avc packet type string. * SH = AVC sequence header * Nalu = AVC NALU * SpsPpsEnd = AVC end of sequence * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_video_avc_packet_type2string(char avc_packet_type); /** * get the frame type string. * I = key frame (for AVC, a seekable frame) * P/B = inter frame (for AVC, a non-seekable frame) * DI = disposable inter frame (H.263 only) * GI = generated key frame (reserved for server use only) * VI = video info/command frame * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_video_frame_type2string(char frame_type); /** * get the SoundFormat string. * Format of SoundData. The following values are defined: * LinearPCM = Linear PCM, platform endian * ADPCM = ADPCM * MP3 = MP3 * LinearPCMLe = Linear PCM, little endian * NellymoserKHz16 = Nellymoser 16 kHz mono * NellymoserKHz8 = Nellymoser 8 kHz mono * Nellymoser = Nellymoser * G711APCM = G.711 A-law logarithmic PCM * G711MuPCM = G.711 mu-law logarithmic PCM * Reserved = reserved * AAC = AAC * Speex = Speex * MP3KHz8 = MP3 8 kHz * DeviceSpecific = Device-specific sound * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_audio_sound_format2string(char sound_format); /** * get the SoundRate of audio tag. * Sampling rate. The following values are defined: * 5.5KHz = 5.5 kHz * 11KHz = 11 kHz * 22KHz = 22 kHz * 44KHz = 44 kHz * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_audio_sound_rate2string(char sound_rate); /** * get the SoundSize of audio tag. * Size of each audio sample. This parameter only pertains to * uncompressed formats. Compressed formats always decode * to 16 bits internally. * 8bit = 8-bit samples * 16bit = 16-bit samples * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_audio_sound_size2string(char sound_size); /** * get the SoundType of audio tag. * Mono or stereo sound * Mono = Mono sound * Stereo = Stereo sound * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_audio_sound_type2string(char sound_type); /** * get the AACPacketType of audio tag. * The following values are defined: * SH = AAC sequence header * Raw = AAC raw * otherwise, "Unknown" * @remark user never free the return char*, * it's static shared const string. */ extern const char* srs_human_flv_audio_aac_packet_type2string(char aac_packet_type); /** * Format the RTMP packet to human readable buffer. * @return Whether parse RTMP packet ok. 0, success; otherwise, failed. */ extern int srs_human_format_rtmp_packet(char* buffer, int nb_buffer, char type, uint32_t timestamp, char* data, int size); extern int srs_human_format_rtmp_packet2(char* buffer, int nb_buffer, char type, uint32_t timestamp, char* data, int size, uint32_t pre_timestamp, int64_t pre_now, int64_t starttime, int64_t nb_packets); /** * Format current time to human readable string. * @return A NULL terminated string. */ extern const char* srs_human_format_time(); #ifndef _WIN32 // for getpid. #include #endif // The log function for librtmp. // User can disable it by define macro SRS_DISABLE_LOG. // Or user can directly use them, or define the alias by: // #define trace(msg, ...) srs_human_trace(msg, ##__VA_ARGS__) // #define warn(msg, ...) srs_human_warn(msg, ##__VA_ARGS__) // #define error(msg, ...) srs_human_error(msg, ##__VA_ARGS__) #ifdef SRS_DISABLE_LOG #define srs_human_trace(msg, ...) (void)0 #define srs_human_warn(msg, ...) (void)0 #define srs_human_error(msg, ...) (void)0 #define srs_human_verbose(msg, ...) (void)0 #define srs_human_raw(msg, ...) (void)0 #else #include #include #define srs_human_trace(msg, ...) \ fprintf(stdout, "[T][%d][%s] ", getpid(), srs_human_format_time());\ fprintf(stdout, msg, ##__VA_ARGS__); fprintf(stdout, "\n") #define srs_human_warn(msg, ...) \ fprintf(stdout, "[W][%d][%s][%d] ", getpid(), srs_human_format_time(), errno); \ fprintf(stdout, msg, ##__VA_ARGS__); \ fprintf(stdout, "\n") #define srs_human_error(msg, ...) \ fprintf(stderr, "[E][%d][%s][%d] ", getpid(), srs_human_format_time(), errno);\ fprintf(stderr, msg, ##__VA_ARGS__); \ fprintf(stderr, " (%s)\n", strerror(errno)) #define srs_human_verbose(msg, ...) (void)0 #define srs_human_raw(msg, ...) printf(msg, ##__VA_ARGS__) #endif /************************************************************* ************************************************************** * IO hijack, use your specified io functions. ************************************************************** *************************************************************/ // the void* will convert to your handler for io hijack. typedef void* srs_hijack_io_t; #ifdef SRS_HIJACK_IO #ifndef _WIN32 // for iovec. #include #endif /** * get the hijack io object in rtmp protocol sdk. * @remark, user should never provides this method, srs-librtmp provides it. */ extern srs_hijack_io_t srs_hijack_io_get(srs_rtmp_t rtmp); #endif // define the following macro and functions in your module to hijack the io. // the example @see https://github.com/ossrs/srs-bench // which use librtmp but use its own io(use st also). #ifdef SRS_HIJACK_IO /** * create hijack. * @return NULL for error; otherwise, ok. */ extern srs_hijack_io_t srs_hijack_io_create(); /** * destroy the context, user must close the socket. */ extern void srs_hijack_io_destroy(srs_hijack_io_t ctx); /** * create socket, not connect yet. * @param owner, the rtmp context which create this socket. * @return 0, success; otherswise, failed. */ extern int srs_hijack_io_create_socket(srs_hijack_io_t ctx, srs_rtmp_t owner); /** * connect socket at server_ip:port. * @return 0, success; otherswise, failed. */ extern int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port); /** * read from socket. * @return 0, success; otherswise, failed. */ extern int srs_hijack_io_read(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread); /** * set the socket recv timeout in ms. * @return 0, success; otherswise, failed. */ extern int srs_hijack_io_set_recv_timeout(srs_hijack_io_t ctx, int64_t tm); /** * get the socket recv timeout. * @return 0, success; otherswise, failed. */ extern int64_t srs_hijack_io_get_recv_timeout(srs_hijack_io_t ctx); /** * get the socket recv bytes. * @return 0, success; otherswise, failed. */ extern int64_t srs_hijack_io_get_recv_bytes(srs_hijack_io_t ctx); /** * set the socket send timeout in ms. * @return 0, success; otherswise, failed. */ extern int srs_hijack_io_set_send_timeout(srs_hijack_io_t ctx, int64_t tm); /** * get the socket send timeout. * @return 0, success; otherswise, failed. */ extern int64_t srs_hijack_io_get_send_timeout(srs_hijack_io_t ctx); /** * get the socket send bytes. * @return 0, success; otherswise, failed. */ extern int64_t srs_hijack_io_get_send_bytes(srs_hijack_io_t ctx); /** * writev of socket. * @return 0, success; otherswise, failed. * @remark We assume that the writev always write all data to peer, like what ST or block-socket done. */ extern int srs_hijack_io_writev(srs_hijack_io_t ctx, const iovec *iov, int iov_size, ssize_t* nwrite); /** * whether the timeout is never timeout in ms. * @return 0, with timeout specified; otherwise, never timeout. */ extern int srs_hijack_io_is_never_timeout(srs_hijack_io_t ctx, int64_t tm); /** * read fully, fill the buf exactly size bytes. * @return 0, success; otherswise, failed. */ extern int srs_hijack_io_read_fully(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread); /** * write bytes to socket. * @return 0, success; otherswise, failed. * @remark We assume that the write always write all data to peer, like what ST or block-socket done. */ extern int srs_hijack_io_write(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nwrite); #endif /************************************************************* ************************************************************** * Windows SRS-LIBRTMP solution ************************************************************** *************************************************************/ // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213 #ifdef _WIN32 // for time. #define _CRT_SECURE_NO_WARNINGS #include int gettimeofday(struct timeval* tv, struct timezone* tz); #define PRId64 "lld" // for inet helpers. typedef int socklen_t; const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); // for mkdir(). #include // for open(). typedef int mode_t; #define S_IRUSR 0 #define S_IWUSR 0 #define S_IXUSR 0 #define S_IRGRP 0 #define S_IWGRP 0 #define S_IXGRP 0 #define S_IROTH 0 #define S_IXOTH 0 // for file seek. #include #include #define open _open #define close _close #define lseek _lseek #define write _write #define read _read // for socket. ssize_t writev(int fd, const struct iovec *iov, int iovcnt); typedef int64_t useconds_t; int usleep(useconds_t usec); int socket_setup(); int socket_cleanup(); // others. #define snprintf _snprintf #endif /************************************************************* ************************************************************* * Deprecated APIs, maybe removed in future versions. ************************************************************* *************************************************************/ /** * Deprecated, for bandwidth test check only. */ extern srs_rtmp_t srs_rtmp_create2(const char* url); /** * Deprecated, use seperate function to retrieve information from rtmp, * for example, use srs_rtmp_get_server_ip to get server ip. */ extern int srs_rtmp_connect_app2(srs_rtmp_t rtmp, char srs_server_ip[128], char srs_server[128], char srs_primary[128], char srs_authors[128], char srs_version[32], int* srs_id, int* srs_pid); /** * Deprecated, use srs_human_format_rtmp_packet instead. */ extern int srs_human_print_rtmp_packet(char type, uint32_t timestamp, char* data, int size); extern int srs_human_print_rtmp_packet2(char type, uint32_t timestamp, char* data, int size, uint32_t pre_timestamp); extern int srs_human_print_rtmp_packet3(char type, uint32_t timestamp, char* data, int size, uint32_t pre_timestamp, int64_t pre_now); extern int srs_human_print_rtmp_packet4(char type, uint32_t timestamp, char* data, int size, uint32_t pre_timestamp, int64_t pre_now, int64_t starttime, int64_t nb_packets); #ifdef __cplusplus } #endif #endif