The client library srs-librtmp of SRS(https://github.com/ossrs/srs)
This repository is exported by SRS3.0+, please read the wiki( CN, EN ).
When you program on linux, the exported project or files can be direclty used.
For windows, I provides a visual studio project example.
We also patch the librtmp to work better with SRS, to get the debug srs ip/pid/cid, which is very important to fast debug.
The API to publish or play RTMP stream.
-
Create RTMP object:
/** * create/destroy a rtmp protocol stack. * @url rtmp url, for example: * rtmp://localhost/live/livestream * @remark default timeout to 30s if not set by srs_rtmp_set_timeout. * * @return a rtmp handler, or NULL if error occured. */ extern srs_rtmp_t srs_rtmp_create(const char* url);
-
Handshake with server:
/** * connect and handshake with server * category: publish/play * previous: rtmp-create * next: connect-app * * @return 0, success; otherswise, failed. */ extern int srs_rtmp_handshake(srs_rtmp_t rtmp);
-
Setup the RTMP object:
/** * 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 app:
/** * connect to rtmp vhost/app * category: publish/play * previous: handshake * next: publish or play * * @return 0, success; otherswise, failed. */ extern int srs_rtmp_connect_app(srs_rtmp_t rtmp);
-
Retrieve server informations:
/** * 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);
-
Start play or publish stream:
/** * 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);
-
Send or receive RTMP packet:
/** * 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 ); extern int srs_rtmp_write_packet(srs_rtmp_t rtmp, char type, uint32_t timestamp, char* data, int size );
-
Destroy RTMP object:
/** * close and destroy the rtmp stack. * @remark, user should never use the rtmp again. */ extern void srs_rtmp_destroy(srs_rtmp_t rtmp);
The API to send RAW AAC frame over RTMP.
-
Determine whether frame is in ADTS format:
/** * 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 RAW AAC ADTS frame, get the size of AAC data:
/** * 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);
-
Write the RAW AAC frame over RTMP:
/** * 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 );
The API to send RAW H.264 frame over RTMP.
-
Check whether RAW H.264 is in annexb format:
/** * 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 );
-
Write H.264 RAW frame over RTMP:
/** * 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 );
The API to read MP4 format.
-
Open MP4 file:
/* Open mp4 file for muxer(write) or demuxer(read). */ extern srs_mp4_t srs_mp4_open_read(const char* file);
-
Initialize the MP4 demuxer:
/** * 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 next sample(header and frame payload):
/** * 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);
Remark: Use
srs_mp4_is_eof
to check whether EOF.
-
Calculate the size of FLV tag, converted from MP4 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);
-
Convert MP4 sample to FLV tag:
/** * 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);
Remark: User must allocate the tag payload. Reamrk: User can send the FLV tag over RTMP.
-
Free the MP4 sample:
/** * Free the allocated mp4 sample. */ extern void srs_mp4_free_sample(srs_mp4_sample_t* sample);
-
Destroy MP4 file:
extern void srs_mp4_close(srs_mp4_t mp4);
The API to read or write FLV file.
-
Open the FLV file, in read or write mode:
/* open flv file for both read/write. */ extern srs_flv_t srs_flv_open_read(const char* file); extern srs_flv_t srs_flv_open_write(const char* file);
-
Read the FLV file header from file:
/** * 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]);
Reamark: Use
srs_flv_is_eof
to check whether EOF.
- Read a FLV tag from file:
/** * 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 );
Reamark: Use
srs_flv_is_eof
to check whether EOF.
- Read a FLV tag body from file:
/**
* 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);
Reamark: Use
srs_flv_is_eof
to check whether EOF.
-
Write the FLV file header to file:
/** * 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 a FLV tag header and body to file:
/** * 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 );
-
Close the FLV file:
extern void srs_flv_close(srs_flv_t flv);
The following APIs are AMF0 codec.
- Number defined as double:
typedef double srs_amf0_number;
- Create AMF0 instance:
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();
- Parse AMF0 instance from buffer:
extern srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed);
- Encode AMF0 instance to buffer:
extern int srs_amf0_size(srs_amf0_t amf0);
extern int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size);
- Detect the type of AMF0 instance:
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);
- Convert the AMF0 instance to basic type:
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);
- Set the AMF0 Number:
extern void srs_amf0_set_number(srs_amf0_t amf0, srs_amf0_number value);
- For AMF0 Object instance:
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);
- For AMF0 EcmaArray instance:
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);
- For AMF0 StrictArray instance:
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);
- Destroy AMF0 instance:
extern void srs_amf0_free(srs_amf0_t amf0);
Winlin 2014.11