1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00
srs/trunk/src/libs/srs_librtmp.hpp

1256 lines
46 KiB
C++

/**
* The MIT License (MIT)
*
* Copyright (c) 2013-2020 Winlin
*
* 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
*/
// @see http://blog.csdn.net/win_lin/article/details/7912693
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
/*************************************************************
**************************************************************
* Windows SRS-LIBRTMP pre-declare
**************************************************************
*************************************************************/
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
#ifdef _WIN32
// To disable some security warnings.
#define _CRT_SECURE_NO_WARNINGS
// include windows first.
#include <windows.h>
// the type used by this header for windows.
#if defined(_MSC_VER)
#include <stdint.h>
#else
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
#endif
typedef unsigned long long u_int64_t;
typedef unsigned int u_int32_t;
typedef u_int32_t uint32_t;
typedef unsigned char u_int8_t;
typedef unsigned short u_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 <stdint.h>
#include <sys/types.h>
#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 <unistd.h>
#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 <string.h>
#include <errno.h>
#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 <sys/uio.h>
#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.
* TODO: FIXME: Incompatible API for https://github.com/ossrs/srs/blob/2.0release/trunk/src/libs/srs_librtmp.hpp#L989
*/
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.
* TODO: FIXME: Incompatible API for https://github.com/ossrs/srs/blob/2.0release/trunk/src/libs/srs_librtmp.hpp#L1039
*/
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
#include <time.h>
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<direct.h>
// 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 <io.h>
#include <fcntl.h>
#define open _open
#define close _close
#define lseek _lseek
// 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