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

For #913: TS/HLS/MPEGTS support complex error

This commit is contained in:
winlin 2017-09-22 21:50:54 +08:00
parent 20a42599f3
commit abcaba33ee
24 changed files with 699 additions and 823 deletions

View file

@ -56,14 +56,14 @@ SrsAsyncCallWorker::~SrsAsyncCallWorker()
srs_cond_destroy(wait); srs_cond_destroy(wait);
} }
int SrsAsyncCallWorker::execute(ISrsAsyncCallTask* t) srs_error_t SrsAsyncCallWorker::execute(ISrsAsyncCallTask* t)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
tasks.push_back(t); tasks.push_back(t);
srs_cond_signal(wait); srs_cond_signal(wait);
return ret; return err;
} }
int SrsAsyncCallWorker::count() int SrsAsyncCallWorker::count()

View file

@ -74,7 +74,7 @@ public:
SrsAsyncCallWorker(); SrsAsyncCallWorker();
virtual ~SrsAsyncCallWorker(); virtual ~SrsAsyncCallWorker();
public: public:
virtual int execute(ISrsAsyncCallTask* t); virtual srs_error_t execute(ISrsAsyncCallTask* t);
virtual int count(); virtual int count();
public: public:
virtual srs_error_t start(); virtual srs_error_t start();

View file

@ -85,6 +85,7 @@ SrsFragmentedMp4::~SrsFragmentedMp4()
int SrsFragmentedMp4::initialize(SrsRequest* r, bool video, SrsMpdWriter* mpd, uint32_t tid) int SrsFragmentedMp4::initialize(SrsRequest* r, bool video, SrsMpdWriter* mpd, uint32_t tid)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
string file_home; string file_home;
string file_name; string file_name;
@ -97,7 +98,10 @@ int SrsFragmentedMp4::initialize(SrsRequest* r, bool video, SrsMpdWriter* mpd, u
string home = _srs_config->get_dash_path(r->vhost); string home = _srs_config->get_dash_path(r->vhost);
set_path(home + "/" + file_home + "/" + file_name); set_path(home + "/" + file_home + "/" + file_name);
if ((ret = create_dir()) != ERROR_SUCCESS) { if ((err = create_dir()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -146,6 +150,7 @@ int SrsFragmentedMp4::write(SrsSharedPtrMessage* shared_msg, SrsFormat* format)
int SrsFragmentedMp4::reap(uint64_t& dts) int SrsFragmentedMp4::reap(uint64_t& dts)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if ((ret = enc->flush(dts)) != ERROR_SUCCESS) { if ((ret = enc->flush(dts)) != ERROR_SUCCESS) {
srs_error("DASH: Flush encoder failed, ret=%d", ret); srs_error("DASH: Flush encoder failed, ret=%d", ret);
@ -154,7 +159,10 @@ int SrsFragmentedMp4::reap(uint64_t& dts)
srs_freep(fw); srs_freep(fw);
if ((ret = rename()) != ERROR_SUCCESS) { if ((err = rename()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -191,6 +199,7 @@ srs_error_t SrsMpdWriter::initialize(SrsRequest* r)
int SrsMpdWriter::write(SrsFormat* format) int SrsMpdWriter::write(SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// MPD is not expired? // MPD is not expired?
if (last_update_mpd != -1 && srs_get_system_time_ms() - last_update_mpd < update_period) { if (last_update_mpd != -1 && srs_get_system_time_ms() - last_update_mpd < update_period) {
@ -204,7 +213,10 @@ int SrsMpdWriter::write(SrsFormat* format)
fragment_home = srs_path_dirname(mpd_path) + "/" + req->stream; fragment_home = srs_path_dirname(mpd_path) + "/" + req->stream;
if ((ret = srs_create_dir_recursively(full_home)) != ERROR_SUCCESS) { if ((err = srs_create_dir_recursively(full_home)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("DASH: Create MPD home failed, home=%s, ret=%d", full_home.c_str(), ret); srs_error("DASH: Create MPD home failed, home=%s, ret=%d", full_home.c_str(), ret);
return ret; return ret;
} }
@ -427,6 +439,7 @@ int SrsDashController::refresh_mpd(SrsFormat* format)
int SrsDashController::refresh_init_mp4(SrsSharedPtrMessage* msg, SrsFormat* format) int SrsDashController::refresh_init_mp4(SrsSharedPtrMessage* msg, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if (msg->size <= 0 || (msg->is_video() && !format->vcodec->is_avc_codec_ok()) if (msg->size <= 0 || (msg->is_video() && !format->vcodec->is_avc_codec_ok())
|| (msg->is_audio() && !format->acodec->is_aac_codec_ok())) { || (msg->is_audio() && !format->acodec->is_aac_codec_ok())) {
@ -435,7 +448,10 @@ int SrsDashController::refresh_init_mp4(SrsSharedPtrMessage* msg, SrsFormat* for
} }
string full_home = home + "/" + req->app + "/" + req->stream; string full_home = home + "/" + req->app + "/" + req->stream;
if ((ret = srs_create_dir_recursively(full_home)) != ERROR_SUCCESS) { if ((err = srs_create_dir_recursively(full_home)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("DASH: Create media home failed, home=%s, ret=%d", full_home.c_str(), ret); srs_error("DASH: Create media home failed, home=%s, ret=%d", full_home.c_str(), ret);
return ret; return ret;
} }
@ -457,7 +473,10 @@ int SrsDashController::refresh_init_mp4(SrsSharedPtrMessage* msg, SrsFormat* for
return ret; return ret;
} }
if ((ret = init_mp4->rename()) != ERROR_SUCCESS) { if ((err = init_mp4->rename()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }

View file

@ -84,6 +84,7 @@ SrsFragment* SrsDvrSegmenter::current()
int SrsDvrSegmenter::open() int SrsDvrSegmenter::open()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// ignore when already open. // ignore when already open.
if (fs->is_open()) { if (fs->is_open()) {
@ -99,7 +100,10 @@ int SrsDvrSegmenter::open()
fragment->set_path(path); fragment->set_path(path);
// create dir first. // create dir first.
if ((ret = fragment->create_dir()) != ERROR_SUCCESS) { if ((err = fragment->create_dir()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -177,6 +181,7 @@ int SrsDvrSegmenter::write_video(SrsSharedPtrMessage* shared_video, SrsFormat* f
int SrsDvrSegmenter::close() int SrsDvrSegmenter::close()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// ignore when already closed. // ignore when already closed.
if (!fs->is_open()) { if (!fs->is_open()) {
@ -191,13 +196,19 @@ int SrsDvrSegmenter::close()
fs->close(); fs->close();
// when tmp flv file exists, reap it. // when tmp flv file exists, reap it.
if ((ret = fragment->rename()) != ERROR_SUCCESS) { if ((err = fragment->rename()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
// TODO: FIXME: the http callback is async, which will trigger thread switch, // TODO: FIXME: the http callback is async, which will trigger thread switch,
// so the on_video maybe invoked during the http callback, and error. // so the on_video maybe invoked during the http callback, and error.
if ((ret = plan->on_reap_segment()) != ERROR_SUCCESS) { if ((err = plan->on_reap_segment()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("dvr: notify plan to reap segment failed. ret=%d", ret); srs_error("dvr: notify plan to reap segment failed. ret=%d", ret);
return ret; return ret;
} }
@ -669,20 +680,20 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
return ret; return ret;
} }
int SrsDvrPlan::on_reap_segment() srs_error_t SrsDvrPlan::on_reap_segment()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
int cid = _srs_context->get_id(); int cid = _srs_context->get_id();
SrsFragment* fragment = segment->current(); SrsFragment* fragment = segment->current();
string fullpath = fragment->fullpath(); string fullpath = fragment->fullpath();
if ((ret = async->execute(new SrsDvrAsyncCallOnDvr(cid, req, fullpath))) != ERROR_SUCCESS) { if ((err = async->execute(new SrsDvrAsyncCallOnDvr(cid, req, fullpath))) != srs_success) {
return ret; return srs_error_wrap(err, "reap segment");
} }
return ret; return err;
} }
srs_error_t SrsDvrPlan::create_plan(string vhost, SrsDvrPlan** pplan) srs_error_t SrsDvrPlan::create_plan(string vhost, SrsDvrPlan** pplan)

View file

@ -203,7 +203,7 @@ public:
// Internal interface for segmenter. // Internal interface for segmenter.
public: public:
// When segmenter close a segment. // When segmenter close a segment.
virtual int on_reap_segment(); virtual srs_error_t on_reap_segment();
public: public:
static srs_error_t create_plan(std::string vhost, SrsDvrPlan** pplan); static srs_error_t create_plan(std::string vhost, SrsDvrPlan** pplan);
}; };

View file

@ -158,12 +158,16 @@ void SrsForwarder::on_unpublish()
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata) int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsSharedPtrMessage* metadata = shared_metadata->copy(); SrsSharedPtrMessage* metadata = shared_metadata->copy();
// TODO: FIXME: config the jitter of Forwarder. // TODO: FIXME: config the jitter of Forwarder.
if ((ret = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { if ((err = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_freep(metadata); srs_freep(metadata);
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -177,12 +181,16 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata)
int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio) int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsSharedPtrMessage* msg = shared_audio->copy(); SrsSharedPtrMessage* msg = shared_audio->copy();
// TODO: FIXME: config the jitter of Forwarder. // TODO: FIXME: config the jitter of Forwarder.
if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { if ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_freep(msg); srs_freep(msg);
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -201,12 +209,16 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio)
int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video) int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsSharedPtrMessage* msg = shared_video->copy(); SrsSharedPtrMessage* msg = shared_video->copy();
// TODO: FIXME: config the jitter of Forwarder. // TODO: FIXME: config the jitter of Forwarder.
if ((ret = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { if ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_freep(msg); srs_freep(msg);
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }

View file

@ -77,33 +77,30 @@ void SrsFragment::set_path(string v)
filepath = v; filepath = v;
} }
int SrsFragment::unlink_file() srs_error_t SrsFragment::unlink_file()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (::unlink(filepath.c_str()) < 0) { if (::unlink(filepath.c_str()) < 0) {
ret = ERROR_SYSTEM_FRAGMENT_UNLINK; return srs_error_new(ERROR_SYSTEM_FRAGMENT_UNLINK, "unlink %s", filepath.c_str());
srs_error("Unlink fragment failed, file=%s, ret=%d.", filepath.c_str(), ret);
return ret;
} }
return ret; return err;
} }
int SrsFragment::create_dir() srs_error_t SrsFragment::create_dir()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
std::string segment_dir = srs_path_dirname(filepath); std::string segment_dir = srs_path_dirname(filepath);
if ((ret = srs_create_dir_recursively(segment_dir)) != ERROR_SUCCESS) { if ((err = srs_create_dir_recursively(segment_dir)) != srs_success) {
srs_error("Create dir %s failed. ret=%d", segment_dir.c_str(), ret); return srs_error_wrap(err, "create %s", segment_dir.c_str());
return ret;
} }
srs_info("Create dir %s ok", segment_dir.c_str()); srs_info("Create dir %s ok", segment_dir.c_str());
return ret; return err;
} }
string SrsFragment::tmppath() string SrsFragment::tmppath()
@ -111,34 +108,30 @@ string SrsFragment::tmppath()
return filepath + ".tmp"; return filepath + ".tmp";
} }
int SrsFragment::unlink_tmpfile() srs_error_t SrsFragment::unlink_tmpfile()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
string filepath = tmppath(); string filepath = tmppath();
if (::unlink(filepath.c_str()) < 0) { if (::unlink(filepath.c_str()) < 0) {
ret = ERROR_SYSTEM_FRAGMENT_UNLINK; return srs_error_new(ERROR_SYSTEM_FRAGMENT_UNLINK, "unlink tmp file %s", filepath.c_str());
srs_error("Unlink temporary fragment failed, file=%s, ret=%d.", filepath.c_str(), ret);
return ret;
} }
return ret; return err;
} }
int SrsFragment::rename() srs_error_t SrsFragment::rename()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
string full_path = fullpath(); string full_path = fullpath();
string tmp_file = tmppath(); string tmp_file = tmppath();
if (::rename(tmp_file.c_str(), full_path.c_str()) < 0) { if (::rename(tmp_file.c_str(), full_path.c_str()) < 0) {
ret = ERROR_SYSTEM_FRAGMENT_RENAME; return srs_error_new(ERROR_SYSTEM_FRAGMENT_RENAME, "rename %s to %s", tmp_file.c_str(), full_path.c_str());
srs_error("rename ts file failed, %s => %s. ret=%d", tmp_file.c_str(), full_path.c_str(), ret);
return ret;
} }
return ret; return err;
} }
SrsFragmentWindow::SrsFragmentWindow() SrsFragmentWindow::SrsFragmentWindow()
@ -164,14 +157,15 @@ SrsFragmentWindow::~SrsFragmentWindow()
void SrsFragmentWindow::dispose() void SrsFragmentWindow::dispose()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
std::vector<SrsFragment*>::iterator it; std::vector<SrsFragment*>::iterator it;
for (it = fragments.begin(); it != fragments.end(); ++it) { for (it = fragments.begin(); it != fragments.end(); ++it) {
SrsFragment* fragment = *it; SrsFragment* fragment = *it;
if ((ret = fragment->unlink_file()) != ERROR_SUCCESS) { if ((err = fragment->unlink_file()) != srs_success) {
srs_warn("Unlink ts failed, file=%s, ret=%d", fragment->fullpath().c_str(), ret); srs_warn("Unlink ts failed %s", srs_error_desc(err).c_str());
srs_freep(err);
} }
srs_freep(fragment); srs_freep(fragment);
} }
@ -179,8 +173,9 @@ void SrsFragmentWindow::dispose()
for (it = expired_fragments.begin(); it != expired_fragments.end(); ++it) { for (it = expired_fragments.begin(); it != expired_fragments.end(); ++it) {
SrsFragment* fragment = *it; SrsFragment* fragment = *it;
if ((ret = fragment->unlink_file()) != ERROR_SUCCESS) { if ((err = fragment->unlink_file()) != srs_success) {
srs_warn("Unlink ts failed, file=%s, ret=%d", fragment->fullpath().c_str(), ret); srs_warn("Unlink ts failed %s", srs_error_desc(err).c_str());
srs_freep(err);
} }
srs_freep(fragment); srs_freep(fragment);
} }
@ -217,14 +212,15 @@ void SrsFragmentWindow::shrink(int64_t window)
void SrsFragmentWindow::clear_expired(bool delete_files) void SrsFragmentWindow::clear_expired(bool delete_files)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
std::vector<SrsFragment*>::iterator it; std::vector<SrsFragment*>::iterator it;
for (it = expired_fragments.begin(); it != expired_fragments.end(); ++it) { for (it = expired_fragments.begin(); it != expired_fragments.end(); ++it) {
SrsFragment* fragment = *it; SrsFragment* fragment = *it;
if (delete_files && (ret = fragment->unlink_file()) != ERROR_SUCCESS) { if (delete_files && (err = fragment->unlink_file()) != srs_success) {
srs_warn("Unlink ts failed, file=%s, ret=%d", fragment->fullpath().c_str(), ret); srs_warn("Unlink ts failed, %s", srs_error_desc(err).c_str());
srs_freep(err);
} }
srs_freep(fragment); srs_freep(fragment);
} }

View file

@ -63,16 +63,16 @@ public:
virtual void set_path(std::string v); virtual void set_path(std::string v);
// Unlink the fragment, to delete the file. // Unlink the fragment, to delete the file.
// @remark Ignore any error. // @remark Ignore any error.
virtual int unlink_file(); virtual srs_error_t unlink_file();
// Create the dir for file recursively. // Create the dir for file recursively.
virtual int create_dir(); virtual srs_error_t create_dir();
public: public:
// Get the temporary path for file. // Get the temporary path for file.
virtual std::string tmppath(); virtual std::string tmppath();
// Unlink the temporary file. // Unlink the temporary file.
virtual int unlink_tmpfile(); virtual srs_error_t unlink_tmpfile();
// Rename the temp file to final file. // Rename the temp file to final file.
virtual int rename(); virtual srs_error_t rename();
}; };
/** /**

View file

@ -433,6 +433,7 @@ int SrsHds::on_audio(SrsSharedPtrMessage* msg)
int SrsHds::flush_mainfest() int SrsHds::flush_mainfest()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
char buf[1024] = {0}; char buf[1024] = {0};
sprintf(buf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" sprintf(buf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
@ -446,7 +447,10 @@ int SrsHds::flush_mainfest()
, hds_req->stream.c_str(), hds_req->stream.c_str(), hds_req->stream.c_str()); , hds_req->stream.c_str(), hds_req->stream.c_str(), hds_req->stream.c_str());
string dir = _srs_config->get_hds_path(hds_req->vhost) + "/" + hds_req->app; string dir = _srs_config->get_hds_path(hds_req->vhost) + "/" + hds_req->app;
if ((ret = srs_create_dir_recursively(dir)) != ERROR_SUCCESS) { if ((err = srs_create_dir_recursively(dir)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("hds create dir failed. ret=%d", ret); srs_error("hds create dir failed. ret=%d", ret);
return ret; return ret;
} }

View file

@ -210,13 +210,14 @@ SrsHlsMuxer::~SrsHlsMuxer()
void SrsHlsMuxer::dispose() void SrsHlsMuxer::dispose()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
segments->dispose(); segments->dispose();
if (current) { if (current) {
if ((ret = current->unlink_tmpfile()) != ERROR_SUCCESS) { if ((err = current->unlink_tmpfile()) != srs_success) {
srs_warn("Unlink tmp ts failed, ret=%d", ret); srs_warn("Unlink tmp ts failed %s", srs_error_desc(err).c_str());
srs_freep(err);
} }
srs_freep(current); srs_freep(current);
} }
@ -264,11 +265,11 @@ srs_error_t SrsHlsMuxer::initialize()
return err; return err;
} }
int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix, srs_error_t SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
string path, string m3u8_file, string ts_file, double fragment, double window, string path, string m3u8_file, string ts_file, double fragment, double window,
bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe
) { ) {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
srs_freep(req); srs_freep(req);
req = r->copy(); req = r->copy();
@ -295,22 +296,21 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
// create m3u8 dir once. // create m3u8 dir once.
m3u8_dir = srs_path_dirname(m3u8); m3u8_dir = srs_path_dirname(m3u8);
if ((ret = srs_create_dir_recursively(m3u8_dir)) != ERROR_SUCCESS) { if ((err = srs_create_dir_recursively(m3u8_dir)) != srs_success) {
srs_error("create app dir %s failed. ret=%d", m3u8_dir.c_str(), ret); return srs_error_wrap(err, "create dir");
return ret;
} }
srs_info("create m3u8 dir %s ok", m3u8_dir.c_str()); srs_info("create m3u8 dir %s ok", m3u8_dir.c_str());
return ret; return err;
} }
int SrsHlsMuxer::segment_open() srs_error_t SrsHlsMuxer::segment_open()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (current) { if (current) {
srs_warn("ignore the segment open, for segment is already open."); srs_warn("ignore the segment open, for segment is already open.");
return ret; return err;
} }
// when segment open, the current segment must be NULL. // when segment open, the current segment must be NULL.
@ -421,24 +421,23 @@ int SrsHlsMuxer::segment_open()
current->uri += ts_url; current->uri += ts_url;
// create dir recursively for hls. // create dir recursively for hls.
if ((ret = current->create_dir()) != ERROR_SUCCESS) { if ((err = current->create_dir()) != srs_success) {
return ret; return srs_error_wrap(err, "create dir");
} }
// open temp ts file. // open temp ts file.
std::string tmp_file = current->tmppath(); std::string tmp_file = current->tmppath();
if ((ret = current->tscw->open(tmp_file.c_str())) != ERROR_SUCCESS) { if ((err = current->tscw->open(tmp_file.c_str())) != srs_success) {
srs_error("open hls muxer failed. ret=%d", ret); return srs_error_wrap(err, "open hls muxer");
return ret;
} }
srs_info("open HLS muxer success. path=%s, tmp=%s", current->fullpath().c_str(), tmp_file.c_str()); srs_info("open HLS muxer success. path=%s, tmp=%s", current->fullpath().c_str(), tmp_file.c_str());
return ret; return err;
} }
int SrsHlsMuxer::on_sequence_header() srs_error_t SrsHlsMuxer::on_sequence_header()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
srs_assert(current); srs_assert(current);
@ -446,7 +445,7 @@ int SrsHlsMuxer::on_sequence_header()
// when close the segement, it will write a discontinuity to m3u8 file. // when close the segement, it will write a discontinuity to m3u8 file.
current->set_sequence_header(true); current->set_sequence_header(true);
return ret; return err;
} }
bool SrsHlsMuxer::is_segment_overflow() bool SrsHlsMuxer::is_segment_overflow()
@ -494,45 +493,45 @@ bool SrsHlsMuxer::pure_audio()
return current && current->tscw && current->tscw->video_codec() == SrsVideoCodecIdDisabled; return current && current->tscw && current->tscw->video_codec() == SrsVideoCodecIdDisabled;
} }
int SrsHlsMuxer::flush_audio(SrsTsMessageCache* cache) srs_error_t SrsHlsMuxer::flush_audio(SrsTsMessageCache* cache)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// if current is NULL, segment is not open, ignore the flush event. // if current is NULL, segment is not open, ignore the flush event.
if (!current) { if (!current) {
srs_warn("flush audio ignored, for segment is not open."); srs_warn("flush audio ignored, for segment is not open.");
return ret; return err;
} }
if (!cache->audio || cache->audio->payload->length() <= 0) { if (!cache->audio || cache->audio->payload->length() <= 0) {
return ret; return err;
} }
// update the duration of segment. // update the duration of segment.
current->append(cache->audio->pts / 90); current->append(cache->audio->pts / 90);
if ((ret = current->tscw->write_audio(cache->audio)) != ERROR_SUCCESS) { if ((err = current->tscw->write_audio(cache->audio)) != srs_success) {
return ret; return srs_error_wrap(err, "hls: write audio");
} }
// write success, clear and free the msg // write success, clear and free the msg
srs_freep(cache->audio); srs_freep(cache->audio);
return ret; return err;
} }
int SrsHlsMuxer::flush_video(SrsTsMessageCache* cache) srs_error_t SrsHlsMuxer::flush_video(SrsTsMessageCache* cache)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// if current is NULL, segment is not open, ignore the flush event. // if current is NULL, segment is not open, ignore the flush event.
if (!current) { if (!current) {
srs_warn("flush video ignored, for segment is not open."); srs_warn("flush video ignored, for segment is not open.");
return ret; return err;
} }
if (!cache->video || cache->video->payload->length() <= 0) { if (!cache->video || cache->video->payload->length() <= 0) {
return ret; return err;
} }
srs_assert(current); srs_assert(current);
@ -540,23 +539,23 @@ int SrsHlsMuxer::flush_video(SrsTsMessageCache* cache)
// update the duration of segment. // update the duration of segment.
current->append(cache->video->dts / 90); current->append(cache->video->dts / 90);
if ((ret = current->tscw->write_video(cache->video)) != ERROR_SUCCESS) { if ((err = current->tscw->write_video(cache->video)) != srs_success) {
return ret; return srs_error_wrap(err, "hls: write video");
} }
// write success, clear and free the msg // write success, clear and free the msg
srs_freep(cache->video); srs_freep(cache->video);
return ret; return err;
} }
int SrsHlsMuxer::segment_close() srs_error_t SrsHlsMuxer::segment_close()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!current) { if (!current) {
srs_warn("ignore the segment close, for segment is not open."); srs_warn("ignore the segment close, for segment is not open.");
return ret; return err;
} }
// when close current segment, the current segment must not be NULL. // when close current segment, the current segment must not be NULL.
@ -568,17 +567,14 @@ int SrsHlsMuxer::segment_close()
// make the segment more acceptable, when in [min, max_td * 2], it's ok. // make the segment more acceptable, when in [min, max_td * 2], it's ok.
if (current->duration() >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS && (int)current->duration() <= max_td * 2 * 1000) { if (current->duration() >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS && (int)current->duration() <= max_td * 2 * 1000) {
// use async to call the http hooks, for it will cause thread switch. // use async to call the http hooks, for it will cause thread switch.
if ((ret = async->execute(new SrsDvrAsyncCallOnHls( if ((err = async->execute(new SrsDvrAsyncCallOnHls(_srs_context->get_id(), req, current->fullpath(),
_srs_context->get_id(), req, current->uri, m3u8, m3u8_url, current->sequence_no, current->duration() / 1000.0))) != srs_success) {
current->fullpath(), current->uri, m3u8, m3u8_url, return srs_error_wrap(err, "segment close");
current->sequence_no, current->duration() / 1000.0))) != ERROR_SUCCESS)
{
return ret;
} }
// use async to call the http hooks, for it will cause thread switch. // use async to call the http hooks, for it will cause thread switch.
if ((ret = async->execute(new SrsDvrAsyncCallOnHlsNotify(_srs_context->get_id(), req, current->uri))) != ERROR_SUCCESS) { if ((err = async->execute(new SrsDvrAsyncCallOnHlsNotify(_srs_context->get_id(), req, current->uri))) != srs_success) {
return ret; return srs_error_wrap(err, "segment close");
} }
srs_info("Reap ts segment, sequence_no=%d, uri=%s, duration=%" PRId64 "ms", current->sequence_no, current->uri.c_str(), current->duration()); srs_info("Reap ts segment, sequence_no=%d, uri=%s, duration=%" PRId64 "ms", current->sequence_no, current->uri.c_str(), current->duration());
@ -586,8 +582,8 @@ int SrsHlsMuxer::segment_close()
srs_freep(current->tscw); srs_freep(current->tscw);
// rename from tmp to real path // rename from tmp to real path
if ((ret = current->rename()) != ERROR_SUCCESS) { if ((err = current->rename()) != srs_success) {
return ret; return srs_error_wrap(err, "rename");
} }
segments->append(current); segments->append(current);
@ -599,8 +595,8 @@ int SrsHlsMuxer::segment_close()
srs_trace("Drop ts segment, sequence_no=%d, uri=%s, duration=%" PRId64 "ms", current->sequence_no, current->uri.c_str(), current->duration()); srs_trace("Drop ts segment, sequence_no=%d, uri=%s, duration=%" PRId64 "ms", current->sequence_no, current->uri.c_str(), current->duration());
// rename from tmp to real path // rename from tmp to real path
if ((ret = current->unlink_tmpfile()) != ERROR_SUCCESS) { if ((err = current->unlink_tmpfile()) != srs_success) {
return ret; return srs_error_wrap(err, "rename");
} }
srs_freep(current); srs_freep(current);
} }
@ -609,34 +605,32 @@ int SrsHlsMuxer::segment_close()
segments->shrink(hls_window * 1000); segments->shrink(hls_window * 1000);
// refresh the m3u8, donot contains the removed ts // refresh the m3u8, donot contains the removed ts
ret = refresh_m3u8(); err = refresh_m3u8();
// remove the ts file. // remove the ts file.
segments->clear_expired(hls_cleanup); segments->clear_expired(hls_cleanup);
// check ret of refresh m3u8 // check ret of refresh m3u8
if (ret != ERROR_SUCCESS) { if (err != srs_success) {
srs_error("refresh m3u8 failed. ret=%d", ret); return srs_error_wrap(err, "hls: refresh m3u8");
return ret;
} }
return ret; return err;
} }
int SrsHlsMuxer::refresh_m3u8() srs_error_t SrsHlsMuxer::refresh_m3u8()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// no segments, also no m3u8, return. // no segments, also no m3u8, return.
if (segments->empty()) { if (segments->empty()) {
return ret; return err;
} }
std::string temp_m3u8 = m3u8 + ".temp"; std::string temp_m3u8 = m3u8 + ".temp";
if ((ret = _refresh_m3u8(temp_m3u8)) == ERROR_SUCCESS) { if ((err = _refresh_m3u8(temp_m3u8)) == srs_success) {
if (rename(temp_m3u8.c_str(), m3u8.c_str()) < 0) { if (rename(temp_m3u8.c_str(), m3u8.c_str()) < 0) {
ret = ERROR_HLS_WRITE_FAILED; err = srs_error_new(ERROR_HLS_WRITE_FAILED, "hls: rename m3u8 file failed. %s => %s", temp_m3u8.c_str(), m3u8.c_str());
srs_error("rename m3u8 file failed. %s => %s, ret=%d", temp_m3u8.c_str(), m3u8.c_str(), ret);
} }
} }
@ -647,22 +641,22 @@ int SrsHlsMuxer::refresh_m3u8()
} }
} }
return ret; return err;
} }
int SrsHlsMuxer::_refresh_m3u8(string m3u8_file) srs_error_t SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// no segments, return. // no segments, return.
if (segments->empty()) { if (segments->empty()) {
return ret; return err;
} }
SrsFileWriter writer; SrsFileWriter writer;
if ((ret = writer.open(m3u8_file)) != ERROR_SUCCESS) { if ((ret = writer.open(m3u8_file)) != ERROR_SUCCESS) {
srs_error("open m3u8 file %s failed. ret=%d", m3u8_file.c_str(), ret); return srs_error_new(ret, "hls: open m3u8 file %s", m3u8_file.c_str());
return ret;
} }
srs_info("open m3u8 file %s success.", m3u8_file.c_str()); srs_info("open m3u8 file %s success.", m3u8_file.c_str());
@ -723,12 +717,11 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
// write m3u8 to writer. // write m3u8 to writer.
std::string m3u8 = ss.str(); std::string m3u8 = ss.str();
if ((ret = writer.write((char*)m3u8.c_str(), (int)m3u8.length(), NULL)) != ERROR_SUCCESS) { if ((ret = writer.write((char*)m3u8.c_str(), (int)m3u8.length(), NULL)) != ERROR_SUCCESS) {
srs_error("write m3u8 failed. ret=%d", ret); return srs_error_new(ret, "hls: write m3u8");
return ret;
} }
srs_info("write m3u8 %s success.", m3u8_file.c_str()); srs_info("write m3u8 %s success.", m3u8_file.c_str());
return ret; return err;
} }
SrsHlsController::SrsHlsController() SrsHlsController::SrsHlsController()
@ -777,9 +770,9 @@ int SrsHlsController::deviation()
return muxer->deviation(); return muxer->deviation();
} }
int SrsHlsController::on_publish(SrsRequest* req) srs_error_t SrsHlsController::on_publish(SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
std::string vhost = req->vhost; std::string vhost = req->vhost;
std::string stream = req->stream; std::string stream = req->stream;
@ -807,42 +800,37 @@ int SrsHlsController::on_publish(SrsRequest* req)
// for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase. // for the HLS donot requires the EXT-X-MEDIA-SEQUENCE be monotonically increase.
// open muxer // open muxer
if ((ret = muxer->update_config(req, entry_prefix, if ((err = muxer->update_config(req, entry_prefix, path, m3u8_file, ts_file, hls_fragment,
path, m3u8_file, ts_file, hls_fragment, hls_window, ts_floor, hls_aof_ratio, hls_window, ts_floor, hls_aof_ratio, cleanup, wait_keyframe)) != srs_success ) {
cleanup, wait_keyframe)) != ERROR_SUCCESS return srs_error_wrap(err, "hls: update config");
) {
srs_error("m3u8 muxer update config failed. ret=%d", ret);
return ret;
} }
if ((ret = muxer->segment_open()) != ERROR_SUCCESS) { if ((err = muxer->segment_open()) != srs_success) {
srs_error("m3u8 muxer open segment failed. ret=%d", ret); return srs_error_wrap(err, "hls: segment open");
return ret;
} }
srs_trace("hls: win=%.2f, frag=%.2f, prefix=%s, path=%s, m3u8=%s, ts=%s, aof=%.2f, floor=%d, clean=%d, waitk=%d, dispose=%d", srs_trace("hls: win=%.2f, frag=%.2f, prefix=%s, path=%s, m3u8=%s, ts=%s, aof=%.2f, floor=%d, clean=%d, waitk=%d, dispose=%d",
hls_window, hls_fragment, entry_prefix.c_str(), path.c_str(), m3u8_file.c_str(), hls_window, hls_fragment, entry_prefix.c_str(), path.c_str(), m3u8_file.c_str(),
ts_file.c_str(), hls_aof_ratio, ts_floor, cleanup, wait_keyframe, hls_dispose); ts_file.c_str(), hls_aof_ratio, ts_floor, cleanup, wait_keyframe, hls_dispose);
return ret; return err;
} }
int SrsHlsController::on_unpublish() srs_error_t SrsHlsController::on_unpublish()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if ((ret = muxer->flush_audio(tsmc)) != ERROR_SUCCESS) { if ((err = muxer->flush_audio(tsmc)) != srs_success) {
srs_error("m3u8 muxer flush audio failed. ret=%d", ret); return srs_error_wrap(err, "hls: flush audio");
return ret;
} }
if ((ret = muxer->segment_close()) != ERROR_SUCCESS) { if ((err = muxer->segment_close()) != srs_success) {
return ret; return srs_error_wrap(err, "hls: segment close");
} }
return ret; return err;
} }
int SrsHlsController::on_sequence_header() srs_error_t SrsHlsController::on_sequence_header()
{ {
// TODO: support discontinuity for the same stream // TODO: support discontinuity for the same stream
// currently we reap and insert discontinity when encoder republish, // currently we reap and insert discontinity when encoder republish,
@ -853,13 +841,13 @@ int SrsHlsController::on_sequence_header()
return muxer->on_sequence_header(); return muxer->on_sequence_header();
} }
int SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts) srs_error_t SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// write audio to cache. // write audio to cache.
if ((ret = tsmc->cache_audio(frame, pts)) != ERROR_SUCCESS) { if ((err = tsmc->cache_audio(frame, pts)) != srs_success) {
return ret; return srs_error_wrap(err, "hls: cache audio");
} }
// reap when current source is pure audio. // reap when current source is pure audio.
@ -871,9 +859,8 @@ int SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts)
// we use absolutely overflow of segment to make jwplayer/ffplay happy // we use absolutely overflow of segment to make jwplayer/ffplay happy
// @see https://github.com/ossrs/srs/issues/151#issuecomment-71155184 // @see https://github.com/ossrs/srs/issues/151#issuecomment-71155184
if (tsmc->audio && muxer->is_segment_absolutely_overflow()) { if (tsmc->audio && muxer->is_segment_absolutely_overflow()) {
srs_info("hls: absolute audio reap segment."); if ((err = reap_segment()) != srs_success) {
if ((ret = reap_segment()) != ERROR_SUCCESS) { return srs_error_wrap(err, "hls: reap segment");
return ret;
} }
} }
@ -881,7 +868,7 @@ int SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts)
// TODO: FIXME: Check whether it's necessary. // TODO: FIXME: Check whether it's necessary.
if (muxer->pure_audio() && tsmc->audio) { if (muxer->pure_audio() && tsmc->audio) {
if (pts - tsmc->audio->start_pts < SRS_CONSTS_HLS_PURE_AUDIO_AGGREGATE) { if (pts - tsmc->audio->start_pts < SRS_CONSTS_HLS_PURE_AUDIO_AGGREGATE) {
return ret; return err;
} }
} }
@ -889,20 +876,20 @@ int SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts)
// it's ok for the hls overload, or maybe cause the audio corrupt, // it's ok for the hls overload, or maybe cause the audio corrupt,
// which introduced by aggregate the audios to a big one. // which introduced by aggregate the audios to a big one.
// @see https://github.com/ossrs/srs/issues/512 // @see https://github.com/ossrs/srs/issues/512
if ((ret = muxer->flush_audio(tsmc)) != ERROR_SUCCESS) { if ((err = muxer->flush_audio(tsmc)) != srs_success) {
return ret; return srs_error_wrap(err, "hls: flush audio");
} }
return ret; return err;
} }
int SrsHlsController::write_video(SrsVideoFrame* frame, int64_t dts) srs_error_t SrsHlsController::write_video(SrsVideoFrame* frame, int64_t dts)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// write video to cache. // write video to cache.
if ((ret = tsmc->cache_video(frame, dts)) != ERROR_SUCCESS) { if ((err = tsmc->cache_video(frame, dts)) != srs_success) {
return ret; return srs_error_wrap(err, "hls: cache video");
} }
// when segment overflow, reap if possible. // when segment overflow, reap if possible.
@ -912,55 +899,50 @@ int SrsHlsController::write_video(SrsVideoFrame* frame, int64_t dts)
// b. always reap when not wait keyframe. // b. always reap when not wait keyframe.
if (!muxer->wait_keyframe() || frame->frame_type == SrsVideoAvcFrameTypeKeyFrame) { if (!muxer->wait_keyframe() || frame->frame_type == SrsVideoAvcFrameTypeKeyFrame) {
// reap the segment, which will also flush the video. // reap the segment, which will also flush the video.
if ((ret = reap_segment()) != ERROR_SUCCESS) { if ((err = reap_segment()) != srs_success) {
return ret; return srs_error_wrap(err, "hls: reap segment");
} }
} }
} }
// flush video when got one // flush video when got one
if ((ret = muxer->flush_video(tsmc)) != ERROR_SUCCESS) { if ((err = muxer->flush_video(tsmc)) != srs_success) {
srs_error("m3u8 muxer flush video failed. ret=%d", ret); return srs_error_wrap(err, "hls: flush video");
return ret;
} }
return ret; return err;
} }
int SrsHlsController::reap_segment() srs_error_t SrsHlsController::reap_segment()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// TODO: flush audio before or after segment? // TODO: flush audio before or after segment?
// TODO: fresh segment begin with audio or video? // TODO: fresh segment begin with audio or video?
// close current ts. // close current ts.
if ((ret = muxer->segment_close()) != ERROR_SUCCESS) { if ((err = muxer->segment_close()) != srs_success) {
srs_error("m3u8 muxer close segment failed. ret=%d", ret); return srs_error_wrap(err, "hls: segment close");
return ret;
} }
// open new ts. // open new ts.
if ((ret = muxer->segment_open()) != ERROR_SUCCESS) { if ((err = muxer->segment_open()) != srs_success) {
srs_error("m3u8 muxer open segment failed. ret=%d", ret); return srs_error_wrap(err, "hls: segment open");
return ret;
} }
// segment open, flush video first. // segment open, flush video first.
if ((ret = muxer->flush_video(tsmc)) != ERROR_SUCCESS) { if ((err = muxer->flush_video(tsmc)) != srs_success) {
srs_error("m3u8 muxer flush video failed. ret=%d", ret); return srs_error_wrap(err, "hls: flush video");
return ret;
} }
// segment open, flush the audio. // segment open, flush the audio.
// @see: ngx_rtmp_hls_open_fragment // @see: ngx_rtmp_hls_open_fragment
/* start fragment with audio to make iPhone happy */ /* start fragment with audio to make iPhone happy */
if ((ret = muxer->flush_audio(tsmc)) != ERROR_SUCCESS) { if ((err = muxer->flush_audio(tsmc)) != srs_success) {
srs_error("m3u8 muxer flush audio failed. ret=%d", ret); return srs_error_wrap(err, "hls: flush audio");
return ret;
} }
return ret; return err;
} }
SrsHls::SrsHls() SrsHls::SrsHls()
@ -1050,24 +1032,24 @@ srs_error_t SrsHls::initialize(SrsOriginHub* h, SrsRequest* r)
return err; return err;
} }
int SrsHls::on_publish() srs_error_t SrsHls::on_publish()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// update the hls time, for hls_dispose. // update the hls time, for hls_dispose.
last_update_time = srs_get_system_time_ms(); last_update_time = srs_get_system_time_ms();
// support multiple publish. // support multiple publish.
if (enabled) { if (enabled) {
return ret; return err;
} }
if (!_srs_config->get_hls_enabled(req->vhost)) { if (!_srs_config->get_hls_enabled(req->vhost)) {
return ret; return err;
} }
if ((ret = controller->on_publish(req)) != ERROR_SUCCESS) { if ((err = controller->on_publish(req)) != srs_success) {
return ret; return srs_error_wrap(err, "hls: on publish");
} }
// if enabled, open the muxer. // if enabled, open the muxer.
@ -1076,31 +1058,32 @@ int SrsHls::on_publish()
// ok, the hls can be dispose, or need to be dispose. // ok, the hls can be dispose, or need to be dispose.
disposable = true; disposable = true;
return ret; return err;
} }
void SrsHls::on_unpublish() void SrsHls::on_unpublish()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// support multiple unpublish. // support multiple unpublish.
if (!enabled) { if (!enabled) {
return; return;
} }
if ((ret = controller->on_unpublish()) != ERROR_SUCCESS) { if ((err = controller->on_unpublish()) != srs_success) {
srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret); srs_warn("hls: ignore unpublish failed %s", srs_error_desc(err).c_str());
srs_freep(err);
} }
enabled = false; enabled = false;
} }
int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format) srs_error_t SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!enabled) { if (!enabled) {
return ret; return err;
} }
// update the hls time, for hls_dispose. // update the hls time, for hls_dispose.
@ -1113,7 +1096,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
srs_assert(format->acodec); srs_assert(format->acodec);
SrsAudioCodecId acodec = format->acodec->id; SrsAudioCodecId acodec = format->acodec->id;
if (acodec != SrsAudioCodecIdAAC && acodec != SrsAudioCodecIdMP3) { if (acodec != SrsAudioCodecIdAAC && acodec != SrsAudioCodecIdMP3) {
return ret; return err;
} }
// ignore sequence header // ignore sequence header
@ -1123,9 +1106,8 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
} }
// TODO: FIXME: config the jitter of HLS. // TODO: FIXME: config the jitter of HLS.
if ((ret = jitter->correct(audio, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { if ((err = jitter->correct(audio, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_error("rtmp jitter correct audio failed. ret=%d", ret); return srs_error_wrap(err, "hls: jitter");
return ret;
} }
// Reset the aac samples counter when DTS jitter. // Reset the aac samples counter when DTS jitter.
@ -1145,20 +1127,19 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
int64_t dts = 90000 * aac_samples / srs_flv_srates[format->acodec->sound_rate]; int64_t dts = 90000 * aac_samples / srs_flv_srates[format->acodec->sound_rate];
aac_samples += nb_samples_per_frame; aac_samples += nb_samples_per_frame;
if ((ret = controller->write_audio(format->audio, dts)) != ERROR_SUCCESS) { if ((err = controller->write_audio(format->audio, dts)) != srs_success) {
srs_error("hls cache write audio failed. ret=%d", ret); return srs_error_wrap(err, "hls: write audio");
return ret;
} }
return ret; return err;
} }
int SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format) srs_error_t SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!enabled) { if (!enabled) {
return ret; return err;
} }
// update the hls time, for hls_dispose. // update the hls time, for hls_dispose.
@ -1171,12 +1152,12 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909 // @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
srs_assert(format->video); srs_assert(format->video);
if (format->video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) { if (format->video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) {
return ret; return err;
} }
srs_assert(format->vcodec); srs_assert(format->vcodec);
if (format->vcodec->id != SrsVideoCodecIdAVC) { if (format->vcodec->id != SrsVideoCodecIdAVC) {
return ret; return err;
} }
// ignore sequence header // ignore sequence header
@ -1185,21 +1166,19 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
} }
// TODO: FIXME: config the jitter of HLS. // TODO: FIXME: config the jitter of HLS.
if ((ret = jitter->correct(video, SrsRtmpJitterAlgorithmOFF)) != ERROR_SUCCESS) { if ((err = jitter->correct(video, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_error("rtmp jitter correct video failed. ret=%d", ret); return srs_error_wrap(err, "hls: jitter");
return ret;
} }
int64_t dts = video->timestamp * 90; int64_t dts = video->timestamp * 90;
if ((ret = controller->write_video(format->video, dts)) != ERROR_SUCCESS) { if ((err = controller->write_video(format->video, dts)) != srs_success) {
srs_error("hls cache write video failed. ret=%d", ret); return srs_error_wrap(err, "hls: write video");
return ret;
} }
// pithy print message. // pithy print message.
hls_show_mux_log(); hls_show_mux_log();
return ret; return err;
} }
void SrsHls::hls_show_mux_log() void SrsHls::hls_show_mux_log()

View file

@ -179,15 +179,15 @@ public:
/** /**
* when publish, update the config for muxer. * when publish, update the config for muxer.
*/ */
virtual int update_config(SrsRequest* r, std::string entry_prefix, virtual srs_error_t update_config(SrsRequest* r, std::string entry_prefix,
std::string path, std::string m3u8_file, std::string ts_file, std::string path, std::string m3u8_file, std::string ts_file,
double fragment, double window, bool ts_floor, double aof_ratio, double fragment, double window, bool ts_floor, double aof_ratio,
bool cleanup, bool wait_keyframe); bool cleanup, bool wait_keyframe);
/** /**
* open a new segment(a new ts file) * open a new segment(a new ts file)
*/ */
virtual int segment_open(); virtual srs_error_t segment_open();
virtual int on_sequence_header(); virtual srs_error_t on_sequence_header();
/** /**
* whether segment overflow, * whether segment overflow,
* that is whether the current segment duration>=(the segment in config) * that is whether the current segment duration>=(the segment in config)
@ -208,15 +208,15 @@ public:
* whether current hls muxer is pure audio mode. * whether current hls muxer is pure audio mode.
*/ */
virtual bool pure_audio(); virtual bool pure_audio();
virtual int flush_audio(SrsTsMessageCache* cache); virtual srs_error_t flush_audio(SrsTsMessageCache* cache);
virtual int flush_video(SrsTsMessageCache* cache); virtual srs_error_t flush_video(SrsTsMessageCache* cache);
/** /**
* Close segment(ts). * Close segment(ts).
*/ */
virtual int segment_close(); virtual srs_error_t segment_close();
private: private:
virtual int refresh_m3u8(); virtual srs_error_t refresh_m3u8();
virtual int _refresh_m3u8(std::string m3u8_file); virtual srs_error_t _refresh_m3u8(std::string m3u8_file);
}; };
/** /**
@ -258,23 +258,23 @@ public:
/** /**
* when publish or unpublish stream. * when publish or unpublish stream.
*/ */
virtual int on_publish(SrsRequest* req); virtual srs_error_t on_publish(SrsRequest* req);
virtual int on_unpublish(); virtual srs_error_t on_unpublish();
/** /**
* when get sequence header, * when get sequence header,
* must write a #EXT-X-DISCONTINUITY to m3u8. * must write a #EXT-X-DISCONTINUITY to m3u8.
* @see: hls-m3u8-draft-pantos-http-live-streaming-12.txt * @see: hls-m3u8-draft-pantos-http-live-streaming-12.txt
* @see: 3.4.11. EXT-X-DISCONTINUITY * @see: 3.4.11. EXT-X-DISCONTINUITY
*/ */
virtual int on_sequence_header(); virtual srs_error_t on_sequence_header();
/** /**
* write audio to cache, if need to flush, flush to muxer. * write audio to cache, if need to flush, flush to muxer.
*/ */
virtual int write_audio(SrsAudioFrame* frame, int64_t pts); virtual srs_error_t write_audio(SrsAudioFrame* frame, int64_t pts);
/** /**
* write video to muxer. * write video to muxer.
*/ */
virtual int write_video(SrsVideoFrame* frame, int64_t dts); virtual srs_error_t write_video(SrsVideoFrame* frame, int64_t dts);
private: private:
/** /**
* reopen the muxer for a new hls segment, * reopen the muxer for a new hls segment,
@ -282,7 +282,7 @@ private:
* then write the key frame to the new segment. * then write the key frame to the new segment.
* so, user must reap_segment then flush_video to hls muxer. * so, user must reap_segment then flush_video to hls muxer.
*/ */
virtual int reap_segment(); virtual srs_error_t reap_segment();
}; };
/** /**
@ -324,7 +324,7 @@ public:
* for the muxer object not destroyed. * for the muxer object not destroyed.
* @param fetch_sequence_header whether fetch sequence from source. * @param fetch_sequence_header whether fetch sequence from source.
*/ */
virtual int on_publish(); virtual srs_error_t on_publish();
/** /**
* the unpublish event, only close the muxer, donot destroy the * the unpublish event, only close the muxer, donot destroy the
* muxer, for when we continue to publish, the m3u8 will continue. * muxer, for when we continue to publish, the m3u8 will continue.
@ -334,14 +334,14 @@ public:
* mux the audio packets to ts. * mux the audio packets to ts.
* @param shared_audio, directly ptr, copy it if need to save it. * @param shared_audio, directly ptr, copy it if need to save it.
*/ */
virtual int on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format);
/** /**
* mux the video packets to ts. * mux the video packets to ts.
* @param shared_video, directly ptr, copy it if need to save it. * @param shared_video, directly ptr, copy it if need to save it.
* @param is_sps_pps whether the video is h.264 sps/pps. * @param is_sps_pps whether the video is h.264 sps/pps.
*/ */
// TODO: FIXME: Remove param is_sps_pps. // TODO: FIXME: Remove param is_sps_pps.
virtual int on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
private: private:
virtual void hls_show_mux_log(); virtual void hls_show_mux_log();
}; };

View file

@ -203,8 +203,12 @@ SrsTsStreamEncoder::~SrsTsStreamEncoder()
int SrsTsStreamEncoder::initialize(SrsFileWriter* w, SrsBufferCache* /*c*/) int SrsTsStreamEncoder::initialize(SrsFileWriter* w, SrsBufferCache* /*c*/)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if ((ret = enc->initialize(w)) != ERROR_SUCCESS) { if ((err = enc->initialize(w)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -213,12 +217,20 @@ int SrsTsStreamEncoder::initialize(SrsFileWriter* w, SrsBufferCache* /*c*/)
int SrsTsStreamEncoder::write_audio(int64_t timestamp, char* data, int size) int SrsTsStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
{ {
return enc->write_audio(timestamp, data, size); srs_error_t err = enc->write_audio(timestamp, data, size);
// TODO: FIXME: Use error
int ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
int SrsTsStreamEncoder::write_video(int64_t timestamp, char* data, int size) int SrsTsStreamEncoder::write_video(int64_t timestamp, char* data, int size)
{ {
return enc->write_video(timestamp, data, size); srs_error_t err = enc->write_video(timestamp, data, size);
// TODO: FIXME: Use error
int ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
int SrsTsStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/) int SrsTsStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)

View file

@ -460,12 +460,12 @@ int SrsKafkaProducer::send(int key, SrsJsonObject* obj)
return ret; return ret;
} }
int SrsKafkaProducer::on_client(int key, SrsListenerType type, string ip) srs_error_t SrsKafkaProducer::on_client(int key, SrsListenerType type, string ip)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!enabled) { if (!enabled) {
return ret; return err;
} }
SrsJsonObject* obj = SrsJsonAny::object(); SrsJsonObject* obj = SrsJsonAny::object();
@ -477,12 +477,12 @@ int SrsKafkaProducer::on_client(int key, SrsListenerType type, string ip)
return worker->execute(new SrsKafkaMessage(this, key, obj)); return worker->execute(new SrsKafkaMessage(this, key, obj));
} }
int SrsKafkaProducer::on_close(int key) srs_error_t SrsKafkaProducer::on_close(int key)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!enabled) { if (!enabled) {
return ret; return err;
} }
SrsJsonObject* obj = SrsJsonAny::object(); SrsJsonObject* obj = SrsJsonAny::object();

View file

@ -141,12 +141,12 @@ public:
* @param type the type of client. * @param type the type of client.
* @param ip the peer ip of client. * @param ip the peer ip of client.
*/ */
virtual int on_client(int key, SrsListenerType type, std::string ip) = 0; virtual srs_error_t on_client(int key, SrsListenerType type, std::string ip) = 0;
/** /**
* when client close or disconnect for error. * when client close or disconnect for error.
* @param key the partition map key, the client id or hash(ip). * @param key the partition map key, the client id or hash(ip).
*/ */
virtual int on_close(int key) = 0; virtual srs_error_t on_close(int key) = 0;
}; };
// @global kafka event producer. // @global kafka event producer.
@ -192,8 +192,8 @@ public:
virtual int send(int key, SrsJsonObject* obj); virtual int send(int key, SrsJsonObject* obj);
// interface ISrsKafkaCluster // interface ISrsKafkaCluster
public: public:
virtual int on_client(int key, SrsListenerType type, std::string ip); virtual srs_error_t on_client(int key, SrsListenerType type, std::string ip);
virtual int on_close(int key); virtual srs_error_t on_close(int key);
// interface ISrsReusableThreadHandler // interface ISrsReusableThreadHandler
public: public:
virtual srs_error_t cycle(); virtual srs_error_t cycle();

View file

@ -178,6 +178,7 @@ srs_error_t SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb
int SrsMpegtsOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf) int SrsMpegtsOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// collect nMB data to parse in a time. // collect nMB data to parse in a time.
// TODO: FIXME: comment the following for release. // TODO: FIXME: comment the following for release.
@ -237,7 +238,10 @@ int SrsMpegtsOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf)
} }
// process each ts packet // process each ts packet
if ((ret = context->decode(stream, this)) != ERROR_SUCCESS) { if ((err = context->decode(stream, this)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_warn("mpegts: ignore parse ts packet failed. ret=%d", ret); srs_warn("mpegts: ignore parse ts packet failed. ret=%d", ret);
continue; continue;
} }
@ -253,9 +257,10 @@ int SrsMpegtsOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf)
return ret; return ret;
} }
int SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg) srs_error_t SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
pprint->elapse(); pprint->elapse();
@ -311,36 +316,35 @@ int SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg)
// when not audio/video, or not adts/annexb format, donot support. // when not audio/video, or not adts/annexb format, donot support.
if (msg->stream_number() != 0) { if (msg->stream_number() != 0) {
ret = ERROR_STREAM_CASTER_TS_ES; return srs_error_new(ERROR_STREAM_CASTER_TS_ES, "ts: unsupported stream format, sid=%#x(%s-%d)",
srs_error("mpegts: unsupported stream format, sid=%#x(%s-%d). ret=%d", msg->sid, msg->is_audio()? "A":msg->is_video()? "V":"N", msg->stream_number());
msg->sid, msg->is_audio()? "A":msg->is_video()? "V":"N", msg->stream_number(), ret);
return ret;
} }
// check supported codec // check supported codec
if (msg->channel->stream != SrsTsStreamVideoH264 && msg->channel->stream != SrsTsStreamAudioAAC) { if (msg->channel->stream != SrsTsStreamVideoH264 && msg->channel->stream != SrsTsStreamAudioAAC) {
ret = ERROR_STREAM_CASTER_TS_CODEC; return srs_error_new(ERROR_STREAM_CASTER_TS_CODEC, "ts: unsupported stream codec=%d", msg->channel->stream);
srs_error("mpegts: unsupported stream codec=%d. ret=%d", msg->channel->stream, ret);
return ret;
} }
// parse the stream. // parse the stream.
SrsBuffer avs; SrsBuffer avs;
if ((ret = avs.initialize(msg->payload->bytes(), msg->payload->length())) != ERROR_SUCCESS) { if ((ret = avs.initialize(msg->payload->bytes(), msg->payload->length())) != ERROR_SUCCESS) {
srs_error("mpegts: initialize av stream failed. ret=%d", ret); return srs_error_new(ret, "ts: init av stream");
return ret;
} }
// publish audio or video. // publish audio or video.
if (msg->channel->stream == SrsTsStreamVideoH264) { if (msg->channel->stream == SrsTsStreamVideoH264) {
return on_ts_video(msg, &avs); if ((ret = on_ts_video(msg, &avs)) != ERROR_SUCCESS) {
return srs_error_new(ret, "ts: consume video");
}
} }
if (msg->channel->stream == SrsTsStreamAudioAAC) { if (msg->channel->stream == SrsTsStreamAudioAAC) {
return on_ts_audio(msg, &avs); if ((ret = on_ts_audio(msg, &avs)) != ERROR_SUCCESS) {
return srs_error_new(ret, "ts: consume audio");
}
} }
// TODO: FIXME: implements it. // TODO: FIXME: implements it.
return ret; return err;
} }
int SrsMpegtsOverUdp::on_ts_video(SrsTsMessage* msg, SrsBuffer* avs) int SrsMpegtsOverUdp::on_ts_video(SrsTsMessage* msg, SrsBuffer* avs)

View file

@ -106,7 +106,7 @@ private:
virtual int on_udp_bytes(std::string host, int port, char* buf, int nb_buf); virtual int on_udp_bytes(std::string host, int port, char* buf, int nb_buf);
// interface ISrsTsHandler // interface ISrsTsHandler
public: public:
virtual int on_ts_message(SrsTsMessage* msg); virtual srs_error_t on_ts_message(SrsTsMessage* msg);
private: private:
virtual int on_ts_video(SrsTsMessage* msg, SrsBuffer* avs); virtual int on_ts_video(SrsTsMessage* msg, SrsBuffer* avs);
virtual int write_h264_sps_pps(uint32_t dts, uint32_t pts); virtual int write_h264_sps_pps(uint32_t dts, uint32_t pts);

View file

@ -166,8 +166,8 @@ srs_error_t SrsRtmpConn::do_cycle()
// notify kafka cluster. // notify kafka cluster.
#ifdef SRS_AUTO_KAFKA #ifdef SRS_AUTO_KAFKA
if ((ret = _srs_kafka->on_client(srs_id(), SrsListenerRtmpStream, ip)) != ERROR_SUCCESS) { if ((err = _srs_kafka->on_client(srs_id(), SrsListenerRtmpStream, ip)) != srs_success) {
return srs_error_new(ret, "kafka on client"); return srs_error_wrap(err, "kafka on client");
} }
#endif #endif
@ -1411,14 +1411,13 @@ int SrsRtmpConn::do_token_traverse_auth(SrsRtmpClient* client)
srs_error_t SrsRtmpConn::on_disconnect() srs_error_t SrsRtmpConn::on_disconnect()
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
http_hooks_on_close(); http_hooks_on_close();
#ifdef SRS_AUTO_KAFKA #ifdef SRS_AUTO_KAFKA
if ((ret = _srs_kafka->on_close(srs_id())) != ERROR_SUCCESS) { if ((err = _srs_kafka->on_close(srs_id())) != srs_success) {
return srs_error_new(ret, "kafka on close"); return srs_error_wrap(err, "kafka on close");
} }
#endif #endif

View file

@ -85,15 +85,15 @@ SrsRtmpJitter::~SrsRtmpJitter()
{ {
} }
int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag) srs_error_t SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// for performance issue // for performance issue
if (ag != SrsRtmpJitterAlgorithmFULL) { if (ag != SrsRtmpJitterAlgorithmFULL) {
// all jitter correct features is disabled, ignore. // all jitter correct features is disabled, ignore.
if (ag == SrsRtmpJitterAlgorithmOFF) { if (ag == SrsRtmpJitterAlgorithmOFF) {
return ret; return err;
} }
// start at zero, but donot ensure monotonically increasing. // start at zero, but donot ensure monotonically increasing.
@ -103,18 +103,18 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag)
last_pkt_correct_time = msg->timestamp; last_pkt_correct_time = msg->timestamp;
} }
msg->timestamp -= last_pkt_correct_time; msg->timestamp -= last_pkt_correct_time;
return ret; return err;
} }
// other algorithm, ignore. // other algorithm, ignore.
return ret; return err;
} }
// full jitter algorithm, do jitter correct. // full jitter algorithm, do jitter correct.
// set to 0 for metadata. // set to 0 for metadata.
if (!msg->is_av()) { if (!msg->is_av()) {
msg->timestamp = 0; msg->timestamp = 0;
return ret; return err;
} }
/** /**
@ -148,7 +148,7 @@ int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag)
msg->timestamp = last_pkt_correct_time; msg->timestamp = last_pkt_correct_time;
last_pkt_time = time; last_pkt_time = time;
return ret; return err;
} }
int SrsRtmpJitter::get_time() int SrsRtmpJitter::get_time()
@ -470,12 +470,16 @@ int SrsConsumer::get_time()
int SrsConsumer::enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsRtmpJitterAlgorithm ag) int SrsConsumer::enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsRtmpJitterAlgorithm ag)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsSharedPtrMessage* msg = shared_msg->copy(); SrsSharedPtrMessage* msg = shared_msg->copy();
if (!atc) { if (!atc) {
if ((ret = jitter->correct(msg, ag)) != ERROR_SUCCESS) { if ((err = jitter->correct(msg, ag)) != srs_success) {
srs_freep(msg); srs_freep(msg);
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
} }
@ -963,6 +967,7 @@ int SrsOriginHub::on_meta_data(SrsSharedPtrMessage* shared_metadata, SrsOnMetaDa
int SrsOriginHub::on_audio(SrsSharedPtrMessage* shared_audio) int SrsOriginHub::on_audio(SrsSharedPtrMessage* shared_audio)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsSharedPtrMessage* msg = shared_audio; SrsSharedPtrMessage* msg = shared_audio;
@ -993,7 +998,11 @@ int SrsOriginHub::on_audio(SrsSharedPtrMessage* shared_audio)
srs_flv_srates[c->sound_rate]); srs_flv_srates[c->sound_rate]);
} }
if ((ret = hls->on_audio(msg, format)) != ERROR_SUCCESS) { if ((err = hls->on_audio(msg, format)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
// apply the error strategy for hls. // apply the error strategy for hls.
// @see https://github.com/ossrs/srs/issues/264 // @see https://github.com/ossrs/srs/issues/264
std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost); std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost);
@ -1063,6 +1072,7 @@ int SrsOriginHub::on_audio(SrsSharedPtrMessage* shared_audio)
int SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header) int SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsSharedPtrMessage* msg = shared_video; SrsSharedPtrMessage* msg = shared_video;
@ -1095,7 +1105,11 @@ int SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_h
c->video_data_rate / 1000, c->frame_rate, c->duration); c->video_data_rate / 1000, c->frame_rate, c->duration);
} }
if ((ret = hls->on_video(msg, format)) != ERROR_SUCCESS) { if ((err = hls->on_video(msg, format)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
// apply the error strategy for hls. // apply the error strategy for hls.
// @see https://github.com/ossrs/srs/issues/264 // @see https://github.com/ossrs/srs/issues/264
std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost); std::string hls_error_strategy = _srs_config->get_hls_on_error(req->vhost);
@ -1165,6 +1179,7 @@ int SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_h
int SrsOriginHub::on_publish() int SrsOriginHub::on_publish()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// create forwarders // create forwarders
if ((ret = create_forwarders()) != ERROR_SUCCESS) { if ((ret = create_forwarders()) != ERROR_SUCCESS) {
@ -1180,7 +1195,10 @@ int SrsOriginHub::on_publish()
} }
#endif #endif
if ((ret = hls->on_publish()) != ERROR_SUCCESS) { if ((err = hls->on_publish()) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("start hls failed. ret=%d", ret); srs_error("start hls failed. ret=%d", ret);
return ret; return ret;
} }
@ -1384,8 +1402,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hls(string vhost)
return err; return err;
} }
if ((ret = hls->on_publish()) != ERROR_SUCCESS) { if ((err = hls->on_publish()) != srs_success) {
return srs_error_new(ret, "hls publish failed"); return srs_error_wrap(err, "hls publish failed");
} }
srs_trace("vhost %s hls reload success", vhost.c_str()); srs_trace("vhost %s hls reload success", vhost.c_str());
@ -1399,8 +1417,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hls(string vhost)
if ((ret = format->on_video(cache_sh_video)) != ERROR_SUCCESS) { if ((ret = format->on_video(cache_sh_video)) != ERROR_SUCCESS) {
return srs_error_new(ret, "format on_video"); return srs_error_new(ret, "format on_video");
} }
if ((ret = hls->on_video(cache_sh_video, format)) != ERROR_SUCCESS) { if ((err = hls->on_video(cache_sh_video, format)) != srs_success) {
return srs_error_new(ret, "hls on_video"); return srs_error_wrap(err, "hls on_video");
} }
} }
@ -1409,8 +1427,8 @@ srs_error_t SrsOriginHub::on_reload_vhost_hls(string vhost)
if ((ret = format->on_audio(cache_sh_audio)) != ERROR_SUCCESS) { if ((ret = format->on_audio(cache_sh_audio)) != ERROR_SUCCESS) {
return srs_error_new(ret, "format on_audio"); return srs_error_new(ret, "format on_audio");
} }
if ((ret = hls->on_audio(cache_sh_audio, format)) != ERROR_SUCCESS) { if ((err = hls->on_audio(cache_sh_audio, format)) != srs_success) {
return srs_error_new(ret, "hls on_audio"); return srs_error_wrap(err, "hls on_audio");
} }
} }

View file

@ -94,7 +94,7 @@ public:
* detect the time jitter and correct it. * detect the time jitter and correct it.
* @param ag the algorithm to use for time jitter. * @param ag the algorithm to use for time jitter.
*/ */
virtual int correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag); virtual srs_error_t correct(SrsSharedPtrMessage* msg, SrsRtmpJitterAlgorithm ag);
/** /**
* get current client time, the last packet time. * get current client time, the last packet time.
*/ */

File diff suppressed because it is too large Load diff

View file

@ -283,7 +283,7 @@ public:
/** /**
* dumps all bytes in stream to ts message. * dumps all bytes in stream to ts message.
*/ */
virtual int dump(SrsBuffer* stream, int* pnb_bytes); virtual srs_error_t dump(SrsBuffer* stream, int* pnb_bytes);
/** /**
* whether ts message is completed to reap. * whether ts message is completed to reap.
* @param payload_unit_start_indicator whether new ts message start. * @param payload_unit_start_indicator whether new ts message start.
@ -334,7 +334,7 @@ public:
* @param msg the ts msg, user should never free it. * @param msg the ts msg, user should never free it.
* @return an int error code. * @return an int error code.
*/ */
virtual int on_ts_message(SrsTsMessage* msg) = 0; virtual srs_error_t on_ts_message(SrsTsMessage* msg) = 0;
}; };
/** /**
@ -392,7 +392,7 @@ public:
* @param handler the ts message handler to process the msg. * @param handler the ts message handler to process the msg.
* @remark we will consume all bytes in stream. * @remark we will consume all bytes in stream.
*/ */
virtual int decode(SrsBuffer* stream, ISrsTsHandler* handler); virtual srs_error_t decode(SrsBuffer* stream, ISrsTsHandler* handler);
// encode methods // encode methods
public: public:
/** /**
@ -401,7 +401,7 @@ public:
* @param vc the video codec, write the PAT/PMT table when changed. * @param vc the video codec, write the PAT/PMT table when changed.
* @param ac the audio codec, write the PAT/PMT table when changed. * @param ac the audio codec, write the PAT/PMT table when changed.
*/ */
virtual int encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsVideoCodecId vc, SrsAudioCodecId ac); virtual srs_error_t encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsVideoCodecId vc, SrsAudioCodecId ac);
// drm methods // drm methods
public: public:
/** /**
@ -410,8 +410,8 @@ public:
*/ */
virtual void set_sync_byte(int8_t sb); virtual void set_sync_byte(int8_t sb);
private: private:
virtual int encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as); virtual srs_error_t encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as);
virtual int encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid, bool pure_audio); virtual srs_error_t encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid, bool pure_audio);
}; };
/** /**
@ -516,10 +516,10 @@ public:
SrsTsPacket(SrsTsContext* c); SrsTsPacket(SrsTsContext* c);
virtual ~SrsTsPacket(); virtual ~SrsTsPacket();
public: public:
virtual int decode(SrsBuffer* stream, SrsTsMessage** ppmsg); virtual srs_error_t decode(SrsBuffer* stream, SrsTsMessage** ppmsg);
public: public:
virtual int size(); virtual int size();
virtual int encode(SrsBuffer* stream); virtual srs_error_t encode(SrsBuffer* stream);
virtual void padding(int nb_stuffings); virtual void padding(int nb_stuffings);
public: public:
static SrsTsPacket* create_pat(SrsTsContext* context, int16_t pmt_number, int16_t pmt_pid); static SrsTsPacket* create_pat(SrsTsContext* context, int16_t pmt_number, int16_t pmt_pid);
@ -832,10 +832,10 @@ public:
SrsTsAdaptationField(SrsTsPacket* pkt); SrsTsAdaptationField(SrsTsPacket* pkt);
virtual ~SrsTsAdaptationField(); virtual ~SrsTsAdaptationField();
public: public:
virtual int decode(SrsBuffer* stream); virtual srs_error_t decode(SrsBuffer* stream);
public: public:
virtual int size(); virtual int size();
virtual int encode(SrsBuffer* stream); virtual srs_error_t encode(SrsBuffer* stream);
}; };
/** /**
@ -880,10 +880,10 @@ public:
SrsTsPayload(SrsTsPacket* p); SrsTsPayload(SrsTsPacket* p);
virtual ~SrsTsPayload(); virtual ~SrsTsPayload();
public: public:
virtual int decode(SrsBuffer* stream, SrsTsMessage** ppmsg) = 0; virtual srs_error_t decode(SrsBuffer* stream, SrsTsMessage** ppmsg) = 0;
public: public:
virtual int size() = 0; virtual int size() = 0;
virtual int encode(SrsBuffer* stream) = 0; virtual srs_error_t encode(SrsBuffer* stream) = 0;
}; };
/** /**
@ -1222,13 +1222,13 @@ public:
SrsTsPayloadPES(SrsTsPacket* p); SrsTsPayloadPES(SrsTsPacket* p);
virtual ~SrsTsPayloadPES(); virtual ~SrsTsPayloadPES();
public: public:
virtual int decode(SrsBuffer* stream, SrsTsMessage** ppmsg); virtual srs_error_t decode(SrsBuffer* stream, SrsTsMessage** ppmsg);
public: public:
virtual int size(); virtual int size();
virtual int encode(SrsBuffer* stream); virtual srs_error_t encode(SrsBuffer* stream);
private: private:
virtual int decode_33bits_dts_pts(SrsBuffer* stream, int64_t* pv); virtual srs_error_t decode_33bits_dts_pts(SrsBuffer* stream, int64_t* pv);
virtual int encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb, int64_t v); virtual srs_error_t encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb, int64_t v);
}; };
/** /**
@ -1289,14 +1289,14 @@ public:
SrsTsPayloadPSI(SrsTsPacket* p); SrsTsPayloadPSI(SrsTsPacket* p);
virtual ~SrsTsPayloadPSI(); virtual ~SrsTsPayloadPSI();
public: public:
virtual int decode(SrsBuffer* stream, SrsTsMessage** ppmsg); virtual srs_error_t decode(SrsBuffer* stream, SrsTsMessage** ppmsg);
public: public:
virtual int size(); virtual int size();
virtual int encode(SrsBuffer* stream); virtual srs_error_t encode(SrsBuffer* stream);
protected: protected:
virtual int psi_size() = 0; virtual int psi_size() = 0;
virtual int psi_encode(SrsBuffer* stream) = 0; virtual srs_error_t psi_encode(SrsBuffer* stream) = 0;
virtual int psi_decode(SrsBuffer* stream) = 0; virtual srs_error_t psi_decode(SrsBuffer* stream) = 0;
}; };
/** /**
@ -1329,10 +1329,10 @@ public:
SrsTsPayloadPATProgram(int16_t n = 0, int16_t p = 0); SrsTsPayloadPATProgram(int16_t n = 0, int16_t p = 0);
virtual ~SrsTsPayloadPATProgram(); virtual ~SrsTsPayloadPATProgram();
public: public:
virtual int decode(SrsBuffer* stream); virtual srs_error_t decode(SrsBuffer* stream);
public: public:
virtual int size(); virtual int size();
virtual int encode(SrsBuffer* stream); virtual srs_error_t encode(SrsBuffer* stream);
}; };
/** /**
@ -1393,10 +1393,10 @@ public:
SrsTsPayloadPAT(SrsTsPacket* p); SrsTsPayloadPAT(SrsTsPacket* p);
virtual ~SrsTsPayloadPAT(); virtual ~SrsTsPayloadPAT();
protected: protected:
virtual int psi_decode(SrsBuffer* stream); virtual srs_error_t psi_decode(SrsBuffer* stream);
protected: protected:
virtual int psi_size(); virtual int psi_size();
virtual int psi_encode(SrsBuffer* stream); virtual srs_error_t psi_encode(SrsBuffer* stream);
}; };
/** /**
@ -1433,10 +1433,10 @@ public:
SrsTsPayloadPMTESInfo(SrsTsStream st = SrsTsStreamReserved, int16_t epid = 0); SrsTsPayloadPMTESInfo(SrsTsStream st = SrsTsStreamReserved, int16_t epid = 0);
virtual ~SrsTsPayloadPMTESInfo(); virtual ~SrsTsPayloadPMTESInfo();
public: public:
virtual int decode(SrsBuffer* stream); virtual srs_error_t decode(SrsBuffer* stream);
public: public:
virtual int size(); virtual int size();
virtual int encode(SrsBuffer* stream); virtual srs_error_t encode(SrsBuffer* stream);
}; };
/** /**
@ -1523,10 +1523,10 @@ public:
SrsTsPayloadPMT(SrsTsPacket* p); SrsTsPayloadPMT(SrsTsPacket* p);
virtual ~SrsTsPayloadPMT(); virtual ~SrsTsPayloadPMT();
protected: protected:
virtual int psi_decode(SrsBuffer* stream); virtual srs_error_t psi_decode(SrsBuffer* stream);
protected: protected:
virtual int psi_size(); virtual int psi_size();
virtual int psi_encode(SrsBuffer* stream); virtual srs_error_t psi_encode(SrsBuffer* stream);
}; };
/** /**
@ -1551,15 +1551,15 @@ public:
* open the writer, donot write the PSI of ts. * open the writer, donot write the PSI of ts.
* @param p a string indicates the path of ts file to mux to. * @param p a string indicates the path of ts file to mux to.
*/ */
virtual int open(std::string p); virtual srs_error_t open(std::string p);
/** /**
* write an audio frame to ts, * write an audio frame to ts,
*/ */
virtual int write_audio(SrsTsMessage* audio); virtual srs_error_t write_audio(SrsTsMessage* audio);
/** /**
* write a video frame to ts, * write a video frame to ts,
*/ */
virtual int write_video(SrsTsMessage* video); virtual srs_error_t write_video(SrsTsMessage* video);
/** /**
* close the writer. * close the writer.
*/ */
@ -1588,15 +1588,15 @@ public:
/** /**
* write audio to cache * write audio to cache
*/ */
virtual int cache_audio(SrsAudioFrame* frame, int64_t dts); virtual srs_error_t cache_audio(SrsAudioFrame* frame, int64_t dts);
/** /**
* write video to muxer. * write video to muxer.
*/ */
virtual int cache_video(SrsVideoFrame* frame, int64_t dts); virtual srs_error_t cache_video(SrsVideoFrame* frame, int64_t dts);
private: private:
virtual int do_cache_mp3(SrsAudioFrame* frame); virtual srs_error_t do_cache_mp3(SrsAudioFrame* frame);
virtual int do_cache_aac(SrsAudioFrame* frame); virtual srs_error_t do_cache_aac(SrsAudioFrame* frame);
virtual int do_cache_avc(SrsVideoFrame* frame); virtual srs_error_t do_cache_avc(SrsVideoFrame* frame);
}; };
/** /**
@ -1619,17 +1619,17 @@ public:
* initialize the underlayer file stream. * initialize the underlayer file stream.
* @param fw the writer to use for ts encoder, user must free it. * @param fw the writer to use for ts encoder, user must free it.
*/ */
virtual int initialize(SrsFileWriter* fw); virtual srs_error_t initialize(SrsFileWriter* fw);
public: public:
/** /**
* write audio/video packet. * write audio/video packet.
* @remark assert data is not NULL. * @remark assert data is not NULL.
*/ */
virtual int write_audio(int64_t timestamp, char* data, int size); virtual srs_error_t write_audio(int64_t timestamp, char* data, int size);
virtual int write_video(int64_t timestamp, char* data, int size); virtual srs_error_t write_video(int64_t timestamp, char* data, int size);
private: private:
virtual int flush_audio(); virtual srs_error_t flush_audio();
virtual int flush_video(); virtual srs_error_t flush_video();
}; };
#endif #endif

View file

@ -509,17 +509,15 @@ int srs_do_create_dir_recursively(string dir)
return true; return true;
} }
int srs_create_dir_recursively(string dir) srs_error_t srs_create_dir_recursively(string dir)
{ {
int ret = ERROR_SUCCESS; int ret = srs_do_create_dir_recursively(dir);
ret = srs_do_create_dir_recursively(dir);
if (ret == ERROR_SYSTEM_DIR_EXISTS) { if (ret == ERROR_SYSTEM_DIR_EXISTS) {
return ERROR_SUCCESS; return srs_success;
} }
return ret; return srs_error_new(ret, "create dir %s", dir.c_str());
} }
bool srs_path_exists(std::string path) bool srs_path_exists(std::string path)

View file

@ -102,7 +102,7 @@ extern std::vector<std::string> srs_string_split(std::string str, std::vector<st
extern bool srs_bytes_equals(void* pa, void* pb, int size); extern bool srs_bytes_equals(void* pa, void* pb, int size);
// create dir recursively // create dir recursively
extern int srs_create_dir_recursively(std::string dir); extern srs_error_t srs_create_dir_recursively(std::string dir);
// whether path exists. // whether path exists.
extern bool srs_path_exists(std::string path); extern bool srs_path_exists(std::string path);

View file

@ -285,6 +285,7 @@ int SrsIngestHlsInput::parse(ISrsTsHandler* ts, ISrsAacHandler* aac)
int SrsIngestHlsInput::parseTs(ISrsTsHandler* handler, char* body, int nb_body) int SrsIngestHlsInput::parseTs(ISrsTsHandler* handler, char* body, int nb_body)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// use stream to parse ts packet. // use stream to parse ts packet.
int nb_packet = (int)nb_body / SRS_TS_PACKET_SIZE; int nb_packet = (int)nb_body / SRS_TS_PACKET_SIZE;
@ -295,7 +296,10 @@ int SrsIngestHlsInput::parseTs(ISrsTsHandler* handler, char* body, int nb_body)
} }
// process each ts packet // process each ts packet
if ((ret = context->decode(stream, handler)) != ERROR_SUCCESS) { if ((err = context->decode(stream, handler)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("mpegts: ignore parse ts packet failed. ret=%d", ret); srs_error("mpegts: ignore parse ts packet failed. ret=%d", ret);
return ret; return ret;
} }
@ -654,7 +658,7 @@ public:
virtual ~SrsIngestHlsOutput(); virtual ~SrsIngestHlsOutput();
// interface ISrsTsHandler // interface ISrsTsHandler
public: public:
virtual int on_ts_message(SrsTsMessage* msg); virtual srs_error_t on_ts_message(SrsTsMessage* msg);
// interface IAacHandler // interface IAacHandler
public: public:
virtual int on_aac_frame(char* frame, int frame_size, double duration); virtual int on_aac_frame(char* frame, int frame_size, double duration);
@ -713,9 +717,10 @@ SrsIngestHlsOutput::~SrsIngestHlsOutput()
queue.clear(); queue.clear();
} }
int SrsIngestHlsOutput::on_ts_message(SrsTsMessage* msg) srs_error_t SrsIngestHlsOutput::on_ts_message(SrsTsMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// about the bytes of msg, specified by elementary stream which indicates by PES_packet_data_byte and stream_id // about the bytes of msg, specified by elementary stream which indicates by PES_packet_data_byte and stream_id
// for example, when SrsTsStream of SrsTsChannel indicates stream_type is SrsTsStreamVideoMpeg4 and SrsTsStreamAudioMpeg4, // for example, when SrsTsStream of SrsTsChannel indicates stream_type is SrsTsStreamVideoMpeg4 and SrsTsStreamAudioMpeg4,
@ -767,26 +772,22 @@ int SrsIngestHlsOutput::on_ts_message(SrsTsMessage* msg)
// when not audio/video, or not adts/annexb format, donot support. // when not audio/video, or not adts/annexb format, donot support.
if (msg->stream_number() != 0) { if (msg->stream_number() != 0) {
ret = ERROR_STREAM_CASTER_TS_ES; return srs_error_new(ERROR_STREAM_CASTER_TS_ES, "ts: unsupported stream format, sid=%#x(%s-%d)",
srs_error("mpegts: unsupported stream format, sid=%#x(%s-%d). ret=%d", msg->sid, msg->is_audio()? "A":msg->is_video()? "V":"N", msg->stream_number());
msg->sid, msg->is_audio()? "A":msg->is_video()? "V":"N", msg->stream_number(), ret);
return ret;
} }
// check supported codec // check supported codec
if (msg->channel->stream != SrsTsStreamVideoH264 && msg->channel->stream != SrsTsStreamAudioAAC) { if (msg->channel->stream != SrsTsStreamVideoH264 && msg->channel->stream != SrsTsStreamAudioAAC) {
ret = ERROR_STREAM_CASTER_TS_CODEC; return srs_error_new(ERROR_STREAM_CASTER_TS_CODEC, "ts: unsupported stream codec=%d", msg->channel->stream);
srs_error("mpegts: unsupported stream codec=%d. ret=%d", msg->channel->stream, ret);
return ret;
} }
// we must use queue to cache the msg, then parse it if possible. // we must use queue to cache the msg, then parse it if possible.
queue.insert(std::make_pair(msg->dts, msg->detach())); queue.insert(std::make_pair(msg->dts, msg->detach()));
if ((ret = parse_message_queue()) != ERROR_SUCCESS) { if ((ret = parse_message_queue()) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "ts: parse message");
} }
return ret; return err;
} }
int SrsIngestHlsOutput::on_aac_frame(char* frame, int frame_size, double duration) int SrsIngestHlsOutput::on_aac_frame(char* frame, int frame_size, double duration)