winlin

refine librtmp, move the utils and human to end section.

... ... @@ -858,117 +858,6 @@ int srs_version_revision()
return VERSION_REVISION;
}
int64_t srs_utils_get_time_ms()
{
srs_update_system_time_ms();
return srs_get_system_time_ms();
}
int64_t srs_utils_get_send_bytes(srs_rtmp_t rtmp)
{
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
return context->rtmp->get_send_bytes();
}
int64_t srs_utils_get_recv_bytes(srs_rtmp_t rtmp)
{
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
return context->rtmp->get_recv_bytes();
}
int srs_utils_parse_timestamp(
u_int32_t time, char type, char* data, int size,
u_int32_t* ppts
) {
int ret = ERROR_SUCCESS;
if (type != SRS_RTMP_TYPE_VIDEO) {
*ppts = time;
return ret;
}
if (!SrsFlvCodec::video_is_h264(data, size)) {
return ERROR_FLV_INVALID_VIDEO_TAG;
}
if (SrsFlvCodec::video_is_sequence_header(data, size)) {
*ppts = time;
return ret;
}
// 1bytes, frame type and codec id.
// 1bytes, avc packet type.
// 3bytes, cts, composition time,
// pts = dts + cts, or
// cts = pts - dts.
if (size < 5) {
return ERROR_FLV_INVALID_VIDEO_TAG;
}
u_int32_t cts = 0;
char* p = data + 2;
char* pp = (char*)&cts;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
*ppts = time + cts;
return ret;
}
char srs_utils_get_flv_video_codec_id(char* data, int size)
{
if (size < 1) {
return 0;
}
char codec_id = data[0];
codec_id = codec_id & 0x0F;
return codec_id;
}
char srs_utils_get_flv_video_avc_packet_type(char* data, int size)
{
if (size < 2) {
return -1;
}
if (!SrsFlvCodec::video_is_h264(data, size)) {
return -1;
}
u_int8_t avc_packet_type = data[1];
if (avc_packet_type > 2) {
return -1;
}
return avc_packet_type;
}
char srs_utils_get_flv_video_frame_type(char* data, int size)
{
if (size < 1) {
return -1;
}
if (!SrsFlvCodec::video_is_h264(data, size)) {
return -1;
}
u_int8_t frame_type = data[0];
frame_type = (frame_type >> 4) & 0x0f;
if (frame_type < 1 || frame_type > 5) {
return -1;
}
return frame_type;
}
struct FlvContext
{
SrsFileReader reader;
... ... @@ -1432,264 +1321,101 @@ void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value)
obj->append(any);
}
char* srs_human_amf0_print(srs_amf0_t amf0, char** pdata, int* psize)
{
if (!amf0) {
return NULL;
/**
* write audio raw frame to SRS.
*/
int srs_audio_write_raw_frame(srs_rtmp_t rtmp,
char sound_format, char sound_rate, char sound_size, char sound_type,
char aac_packet_type, char* frame, int frame_size, u_int32_t timestamp
) {
Context* context = (Context*)rtmp;
srs_assert(context);
// TODO: FIXME: for aac, must send the sequence header first.
// for audio frame, there is 1 or 2 bytes header:
// 1bytes, SoundFormat|SoundRate|SoundSize|SoundType
// 1bytes, AACPacketType for SoundFormat == 10
int size = frame_size + 1;
if (aac_packet_type == SrsCodecAudioAAC) {
size += 1;
}
char* data = new char[size];
char* p = data;
SrsAmf0Any* any = (SrsAmf0Any*)amf0;
u_int8_t audio_header = sound_type & 0x01;
audio_header |= (sound_size << 1) & 0x02;
audio_header |= (sound_rate << 2) & 0x0c;
audio_header |= (sound_format << 4) & 0xf0;
return any->human_print(pdata, psize);
}
const char* srs_human_flv_tag_type2string(char type)
{
static const char* audio = "Audio";
static const char* video = "Video";
static const char* data = "Data";
static const char* unknown = "Unknown";
*p++ = audio_header;
switch (type) {
case SRS_RTMP_TYPE_AUDIO: return audio;
case SRS_RTMP_TYPE_VIDEO: return video;
case SRS_RTMP_TYPE_SCRIPT: return data;
default: return unknown;
if (aac_packet_type == SrsCodecAudioAAC) {
*p++ = aac_packet_type;
}
return unknown;
memcpy(p, frame, frame_size);
return srs_write_packet(context, SRS_RTMP_TYPE_AUDIO, timestamp, data, size);
}
const char* srs_human_flv_video_codec_id2string(char codec_id)
{
static const char* h263 = "H.263";
static const char* screen = "Screen";
static const char* vp6 = "VP6";
static const char* vp6_alpha = "VP6Alpha";
static const char* screen2 = "Screen2";
static const char* h264 = "H.264";
static const char* unknown = "Unknown";
/**
* write h264 packet, with rtmp header.
* @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame.
* @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU.
* @param h264_raw_data the h.264 raw data, user must free it.
*/
int __srs_write_h264_packet(Context* context,
int8_t frame_type, int8_t avc_packet_type,
char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts
) {
// the timestamp in rtmp message header is dts.
u_int32_t timestamp = dts;
switch (codec_id) {
case 2: return h263;
case 3: return screen;
case 4: return vp6;
case 5: return vp6_alpha;
case 6: return screen2;
case 7: return h264;
default: return unknown;
}
// for h264 in RTMP video payload, there is 5bytes header:
// 1bytes, FrameType | CodecID
// 1bytes, AVCPacketType
// 3bytes, CompositionTime, the cts.
// @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
int size = h264_raw_size + 5;
char* data = new char[size];
char* p = data;
return unknown;
}
// @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
// Frame Type, Type of video frame.
// CodecID, Codec Identifier.
// set the rtmp header
*p++ = (frame_type << 4) | SrsCodecVideoAVC;
// AVCPacketType
*p++ = avc_packet_type;
const char* srs_human_flv_video_avc_packet_type2string(char avc_packet_type)
{
static const char* sps_pps = "SpsPps";
static const char* nalu = "Nalu";
static const char* sps_pps_end = "SpsPpsEnd";
static const char* unknown = "Unknown";
// CompositionTime
// pts = dts + cts, or
// cts = pts - dts.
// where cts is the header in rtmp video packet payload header.
u_int32_t cts = pts - dts;
char* pp = (char*)&cts;
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
switch (avc_packet_type) {
case 0: return sps_pps;
case 1: return nalu;
case 2: return sps_pps_end;
default: return unknown;
}
// h.264 raw data.
memcpy(p, h264_raw_data, h264_raw_size);
return unknown;
return srs_write_packet(context, SRS_RTMP_TYPE_VIDEO, timestamp, data, size);
}
const char* srs_human_flv_video_frame_type2string(char frame_type)
/**
* write the h264 sps/pps in context over RTMP.
*/
int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
{
static const char* keyframe = "I";
static const char* interframe = "P/B";
static const char* disposable_interframe = "DI";
static const char* generated_keyframe = "GI";
static const char* video_infoframe = "VI";
static const char* unknown = "Unknown";
int ret = ERROR_SUCCESS;
switch (frame_type) {
case 1: return keyframe;
case 2: return interframe;
case 3: return disposable_interframe;
case 4: return generated_keyframe;
case 5: return video_infoframe;
default: return unknown;
}
return unknown;
}
int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int size)
{
int ret = ERROR_SUCCESS;
u_int32_t pts;
if (srs_utils_parse_timestamp(timestamp, type, data, size, &pts) != 0) {
return ret;
}
if (type == SRS_RTMP_TYPE_VIDEO) {
srs_human_trace("Video packet type=%s, dts=%d, pts=%d, size=%d, %s(%s,%s)",
srs_human_flv_tag_type2string(type), timestamp, pts, size,
srs_human_flv_video_codec_id2string(srs_utils_get_flv_video_codec_id(data, size)),
srs_human_flv_video_avc_packet_type2string(srs_utils_get_flv_video_avc_packet_type(data, size)),
srs_human_flv_video_frame_type2string(srs_utils_get_flv_video_frame_type(data, size))
);
} else if (type == SRS_RTMP_TYPE_AUDIO) {
srs_human_trace("Audio packet type=%s, dts=%d, pts=%d, size=%d",
srs_human_flv_tag_type2string(type), timestamp, pts, size);
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
srs_human_verbose("Data packet type=%s, time=%d, size=%d",
srs_human_flv_tag_type2string(type), timestamp, size);
int nparsed = 0;
while (nparsed < size) {
int nb_parsed_this = 0;
srs_amf0_t amf0 = srs_amf0_parse(data + nparsed, size - nparsed, &nb_parsed_this);
if (amf0 == NULL) {
break;
}
nparsed += nb_parsed_this;
char* amf0_str = NULL;
srs_human_raw("%s", srs_human_amf0_print(amf0, &amf0_str, NULL));
srs_amf0_free_bytes(amf0_str);
}
} else {
srs_human_trace("Unknown packet type=%s, dts=%d, pts=%d, size=%d",
srs_human_flv_tag_type2string(type), timestamp, pts, size);
}
return ret;
}
const char* srs_human_format_time()
{
struct timeval tv;
static char buf[23];
memset(buf, 0, sizeof(buf));
// clock time
if (gettimeofday(&tv, NULL) == -1) {
return buf;
}
// to calendar time
struct tm* tm;
if ((tm = localtime((const time_t*)&tv.tv_sec)) == NULL) {
return buf;
}
snprintf(buf, sizeof(buf),
"%d-%02d-%02d %02d:%02d:%02d.%03d",
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
(int)(tv.tv_usec / 1000));
// for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213
buf[sizeof(buf) - 1] = 0;
return buf;
}
/**
* write audio raw frame to SRS.
*/
int srs_audio_write_raw_frame(srs_rtmp_t rtmp,
char sound_format, char sound_rate, char sound_size, char sound_type,
char aac_packet_type, char* frame, int frame_size, u_int32_t timestamp
) {
Context* context = (Context*)rtmp;
srs_assert(context);
// TODO: FIXME: for aac, must send the sequence header first.
// for audio frame, there is 1 or 2 bytes header:
// 1bytes, SoundFormat|SoundRate|SoundSize|SoundType
// 1bytes, AACPacketType for SoundFormat == 10
int size = frame_size + 1;
if (aac_packet_type == SrsCodecAudioAAC) {
size += 1;
}
char* data = new char[size];
char* p = data;
u_int8_t audio_header = sound_type & 0x01;
audio_header |= (sound_size << 1) & 0x02;
audio_header |= (sound_rate << 2) & 0x0c;
audio_header |= (sound_format << 4) & 0xf0;
*p++ = audio_header;
if (aac_packet_type == SrsCodecAudioAAC) {
*p++ = aac_packet_type;
}
memcpy(p, frame, frame_size);
return srs_write_packet(context, SRS_RTMP_TYPE_AUDIO, timestamp, data, size);
}
/**
* write h264 packet, with rtmp header.
* @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame.
* @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU.
* @param h264_raw_data the h.264 raw data, user must free it.
*/
int __srs_write_h264_packet(Context* context,
int8_t frame_type, int8_t avc_packet_type,
char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts
) {
// the timestamp in rtmp message header is dts.
u_int32_t timestamp = dts;
// for h264 in RTMP video payload, there is 5bytes header:
// 1bytes, FrameType | CodecID
// 1bytes, AVCPacketType
// 3bytes, CompositionTime, the cts.
// @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
int size = h264_raw_size + 5;
char* data = new char[size];
char* p = data;
// @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
// Frame Type, Type of video frame.
// CodecID, Codec Identifier.
// set the rtmp header
*p++ = (frame_type << 4) | SrsCodecVideoAVC;
// AVCPacketType
*p++ = avc_packet_type;
// CompositionTime
// pts = dts + cts, or
// cts = pts - dts.
// where cts is the header in rtmp video packet payload header.
u_int32_t cts = pts - dts;
char* pp = (char*)&cts;
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
// h.264 raw data.
memcpy(p, h264_raw_data, h264_raw_size);
return srs_write_packet(context, SRS_RTMP_TYPE_VIDEO, timestamp, data, size);
}
/**
* write the h264 sps/pps in context over RTMP.
*/
int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
{
int ret = ERROR_SUCCESS;
// only send when both sps and pps changed.
if (!context->h264_sps_changed || !context->h264_pps_changed) {
return ret;
// only send when both sps and pps changed.
if (!context->h264_sps_changed || !context->h264_pps_changed) {
return ret;
}
// 5bytes sps/pps header:
... ... @@ -1986,6 +1712,280 @@ int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_
return srs_avc_startswith_annexb(&stream, pnb_start_code);
}
int64_t srs_utils_get_time_ms()
{
srs_update_system_time_ms();
return srs_get_system_time_ms();
}
int64_t srs_utils_get_send_bytes(srs_rtmp_t rtmp)
{
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
return context->rtmp->get_send_bytes();
}
int64_t srs_utils_get_recv_bytes(srs_rtmp_t rtmp)
{
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
return context->rtmp->get_recv_bytes();
}
int srs_utils_parse_timestamp(
u_int32_t time, char type, char* data, int size,
u_int32_t* ppts
) {
int ret = ERROR_SUCCESS;
if (type != SRS_RTMP_TYPE_VIDEO) {
*ppts = time;
return ret;
}
if (!SrsFlvCodec::video_is_h264(data, size)) {
return ERROR_FLV_INVALID_VIDEO_TAG;
}
if (SrsFlvCodec::video_is_sequence_header(data, size)) {
*ppts = time;
return ret;
}
// 1bytes, frame type and codec id.
// 1bytes, avc packet type.
// 3bytes, cts, composition time,
// pts = dts + cts, or
// cts = pts - dts.
if (size < 5) {
return ERROR_FLV_INVALID_VIDEO_TAG;
}
u_int32_t cts = 0;
char* p = data + 2;
char* pp = (char*)&cts;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
*ppts = time + cts;
return ret;
}
char srs_utils_get_flv_video_codec_id(char* data, int size)
{
if (size < 1) {
return 0;
}
char codec_id = data[0];
codec_id = codec_id & 0x0F;
return codec_id;
}
char srs_utils_get_flv_video_avc_packet_type(char* data, int size)
{
if (size < 2) {
return -1;
}
if (!SrsFlvCodec::video_is_h264(data, size)) {
return -1;
}
u_int8_t avc_packet_type = data[1];
if (avc_packet_type > 2) {
return -1;
}
return avc_packet_type;
}
char srs_utils_get_flv_video_frame_type(char* data, int size)
{
if (size < 1) {
return -1;
}
if (!SrsFlvCodec::video_is_h264(data, size)) {
return -1;
}
u_int8_t frame_type = data[0];
frame_type = (frame_type >> 4) & 0x0f;
if (frame_type < 1 || frame_type > 5) {
return -1;
}
return frame_type;
}
char* srs_human_amf0_print(srs_amf0_t amf0, char** pdata, int* psize)
{
if (!amf0) {
return NULL;
}
SrsAmf0Any* any = (SrsAmf0Any*)amf0;
return any->human_print(pdata, psize);
}
const char* srs_human_flv_tag_type2string(char type)
{
static const char* audio = "Audio";
static const char* video = "Video";
static const char* data = "Data";
static const char* unknown = "Unknown";
switch (type) {
case SRS_RTMP_TYPE_AUDIO: return audio;
case SRS_RTMP_TYPE_VIDEO: return video;
case SRS_RTMP_TYPE_SCRIPT: return data;
default: return unknown;
}
return unknown;
}
const char* srs_human_flv_video_codec_id2string(char codec_id)
{
static const char* h263 = "H.263";
static const char* screen = "Screen";
static const char* vp6 = "VP6";
static const char* vp6_alpha = "VP6Alpha";
static const char* screen2 = "Screen2";
static const char* h264 = "H.264";
static const char* unknown = "Unknown";
switch (codec_id) {
case 2: return h263;
case 3: return screen;
case 4: return vp6;
case 5: return vp6_alpha;
case 6: return screen2;
case 7: return h264;
default: return unknown;
}
return unknown;
}
const char* srs_human_flv_video_avc_packet_type2string(char avc_packet_type)
{
static const char* sps_pps = "SpsPps";
static const char* nalu = "Nalu";
static const char* sps_pps_end = "SpsPpsEnd";
static const char* unknown = "Unknown";
switch (avc_packet_type) {
case 0: return sps_pps;
case 1: return nalu;
case 2: return sps_pps_end;
default: return unknown;
}
return unknown;
}
const char* srs_human_flv_video_frame_type2string(char frame_type)
{
static const char* keyframe = "I";
static const char* interframe = "P/B";
static const char* disposable_interframe = "DI";
static const char* generated_keyframe = "GI";
static const char* video_infoframe = "VI";
static const char* unknown = "Unknown";
switch (frame_type) {
case 1: return keyframe;
case 2: return interframe;
case 3: return disposable_interframe;
case 4: return generated_keyframe;
case 5: return video_infoframe;
default: return unknown;
}
return unknown;
}
int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int size)
{
int ret = ERROR_SUCCESS;
u_int32_t pts;
if (srs_utils_parse_timestamp(timestamp, type, data, size, &pts) != 0) {
return ret;
}
if (type == SRS_RTMP_TYPE_VIDEO) {
srs_human_trace("Video packet type=%s, dts=%d, pts=%d, size=%d, %s(%s,%s)",
srs_human_flv_tag_type2string(type), timestamp, pts, size,
srs_human_flv_video_codec_id2string(srs_utils_get_flv_video_codec_id(data, size)),
srs_human_flv_video_avc_packet_type2string(srs_utils_get_flv_video_avc_packet_type(data, size)),
srs_human_flv_video_frame_type2string(srs_utils_get_flv_video_frame_type(data, size))
);
} else if (type == SRS_RTMP_TYPE_AUDIO) {
srs_human_trace("Audio packet type=%s, dts=%d, pts=%d, size=%d",
srs_human_flv_tag_type2string(type), timestamp, pts, size);
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
srs_human_verbose("Data packet type=%s, time=%d, size=%d",
srs_human_flv_tag_type2string(type), timestamp, size);
int nparsed = 0;
while (nparsed < size) {
int nb_parsed_this = 0;
srs_amf0_t amf0 = srs_amf0_parse(data + nparsed, size - nparsed, &nb_parsed_this);
if (amf0 == NULL) {
break;
}
nparsed += nb_parsed_this;
char* amf0_str = NULL;
srs_human_raw("%s", srs_human_amf0_print(amf0, &amf0_str, NULL));
srs_amf0_free_bytes(amf0_str);
}
} else {
srs_human_trace("Unknown packet type=%s, dts=%d, pts=%d, size=%d",
srs_human_flv_tag_type2string(type), timestamp, pts, size);
}
return ret;
}
const char* srs_human_format_time()
{
struct timeval tv;
static char buf[23];
memset(buf, 0, sizeof(buf));
// clock time
if (gettimeofday(&tv, NULL) == -1) {
return buf;
}
// to calendar time
struct tm* tm;
if ((tm = localtime((const time_t*)&tv.tv_sec)) == NULL) {
return buf;
}
snprintf(buf, sizeof(buf),
"%d-%02d-%02d %02d:%02d:%02d.%03d",
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
(int)(tv.tv_usec / 1000));
// for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213
buf[sizeof(buf) - 1] = 0;
return buf;
}
#ifdef __cplusplus
}
#endif
... ...
... ... @@ -265,83 +265,6 @@ extern int srs_version_revision();
/*************************************************************
**************************************************************
* utilities
**************************************************************
*************************************************************/
/**
* get the current system time in ms.
* use gettimeofday() to get system time.
*/
extern int64_t srs_utils_get_time_ms();
/**
* get the send bytes.
*/
extern int64_t srs_utils_get_send_bytes(srs_rtmp_t rtmp);
/**
* get the recv bytes.
*/
extern int64_t srs_utils_get_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_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(
u_int32_t time, char type, char* data, int size,
u_int32_t* ppts
);
/**
* 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_get_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_get_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_get_flv_video_frame_type(char* data, int size);
/*************************************************************
**************************************************************
* flv codec
* @example /trunk/research/librtmp/srs_flv_injecter.c
* @example /trunk/research/librtmp/srs_flv_parser.c
... ... @@ -500,80 +423,6 @@ extern void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value);
/*************************************************************
**************************************************************
* 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.
* SpsPps = 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);
/**
* print the rtmp packet, use srs_human_trace/srs_human_verbose for packet,
* and use srs_human_raw for script data body.
* @return an error code for parse the timetstamp to dts and pts.
*/
extern int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int size);
// log to console, for use srs-librtmp application.
extern const char* srs_human_format_time();
#define srs_human_trace(msg, ...) printf("[%s] ", srs_human_format_time());printf(msg, ##__VA_ARGS__);printf("\n")
#define srs_human_verbose(msg, ...) printf("[%s] ", srs_human_format_time());printf(msg, ##__VA_ARGS__);printf("\n")
#define srs_human_raw(msg, ...) printf(msg, ##__VA_ARGS__)
/*************************************************************
**************************************************************
* audio raw codec
**************************************************************
*************************************************************/
... ... @@ -735,6 +584,157 @@ extern int srs_h264_startswith_annexb(
int* pnb_start_code
);
/*************************************************************
**************************************************************
* utilities
**************************************************************
*************************************************************/
/**
* get the current system time in ms.
* use gettimeofday() to get system time.
*/
extern int64_t srs_utils_get_time_ms();
/**
* get the send bytes.
*/
extern int64_t srs_utils_get_send_bytes(srs_rtmp_t rtmp);
/**
* get the recv bytes.
*/
extern int64_t srs_utils_get_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_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(
u_int32_t time, char type, char* data, int size,
u_int32_t* ppts
);
/**
* 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_get_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_get_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_get_flv_video_frame_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.
* SpsPps = 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);
/**
* print the rtmp packet, use srs_human_trace/srs_human_verbose for packet,
* and use srs_human_raw for script data body.
* @return an error code for parse the timetstamp to dts and pts.
*/
extern int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int size);
// log to console, for use srs-librtmp application.
extern const char* srs_human_format_time();
#define srs_human_trace(msg, ...) printf("[%s] ", srs_human_format_time());printf(msg, ##__VA_ARGS__);printf("\n")
#define srs_human_verbose(msg, ...) printf("[%s] ", srs_human_format_time());printf(msg, ##__VA_ARGS__);printf("\n")
#define srs_human_raw(msg, ...) printf(msg, ##__VA_ARGS__)
#ifdef __cplusplus
}
#endif
... ...