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

substitute all TAB with 4spaces.

This commit is contained in:
winlin 2014-03-18 11:32:58 +08:00
parent e5770b10b1
commit c85dde7f3f
64 changed files with 14105 additions and 14105 deletions

View file

@ -45,28 +45,28 @@ SrsBandwidth::~SrsBandwidth()
int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServer* _rtmp)
{
int ret = ERROR_SUCCESS;
rtmp = _rtmp;
req = _req;
if (!_srs_config->get_bw_check_enabled(req->vhost)) {
return ret;
}
int ret = ERROR_SUCCESS;
rtmp = _rtmp;
req = _req;
if (!_srs_config->get_bw_check_enabled(req->vhost)) {
return ret;
}
// validate the bandwidth check key
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
if (req->tcUrl.find(key) == std::string::npos) {
ret = ERROR_SYSTEM_BANDWIDTH_KEY;
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
return ret;
}
// shared global last check time,
// to avoid attach by bandwidth check,
// if client request check in the window(specifeid by interval),
// directly reject the request.
// validate the bandwidth check key
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
if (req->tcUrl.find(key) == std::string::npos) {
ret = ERROR_SYSTEM_BANDWIDTH_KEY;
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
return ret;
}
// shared global last check time,
// to avoid attach by bandwidth check,
// if client request check in the window(specifeid by interval),
// directly reject the request.
static int64_t last_check_time = 0;
int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost);
@ -75,16 +75,16 @@ int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServe
if (last_check_time > 0 && time_now - last_check_time < interval_ms) {
ret = ERROR_SYSTEM_BANDWIDTH_DENIED;
srs_trace("bandcheck denied, "
"last_check=%"PRId64", now=%"PRId64", interval=%d",
last_check_time, time_now, interval_ms);
"last_check=%"PRId64", now=%"PRId64", interval=%d",
last_check_time, time_now, interval_ms);
rtmp->response_connect_reject(req, "bandcheck rejected");
return ret;
}
// accept and do bandwidth check.
last_check_time = time_now;
last_check_time = time_now;
char* local_ip = 0;
if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) {
srs_error("get local ip failed. ret = %d", ret);
@ -137,7 +137,7 @@ int SrsBandwidth::do_bandwidth_check()
{
int ret = ERROR_SUCCESS;
SrsProtocol* protocol = rtmp->get_protocol();
SrsProtocol* protocol = rtmp->get_protocol();
int play_duration_ms = 3000;
int play_interval_ms = 0;
@ -154,14 +154,14 @@ int SrsBandwidth::do_bandwidth_check()
int64_t start_time = srs_get_system_time_ms();
ret = check_play(play_duration_ms,
play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps);
play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps);
if (ret != ERROR_SUCCESS) {
srs_error("band width play check failed. ret=%d", ret);
return ret;
}
ret = check_publish(publish_duration_ms,
publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps);
publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps);
if (ret != ERROR_SUCCESS) {
srs_error("band width publish check failed. ret=%d", ret);
return ret;
@ -188,29 +188,29 @@ int SrsBandwidth::do_bandwidth_check()
pkt->data->set("publish_bytes", SrsAmf0Any::number(publish_bytes));
pkt->data->set("publish_time", SrsAmf0Any::number(publish_actual_duration_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check finish message failed. ret=%d", ret);
return ret;
}
// if flash, we notice the result, and expect a final packet.
while (true) {
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
// info level to ignore and return success.
srs_info("expect final message failed. ret=%d", ret);
return ERROR_SUCCESS;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get final message success.");
if (pkt->is_flash_final()) {
srs_info("BW check recv flash final response.");
break;
}
}
while (true) {
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
// info level to ignore and return success.
srs_info("expect final message failed. ret=%d", ret);
return ERROR_SUCCESS;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get final message success.");
if (pkt->is_flash_final()) {
srs_info("BW check recv flash final response.");
break;
}
}
srs_info("BW check finished.");
@ -218,44 +218,44 @@ int SrsBandwidth::do_bandwidth_check()
}
int SrsBandwidth::check_play(
int duration_ms, int interval_ms, int& actual_duration_ms,
int& play_bytes, int max_play_kbps)
int duration_ms, int interval_ms, int& actual_duration_ms,
int& play_bytes, int max_play_kbps)
{
int ret = ERROR_SUCCESS;
SrsProtocol* protocol = rtmp->get_protocol();
SrsProtocol* protocol = rtmp->get_protocol();
if (true) {
// send start play command to client
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check start play message failed. ret=%d", ret);
return ret;
}
srs_info("BW check begin.");
}
if (true) {
// send start play command to client
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check start play message failed. ret=%d", ret);
return ret;
}
srs_info("BW check begin.");
}
while (true) {
// recv client's starting play response
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_starting_play()) {
srs_info("BW check recv play begin response.");
break;
}
}
while (true) {
// recv client's starting play response
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_starting_play()) {
srs_info("BW check recv play begin response.");
break;
}
}
// send play data to client
int64_t current_time = srs_get_system_time_ms();
@ -280,10 +280,10 @@ int SrsBandwidth::check_play(
}
data_count += 2;
// TODO: FIXME: get length from the rtmp protocol stack.
// TODO: FIXME: get length from the rtmp protocol stack.
play_bytes += pkt->get_payload_length();
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check play messages failed. ret=%d", ret);
return ret;
@ -305,81 +305,81 @@ int SrsBandwidth::check_play(
actual_duration_ms = srs_get_system_time_ms() - current_time;
srs_info("BW check send play bytes over.");
if (true) {
// notify client to stop play
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes));
if (true) {
// notify client to stop play
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check stop play message failed. ret=%d", ret);
return ret;
}
srs_info("BW check stop play bytes.");
}
srs_error("send bandwidth check stop play message failed. ret=%d", ret);
return ret;
}
srs_info("BW check stop play bytes.");
}
while (true) {
// recv client's stop play response.
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_stopped_play()) {
srs_info("BW check recv stop play response.");
break;
}
}
while (true) {
// recv client's stop play response.
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_stopped_play()) {
srs_info("BW check recv stop play response.");
break;
}
}
return ret;
}
int SrsBandwidth::check_publish(
int duration_ms, int interval_ms, int& actual_duration_ms,
int& publish_bytes, int max_pub_kbps)
int duration_ms, int interval_ms, int& actual_duration_ms,
int& publish_bytes, int max_pub_kbps)
{
int ret = ERROR_SUCCESS;
SrsProtocol* protocol = rtmp->get_protocol();
SrsProtocol* protocol = rtmp->get_protocol();
if (true) {
// notify client to start publish
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check start publish message failed. ret=%d", ret);
return ret;
}
srs_info("BW check publish begin.");
}
if (true) {
// notify client to start publish
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check start publish message failed. ret=%d", ret);
return ret;
}
srs_info("BW check publish begin.");
}
while (true) {
// read client's notification of starting publish
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_starting_publish()) {
srs_info("BW check recv publish begin response.");
break;
}
}
while (true) {
// read client's notification of starting publish
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_starting_publish()) {
srs_info("BW check recv publish begin response.");
break;
}
}
// recv publish msgs until @duration_ms ms
int64_t current_time = srs_get_system_time_ms();
@ -393,7 +393,7 @@ int SrsBandwidth::check_publish(
}
SrsAutoFree(SrsCommonMessage, msg, false);
// TODO: FIXME.
// TODO: FIXME.
publish_bytes += msg->header.payload_length;
int kbps = 0;
@ -411,21 +411,21 @@ int SrsBandwidth::check_publish(
actual_duration_ms = srs_get_system_time_ms() - current_time;
srs_info("BW check recv publish data over.");
if (true) {
// notify client to stop publish
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes));
if (true) {
// notify client to stop publish
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
return ret;
}
srs_info("BW check stop publish bytes.");
}
srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
return ret;
}
srs_info("BW check stop publish bytes.");
}
// expect client to stop publish
// if flash client, we never expect the client stop publish bytes,
@ -433,22 +433,22 @@ int SrsBandwidth::check_publish(
// there are many many packets in the queue.
// we just ignore the packet and send the bandwidth test data.
// TODO: FIXME: check whether flash client.
while (false) {
// recv client's stop publish response.
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_stopped_publish()) {
srs_info("BW check recv stop publish response.");
break;
}
}
while (false) {
// recv client's stop publish response.
SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret);
return ret;
}
SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes.");
if (pkt->is_stopped_publish()) {
srs_info("BW check recv stop publish response.");
break;
}
}
return ret;
}

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,7 @@ class SrsRefer;
class SrsConsumer;
class SrsCommonMessage;
class SrsSocket;
#ifdef SRS_HTTP_CALLBACK
#ifdef SRS_HTTP_CALLBACK
class SrsHttpHooks;
#endif
class SrsBandwidth;
@ -53,43 +53,43 @@ class SrsBandwidth;
class SrsClient : public SrsConnection, public ISrsReloadHandler
{
private:
char* ip;
SrsRequest* req;
SrsResponse* res;
SrsSocket* skt;
SrsRtmpServer* rtmp;
SrsRefer* refer;
#ifdef SRS_HTTP_CALLBACK
SrsHttpHooks* http_hooks;
char* ip;
SrsRequest* req;
SrsResponse* res;
SrsSocket* skt;
SrsRtmpServer* rtmp;
SrsRefer* refer;
#ifdef SRS_HTTP_CALLBACK
SrsHttpHooks* http_hooks;
#endif
SrsBandwidth* bandwidth;
SrsBandwidth* bandwidth;
public:
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsClient();
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsClient();
protected:
virtual int do_cycle();
virtual int do_cycle();
// interface ISrsReloadHandler
public:
virtual int on_reload_vhost_removed(std::string vhost);
virtual int on_reload_vhost_removed(std::string vhost);
private:
// when valid and connected to vhost/app, service the client.
virtual int service_cycle();
// stream(play/publish) service cycle, identify client first.
virtual int stream_service_cycle();
virtual int check_vhost();
virtual int playing(SrsSource* source);
virtual int fmle_publish(SrsSource* source);
virtual int flash_publish(SrsSource* source);
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
virtual int get_peer_ip();
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
// when valid and connected to vhost/app, service the client.
virtual int service_cycle();
// stream(play/publish) service cycle, identify client first.
virtual int stream_service_cycle();
virtual int check_vhost();
virtual int playing(SrsSource* source);
virtual int fmle_publish(SrsSource* source);
virtual int flash_publish(SrsSource* source);
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
virtual int get_peer_ip();
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
private:
virtual int on_connect();
virtual void on_close();
virtual int on_publish();
virtual void on_unpublish();
virtual int on_play();
virtual void on_stop();
virtual int on_connect();
virtual void on_close();
virtual int on_publish();
virtual void on_unpublish();
virtual int on_play();
virtual void on_stop();
};
#endif

View file

@ -33,29 +33,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsCodecBuffer::SrsCodecBuffer()
{
size = 0;
bytes = NULL;
size = 0;
bytes = NULL;
}
void SrsCodecBuffer::append(void* data, int len)
{
srs_assert(data);
srs_assert(len > 0);
srs_assert(data);
srs_assert(len > 0);
bytes = (char*)realloc(bytes, size + len);
memcpy(bytes + size, data, len);
size += len;
bytes = (char*)realloc(bytes, size + len);
memcpy(bytes + size, data, len);
size += len;
}
void SrsCodecBuffer::free()
{
size = 0;
srs_freepa(bytes);
size = 0;
srs_freepa(bytes);
}
SrsCodecSample::SrsCodecSample()
{
clear();
clear();
}
SrsCodecSample::~SrsCodecSample()
@ -64,468 +64,468 @@ SrsCodecSample::~SrsCodecSample()
void SrsCodecSample::clear()
{
is_video = false;
nb_buffers = 0;
is_video = false;
nb_buffers = 0;
cts = 0;
frame_type = SrsCodecVideoAVCFrameReserved;
avc_packet_type = SrsCodecVideoAVCTypeReserved;
sound_rate = SrsCodecAudioSampleRateReserved;
sound_size = SrsCodecAudioSampleSizeReserved;
sound_type = SrsCodecAudioSoundTypeReserved;
aac_packet_type = SrsCodecAudioTypeReserved;
cts = 0;
frame_type = SrsCodecVideoAVCFrameReserved;
avc_packet_type = SrsCodecVideoAVCTypeReserved;
sound_rate = SrsCodecAudioSampleRateReserved;
sound_size = SrsCodecAudioSampleSizeReserved;
sound_type = SrsCodecAudioSoundTypeReserved;
aac_packet_type = SrsCodecAudioTypeReserved;
}
int SrsCodecSample::add_sample(char* bytes, int size)
{
int ret = ERROR_SUCCESS;
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode samples error, "
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
return ret;
}
SrsCodecBuffer* buf = &buffers[nb_buffers++];
buf->bytes = bytes;
buf->size = size;
return ret;
int ret = ERROR_SUCCESS;
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode samples error, "
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
return ret;
}
SrsCodecBuffer* buf = &buffers[nb_buffers++];
buf->bytes = bytes;
buf->size = size;
return ret;
}
SrsCodec::SrsCodec()
{
width = 0;
height = 0;
duration = 0;
NAL_unit_length = 0;
frame_rate = 0;
video_data_rate = 0;
video_codec_id = 0;
audio_data_rate = 0;
audio_codec_id = 0;
avc_profile = 0;
avc_level = 0;
aac_profile = 0;
aac_sample_rate = 0;
aac_channels = 0;
avc_extra_size = 0;
avc_extra_data = NULL;
aac_extra_size = 0;
aac_extra_data = NULL;
sequenceParameterSetLength = 0;
sequenceParameterSetNALUnit = NULL;
pictureParameterSetLength = 0;
pictureParameterSetNALUnit = NULL;
width = 0;
height = 0;
duration = 0;
NAL_unit_length = 0;
frame_rate = 0;
video_data_rate = 0;
video_codec_id = 0;
audio_data_rate = 0;
audio_codec_id = 0;
avc_profile = 0;
avc_level = 0;
aac_profile = 0;
aac_sample_rate = 0;
aac_channels = 0;
avc_extra_size = 0;
avc_extra_data = NULL;
aac_extra_size = 0;
aac_extra_data = NULL;
sequenceParameterSetLength = 0;
sequenceParameterSetNALUnit = NULL;
pictureParameterSetLength = 0;
pictureParameterSetNALUnit = NULL;
stream = new SrsStream();
stream = new SrsStream();
}
SrsCodec::~SrsCodec()
{
srs_freepa(avc_extra_data);
srs_freepa(aac_extra_data);
srs_freepa(avc_extra_data);
srs_freepa(aac_extra_data);
srs_freep(stream);
srs_freepa(sequenceParameterSetNALUnit);
srs_freepa(pictureParameterSetNALUnit);
srs_freep(stream);
srs_freepa(sequenceParameterSetNALUnit);
srs_freepa(pictureParameterSetNALUnit);
}
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
sample->is_video = false;
if (!data || size <= 0) {
srs_trace("no audio present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
int ret = ERROR_SUCCESS;
sample->is_video = false;
if (!data || size <= 0) {
srs_trace("no audio present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
// audio decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio sound_format failed. ret=%d", ret);
return ret;
}
int8_t sound_format = stream->read_1bytes();
int8_t sound_type = sound_format & 0x01;
int8_t sound_size = (sound_format >> 1) & 0x01;
int8_t sound_rate = (sound_format >> 2) & 0x03;
sound_format = (sound_format >> 4) & 0x0f;
audio_codec_id = sound_format;
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
// reset the sample rate by sequence header
// audio decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio sound_format failed. ret=%d", ret);
return ret;
}
int8_t sound_format = stream->read_1bytes();
int8_t sound_type = sound_format & 0x01;
int8_t sound_size = (sound_format >> 1) & 0x01;
int8_t sound_rate = (sound_format >> 2) & 0x03;
sound_format = (sound_format >> 4) & 0x0f;
audio_codec_id = sound_format;
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
// reset the sample rate by sequence header
static int aac_sample_rates[] = {
96000, 88200, 64000, 48000,
44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000,
7350, 0, 0, 0
96000, 88200, 64000, 48000,
44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000,
7350, 0, 0, 0
};
switch (aac_sample_rates[aac_sample_rate]) {
case 11025:
sample->sound_rate = SrsCodecAudioSampleRate11025;
break;
sample->sound_rate = SrsCodecAudioSampleRate11025;
break;
case 22050:
sample->sound_rate = SrsCodecAudioSampleRate22050;
break;
sample->sound_rate = SrsCodecAudioSampleRate22050;
break;
case 44100:
sample->sound_rate = SrsCodecAudioSampleRate44100;
break;
sample->sound_rate = SrsCodecAudioSampleRate44100;
break;
};
// only support aac
if (audio_codec_id != SrsCodecAudioAAC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support audio aac codec. ret=%d", ret);
return ret;
}
// only support aac
if (audio_codec_id != SrsCodecAudioAAC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support audio aac codec. ret=%d", ret);
return ret;
}
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
return ret;
}
int8_t aac_packet_type = stream->read_1bytes();
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
// AudioSpecificConfig
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
aac_extra_size = stream->left();
if (aac_extra_size > 0) {
srs_freepa(aac_extra_data);
aac_extra_data = new char[aac_extra_size];
memcpy(aac_extra_data, stream->current(), aac_extra_size);
}
// only need to decode the first 2bytes:
// audioObjectType, aac_profile, 5bits.
// samplingFrequencyIndex, aac_sample_rate, 4bits.
// channelConfiguration, aac_channels, 4bits
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
return ret;
}
aac_profile = stream->read_1bytes();
aac_sample_rate = stream->read_1bytes();
aac_channels = (aac_sample_rate >> 3) & 0x0f;
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
aac_profile = (aac_profile >> 3) & 0x1f;
if (aac_profile == 0 || aac_profile == 0x1f) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed, "
"adts object=%d invalid. ret=%d", aac_profile, ret);
return ret;
}
// aac_profile = audioObjectType - 1
aac_profile--;
if (aac_profile > 3) {
// Mark all extended profiles as LC
// to make Android as happy as possible.
// @see: ngx_rtmp_hls_parse_aac_header
aac_profile = 1;
}
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
// ensure the sequence header demuxed
if (aac_extra_size <= 0 || !aac_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
return ret;
}
// Raw AAC frame data in UI8 []
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
srs_error("hls add audio sample failed. ret=%d", ret);
return ret;
}
} else {
// ignored.
}
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
return ret;
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
return ret;
}
int8_t aac_packet_type = stream->read_1bytes();
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
// AudioSpecificConfig
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
aac_extra_size = stream->left();
if (aac_extra_size > 0) {
srs_freepa(aac_extra_data);
aac_extra_data = new char[aac_extra_size];
memcpy(aac_extra_data, stream->current(), aac_extra_size);
}
// only need to decode the first 2bytes:
// audioObjectType, aac_profile, 5bits.
// samplingFrequencyIndex, aac_sample_rate, 4bits.
// channelConfiguration, aac_channels, 4bits
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
return ret;
}
aac_profile = stream->read_1bytes();
aac_sample_rate = stream->read_1bytes();
aac_channels = (aac_sample_rate >> 3) & 0x0f;
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
aac_profile = (aac_profile >> 3) & 0x1f;
if (aac_profile == 0 || aac_profile == 0x1f) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed, "
"adts object=%d invalid. ret=%d", aac_profile, ret);
return ret;
}
// aac_profile = audioObjectType - 1
aac_profile--;
if (aac_profile > 3) {
// Mark all extended profiles as LC
// to make Android as happy as possible.
// @see: ngx_rtmp_hls_parse_aac_header
aac_profile = 1;
}
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
// ensure the sequence header demuxed
if (aac_extra_size <= 0 || !aac_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
return ret;
}
// Raw AAC frame data in UI8 []
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
srs_error("hls add audio sample failed. ret=%d", ret);
return ret;
}
} else {
// ignored.
}
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
return ret;
}
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
sample->is_video = true;
if (!data || size <= 0) {
srs_trace("no video present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
int ret = ERROR_SUCCESS;
sample->is_video = true;
if (!data || size <= 0) {
srs_trace("no video present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
// video decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video frame_type failed. ret=%d", ret);
return ret;
}
int8_t frame_type = stream->read_1bytes();
int8_t codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
// only support h.264/avc
if (codec_id != SrsCodecVideoAVC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
return ret;
}
video_codec_id = codec_id;
if (!stream->require(4)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
return ret;
}
int8_t avc_packet_type = stream->read_1bytes();
int32_t composition_time = stream->read_3bytes();
// pts = dts + cts.
sample->cts = composition_time;
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
// AVCDecoderConfigurationRecord
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
avc_extra_size = stream->left();
if (avc_extra_size > 0) {
srs_freepa(avc_extra_data);
avc_extra_data = new char[avc_extra_size];
memcpy(avc_extra_data, stream->current(), avc_extra_size);
}
if (!stream->require(6)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
return ret;
}
//int8_t configurationVersion = stream->read_1bytes();
//int8_t AVCProfileIndication = stream->read_1bytes();
//int8_t profile_compatibility = stream->read_1bytes();
//int8_t AVCLevelIndication = stream->read_1bytes();
stream->skip(4);
// parse the NALU size.
int8_t lengthSizeMinusOne = stream->read_1bytes();
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
// 1 sps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
int8_t numOfSequenceParameterSets = stream->read_1bytes();
numOfSequenceParameterSets &= 0x1f;
if (numOfSequenceParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
return ret;
}
sequenceParameterSetLength = stream->read_2bytes();
if (!stream->require(sequenceParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
return ret;
}
if (sequenceParameterSetLength > 0) {
srs_freepa(sequenceParameterSetNALUnit);
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
stream->skip(sequenceParameterSetLength);
}
// 1 pps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
int8_t numOfPictureParameterSets = stream->read_1bytes();
numOfPictureParameterSets &= 0x1f;
if (numOfPictureParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
return ret;
}
pictureParameterSetLength = stream->read_2bytes();
if (!stream->require(pictureParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
return ret;
}
if (pictureParameterSetLength > 0) {
srs_freepa(pictureParameterSetNALUnit);
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
stream->skip(pictureParameterSetLength);
}
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
// ensure the sequence header demuxed
if (avc_extra_size <= 0 || !avc_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
return ret;
}
// One or more NALUs (Full frames are required)
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
int PictureLength = stream->left();
for (int i = 0; i < PictureLength;) {
if (!stream->require(NAL_unit_length + 1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
return ret;
}
int32_t NALUnitLength = 0;
if (NAL_unit_length == 3) {
NALUnitLength = stream->read_4bytes();
} else if (NALUnitLength == 2) {
NALUnitLength = stream->read_3bytes();
} else if (NALUnitLength == 1) {
NALUnitLength = stream->read_2bytes();
} else {
NALUnitLength = stream->read_1bytes();
}
// NALUnit
if (!stream->require(NALUnitLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
return ret;
}
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
srs_error("hls add video sample failed. ret=%d", ret);
return ret;
}
stream->skip(NALUnitLength);
i += NAL_unit_length + 1 + NALUnitLength;
}
} else {
// ignored.
}
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
frame_type, video_codec_id, avc_packet_type, composition_time, size);
return ret;
// video decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video frame_type failed. ret=%d", ret);
return ret;
}
int8_t frame_type = stream->read_1bytes();
int8_t codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
// only support h.264/avc
if (codec_id != SrsCodecVideoAVC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
return ret;
}
video_codec_id = codec_id;
if (!stream->require(4)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
return ret;
}
int8_t avc_packet_type = stream->read_1bytes();
int32_t composition_time = stream->read_3bytes();
// pts = dts + cts.
sample->cts = composition_time;
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
// AVCDecoderConfigurationRecord
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
avc_extra_size = stream->left();
if (avc_extra_size > 0) {
srs_freepa(avc_extra_data);
avc_extra_data = new char[avc_extra_size];
memcpy(avc_extra_data, stream->current(), avc_extra_size);
}
if (!stream->require(6)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
return ret;
}
//int8_t configurationVersion = stream->read_1bytes();
//int8_t AVCProfileIndication = stream->read_1bytes();
//int8_t profile_compatibility = stream->read_1bytes();
//int8_t AVCLevelIndication = stream->read_1bytes();
stream->skip(4);
// parse the NALU size.
int8_t lengthSizeMinusOne = stream->read_1bytes();
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
// 1 sps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
int8_t numOfSequenceParameterSets = stream->read_1bytes();
numOfSequenceParameterSets &= 0x1f;
if (numOfSequenceParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
return ret;
}
sequenceParameterSetLength = stream->read_2bytes();
if (!stream->require(sequenceParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
return ret;
}
if (sequenceParameterSetLength > 0) {
srs_freepa(sequenceParameterSetNALUnit);
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
stream->skip(sequenceParameterSetLength);
}
// 1 pps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
int8_t numOfPictureParameterSets = stream->read_1bytes();
numOfPictureParameterSets &= 0x1f;
if (numOfPictureParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
return ret;
}
pictureParameterSetLength = stream->read_2bytes();
if (!stream->require(pictureParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
return ret;
}
if (pictureParameterSetLength > 0) {
srs_freepa(pictureParameterSetNALUnit);
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
stream->skip(pictureParameterSetLength);
}
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
// ensure the sequence header demuxed
if (avc_extra_size <= 0 || !avc_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
return ret;
}
// One or more NALUs (Full frames are required)
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
int PictureLength = stream->left();
for (int i = 0; i < PictureLength;) {
if (!stream->require(NAL_unit_length + 1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
return ret;
}
int32_t NALUnitLength = 0;
if (NAL_unit_length == 3) {
NALUnitLength = stream->read_4bytes();
} else if (NALUnitLength == 2) {
NALUnitLength = stream->read_3bytes();
} else if (NALUnitLength == 1) {
NALUnitLength = stream->read_2bytes();
} else {
NALUnitLength = stream->read_1bytes();
}
// NALUnit
if (!stream->require(NALUnitLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
return ret;
}
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
srs_error("hls add video sample failed. ret=%d", ret);
return ret;
}
stream->skip(NALUnitLength);
i += NAL_unit_length + 1 + NALUnitLength;
}
} else {
// ignored.
}
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
frame_type, video_codec_id, avc_packet_type, composition_time, size);
return ret;
}
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
{
// 2bytes required.
if (size < 1) {
return false;
}
// 2bytes required.
if (size < 1) {
return false;
}
char frame_type = *(char*)data;
frame_type = (frame_type >> 4) & 0x0F;
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
char frame_type = *(char*)data;
frame_type = (frame_type >> 4) & 0x0F;
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
}
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
{
// sequence header only for h264
if (!video_is_h264(data, size)) {
return false;
}
// 2bytes required.
if (size < 2) {
return false;
}
// sequence header only for h264
if (!video_is_h264(data, size)) {
return false;
}
// 2bytes required.
if (size < 2) {
return false;
}
char frame_type = *(char*)data;
frame_type = (frame_type >> 4) & 0x0F;
char frame_type = *(char*)data;
frame_type = (frame_type >> 4) & 0x0F;
char avc_packet_type = *(char*)(data + 1);
return frame_type == SrsCodecVideoAVCFrameKeyFrame
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
char avc_packet_type = *(char*)(data + 1);
return frame_type == SrsCodecVideoAVCFrameKeyFrame
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
}
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
{
// sequence header only for aac
if (!audio_is_aac(data, size)) {
return false;
}
// 2bytes required.
if (size < 2) {
return false;
}
char aac_packet_type = *(char*)(data + 1);
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
// sequence header only for aac
if (!audio_is_aac(data, size)) {
return false;
}
// 2bytes required.
if (size < 2) {
return false;
}
char aac_packet_type = *(char*)(data + 1);
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
}
bool SrsCodec::video_is_h264(int8_t* data, int size)
{
// 1bytes required.
if (size < 1) {
return false;
}
// 1bytes required.
if (size < 1) {
return false;
}
char codec_id = *(char*)data;
codec_id = codec_id & 0x0F;
return codec_id == SrsCodecVideoAVC;
char codec_id = *(char*)data;
codec_id = codec_id & 0x0F;
return codec_id == SrsCodecVideoAVC;
}
bool SrsCodec::audio_is_aac(int8_t* data, int size)
{
// 1bytes required.
if (size < 1) {
return false;
}
char sound_format = *(char*)data;
sound_format = (sound_format >> 4) & 0x0F;
return sound_format == SrsCodecAudioAAC;
// 1bytes required.
if (size < 1) {
return false;
}
char sound_format = *(char*)data;
sound_format = (sound_format >> 4) & 0x0F;
return sound_format == SrsCodecAudioAAC;
}

View file

@ -37,104 +37,104 @@ class SrsStream;
// E.4.3.1 VIDEODATA
// CodecID UB [4]
// 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
// 2 = Sorenson H.263
// 3 = Screen video
// 4 = On2 VP6
// 5 = On2 VP6 with alpha channel
// 6 = Screen video version 2
// 7 = AVC
enum SrsCodecVideo
{
SrsCodecVideoReserved = 0,
SrsCodecVideoSorensonH263 = 2,
SrsCodecVideoScreenVideo = 3,
SrsCodecVideoOn2VP6 = 4,
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
SrsCodecVideoScreenVideoVersion2 = 6,
SrsCodecVideoAVC = 7,
SrsCodecVideoReserved = 0,
SrsCodecVideoSorensonH263 = 2,
SrsCodecVideoScreenVideo = 3,
SrsCodecVideoOn2VP6 = 4,
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
SrsCodecVideoScreenVideoVersion2 = 6,
SrsCodecVideoAVC = 7,
};
// E.4.3.1 VIDEODATA
// Frame Type UB [4]
// 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
// 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
enum SrsCodecVideoAVCFrame
{
SrsCodecVideoAVCFrameReserved = 0,
SrsCodecVideoAVCFrameKeyFrame = 1,
SrsCodecVideoAVCFrameInterFrame = 2,
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
SrsCodecVideoAVCFrameReserved = 0,
SrsCodecVideoAVCFrameKeyFrame = 1,
SrsCodecVideoAVCFrameInterFrame = 2,
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
};
// AVCPacketType IF CodecID == 7 UI8
// 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)
// 0 = AVC sequence header
// 1 = AVC NALU
// 2 = AVC end of sequence (lower level NALU sequence ender is
// not required or supported)
enum SrsCodecVideoAVCType
{
SrsCodecVideoAVCTypeReserved = -1,
SrsCodecVideoAVCTypeSequenceHeader = 0,
SrsCodecVideoAVCTypeNALU = 1,
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
SrsCodecVideoAVCTypeReserved = -1,
SrsCodecVideoAVCTypeSequenceHeader = 0,
SrsCodecVideoAVCTypeNALU = 1,
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
};
// SoundFormat UB [4]
// 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
// 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.
enum SrsCodecAudio
{
SrsCodecAudioLinearPCMPlatformEndian = 0,
SrsCodecAudioADPCM = 1,
SrsCodecAudioMP3 = 2,
SrsCodecAudioLinearPCMLittleEndian = 3,
SrsCodecAudioNellymoser16kHzMono = 4,
SrsCodecAudioNellymoser8kHzMono = 5,
SrsCodecAudioNellymoser = 6,
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
SrsCodecAudioReserved = 9,
SrsCodecAudioAAC = 10,
SrsCodecAudioSpeex = 11,
SrsCodecAudioReservedMP3_8kHz = 14,
SrsCodecAudioReservedDeviceSpecificSound = 15,
SrsCodecAudioLinearPCMPlatformEndian = 0,
SrsCodecAudioADPCM = 1,
SrsCodecAudioMP3 = 2,
SrsCodecAudioLinearPCMLittleEndian = 3,
SrsCodecAudioNellymoser16kHzMono = 4,
SrsCodecAudioNellymoser8kHzMono = 5,
SrsCodecAudioNellymoser = 6,
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
SrsCodecAudioReserved = 9,
SrsCodecAudioAAC = 10,
SrsCodecAudioSpeex = 11,
SrsCodecAudioReservedMP3_8kHz = 14,
SrsCodecAudioReservedDeviceSpecificSound = 15,
};
// AACPacketType IF SoundFormat == 10 UI8
// The following values are defined:
// 0 = AAC sequence header
// 1 = AAC raw
// 0 = AAC sequence header
// 1 = AAC raw
enum SrsCodecAudioType
{
SrsCodecAudioTypeReserved = -1,
SrsCodecAudioTypeSequenceHeader = 0,
SrsCodecAudioTypeRawData = 1,
SrsCodecAudioTypeReserved = -1,
SrsCodecAudioTypeSequenceHeader = 0,
SrsCodecAudioTypeRawData = 1,
};
// Sampling rate. The following values are defined:
@ -144,12 +144,12 @@ enum SrsCodecAudioType
// 3 = 44 kHz = 44100 Hz
enum SrsCodecAudioSampleRate
{
SrsCodecAudioSampleRateReserved = -1,
SrsCodecAudioSampleRate5512 = 0,
SrsCodecAudioSampleRate11025 = 1,
SrsCodecAudioSampleRate22050 = 2,
SrsCodecAudioSampleRate44100 = 3,
SrsCodecAudioSampleRateReserved = -1,
SrsCodecAudioSampleRate5512 = 0,
SrsCodecAudioSampleRate11025 = 1,
SrsCodecAudioSampleRate22050 = 2,
SrsCodecAudioSampleRate44100 = 3,
};
// Size of each audio sample. This parameter only pertains to
@ -159,10 +159,10 @@ enum SrsCodecAudioSampleRate
// 1 = 16-bit samples
enum SrsCodecAudioSampleSize
{
SrsCodecAudioSampleSizeReserved = -1,
SrsCodecAudioSampleSize8bit = 0,
SrsCodecAudioSampleSize16bit = 1,
SrsCodecAudioSampleSizeReserved = -1,
SrsCodecAudioSampleSize8bit = 0,
SrsCodecAudioSampleSize16bit = 1,
};
// Mono or stereo sound
@ -170,10 +170,10 @@ enum SrsCodecAudioSampleSize
// 1 = Stereo sound
enum SrsCodecAudioSoundType
{
SrsCodecAudioSoundTypeReserved = -1,
SrsCodecAudioSoundTypeMono = 0,
SrsCodecAudioSoundTypeStereo = 1,
SrsCodecAudioSoundTypeReserved = -1,
SrsCodecAudioSoundTypeMono = 0,
SrsCodecAudioSoundTypeStereo = 1,
};
/**
@ -181,21 +181,21 @@ enum SrsCodecAudioSoundType
*/
struct SrsCodecBuffer
{
/**
* @remark user must manage the bytes.
*/
int size;
char* bytes;
SrsCodecBuffer();
void append(void* data, int len);
/**
* free the bytes,
* user can invoke it to free the bytes,
* the SrsCodecBuffer never free automatically.
*/
void free();
/**
* @remark user must manage the bytes.
*/
int size;
char* bytes;
SrsCodecBuffer();
void append(void* data, int len);
/**
* free the bytes,
* user can invoke it to free the bytes,
* the SrsCodecBuffer never free automatically.
*/
void free();
};
/**
@ -204,26 +204,26 @@ struct SrsCodecBuffer
class SrsCodecSample
{
public:
int nb_buffers;
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
int nb_buffers;
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
public:
bool is_video;
// video specified
SrsCodecVideoAVCFrame frame_type;
SrsCodecVideoAVCType avc_packet_type;
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
// cts = pts - dts, where dts = flvheader->timestamp.
int32_t cts;
// audio specified
SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type;
bool is_video;
// video specified
SrsCodecVideoAVCFrame frame_type;
SrsCodecVideoAVCType avc_packet_type;
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
// cts = pts - dts, where dts = flvheader->timestamp.
int32_t cts;
// audio specified
SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type;
public:
SrsCodecSample();
virtual ~SrsCodecSample();
void clear();
int add_sample(char* bytes, int size);
SrsCodecSample();
virtual ~SrsCodecSample();
void clear();
int add_sample(char* bytes, int size);
};
/**
@ -232,81 +232,81 @@ public:
class SrsCodec
{
private:
SrsStream* stream;
SrsStream* stream;
public:
/**
* video specified
*/
// @see: SrsCodecVideo
int video_codec_id;
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_profile;
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_level;
int width;
int height;
int video_data_rate; // in bps
int frame_rate;
int duration;
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
int8_t NAL_unit_length;
u_int16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit;
u_int16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit;
/**
* audio specified
*/
// @see: SrsCodecAudioType
int audio_codec_id;
int audio_data_rate; // in bps
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
u_int8_t aac_profile;
// samplingFrequencyIndex
u_int8_t aac_sample_rate;
// channelConfiguration
u_int8_t aac_channels;
// the avc extra data, the AVC sequence header,
// without the flv codec header,
// @see: ffmpeg, AVCodecContext::extradata
int avc_extra_size;
char* avc_extra_data;
// the aac extra data, the AAC sequence header,
// without the flv codec header,
// @see: ffmpeg, AVCodecContext::extradata
int aac_extra_size;
char* aac_extra_data;
/**
* video specified
*/
// @see: SrsCodecVideo
int video_codec_id;
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_profile;
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_level;
int width;
int height;
int video_data_rate; // in bps
int frame_rate;
int duration;
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
int8_t NAL_unit_length;
u_int16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit;
u_int16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit;
/**
* audio specified
*/
// @see: SrsCodecAudioType
int audio_codec_id;
int audio_data_rate; // in bps
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
u_int8_t aac_profile;
// samplingFrequencyIndex
u_int8_t aac_sample_rate;
// channelConfiguration
u_int8_t aac_channels;
// the avc extra data, the AVC sequence header,
// without the flv codec header,
// @see: ffmpeg, AVCodecContext::extradata
int avc_extra_size;
char* avc_extra_data;
// the aac extra data, the AAC sequence header,
// without the flv codec header,
// @see: ffmpeg, AVCodecContext::extradata
int aac_extra_size;
char* aac_extra_data;
public:
SrsCodec();
virtual ~SrsCodec();
SrsCodec();
virtual ~SrsCodec();
// the following function used for hls to build the codec info.
public:
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
// the following function used to finger out the flv/rtmp packet detail.
public:
/**
* only check the frame_type, not check the codec type.
*/
static bool video_is_keyframe(int8_t* data, int size);
/**
* check codec h264, keyframe, sequence header
*/
static bool video_is_sequence_header(int8_t* data, int size);
/**
* check codec aac, sequence header
*/
static bool audio_is_sequence_header(int8_t* data, int size);
/**
* check codec h264.
*/
static bool video_is_h264(int8_t* data, int size);
/**
* only check the frame_type, not check the codec type.
*/
static bool video_is_keyframe(int8_t* data, int size);
/**
* check codec h264, keyframe, sequence header
*/
static bool video_is_sequence_header(int8_t* data, int size);
/**
* check codec aac, sequence header
*/
static bool audio_is_sequence_header(int8_t* data, int size);
/**
* check codec h264.
*/
static bool video_is_h264(int8_t* data, int size);
private:
/**
* check codec aac.
*/
static bool audio_is_aac(int8_t* data, int size);
/**
* check codec aac.
*/
static bool audio_is_aac(int8_t* data, int size);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -66,25 +66,25 @@ class SrsFileBuffer;
class SrsConfDirective
{
public:
int conf_line;
std::string name;
std::vector<std::string> args;
std::vector<SrsConfDirective*> directives;
int conf_line;
std::string name;
std::vector<std::string> args;
std::vector<SrsConfDirective*> directives;
public:
SrsConfDirective();
virtual ~SrsConfDirective();
std::string arg0();
std::string arg1();
std::string arg2();
SrsConfDirective* at(int index);
SrsConfDirective* get(std::string _name);
SrsConfDirective* get(std::string _name, std::string _arg0);
SrsConfDirective();
virtual ~SrsConfDirective();
std::string arg0();
std::string arg1();
std::string arg2();
SrsConfDirective* at(int index);
SrsConfDirective* get(std::string _name);
SrsConfDirective* get(std::string _name, std::string _arg0);
public:
virtual int parse(const char* filename);
virtual int parse(const char* filename);
public:
enum SrsDirectiveType{parse_file, parse_block};
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
enum SrsDirectiveType{parse_file, parse_block};
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
};
/**
@ -97,81 +97,81 @@ public:
class SrsConfig
{
private:
bool show_help;
bool show_version;
std::string config_file;
SrsConfDirective* root;
std::vector<ISrsReloadHandler*> subscribes;
bool show_help;
bool show_version;
std::string config_file;
SrsConfDirective* root;
std::vector<ISrsReloadHandler*> subscribes;
public:
SrsConfig();
virtual ~SrsConfig();
SrsConfig();
virtual ~SrsConfig();
public:
virtual int reload();
virtual void subscribe(ISrsReloadHandler* handler);
virtual void unsubscribe(ISrsReloadHandler* handler);
virtual int reload();
virtual void subscribe(ISrsReloadHandler* handler);
virtual void unsubscribe(ISrsReloadHandler* handler);
public:
virtual int parse_options(int argc, char** argv);
virtual int parse_options(int argc, char** argv);
private:
virtual int parse_file(const char* filename);
virtual int parse_argv(int& i, char** argv);
virtual void print_help(char** argv);
virtual int parse_file(const char* filename);
virtual int parse_argv(int& i, char** argv);
virtual void print_help(char** argv);
public:
virtual SrsConfDirective* get_vhost(std::string vhost);
virtual bool get_vhost_enabled(std::string vhost);
virtual bool get_vhost_enabled(SrsConfDirective* vhost);
virtual SrsConfDirective* get_vhost_on_connect(std::string vhost);
virtual SrsConfDirective* get_vhost_on_close(std::string vhost);
virtual SrsConfDirective* get_vhost_on_publish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
virtual bool get_engine_enabled(SrsConfDirective* engine);
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
virtual int get_engine_vbitrate(SrsConfDirective* engine);
virtual double get_engine_vfps(SrsConfDirective* engine);
virtual int get_engine_vwidth(SrsConfDirective* engine);
virtual int get_engine_vheight(SrsConfDirective* engine);
virtual int get_engine_vthreads(SrsConfDirective* engine);
virtual std::string get_engine_vprofile(SrsConfDirective* engine);
virtual std::string get_engine_vpreset(SrsConfDirective* engine);
virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams);
virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
virtual std::string get_engine_acodec(SrsConfDirective* engine);
virtual int get_engine_abitrate(SrsConfDirective* engine);
virtual int get_engine_asample_rate(SrsConfDirective* engine);
virtual int get_engine_achannels(SrsConfDirective* engine);
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
virtual std::string get_engine_output(SrsConfDirective* engine);
virtual std::string get_log_dir();
virtual int get_max_connections();
virtual bool get_gop_cache(std::string vhost);
virtual double get_queue_length(std::string vhost);
virtual SrsConfDirective* get_forward(std::string vhost);
virtual SrsConfDirective* get_vhost(std::string vhost);
virtual bool get_vhost_enabled(std::string vhost);
virtual bool get_vhost_enabled(SrsConfDirective* vhost);
virtual SrsConfDirective* get_vhost_on_connect(std::string vhost);
virtual SrsConfDirective* get_vhost_on_close(std::string vhost);
virtual SrsConfDirective* get_vhost_on_publish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
virtual bool get_engine_enabled(SrsConfDirective* engine);
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
virtual int get_engine_vbitrate(SrsConfDirective* engine);
virtual double get_engine_vfps(SrsConfDirective* engine);
virtual int get_engine_vwidth(SrsConfDirective* engine);
virtual int get_engine_vheight(SrsConfDirective* engine);
virtual int get_engine_vthreads(SrsConfDirective* engine);
virtual std::string get_engine_vprofile(SrsConfDirective* engine);
virtual std::string get_engine_vpreset(SrsConfDirective* engine);
virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams);
virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
virtual std::string get_engine_acodec(SrsConfDirective* engine);
virtual int get_engine_abitrate(SrsConfDirective* engine);
virtual int get_engine_asample_rate(SrsConfDirective* engine);
virtual int get_engine_achannels(SrsConfDirective* engine);
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
virtual std::string get_engine_output(SrsConfDirective* engine);
virtual std::string get_log_dir();
virtual int get_max_connections();
virtual bool get_gop_cache(std::string vhost);
virtual double get_queue_length(std::string vhost);
virtual SrsConfDirective* get_forward(std::string vhost);
private:
virtual SrsConfDirective* get_hls(std::string vhost);
virtual SrsConfDirective* get_hls(std::string vhost);
public:
virtual bool get_hls_enabled(std::string vhost);
virtual std::string get_hls_path(std::string vhost);
virtual double get_hls_fragment(std::string vhost);
virtual double get_hls_window(std::string vhost);
virtual SrsConfDirective* get_refer(std::string vhost);
virtual SrsConfDirective* get_refer_play(std::string vhost);
virtual SrsConfDirective* get_refer_publish(std::string vhost);
virtual SrsConfDirective* get_listen();
virtual int get_chunk_size(const std::string& vhost);
virtual int get_pithy_print_publish();
virtual int get_pithy_print_forwarder();
virtual int get_pithy_print_encoder();
virtual int get_pithy_print_hls();
virtual int get_pithy_print_play();
virtual bool get_hls_enabled(std::string vhost);
virtual std::string get_hls_path(std::string vhost);
virtual double get_hls_fragment(std::string vhost);
virtual double get_hls_window(std::string vhost);
virtual SrsConfDirective* get_refer(std::string vhost);
virtual SrsConfDirective* get_refer_play(std::string vhost);
virtual SrsConfDirective* get_refer_publish(std::string vhost);
virtual SrsConfDirective* get_listen();
virtual int get_chunk_size(const std::string& vhost);
virtual int get_pithy_print_publish();
virtual int get_pithy_print_forwarder();
virtual int get_pithy_print_encoder();
virtual int get_pithy_print_hls();
virtual int get_pithy_print_play();
virtual bool get_bw_check_enabled(const std::string& vhost);
virtual std::string get_bw_check_key(const std::string& vhost);
virtual int get_bw_check_interval_ms(const std::string& vhost);
virtual int get_bw_check_limit_kbps(const std::string& vhost);
virtual std::string get_bw_check_key(const std::string& vhost);
virtual int get_bw_check_interval_ms(const std::string& vhost);
virtual int get_bw_check_limit_kbps(const std::string& vhost);
};
/**

View file

@ -29,19 +29,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd)
{
server = srs_server;
stfd = client_stfd;
connection_id = 0;
server = srs_server;
stfd = client_stfd;
connection_id = 0;
}
SrsConnection::~SrsConnection()
{
srs_close_stfd(stfd);
srs_close_stfd(stfd);
}
int SrsConnection::start()
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
if (st_thread_create(cycle_thread, this, 0, 0) == NULL) {
ret = ERROR_ST_CREATE_CYCLE_THREAD;
@ -49,44 +49,44 @@ int SrsConnection::start()
return ret;
}
srs_verbose("create st conn cycle thread success.");
return ret;
return ret;
}
void SrsConnection::cycle()
{
int ret = ERROR_SUCCESS;
_srs_context->generate_id();
connection_id = _srs_context->get_id();
ret = do_cycle();
// if socket io error, set to closed.
if (srs_is_client_gracefully_close(ret)) {
ret = ERROR_SOCKET_CLOSED;
}
int ret = ERROR_SUCCESS;
// success.
if (ret == ERROR_SUCCESS) {
srs_trace("client process normally finished. ret=%d", ret);
}
// client close peer.
if (ret == ERROR_SOCKET_CLOSED) {
srs_warn("client disconnect peer. ret=%d", ret);
}
server->remove(this);
_srs_context->generate_id();
connection_id = _srs_context->get_id();
ret = do_cycle();
// if socket io error, set to closed.
if (srs_is_client_gracefully_close(ret)) {
ret = ERROR_SOCKET_CLOSED;
}
// success.
if (ret == ERROR_SUCCESS) {
srs_trace("client process normally finished. ret=%d", ret);
}
// client close peer.
if (ret == ERROR_SOCKET_CLOSED) {
srs_warn("client disconnect peer. ret=%d", ret);
}
server->remove(this);
}
void* SrsConnection::cycle_thread(void* arg)
{
SrsConnection* conn = (SrsConnection*)arg;
srs_assert(conn != NULL);
conn->cycle();
return NULL;
SrsConnection* conn = (SrsConnection*)arg;
srs_assert(conn != NULL);
conn->cycle();
return NULL;
}

View file

@ -36,19 +36,19 @@ class SrsServer;
class SrsConnection
{
protected:
SrsServer* server;
st_netfd_t stfd;
int connection_id;
SrsServer* server;
st_netfd_t stfd;
int connection_id;
public:
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsConnection();
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsConnection();
public:
virtual int start();
virtual int start();
protected:
virtual int do_cycle() = 0;
virtual int do_cycle() = 0;
private:
virtual void cycle();
static void* cycle_thread(void* arg);
virtual void cycle();
static void* cycle_thread(void* arg);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -47,38 +47,38 @@ class SrsPithyPrint;
class SrsFFMPEG
{
private:
bool started;
pid_t pid;
bool started;
pid_t pid;
private:
std::string log_file;
int log_fd;
std::string log_file;
int log_fd;
private:
std::string ffmpeg;
std::vector<std::string> vfilter;
std::string vcodec;
int vbitrate;
double vfps;
int vwidth;
int vheight;
int vthreads;
std::string vprofile;
std::string vpreset;
std::vector<std::string> vparams;
std::string acodec;
int abitrate;
int asample_rate;
int achannels;
std::vector<std::string> aparams;
std::string output;
std::string input;
std::string ffmpeg;
std::vector<std::string> vfilter;
std::string vcodec;
int vbitrate;
double vfps;
int vwidth;
int vheight;
int vthreads;
std::string vprofile;
std::string vpreset;
std::vector<std::string> vparams;
std::string acodec;
int abitrate;
int asample_rate;
int achannels;
std::vector<std::string> aparams;
std::string output;
std::string input;
public:
SrsFFMPEG(std::string ffmpeg_bin);
virtual ~SrsFFMPEG();
SrsFFMPEG(std::string ffmpeg_bin);
virtual ~SrsFFMPEG();
public:
virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
virtual int start();
virtual int cycle();
virtual void stop();
virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
virtual int start();
virtual int cycle();
virtual void stop();
};
/**
@ -88,26 +88,26 @@ public:
class SrsEncoder : public ISrsThreadHandler
{
private:
std::vector<SrsFFMPEG*> ffmpegs;
std::vector<SrsFFMPEG*> ffmpegs;
private:
SrsThread* pthread;
SrsPithyPrint* pithy_print;
SrsThread* pthread;
SrsPithyPrint* pithy_print;
public:
SrsEncoder();
virtual ~SrsEncoder();
SrsEncoder();
virtual ~SrsEncoder();
public:
virtual int on_publish(SrsRequest* req);
virtual void on_unpublish();
virtual int on_publish(SrsRequest* req);
virtual void on_unpublish();
// interface ISrsThreadHandler.
public:
virtual int cycle();
virtual void on_leave_loop();
virtual int cycle();
virtual void on_leave_loop();
private:
virtual void clear_engines();
virtual SrsFFMPEG* at(int index);
virtual int parse_scope_engines(SrsRequest* req);
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
virtual void encoder();
virtual void clear_engines();
virtual SrsFFMPEG* at(int index);
virtual int parse_scope_engines(SrsRequest* req);
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
virtual void encoder();
};
#endif

View file

@ -42,203 +42,203 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsForwarder::SrsForwarder(SrsSource* _source)
{
source = _source;
io = NULL;
client = NULL;
stfd = NULL;
stream_id = 0;
source = _source;
io = NULL;
client = NULL;
stfd = NULL;
stream_id = 0;
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
queue = new SrsMessageQueue();
jitter = new SrsRtmpJitter();
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
queue = new SrsMessageQueue();
jitter = new SrsRtmpJitter();
}
SrsForwarder::~SrsForwarder()
{
on_unpublish();
srs_freep(pthread);
srs_freep(queue);
srs_freep(jitter);
on_unpublish();
srs_freep(pthread);
srs_freep(queue);
srs_freep(jitter);
}
void SrsForwarder::set_queue_size(double queue_size)
{
queue->set_queue_size(queue_size);
queue->set_queue_size(queue_size);
}
int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server)
{
int ret = ERROR_SUCCESS;
// forward app
app = req->app;
stream_name = req->stream;
server = forward_server;
std::string s_port = RTMP_DEFAULT_PORT;
port = ::atoi(RTMP_DEFAULT_PORT);
size_t pos = forward_server.find(":");
if (pos != std::string::npos) {
s_port = forward_server.substr(pos + 1);
server = forward_server.substr(0, pos);
}
// discovery vhost
std::string vhost = req->vhost;
srs_vhost_resolve(vhost, s_port);
port = ::atoi(s_port.c_str());
// generate tcUrl
tc_url = "rtmp://";
tc_url += vhost;
tc_url += "/";
tc_url += req->app;
// dead loop check
std::string source_ep = req->vhost;
source_ep += ":";
source_ep += req->port;
std::string dest_ep = vhost;
dest_ep += ":";
dest_ep += s_port;
if (source_ep == dest_ep) {
ret = ERROR_SYSTEM_FORWARD_LOOP;
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
source_ep.c_str(), dest_ep.c_str(), ret);
return ret;
}
srs_trace("start forward %s to %s, stream: %s/%s",
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
stream_name.c_str());
if ((ret = pthread->start()) != ERROR_SUCCESS) {
int ret = ERROR_SUCCESS;
// forward app
app = req->app;
stream_name = req->stream;
server = forward_server;
std::string s_port = RTMP_DEFAULT_PORT;
port = ::atoi(RTMP_DEFAULT_PORT);
size_t pos = forward_server.find(":");
if (pos != std::string::npos) {
s_port = forward_server.substr(pos + 1);
server = forward_server.substr(0, pos);
}
// discovery vhost
std::string vhost = req->vhost;
srs_vhost_resolve(vhost, s_port);
port = ::atoi(s_port.c_str());
// generate tcUrl
tc_url = "rtmp://";
tc_url += vhost;
tc_url += "/";
tc_url += req->app;
// dead loop check
std::string source_ep = req->vhost;
source_ep += ":";
source_ep += req->port;
std::string dest_ep = vhost;
dest_ep += ":";
dest_ep += s_port;
if (source_ep == dest_ep) {
ret = ERROR_SYSTEM_FORWARD_LOOP;
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
source_ep.c_str(), dest_ep.c_str(), ret);
return ret;
}
srs_trace("start forward %s to %s, stream: %s/%s",
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
stream_name.c_str());
if ((ret = pthread->start()) != ERROR_SUCCESS) {
srs_error("start srs thread failed. ret=%d", ret);
return ret;
}
return ret;
}
return ret;
}
void SrsForwarder::on_unpublish()
{
pthread->stop();
close_underlayer_socket();
srs_freep(client);
srs_freep(io);
pthread->stop();
close_underlayer_socket();
srs_freep(client);
srs_freep(io);
}
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
{
int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
srs_freep(metadata);
return ret;
}
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
return ret;
}
return ret;
int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
srs_freep(metadata);
return ret;
}
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
srs_freep(msg);
return ret;
}
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
return ret;
}
return ret;
int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
srs_freep(msg);
return ret;
}
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
srs_freep(msg);
return ret;
}
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
return ret;
}
return ret;
int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
srs_freep(msg);
return ret;
}
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsForwarder::cycle()
{
int ret = ERROR_SUCCESS;
if ((ret = connect_server()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(client);
int ret = ERROR_SUCCESS;
if ((ret = connect_server()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(client);
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
if ((ret = client->handshake()) != ERROR_SUCCESS) {
srs_error("handshake with server failed. ret=%d", ret);
return ret;
}
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
return ret;
}
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
return ret;
}
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
stream_name.c_str(), stream_id, ret);
return ret;
}
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
return ret;
}
if ((ret = forward()) != ERROR_SUCCESS) {
return ret;
}
return ret;
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
if ((ret = client->handshake()) != ERROR_SUCCESS) {
srs_error("handshake with server failed. ret=%d", ret);
return ret;
}
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
return ret;
}
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
return ret;
}
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
stream_name.c_str(), stream_id, ret);
return ret;
}
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
return ret;
}
if ((ret = forward()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
void SrsForwarder::close_underlayer_socket()
{
srs_close_stfd(stfd);
srs_close_stfd(stfd);
}
int SrsForwarder::connect_server()
{
int ret = ERROR_SUCCESS;
// reopen
close_underlayer_socket();
// open socket.
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
int ret = ERROR_SUCCESS;
// reopen
close_underlayer_socket();
// open socket.
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
@ -255,20 +255,20 @@ int SrsForwarder::connect_server()
return ret;
}
srs_freep(client);
srs_freep(io);
io = new SrsSocket(stfd);
client = new SrsRtmpClient(io);
// connect to server.
std::string ip = srs_dns_resolve(server);
if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret;
}
srs_freep(client);
srs_freep(io);
io = new SrsSocket(stfd);
client = new SrsRtmpClient(io);
// connect to server.
std::string ip = srs_dns_resolve(server);
if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
@ -281,69 +281,69 @@ int SrsForwarder::connect_server()
}
srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
return ret;
return ret;
}
int SrsForwarder::forward()
{
int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
while (pthread->can_loop()) {
// switch to other st-threads.
st_usleep(0);
while (pthread->can_loop()) {
// switch to other st-threads.
st_usleep(0);
// read from client.
if (true) {
SrsCommonMessage* msg = NULL;
ret = client->recv_message(&msg);
srs_verbose("play loop recv message. ret=%d", ret);
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
srs_error("recv server control message failed. ret=%d", ret);
return ret;
}
}
// forward all messages.
int count = 0;
SrsSharedPtrMessage** msgs = NULL;
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
srs_error("get message to forward failed. ret=%d", ret);
return ret;
}
// ignore when no messages.
if (count <= 0) {
srs_verbose("no packets to forward.");
continue;
}
SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
// read from client.
if (true) {
SrsCommonMessage* msg = NULL;
ret = client->recv_message(&msg);
srs_verbose("play loop recv message. ret=%d", ret);
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
srs_error("recv server control message failed. ret=%d", ret);
return ret;
}
}
// forward all messages.
int count = 0;
SrsSharedPtrMessage** msgs = NULL;
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
srs_error("get message to forward failed. ret=%d", ret);
return ret;
}
// ignore when no messages.
if (count <= 0) {
srs_verbose("no packets to forward.");
continue;
}
SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
// pithy print
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
if (pithy_print.can_print()) {
srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
}
// all msgs to forward.
for (int i = 0; i < count; i++) {
SrsSharedPtrMessage* msg = msgs[i];
srs_assert(msg);
msgs[i] = NULL;
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
srs_error("forwarder send message to server failed. ret=%d", ret);
return ret;
}
}
}
return ret;
// pithy print
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
if (pithy_print.can_print()) {
srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
}
// all msgs to forward.
for (int i = 0; i < count; i++) {
SrsSharedPtrMessage* msg = msgs[i];
srs_assert(msg);
msgs[i] = NULL;
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
srs_error("forwarder send message to server failed. ret=%d", ret);
return ret;
}
}
}
return ret;
}

View file

@ -49,39 +49,39 @@ class SrsSource;
class SrsForwarder : public ISrsThreadHandler
{
private:
std::string app;
std::string tc_url;
std::string stream_name;
int stream_id;
std::string server;
int port;
std::string app;
std::string tc_url;
std::string stream_name;
int stream_id;
std::string server;
int port;
private:
st_netfd_t stfd;
SrsThread* pthread;
st_netfd_t stfd;
SrsThread* pthread;
private:
SrsSource* source;
ISrsProtocolReaderWriter* io;
SrsRtmpClient* client;
SrsRtmpJitter* jitter;
SrsMessageQueue* queue;
SrsSource* source;
ISrsProtocolReaderWriter* io;
SrsRtmpClient* client;
SrsRtmpJitter* jitter;
SrsMessageQueue* queue;
public:
SrsForwarder(SrsSource* _source);
virtual ~SrsForwarder();
SrsForwarder(SrsSource* _source);
virtual ~SrsForwarder();
public:
virtual void set_queue_size(double queue_size);
virtual void set_queue_size(double queue_size);
public:
virtual int on_publish(SrsRequest* req, std::string forward_server);
virtual void on_unpublish();
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
virtual int on_audio(SrsSharedPtrMessage* msg);
virtual int on_video(SrsSharedPtrMessage* msg);
virtual int on_publish(SrsRequest* req, std::string forward_server);
virtual void on_unpublish();
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
virtual int on_audio(SrsSharedPtrMessage* msg);
virtual int on_video(SrsSharedPtrMessage* msg);
// interface ISrsThreadHandler.
public:
virtual int cycle();
virtual int cycle();
private:
virtual void close_underlayer_socket();
virtual int connect_server();
virtual int forward();
virtual void close_underlayer_socket();
virtual int connect_server();
virtual int forward();
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -56,40 +56,40 @@ class SrsSource;
class SrsHlsAacJitter
{
private:
int64_t base_pts;
int64_t nb_samples;
int sync_ms;
int64_t base_pts;
int64_t nb_samples;
int sync_ms;
public:
SrsHlsAacJitter();
virtual ~SrsHlsAacJitter();
/**
* when buffer start, calc the "correct" pts for ts,
* @param flv_pts, the flv pts calc from flv header timestamp,
* @return the calc correct pts.
*/
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
/**
* when buffer continue, muxer donot write to file,
* the audio buffer continue grow and donot need a pts,
* for the ts audio PES packet only has one pts at the first time.
*/
virtual void on_buffer_continue();
SrsHlsAacJitter();
virtual ~SrsHlsAacJitter();
/**
* when buffer start, calc the "correct" pts for ts,
* @param flv_pts, the flv pts calc from flv header timestamp,
* @return the calc correct pts.
*/
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
/**
* when buffer continue, muxer donot write to file,
* the audio buffer continue grow and donot need a pts,
* for the ts audio PES packet only has one pts at the first time.
*/
virtual void on_buffer_continue();
};
//TODO: refine the ts muxer, do more jobs.
class SrsTSMuxer
{
private:
int fd;
std::string path;
int fd;
std::string path;
public:
SrsTSMuxer();
virtual ~SrsTSMuxer();
SrsTSMuxer();
virtual ~SrsTSMuxer();
public:
virtual int open(std::string _path);
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
virtual void close();
virtual int open(std::string _path);
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
virtual void close();
};
/**
@ -98,26 +98,26 @@ public:
*/
struct SrsM3u8Segment
{
// duration in seconds in m3u8.
double duration;
// sequence number in m3u8.
int sequence_no;
// ts uri in m3u8.
std::string uri;
// ts full file to write.
std::string full_path;
// the muxer to write ts.
SrsTSMuxer* muxer;
// current segment start dts for m3u8
int64_t segment_start_dts;
SrsM3u8Segment();
virtual ~SrsM3u8Segment();
/**
* update the segment duration.
*/
virtual double update_duration(int64_t video_stream_dts);
// duration in seconds in m3u8.
double duration;
// sequence number in m3u8.
int sequence_no;
// ts uri in m3u8.
std::string uri;
// ts full file to write.
std::string full_path;
// the muxer to write ts.
SrsTSMuxer* muxer;
// current segment start dts for m3u8
int64_t segment_start_dts;
SrsM3u8Segment();
virtual ~SrsM3u8Segment();
/**
* update the segment duration.
*/
virtual double update_duration(int64_t video_stream_dts);
};
/**
@ -126,39 +126,39 @@ struct SrsM3u8Segment
class SrsM3u8Muxer
{
private:
std::string app;
std::string stream;
std::string app;
std::string stream;
private:
std::string hls_path;
int hls_fragment;
int hls_window;
std::string hls_path;
int hls_fragment;
int hls_window;
private:
int file_index;
std::string m3u8;
int file_index;
std::string m3u8;
private:
/**
* m3u8 segments.
*/
std::vector<SrsM3u8Segment*> segments;
/**
* current writing segment.
*/
SrsM3u8Segment* current;
// last known dts
int64_t video_stream_dts;
/**
* m3u8 segments.
*/
std::vector<SrsM3u8Segment*> segments;
/**
* current writing segment.
*/
SrsM3u8Segment* current;
// last known dts
int64_t video_stream_dts;
public:
SrsM3u8Muxer();
virtual ~SrsM3u8Muxer();
SrsM3u8Muxer();
virtual ~SrsM3u8Muxer();
public:
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
virtual int segment_open();
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
virtual int segment_close();
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
virtual int segment_open();
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
virtual int segment_close();
private:
virtual int refresh_m3u8();
virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
virtual int create_dir();
virtual int refresh_m3u8();
virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
virtual int create_dir();
};
/**
@ -167,35 +167,35 @@ private:
class SrsTSCache
{
private:
// current frame and buffer
SrsMpegtsFrame* af;
SrsCodecBuffer* ab;
SrsMpegtsFrame* vf;
SrsCodecBuffer* vb;
// current frame and buffer
SrsMpegtsFrame* af;
SrsCodecBuffer* ab;
SrsMpegtsFrame* vf;
SrsCodecBuffer* vb;
private:
// the audio cache buffer start pts, to flush audio if full.
int64_t audio_buffer_start_pts;
// time jitter for aac
SrsHlsAacJitter* aac_jitter;
// the audio cache buffer start pts, to flush audio if full.
int64_t audio_buffer_start_pts;
// time jitter for aac
SrsHlsAacJitter* aac_jitter;
public:
SrsTSCache();
virtual ~SrsTSCache();
SrsTSCache();
virtual ~SrsTSCache();
public:
/**
* write audio to cache, if need to flush, flush to muxer.
*/
virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample);
/**
* write video to muxer.
*/
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
/**
* flush audio in cache to muxer.
*/
virtual int flush_audio(SrsM3u8Muxer* muxer);
/**
* write audio to cache, if need to flush, flush to muxer.
*/
virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample);
/**
* write video to muxer.
*/
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
/**
* flush audio in cache to muxer.
*/
virtual int flush_audio(SrsM3u8Muxer* muxer);
private:
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
};
/**
@ -204,43 +204,43 @@ private:
class SrsHls
{
private:
SrsM3u8Muxer* muxer;
SrsTSCache* ts_cache;
SrsM3u8Muxer* muxer;
SrsTSCache* ts_cache;
private:
bool hls_enabled;
SrsSource* source;
SrsCodec* codec;
SrsCodecSample* sample;
SrsRtmpJitter* jitter;
SrsPithyPrint* pithy_print;
bool hls_enabled;
SrsSource* source;
SrsCodec* codec;
SrsCodecSample* sample;
SrsRtmpJitter* jitter;
SrsPithyPrint* pithy_print;
public:
SrsHls(SrsSource* _source);
virtual ~SrsHls();
SrsHls(SrsSource* _source);
virtual ~SrsHls();
public:
/**
* publish stream event, continue to write the m3u8,
* for the muxer object not destroyed.
*/
virtual int on_publish(SrsRequest* req);
/**
* the unpublish event, only close the muxer, donot destroy the
* muxer, for when we continue to publish, the m3u8 will continue.
*/
virtual void on_unpublish();
/**
* get some information from metadata, it's optinal.
*/
virtual int on_meta_data(SrsAmf0Object* metadata);
/**
* mux the audio packets to ts.
*/
virtual int on_audio(SrsSharedPtrMessage* audio);
/**
* mux the video packets to ts.
*/
virtual int on_video(SrsSharedPtrMessage* video);
/**
* publish stream event, continue to write the m3u8,
* for the muxer object not destroyed.
*/
virtual int on_publish(SrsRequest* req);
/**
* the unpublish event, only close the muxer, donot destroy the
* muxer, for when we continue to publish, the m3u8 will continue.
*/
virtual void on_unpublish();
/**
* get some information from metadata, it's optinal.
*/
virtual int on_meta_data(SrsAmf0Object* metadata);
/**
* mux the audio packets to ts.
*/
virtual int on_audio(SrsSharedPtrMessage* audio);
/**
* mux the video packets to ts.
*/
virtual int on_video(SrsSharedPtrMessage* video);
private:
virtual void hls_mux();
virtual void hls_mux();
};
#endif

View file

@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsHttpUri::SrsHttpUri()
{
port = SRS_DEFAULT_HTTP_PORT;
port = SRS_DEFAULT_HTTP_PORT;
}
SrsHttpUri::~SrsHttpUri()
@ -51,7 +51,7 @@ SrsHttpUri::~SrsHttpUri()
int SrsHttpUri::initialize(std::string _url)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
url = _url;
const char* purl = url.c_str();
@ -65,7 +65,7 @@ int SrsHttpUri::initialize(std::string _url)
return ret;
}
std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
if(!field.empty()){
schema = field;
}
@ -80,7 +80,7 @@ int SrsHttpUri::initialize(std::string _url)
path = get_uri_field(url, &hp_u, UF_PATH);
srs_info("parse url %s success", purl);
return ret;
return ret;
}
const char* SrsHttpUri::get_url()
@ -128,24 +128,24 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht
SrsHttpClient::SrsHttpClient()
{
connected = false;
stfd = NULL;
connected = false;
stfd = NULL;
}
SrsHttpClient::~SrsHttpClient()
{
disconnect();
disconnect();
}
int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
{
int ret = ERROR_SUCCESS;
if ((ret = connect(uri)) != ERROR_SUCCESS) {
srs_error("http connect server failed. ret=%d", ret);
return ret;
}
int ret = ERROR_SUCCESS;
if ((ret = connect(uri)) != ERROR_SUCCESS) {
srs_error("http connect server failed. ret=%d", ret);
return ret;
}
// send POST request to uri
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
std::stringstream ss;
@ -176,33 +176,33 @@ int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
return ret;
}
srs_info("parse http post response success.");
return ret;
return ret;
}
void SrsHttpClient::disconnect()
{
connected = false;
srs_close_stfd(stfd);
connected = false;
srs_close_stfd(stfd);
}
int SrsHttpClient::connect(SrsHttpUri* uri)
{
int ret = ERROR_SUCCESS;
if (connected) {
return ret;
}
disconnect();
std::string ip = srs_dns_resolve(uri->get_host());
if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret;
}
int ret = ERROR_SUCCESS;
if (connected) {
return ret;
}
disconnect();
std::string ip = srs_dns_resolve(uri->get_host());
if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret;
}
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
@ -217,7 +217,7 @@ int SrsHttpClient::connect(SrsHttpUri* uri)
srs_error("st_netfd_open_socket failed. ret=%d", ret);
return ret;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(uri->get_port());
@ -226,16 +226,16 @@ int SrsHttpClient::connect(SrsHttpUri* uri)
if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
ret = ERROR_ST_CONNECT;
srs_error("connect to server error. "
"ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);
"ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);
return ret;
}
srs_info("connect to server success. "
"http url=%s, server=%s, ip=%s, port=%d",
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
"http url=%s, server=%s, ip=%s, port=%d",
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
connected = true;
return ret;
return ret;
}
int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response)
@ -327,17 +327,17 @@ int SrsHttpClient::parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::str
char buf[SRS_HTTP_BODY_BUFFER];
return parse_response_body_data(
uri, skt, response, (size_t)body_left,
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
uri, skt, response, (size_t)body_left,
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
);
} else {
// if ignore response, use shared fast memory.
static char buf[SRS_HTTP_BODY_BUFFER];
return parse_response_body_data(
uri, skt, response, (size_t)body_left,
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
);
uri, skt, response, (size_t)body_left,
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
);
}
return ret;
@ -351,7 +351,7 @@ int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std
while (body_left > 0) {
ssize_t nread;
int size_to_read = srs_min(size, body_left);
int size_to_read = srs_min(size, body_left);
if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) {
srs_error("read header from server failed. ret=%d", ret);
return ret;
@ -394,424 +394,424 @@ SrsHttpHooks::~SrsHttpHooks()
int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req)
{
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_connect url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret;
}
/**
{
"action": "on_connect",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"pageUrl": "http://www.test.com/live.html"
}
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_connect url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret;
}
/**
{
"action": "on_connect",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"pageUrl": "http://www.test.com/live.html"
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_connect" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// pageUrl
<< '"' << "pageUrl" << '"' << ':'
<< '"' << req->pageUrl << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_connect uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_connect validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret;
}
srs_trace("http hook on_connect success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_connect" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// pageUrl
<< '"' << "pageUrl" << '"' << ':'
<< '"' << req->pageUrl << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_connect uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_connect validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret;
}
srs_trace("http hook on_connect success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)
{
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_close url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return;
}
/**
{
"action": "on_close",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_close url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return;
}
/**
{
"action": "on_close",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_close" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_close uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_close validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return;
}
srs_trace("http hook on_close success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_close" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_close uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_close validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return;
}
srs_trace("http hook on_close success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)
{
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_publish url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret;
}
/**
{
"action": "on_publish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_publish url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret;
}
/**
{
"action": "on_publish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_publish" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_publish uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_publish validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret;
}
srs_trace("http hook on_publish success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_publish" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_publish uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_publish validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret;
}
srs_trace("http hook on_publish success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)
{
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_unpublish url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return;
}
/**
{
"action": "on_unpublish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_unpublish url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return;
}
/**
{
"action": "on_unpublish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_unpublish" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_unpublish uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_unpublish validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return;
}
srs_trace("http hook on_unpublish success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_unpublish" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_unpublish uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_unpublish validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return;
}
srs_trace("http hook on_unpublish success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)
{
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_play url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret;
}
/**
{
"action": "on_play",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_play url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret;
}
/**
{
"action": "on_play",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_play" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_play uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_play validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret;
}
srs_trace("http hook on_play success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_play" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_play uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_play validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret;
}
srs_trace("http hook on_play success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret;
}
void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)
{
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_stop url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return;
}
/**
{
"action": "on_stop",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
int ret = ERROR_SUCCESS;
SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_stop url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return;
}
/**
{
"action": "on_stop",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_stop" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_stop uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_stop validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return;
}
srs_trace("http hook on_stop success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_stop" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
std::string data = ss.str();
std::string res;
SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_stop uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_stop validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return;
}
srs_trace("http hook on_stop success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return;
}
#endif

View file

@ -40,8 +40,8 @@ class SrsSocket;
#include <http_parser.h>
#define SRS_HTTP_HEADER_BUFFER 1024
#define SRS_HTTP_BODY_BUFFER 32 * 1024
#define SRS_HTTP_HEADER_BUFFER 1024
#define SRS_HTTP_BODY_BUFFER 32 * 1024
/**
* used to resolve the http uri.
@ -55,13 +55,13 @@ private:
int port;
std::string path;
public:
SrsHttpUri();
virtual ~SrsHttpUri();
SrsHttpUri();
virtual ~SrsHttpUri();
public:
/**
* initialize the http uri.
*/
virtual int initialize(std::string _url);
/**
* initialize the http uri.
*/
virtual int initialize(std::string _url);
public:
virtual const char* get_url();
virtual const char* get_schema();
@ -82,23 +82,23 @@ private:
class SrsHttpClient
{
private:
bool connected;
st_netfd_t stfd;
bool connected;
st_netfd_t stfd;
private:
http_parser http_header;
public:
SrsHttpClient();
virtual ~SrsHttpClient();
SrsHttpClient();
virtual ~SrsHttpClient();
public:
/**
* to post data to the uri.
* @param req the data post to uri.
* @param res the response data from server.
*/
virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
/**
* to post data to the uri.
* @param req the data post to uri.
* @param res the response data from server.
*/
virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
private:
virtual void disconnect();
virtual int connect(SrsHttpUri* uri);
virtual void disconnect();
virtual int connect(SrsHttpUri* uri);
private:
virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);
virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);
@ -117,54 +117,54 @@ private:
class SrsHttpHooks
{
public:
SrsHttpHooks();
virtual ~SrsHttpHooks();
SrsHttpHooks();
virtual ~SrsHttpHooks();
public:
/**
* on_connect hook, when client connect to srs.
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_close hook, when client disconnect to srs, where client is valid by on_connect.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
*/
virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_publish hook, when client(encoder) start to publish stream
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_unpublish hook, when client(encoder) stop publish stream.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
*/
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_play hook, when client start to play stream.
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_stop hook, when client stop to play the stream.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
*/
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_connect hook, when client connect to srs.
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_close hook, when client disconnect to srs, where client is valid by on_connect.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
*/
virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_publish hook, when client(encoder) start to publish stream
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_unpublish hook, when client(encoder) stop publish stream.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
*/
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_play hook, when client start to play stream.
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
/**
* on_stop hook, when client stop to play the stream.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
*/
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
};
#endif

View file

@ -36,7 +36,7 @@ SrsThreadContext::~SrsThreadContext()
void SrsThreadContext::generate_id()
{
static int id = 1;
static int id = 1;
cache[st_thread_self()] = id++;
}
@ -55,7 +55,7 @@ int SrsThreadContext::get_id()
SrsFastLog::SrsFastLog()
{
level = SrsLogLevel::Trace;
level = SrsLogLevel::Trace;
log_data = new char[LOG_MAX_SIZE];
}
@ -185,15 +185,15 @@ bool SrsFastLog::generate_header(const char* tag, int context_id, const char* le
int log_header_size = -1;
if (tag) {
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ",
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),
level_name, tag, context_id, errno);
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ",
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),
level_name, tag, context_id, errno);
} else {
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ",
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),
level_name, context_id, errno);
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ",
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),
level_name, context_id, errno);
}
if (log_header_size == -1) {

View file

@ -35,132 +35,132 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
struct SrsStageInfo : public ISrsReloadHandler
{
int stage_id;
int pithy_print_time_ms;
int nb_clients;
SrsStageInfo(int _stage_id)
{
stage_id = _stage_id;
nb_clients = 0;
update_print_time();
_srs_config->subscribe(this);
}
virtual ~SrsStageInfo()
{
_srs_config->unsubscribe(this);
}
void update_print_time()
{
switch (stage_id) {
case SRS_STAGE_PLAY_USER: {
pithy_print_time_ms = _srs_config->get_pithy_print_play();
break;
}
case SRS_STAGE_PUBLISH_USER: {
pithy_print_time_ms = _srs_config->get_pithy_print_publish();
break;
}
case SRS_STAGE_FORWARDER: {
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
break;
}
case SRS_STAGE_ENCODER: {
pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
break;
}
case SRS_STAGE_HLS: {
pithy_print_time_ms = _srs_config->get_pithy_print_hls();
break;
}
default: {
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
break;
}
}
}
int stage_id;
int pithy_print_time_ms;
int nb_clients;
SrsStageInfo(int _stage_id)
{
stage_id = _stage_id;
nb_clients = 0;
update_print_time();
_srs_config->subscribe(this);
}
virtual ~SrsStageInfo()
{
_srs_config->unsubscribe(this);
}
void update_print_time()
{
switch (stage_id) {
case SRS_STAGE_PLAY_USER: {
pithy_print_time_ms = _srs_config->get_pithy_print_play();
break;
}
case SRS_STAGE_PUBLISH_USER: {
pithy_print_time_ms = _srs_config->get_pithy_print_publish();
break;
}
case SRS_STAGE_FORWARDER: {
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
break;
}
case SRS_STAGE_ENCODER: {
pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
break;
}
case SRS_STAGE_HLS: {
pithy_print_time_ms = _srs_config->get_pithy_print_hls();
break;
}
default: {
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
break;
}
}
}
public:
virtual int on_reload_pithy_print()
{
update_print_time();
return ERROR_SUCCESS;
}
virtual int on_reload_pithy_print()
{
update_print_time();
return ERROR_SUCCESS;
}
};
static std::map<int, SrsStageInfo*> _srs_stages;
SrsPithyPrint::SrsPithyPrint(int _stage_id)
{
stage_id = _stage_id;
client_id = enter_stage();
printed_age = age = 0;
stage_id = _stage_id;
client_id = enter_stage();
printed_age = age = 0;
}
SrsPithyPrint::~SrsPithyPrint()
{
leave_stage();
leave_stage();
}
int SrsPithyPrint::enter_stage()
{
SrsStageInfo* stage = NULL;
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
if (it == _srs_stages.end()) {
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
} else {
stage = it->second;
}
srs_assert(stage != NULL);
client_id = stage->nb_clients++;
SrsStageInfo* stage = NULL;
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
if (it == _srs_stages.end()) {
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
} else {
stage = it->second;
}
srs_assert(stage != NULL);
client_id = stage->nb_clients++;
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
return client_id;
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
return client_id;
}
void SrsPithyPrint::leave_stage()
{
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
stage->nb_clients--;
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
stage->nb_clients--;
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
}
void SrsPithyPrint::elapse(int64_t time_ms)
{
age += time_ms;
age += time_ms;
}
bool SrsPithyPrint::can_print()
{
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
int64_t alive_age = age - printed_age;
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
bool can_print = alive_age >= can_print_age;
if (can_print) {
printed_age = age;
}
return can_print;
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
int64_t alive_age = age - printed_age;
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
bool can_print = alive_age >= can_print_age;
if (can_print) {
printed_age = age;
}
return can_print;
}
int64_t SrsPithyPrint::get_age()
{
return age;
return age;
}
void SrsPithyPrint::set_age(int64_t _age)
{
age = _age;
age = _age;
}

View file

@ -50,39 +50,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsPithyPrint
{
private:
int client_id;
int stage_id;
int64_t age;
int64_t printed_age;
int client_id;
int stage_id;
int64_t age;
int64_t printed_age;
public:
/**
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
*/
SrsPithyPrint(int _stage_id);
virtual ~SrsPithyPrint();
/**
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
*/
SrsPithyPrint(int _stage_id);
virtual ~SrsPithyPrint();
private:
/**
* enter the specified stage, return the client id.
*/
virtual int enter_stage();
/**
* leave the specified stage, release the client id.
*/
virtual void leave_stage();
/**
* enter the specified stage, return the client id.
*/
virtual int enter_stage();
/**
* leave the specified stage, release the client id.
*/
virtual void leave_stage();
public:
/**
* specified client elapse some time.
*/
virtual void elapse(int64_t time_ms);
/**
* whether current client can print.
*/
virtual bool can_print();
/**
* get the elapsed time in ms.
*/
virtual int64_t get_age();
virtual void set_age(int64_t _age);
/**
* specified client elapse some time.
*/
virtual void elapse(int64_t time_ms);
/**
* whether current client can print.
*/
virtual bool can_print();
/**
* get the elapsed time in ms.
*/
virtual int64_t get_age();
virtual void set_age(int64_t _age);
};
#endif

View file

@ -29,60 +29,60 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
int SrsRefer::check(std::string page_url, SrsConfDirective* refer)
{
int ret = ERROR_SUCCESS;
if (!refer) {
srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
return ret;
}
for (int i = 0; i < (int)refer->args.size(); i++) {
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
srs_verbose("check refer success. page_url=%s, refer=%s",
page_url.c_str(), refer->args.at(i).c_str());
return ret;
}
}
ret = ERROR_RTMP_ACCESS_DENIED;
srs_error("check refer failed. ret=%d", ret);
return ret;
int ret = ERROR_SUCCESS;
if (!refer) {
srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
return ret;
}
for (int i = 0; i < (int)refer->args.size(); i++) {
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
srs_verbose("check refer success. page_url=%s, refer=%s",
page_url.c_str(), refer->args.at(i).c_str());
return ret;
}
}
ret = ERROR_RTMP_ACCESS_DENIED;
srs_error("check refer failed. ret=%d", ret);
return ret;
}
int SrsRefer::check_single_refer(std::string page_url, std::string refer)
{
int ret = ERROR_SUCCESS;
size_t pos = std::string::npos;
std::string domain_name = page_url;
if ((pos = domain_name.find("://")) != std::string::npos) {
domain_name = domain_name.substr(pos + 3);
}
if ((pos = domain_name.find("/")) != std::string::npos) {
domain_name = domain_name.substr(0, pos);
}
if ((pos = domain_name.find(":")) != std::string::npos) {
domain_name = domain_name.substr(0, pos);
}
pos = domain_name.find(refer);
if (pos == std::string::npos) {
ret = ERROR_RTMP_ACCESS_DENIED;
}
// match primary domain.
if (pos != domain_name.length() - refer.length()) {
ret = ERROR_RTMP_ACCESS_DENIED;
}
if (ret != ERROR_SUCCESS) {
srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d",
page_url.c_str(), domain_name.c_str(), refer.c_str(), ret);
}
return ret;
int ret = ERROR_SUCCESS;
size_t pos = std::string::npos;
std::string domain_name = page_url;
if ((pos = domain_name.find("://")) != std::string::npos) {
domain_name = domain_name.substr(pos + 3);
}
if ((pos = domain_name.find("/")) != std::string::npos) {
domain_name = domain_name.substr(0, pos);
}
if ((pos = domain_name.find(":")) != std::string::npos) {
domain_name = domain_name.substr(0, pos);
}
pos = domain_name.find(refer);
if (pos == std::string::npos) {
ret = ERROR_RTMP_ACCESS_DENIED;
}
// match primary domain.
if (pos != domain_name.length() - refer.length()) {
ret = ERROR_RTMP_ACCESS_DENIED;
}
if (ret != ERROR_SUCCESS) {
srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d",
page_url.c_str(), domain_name.c_str(), refer.c_str(), ret);
}
return ret;
}

View file

@ -36,14 +36,14 @@ class SrsConfDirective;
class SrsRefer
{
public:
/**
* to check the refer.
* @param page_url the client page url.
* @param refer the refer in config.
*/
virtual int check(std::string page_url, SrsConfDirective* refer);
/**
* to check the refer.
* @param page_url the client page url.
* @param refer the refer in config.
*/
virtual int check(std::string page_url, SrsConfDirective* refer);
private:
virtual int check_single_refer(std::string page_url, std::string refer);
virtual int check_single_refer(std::string page_url, std::string refer);
};
#endif

View file

@ -37,41 +37,41 @@ ISrsReloadHandler::~ISrsReloadHandler()
int ISrsReloadHandler::on_reload_listen()
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_pithy_print()
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/)
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/)
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/)
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_forward(string /*vhost*/)
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_hls(string /*vhost*/)
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int ISrsReloadHandler::on_reload_transcode(string /*vhost*/)
{
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}

View file

@ -37,17 +37,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsReloadHandler
{
public:
ISrsReloadHandler();
virtual ~ISrsReloadHandler();
ISrsReloadHandler();
virtual ~ISrsReloadHandler();
public:
virtual int on_reload_listen();
virtual int on_reload_pithy_print();
virtual int on_reload_vhost_removed(std::string vhost);
virtual int on_reload_gop_cache(std::string vhost);
virtual int on_reload_queue_length(std::string vhost);
virtual int on_reload_forward(std::string vhost);
virtual int on_reload_hls(std::string vhost);
virtual int on_reload_transcode(std::string vhost);
virtual int on_reload_listen();
virtual int on_reload_pithy_print();
virtual int on_reload_vhost_removed(std::string vhost);
virtual int on_reload_gop_cache(std::string vhost);
virtual int on_reload_queue_length(std::string vhost);
virtual int on_reload_forward(std::string vhost);
virtual int on_reload_hls(std::string vhost);
virtual int on_reload_transcode(std::string vhost);
};
#endif

View file

@ -40,40 +40,40 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
{
fd = -1;
stfd = NULL;
port = 0;
server = _server;
type = _type;
fd = -1;
stfd = NULL;
port = 0;
server = _server;
type = _type;
pthread = new SrsThread(this, 0);
pthread = new SrsThread(this, 0);
}
SrsListener::~SrsListener()
{
srs_close_stfd(stfd);
pthread->stop();
srs_freep(pthread);
// st does not close it sometimes,
// close it manually.
close(fd);
srs_close_stfd(stfd);
pthread->stop();
srs_freep(pthread);
// st does not close it sometimes,
// close it manually.
close(fd);
}
int SrsListener::listen(int _port)
{
int ret = ERROR_SUCCESS;
port = _port;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
int ret = ERROR_SUCCESS;
port = _port;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
ret = ERROR_SOCKET_CREATE;
srs_error("create linux socket error. ret=%d", ret);
return ret;
}
srs_verbose("create linux socket success. fd=%d", fd);
}
srs_verbose("create linux socket success. fd=%d", fd);
int reuse_socket = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
@ -115,19 +115,19 @@ int SrsListener::listen(int _port)
srs_verbose("create st listen thread success.");
srs_trace("server started, listen at port=%d, fd=%d", port, fd);
return ret;
return ret;
}
void SrsListener::on_enter_loop()
{
srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd);
srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd);
}
int SrsListener::cycle()
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
if(client_stfd == NULL){
@ -136,45 +136,45 @@ int SrsListener::cycle()
return ret;
}
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
srs_warn("accept client error. ret=%d", ret);
return ret;
}
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
return ret;
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
srs_warn("accept client error. ret=%d", ret);
return ret;
}
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
return ret;
}
SrsServer::SrsServer()
{
signal_reload = false;
signal_gmc_stop = false;
srs_assert(_srs_config);
_srs_config->subscribe(this);
signal_reload = false;
signal_gmc_stop = false;
srs_assert(_srs_config);
_srs_config->subscribe(this);
}
SrsServer::~SrsServer()
{
_srs_config->unsubscribe(this);
if (true) {
std::vector<SrsConnection*>::iterator it;
for (it = conns.begin(); it != conns.end(); ++it) {
SrsConnection* conn = *it;
srs_freep(conn);
}
conns.clear();
}
close_listeners();
_srs_config->unsubscribe(this);
if (true) {
std::vector<SrsConnection*>::iterator it;
for (it = conns.begin(); it != conns.end(); ++it) {
SrsConnection* conn = *it;
srs_freep(conn);
}
conns.clear();
}
close_listeners();
}
int SrsServer::initialize()
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
// use linux epoll.
if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
@ -190,159 +190,159 @@ int SrsServer::initialize()
return ret;
}
srs_verbose("st_init success");
// set current log id.
_srs_context->generate_id();
srs_info("log set id success");
return ret;
// set current log id.
_srs_context->generate_id();
srs_info("log set id success");
return ret;
}
int SrsServer::listen()
{
int ret = ERROR_SUCCESS;
SrsConfDirective* conf = NULL;
// stream service port.
conf = _srs_config->get_listen();
srs_assert(conf);
close_listeners();
for (int i = 0; i < (int)conf->args.size(); i++) {
SrsListener* listener = new SrsListener(this, SrsListenerStream);
listeners.push_back(listener);
int port = ::atoi(conf->args.at(i).c_str());
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
srs_error("listen at port %d failed. ret=%d", port, ret);
return ret;
}
}
return ret;
int ret = ERROR_SUCCESS;
SrsConfDirective* conf = NULL;
// stream service port.
conf = _srs_config->get_listen();
srs_assert(conf);
close_listeners();
for (int i = 0; i < (int)conf->args.size(); i++) {
SrsListener* listener = new SrsListener(this, SrsListenerStream);
listeners.push_back(listener);
int port = ::atoi(conf->args.at(i).c_str());
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
srs_error("listen at port %d failed. ret=%d", port, ret);
return ret;
}
}
return ret;
}
int SrsServer::cycle()
{
int ret = ERROR_SUCCESS;
// the deamon thread, update the time cache
while (true) {
st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
srs_update_system_time_ms();
int ret = ERROR_SUCCESS;
// the deamon thread, update the time cache
while (true) {
st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
srs_update_system_time_ms();
// for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc
// if user interrupt the program, exit to check mem leak.
// but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump.
#ifdef SRS_GPERF_MC
if (signal_gmc_stop) {
break;
}
if (signal_gmc_stop) {
break;
}
#endif
if (signal_reload) {
signal_reload = false;
srs_info("get signal reload, to reload the config.");
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
srs_error("reload config failed. ret=%d", ret);
return ret;
}
srs_trace("reload config success.");
}
}
return ret;
if (signal_reload) {
signal_reload = false;
srs_info("get signal reload, to reload the config.");
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
srs_error("reload config failed. ret=%d", ret);
return ret;
}
srs_trace("reload config success.");
}
}
return ret;
}
void SrsServer::remove(SrsConnection* conn)
{
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
if (it != conns.end()) {
conns.erase(it);
}
srs_info("conn removed. conns=%d", (int)conns.size());
// all connections are created by server,
// so we free it here.
srs_freep(conn);
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
if (it != conns.end()) {
conns.erase(it);
}
srs_info("conn removed. conns=%d", (int)conns.size());
// all connections are created by server,
// so we free it here.
srs_freep(conn);
}
void SrsServer::on_signal(int signo)
{
if (signo == SIGNAL_RELOAD) {
signal_reload = true;
return;
}
if (signo == SIGINT) {
if (signo == SIGNAL_RELOAD) {
signal_reload = true;
return;
}
if (signo == SIGINT) {
#ifdef SRS_GPERF_MC
srs_trace("gmc is on, main cycle will terminate normally.");
signal_gmc_stop = true;
srs_trace("gmc is on, main cycle will terminate normally.");
signal_gmc_stop = true;
#else
srs_trace("user terminate program");
exit(0);
srs_trace("user terminate program");
exit(0);
#endif
return;
}
return;
}
// TODO: handle the SIGINT, SIGTERM.
// TODO: handle the SIGINT, SIGTERM.
}
void SrsServer::close_listeners()
{
std::vector<SrsListener*>::iterator it;
for (it = listeners.begin(); it != listeners.end(); ++it) {
SrsListener* listener = *it;
srs_freep(listener);
}
listeners.clear();
std::vector<SrsListener*>::iterator it;
for (it = listeners.begin(); it != listeners.end(); ++it) {
SrsListener* listener = *it;
srs_freep(listener);
}
listeners.clear();
}
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
{
int ret = ERROR_SUCCESS;
int max_connections = _srs_config->get_max_connections();
if ((int)conns.size() >= max_connections) {
int fd = st_netfd_fileno(client_stfd);
srs_error("exceed the max connections, drop client: "
"clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
srs_close_stfd(client_stfd);
return ret;
}
SrsConnection* conn = NULL;
if (type == SrsListenerStream) {
conn = new SrsClient(this, client_stfd);
} else {
// handler others
}
srs_assert(conn);
// directly enqueue, the cycle thread will remove the client.
conns.push_back(conn);
srs_verbose("add conn from port %d to vector. conns=%d", port, (int)conns.size());
// cycle will start process thread and when finished remove the client.
if ((ret = conn->start()) != ERROR_SUCCESS) {
return ret;
}
srs_verbose("conn start finished. ret=%d", ret);
int ret = ERROR_SUCCESS;
return ret;
int max_connections = _srs_config->get_max_connections();
if ((int)conns.size() >= max_connections) {
int fd = st_netfd_fileno(client_stfd);
srs_error("exceed the max connections, drop client: "
"clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
srs_close_stfd(client_stfd);
return ret;
}
SrsConnection* conn = NULL;
if (type == SrsListenerStream) {
conn = new SrsClient(this, client_stfd);
} else {
// handler others
}
srs_assert(conn);
// directly enqueue, the cycle thread will remove the client.
conns.push_back(conn);
srs_verbose("add conn from port %d to vector. conns=%d", port, (int)conns.size());
// cycle will start process thread and when finished remove the client.
if ((ret = conn->start()) != ERROR_SUCCESS) {
return ret;
}
srs_verbose("conn start finished. ret=%d", ret);
return ret;
}
int SrsServer::on_reload_listen()
{
return listen();
return listen();
}

View file

@ -41,53 +41,53 @@ class SrsConnection;
enum SrsListenerType
{
SrsListenerStream = 0,
SrsListenerApi
SrsListenerStream = 0,
SrsListenerApi
};
class SrsListener : public ISrsThreadHandler
{
public:
SrsListenerType type;
SrsListenerType type;
private:
int fd;
st_netfd_t stfd;
int port;
SrsServer* server;
SrsThread* pthread;
int fd;
st_netfd_t stfd;
int port;
SrsServer* server;
SrsThread* pthread;
public:
SrsListener(SrsServer* _server, SrsListenerType _type);
virtual ~SrsListener();
SrsListener(SrsServer* _server, SrsListenerType _type);
virtual ~SrsListener();
public:
virtual int listen(int port);
virtual int listen(int port);
// interface ISrsThreadHandler.
public:
virtual void on_enter_loop();
virtual int cycle();
virtual void on_enter_loop();
virtual int cycle();
};
class SrsServer : public ISrsReloadHandler
{
friend class SrsListener;
friend class SrsListener;
private:
std::vector<SrsConnection*> conns;
std::vector<SrsListener*> listeners;
bool signal_reload;
bool signal_gmc_stop;
std::vector<SrsConnection*> conns;
std::vector<SrsListener*> listeners;
bool signal_reload;
bool signal_gmc_stop;
public:
SrsServer();
virtual ~SrsServer();
SrsServer();
virtual ~SrsServer();
public:
virtual int initialize();
virtual int listen();
virtual int cycle();
virtual void remove(SrsConnection* conn);
virtual void on_signal(int signo);
virtual int initialize();
virtual int listen();
virtual int cycle();
virtual void remove(SrsConnection* conn);
virtual void on_signal(int signo);
private:
virtual void close_listeners();
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
virtual void close_listeners();
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
public:
virtual int on_reload_listen();
virtual int on_reload_listen();
};
#endif

View file

@ -28,9 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsSocket::SrsSocket(st_netfd_t client_stfd)
{
stfd = client_stfd;
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
recv_bytes = send_bytes = 0;
start_time_ms = srs_get_system_time_ms();
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
recv_bytes = send_bytes = 0;
start_time_ms = srs_get_system_time_ms();
}
SrsSocket::~SrsSocket()
@ -39,59 +39,59 @@ SrsSocket::~SrsSocket()
bool SrsSocket::is_never_timeout(int64_t timeout_us)
{
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
}
void SrsSocket::set_recv_timeout(int64_t timeout_us)
{
recv_timeout = timeout_us;
recv_timeout = timeout_us;
}
int64_t SrsSocket::get_recv_timeout()
{
return recv_timeout;
return recv_timeout;
}
void SrsSocket::set_send_timeout(int64_t timeout_us)
{
send_timeout = timeout_us;
send_timeout = timeout_us;
}
int64_t SrsSocket::get_send_timeout()
{
return send_timeout;
return send_timeout;
}
int64_t SrsSocket::get_recv_bytes()
{
return recv_bytes;
return recv_bytes;
}
int64_t SrsSocket::get_send_bytes()
{
return send_bytes;
return send_bytes;
}
int SrsSocket::get_recv_kbps()
{
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return recv_bytes * 8 / diff_ms;
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return recv_bytes * 8 / diff_ms;
}
int SrsSocket::get_send_kbps()
{
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return send_bytes * 8 / diff_ms;
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return send_bytes * 8 / diff_ms;
}
int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
@ -103,10 +103,10 @@ int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
// On success a non-negative integer indicating the number of bytes actually read is returned
// (a value of 0 means the network connection is closed or end of file is reached).
if (*nread <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (*nread == 0) {
errno = ECONNRESET;
}
@ -128,10 +128,10 @@ int SrsSocket::read_fully(const void* buf, size_t size, ssize_t* nread)
// On success a non-negative integer indicating the number of bytes actually read is returned
// (a value less than nbyte means the network connection is closed or end of file is reached)
if (*nread != (ssize_t)size) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (*nread >= 0) {
errno = ECONNRESET;
}
@ -151,10 +151,10 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite)
*nwrite = st_write(stfd, (void*)buf, size, send_timeout);
if (*nwrite <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
return ERROR_SOCKET_WRITE;
}
@ -170,10 +170,10 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
*nwrite = st_writev(stfd, iov, iov_size, send_timeout);
if (*nwrite <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
return ERROR_SOCKET_WRITE;
}

View file

@ -40,25 +40,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsSocket : public ISrsProtocolReaderWriter
{
private:
int64_t recv_timeout;
int64_t send_timeout;
int64_t recv_bytes;
int64_t send_bytes;
int64_t start_time_ms;
int64_t recv_timeout;
int64_t send_timeout;
int64_t recv_bytes;
int64_t send_bytes;
int64_t start_time_ms;
st_netfd_t stfd;
public:
SrsSocket(st_netfd_t client_stfd);
virtual ~SrsSocket();
public:
virtual bool is_never_timeout(int64_t timeout_us);
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout();
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual bool is_never_timeout(int64_t timeout_us);
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout();
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
public:
virtual int read(const void* buf, size_t size, ssize_t* nread);
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);

File diff suppressed because it is too large Load diff

View file

@ -57,20 +57,20 @@ class SrsEncoder;
class SrsRtmpJitter
{
private:
int64_t last_pkt_time;
int64_t last_pkt_correct_time;
int64_t last_pkt_time;
int64_t last_pkt_correct_time;
public:
SrsRtmpJitter();
virtual ~SrsRtmpJitter();
SrsRtmpJitter();
virtual ~SrsRtmpJitter();
public:
/**
* detect the time jitter and correct it.
*/
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
/**
* get current client time, the last packet time.
*/
virtual int get_time();
/**
* detect the time jitter and correct it.
*/
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
/**
* get current client time, the last packet time.
*/
virtual int get_time();
};
/**
@ -80,39 +80,39 @@ public:
class SrsMessageQueue
{
private:
int64_t av_start_time;
int64_t av_end_time;
int queue_size_ms;
std::vector<SrsSharedPtrMessage*> msgs;
int64_t av_start_time;
int64_t av_end_time;
int queue_size_ms;
std::vector<SrsSharedPtrMessage*> msgs;
public:
SrsMessageQueue();
virtual ~SrsMessageQueue();
SrsMessageQueue();
virtual ~SrsMessageQueue();
public:
/**
* set the queue size
* @param queue_size the queue size in seconds.
*/
virtual void set_queue_size(double queue_size);
/**
* set the queue size
* @param queue_size the queue size in seconds.
*/
virtual void set_queue_size(double queue_size);
public:
/**
* enqueue the message, the timestamp always monotonically.
* @param msg, the msg to enqueue, user never free it whatever the return code.
*/
virtual int enqueue(SrsSharedPtrMessage* msg);
/**
* get packets in consumer queue.
* @pmsgs SrsMessages*[], output the prt array.
* @count the count in array.
* @max_count the max count to dequeue, 0 to dequeue all.
*/
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
/**
* enqueue the message, the timestamp always monotonically.
* @param msg, the msg to enqueue, user never free it whatever the return code.
*/
virtual int enqueue(SrsSharedPtrMessage* msg);
/**
* get packets in consumer queue.
* @pmsgs SrsMessages*[], output the prt array.
* @count the count in array.
* @max_count the max count to dequeue, 0 to dequeue all.
*/
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
private:
/**
* remove a gop from the front.
* if no iframe found, clear it.
*/
virtual void shrink();
virtual void clear();
/**
* remove a gop from the front.
* if no iframe found, clear it.
*/
virtual void shrink();
virtual void clear();
};
/**
@ -121,39 +121,39 @@ private:
class SrsConsumer
{
private:
SrsRtmpJitter* jitter;
SrsSource* source;
SrsMessageQueue* queue;
bool paused;
SrsRtmpJitter* jitter;
SrsSource* source;
SrsMessageQueue* queue;
bool paused;
public:
SrsConsumer(SrsSource* _source);
virtual ~SrsConsumer();
SrsConsumer(SrsSource* _source);
virtual ~SrsConsumer();
public:
virtual void set_queue_size(double queue_size);
virtual void set_queue_size(double queue_size);
public:
/**
* get current client time, the last packet time.
*/
virtual int get_time();
/**
* enqueue an shared ptr message.
* @param tba timebase of audio.
* used to calc the audio time delta if time-jitter detected.
* @param tbv timebase of video.
* used to calc the video time delta if time-jitter detected.
*/
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
/**
* get packets in consumer queue.
* @pmsgs SrsMessages*[], output the prt array.
* @count the count in array.
* @max_count the max count to dequeue, 0 to dequeue all.
*/
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
/**
* when client send the pause message.
*/
virtual int on_play_client_pause(bool is_pause);
/**
* get current client time, the last packet time.
*/
virtual int get_time();
/**
* enqueue an shared ptr message.
* @param tba timebase of audio.
* used to calc the audio time delta if time-jitter detected.
* @param tbv timebase of video.
* used to calc the video time delta if time-jitter detected.
*/
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
/**
* get packets in consumer queue.
* @pmsgs SrsMessages*[], output the prt array.
* @count the count in array.
* @max_count the max count to dequeue, 0 to dequeue all.
*/
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
/**
* when client send the pause message.
*/
virtual int on_play_client_pause(bool is_pause);
};
/**
@ -164,33 +164,33 @@ public:
class SrsGopCache
{
private:
/**
* if disabled the gop cache,
* the client will wait for the next keyframe for h264,
* and will be black-screen.
*/
bool enable_gop_cache;
/**
* the video frame count, avoid cache for pure audio stream.
*/
int cached_video_count;
/**
* cached gop.
*/
std::vector<SrsSharedPtrMessage*> gop_cache;
/**
* if disabled the gop cache,
* the client will wait for the next keyframe for h264,
* and will be black-screen.
*/
bool enable_gop_cache;
/**
* the video frame count, avoid cache for pure audio stream.
*/
int cached_video_count;
/**
* cached gop.
*/
std::vector<SrsSharedPtrMessage*> gop_cache;
public:
SrsGopCache();
virtual ~SrsGopCache();
SrsGopCache();
virtual ~SrsGopCache();
public:
virtual void set(bool enabled);
/**
* only for h264 codec
* 1. cache the gop when got h264 video packet.
* 2. clear gop when got keyframe.
*/
virtual int cache(SrsSharedPtrMessage* msg);
virtual void clear();
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
virtual void set(bool enabled);
/**
* only for h264 codec
* 1. cache the gop when got h264 video packet.
* 2. clear gop when got keyframe.
*/
virtual int cache(SrsSharedPtrMessage* msg);
virtual void clear();
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
};
/**
@ -199,89 +199,89 @@ public:
class SrsSource : public ISrsReloadHandler
{
private:
static std::map<std::string, SrsSource*> pool;
static std::map<std::string, SrsSource*> pool;
public:
/**
* find stream by vhost/app/stream.
* @param req the client request.
* @return the matched source, never be NULL.
* @remark stream_url should without port and schema.
*/
static SrsSource* find(SrsRequest* req);
/**
* find stream by vhost/app/stream.
* @param req the client request.
* @return the matched source, never be NULL.
* @remark stream_url should without port and schema.
*/
static SrsSource* find(SrsRequest* req);
private:
// deep copy of client request.
SrsRequest* req;
// to delivery stream to clients.
std::vector<SrsConsumer*> consumers;
// hls handler.
// deep copy of client request.
SrsRequest* req;
// to delivery stream to clients.
std::vector<SrsConsumer*> consumers;
// hls handler.
#ifdef SRS_HLS
SrsHls* hls;
SrsHls* hls;
#endif
// transcoding handler.
// transcoding handler.
#ifdef SRS_FFMPEG
SrsEncoder* encoder;
SrsEncoder* encoder;
#endif
// gop cache for client fast startup.
SrsGopCache* gop_cache;
// to forward stream to other servers
std::vector<SrsForwarder*> forwarders;
// gop cache for client fast startup.
SrsGopCache* gop_cache;
// to forward stream to other servers
std::vector<SrsForwarder*> forwarders;
private:
/**
* the sample rate of audio in metadata.
*/
int sample_rate;
/**
* the video frame rate in metadata.
*/
int frame_rate;
/**
* can publish, true when is not streaming
*/
bool _can_publish;
/**
* the sample rate of audio in metadata.
*/
int sample_rate;
/**
* the video frame rate in metadata.
*/
int frame_rate;
/**
* can publish, true when is not streaming
*/
bool _can_publish;
private:
SrsSharedPtrMessage* cache_metadata;
// the cached video sequence header.
SrsSharedPtrMessage* cache_sh_video;
// the cached audio sequence header.
SrsSharedPtrMessage* cache_sh_audio;
SrsSharedPtrMessage* cache_metadata;
// the cached video sequence header.
SrsSharedPtrMessage* cache_sh_video;
// the cached audio sequence header.
SrsSharedPtrMessage* cache_sh_audio;
public:
/**
* @param _req the client request object,
* this object will deep copy it for reload.
*/
SrsSource(SrsRequest* _req);
virtual ~SrsSource();
/**
* @param _req the client request object,
* this object will deep copy it for reload.
*/
SrsSource(SrsRequest* _req);
virtual ~SrsSource();
// interface ISrsReloadHandler
public:
virtual int on_reload_gop_cache(std::string vhost);
virtual int on_reload_queue_length(std::string vhost);
virtual int on_reload_forward(std::string vhost);
virtual int on_reload_hls(std::string vhost);
virtual int on_reload_transcode(std::string vhost);
virtual int on_reload_gop_cache(std::string vhost);
virtual int on_reload_queue_length(std::string vhost);
virtual int on_reload_forward(std::string vhost);
virtual int on_reload_hls(std::string vhost);
virtual int on_reload_transcode(std::string vhost);
public:
// for the SrsForwarder to callback to request the sequence headers.
virtual int on_forwarder_start(SrsForwarder* forwarder);
// for the SrsHls to callback to request the sequence headers.
virtual int on_hls_start();
// for the SrsForwarder to callback to request the sequence headers.
virtual int on_forwarder_start(SrsForwarder* forwarder);
// for the SrsHls to callback to request the sequence headers.
virtual int on_hls_start();
public:
virtual bool can_publish();
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
virtual int on_audio(SrsCommonMessage* audio);
virtual int on_video(SrsCommonMessage* video);
/**
* publish stream event notify.
* @param _req the request from client, the source will deep copy it,
* for when reload the request of client maybe invalid.
*/
virtual int on_publish(SrsRequest* _req);
virtual void on_unpublish();
virtual bool can_publish();
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
virtual int on_audio(SrsCommonMessage* audio);
virtual int on_video(SrsCommonMessage* video);
/**
* publish stream event notify.
* @param _req the request from client, the source will deep copy it,
* for when reload the request of client maybe invalid.
*/
virtual int on_publish(SrsRequest* _req);
virtual void on_unpublish();
public:
virtual int create_consumer(SrsConsumer*& consumer);
virtual void on_consumer_destroy(SrsConsumer* consumer);
virtual void set_cache(bool enabled);
virtual int create_consumer(SrsConsumer*& consumer);
virtual void on_consumer_destroy(SrsConsumer* consumer);
virtual void set_cache(bool enabled);
private:
virtual int create_forwarders();
virtual void destroy_forwarders();
virtual int create_forwarders();
virtual void destroy_forwarders();
};
#endif

View file

@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
void srs_close_stfd(st_netfd_t& stfd)
{
if (stfd) {
int fd = st_netfd_fileno(stfd);
st_netfd_close(stfd);
stfd = NULL;
// st does not close it sometimes,
// close it manually.
close(fd);
}
if (stfd) {
int fd = st_netfd_fileno(stfd);
st_netfd_close(stfd);
stfd = NULL;
// st does not close it sometimes,
// close it manually.
close(fd);
}
}

View file

@ -40,14 +40,14 @@ void ISrsThreadHandler::on_enter_loop()
int ISrsThreadHandler::on_before_cycle()
{
int ret = ERROR_SUCCESS;
return ret;
int ret = ERROR_SUCCESS;
return ret;
}
int ISrsThreadHandler::on_end_cycle()
{
int ret = ERROR_SUCCESS;
return ret;
int ret = ERROR_SUCCESS;
return ret;
}
void ISrsThreadHandler::on_leave_loop()
@ -56,29 +56,29 @@ void ISrsThreadHandler::on_leave_loop()
SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us)
{
handler = thread_handler;
cycle_interval_us = interval_us;
tid = NULL;
loop = false;
handler = thread_handler;
cycle_interval_us = interval_us;
tid = NULL;
loop = false;
}
SrsThread::~SrsThread()
{
stop();
stop();
}
int SrsThread::start()
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
if(tid) {
srs_info("thread already running.");
return ret;
}
if((tid = st_thread_create(thread_fun, this, 1, 0)) == NULL){
ret = ERROR_ST_CREATE_CYCLE_THREAD;
ret = ERROR_ST_CREATE_CYCLE_THREAD;
srs_error("st_thread_create failed. ret=%d", ret);
return ret;
}
@ -88,74 +88,74 @@ int SrsThread::start()
void SrsThread::stop()
{
if (tid) {
loop = false;
// the interrupt will cause the socket to read/write error,
// which will terminate the cycle thread.
st_thread_interrupt(tid);
// wait the thread to exit.
st_thread_join(tid, NULL);
tid = NULL;
}
if (tid) {
loop = false;
// the interrupt will cause the socket to read/write error,
// which will terminate the cycle thread.
st_thread_interrupt(tid);
// wait the thread to exit.
st_thread_join(tid, NULL);
tid = NULL;
}
}
bool SrsThread::can_loop()
{
return loop;
return loop;
}
void SrsThread::thread_cycle()
{
int ret = ERROR_SUCCESS;
srs_assert(handler);
_srs_context->generate_id();
srs_trace("thread cycle start");
int ret = ERROR_SUCCESS;
srs_assert(handler);
_srs_context->generate_id();
srs_trace("thread cycle start");
handler->on_end_cycle();
loop = true;
while (loop) {
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
goto failed;
}
srs_info("thread on before cycle success");
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
goto failed;
}
srs_info("thread cycle success");
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
goto failed;
}
srs_info("thread on end cycle success");
handler->on_end_cycle();
loop = true;
while (loop) {
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
goto failed;
}
srs_info("thread on before cycle success");
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
goto failed;
}
srs_info("thread cycle success");
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
goto failed;
}
srs_info("thread on end cycle success");
failed:
if (!loop) {
break;
}
st_usleep(cycle_interval_us);
}
handler->on_leave_loop();
srs_trace("thread cycle finished");
if (!loop) {
break;
}
st_usleep(cycle_interval_us);
}
handler->on_leave_loop();
srs_trace("thread cycle finished");
}
void* SrsThread::thread_fun(void* arg)
{
SrsThread* obj = (SrsThread*)arg;
srs_assert(obj);
obj->thread_cycle();
return NULL;
SrsThread* obj = (SrsThread*)arg;
srs_assert(obj);
obj->thread_cycle();
return NULL;
}

View file

@ -34,14 +34,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/**
* the handler for the thread, callback interface.
* the thread model defines as:
* handler->on_enter_loop()
* while loop:
* handler->on_before_cycle()
* handler->cycle()
* handler->on_end_cycle()
* if !loop then break for user stop thread.
* sleep(CycleIntervalMilliseconds)
* handler->on_leave_loop()
* handler->on_enter_loop()
* while loop:
* handler->on_before_cycle()
* handler->cycle()
* handler->on_end_cycle()
* if !loop then break for user stop thread.
* sleep(CycleIntervalMilliseconds)
* handler->on_leave_loop()
* when stop, the thread will interrupt the st_thread,
* which will cause the socket to return error and
* terminate the cycle thread.
@ -49,31 +49,31 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* when thread interrupt, the socket maybe not got EINT,
* espectially on st_usleep(), so the cycle must check the loop,
* when handler->cycle() has loop itself, for example:
* handler->cycle() is:
* while (true):
* st_usleep(0);
* if (read_from_socket(skt) < 0) break;
* handler->cycle() is:
* while (true):
* st_usleep(0);
* if (read_from_socket(skt) < 0) break;
* if thread stop when read_from_socket, it's ok, the loop will break,
* but when thread stop interrupt the s_usleep(0), then the loop is
* death loop.
* in a word, the handler->cycle() must:
* handler->cycle() is:
* while (pthread->can_loop()):
* st_usleep(0);
* if (read_from_socket(skt) < 0) break;
* handler->cycle() is:
* while (pthread->can_loop()):
* st_usleep(0);
* if (read_from_socket(skt) < 0) break;
* check the loop, then it works.
*/
class ISrsThreadHandler
{
public:
ISrsThreadHandler();
virtual ~ISrsThreadHandler();
ISrsThreadHandler();
virtual ~ISrsThreadHandler();
public:
virtual void on_enter_loop();
virtual int on_before_cycle();
virtual int cycle() = 0;
virtual int on_end_cycle();
virtual void on_leave_loop();
virtual void on_enter_loop();
virtual int on_before_cycle();
virtual int cycle() = 0;
virtual int on_end_cycle();
virtual void on_leave_loop();
};
/**
@ -83,41 +83,41 @@ public:
class SrsThread
{
private:
st_thread_t tid;
bool loop;
st_thread_t tid;
bool loop;
private:
ISrsThreadHandler* handler;
int64_t cycle_interval_us;
ISrsThreadHandler* handler;
int64_t cycle_interval_us;
public:
/**
* initialize the thread.
* @param thread_handler, the cycle handler for the thread.
* @param interval_us, the sleep interval when cycle finished.
*/
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
virtual ~SrsThread();
/**
* initialize the thread.
* @param thread_handler, the cycle handler for the thread.
* @param interval_us, the sleep interval when cycle finished.
*/
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
virtual ~SrsThread();
public:
/**
* start the thread, invoke the cycle of handler util
* user stop the thread.
* @remark ignore any error of cycle of handler.
* @remark user can start multiple times, ignore if already started.
*/
virtual int start();
/**
* stop the thread, wait for the thread to terminate.
* @remark user can stop multiple times, ignore if already stopped.
*/
virtual void stop();
/**
* whether the thread should loop,
* used for handler->cycle() which has a loop method,
* to check this method, break if false.
*/
virtual bool can_loop();
/**
* start the thread, invoke the cycle of handler util
* user stop the thread.
* @remark ignore any error of cycle of handler.
* @remark user can start multiple times, ignore if already started.
*/
virtual int start();
/**
* stop the thread, wait for the thread to terminate.
* @remark user can stop multiple times, ignore if already stopped.
*/
virtual void stop();
/**
* whether the thread should loop,
* used for handler->cycle() which has a loop method,
* to check this method, break if false.
*/
virtual bool can_loop();
private:
virtual void thread_cycle();
static void* thread_fun(void* arg);
virtual void thread_cycle();
static void* thread_fun(void* arg);
};
#endif

View file

@ -32,7 +32,7 @@ static int64_t _srs_system_time_us_cache = 0;
int64_t srs_get_system_time_ms()
{
return _srs_system_time_us_cache / 1000;
return _srs_system_time_us_cache / 1000;
}
void srs_update_system_time_ms()
@ -49,19 +49,19 @@ void srs_update_system_time_ms()
std::string srs_replace(std::string str, std::string old_str, std::string new_str)
{
std::string ret = str;
if (old_str == new_str) {
return ret;
}
size_t pos = 0;
while ((pos = ret.find(old_str, pos)) != std::string::npos) {
ret = ret.replace(pos, old_str.length(), new_str);
pos += new_str.length();
}
return ret;
std::string ret = str;
if (old_str == new_str) {
return ret;
}
size_t pos = 0;
while ((pos = ret.find(old_str, pos)) != std::string::npos) {
ret = ret.replace(pos, old_str.length(), new_str);
pos += new_str.length();
}
return ret;
}
std::string srs_dns_resolve(std::string host)

View file

@ -69,18 +69,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// free the p and set to NULL.
// p must be a T*.
#define srs_freep(p) \
if (p) { \
delete p; \
p = NULL; \
} \
(void)0
if (p) { \
delete p; \
p = NULL; \
} \
(void)0
// free the p which represents a array
#define srs_freepa(p) \
if (p) { \
delete[] p; \
p = NULL; \
} \
(void)0
if (p) { \
delete[] p; \
p = NULL; \
} \
(void)0
// compare
#define srs_min(a, b) (((a) < (b))? (a) : (b))

View file

@ -34,7 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* auto free the instance in the current scope.
*/
#define SrsAutoFree(className, instance, is_array) \
__SrsAutoFree<className> _auto_free_##instance(&instance, is_array)
__SrsAutoFree<className> _auto_free_##instance(&instance, is_array)
template<class T>
class __SrsAutoFree

View file

@ -46,46 +46,46 @@ SrsBuffer::~SrsBuffer()
int SrsBuffer::size()
{
return (int)data.size();
return (int)data.size();
}
char* SrsBuffer::bytes()
{
return &data.at(0);
return &data.at(0);
}
void SrsBuffer::erase(int size)
{
data.erase(data.begin(), data.begin() + size);
data.erase(data.begin(), data.begin() + size);
}
void SrsBuffer::append(char* bytes, int size)
{
data.insert(data.end(), bytes, bytes + size);
data.insert(data.end(), bytes, bytes + size);
}
int SrsBuffer::ensure_buffer_bytes(ISrsBufferReader* skt, int required_size)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
if (required_size < 0) {
ret = ERROR_SYSTEM_SIZE_NEGATIVE;
srs_error("size is negative. size=%d, ret=%d", required_size, ret);
return ret;
}
if (required_size < 0) {
ret = ERROR_SYSTEM_SIZE_NEGATIVE;
srs_error("size is negative. size=%d, ret=%d", required_size, ret);
return ret;
}
while (size() < required_size) {
char buffer[SOCKET_READ_SIZE];
ssize_t nread;
if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) {
return ret;
}
srs_assert((int)nread > 0);
append(buffer, (int)nread);
}
return ret;
while (size() < required_size) {
char buffer[SOCKET_READ_SIZE];
ssize_t nread;
if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) {
return ret;
}
srs_assert((int)nread > 0);
append(buffer, (int)nread);
}
return ret;
}

View file

@ -38,8 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsBufferReader
{
public:
ISrsBufferReader();
virtual ~ISrsBufferReader();
ISrsBufferReader();
virtual ~ISrsBufferReader();
// for protocol/amf0/msg-codec
public:
virtual int read(const void* buf, size_t size, ssize_t* nread) = 0;
@ -53,18 +53,18 @@ public:
class SrsBuffer
{
private:
std::vector<char> data;
std::vector<char> data;
public:
SrsBuffer();
virtual ~SrsBuffer();
SrsBuffer();
virtual ~SrsBuffer();
public:
virtual int size();
virtual char* bytes();
virtual void erase(int size);
virtual int size();
virtual char* bytes();
virtual void erase(int size);
private:
virtual void append(char* bytes, int size);
virtual void append(char* bytes, int size);
public:
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
};
#endif

View file

@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bool srs_is_system_control_error(int error_code)
{
return error_code == ERROR_CONTROL_RTMP_CLOSE
|| error_code == ERROR_CONTROL_REPUBLISH;
return error_code == ERROR_CONTROL_RTMP_CLOSE
|| error_code == ERROR_CONTROL_REPUBLISH;
}
bool srs_is_client_gracefully_close(int error_code)
{
return error_code == ERROR_SOCKET_READ
|| error_code == ERROR_SOCKET_READ_FULLY
|| error_code == ERROR_SOCKET_WRITE;
return error_code == ERROR_SOCKET_READ
|| error_code == ERROR_SOCKET_READ_FULLY
|| error_code == ERROR_SOCKET_WRITE;
}

View file

@ -30,133 +30,133 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp>
#define ERROR_SUCCESS 0
#define ERROR_SUCCESS 0
#define ERROR_ST_SET_EPOLL 100
#define ERROR_ST_INITIALIZE 101
#define ERROR_ST_OPEN_SOCKET 102
#define ERROR_ST_CREATE_LISTEN_THREAD 103
#define ERROR_ST_CREATE_CYCLE_THREAD 104
#define ERROR_ST_CONNECT 105
#define ERROR_ST_SET_EPOLL 100
#define ERROR_ST_INITIALIZE 101
#define ERROR_ST_OPEN_SOCKET 102
#define ERROR_ST_CREATE_LISTEN_THREAD 103
#define ERROR_ST_CREATE_CYCLE_THREAD 104
#define ERROR_ST_CONNECT 105
#define ERROR_SOCKET_CREATE 200
#define ERROR_SOCKET_SETREUSE 201
#define ERROR_SOCKET_BIND 202
#define ERROR_SOCKET_LISTEN 203
#define ERROR_SOCKET_CLOSED 204
#define ERROR_SOCKET_GET_PEER_NAME 205
#define ERROR_SOCKET_GET_PEER_IP 206
#define ERROR_SOCKET_READ 207
#define ERROR_SOCKET_READ_FULLY 208
#define ERROR_SOCKET_WRITE 209
#define ERROR_SOCKET_WAIT 210
#define ERROR_SOCKET_TIMEOUT 211
#define ERROR_SOCKET_CREATE 200
#define ERROR_SOCKET_SETREUSE 201
#define ERROR_SOCKET_BIND 202
#define ERROR_SOCKET_LISTEN 203
#define ERROR_SOCKET_CLOSED 204
#define ERROR_SOCKET_GET_PEER_NAME 205
#define ERROR_SOCKET_GET_PEER_IP 206
#define ERROR_SOCKET_READ 207
#define ERROR_SOCKET_READ_FULLY 208
#define ERROR_SOCKET_WRITE 209
#define ERROR_SOCKET_WAIT 210
#define ERROR_SOCKET_TIMEOUT 211
#define ERROR_SOCKET_GET_LOCAL_IP 212
#define ERROR_RTMP_PLAIN_REQUIRED 300
#define ERROR_RTMP_CHUNK_START 301
#define ERROR_RTMP_MSG_INVLIAD_SIZE 302
#define ERROR_RTMP_AMF0_DECODE 303
#define ERROR_RTMP_AMF0_INVALID 304
#define ERROR_RTMP_REQ_CONNECT 305
#define ERROR_RTMP_REQ_TCURL 306
#define ERROR_RTMP_MESSAGE_DECODE 307
#define ERROR_RTMP_MESSAGE_ENCODE 308
#define ERROR_RTMP_AMF0_ENCODE 309
#define ERROR_RTMP_CHUNK_SIZE 310
#define ERROR_RTMP_TRY_SIMPLE_HS 311
#define ERROR_RTMP_CH_SCHEMA 312
#define ERROR_RTMP_PACKET_SIZE 313
#define ERROR_RTMP_VHOST_NOT_FOUND 314
#define ERROR_RTMP_ACCESS_DENIED 315
#define ERROR_RTMP_HANDSHAKE 316
#define ERROR_RTMP_NO_REQUEST 317
#define ERROR_RTMP_PLAIN_REQUIRED 300
#define ERROR_RTMP_CHUNK_START 301
#define ERROR_RTMP_MSG_INVLIAD_SIZE 302
#define ERROR_RTMP_AMF0_DECODE 303
#define ERROR_RTMP_AMF0_INVALID 304
#define ERROR_RTMP_REQ_CONNECT 305
#define ERROR_RTMP_REQ_TCURL 306
#define ERROR_RTMP_MESSAGE_DECODE 307
#define ERROR_RTMP_MESSAGE_ENCODE 308
#define ERROR_RTMP_AMF0_ENCODE 309
#define ERROR_RTMP_CHUNK_SIZE 310
#define ERROR_RTMP_TRY_SIMPLE_HS 311
#define ERROR_RTMP_CH_SCHEMA 312
#define ERROR_RTMP_PACKET_SIZE 313
#define ERROR_RTMP_VHOST_NOT_FOUND 314
#define ERROR_RTMP_ACCESS_DENIED 315
#define ERROR_RTMP_HANDSHAKE 316
#define ERROR_RTMP_NO_REQUEST 317
// if user use complex handshake, but without ssl,
// 1. srs is ok, ignore and turn to simple handshake.
// 2. srs-librtmp return error, to terminate the program.
#define ERROR_RTMP_HS_SSL_REQUIRE 318
#define ERROR_RTMP_HS_SSL_REQUIRE 318
#define ERROR_SYSTEM_STREAM_INIT 400
#define ERROR_SYSTEM_PACKET_INVALID 401
#define ERROR_SYSTEM_CLIENT_INVALID 402
#define ERROR_SYSTEM_ASSERT_FAILED 403
#define ERROR_SYSTEM_SIZE_NEGATIVE 404
#define ERROR_SYSTEM_CONFIG_INVALID 405
#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406
#define ERROR_SYSTEM_CONFIG_BLOCK_START 407
#define ERROR_SYSTEM_CONFIG_BLOCK_END 408
#define ERROR_SYSTEM_CONFIG_EOF 409
#define ERROR_SYSTEM_STREAM_BUSY 410
#define ERROR_SYSTEM_IP_INVALID 411
#define ERROR_SYSTEM_FORWARD_LOOP 412
#define ERROR_SYSTEM_WAITPID 413
#define ERROR_SYSTEM_BANDWIDTH_KEY 414
#define ERROR_SYSTEM_BANDWIDTH_DENIED 415
#define ERROR_SYSTEM_STREAM_INIT 400
#define ERROR_SYSTEM_PACKET_INVALID 401
#define ERROR_SYSTEM_CLIENT_INVALID 402
#define ERROR_SYSTEM_ASSERT_FAILED 403
#define ERROR_SYSTEM_SIZE_NEGATIVE 404
#define ERROR_SYSTEM_CONFIG_INVALID 405
#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406
#define ERROR_SYSTEM_CONFIG_BLOCK_START 407
#define ERROR_SYSTEM_CONFIG_BLOCK_END 408
#define ERROR_SYSTEM_CONFIG_EOF 409
#define ERROR_SYSTEM_STREAM_BUSY 410
#define ERROR_SYSTEM_IP_INVALID 411
#define ERROR_SYSTEM_FORWARD_LOOP 412
#define ERROR_SYSTEM_WAITPID 413
#define ERROR_SYSTEM_BANDWIDTH_KEY 414
#define ERROR_SYSTEM_BANDWIDTH_DENIED 415
// see librtmp.
// failed when open ssl create the dh
#define ERROR_OpenSslCreateDH 500
#define ERROR_OpenSslCreateDH 500
// failed when open ssl create the Private key.
#define ERROR_OpenSslCreateP 501
#define ERROR_OpenSslCreateP 501
// when open ssl create G.
#define ERROR_OpenSslCreateG 502
#define ERROR_OpenSslCreateG 502
// when open ssl parse P1024
#define ERROR_OpenSslParseP1024 503
#define ERROR_OpenSslParseP1024 503
// when open ssl set G
#define ERROR_OpenSslSetG 504
#define ERROR_OpenSslSetG 504
// when open ssl generate DHKeys
#define ERROR_OpenSslGenerateDHKeys 505
#define ERROR_OpenSslGenerateDHKeys 505
// when open ssl share key already computed.
#define ERROR_OpenSslShareKeyComputed 506
#define ERROR_OpenSslShareKeyComputed 506
// when open ssl get shared key size.
#define ERROR_OpenSslGetSharedKeySize 507
#define ERROR_OpenSslGetSharedKeySize 507
// when open ssl get peer public key.
#define ERROR_OpenSslGetPeerPublicKey 508
#define ERROR_OpenSslGetPeerPublicKey 508
// when open ssl compute shared key.
#define ERROR_OpenSslComputeSharedKey 509
#define ERROR_OpenSslComputeSharedKey 509
// when open ssl is invalid DH state.
#define ERROR_OpenSslInvalidDHState 510
#define ERROR_OpenSslInvalidDHState 510
// when open ssl copy key
#define ERROR_OpenSslCopyKey 511
#define ERROR_OpenSslCopyKey 511
// when open ssl sha256 digest key invalid size.
#define ERROR_OpenSslSha256DigestSize 512
#define ERROR_OpenSslSha256DigestSize 512
#define ERROR_HLS_METADATA 600
#define ERROR_HLS_DECODE_ERROR 601
#define ERROR_HLS_CREATE_DIR 602
#define ERROR_HLS_OPEN_FAILED 603
#define ERROR_HLS_WRITE_FAILED 604
#define ERROR_HLS_AAC_FRAME_LENGTH 605
#define ERROR_HLS_AVC_SAMPLE_SIZE 606
#define ERROR_HLS_METADATA 600
#define ERROR_HLS_DECODE_ERROR 601
#define ERROR_HLS_CREATE_DIR 602
#define ERROR_HLS_OPEN_FAILED 603
#define ERROR_HLS_WRITE_FAILED 604
#define ERROR_HLS_AAC_FRAME_LENGTH 605
#define ERROR_HLS_AVC_SAMPLE_SIZE 606
#define ERROR_ENCODER_VCODEC 700
#define ERROR_ENCODER_OUTPUT 701
#define ERROR_ENCODER_ACHANNELS 702
#define ERROR_ENCODER_ASAMPLE_RATE 703
#define ERROR_ENCODER_ABITRATE 704
#define ERROR_ENCODER_ACODEC 705
#define ERROR_ENCODER_VPRESET 706
#define ERROR_ENCODER_VPROFILE 707
#define ERROR_ENCODER_VTHREADS 708
#define ERROR_ENCODER_VHEIGHT 709
#define ERROR_ENCODER_VWIDTH 710
#define ERROR_ENCODER_VFPS 711
#define ERROR_ENCODER_VBITRATE 712
#define ERROR_ENCODER_FORK 713
#define ERROR_ENCODER_LOOP 714
#define ERROR_ENCODER_OPEN 715
#define ERROR_ENCODER_DUP2 716
#define ERROR_ENCODER_VCODEC 700
#define ERROR_ENCODER_OUTPUT 701
#define ERROR_ENCODER_ACHANNELS 702
#define ERROR_ENCODER_ASAMPLE_RATE 703
#define ERROR_ENCODER_ABITRATE 704
#define ERROR_ENCODER_ACODEC 705
#define ERROR_ENCODER_VPRESET 706
#define ERROR_ENCODER_VPROFILE 707
#define ERROR_ENCODER_VTHREADS 708
#define ERROR_ENCODER_VHEIGHT 709
#define ERROR_ENCODER_VWIDTH 710
#define ERROR_ENCODER_VFPS 711
#define ERROR_ENCODER_VBITRATE 712
#define ERROR_ENCODER_FORK 713
#define ERROR_ENCODER_LOOP 714
#define ERROR_ENCODER_OPEN 715
#define ERROR_ENCODER_DUP2 716
#define ERROR_HTTP_PARSE_URI 800
#define ERROR_HTTP_DATA_INVLIAD 801
#define ERROR_HTTP_PARSE_HEADER 802
#define ERROR_HTTP_PARSE_URI 800
#define ERROR_HTTP_DATA_INVLIAD 801
#define ERROR_HTTP_PARSE_HEADER 802
// system control message,
// not an error, but special control logic.
// sys ctl: rtmp close stream, support replay.
#define ERROR_CONTROL_RTMP_CLOSE 900
#define ERROR_CONTROL_RTMP_CLOSE 900
// FMLE stop publish and republish.
#define ERROR_CONTROL_REPUBLISH 901
#define ERROR_CONTROL_REPUBLISH 901
/**
* whether the error code is an system control error.

View file

@ -65,6 +65,6 @@ void ISrsThreadContext::generate_id()
int ISrsThreadContext::get_id()
{
return 0;
return 0;
}

View file

@ -110,16 +110,16 @@ extern ISrsThreadContext* _srs_context;
#endif
#if 1
#undef srs_verbose
#define srs_verbose(msg, ...) (void)0
#undef srs_verbose
#define srs_verbose(msg, ...) (void)0
#endif
#if 1
#undef srs_info
#define srs_info(msg, ...) (void)0
#undef srs_info
#define srs_info(msg, ...) (void)0
#endif
#if 0
#undef srs_trace
#define srs_trace(msg, ...) (void)0
#undef srs_trace
#define srs_trace(msg, ...) (void)0
#endif
#endif

View file

@ -28,8 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsStream::SrsStream()
{
p = bytes = NULL;
size = 0;
p = bytes = NULL;
size = 0;
}
SrsStream::~SrsStream()
@ -38,113 +38,113 @@ SrsStream::~SrsStream()
int SrsStream::initialize(char* _bytes, int _size)
{
int ret = ERROR_SUCCESS;
if (!_bytes) {
ret = ERROR_SYSTEM_STREAM_INIT;
srs_error("stream param bytes must not be NULL. ret=%d", ret);
return ret;
}
if (_size <= 0) {
ret = ERROR_SYSTEM_STREAM_INIT;
srs_error("stream param size must be positive. ret=%d", ret);
return ret;
}
int ret = ERROR_SUCCESS;
if (!_bytes) {
ret = ERROR_SYSTEM_STREAM_INIT;
srs_error("stream param bytes must not be NULL. ret=%d", ret);
return ret;
}
if (_size <= 0) {
ret = ERROR_SYSTEM_STREAM_INIT;
srs_error("stream param size must be positive. ret=%d", ret);
return ret;
}
size = _size;
p = bytes = _bytes;
size = _size;
p = bytes = _bytes;
return ret;
return ret;
}
void SrsStream::reset()
{
p = bytes;
p = bytes;
}
bool SrsStream::empty()
{
return !p || !bytes || (p >= bytes + size);
return !p || !bytes || (p >= bytes + size);
}
bool SrsStream::require(int required_size)
{
return !empty() && (required_size <= bytes + size - p);
return !empty() && (required_size <= bytes + size - p);
}
void SrsStream::skip(int size)
{
p += size;
p += size;
}
int SrsStream::pos()
{
return p - bytes;
return p - bytes;
}
int SrsStream::left()
{
return size - pos();
return size - pos();
}
char* SrsStream::current()
{
return p;
return p;
}
int8_t SrsStream::read_1bytes()
{
srs_assert(require(1));
return (int8_t)*p++;
srs_assert(require(1));
return (int8_t)*p++;
}
int16_t SrsStream::read_2bytes()
{
srs_assert(require(2));
int16_t value;
pp = (char*)&value;
pp[1] = *p++;
pp[0] = *p++;
return value;
srs_assert(require(2));
int16_t value;
pp = (char*)&value;
pp[1] = *p++;
pp[0] = *p++;
return value;
}
int32_t SrsStream::read_3bytes()
{
srs_assert(require(3));
int32_t value = 0x00;
pp = (char*)&value;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
return value;
srs_assert(require(3));
int32_t value = 0x00;
pp = (char*)&value;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
return value;
}
int32_t SrsStream::read_4bytes()
{
srs_assert(require(4));
int32_t value;
pp = (char*)&value;
pp[3] = *p++;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
return value;
srs_assert(require(4));
int32_t value;
pp = (char*)&value;
pp[3] = *p++;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
return value;
}
int64_t SrsStream::read_8bytes()
{
srs_assert(require(8));
int64_t value;
pp = (char*)&value;
srs_assert(require(8));
int64_t value;
pp = (char*)&value;
pp[7] = *p++;
pp[6] = *p++;
pp[5] = *p++;
@ -153,69 +153,69 @@ int64_t SrsStream::read_8bytes()
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
return value;
return value;
}
std::string SrsStream::read_string(int len)
{
srs_assert(require(len));
std::string value;
value.append(p, len);
p += len;
return value;
srs_assert(require(len));
std::string value;
value.append(p, len);
p += len;
return value;
}
void SrsStream::write_1bytes(int8_t value)
{
srs_assert(require(1));
*p++ = value;
srs_assert(require(1));
*p++ = value;
}
void SrsStream::write_2bytes(int16_t value)
{
srs_assert(require(2));
pp = (char*)&value;
*p++ = pp[1];
*p++ = pp[0];
srs_assert(require(2));
pp = (char*)&value;
*p++ = pp[1];
*p++ = pp[0];
}
void SrsStream::write_4bytes(int32_t value)
{
srs_assert(require(4));
pp = (char*)&value;
*p++ = pp[3];
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
srs_assert(require(4));
pp = (char*)&value;
*p++ = pp[3];
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
}
void SrsStream::write_8bytes(int64_t value)
{
srs_assert(require(8));
pp = (char*)&value;
*p++ = pp[7];
*p++ = pp[6];
*p++ = pp[5];
*p++ = pp[4];
*p++ = pp[3];
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
srs_assert(require(8));
pp = (char*)&value;
*p++ = pp[7];
*p++ = pp[6];
*p++ = pp[5];
*p++ = pp[4];
*p++ = pp[3];
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
}
void SrsStream::write_string(std::string value)
{
srs_assert(require(value.length()));
memcpy(p, value.data(), value.length());
p += value.length();
srs_assert(require(value.length()));
memcpy(p, value.data(), value.length());
p += value.length();
}

View file

@ -36,95 +36,95 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsStream
{
private:
char* p;
char* pp;
char* bytes;
int size;
char* p;
char* pp;
char* bytes;
int size;
public:
SrsStream();
virtual ~SrsStream();
SrsStream();
virtual ~SrsStream();
public:
/**
* initialize the stream from bytes.
* @_bytes, must not be NULL, or return error.
* @_size, must be positive, or return error.
* @remark, stream never free the _bytes, user must free it.
*/
virtual int initialize(char* _bytes, int _size);
/**
* reset the position to beginning.
*/
virtual void reset();
/**
* whether stream is empty.
* if empty, never read or write.
*/
virtual bool empty();
/**
* whether required size is ok.
* @return true if stream can read/write specified required_size bytes.
*/
virtual bool require(int required_size);
/**
* to skip some size.
* @size can be any value. positive to forward; nagetive to backward.
*/
virtual void skip(int size);
/**
* tell the current pos.
*/
virtual int pos();
/**
* left size of bytes.
*/
virtual int left();
virtual char* current();
/**
* initialize the stream from bytes.
* @_bytes, must not be NULL, or return error.
* @_size, must be positive, or return error.
* @remark, stream never free the _bytes, user must free it.
*/
virtual int initialize(char* _bytes, int _size);
/**
* reset the position to beginning.
*/
virtual void reset();
/**
* whether stream is empty.
* if empty, never read or write.
*/
virtual bool empty();
/**
* whether required size is ok.
* @return true if stream can read/write specified required_size bytes.
*/
virtual bool require(int required_size);
/**
* to skip some size.
* @size can be any value. positive to forward; nagetive to backward.
*/
virtual void skip(int size);
/**
* tell the current pos.
*/
virtual int pos();
/**
* left size of bytes.
*/
virtual int left();
virtual char* current();
public:
/**
* get 1bytes char from stream.
*/
virtual int8_t read_1bytes();
/**
* get 2bytes int from stream.
*/
virtual int16_t read_2bytes();
/**
* get 3bytes int from stream.
*/
virtual int32_t read_3bytes();
/**
* get 4bytes int from stream.
*/
virtual int32_t read_4bytes();
/**
* get 8bytes int from stream.
*/
virtual int64_t read_8bytes();
/**
* get string from stream, length specifies by param len.
*/
virtual std::string read_string(int len);
/**
* get 1bytes char from stream.
*/
virtual int8_t read_1bytes();
/**
* get 2bytes int from stream.
*/
virtual int16_t read_2bytes();
/**
* get 3bytes int from stream.
*/
virtual int32_t read_3bytes();
/**
* get 4bytes int from stream.
*/
virtual int32_t read_4bytes();
/**
* get 8bytes int from stream.
*/
virtual int64_t read_8bytes();
/**
* get string from stream, length specifies by param len.
*/
virtual std::string read_string(int len);
public:
/**
* write 1bytes char to stream.
*/
virtual void write_1bytes(int8_t value);
/**
* write 2bytes int to stream.
*/
virtual void write_2bytes(int16_t value);
/**
* write 4bytes int to stream.
*/
virtual void write_4bytes(int32_t value);
/**
* write 8bytes int to stream.
*/
virtual void write_8bytes(int64_t value);
/**
* write string to stream
*/
virtual void write_string(std::string value);
/**
* write 1bytes char to stream.
*/
virtual void write_1bytes(int8_t value);
/**
* write 2bytes int to stream.
*/
virtual void write_2bytes(int16_t value);
/**
* write 4bytes int to stream.
*/
virtual void write_4bytes(int32_t value);
/**
* write 8bytes int to stream.
*/
virtual void write_8bytes(int64_t value);
/**
* write string to stream
*/
virtual void write_string(std::string value);
};
#endif

View file

@ -34,25 +34,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <sys/uio.h>
#ifndef ST_UTIME_NO_TIMEOUT
#define ST_UTIME_NO_TIMEOUT -1
#define ST_UTIME_NO_TIMEOUT -1
#endif
SimpleSocketStream::SimpleSocketStream()
{
fd = -1;
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
recv_bytes = send_bytes = 0;
srs_update_system_time_ms();
start_time_ms = srs_get_system_time_ms();
fd = -1;
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
recv_bytes = send_bytes = 0;
srs_update_system_time_ms();
start_time_ms = srs_get_system_time_ms();
}
SimpleSocketStream::~SimpleSocketStream()
{
if (fd != -1) {
::close(fd);
fd = -1;
}
if (fd != -1) {
::close(fd);
fd = -1;
}
}
int SimpleSocketStream::create_socket()
@ -61,7 +61,7 @@ int SimpleSocketStream::create_socket()
return -1;
}
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
int SimpleSocketStream::connect(const char* server_ip, int port)
@ -75,23 +75,23 @@ int SimpleSocketStream::connect(const char* server_ip, int port)
return -1;
}
return ERROR_SUCCESS;
return ERROR_SUCCESS;
}
// ISrsBufferReader
int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
{
int ret = ERROR_SUCCESS;
*nread = ::recv(fd, (void*)buf, size, 0);
int ret = ERROR_SUCCESS;
*nread = ::recv(fd, (void*)buf, size, 0);
// On success a non-negative integer indicating the number of bytes actually read is returned
// (a value of 0 means the network connection is closed or end of file is reached).
if (*nread <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (*nread == 0) {
errno = ECONNRESET;
}
@ -100,131 +100,131 @@ int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
}
recv_bytes += *nread;
return ret;
return ret;
}
// ISrsProtocolReader
void SimpleSocketStream::set_recv_timeout(int64_t timeout_us)
{
recv_timeout = timeout_us;
recv_timeout = timeout_us;
}
int64_t SimpleSocketStream::get_recv_timeout()
{
return recv_timeout;
return recv_timeout;
}
int64_t SimpleSocketStream::get_recv_bytes()
{
return recv_bytes;
return recv_bytes;
}
int SimpleSocketStream::get_recv_kbps()
{
srs_update_system_time_ms();
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return recv_bytes * 8 / diff_ms;
srs_update_system_time_ms();
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return recv_bytes * 8 / diff_ms;
}
// ISrsProtocolWriter
void SimpleSocketStream::set_send_timeout(int64_t timeout_us)
{
send_timeout = timeout_us;
send_timeout = timeout_us;
}
int64_t SimpleSocketStream::get_send_timeout()
{
return send_timeout;
return send_timeout;
}
int64_t SimpleSocketStream::get_send_bytes()
{
return send_bytes;
return send_bytes;
}
int SimpleSocketStream::get_send_kbps()
{
srs_update_system_time_ms();
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return send_bytes * 8 / diff_ms;
srs_update_system_time_ms();
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) {
return 0;
}
return send_bytes * 8 / diff_ms;
}
int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
*nwrite = ::writev(fd, iov, iov_size);
if (*nwrite <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
return ERROR_SOCKET_WRITE;
}
send_bytes += *nwrite;
return ret;
return ret;
}
// ISrsProtocolReaderWriter
bool SimpleSocketStream::is_never_timeout(int64_t timeout_us)
{
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
}
int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread)
{
int ret = ERROR_SUCCESS;
size_t left = size;
*nread = 0;
while (left > 0) {
char* this_buf = (char*)buf + *nread;
ssize_t this_nread;
if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) {
return ret;
}
*nread += this_nread;
left -= this_nread;
}
int ret = ERROR_SUCCESS;
size_t left = size;
*nread = 0;
while (left > 0) {
char* this_buf = (char*)buf + *nread;
ssize_t this_nread;
if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) {
return ret;
}
*nread += this_nread;
left -= this_nread;
}
recv_bytes += *nread;
return ret;
return ret;
}
int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
*nwrite = ::send(fd, (void*)buf, size, 0);
if (*nwrite <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
return ERROR_SOCKET_WRITE;
}
send_bytes += *nwrite;
return ret;
return ret;
}

View file

@ -39,37 +39,37 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SimpleSocketStream : public ISrsProtocolReaderWriter
{
private:
int64_t start_time_ms;
int64_t recv_timeout;
int64_t send_timeout;
int64_t recv_bytes;
int64_t send_bytes;
int fd;
int64_t start_time_ms;
int64_t recv_timeout;
int64_t send_timeout;
int64_t recv_bytes;
int64_t send_bytes;
int fd;
public:
SimpleSocketStream();
virtual ~SimpleSocketStream();
public:
virtual int create_socket();
virtual int connect(const char* server, int port);
virtual int create_socket();
virtual int connect(const char* server, int port);
// ISrsBufferReader
public:
virtual int read(const void* buf, size_t size, ssize_t* nread);
// ISrsProtocolReader
public:
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual int64_t get_recv_bytes();
virtual int get_recv_kbps();
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual int64_t get_recv_bytes();
virtual int get_recv_kbps();
// ISrsProtocolWriter
public:
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout();
virtual int64_t get_send_bytes();
virtual int get_send_kbps();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout();
virtual int64_t get_send_bytes();
virtual int get_send_kbps();
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
// ISrsProtocolReaderWriter
public:
virtual bool is_never_timeout(int64_t timeout_us);
virtual bool is_never_timeout(int64_t timeout_us);
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
virtual int write(const void* buf, size_t size, ssize_t* nwrite);
};

View file

@ -38,9 +38,9 @@ using namespace std;
// if user want to define log, define the folowing macro.
#ifndef SRS_RTMP_USER_DEFINED_LOG
// kernel module.
ISrsLog* _srs_log = new ISrsLog();
ISrsThreadContext* _srs_context = new ISrsThreadContext();
// kernel module.
ISrsLog* _srs_log = new ISrsLog();
ISrsThreadContext* _srs_context = new ISrsThreadContext();
#endif
/**
@ -48,14 +48,14 @@ using namespace std;
*/
struct Context
{
std::string url;
std::string tcUrl;
std::string host;
std::string port;
std::string vhost;
std::string app;
std::string stream;
std::string url;
std::string tcUrl;
std::string host;
std::string port;
std::string vhost;
std::string app;
std::string stream;
SrsRtmpClient* rtmp;
SimpleSocketStream* skt;
int stream_id;
@ -73,68 +73,68 @@ struct Context
int srs_librtmp_context_connect(Context* context)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
// parse uri
size_t pos = string::npos;
string uri = context->url;
// tcUrl, stream
if ((pos = uri.rfind("/")) != string::npos) {
context->stream = uri.substr(pos + 1);
context->tcUrl = uri = uri.substr(0, pos);
}
// schema
if ((pos = uri.find("rtmp://")) != string::npos) {
uri = uri.substr(pos + 7);
}
// host/vhost/port
if ((pos = uri.find(":")) != string::npos) {
context->vhost = context->host = uri.substr(0, pos);
uri = uri.substr(pos + 1);
if ((pos = uri.find("/")) != string::npos) {
context->port = uri.substr(0, pos);
uri = uri.substr(pos + 1);
}
} else {
if ((pos = uri.find("/")) != string::npos) {
context->vhost = context->host = uri.substr(0, pos);
uri = uri.substr(pos + 1);
}
context->port = RTMP_DEFAULT_PORT;
}
// app
context->app = uri;
// query of app
if ((pos = uri.find("?")) != string::npos) {
context->app = uri.substr(0, pos);
string query = uri.substr(pos + 1);
if ((pos = query.find("vhost=")) != string::npos) {
context->vhost = query.substr(pos + 6);
if ((pos = context->vhost.find("&")) != string::npos) {
context->vhost = context->vhost.substr(pos);
}
}
}
size_t pos = string::npos;
string uri = context->url;
// tcUrl, stream
if ((pos = uri.rfind("/")) != string::npos) {
context->stream = uri.substr(pos + 1);
context->tcUrl = uri = uri.substr(0, pos);
}
// schema
if ((pos = uri.find("rtmp://")) != string::npos) {
uri = uri.substr(pos + 7);
}
// host/vhost/port
if ((pos = uri.find(":")) != string::npos) {
context->vhost = context->host = uri.substr(0, pos);
uri = uri.substr(pos + 1);
if ((pos = uri.find("/")) != string::npos) {
context->port = uri.substr(0, pos);
uri = uri.substr(pos + 1);
}
} else {
if ((pos = uri.find("/")) != string::npos) {
context->vhost = context->host = uri.substr(0, pos);
uri = uri.substr(pos + 1);
}
context->port = RTMP_DEFAULT_PORT;
}
// app
context->app = uri;
// query of app
if ((pos = uri.find("?")) != string::npos) {
context->app = uri.substr(0, pos);
string query = uri.substr(pos + 1);
if ((pos = query.find("vhost=")) != string::npos) {
context->vhost = query.substr(pos + 6);
if ((pos = context->vhost.find("&")) != string::npos) {
context->vhost = context->vhost.substr(pos);
}
}
}
// create socket
srs_freep(context->skt);
context->skt = new SimpleSocketStream();
if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
return ret;
}
// connect to server:port
string server = srs_dns_resolve(context->host);
if (server.empty()) {
return -1;
}
if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
return ret;
}
return ret;
srs_freep(context->skt);
context->skt = new SimpleSocketStream();
if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
return ret;
}
// connect to server:port
string server = srs_dns_resolve(context->host);
if (server.empty()) {
return -1;
}
if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
#ifdef __cplusplus
@ -144,7 +144,7 @@ extern "C"{
srs_rtmp_t srs_rtmp_create(const char* url)
{
Context* context = new Context();
context->url = url;
context->url = url;
return context;
}
@ -158,8 +158,8 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp)
int srs_simple_handshake(srs_rtmp_t rtmp)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
@ -167,26 +167,26 @@ int srs_simple_handshake(srs_rtmp_t rtmp)
if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
return ret;
}
// simple handshake
srs_freep(context->rtmp);
context->rtmp = new SrsRtmpClient(context->skt);
if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {
return ret;
}
return ret;
// simple handshake
srs_freep(context->rtmp);
context->rtmp = new SrsRtmpClient(context->skt);
if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int srs_complex_handshake(srs_rtmp_t rtmp)
{
#ifndef SRS_SSL
return ERROR_RTMP_HS_SSL_REQUIRE;
return ERROR_RTMP_HS_SSL_REQUIRE;
#endif
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
@ -194,43 +194,43 @@ int srs_complex_handshake(srs_rtmp_t rtmp)
if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
return ret;
}
// complex handshake
srs_freep(context->rtmp);
context->rtmp = new SrsRtmpClient(context->skt);
if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {
return ret;
}
return ret;
// complex handshake
srs_freep(context->rtmp);
context->rtmp = new SrsRtmpClient(context->skt);
if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int srs_connect_app(srs_rtmp_t rtmp)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
string tcUrl = "rtmp://";
tcUrl += context->vhost;
tcUrl += ":";
tcUrl += context->port;
tcUrl += "/";
tcUrl += context->app;
if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {
return ret;
}
return ret;
string tcUrl = "rtmp://";
tcUrl += context->vhost;
tcUrl += ":";
tcUrl += context->port;
tcUrl += "/";
tcUrl += context->app;
if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int srs_play_stream(srs_rtmp_t rtmp)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
@ -241,13 +241,13 @@ int srs_play_stream(srs_rtmp_t rtmp)
return ret;
}
return ret;
return ret;
}
int srs_publish_stream(srs_rtmp_t rtmp)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
@ -255,30 +255,30 @@ int srs_publish_stream(srs_rtmp_t rtmp)
return ret;
}
return ret;
return ret;
}
const char* srs_type2string(int type)
{
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";
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";
}
int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size)
{
*type = 0;
*timestamp = 0;
*data = NULL;
*size = 0;
int ret = ERROR_SUCCESS;
*type = 0;
*timestamp = 0;
*data = NULL;
*size = 0;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
@ -322,81 +322,81 @@ int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** dat
break;
}
return ret;
return ret;
}
int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp;
SrsSharedPtrMessage* msg = NULL;
if (type == SRS_RTMP_TYPE_AUDIO) {
SrsMessageHeader header;
header.initialize_audio(size, timestamp, context->stream_id);
msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data);
return ret;
}
} else if (type == SRS_RTMP_TYPE_VIDEO) {
SrsMessageHeader header;
header.initialize_video(size, timestamp, context->stream_id);
msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data);
return ret;
}
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
SrsMessageHeader header;
header.initialize_amf0_script(size, context->stream_id);
msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data);
return ret;
}
}
if (msg) {
// send out encoded msg.
if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) {
return ret;
}
} else {
// directly free data if not sent out.
srs_freepa(data);
}
return ret;
SrsSharedPtrMessage* msg = NULL;
if (type == SRS_RTMP_TYPE_AUDIO) {
SrsMessageHeader header;
header.initialize_audio(size, timestamp, context->stream_id);
msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data);
return ret;
}
} else if (type == SRS_RTMP_TYPE_VIDEO) {
SrsMessageHeader header;
header.initialize_video(size, timestamp, context->stream_id);
msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data);
return ret;
}
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
SrsMessageHeader header;
header.initialize_amf0_script(size, context->stream_id);
msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data);
return ret;
}
}
if (msg) {
// send out encoded msg.
if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) {
return ret;
}
} else {
// directly free data if not sent out.
srs_freepa(data);
}
return ret;
}
int srs_ssl_enabled()
{
#ifndef SRS_SSL
return false;
return false;
#endif
return true;
return true;
}
int srs_version_major()
{
return ::atoi(VERSION_MAJOR);
return ::atoi(VERSION_MAJOR);
}
int srs_version_minor()
{
return ::atoi(VERSION_MINOR);
return ::atoi(VERSION_MINOR);
}
int srs_version_revision()
{
return ::atoi(VERSION_REVISION);
return ::atoi(VERSION_REVISION);
}
#ifdef __cplusplus

View file

@ -48,7 +48,7 @@ typedef void* srs_rtmp_t;
/**
* create/destroy a rtmp protocol stack.
* @url rtmp url, for example:
* rtmp://127.0.0.1/live/livestream
* rtmp://127.0.0.1/live/livestream
* @return a rtmp handler, or NULL if error occured.
*/
srs_rtmp_t srs_rtmp_create(const char* url);
@ -113,23 +113,23 @@ int srs_publish_stream(srs_rtmp_t rtmp);
#define SRS_RTMP_TYPE_SCRIPT 18
/**
* 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"
* SRS_RTMP_TYPE_AUDIO to "Audio"
* SRS_RTMP_TYPE_VIDEO to "Video"
* SRS_RTMP_TYPE_SCRIPT to "Data"
* otherwise, "Unknown"
*/
const char* srs_type2string(int type);
/**
* 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
* SRS_RTMP_TYPE_AUDIO, FlvTagAudio
* SRS_RTMP_TYPE_VIDEO, FlvTagVideo
* SRS_RTMP_TYPE_SCRIPT, FlvTagScript
* @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"
* FlvTagAudio, @see "E.4.2.1 AUDIODATA"
* FlvTagVideo, @see "E.4.3.1 VIDEODATA"
* FlvTagScript, @see "E.4.4.1 SCRIPTDATA"
* @param size, size of packet.
* @return the error code. 0 for success; otherwise, error.
*

View file

@ -158,8 +158,8 @@ public:
private:
int connect_server();
private:
st_netfd_t stfd;
ISrsProtocolReaderWriter* skt;
st_netfd_t stfd;
ISrsProtocolReaderWriter* skt;
SrsBandCheckClient* bandCheck_Client;
std::string server_address;
int server_port;
@ -493,8 +493,8 @@ int SrsBandCheckClient::expect_stop_pub()
this->set_recv_timeout(1000 * 1000);
this->set_send_timeout(1000 * 1000);
SrsCommonMessage* msg;
SrsBandwidthPacket* pkt;
SrsCommonMessage* msg;
SrsBandwidthPacket* pkt;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(this->protocol, &msg, &pkt)) != ERROR_SUCCESS) {
return ret;
}
@ -641,16 +641,16 @@ int SrsBandCheckClient::send_final()
SrsBandCheck::SrsBandCheck()
{
skt = NULL;
bandCheck_Client = NULL;
stfd = NULL;
skt = NULL;
bandCheck_Client = NULL;
stfd = NULL;
}
SrsBandCheck::~SrsBandCheck()
{
srs_freep(bandCheck_Client);
srs_freep(skt);
srs_close_stfd(stfd);
srs_freep(bandCheck_Client);
srs_freep(skt);
srs_close_stfd(stfd);
}
int SrsBandCheck::check(const std::string &app, const std::string &tcUrl)
@ -709,7 +709,7 @@ int SrsBandCheck::connect_server()
return ret;
}
skt = new SrsSocket(stfd);
skt = new SrsSocket(stfd);
bandCheck_Client = new SrsBandCheckClient(skt);
// connect to server.
@ -757,7 +757,7 @@ int init_st()
void print_help(char** argv)
{
printf(
"Usage: %s [OPTION]...\n"
"Usage: %s [OPTION]...\n"
"test band width from client to rtmp server.\n"
"Mandatory arguments to long options are mandatory for short options too.\n"
" -i, --ip the ip or domain that to test\n"
@ -767,8 +767,8 @@ void print_help(char** argv)
" -V, --version output version information and exit \n"
" -h, --help display this help and exit \n"
"\n"
"For example:\n"
" %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e"
"For example:\n"
" %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e"
"\n\n"
"Exit status:\n"
"0 if OK,\n"

View file

@ -38,21 +38,21 @@ SrsServer* _srs_server = new SrsServer();
#include <signal.h>
#ifdef SRS_GPERF_MP
#include <gperftools/heap-profiler.h>
#include <gperftools/heap-profiler.h>
#endif
#ifdef SRS_GPERF_CP
#include <gperftools/profiler.h>
#include <gperftools/profiler.h>
#endif
void handler(int signo)
{
srs_trace("get a signal, signo=%d", signo);
_srs_server->on_signal(signo);
srs_trace("get a signal, signo=%d", signo);
_srs_server->on_signal(signo);
}
int main(int argc, char** argv)
{
int ret = ERROR_SUCCESS;
int ret = ERROR_SUCCESS;
#ifdef SRS_GPERF_MP
HeapProfilerStart("gperf.srs.gmp");
@ -60,37 +60,37 @@ int main(int argc, char** argv)
#ifdef SRS_GPERF_CP
ProfilerStart("gperf.srs.gcp");
#endif
signal(SIGNAL_RELOAD, handler);
signal(SIGINT, handler);
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
return ret;
}
signal(SIGNAL_RELOAD, handler);
signal(SIGINT, handler);
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
return ret;
}
#ifdef SRS_GPERF_MC
#ifdef SRS_GPERF_MP
srs_error("option --with-gmc confict with --with-gmp, "
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
"Note that since the heap-checker uses the heap-profiling framework internally, "
"it is not possible to run both the heap-checker and heap profiler at the same time");
return -1;
#endif
#ifdef SRS_GPERF_MP
srs_error("option --with-gmc confict with --with-gmp, "
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
"Note that since the heap-checker uses the heap-profiling framework internally, "
"it is not possible to run both the heap-checker and heap profiler at the same time");
return -1;
#endif
#endif
if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) {
return ret;
}
// TODO: create log dir in _srs_config->get_log_dir()
if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
return ret;
}
if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) {
return ret;
}
if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) {
return ret;
}
// TODO: create log dir in _srs_config->get_log_dir()
if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
return ret;
}
if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) {
return ret;
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -43,29 +43,29 @@ class __SrsAmf0ObjectEOF;
////////////////////////////////////////////////////////////////////////
// amf0 codec
// 1. SrsAmf0Any: read any from stream
// SrsAmf0Any* pany = NULL;
// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) {
// return ret;
// }
// srs_assert(pany); // if success, always valid object.
// SrsAmf0Any* pany = NULL;
// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) {
// return ret;
// }
// srs_assert(pany); // if success, always valid object.
// 2. SrsAmf0Any: convert to specifid type, for instance, string
// SrsAmf0Any* pany = ...
// if (pany->is_string()) {
// string v = pany->to_str();
// }
// SrsAmf0Any* pany = ...
// if (pany->is_string()) {
// string v = pany->to_str();
// }
// 3. SrsAmf0Any: parse specified type to any, for instance, string
// SrsAmf0Any* pany = SrsAmf0Any::str("winlin");
// SrsAmf0Any* pany = SrsAmf0Any::str("winlin");
// 4. SrsAmf0Size: get amf0 instance size
// int size = SrsAmf0Size::str("winlin");
// int size = SrsAmf0Size::str("winlin");
// 5. SrsAmf0Object: create the amf0 object.
// SrsAmf0Object* obj = SrsAmf0Any::object();
// SrsAmf0Object* obj = SrsAmf0Any::object();
// 5. SrsAmf0EcmaArray: create the amf0 ecma array.
// SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
// SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
//
// please carefully the size and count of amf0 any:
// 1. total_size(): the total memory size the object wrote to buffer.
// 2. count(): the total element count of object, for instance, the properties
// of amf0 object, used for key_at/value_at loop.
// of amf0 object, used for key_at/value_at loop.
//
// for detail usage, see interfaces of each object.
////////////////////////////////////////////////////////////////////////
@ -76,73 +76,73 @@ class __SrsAmf0ObjectEOF;
* any amf0 value.
* 2.1 Types Overview
* value-type = number-type | boolean-type | string-type | object-type
* | null-marker | undefined-marker | reference-type | ecma-array-type
* | strict-array-type | date-type | long-string-type | xml-document-type
* | typed-object-type
* | null-marker | undefined-marker | reference-type | ecma-array-type
* | strict-array-type | date-type | long-string-type | xml-document-type
* | typed-object-type
*/
class SrsAmf0Any
{
public:
char marker;
char marker;
public:
SrsAmf0Any();
virtual ~SrsAmf0Any();
SrsAmf0Any();
virtual ~SrsAmf0Any();
public:
virtual bool is_string();
virtual bool is_boolean();
virtual bool is_number();
virtual bool is_null();
virtual bool is_undefined();
virtual bool is_object();
virtual bool is_object_eof();
virtual bool is_ecma_array();
virtual bool is_string();
virtual bool is_boolean();
virtual bool is_number();
virtual bool is_null();
virtual bool is_undefined();
virtual bool is_object();
virtual bool is_object_eof();
virtual bool is_ecma_array();
public:
/**
* get the string of any when is_string() indicates true.
* user must ensure the type is a string, or assert failed.
*/
virtual std::string to_str();
/**
* get the boolean of any when is_boolean() indicates true.
* user must ensure the type is a boolean, or assert failed.
*/
virtual bool to_boolean();
/**
* get the number of any when is_number() indicates true.
* user must ensure the type is a number, or assert failed.
*/
virtual double to_number();
/**
* get the object of any when is_object() indicates true.
* user must ensure the type is a object, or assert failed.
*/
virtual SrsAmf0Object* to_object();
/**
* get the ecma array of any when is_ecma_array() indicates true.
* user must ensure the type is a ecma array, or assert failed.
*/
virtual SrsAmf0EcmaArray* to_ecma_array();
/**
* get the string of any when is_string() indicates true.
* user must ensure the type is a string, or assert failed.
*/
virtual std::string to_str();
/**
* get the boolean of any when is_boolean() indicates true.
* user must ensure the type is a boolean, or assert failed.
*/
virtual bool to_boolean();
/**
* get the number of any when is_number() indicates true.
* user must ensure the type is a number, or assert failed.
*/
virtual double to_number();
/**
* get the object of any when is_object() indicates true.
* user must ensure the type is a object, or assert failed.
*/
virtual SrsAmf0Object* to_object();
/**
* get the ecma array of any when is_ecma_array() indicates true.
* user must ensure the type is a ecma array, or assert failed.
*/
virtual SrsAmf0EcmaArray* to_ecma_array();
public:
/**
* get the size of amf0 any, including the marker size.
*/
virtual int total_size() = 0;
/**
* read elem from stream
*/
virtual int read(SrsStream* stream) = 0;
virtual int write(SrsStream* stream) = 0;
/**
* get the size of amf0 any, including the marker size.
*/
virtual int total_size() = 0;
/**
* read elem from stream
*/
virtual int read(SrsStream* stream) = 0;
virtual int write(SrsStream* stream) = 0;
public:
static SrsAmf0Any* str(const char* value = NULL);
static SrsAmf0Any* boolean(bool value = false);
static SrsAmf0Any* number(double value = 0.0);
static SrsAmf0Any* null();
static SrsAmf0Any* undefined();
static SrsAmf0Object* object();
static SrsAmf0Any* object_eof();
static SrsAmf0EcmaArray* ecma_array();
static SrsAmf0Any* str(const char* value = NULL);
static SrsAmf0Any* boolean(bool value = false);
static SrsAmf0Any* number(double value = 0.0);
static SrsAmf0Any* null();
static SrsAmf0Any* undefined();
static SrsAmf0Object* object();
static SrsAmf0Any* object_eof();
static SrsAmf0EcmaArray* ecma_array();
public:
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
};
/**
@ -153,33 +153,33 @@ public:
class SrsAmf0Object : public SrsAmf0Any
{
private:
__SrsUnSortedHashtable* properties;
__SrsAmf0ObjectEOF* eof;
__SrsUnSortedHashtable* properties;
__SrsAmf0ObjectEOF* eof;
private:
// use SrsAmf0Any::object() to create it.
friend class SrsAmf0Any;
SrsAmf0Object();
// use SrsAmf0Any::object() to create it.
friend class SrsAmf0Any;
SrsAmf0Object();
public:
virtual ~SrsAmf0Object();
virtual ~SrsAmf0Object();
public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
public:
virtual int count();
// @remark: max index is count().
virtual std::string key_at(int index);
// @remark: max index is count().
virtual SrsAmf0Any* value_at(int index);
virtual int count();
// @remark: max index is count().
virtual std::string key_at(int index);
// @remark: max index is count().
virtual SrsAmf0Any* value_at(int index);
public:
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
};
/**
@ -191,35 +191,35 @@ public:
class SrsAmf0EcmaArray : public SrsAmf0Any
{
private:
__SrsUnSortedHashtable* properties;
__SrsAmf0ObjectEOF* eof;
int32_t _count;
__SrsUnSortedHashtable* properties;
__SrsAmf0ObjectEOF* eof;
int32_t _count;
private:
// use SrsAmf0Any::ecma_array() to create it.
friend class SrsAmf0Any;
SrsAmf0EcmaArray();
// use SrsAmf0Any::ecma_array() to create it.
friend class SrsAmf0Any;
SrsAmf0EcmaArray();
public:
virtual ~SrsAmf0EcmaArray();
virtual ~SrsAmf0EcmaArray();
public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
public:
virtual void clear();
virtual int count();
// @remark: max index is count().
virtual std::string key_at(int index);
// @remark: max index is count().
virtual SrsAmf0Any* value_at(int index);
virtual void clear();
virtual int count();
// @remark: max index is count().
virtual std::string key_at(int index);
// @remark: max index is count().
virtual SrsAmf0Any* value_at(int index);
public:
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
};
/**
@ -228,22 +228,22 @@ public:
class SrsAmf0Size
{
public:
static int utf8(std::string value);
static int str(std::string value);
static int number();
static int null();
static int undefined();
static int boolean();
static int object(SrsAmf0Object* obj);
static int object_eof();
static int ecma_array(SrsAmf0EcmaArray* arr);
static int any(SrsAmf0Any* o);
static int utf8(std::string value);
static int str(std::string value);
static int number();
static int null();
static int undefined();
static int boolean();
static int object(SrsAmf0Object* obj);
static int object_eof();
static int ecma_array(SrsAmf0EcmaArray* arr);
static int any(SrsAmf0Any* o);
};
/**
* read anything from stream.
* @param ppvalue, the output amf0 any elem.
* NULL if error; otherwise, never NULL and user must free it.
* NULL if error; otherwise, never NULL and user must free it.
*/
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);
@ -259,7 +259,7 @@ extern int srs_amf0_write_string(SrsStream* stream, std::string value);
* read amf0 boolean from stream.
* 2.4 String Type
* boolean-type = boolean-marker U8
* 0 is false, <> 0 is true
* 0 is false, <> 0 is true
*/
extern int srs_amf0_read_boolean(SrsStream* stream, bool& value);
extern int srs_amf0_write_boolean(SrsStream* stream, bool value);

File diff suppressed because it is too large Load diff

View file

@ -39,17 +39,17 @@ class SrsComplexHandshake;
class SrsSimpleHandshake
{
public:
SrsSimpleHandshake();
virtual ~SrsSimpleHandshake();
SrsSimpleHandshake();
virtual ~SrsSimpleHandshake();
public:
/**
* simple handshake.
* @param complex_hs, try complex handshake first,
* if NULL, use simple handshake.
* if failed, rollback to simple handshake.
*/
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
/**
* simple handshake.
* @param complex_hs, try complex handshake first,
* if NULL, use simple handshake.
* if failed, rollback to simple handshake.
*/
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
};
/**
@ -60,20 +60,20 @@ public:
class SrsComplexHandshake
{
public:
SrsComplexHandshake();
virtual ~SrsComplexHandshake();
SrsComplexHandshake();
virtual ~SrsComplexHandshake();
public:
/**
* complex hanshake.
* @_c1, size of c1 must be 1536.
* @remark, user must free the c1.
* @return user must:
* continue connect app if success,
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
* otherwise, disconnect
*/
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1);
virtual int handshake_with_server(ISrsProtocolReaderWriter* io);
/**
* complex hanshake.
* @_c1, size of c1 must be 1536.
* @remark, user must free the c1.
* @return user must:
* continue connect app if success,
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
* otherwise, disconnect
*/
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1);
virtual int handshake_with_server(ISrsProtocolReaderWriter* io);
};
#endif

View file

@ -40,14 +40,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsProtocolReader : public ISrsBufferReader
{
public:
ISrsProtocolReader();
virtual ~ISrsProtocolReader();
ISrsProtocolReader();
virtual ~ISrsProtocolReader();
// for protocol
public:
virtual void set_recv_timeout(int64_t timeout_us) = 0;
virtual int64_t get_recv_timeout() = 0;
virtual int64_t get_recv_bytes() = 0;
virtual int get_recv_kbps() = 0;
virtual void set_recv_timeout(int64_t timeout_us) = 0;
virtual int64_t get_recv_timeout() = 0;
virtual int64_t get_recv_bytes() = 0;
virtual int get_recv_kbps() = 0;
};
/**
@ -56,28 +56,28 @@ public:
class ISrsProtocolWriter
{
public:
ISrsProtocolWriter();
virtual ~ISrsProtocolWriter();
ISrsProtocolWriter();
virtual ~ISrsProtocolWriter();
// for protocol
public:
virtual void set_send_timeout(int64_t timeout_us) = 0;
virtual int64_t get_send_timeout() = 0;
virtual int64_t get_send_bytes() = 0;
virtual int get_send_kbps() = 0;
virtual void set_send_timeout(int64_t timeout_us) = 0;
virtual int64_t get_send_timeout() = 0;
virtual int64_t get_send_bytes() = 0;
virtual int get_send_kbps() = 0;
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite) = 0;
};
class ISrsProtocolReaderWriter : public ISrsProtocolReader, public ISrsProtocolWriter
{
public:
ISrsProtocolReaderWriter();
virtual ~ISrsProtocolReaderWriter();
ISrsProtocolReaderWriter();
virtual ~ISrsProtocolReaderWriter();
// for protocol
public:
/**
* whether the specified timeout_us is never timeout.
*/
virtual bool is_never_timeout(int64_t timeout_us) = 0;
/**
* whether the specified timeout_us is never timeout.
*/
virtual bool is_never_timeout(int64_t timeout_us) = 0;
// for handshake.
public:
virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0;

File diff suppressed because it is too large Load diff

View file

@ -48,41 +48,41 @@ class SrsPlayPacket;
*/
struct SrsRequest
{
/**
* tcUrl: rtmp://request_vhost:port/app/stream
* support pass vhost in query string, such as:
* rtmp://ip:port/app?vhost=request_vhost/stream
* rtmp://ip:port/app...vhost...request_vhost/stream
*/
std::string tcUrl;
std::string pageUrl;
std::string swfUrl;
double objectEncoding;
std::string schema;
std::string vhost;
std::string port;
std::string app;
std::string stream;
SrsRequest();
virtual ~SrsRequest();
/**
* tcUrl: rtmp://request_vhost:port/app/stream
* support pass vhost in query string, such as:
* rtmp://ip:port/app?vhost=request_vhost/stream
* rtmp://ip:port/app...vhost...request_vhost/stream
*/
std::string tcUrl;
std::string pageUrl;
std::string swfUrl;
double objectEncoding;
std::string schema;
std::string vhost;
std::string port;
std::string app;
std::string stream;
SrsRequest();
virtual ~SrsRequest();
/**
* deep copy the request, for source to use it to support reload,
* for when initialize the source, the request is valid,
* when reload it, the request maybe invalid, so need to copy it.
*/
virtual SrsRequest* copy();
/**
* disconvery vhost/app from tcUrl.
*/
virtual int discovery_app();
virtual std::string get_stream_url();
virtual void strip();
/**
* deep copy the request, for source to use it to support reload,
* for when initialize the source, the request is valid,
* when reload it, the request maybe invalid, so need to copy it.
*/
virtual SrsRequest* copy();
/**
* disconvery vhost/app from tcUrl.
*/
virtual int discovery_app();
virtual std::string get_stream_url();
virtual void strip();
private:
std::string& trim(std::string& str, std::string chs);
std::string& trim(std::string& str, std::string chs);
};
/**
@ -90,10 +90,10 @@ private:
*/
struct SrsResponse
{
int stream_id;
SrsResponse();
virtual ~SrsResponse();
int stream_id;
SrsResponse();
virtual ~SrsResponse();
};
/**
@ -101,10 +101,10 @@ struct SrsResponse
*/
enum SrsClientType
{
SrsClientUnknown,
SrsClientPlay,
SrsClientFMLEPublish,
SrsClientFlashPublish,
SrsClientUnknown,
SrsClientPlay,
SrsClientFMLEPublish,
SrsClientFlashPublish,
};
std::string srs_client_type_string(SrsClientType type);
@ -114,36 +114,36 @@ std::string srs_client_type_string(SrsClientType type);
class SrsRtmpClient
{
protected:
SrsProtocol* protocol;
ISrsProtocolReaderWriter* io;
SrsProtocol* protocol;
ISrsProtocolReaderWriter* io;
public:
SrsRtmpClient(ISrsProtocolReaderWriter* skt);
virtual ~SrsRtmpClient();
SrsRtmpClient(ISrsProtocolReaderWriter* skt);
virtual ~SrsRtmpClient();
public:
virtual void set_recv_timeout(int64_t timeout_us);
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
virtual void set_recv_timeout(int64_t timeout_us);
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
// try complex, then simple handshake.
virtual int handshake();
// only use simple handshake
virtual int simple_handshake();
// only use complex handshake
virtual int complex_handshake();
virtual int connect_app(std::string app, std::string tc_url);
virtual int create_stream(int& stream_id);
virtual int play(std::string stream, int stream_id);
// flash publish schema:
// connect-app => create-stream => flash-publish
virtual int publish(std::string stream, int stream_id);
// FMLE publish schema:
// connect-app => FMLE publish
virtual int fmle_publish(std::string stream, int& stream_id);
// try complex, then simple handshake.
virtual int handshake();
// only use simple handshake
virtual int simple_handshake();
// only use complex handshake
virtual int complex_handshake();
virtual int connect_app(std::string app, std::string tc_url);
virtual int create_stream(int& stream_id);
virtual int play(std::string stream, int stream_id);
// flash publish schema:
// connect-app => create-stream => flash-publish
virtual int publish(std::string stream, int stream_id);
// FMLE publish schema:
// connect-app => FMLE publish
virtual int fmle_publish(std::string stream, int& stream_id);
};
/**
@ -155,93 +155,93 @@ public:
class SrsRtmpServer
{
private:
SrsProtocol* protocol;
ISrsProtocolReaderWriter* io;
SrsProtocol* protocol;
ISrsProtocolReaderWriter* io;
public:
SrsRtmpServer(ISrsProtocolReaderWriter* skt);
virtual ~SrsRtmpServer();
SrsRtmpServer(ISrsProtocolReaderWriter* skt);
virtual ~SrsRtmpServer();
public:
virtual SrsProtocol* get_protocol();
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout();
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
virtual SrsProtocol* get_protocol();
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout();
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
virtual int handshake();
virtual int connect_app(SrsRequest* req);
virtual int set_window_ack_size(int ack_size);
/**
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
* using the Limit type field.
*/
virtual int set_peer_bandwidth(int bandwidth, int type);
/**
* @param server_ip the ip of server.
*/
virtual int handshake();
virtual int connect_app(SrsRequest* req);
virtual int set_window_ack_size(int ack_size);
/**
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
* using the Limit type field.
*/
virtual int set_peer_bandwidth(int bandwidth, int type);
/**
* @param server_ip the ip of server.
*/
virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL);
virtual void response_connect_reject(SrsRequest* req, const char* desc);
virtual int on_bw_done();
/**
* recv some message to identify the client.
* @stream_id, client will createStream to play or publish by flash,
* the stream_id used to response the createStream request.
* @type, output the client type.
*/
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
/**
* set the chunk size when client type identified.
*/
virtual int set_chunk_size(int chunk_size);
/**
* when client type is play, response with packets:
* StreamBegin,
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
* |RtmpSampleAccess(false, false),
* onStatus(NetStream.Data.Start).
*/
virtual int start_play(int stream_id);
/**
* when client(type is play) send pause message,
* if is_pause, response the following packets:
* onStatus(NetStream.Pause.Notify)
* StreamEOF
* if not is_pause, response the following packets:
* onStatus(NetStream.Unpause.Notify)
* StreamBegin
*/
virtual int on_play_client_pause(int stream_id, bool is_pause);
/**
* when client type is publish, response with packets:
* releaseStream response
* FCPublish
* FCPublish response
* createStream response
* onFCPublish(NetStream.Publish.Start)
* onStatus(NetStream.Publish.Start)
*/
virtual int start_fmle_publish(int stream_id);
/**
* process the FMLE unpublish event.
* @unpublish_tid the unpublish request transaction id.
*/
virtual int fmle_unpublish(int stream_id, double unpublish_tid);
/**
* when client type is publish, response with packets:
* onStatus(NetStream.Publish.Start)
*/
virtual int start_flash_publish(int stream_id);
virtual int on_bw_done();
/**
* recv some message to identify the client.
* @stream_id, client will createStream to play or publish by flash,
* the stream_id used to response the createStream request.
* @type, output the client type.
*/
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
/**
* set the chunk size when client type identified.
*/
virtual int set_chunk_size(int chunk_size);
/**
* when client type is play, response with packets:
* StreamBegin,
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
* |RtmpSampleAccess(false, false),
* onStatus(NetStream.Data.Start).
*/
virtual int start_play(int stream_id);
/**
* when client(type is play) send pause message,
* if is_pause, response the following packets:
* onStatus(NetStream.Pause.Notify)
* StreamEOF
* if not is_pause, response the following packets:
* onStatus(NetStream.Unpause.Notify)
* StreamBegin
*/
virtual int on_play_client_pause(int stream_id, bool is_pause);
/**
* when client type is publish, response with packets:
* releaseStream response
* FCPublish
* FCPublish response
* createStream response
* onFCPublish(NetStream.Publish.Start)
* onStatus(NetStream.Publish.Start)
*/
virtual int start_fmle_publish(int stream_id);
/**
* process the FMLE unpublish event.
* @unpublish_tid the unpublish request transaction id.
*/
virtual int fmle_unpublish(int stream_id, double unpublish_tid);
/**
* when client type is publish, response with packets:
* onStatus(NetStream.Publish.Start)
*/
virtual int start_flash_publish(int stream_id);
private:
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
private:
virtual int identify_play_client(SrsPlayPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_play_client(SrsPlayPacket* req, SrsClientType& type, std::string& stream_name);
};
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -25,24 +25,24 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
void srs_vhost_resolve(std::string& vhost, std::string& app)
{
app = srs_replace(app, "...", "?");
size_t pos = 0;
if ((pos = app.find("?")) == std::string::npos) {
return;
}
std::string query = app.substr(pos + 1);
app = app.substr(0, pos);
if ((pos = query.find("vhost?")) != std::string::npos
|| (pos = query.find("vhost=")) != std::string::npos
|| (pos = query.find("Vhost?")) != std::string::npos
|| (pos = query.find("Vhost=")) != std::string::npos
) {
query = query.substr(pos + 6);
if (!query.empty()) {
vhost = query;
}
}
app = srs_replace(app, "...", "?");
size_t pos = 0;
if ((pos = app.find("?")) == std::string::npos) {
return;
}
std::string query = app.substr(pos + 1);
app = app.substr(0, pos);
if ((pos = query.find("vhost?")) != std::string::npos
|| (pos = query.find("vhost=")) != std::string::npos
|| (pos = query.find("Vhost?")) != std::string::npos
|| (pos = query.find("Vhost=")) != std::string::npos
) {
query = query.substr(pos + 6);
if (!query.empty()) {
vhost = query;
}
}
}

View file

@ -36,8 +36,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// resolve the vhost in query string
// @param app, may contains the vhost in query string format:
// app?vhost=request_vhost
// app...vhost...request_vhost
// app?vhost=request_vhost
// app...vhost...request_vhost
extern void srs_vhost_resolve(std::string& vhost, std::string& app);
#endif

View file

@ -1,88 +1,88 @@
file
main readonly separator,
..\main\srs_main_server.cpp,
..\main\srs_main_bandcheck.cpp,
auto readonly separator,
..\..\objs\srs_auto_headers.hpp,
libs readonly separator,
..\libs\srs_librtmp.hpp,
..\libs\srs_librtmp.cpp,
..\libs\srs_lib_simple_socket.hpp,
..\libs\srs_lib_simple_socket.cpp,
core readonly separator,
..\core\srs_core.hpp,
..\core\srs_core.cpp,
..\core\srs_core_autofree.hpp,
..\core\srs_core_autofree.cpp,
kernel readonly separator,
..\kernel\srs_kernel_buffer.hpp,
..\kernel\srs_kernel_buffer.cpp,
..\kernel\srs_kernel_error.hpp,
..\kernel\srs_kernel_error.cpp,
..\kernel\srs_kernel_log.hpp,
..\kernel\srs_kernel_log.cpp,
..\kernel\srs_kernel_stream.hpp,
..\kernel\srs_kernel_stream.cpp,
rtmp-protocol readonly separator,
..\rtmp\srs_protocol_amf0.hpp,
..\rtmp\srs_protocol_amf0.cpp,
..\rtmp\srs_protocol_handshake.hpp,
..\rtmp\srs_protocol_handshake.cpp,
..\rtmp\srs_protocol_io.hpp,
..\rtmp\srs_protocol_io.cpp,
..\rtmp\srs_protocol_rtmp.hpp,
..\rtmp\srs_protocol_rtmp.cpp,
..\rtmp\srs_protocol_rtmp_stack.hpp,
..\rtmp\srs_protocol_rtmp_stack.cpp,
..\rtmp\srs_protocol_utility.hpp,
..\rtmp\srs_protocol_utility.cpp,
app readonly separator,
..\app\srs_app_bandwidth.hpp,
..\app\srs_app_bandwidth.cpp,
..\app\srs_app_client.hpp,
..\app\srs_app_client.cpp,
..\app\srs_app_codec.hpp,
..\app\srs_app_codec.cpp,
..\app\srs_app_conn.hpp,
..\app\srs_app_conn.cpp,
..\app\srs_app_config.hpp,
..\app\srs_app_config.cpp,
..\app\srs_app_encoder.hpp,
..\app\srs_app_encoder.cpp,
..\app\srs_app_forward.hpp,
..\app\srs_app_forward.cpp,
..\app\srs_app_hls.hpp,
..\app\srs_app_hls.cpp,
..\app\srs_app_http.hpp,
..\app\srs_app_http.cpp,
..\app\srs_app_log.hpp,
..\app\srs_app_log.cpp,
..\app\srs_app_refer.hpp,
..\app\srs_app_refer.cpp,
..\app\srs_app_reload.hpp,
..\app\srs_app_reload.cpp,
..\app\srs_app_pithy_print.hpp,
..\app\srs_app_pithy_print.cpp,
..\app\srs_app_thread.hpp,
..\app\srs_app_thread.cpp,
..\app\srs_app_server.hpp,
..\app\srs_app_server.cpp,
..\app\srs_app_st.hpp,
..\app\srs_app_st.cpp,
..\app\srs_app_socket.hpp,
..\app\srs_app_socket.cpp,
..\app\srs_app_source.hpp,
..\app\srs_app_source.cpp,
utest readonly separator,
..\utest\srs_utest.hpp,
..\utest\srs_utest.cpp,
..\utest\srs_utest_amf0.hpp,
..\utest\srs_utest_amf0.cpp,
research readonly separator,
..\..\research\librtmp\srs_play.c,
..\..\research\librtmp\srs_publish.c,
..\..\research\hls\ts_info.cc;
main readonly separator,
..\main\srs_main_server.cpp,
..\main\srs_main_bandcheck.cpp,
auto readonly separator,
..\..\objs\srs_auto_headers.hpp,
libs readonly separator,
..\libs\srs_librtmp.hpp,
..\libs\srs_librtmp.cpp,
..\libs\srs_lib_simple_socket.hpp,
..\libs\srs_lib_simple_socket.cpp,
core readonly separator,
..\core\srs_core.hpp,
..\core\srs_core.cpp,
..\core\srs_core_autofree.hpp,
..\core\srs_core_autofree.cpp,
kernel readonly separator,
..\kernel\srs_kernel_buffer.hpp,
..\kernel\srs_kernel_buffer.cpp,
..\kernel\srs_kernel_error.hpp,
..\kernel\srs_kernel_error.cpp,
..\kernel\srs_kernel_log.hpp,
..\kernel\srs_kernel_log.cpp,
..\kernel\srs_kernel_stream.hpp,
..\kernel\srs_kernel_stream.cpp,
rtmp-protocol readonly separator,
..\rtmp\srs_protocol_amf0.hpp,
..\rtmp\srs_protocol_amf0.cpp,
..\rtmp\srs_protocol_handshake.hpp,
..\rtmp\srs_protocol_handshake.cpp,
..\rtmp\srs_protocol_io.hpp,
..\rtmp\srs_protocol_io.cpp,
..\rtmp\srs_protocol_rtmp.hpp,
..\rtmp\srs_protocol_rtmp.cpp,
..\rtmp\srs_protocol_rtmp_stack.hpp,
..\rtmp\srs_protocol_rtmp_stack.cpp,
..\rtmp\srs_protocol_utility.hpp,
..\rtmp\srs_protocol_utility.cpp,
app readonly separator,
..\app\srs_app_bandwidth.hpp,
..\app\srs_app_bandwidth.cpp,
..\app\srs_app_client.hpp,
..\app\srs_app_client.cpp,
..\app\srs_app_codec.hpp,
..\app\srs_app_codec.cpp,
..\app\srs_app_conn.hpp,
..\app\srs_app_conn.cpp,
..\app\srs_app_config.hpp,
..\app\srs_app_config.cpp,
..\app\srs_app_encoder.hpp,
..\app\srs_app_encoder.cpp,
..\app\srs_app_forward.hpp,
..\app\srs_app_forward.cpp,
..\app\srs_app_hls.hpp,
..\app\srs_app_hls.cpp,
..\app\srs_app_http.hpp,
..\app\srs_app_http.cpp,
..\app\srs_app_log.hpp,
..\app\srs_app_log.cpp,
..\app\srs_app_refer.hpp,
..\app\srs_app_refer.cpp,
..\app\srs_app_reload.hpp,
..\app\srs_app_reload.cpp,
..\app\srs_app_pithy_print.hpp,
..\app\srs_app_pithy_print.cpp,
..\app\srs_app_thread.hpp,
..\app\srs_app_thread.cpp,
..\app\srs_app_server.hpp,
..\app\srs_app_server.cpp,
..\app\srs_app_st.hpp,
..\app\srs_app_st.cpp,
..\app\srs_app_socket.hpp,
..\app\srs_app_socket.cpp,
..\app\srs_app_source.hpp,
..\app\srs_app_source.cpp,
utest readonly separator,
..\utest\srs_utest.hpp,
..\utest\srs_utest.cpp,
..\utest\srs_utest_amf0.hpp,
..\utest\srs_utest_amf0.cpp,
research readonly separator,
..\..\research\librtmp\srs_play.c,
..\..\research\librtmp\srs_publish.c,
..\..\research\hls\ts_info.cc;
mainconfig
"" = "MAIN";
"" = "MAIN";

View file

@ -39,30 +39,30 @@ SrsServer* _srs_server = NULL;
// basic test and samples.
VOID TEST(SampleTest, FastSampleInt64Test)
{
EXPECT_EQ(1, (int)sizeof(int8_t));
EXPECT_EQ(2, (int)sizeof(int16_t));
EXPECT_EQ(4, (int)sizeof(int32_t));
EXPECT_EQ(8, (int)sizeof(int64_t));
EXPECT_EQ(1, (int)sizeof(int8_t));
EXPECT_EQ(2, (int)sizeof(int16_t));
EXPECT_EQ(4, (int)sizeof(int32_t));
EXPECT_EQ(8, (int)sizeof(int64_t));
}
VOID TEST(SampleTest, FastSampleMacrosTest)
{
EXPECT_TRUE(1);
EXPECT_FALSE(0);
EXPECT_EQ(1, 1); // ==
EXPECT_NE(1, 2); // !=
EXPECT_LE(1, 2); // <=
EXPECT_LT(1, 2); // <
EXPECT_GE(2, 1); // >=
EXPECT_GT(2, 1); // >
EXPECT_TRUE(1);
EXPECT_FALSE(0);
EXPECT_EQ(1, 1); // ==
EXPECT_NE(1, 2); // !=
EXPECT_LE(1, 2); // <=
EXPECT_LT(1, 2); // <
EXPECT_GE(2, 1); // >=
EXPECT_GT(2, 1); // >
EXPECT_STREQ("winlin", "winlin");
EXPECT_STRNE("winlin", "srs");
EXPECT_STRCASEEQ("winlin", "Winlin");
EXPECT_STRCASENE("winlin", "srs");
EXPECT_FLOAT_EQ(1.0, 1.000000000000001);
EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001);
EXPECT_NEAR(10, 15, 5);
EXPECT_STREQ("winlin", "winlin");
EXPECT_STRNE("winlin", "srs");
EXPECT_STRCASEEQ("winlin", "Winlin");
EXPECT_STRCASENE("winlin", "srs");
EXPECT_FLOAT_EQ(1.0, 1.000000000000001);
EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001);
EXPECT_NEAR(10, 15, 5);
}

File diff suppressed because it is too large Load diff