Merge branch '2.0release' into develop

pull/499/head
winlin 10 years ago
commit 5d75e32e1d

@ -348,7 +348,8 @@ Remark:
### SRS 2.0 history ### SRS 2.0 history
* v2.0, 2015-05-30, fix [#420](https://github.com/simple-rtmp-server/srs/issues/420) remove ts for hls ram mode. * v2.0, 2015-06-06, fix [#421](https://github.com/simple-rtmp-server/srs/issues/421) drop video for unkown RTMP header.
* v2.0, 2015-06-05, fix [#420](https://github.com/simple-rtmp-server/srs/issues/420) remove ts for hls ram mode.
* v2.0, 2015-05-30, fix [#209](https://github.com/simple-rtmp-server/srs/issues/209) cleanup hls when stop and timeout. 2.0.173. * v2.0, 2015-05-30, fix [#209](https://github.com/simple-rtmp-server/srs/issues/209) cleanup hls when stop and timeout. 2.0.173.
* v2.0, 2015-05-29, fix [#409](https://github.com/simple-rtmp-server/srs/issues/409) support pure video hls. 2.0.172. * v2.0, 2015-05-29, fix [#409](https://github.com/simple-rtmp-server/srs/issues/409) support pure video hls. 2.0.172.
* v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS. * v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS.

@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_AUTO_INGEST #ifdef SRS_AUTO_INGEST
#include <stdlib.h>
using namespace std; using namespace std;
#include <srs_kernel_error.hpp> #include <srs_kernel_error.hpp>
@ -39,11 +40,9 @@ using namespace std;
// ingest never sleep a long time, for we must start the stream ASAP. // ingest never sleep a long time, for we must start the stream ASAP.
#define SRS_AUTO_INGESTER_SLEEP_US (int64_t)(3*1000*1000LL) #define SRS_AUTO_INGESTER_SLEEP_US (int64_t)(3*1000*1000LL)
SrsIngesterFFMPEG::SrsIngesterFFMPEG(SrsFFMPEG* _ffmpeg, string _vhost, string _id) SrsIngesterFFMPEG::SrsIngesterFFMPEG()
{ {
ffmpeg = _ffmpeg; ffmpeg = NULL;
vhost = _vhost;
id = _id;
} }
SrsIngesterFFMPEG::~SrsIngesterFFMPEG() SrsIngesterFFMPEG::~SrsIngesterFFMPEG()
@ -51,6 +50,53 @@ SrsIngesterFFMPEG::~SrsIngesterFFMPEG()
srs_freep(ffmpeg); srs_freep(ffmpeg);
} }
int SrsIngesterFFMPEG::initialize(SrsFFMPEG* ff, string v, string i)
{
int ret = ERROR_SUCCESS;
ffmpeg = ff;
vhost = v;
id = i;
starttime = srs_get_system_time_ms();
return ret;
}
string SrsIngesterFFMPEG::uri()
{
return vhost + "/" + id;
}
int SrsIngesterFFMPEG::alive()
{
return (int)(srs_get_system_time_ms() - starttime);
}
bool SrsIngesterFFMPEG::equals(string v)
{
return vhost == v;
}
bool SrsIngesterFFMPEG::equals(string v, string i)
{
return vhost == v && id == i;
}
int SrsIngesterFFMPEG::start()
{
return ffmpeg->start();
}
void SrsIngesterFFMPEG::stop()
{
ffmpeg->stop();
}
int SrsIngesterFFMPEG::cycle()
{
return ffmpeg->cycle();
}
void SrsIngesterFFMPEG::fast_stop() void SrsIngesterFFMPEG::fast_stop()
{ {
ffmpeg->fast_stop(); ffmpeg->fast_stop();
@ -129,6 +175,8 @@ int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest
// get all engines. // get all engines.
std::vector<SrsConfDirective*> engines = _srs_config->get_transcode_engines(ingest); std::vector<SrsConfDirective*> engines = _srs_config->get_transcode_engines(ingest);
// create ingesters without engines.
if (engines.empty()) { if (engines.empty()) {
SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin);
if ((ret = initialize_ffmpeg(ffmpeg, vhost, ingest, NULL)) != ERROR_SUCCESS) { if ((ret = initialize_ffmpeg(ffmpeg, vhost, ingest, NULL)) != ERROR_SUCCESS) {
@ -139,12 +187,17 @@ int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest
return ret; return ret;
} }
SrsIngesterFFMPEG* ingester = new SrsIngesterFFMPEG(ffmpeg, vhost->arg0(), ingest->arg0()); SrsIngesterFFMPEG* ingester = new SrsIngesterFFMPEG();
if ((ret = ingester->initialize(ffmpeg, vhost->arg0(), ingest->arg0())) != ERROR_SUCCESS) {
srs_freep(ingester);
return ret;
}
ingesters.push_back(ingester); ingesters.push_back(ingester);
return ret; return ret;
} }
// create engine // create ingesters with engine
for (int i = 0; i < (int)engines.size(); i++) { for (int i = 0; i < (int)engines.size(); i++) {
SrsConfDirective* engine = engines[i]; SrsConfDirective* engine = engines[i];
SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin);
@ -156,8 +209,13 @@ int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest
} }
return ret; return ret;
} }
SrsIngesterFFMPEG* ingester = new SrsIngesterFFMPEG();
if ((ret = ingester->initialize(ffmpeg, vhost->arg0(), ingest->arg0())) != ERROR_SUCCESS) {
srs_freep(ingester);
return ret;
}
SrsIngesterFFMPEG* ingester = new SrsIngesterFFMPEG(ffmpeg, vhost->arg0(), ingest->arg0());
ingesters.push_back(ingester); ingesters.push_back(ingester);
} }
@ -196,13 +254,13 @@ int SrsIngester::cycle()
SrsIngesterFFMPEG* ingester = *it; SrsIngesterFFMPEG* ingester = *it;
// start all ffmpegs. // start all ffmpegs.
if ((ret = ingester->ffmpeg->start()) != ERROR_SUCCESS) { if ((ret = ingester->start()) != ERROR_SUCCESS) {
srs_error("ingest ffmpeg start failed. ret=%d", ret); srs_error("ingest ffmpeg start failed. ret=%d", ret);
return ret; return ret;
} }
// check ffmpeg status. // check ffmpeg status.
if ((ret = ingester->ffmpeg->cycle()) != ERROR_SUCCESS) { if ((ret = ingester->cycle()) != ERROR_SUCCESS) {
srs_error("ingest ffmpeg cycle failed. ret=%d", ret); srs_error("ingest ffmpeg cycle failed. ret=%d", ret);
return ret; return ret;
} }
@ -376,11 +434,14 @@ void SrsIngester::show_ingest_log_message()
return; return;
} }
// random choose one ingester to report.
int index = rand() % (int)ingesters.size();
SrsIngesterFFMPEG* ingester = ingesters.at(index);
// reportable // reportable
if (pprint->can_print()) { if (pprint->can_print()) {
// TODO: FIXME: show more info. srs_trace("-> "SRS_CONSTS_LOG_INGESTER" time=%"PRId64", ingesters=%d, #%d(alive=%ds, %s)",
srs_trace("-> "SRS_CONSTS_LOG_INGESTER pprint->age(), (int)ingesters.size(), index, ingester->alive() / 1000, ingester->uri().c_str());
" time=%"PRId64", ingesters=%d", pprint->age(), (int)ingesters.size());
} }
} }
@ -407,16 +468,15 @@ int SrsIngester::on_reload_vhost_removed(string vhost)
for (it = ingesters.begin(); it != ingesters.end();) { for (it = ingesters.begin(); it != ingesters.end();) {
SrsIngesterFFMPEG* ingester = *it; SrsIngesterFFMPEG* ingester = *it;
if (ingester->vhost != vhost) { if (!ingester->equals(vhost)) {
++it; ++it;
continue; continue;
} }
// stop the ffmpeg and free it. // stop the ffmpeg and free it.
ingester->ffmpeg->stop(); ingester->stop();
srs_trace("reload stop ingester, " srs_trace("reload stop ingester, vhost=%s, id=%s", vhost.c_str(), ingester->uri().c_str());
"vhost=%s, id=%s", vhost.c_str(), ingester->id.c_str());
srs_freep(ingester); srs_freep(ingester);
@ -436,16 +496,15 @@ int SrsIngester::on_reload_ingest_removed(string vhost, string ingest_id)
for (it = ingesters.begin(); it != ingesters.end();) { for (it = ingesters.begin(); it != ingesters.end();) {
SrsIngesterFFMPEG* ingester = *it; SrsIngesterFFMPEG* ingester = *it;
if (ingester->vhost != vhost || ingester->id != ingest_id) { if (!ingester->equals(vhost, ingest_id)) {
++it; ++it;
continue; continue;
} }
// stop the ffmpeg and free it. // stop the ffmpeg and free it.
ingester->ffmpeg->stop(); ingester->stop();
srs_trace("reload stop ingester, " srs_trace("reload stop ingester, vhost=%s, id=%s", vhost.c_str(), ingester->uri().c_str());
"vhost=%s, id=%s", vhost.c_str(), ingester->id.c_str());
srs_freep(ingester); srs_freep(ingester);

@ -45,14 +45,26 @@ class SrsPithyPrint;
*/ */
class SrsIngesterFFMPEG class SrsIngesterFFMPEG
{ {
public: private:
std::string vhost; std::string vhost;
std::string id; std::string id;
SrsFFMPEG* ffmpeg; SrsFFMPEG* ffmpeg;
int64_t starttime;
SrsIngesterFFMPEG(SrsFFMPEG* _ffmpeg, std::string _vhost, std::string _id); public:
SrsIngesterFFMPEG();
virtual ~SrsIngesterFFMPEG(); virtual ~SrsIngesterFFMPEG();
public:
virtual int initialize(SrsFFMPEG* ff, std::string v, std::string i);
// the ingest uri, [vhost]/[ingest id]
virtual std::string uri();
// the alive in ms.
virtual int alive();
virtual bool equals(std::string v, std::string i);
virtual bool equals(std::string v);
public:
virtual int start();
virtual void stop();
virtual int cycle();
// @see SrsFFMPEG.fast_stop(). // @see SrsFFMPEG.fast_stop().
virtual void fast_stop(); virtual void fast_stop();
}; };

@ -61,8 +61,9 @@ public:
*/ */
virtual bool can_handle() = 0; virtual bool can_handle() = 0;
/** /**
* process the received message. * process the received message.
*/ * @remark user must free this message.
*/
virtual int handle(SrsCommonMessage* msg) = 0; virtual int handle(SrsCommonMessage* msg) = 0;
/** /**
* when recv message error. * when recv message error.

@ -916,7 +916,6 @@ int SrsRtmpConn::handle_publish_message(SrsSource* source, SrsCommonMessage* msg
srs_error("fmle decode unpublish message failed. ret=%d", ret); srs_error("fmle decode unpublish message failed. ret=%d", ret);
return ret; return ret;
} }
SrsAutoFree(SrsPacket, pkt); SrsAutoFree(SrsPacket, pkt);
// for flash, any packet is republish. // for flash, any packet is republish.

@ -604,15 +604,15 @@ int SrsGopCache::cache(SrsSharedPtrMessage* shared_msg)
// the gop cache know when to gop it. // the gop cache know when to gop it.
SrsSharedPtrMessage* msg = shared_msg; SrsSharedPtrMessage* msg = shared_msg;
// disable gop cache when not h.264
if (!SrsFlvCodec::video_is_h264(msg->payload, msg->size)) {
srs_info("gop donot cache video for none h.264");
return ret;
}
// got video, update the video count if acceptable // got video, update the video count if acceptable
if (msg->is_video()) { if (msg->is_video()) {
// drop video when not h.264
if (!SrsFlvCodec::video_is_h264(msg->payload, msg->size)) {
srs_info("gop cache drop video for none h.264");
return ret;
}
cached_video_count++; cached_video_count++;
audio_after_last_video_count = 0; audio_after_last_video_count = 0;
} }
@ -1464,11 +1464,25 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
} }
srs_info("Audio dts=%"PRId64", size=%d", msg.timestamp, msg.size); srs_info("Audio dts=%"PRId64", size=%d", msg.timestamp, msg.size);
// directly process the audio message.
if (!mix_correct) { if (!mix_correct) {
return on_audio_imp(&msg); return on_audio_imp(&msg);
} }
return do_mix_correct(&msg); // insert msg to the queue.
mix_queue->push(msg.copy());
// fetch someone from mix queue.
SrsSharedPtrMessage* m = mix_queue->pop();
if (!m) {
return ret;
}
// consume the monotonically increase message.
ret = on_audio_imp(m);
srs_freep(m);
return ret;
} }
int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg) int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
@ -1619,6 +1633,18 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// drop any unknown header video.
// @see https://github.com/simple-rtmp-server/srs/issues/421
if (!SrsFlvCodec::video_is_acceptable(shared_video->payload, shared_video->size)) {
char b0 = 0x00;
if (shared_video->size > 0) {
b0 = shared_video->payload[0];
}
srs_warn("drop unknown header video, size=%d, bytes[0]=%#x", shared_video->size, b0);
return ret;
}
// convert shared_video to msg, user should not use shared_video again. // convert shared_video to msg, user should not use shared_video again.
// the payload is transfer to msg, and set to NULL in shared_video. // the payload is transfer to msg, and set to NULL in shared_video.
SrsSharedPtrMessage msg; SrsSharedPtrMessage msg;
@ -1628,11 +1654,26 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
} }
srs_info("Video dts=%"PRId64", size=%d", msg.timestamp, msg.size); srs_info("Video dts=%"PRId64", size=%d", msg.timestamp, msg.size);
// directly process the audio message.
if (!mix_correct) { if (!mix_correct) {
return on_video_imp(&msg); return on_video_imp(&msg);
} }
return do_mix_correct(&msg); // insert msg to the queue.
mix_queue->push(msg.copy());
// fetch someone from mix queue.
SrsSharedPtrMessage* m = mix_queue->pop();
if (!m) {
return ret;
}
SrsAutoFree(SrsSharedPtrMessage, m);
// consume the monotonically increase message.
ret = on_video_imp(m);
srs_freep(m);
return ret;
} }
int SrsSource::on_video_imp(SrsSharedPtrMessage* msg) int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
@ -1766,29 +1807,6 @@ int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
return ret; return ret;
} }
int SrsSource::do_mix_correct(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
// insert msg to the queue.
mix_queue->push(msg->copy());
// fetch someone from mix queue.
SrsSharedPtrMessage* m = mix_queue->pop();
if (!m) {
return ret;
}
SrsAutoFree(SrsSharedPtrMessage, m);
// consume the monotonically increase message.
if (m->is_audio()) {
return on_audio_imp(m);
}
srs_assert(m->is_video());
return on_video_imp(m);
}
int SrsSource::on_aggregate(SrsCommonMessage* msg) int SrsSource::on_aggregate(SrsCommonMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;

@ -536,8 +536,6 @@ public:
virtual int on_video(SrsCommonMessage* video); virtual int on_video(SrsCommonMessage* video);
private: private:
virtual int on_video_imp(SrsSharedPtrMessage* video); virtual int on_video_imp(SrsSharedPtrMessage* video);
private:
virtual int do_mix_correct(SrsSharedPtrMessage* msg);
public: public:
virtual int on_aggregate(SrsCommonMessage* msg); virtual int on_aggregate(SrsCommonMessage* msg);
/** /**

@ -266,6 +266,28 @@ bool SrsFlvCodec::audio_is_aac(char* data, int size)
return sound_format == SrsCodecAudioAAC; return sound_format == SrsCodecAudioAAC;
} }
bool SrsFlvCodec::video_is_acceptable(char* data, int size)
{
// 1bytes required.
if (size < 1) {
return false;
}
char frame_type = data[0];
char codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
if (frame_type < 1 || frame_type > 5) {
return false;
}
if (codec_id < 2 || codec_id > 7) {
return false;
}
return true;
}
string srs_codec_avc_nalu2str(SrsAvcNaluType nalu_type) string srs_codec_avc_nalu2str(SrsAvcNaluType nalu_type)
{ {
switch (nalu_type) { switch (nalu_type) {

@ -222,6 +222,12 @@ public:
* check codec aac. * check codec aac.
*/ */
static bool audio_is_aac(char* data, int size); static bool audio_is_aac(char* data, int size);
/**
* check the video RTMP/flv header info,
* @return true if video RTMP/flv header is ok.
* @remark all type of audio is possible, no need to check audio.
*/
static bool video_is_acceptable(char* data, int size);
}; };
/** /**

@ -97,8 +97,8 @@ void SrsFastBuffer::set_buffer(int buffer_size)
} }
// realloc for buffer change bigger. // realloc for buffer change bigger.
int start = p - buffer; int start = (int)(p - buffer);
int nb_bytes = end - p; int nb_bytes = (int)(end - p);
buffer = (char*)realloc(buffer, nb_resize_buf); buffer = (char*)realloc(buffer, nb_resize_buf);
nb_buffer = nb_resize_buf; nb_buffer = nb_resize_buf;

Loading…
Cancel
Save