For #913, source support complex error

pull/1080/head
winlin 7 years ago
parent abcaba33ee
commit 9802dc326e

@ -112,11 +112,12 @@ srs_error_t SrsConnection::cycle()
// TODO: FIXME: Only reset the error when client closed it. // TODO: FIXME: Only reset the error when client closed it.
if (srs_is_client_gracefully_close(srs_error_code(err))) { if (srs_is_client_gracefully_close(srs_error_code(err))) {
srs_warn("client disconnect peer. ret=%d", srs_error_code(err)); srs_warn("client disconnect peer. ret=%d", srs_error_code(err));
srs_freep(err); } else {
return srs_success; srs_error("connect error %s", srs_error_desc(err).c_str());
} }
return srs_error_wrap(err, "cycle"); srs_freep(err);
return srs_success;
} }
int SrsConnection::srs_id() int SrsConnection::srs_id()

@ -81,30 +81,25 @@ SrsFragment* SrsDvrSegmenter::current()
return fragment; return fragment;
} }
int SrsDvrSegmenter::open() srs_error_t SrsDvrSegmenter::open()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
// ignore when already open. // ignore when already open.
if (fs->is_open()) { if (fs->is_open()) {
return ret; return err;
} }
string path = generate_path(); string path = generate_path();
if (srs_path_exists(path)) { if (srs_path_exists(path)) {
ret = ERROR_DVR_CANNOT_APPEND; return srs_error_new(ERROR_DVR_CANNOT_APPEND, "DVR can't append to exists path=%s", path.c_str());
srs_error("DVR can't append to exists path=%s. ret=%d", path.c_str(), ret);
return ret;
} }
fragment->set_path(path); fragment->set_path(path);
// create dir first. // create dir first.
if ((err = fragment->create_dir()) != srs_success) { if ((err = fragment->create_dir()) != srs_success) {
// TODO: FIXME: Use error return srs_error_wrap(err, "create dir");
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
// create jitter. // create jitter.
@ -114,106 +109,95 @@ int SrsDvrSegmenter::open()
// open file writer, in append or create mode. // open file writer, in append or create mode.
string tmp_dvr_file = fragment->tmppath(); string tmp_dvr_file = fragment->tmppath();
if ((ret = fs->open(tmp_dvr_file)) != ERROR_SUCCESS) { if ((ret = fs->open(tmp_dvr_file)) != ERROR_SUCCESS) {
srs_error("open file stream for file %s failed. ret=%d", path.c_str(), ret); return srs_error_new(ret, "open file %s", path.c_str());
return ret;
} }
// initialize the encoder. // initialize the encoder.
if ((ret = open_encoder()) != ERROR_SUCCESS) { if ((err = open_encoder()) != srs_success) {
srs_error("initialize enc by fs for file %s failed. ret=%d", path.c_str(), ret); return srs_error_wrap(err, "open encoder");
return ret;
} }
srs_trace("dvr stream %s to file %s", req->stream.c_str(), path.c_str()); srs_trace("dvr stream %s to file %s", req->stream.c_str(), path.c_str());
return err;
return ret;
} }
int SrsDvrSegmenter::write_metadata(SrsSharedPtrMessage* metadata) srs_error_t SrsDvrSegmenter::write_metadata(SrsSharedPtrMessage* metadata)
{ {
return encode_metadata(metadata); return encode_metadata(metadata);
} }
int SrsDvrSegmenter::write_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format) srs_error_t SrsDvrSegmenter::write_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
SrsSharedPtrMessage* audio = shared_audio->copy(); SrsSharedPtrMessage* audio = shared_audio->copy();
SrsAutoFree(SrsSharedPtrMessage, audio); SrsAutoFree(SrsSharedPtrMessage, audio);
if ((jitter->correct(audio, jitter_algorithm)) != ERROR_SUCCESS) { if ((err = jitter->correct(audio, jitter_algorithm)) != srs_success) {
return ret; return srs_error_wrap(err, "jitter");
} }
if ((ret = on_update_duration(audio)) != ERROR_SUCCESS) { if ((err = on_update_duration(audio)) != srs_success) {
return ret; return srs_error_wrap(err, "update duration");
} }
if ((ret = encode_audio(audio, format)) != ERROR_SUCCESS) { if ((err = encode_audio(audio, format)) != srs_success) {
return ret; return srs_error_wrap(err, "encode audio");
} }
return ret; return err;
} }
int SrsDvrSegmenter::write_video(SrsSharedPtrMessage* shared_video, SrsFormat* format) srs_error_t SrsDvrSegmenter::write_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
SrsSharedPtrMessage* video = shared_video->copy(); SrsSharedPtrMessage* video = shared_video->copy();
SrsAutoFree(SrsSharedPtrMessage, video); SrsAutoFree(SrsSharedPtrMessage, video);
if ((jitter->correct(video, jitter_algorithm)) != ERROR_SUCCESS) { if ((err = jitter->correct(video, jitter_algorithm)) != srs_success) {
return ret; return srs_error_wrap(err, "jitter");
} }
if ((ret = encode_video(video, format)) != ERROR_SUCCESS) { if ((err = encode_video(video, format)) != srs_success) {
return ret; return srs_error_wrap(err, "encode video");
} }
if ((ret = on_update_duration(video)) != ERROR_SUCCESS) { if ((err = on_update_duration(video)) != srs_success) {
return ret; return srs_error_wrap(err, "update duration");
} }
return ret; return err;
} }
int SrsDvrSegmenter::close() srs_error_t SrsDvrSegmenter::close()
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
// ignore when already closed. // ignore when already closed.
if (!fs->is_open()) { if (!fs->is_open()) {
return ret; return err;
} }
// Close the encoder, then close the fs object. // Close the encoder, then close the fs object.
if ((ret = close_encoder()) != ERROR_SUCCESS) { if ((err = close_encoder()) != srs_success) {
return ret; return srs_error_wrap(err, "close encoder");
} }
fs->close(); fs->close();
// when tmp flv file exists, reap it. // when tmp flv file exists, reap it.
if ((err = fragment->rename()) != srs_success) { if ((err = fragment->rename()) != srs_success) {
// TODO: FIXME: Use error return srs_error_wrap(err, "rename fragment");
ret = srs_error_code(err);
srs_freep(err);
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 ((err = plan->on_reap_segment()) != srs_success) { if ((err = plan->on_reap_segment()) != srs_success) {
// TODO: FIXME: Use error return srs_error_wrap(err, "reap segment");
ret = srs_error_code(err);
srs_freep(err);
srs_error("dvr: notify plan to reap segment failed. ret=%d", ret);
return ret;
} }
return ret; return err;
} }
string SrsDvrSegmenter::generate_path() string SrsDvrSegmenter::generate_path()
@ -235,13 +219,10 @@ string SrsDvrSegmenter::generate_path()
return flv_path; return flv_path;
} }
int SrsDvrSegmenter::on_update_duration(SrsSharedPtrMessage* msg) srs_error_t SrsDvrSegmenter::on_update_duration(SrsSharedPtrMessage* msg)
{ {
int ret = ERROR_SUCCESS;
fragment->append(msg->timestamp); fragment->append(msg->timestamp);
return srs_success;
return ret;
} }
srs_error_t SrsDvrSegmenter::on_reload_vhost_dvr(std::string vhost) srs_error_t SrsDvrSegmenter::on_reload_vhost_dvr(std::string vhost)
@ -273,13 +254,14 @@ SrsDvrFlvSegmenter::~SrsDvrFlvSegmenter()
srs_freep(enc); srs_freep(enc);
} }
int SrsDvrFlvSegmenter::refresh_metadata() srs_error_t SrsDvrFlvSegmenter::refresh_metadata()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// no duration or filesize specified. // no duration or filesize specified.
if (!duration_offset || !filesize_offset) { if (!duration_offset || !filesize_offset) {
return ret; return err;
} }
int64_t cur = fs->tellg(); int64_t cur = fs->tellg();
@ -290,7 +272,7 @@ int SrsDvrFlvSegmenter::refresh_metadata()
SrsBuffer stream; SrsBuffer stream;
if ((ret = stream.initialize(buf, SrsAmf0Size::number())) != ERROR_SUCCESS) { if ((ret = stream.initialize(buf, SrsAmf0Size::number())) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init stream");
} }
// filesize to buf. // filesize to buf.
@ -299,13 +281,13 @@ int SrsDvrFlvSegmenter::refresh_metadata()
stream.skip(-1 * stream.pos()); stream.skip(-1 * stream.pos());
if ((ret = size->write(&stream)) != ERROR_SUCCESS) { if ((ret = size->write(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write filesize");
} }
// update the flesize. // update the flesize.
fs->seek2(filesize_offset); fs->seek2(filesize_offset);
if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) { if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "update filesize");
} }
// duration to buf // duration to buf
@ -314,24 +296,25 @@ int SrsDvrFlvSegmenter::refresh_metadata()
stream.skip(-1 * stream.pos()); stream.skip(-1 * stream.pos());
if ((ret = dur->write(&stream)) != ERROR_SUCCESS) { if ((ret = dur->write(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write duration");
} }
// update the duration // update the duration
fs->seek2(duration_offset); fs->seek2(duration_offset);
if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) { if ((ret = fs->write(buf, SrsAmf0Size::number(), NULL)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "update duration");
} }
// reset the offset. // reset the offset.
fs->seek2(cur); fs->seek2(cur);
return ret; return err;
} }
int SrsDvrFlvSegmenter::open_encoder() srs_error_t SrsDvrFlvSegmenter::open_encoder()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
has_keyframe = false; has_keyframe = false;
@ -343,42 +326,42 @@ int SrsDvrFlvSegmenter::open_encoder()
enc = new SrsFlvTransmuxer(); enc = new SrsFlvTransmuxer();
if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) { if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init encoder");
} }
// write the flv header to writer. // write the flv header to writer.
if ((ret = enc->write_header()) != ERROR_SUCCESS) { if ((ret = enc->write_header()) != ERROR_SUCCESS) {
srs_error("write flv header failed. ret=%d", ret); return srs_error_new(ret, "write flv header");
return ret;
} }
return ret; return err;
} }
int SrsDvrFlvSegmenter::encode_metadata(SrsSharedPtrMessage* metadata) srs_error_t SrsDvrFlvSegmenter::encode_metadata(SrsSharedPtrMessage* metadata)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// Ignore when metadata already written. // Ignore when metadata already written.
if (duration_offset || filesize_offset) { if (duration_offset || filesize_offset) {
return ret; return err;
} }
SrsBuffer stream; SrsBuffer stream;
if ((ret = stream.initialize(metadata->payload, metadata->size)) != ERROR_SUCCESS) { if ((ret = stream.initialize(metadata->payload, metadata->size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init stream");
} }
SrsAmf0Any* name = SrsAmf0Any::str(); SrsAmf0Any* name = SrsAmf0Any::str();
SrsAutoFree(SrsAmf0Any, name); SrsAutoFree(SrsAmf0Any, name);
if ((ret = name->read(&stream)) != ERROR_SUCCESS) { if ((ret = name->read(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read name");
} }
SrsAmf0Object* obj = SrsAmf0Any::object(); SrsAmf0Object* obj = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, obj); SrsAutoFree(SrsAmf0Object, obj);
if ((ret = obj->read(&stream)) != ERROR_SUCCESS) { if ((ret = obj->read(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read object");
} }
// remove duration and filesize. // remove duration and filesize.
@ -401,39 +384,41 @@ int SrsDvrFlvSegmenter::encode_metadata(SrsSharedPtrMessage* metadata)
// convert metadata to bytes. // convert metadata to bytes.
if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init stream");
} }
if ((ret = name->write(&stream)) != ERROR_SUCCESS) { if ((ret = name->write(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write name");
} }
if ((ret = obj->write(&stream)) != ERROR_SUCCESS) { if ((ret = obj->write(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write object");
} }
// to flv file. // to flv file.
if ((ret = enc->write_metadata(18, payload, size)) != ERROR_SUCCESS) { if ((ret = enc->write_metadata(18, payload, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write metadata");
} }
return ret; return err;
} }
int SrsDvrFlvSegmenter::encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format) srs_error_t SrsDvrFlvSegmenter::encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
char* payload = audio->payload; char* payload = audio->payload;
int size = audio->size; int size = audio->size;
if ((ret = enc->write_audio(audio->timestamp, payload, size)) != ERROR_SUCCESS) { if ((ret = enc->write_audio(audio->timestamp, payload, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write audio");
} }
return ret; return err;
} }
int SrsDvrFlvSegmenter::encode_video(SrsSharedPtrMessage* video, SrsFormat* format) srs_error_t SrsDvrFlvSegmenter::encode_video(SrsSharedPtrMessage* video, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
char* payload = video->payload; char* payload = video->payload;
int size = video->size; int size = video->size;
@ -446,21 +431,18 @@ int SrsDvrFlvSegmenter::encode_video(SrsSharedPtrMessage* video, SrsFormat* form
// accept the sequence header here. // accept the sequence header here.
// when got no keyframe, ignore when should wait keyframe. // when got no keyframe, ignore when should wait keyframe.
if (!has_keyframe && !sh) { if (!has_keyframe && !sh && wait_keyframe) {
if (wait_keyframe) { return err;
srs_info("dvr: ignore when wait keyframe.");
return ret;
}
} }
if ((ret = enc->write_video(video->timestamp, payload, size)) != ERROR_SUCCESS) { if ((ret = enc->write_video(video->timestamp, payload, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "write video");
} }
return ret; return err;
} }
int SrsDvrFlvSegmenter::close_encoder() srs_error_t SrsDvrFlvSegmenter::close_encoder()
{ {
return refresh_metadata(); return refresh_metadata();
} }
@ -475,32 +457,36 @@ SrsDvrMp4Segmenter::~SrsDvrMp4Segmenter()
srs_freep(enc); srs_freep(enc);
} }
int SrsDvrMp4Segmenter::refresh_metadata() srs_error_t SrsDvrMp4Segmenter::refresh_metadata()
{ {
return ERROR_SUCCESS; return srs_success;
} }
int SrsDvrMp4Segmenter::open_encoder() srs_error_t SrsDvrMp4Segmenter::open_encoder()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
srs_freep(enc); srs_freep(enc);
enc = new SrsMp4Encoder(); enc = new SrsMp4Encoder();
if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) { if ((ret = enc->initialize(fs)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init encoder");
} }
return ret; return err;
} }
int SrsDvrMp4Segmenter::encode_metadata(SrsSharedPtrMessage* /*metadata*/) srs_error_t SrsDvrMp4Segmenter::encode_metadata(SrsSharedPtrMessage* /*metadata*/)
{ {
return ERROR_SUCCESS; return srs_success;
} }
int SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format) srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsAudioCodecId sound_format = format->acodec->id; SrsAudioCodecId sound_format = format->acodec->id;
SrsAudioSampleRate sound_rate = format->acodec->sound_rate; SrsAudioSampleRate sound_rate = format->acodec->sound_rate;
SrsAudioSampleBits sound_size = format->acodec->sound_size; SrsAudioSampleBits sound_size = format->acodec->sound_size;
@ -518,11 +504,18 @@ int SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage* audio, SrsFormat* form
uint32_t nb_sample = (uint32_t)format->nb_raw; uint32_t nb_sample = (uint32_t)format->nb_raw;
uint32_t dts = (uint32_t)audio->timestamp; uint32_t dts = (uint32_t)audio->timestamp;
return enc->write_sample(SrsMp4HandlerTypeSOUN, 0x00, ct, dts, dts, sample, nb_sample); if ((ret = enc->write_sample(SrsMp4HandlerTypeSOUN, 0x00, ct, dts, dts, sample, nb_sample)) != ERROR_SUCCESS) {
return srs_error_new(ret, "write sample");
}
return err;
} }
int SrsDvrMp4Segmenter::encode_video(SrsSharedPtrMessage* video, SrsFormat* format) srs_error_t SrsDvrMp4Segmenter::encode_video(SrsSharedPtrMessage* video, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsVideoAvcFrameType frame_type = format->video->frame_type; SrsVideoAvcFrameType frame_type = format->video->frame_type;
SrsVideoCodecId codec_id = format->vcodec->id; SrsVideoCodecId codec_id = format->vcodec->id;
@ -538,18 +531,23 @@ int SrsDvrMp4Segmenter::encode_video(SrsSharedPtrMessage* video, SrsFormat* form
uint8_t* sample = (uint8_t*)format->raw; uint8_t* sample = (uint8_t*)format->raw;
uint32_t nb_sample = (uint32_t)format->nb_raw; uint32_t nb_sample = (uint32_t)format->nb_raw;
return enc->write_sample(SrsMp4HandlerTypeVIDE, frame_type, ct, dts, pts, sample, nb_sample); if ((ret = enc->write_sample(SrsMp4HandlerTypeVIDE, frame_type, ct, dts, pts, sample, nb_sample)) != ERROR_SUCCESS) {
return srs_error_new(ret, "write sample");
}
return err;
} }
int SrsDvrMp4Segmenter::close_encoder() srs_error_t SrsDvrMp4Segmenter::close_encoder()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if ((ret = enc->flush()) != ERROR_SUCCESS) { if ((ret = enc->flush()) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "flush encoder");
} }
return ret; return err;
} }
SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(int c, SrsRequest* r, string p) SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(int c, SrsRequest* r, string p)
@ -579,13 +577,9 @@ srs_error_t SrsDvrAsyncCallOnDvr::call()
if (true) { if (true) {
SrsConfDirective* conf = _srs_config->get_vhost_on_dvr(req->vhost); SrsConfDirective* conf = _srs_config->get_vhost_on_dvr(req->vhost);
if (conf) {
if (!conf) { hooks = conf->args;
srs_info("ignore the empty http callback: on_dvr");
return err;
} }
hooks = conf->args;
} }
for (int i = 0; i < (int)hooks.size(); i++) { for (int i = 0; i < (int)hooks.size(); i++) {
@ -639,45 +633,45 @@ srs_error_t SrsDvrPlan::initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsReque
return err; return err;
} }
int SrsDvrPlan::on_meta_data(SrsSharedPtrMessage* shared_metadata) srs_error_t SrsDvrPlan::on_meta_data(SrsSharedPtrMessage* shared_metadata)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!dvr_enabled) { if (!dvr_enabled) {
return ret; return err;
} }
return segment->write_metadata(shared_metadata); return segment->write_metadata(shared_metadata);
} }
int SrsDvrPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format) srs_error_t SrsDvrPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!dvr_enabled) { if (!dvr_enabled) {
return ret; return err;
} }
if ((ret = segment->write_audio(shared_audio, format)) != ERROR_SUCCESS) { if ((err = segment->write_audio(shared_audio, format)) != srs_success) {
return ret; return srs_error_wrap(err, "write audio");
} }
return ret; return err;
} }
int SrsDvrPlan::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format) srs_error_t SrsDvrPlan::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!dvr_enabled) { if (!dvr_enabled) {
return ret; return err;
} }
if ((ret = segment->write_video(shared_video, format)) != ERROR_SUCCESS) { if ((err = segment->write_video(shared_video, format)) != srs_success) {
return ret; return srs_error_wrap(err, "write video");
} }
return ret; return err;
} }
srs_error_t SrsDvrPlan::on_reap_segment() srs_error_t SrsDvrPlan::on_reap_segment()
@ -719,30 +713,30 @@ SrsDvrSessionPlan::~SrsDvrSessionPlan()
{ {
} }
int SrsDvrSessionPlan::on_publish() srs_error_t SrsDvrSessionPlan::on_publish()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// support multiple publish. // support multiple publish.
if (dvr_enabled) { if (dvr_enabled) {
return ret; return err;
} }
if (!_srs_config->get_dvr_enabled(req->vhost)) { if (!_srs_config->get_dvr_enabled(req->vhost)) {
return ret; return err;
} }
if ((ret = segment->close()) != ERROR_SUCCESS) { if ((err = segment->close()) != srs_success) {
return ret; return srs_error_wrap(err, "close segment");
} }
if ((ret = segment->open()) != ERROR_SUCCESS) { if ((err = segment->open()) != srs_success) {
return ret; return srs_error_wrap(err, "open segment");
} }
dvr_enabled = true; dvr_enabled = true;
return ret; return err;
} }
void SrsDvrSessionPlan::on_unpublish() void SrsDvrSessionPlan::on_unpublish()
@ -753,9 +747,9 @@ void SrsDvrSessionPlan::on_unpublish()
} }
// ignore error. // ignore error.
int ret = segment->close(); srs_error_t err = segment->close();
if (ret != ERROR_SUCCESS) { if (err != srs_success) {
srs_warn("ignore flv close error. ret=%d", ret); srs_warn("ignore flv close error %s", srs_error_desc(err).c_str());
} }
dvr_enabled = false; dvr_enabled = false;
@ -788,111 +782,109 @@ srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub* h, SrsDvrSegmenter* s, S
return srs_success; return srs_success;
} }
int SrsDvrSegmentPlan::on_publish() srs_error_t SrsDvrSegmentPlan::on_publish()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// support multiple publish. // support multiple publish.
if (dvr_enabled) { if (dvr_enabled) {
return ret; return err;
} }
if (!_srs_config->get_dvr_enabled(req->vhost)) { if (!_srs_config->get_dvr_enabled(req->vhost)) {
return ret; return err;
} }
if ((ret = segment->close()) != ERROR_SUCCESS) { if ((err = segment->close()) != srs_success) {
return ret; return srs_error_wrap(err, "segment close");
} }
if ((ret = segment->open()) != ERROR_SUCCESS) { if ((err = segment->open()) != srs_success) {
return ret; return srs_error_wrap(err, "segment open");
} }
dvr_enabled = true; dvr_enabled = true;
return ret; return err;
} }
void SrsDvrSegmentPlan::on_unpublish() void SrsDvrSegmentPlan::on_unpublish()
{ {
} }
int SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format) srs_error_t SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if ((ret = update_duration(shared_audio)) != ERROR_SUCCESS) { if ((err = update_duration(shared_audio)) != srs_success) {
return ret; return srs_error_wrap(err, "update duration");
} }
if ((ret = SrsDvrPlan::on_audio(shared_audio, format)) != ERROR_SUCCESS) { if ((err = SrsDvrPlan::on_audio(shared_audio, format)) != srs_success) {
return ret; return srs_error_wrap(err, "consume audio");
} }
return ret; return err;
} }
int SrsDvrSegmentPlan::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format) srs_error_t SrsDvrSegmentPlan::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if ((ret = update_duration(shared_video)) != ERROR_SUCCESS) { if ((err = update_duration(shared_video)) != srs_success) {
return ret; return srs_error_wrap(err, "update duration");
} }
if ((ret = SrsDvrPlan::on_video(shared_video, format)) != ERROR_SUCCESS) { if ((err = SrsDvrPlan::on_video(shared_video, format)) != srs_success) {
return ret; return srs_error_wrap(err, "consume video");
} }
return ret; return err;
} }
int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg) srs_error_t SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
srs_assert(segment); srs_assert(segment);
// ignore if duration ok. // ignore if duration ok.
SrsFragment* fragment = segment->current(); SrsFragment* fragment = segment->current();
if (cduration <= 0 || fragment->duration() < cduration) { if (cduration <= 0 || fragment->duration() < cduration) {
return ret; return err;
} }
// when wait keyframe, ignore if no frame arrived. // when wait keyframe, ignore if no frame arrived.
// @see https://github.com/ossrs/srs/issues/177 // @see https://github.com/ossrs/srs/issues/177
if (wait_keyframe) { if (wait_keyframe) {
if (!msg->is_video()) { if (!msg->is_video()) {
return ret; return err;
} }
char* payload = msg->payload; char* payload = msg->payload;
int size = msg->size; int size = msg->size;
bool is_key_frame = SrsFlvVideo::h264(payload, size) bool is_key_frame = SrsFlvVideo::h264(payload, size) && SrsFlvVideo::keyframe(payload, size) && !SrsFlvVideo::sh(payload, size);
&& SrsFlvVideo::keyframe(payload, size)
&& !SrsFlvVideo::sh(payload, size);
if (!is_key_frame) { if (!is_key_frame) {
return ret; return err;
} }
} }
// reap segment // reap segment
if ((ret = segment->close()) != ERROR_SUCCESS) { if ((err = segment->close()) != srs_success) {
return ret; return srs_error_wrap(err, "segment close");
} }
// open new flv file // open new flv file
if ((ret = segment->open()) != ERROR_SUCCESS) { if ((err = segment->open()) != srs_success) {
return ret; return srs_error_wrap(err, "segment open");
} }
// update sequence header // update sequence header
if ((ret = hub->on_dvr_request_sh()) != ERROR_SUCCESS) { if ((err = hub->on_dvr_request_sh()) != srs_success) {
return ret; return srs_error_wrap(err, "request sh");
} }
return ret; return err;
} }
srs_error_t SrsDvrSegmentPlan::on_reload_vhost_dvr(string vhost) srs_error_t SrsDvrSegmentPlan::on_reload_vhost_dvr(string vhost)
@ -959,20 +951,20 @@ srs_error_t SrsDvr::initialize(SrsOriginHub* h, SrsRequest* r)
return err; return err;
} }
int SrsDvr::on_publish() srs_error_t SrsDvr::on_publish()
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// the dvr for this stream is not actived. // the dvr for this stream is not actived.
if (!actived) { if (!actived) {
return ret; return err;
} }
if ((ret = plan->on_publish()) != ERROR_SUCCESS) { if ((err = plan->on_publish()) != srs_success) {
return ret; return srs_error_wrap(err, "publish");
} }
return ret; return err;
} }
void SrsDvr::on_unpublish() void SrsDvr::on_unpublish()
@ -980,37 +972,37 @@ void SrsDvr::on_unpublish()
plan->on_unpublish(); plan->on_unpublish();
} }
int SrsDvr::on_meta_data(SrsSharedPtrMessage* metadata) srs_error_t SrsDvr::on_meta_data(SrsSharedPtrMessage* metadata)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// the dvr for this stream is not actived. // the dvr for this stream is not actived.
if (!actived) { if (!actived) {
return ret; return err;
} }
if ((ret = plan->on_meta_data(metadata)) != ERROR_SUCCESS) { if ((err = plan->on_meta_data(metadata)) != srs_success) {
return ret; return srs_error_wrap(err, "metadata");
} }
return ret; return err;
} }
int SrsDvr::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format) srs_error_t SrsDvr::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
{ {
// the dvr for this stream is not actived. // the dvr for this stream is not actived.
if (!actived) { if (!actived) {
return ERROR_SUCCESS; return srs_success;
} }
return plan->on_audio(shared_audio, format); return plan->on_audio(shared_audio, format);
} }
int SrsDvr::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format) srs_error_t SrsDvr::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
{ {
// the dvr for this stream is not actived. // the dvr for this stream is not actived.
if (!actived) { if (!actived) {
return ERROR_SUCCESS; return srs_success;
} }
return plan->on_video(shared_video, format); return plan->on_video(shared_video, format);
@ -1018,7 +1010,6 @@ int SrsDvr::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
srs_error_t SrsDvr::on_reload_vhost_dvr_apply(string vhost) srs_error_t SrsDvr::on_reload_vhost_dvr_apply(string vhost)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
SrsConfDirective* conf = _srs_config->get_dvr_apply(req->vhost); SrsConfDirective* conf = _srs_config->get_dvr_apply(req->vhost);
@ -1035,11 +1026,11 @@ srs_error_t SrsDvr::on_reload_vhost_dvr_apply(string vhost)
return err; return err;
} }
if ((ret = on_publish()) != ERROR_SUCCESS) { if ((err = on_publish()) != srs_success) {
return srs_error_new(ret, "on publish"); return srs_error_wrap(err, "on publish");
} }
if ((ret = hub->on_dvr_request_sh()) != ERROR_SUCCESS) { if ((err = hub->on_dvr_request_sh()) != srs_success) {
return srs_error_new(ret, "request sh"); return srs_error_wrap(err, "request sh");
} }
return err; return err;

@ -78,33 +78,33 @@ public:
// Open new segment file. // Open new segment file.
// @param use_tmp_file Whether use tmp file for DVR, and rename when close. // @param use_tmp_file Whether use tmp file for DVR, and rename when close.
// @remark Ignore when file is already open. // @remark Ignore when file is already open.
virtual int open(); virtual srs_error_t open();
// Write the metadata. // Write the metadata.
virtual int write_metadata(SrsSharedPtrMessage* metadata); virtual srs_error_t write_metadata(SrsSharedPtrMessage* metadata);
// Write audio packet. // Write audio packet.
// @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 write_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format); virtual srs_error_t write_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format);
// Write video packet. // Write video packet.
// @param shared_video, directly ptr, copy it if need to save it. // @param shared_video, directly ptr, copy it if need to save it.
virtual int write_video(SrsSharedPtrMessage* shared_video, SrsFormat* format); virtual srs_error_t write_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
// Refresh the metadata. For example, there is duration in flv metadata, // Refresh the metadata. For example, there is duration in flv metadata,
// when DVR in append mode, the duration must be update every some seconds. // when DVR in append mode, the duration must be update every some seconds.
// @remark Maybe ignored by concreate segmenter. // @remark Maybe ignored by concreate segmenter.
virtual int refresh_metadata() = 0; virtual srs_error_t refresh_metadata() = 0;
// Close current segment. // Close current segment.
// @remark ignore when already closed. // @remark ignore when already closed.
virtual int close(); virtual srs_error_t close();
protected: protected:
virtual int open_encoder() = 0; virtual srs_error_t open_encoder() = 0;
virtual int encode_metadata(SrsSharedPtrMessage* metadata) = 0; virtual srs_error_t encode_metadata(SrsSharedPtrMessage* metadata) = 0;
virtual int encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format) = 0; virtual srs_error_t encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format) = 0;
virtual int encode_video(SrsSharedPtrMessage* video, SrsFormat* format) = 0; virtual srs_error_t encode_video(SrsSharedPtrMessage* video, SrsFormat* format) = 0;
virtual int close_encoder() = 0; virtual srs_error_t close_encoder() = 0;
private: private:
// Generate the flv segment path. // Generate the flv segment path.
virtual std::string generate_path(); virtual std::string generate_path();
// When update the duration of segment by rtmp msg. // When update the duration of segment by rtmp msg.
virtual int on_update_duration(SrsSharedPtrMessage* msg); virtual srs_error_t on_update_duration(SrsSharedPtrMessage* msg);
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual srs_error_t on_reload_vhost_dvr(std::string vhost); virtual srs_error_t on_reload_vhost_dvr(std::string vhost);
@ -131,13 +131,13 @@ public:
SrsDvrFlvSegmenter(); SrsDvrFlvSegmenter();
virtual ~SrsDvrFlvSegmenter(); virtual ~SrsDvrFlvSegmenter();
public: public:
virtual int refresh_metadata(); virtual srs_error_t refresh_metadata();
protected: protected:
virtual int open_encoder(); virtual srs_error_t open_encoder();
virtual int encode_metadata(SrsSharedPtrMessage* metadata); virtual srs_error_t encode_metadata(SrsSharedPtrMessage* metadata);
virtual int encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format); virtual srs_error_t encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format);
virtual int encode_video(SrsSharedPtrMessage* video, SrsFormat* format); virtual srs_error_t encode_video(SrsSharedPtrMessage* video, SrsFormat* format);
virtual int close_encoder(); virtual srs_error_t close_encoder();
}; };
/** /**
@ -152,13 +152,13 @@ public:
SrsDvrMp4Segmenter(); SrsDvrMp4Segmenter();
virtual ~SrsDvrMp4Segmenter(); virtual ~SrsDvrMp4Segmenter();
public: public:
virtual int refresh_metadata(); virtual srs_error_t refresh_metadata();
protected: protected:
virtual int open_encoder(); virtual srs_error_t open_encoder();
virtual int encode_metadata(SrsSharedPtrMessage* metadata); virtual srs_error_t encode_metadata(SrsSharedPtrMessage* metadata);
virtual int encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format); virtual srs_error_t encode_audio(SrsSharedPtrMessage* audio, SrsFormat* format);
virtual int encode_video(SrsSharedPtrMessage* video, SrsFormat* format); virtual srs_error_t encode_video(SrsSharedPtrMessage* video, SrsFormat* format);
virtual int close_encoder(); virtual srs_error_t close_encoder();
}; };
/** /**
@ -195,12 +195,12 @@ public:
virtual ~SrsDvrPlan(); virtual ~SrsDvrPlan();
public: public:
virtual srs_error_t initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsRequest* r); virtual srs_error_t initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsRequest* r);
virtual int on_publish() = 0; virtual srs_error_t on_publish() = 0;
virtual void on_unpublish() = 0; virtual void on_unpublish() = 0;
virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata); virtual srs_error_t on_meta_data(SrsSharedPtrMessage* shared_metadata);
virtual int on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format);
virtual int on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
// Internal interface for segmenter. // Internal interface for segmenter.
public: public:
// When segmenter close a segment. // When segmenter close a segment.
virtual srs_error_t on_reap_segment(); virtual srs_error_t on_reap_segment();
@ -217,7 +217,7 @@ public:
SrsDvrSessionPlan(); SrsDvrSessionPlan();
virtual ~SrsDvrSessionPlan(); virtual ~SrsDvrSessionPlan();
public: public:
virtual int on_publish(); virtual srs_error_t on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
}; };
@ -235,12 +235,12 @@ public:
virtual ~SrsDvrSegmentPlan(); virtual ~SrsDvrSegmentPlan();
public: public:
virtual srs_error_t initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsRequest* r); virtual srs_error_t initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsRequest* r);
virtual int on_publish(); virtual srs_error_t on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
virtual int on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format);
virtual int on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
private: private:
virtual int update_duration(SrsSharedPtrMessage* msg); virtual srs_error_t update_duration(SrsSharedPtrMessage* msg);
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual srs_error_t on_reload_vhost_dvr(std::string vhost); virtual srs_error_t on_reload_vhost_dvr(std::string vhost);
@ -275,7 +275,7 @@ public:
* when encoder start to publish RTMP stream. * when encoder start to publish RTMP stream.
* @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., * the unpublish event.,
* when encoder stop(unpublish) to publish RTMP stream. * when encoder stop(unpublish) to publish RTMP stream.
@ -284,17 +284,17 @@ public:
/** /**
* get some information from metadata, it's optinal. * get some information from metadata, it's optinal.
*/ */
virtual int on_meta_data(SrsSharedPtrMessage* metadata); virtual srs_error_t on_meta_data(SrsSharedPtrMessage* metadata);
/** /**
* mux the audio packets to dvr. * mux the audio packets to dvr.
* @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* foramt); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* foramt);
/** /**
* mux the video packets to dvr. * mux the video packets to dvr.
* @param shared_video, directly ptr, copy it if need to save it. * @param shared_video, directly ptr, copy it if need to save it.
*/ */
virtual int on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual srs_error_t on_reload_vhost_dvr_apply(std::string vhost); virtual srs_error_t on_reload_vhost_dvr_apply(std::string vhost);

@ -189,11 +189,10 @@ srs_error_t SrsEdgeIngester::initialize(SrsSource* s, SrsPlayEdge* e, SrsRequest
srs_error_t SrsEdgeIngester::start() srs_error_t SrsEdgeIngester::start()
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
if ((ret = source->on_publish()) != ERROR_SUCCESS) { if ((err = source->on_publish()) != srs_success) {
return srs_error_new(ret, "notify source"); return srs_error_wrap(err, "notify source");
} }
srs_freep(trd); srs_freep(trd);
@ -262,8 +261,8 @@ srs_error_t SrsEdgeIngester::do_cycle()
// reset the redirect to empty, for maybe the origin changed. // reset the redirect to empty, for maybe the origin changed.
redirect = ""; redirect = "";
if ((ret = source->on_source_id_changed(_srs_context->get_id())) != ERROR_SUCCESS) { if ((err = source->on_source_id_changed(_srs_context->get_id())) != srs_success) {
return srs_error_new(ret, "on source id changed"); return srs_error_wrap(err, "on source id changed");
} }
if ((ret = upstream->connect(req, lb)) != ERROR_SUCCESS) { if ((ret = upstream->connect(req, lb)) != ERROR_SUCCESS) {
@ -274,17 +273,17 @@ srs_error_t SrsEdgeIngester::do_cycle()
return srs_error_new(ret, "notify edge play"); return srs_error_new(ret, "notify edge play");
} }
ret = ingest(); err = ingest();
// retry for rtmp 302 immediately. // retry for rtmp 302 immediately.
if (ret == ERROR_CONTROL_REDIRECT) { if (srs_error_code(err) == ERROR_CONTROL_REDIRECT) {
ret = ERROR_SUCCESS; srs_error_reset(err);
continue; continue;
} }
if (srs_is_client_gracefully_close(ret)) { if (srs_is_client_gracefully_close(err)) {
srs_warn("origin disconnected, retry. ret=%d", ret); srs_warn("origin disconnected, retry, error %s", srs_error_desc(err).c_str());
ret = ERROR_SUCCESS; srs_error_reset(err);
} }
break; break;
} }
@ -292,9 +291,10 @@ srs_error_t SrsEdgeIngester::do_cycle()
return srs_error_new(ret, "cycle"); return srs_error_new(ret, "cycle");
} }
int SrsEdgeIngester::ingest() srs_error_t SrsEdgeIngester::ingest()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
SrsPithyPrint* pprint = SrsPithyPrint::create_edge(); SrsPithyPrint* pprint = SrsPithyPrint::create_edge();
SrsAutoFree(SrsPithyPrint, pprint); SrsAutoFree(SrsPithyPrint, pprint);
@ -305,10 +305,7 @@ int SrsEdgeIngester::ingest()
while (true) { while (true) {
srs_error_t err = srs_success; srs_error_t err = srs_success;
if ((err = trd->pull()) != srs_success) { if ((err = trd->pull()) != srs_success) {
// TODO: FIXME: Use error return srs_error_wrap(err, "thread quit");
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
pprint->elapse(); pprint->elapse();
@ -321,82 +318,71 @@ int SrsEdgeIngester::ingest()
// read from client. // read from client.
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
if ((ret = upstream->recv_message(&msg)) != ERROR_SUCCESS) { if ((ret = upstream->recv_message(&msg)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) { return srs_error_new(ret, "recv message");
srs_error("pull origin server message failed. ret=%d", ret);
}
return ret;
} }
srs_verbose("edge loop recv message. ret=%d", ret);
srs_assert(msg); srs_assert(msg);
SrsAutoFree(SrsCommonMessage, msg); SrsAutoFree(SrsCommonMessage, msg);
if ((ret = process_publish_message(msg)) != ERROR_SUCCESS) { if ((err = process_publish_message(msg)) != srs_success) {
return ret; return srs_error_wrap(err, "process message");
} }
} }
return ret; return err;
} }
int SrsEdgeIngester::process_publish_message(SrsCommonMessage* msg) srs_error_t SrsEdgeIngester::process_publish_message(SrsCommonMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// process audio packet // process audio packet
if (msg->header.is_audio()) { if (msg->header.is_audio()) {
if ((ret = source->on_audio(msg)) != ERROR_SUCCESS) { if ((err = source->on_audio(msg)) != srs_success) {
srs_error("source process audio message failed. ret=%d", ret); return srs_error_wrap(err, "source consume audio");
return ret;
} }
} }
// process video packet // process video packet
if (msg->header.is_video()) { if (msg->header.is_video()) {
if ((ret = source->on_video(msg)) != ERROR_SUCCESS) { if ((err = source->on_video(msg)) != srs_success) {
srs_error("source process video message failed. ret=%d", ret); return srs_error_wrap(err, "source consume video");
return ret;
} }
} }
// process aggregate packet // process aggregate packet
if (msg->header.is_aggregate()) { if (msg->header.is_aggregate()) {
if ((ret = source->on_aggregate(msg)) != ERROR_SUCCESS) { if ((err = source->on_aggregate(msg)) != srs_success) {
srs_error("source process aggregate message failed. ret=%d", ret); return srs_error_wrap(err, "source consume aggregate");
return ret;
} }
return ret; return err;
} }
// process onMetaData // process onMetaData
if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
SrsPacket* pkt = NULL; SrsPacket* pkt = NULL;
if ((ret = upstream->decode_message(msg, &pkt)) != ERROR_SUCCESS) { if ((ret = upstream->decode_message(msg, &pkt)) != ERROR_SUCCESS) {
srs_error("decode onMetaData message failed. ret=%d", ret); return srs_error_new(ret, "decode message");
return ret;
} }
SrsAutoFree(SrsPacket, pkt); SrsAutoFree(SrsPacket, pkt);
if (dynamic_cast<SrsOnMetaDataPacket*>(pkt)) { if (dynamic_cast<SrsOnMetaDataPacket*>(pkt)) {
SrsOnMetaDataPacket* metadata = dynamic_cast<SrsOnMetaDataPacket*>(pkt); SrsOnMetaDataPacket* metadata = dynamic_cast<SrsOnMetaDataPacket*>(pkt);
if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) { if ((err = source->on_meta_data(msg, metadata)) != srs_success) {
srs_error("source process onMetaData message failed. ret=%d", ret); return srs_error_wrap(err, "source consume metadata");
return ret;
} }
srs_info("process onMetaData message success."); return err;
return ret;
} }
srs_info("ignore AMF0/AMF3 data message."); return err;
return ret;
} }
// call messages, for example, reject, redirect. // call messages, for example, reject, redirect.
if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) { if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {
SrsPacket* pkt = NULL; SrsPacket* pkt = NULL;
if ((ret = upstream->decode_message(msg, &pkt)) != ERROR_SUCCESS) { if ((ret = upstream->decode_message(msg, &pkt)) != ERROR_SUCCESS) {
srs_error("decode call message failed. ret=%d", ret); return srs_error_new(ret, "decode message");
return ret;
} }
SrsAutoFree(SrsPacket, pkt); SrsAutoFree(SrsPacket, pkt);
@ -404,35 +390,33 @@ int SrsEdgeIngester::process_publish_message(SrsCommonMessage* msg)
if (dynamic_cast<SrsCallPacket*>(pkt)) { if (dynamic_cast<SrsCallPacket*>(pkt)) {
SrsCallPacket* call = dynamic_cast<SrsCallPacket*>(pkt); SrsCallPacket* call = dynamic_cast<SrsCallPacket*>(pkt);
if (!call->arguments->is_object()) { if (!call->arguments->is_object()) {
return ret; return err;
} }
SrsAmf0Any* prop = NULL; SrsAmf0Any* prop = NULL;
SrsAmf0Object* evt = call->arguments->to_object(); SrsAmf0Object* evt = call->arguments->to_object();
if ((prop = evt->ensure_property_string("level")) == NULL) { if ((prop = evt->ensure_property_string("level")) == NULL) {
return ret; return err;
} else if (prop->to_str() != StatusLevelError) { } else if (prop->to_str() != StatusLevelError) {
return ret; return err;
} }
if ((prop = evt->get_property("ex")) == NULL || !prop->is_object()) { if ((prop = evt->get_property("ex")) == NULL || !prop->is_object()) {
return ret; return err;
} }
SrsAmf0Object* ex = prop->to_object(); SrsAmf0Object* ex = prop->to_object();
if ((prop = ex->ensure_property_string("redirect")) == NULL) { if ((prop = ex->ensure_property_string("redirect")) == NULL) {
return ret; return err;
} }
redirect = prop->to_str(); redirect = prop->to_str();
ret = ERROR_CONTROL_REDIRECT; return srs_error_new(ERROR_CONTROL_REDIRECT, "RTMP 302 redirect to %s", redirect.c_str());
srs_info("RTMP 302 redirect to %s, ret=%d", redirect.c_str(), ret);
return ret;
} }
} }
return ret; return err;
} }
SrsEdgeForwarder::SrsEdgeForwarder() SrsEdgeForwarder::SrsEdgeForwarder()
@ -591,8 +575,8 @@ srs_error_t SrsEdgeForwarder::do_cycle()
// forward all messages. // forward all messages.
// each msg in msgs.msgs must be free, for the SrsMessageArray never free them. // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
int count = 0; int count = 0;
if ((ret = queue->dump_packets(msgs.max, msgs.msgs, count)) != ERROR_SUCCESS) { if ((err = queue->dump_packets(msgs.max, msgs.msgs, count)) != srs_success) {
return srs_error_new(ret, "queue dumps packets"); return srs_error_wrap(err, "queue dumps packets");
} }
pprint->elapse(); pprint->elapse();
@ -617,13 +601,13 @@ srs_error_t SrsEdgeForwarder::do_cycle()
return err; return err;
} }
int SrsEdgeForwarder::proxy(SrsCommonMessage* msg) srs_error_t SrsEdgeForwarder::proxy(SrsCommonMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if ((ret = send_error_code) != ERROR_SUCCESS) { if ((ret = send_error_code) != ERROR_SUCCESS) {
srs_error("publish edge proxy thread send error, ret=%d", ret); return srs_error_new(ret, "edge forwarder");
return ret;
} }
// the msg is auto free by source, // the msg is auto free by source,
@ -631,24 +615,21 @@ int SrsEdgeForwarder::proxy(SrsCommonMessage* msg)
if (msg->size <= 0 if (msg->size <= 0
|| msg->header.is_set_chunk_size() || msg->header.is_set_chunk_size()
|| msg->header.is_window_ackledgement_size() || msg->header.is_window_ackledgement_size()
|| msg->header.is_ackledgement() || msg->header.is_ackledgement()) {
) { return err;
return ret;
} }
SrsSharedPtrMessage copy; SrsSharedPtrMessage copy;
if ((ret = copy.create(msg)) != ERROR_SUCCESS) { if ((ret = copy.create(msg)) != ERROR_SUCCESS) {
srs_error("initialize the msg failed. ret=%d", ret); return srs_error_new(ret, "create message");
return ret;
} }
srs_verbose("initialize shared ptr msg success.");
copy.stream_id = sdk->sid(); copy.stream_id = sdk->sid();
if ((ret = queue->enqueue(copy.copy())) != ERROR_SUCCESS) { if ((err = queue->enqueue(copy.copy())) != srs_success) {
srs_error("enqueue edge publish msg failed. ret=%d", ret); return srs_error_wrap(err, "enqueue message");
} }
return ret; return err;
} }
SrsPlayEdge::SrsPlayEdge() SrsPlayEdge::SrsPlayEdge()
@ -761,17 +742,13 @@ bool SrsPublishEdge::can_publish()
return state != SrsEdgeStatePublish; return state != SrsEdgeStatePublish;
} }
int SrsPublishEdge::on_client_publish() srs_error_t SrsPublishEdge::on_client_publish()
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
// error when not init state. // error when not init state.
if (state != SrsEdgeStateInit) { if (state != SrsEdgeStateInit) {
ret = ERROR_RTMP_EDGE_PUBLISH_STATE; return srs_error_new(ERROR_RTMP_EDGE_PUBLISH_STATE, "invalid state");
srs_error("invalid state for client to publish stream on edge. "
"state=%d, ret=%d", state, ret);
return ret;
} }
// @see https://github.com/ossrs/srs/issues/180 // @see https://github.com/ossrs/srs/issues/180
@ -786,22 +763,18 @@ int SrsPublishEdge::on_client_publish()
// start to forward stream to origin. // start to forward stream to origin.
err = forwarder->start(); err = forwarder->start();
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
// @see https://github.com/ossrs/srs/issues/180 // @see https://github.com/ossrs/srs/issues/180
// when failed, revert to init // when failed, revert to init
if (ret != ERROR_SUCCESS) { if (err != srs_success) {
SrsEdgeState pstate = state; SrsEdgeState pstate = state;
state = SrsEdgeStateInit; state = SrsEdgeStateInit;
srs_trace("edge revert from %d to state %d (push). ret=%d", pstate, state, ret); srs_trace("edge revert from %d to state %d (push), error %s", pstate, state, srs_error_desc(err).c_str());
} }
return ret; return err;
} }
int SrsPublishEdge::on_proxy_publish(SrsCommonMessage* msg) srs_error_t SrsPublishEdge::on_proxy_publish(SrsCommonMessage* msg)
{ {
return forwarder->proxy(msg); return forwarder->proxy(msg);
} }

@ -139,8 +139,8 @@ public:
private: private:
virtual srs_error_t do_cycle(); virtual srs_error_t do_cycle();
private: private:
virtual int ingest(); virtual srs_error_t ingest();
virtual int process_publish_message(SrsCommonMessage* msg); virtual srs_error_t process_publish_message(SrsCommonMessage* msg);
}; };
/** /**
@ -181,7 +181,7 @@ public:
private: private:
virtual srs_error_t do_cycle(); virtual srs_error_t do_cycle();
public: public:
virtual int proxy(SrsCommonMessage* msg); virtual srs_error_t proxy(SrsCommonMessage* msg);
}; };
/** /**
@ -239,11 +239,11 @@ public:
/** /**
* when client publish stream on edge. * when client publish stream on edge.
*/ */
virtual int on_client_publish(); virtual srs_error_t on_client_publish();
/** /**
* proxy publish stream to edge * proxy publish stream to edge
*/ */
virtual int on_proxy_publish(SrsCommonMessage* msg); virtual srs_error_t on_proxy_publish(SrsCommonMessage* msg);
/** /**
* proxy unpublish stream to edge. * proxy unpublish stream to edge.
*/ */

@ -71,9 +71,9 @@ SrsForwarder::~SrsForwarder()
srs_freep(sh_audio); srs_freep(sh_audio);
} }
int SrsForwarder::initialize(SrsRequest* r, string ep) srs_error_t SrsForwarder::initialize(SrsRequest* r, string ep)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// it's ok to use the request object, // it's ok to use the request object,
// SrsSource already copy it and never delete it. // SrsSource already copy it and never delete it.
@ -82,7 +82,7 @@ int SrsForwarder::initialize(SrsRequest* r, string ep)
// the ep(endpoint) to forward to // the ep(endpoint) to forward to
ep_forward = ep; ep_forward = ep;
return ret; return err;
} }
void SrsForwarder::set_queue_size(double queue_size) void SrsForwarder::set_queue_size(double queue_size)
@ -90,9 +90,8 @@ void SrsForwarder::set_queue_size(double queue_size)
queue->set_queue_size(queue_size); queue->set_queue_size(queue_size);
} }
int SrsForwarder::on_publish() srs_error_t SrsForwarder::on_publish()
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
// discovery the server port and tcUrl from req and ep_forward. // discovery the server port and tcUrl from req and ep_forward.
@ -127,26 +126,17 @@ int SrsForwarder::on_publish()
dest_ep += req->vhost; dest_ep += req->vhost;
if (source_ep == dest_ep) { if (source_ep == dest_ep) {
ret = ERROR_SYSTEM_FORWARD_LOOP; return srs_error_new(ERROR_SYSTEM_FORWARD_LOOP, "forward loop detected. src=%s, dest=%s", source_ep.c_str(), dest_ep.c_str());
srs_warn("forward loop detected. src=%s, dest=%s, ret=%d",
source_ep.c_str(), dest_ep.c_str(), ret);
return ret;
} }
srs_trace("start forward %s to %s, tcUrl=%s, stream=%s", srs_trace("start forward %s to %s, tcUrl=%s, stream=%s", source_ep.c_str(), dest_ep.c_str(), tcUrl.c_str(), req->stream.c_str());
source_ep.c_str(), dest_ep.c_str(), tcUrl.c_str(),
req->stream.c_str());
srs_freep(trd); srs_freep(trd);
trd = new SrsSTCoroutine("forward", this); trd = new SrsSTCoroutine("forward", this);
if ((err = trd->start()) != srs_success) { if ((err = trd->start()) != srs_success) {
// TODO: FIXME: Use error return srs_error_wrap(err, "start thread");
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
return ret; return err;
} }
void SrsForwarder::on_unpublish() void SrsForwarder::on_unpublish()
@ -155,43 +145,33 @@ void SrsForwarder::on_unpublish()
sdk->close(); sdk->close();
} }
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata) srs_error_t SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_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 ((err = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != srs_success) { if ((err = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_freep(metadata); return srs_error_wrap(err, "jitter");
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) { if ((err = queue->enqueue(metadata)) != srs_success) {
return ret; return srs_error_wrap(err, "enqueue metadata");
} }
return ret; return err;
} }
int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio) srs_error_t SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_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 ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) { if ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_freep(msg); return srs_error_wrap(err, "jitter");
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
if (SrsFlvAudio::sh(msg->payload, msg->size)) { if (SrsFlvAudio::sh(msg->payload, msg->size)) {
@ -199,27 +179,22 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio)
sh_audio = msg->copy(); sh_audio = msg->copy();
} }
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { if ((err = queue->enqueue(msg)) != srs_success) {
return ret; return srs_error_wrap(err, "enqueue audio");
} }
return ret; return err;
} }
int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video) srs_error_t SrsForwarder::on_video(SrsSharedPtrMessage* shared_video)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_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 ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) { if ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
srs_freep(msg); return srs_error_wrap(err, "jitter");
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
if (SrsFlvVideo::sh(msg->payload, msg->size)) { if (SrsFlvVideo::sh(msg->payload, msg->size)) {
@ -227,11 +202,11 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video)
sh_video = msg->copy(); sh_video = msg->copy();
} }
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { if ((err = queue->enqueue(msg)) != srs_success) {
return ret; return srs_error_wrap(err, "enqueue video");
} }
return ret; return err;
} }
// when error, forwarder sleep for a while and retry. // when error, forwarder sleep for a while and retry.
@ -287,21 +262,22 @@ srs_error_t SrsForwarder::do_cycle()
return srs_error_new(ret, "sdk publish"); return srs_error_new(ret, "sdk publish");
} }
if ((ret = hub->on_forwarder_start(this)) != ERROR_SUCCESS) { if ((err = hub->on_forwarder_start(this)) != srs_success) {
return srs_error_new(ret, "notify hub start"); return srs_error_wrap(err, "notify hub start");
} }
if ((ret = forward()) != ERROR_SUCCESS) { if ((err = forward()) != srs_success) {
return srs_error_new(ret, "forward"); return srs_error_wrap(err, "forward");
} }
return err; return err;
} }
#define SYS_MAX_FORWARD_SEND_MSGS 128 #define SYS_MAX_FORWARD_SEND_MSGS 128
int SrsForwarder::forward() srs_error_t SrsForwarder::forward()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
sdk->set_recv_timeout(SRS_CONSTS_RTMP_PULSE_TMMS); sdk->set_recv_timeout(SRS_CONSTS_RTMP_PULSE_TMMS);
@ -314,24 +290,18 @@ int SrsForwarder::forward()
// TODO: FIXME: maybe need to zero the sequence header timestamp. // TODO: FIXME: maybe need to zero the sequence header timestamp.
if (sh_video) { if (sh_video) {
if ((ret = sdk->send_and_free_message(sh_video->copy())) != ERROR_SUCCESS) { if ((ret = sdk->send_and_free_message(sh_video->copy())) != ERROR_SUCCESS) {
srs_error("forwarder send sh_video to server failed. ret=%d", ret); return srs_error_new(ret, "send video sh");
return ret;
} }
} }
if (sh_audio) { if (sh_audio) {
if ((ret = sdk->send_and_free_message(sh_audio->copy())) != ERROR_SUCCESS) { if ((ret = sdk->send_and_free_message(sh_audio->copy())) != ERROR_SUCCESS) {
srs_error("forwarder send sh_audio to server failed. ret=%d", ret); return srs_error_new(ret, "send audio sh");
return ret;
} }
} }
while (true) { while (true) {
srs_error_t err = srs_success;
if ((err = trd->pull()) != srs_success) { if ((err = trd->pull()) != srs_success) {
// TODO: FIXME: Use error return srs_error_wrap(err, "thread quit");
ret = srs_error_code(err);
srs_freep(err);
return ret;
} }
pprint->elapse(); pprint->elapse();
@ -341,10 +311,8 @@ int SrsForwarder::forward()
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
ret = sdk->recv_message(&msg); ret = sdk->recv_message(&msg);
srs_verbose("play loop recv message. ret=%d", ret);
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
srs_error("recv server control message failed. ret=%d", ret); return srs_error_new(ret, "receive control message");
return ret;
} }
srs_freep(msg); srs_freep(msg);
@ -353,9 +321,8 @@ int SrsForwarder::forward()
// forward all messages. // forward all messages.
// each msg in msgs.msgs must be free, for the SrsMessageArray never free them. // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
int count = 0; int count = 0;
if ((ret = queue->dump_packets(msgs.max, msgs.msgs, count)) != ERROR_SUCCESS) { if ((err = queue->dump_packets(msgs.max, msgs.msgs, count)) != srs_success) {
srs_error("get message to forward failed. ret=%d", ret); return srs_error_wrap(err, "dump packets");
return ret;
} }
// pithy print // pithy print
@ -365,18 +332,16 @@ int SrsForwarder::forward()
// ignore when no messages. // ignore when no messages.
if (count <= 0) { if (count <= 0) {
srs_verbose("no packets to forward.");
continue; continue;
} }
// sendout messages, all messages are freed by send_and_free_messages(). // sendout messages, all messages are freed by send_and_free_messages().
if ((ret = sdk->send_and_free_messages(msgs.msgs, count)) != ERROR_SUCCESS) { if ((ret = sdk->send_and_free_messages(msgs.msgs, count)) != ERROR_SUCCESS) {
srs_error("forwarder messages to server failed. ret=%d", ret); return srs_error_new(ret, "send messages");
return ret;
} }
} }
return ret; return err;
} }

@ -70,33 +70,33 @@ public:
SrsForwarder(SrsOriginHub* h); SrsForwarder(SrsOriginHub* h);
virtual ~SrsForwarder(); virtual ~SrsForwarder();
public: public:
virtual int initialize(SrsRequest* r, std::string ep); virtual srs_error_t initialize(SrsRequest* r, std::string ep);
virtual void set_queue_size(double queue_size); virtual void set_queue_size(double queue_size);
public: public:
virtual int on_publish(); virtual srs_error_t on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
/** /**
* forward the audio packet. * forward the audio packet.
* @param shared_metadata, directly ptr, copy it if need to save it. * @param shared_metadata, directly ptr, copy it if need to save it.
*/ */
virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata); virtual srs_error_t on_meta_data(SrsSharedPtrMessage* shared_metadata);
/** /**
* forward the audio packet. * forward the audio packet.
* @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); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio);
/** /**
* forward the video packet. * forward the video packet.
* @param shared_video, directly ptr, copy it if need to save it. * @param shared_video, directly ptr, copy it if need to save it.
*/ */
virtual int on_video(SrsSharedPtrMessage* shared_video); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video);
// interface ISrsReusableThread2Handler. // interface ISrsReusableThread2Handler.
public: public:
virtual srs_error_t cycle(); virtual srs_error_t cycle();
private: private:
virtual srs_error_t do_cycle(); virtual srs_error_t do_cycle();
private: private:
virtual int forward(); virtual srs_error_t forward();
}; };
#endif #endif

@ -99,6 +99,7 @@ srs_error_t SrsBufferCache::start()
int SrsBufferCache::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter) int SrsBufferCache::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jitter)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if (fast_cache <= 0) { if (fast_cache <= 0) {
srs_info("http: ignore dump fast cache."); srs_info("http: ignore dump fast cache.");
@ -106,7 +107,10 @@ int SrsBufferCache::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jit
} }
// the jitter is get from SrsSource, which means the time_jitter of vhost. // the jitter is get from SrsSource, which means the time_jitter of vhost.
if ((ret = queue->dump_packets(consumer, false, jitter)) != ERROR_SUCCESS) { if ((err = queue->dump_packets(consumer, false, jitter)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }
@ -118,7 +122,6 @@ int SrsBufferCache::dump_cache(SrsConsumer* consumer, SrsRtmpJitterAlgorithm jit
srs_error_t SrsBufferCache::cycle() srs_error_t SrsBufferCache::cycle()
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
// TODO: FIXME: support reload. // TODO: FIXME: support reload.
@ -130,8 +133,8 @@ srs_error_t SrsBufferCache::cycle()
// the stream cache will create consumer to cache stream, // the stream cache will create consumer to cache stream,
// which will trigger to fetch stream from origin for edge. // which will trigger to fetch stream from origin for edge.
SrsConsumer* consumer = NULL; SrsConsumer* consumer = NULL;
if ((ret = source->create_consumer(NULL, consumer, false, false, true)) != ERROR_SUCCESS) { if ((err = source->create_consumer(NULL, consumer, false, false, true)) != srs_success) {
return srs_error_new(ret, "create consumer"); return srs_error_wrap(err, "create consumer");
} }
SrsAutoFree(SrsConsumer, consumer); SrsAutoFree(SrsConsumer, consumer);
@ -154,8 +157,8 @@ srs_error_t SrsBufferCache::cycle()
// get messages from consumer. // get messages from consumer.
// each msg in msgs.msgs must be free, for the SrsMessageArray never free them. // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
int count = 0; int count = 0;
if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) { if ((err = consumer->dump_packets(&msgs, count)) != srs_success) {
return srs_error_new(ret, "consumer dump packets"); return srs_error_wrap(err, "consumer dump packets");
} }
if (count <= 0) { if (count <= 0) {
@ -521,8 +524,8 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
// create consumer of souce, ignore gop cache, use the audio gop cache. // create consumer of souce, ignore gop cache, use the audio gop cache.
SrsConsumer* consumer = NULL; SrsConsumer* consumer = NULL;
if ((ret = source->create_consumer(NULL, consumer, true, true, !enc->has_cache())) != ERROR_SUCCESS) { if ((err = source->create_consumer(NULL, consumer, true, true, !enc->has_cache())) != srs_success) {
return srs_error_new(ret, "create consumer"); return srs_error_wrap(err, "create consumer");
} }
SrsAutoFree(SrsConsumer, consumer); SrsAutoFree(SrsConsumer, consumer);
srs_verbose("http: consumer created success."); srs_verbose("http: consumer created success.");
@ -579,8 +582,8 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
// get messages from consumer. // get messages from consumer.
// each msg in msgs.msgs must be free, for the SrsMessageArray never free them. // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
int count = 0; int count = 0;
if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) { if ((err = consumer->dump_packets(&msgs, count)) != srs_success) {
return srs_error_new(ret, "consumer dump packets"); return srs_error_wrap(err, "consumer dump packets");
} }
if (count <= 0) { if (count <= 0) {
@ -977,8 +980,8 @@ srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandle
} }
SrsSource* s = NULL; SrsSource* s = NULL;
if ((ret = SrsSource::fetch_or_create(r, server, &s)) != ERROR_SUCCESS) { if ((err = SrsSource::fetch_or_create(r, server, &s)) != srs_success) {
return srs_error_new(ret, "source create"); return srs_error_wrap(err, "source create");
} }
srs_assert(s != NULL); srs_assert(s != NULL);

@ -368,6 +368,7 @@ void SrsPublishRecvThread::stop()
int SrsPublishRecvThread::consume(SrsCommonMessage* msg) int SrsPublishRecvThread::consume(SrsCommonMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// when cid changed, change it. // when cid changed, change it.
if (ncid != cid) { if (ncid != cid) {
@ -386,7 +387,10 @@ int SrsPublishRecvThread::consume(SrsCommonMessage* msg)
srs_update_system_time_ms(), msg->header.timestamp, msg->size); srs_update_system_time_ms(), msg->header.timestamp, msg->size);
// the rtmp connection will handle this message // the rtmp connection will handle this message
ret = _conn->handle_publish_message(_source, msg); err = _conn->handle_publish_message(_source, msg);
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
// must always free it, // must always free it,
// the source will copy it if need to use. // the source will copy it if need to use.

File diff suppressed because it is too large Load Diff

@ -148,24 +148,24 @@ public:
virtual void cleanup(); virtual void cleanup();
private: private:
// when valid and connected to vhost/app, service the client. // when valid and connected to vhost/app, service the client.
virtual int service_cycle(); virtual srs_error_t service_cycle();
// stream(play/publish) service cycle, identify client first. // stream(play/publish) service cycle, identify client first.
virtual int stream_service_cycle(); virtual srs_error_t stream_service_cycle();
virtual int check_vhost(bool try_default_vhost); virtual srs_error_t check_vhost(bool try_default_vhost);
virtual int playing(SrsSource* source); virtual srs_error_t playing(SrsSource* source);
virtual int do_playing(SrsSource* source, SrsConsumer* consumer, SrsQueueRecvThread* trd); virtual srs_error_t do_playing(SrsSource* source, SrsConsumer* consumer, SrsQueueRecvThread* trd);
virtual int publishing(SrsSource* source); virtual srs_error_t publishing(SrsSource* source);
virtual int do_publishing(SrsSource* source, SrsPublishRecvThread* trd); virtual srs_error_t do_publishing(SrsSource* source, SrsPublishRecvThread* trd);
virtual int acquire_publish(SrsSource* source); virtual srs_error_t acquire_publish(SrsSource* source);
virtual void release_publish(SrsSource* source); virtual void release_publish(SrsSource* source);
virtual int handle_publish_message(SrsSource* source, SrsCommonMessage* msg); virtual srs_error_t handle_publish_message(SrsSource* source, SrsCommonMessage* msg);
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg); virtual srs_error_t process_publish_message(SrsSource* source, SrsCommonMessage* msg);
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); virtual srs_error_t process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
virtual void change_mw_sleep(int sleep_ms); virtual void change_mw_sleep(int sleep_ms);
virtual void set_sock_options(); virtual void set_sock_options();
private: private:
virtual int check_edge_token_traverse_auth(); virtual srs_error_t check_edge_token_traverse_auth();
virtual int do_token_traverse_auth(SrsRtmpClient* client); virtual srs_error_t do_token_traverse_auth(SrsRtmpClient* client);
private: private:
/** /**
* when the connection disconnect, call this method. * when the connection disconnect, call this method.

@ -484,6 +484,7 @@ int SrsRtspConn::kickoff_audio_cache(SrsRtpPacket* pkt, int64_t dts)
int SrsRtspConn::write_sequence_header() int SrsRtspConn::write_sequence_header()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// use the current dts. // use the current dts.
int64_t dts = vjitter->timestamp() / 90; int64_t dts = vjitter->timestamp() / 90;
@ -500,7 +501,10 @@ int SrsRtspConn::write_sequence_header()
SrsFormat* format = new SrsFormat(); SrsFormat* format = new SrsFormat();
SrsAutoFree(SrsFormat, format); SrsAutoFree(SrsFormat, format);
if ((ret = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != ERROR_SUCCESS) { if ((err = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret; return ret;
} }

@ -1389,15 +1389,16 @@ srs_error_t SrsServer::on_reload_http_stream_updated()
return err; return err;
} }
int SrsServer::on_publish(SrsSource* s, SrsRequest* r) srs_error_t SrsServer::on_publish(SrsSource* s, SrsRequest* r)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if ((ret = http_server->http_mount(s, r)) != ERROR_SUCCESS) { if ((ret = http_server->http_mount(s, r)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "http mount");
} }
return ret; return err;
} }
void SrsServer::on_unpublish(SrsSource* s, SrsRequest* r) void SrsServer::on_unpublish(SrsSource* s, SrsRequest* r)

@ -382,7 +382,7 @@ public:
virtual srs_error_t on_reload_http_stream_updated(); virtual srs_error_t on_reload_http_stream_updated();
// interface ISrsSourceHandler // interface ISrsSourceHandler
public: public:
virtual int on_publish(SrsSource* s, SrsRequest* r); virtual srs_error_t on_publish(SrsSource* s, SrsRequest* r);
virtual void on_unpublish(SrsSource* s, SrsRequest* r); virtual void on_unpublish(SrsSource* s, SrsRequest* r);
}; };

File diff suppressed because it is too large Load Diff

@ -98,7 +98,7 @@ public:
/** /**
* get current client time, the last packet time. * get current client time, the last packet time.
*/ */
virtual int get_time(); virtual int64_t get_time();
}; };
#ifdef SRS_PERF_QUEUE_FAST_VECTOR #ifdef SRS_PERF_QUEUE_FAST_VECTOR
@ -168,19 +168,19 @@ public:
* @param msg, the msg to enqueue, user never free it whatever the return code. * @param msg, the msg to enqueue, user never free it whatever the return code.
* @param is_overflow, whether overflow and shrinked. NULL to ignore. * @param is_overflow, whether overflow and shrinked. NULL to ignore.
*/ */
virtual int enqueue(SrsSharedPtrMessage* msg, bool* is_overflow = NULL); virtual srs_error_t enqueue(SrsSharedPtrMessage* msg, bool* is_overflow = NULL);
/** /**
* get packets in consumer queue. * get packets in consumer queue.
* @pmsgs SrsSharedPtrMessage*[], used to store the msgs, user must alloc it. * @pmsgs SrsSharedPtrMessage*[], used to store the msgs, user must alloc it.
* @count the count in array, output param. * @count the count in array, output param.
* @max_count the max count to dequeue, must be positive. * @max_count the max count to dequeue, must be positive.
*/ */
virtual int dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, int& count); virtual srs_error_t dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, int& count);
/** /**
* dumps packets to consumer, use specified args. * dumps packets to consumer, use specified args.
* @remark the atc/tba/tbv/ag are same to SrsConsumer.enqueue(). * @remark the atc/tba/tbv/ag are same to SrsConsumer.enqueue().
*/ */
virtual int dump_packets(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag); virtual srs_error_t dump_packets(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag);
private: private:
/** /**
* remove a gop from the front. * remove a gop from the front.
@ -250,21 +250,21 @@ public:
/** /**
* get current client time, the last packet time. * get current client time, the last packet time.
*/ */
virtual int get_time(); virtual int64_t get_time();
/** /**
* enqueue an shared ptr message. * enqueue an shared ptr message.
* @param shared_msg, directly ptr, copy it if need to save it. * @param shared_msg, directly ptr, copy it if need to save it.
* @param whether atc, donot use jitter correct if true. * @param whether atc, donot use jitter correct if true.
* @param ag the algorithm of time jitter. * @param ag the algorithm of time jitter.
*/ */
virtual int enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsRtmpJitterAlgorithm ag); virtual srs_error_t enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsRtmpJitterAlgorithm ag);
/** /**
* get packets in consumer queue. * get packets in consumer queue.
* @param msgs the msgs array to dump packets to send. * @param msgs the msgs array to dump packets to send.
* @param count the count in array, intput and output param. * @param count the count in array, intput and output param.
* @remark user can specifies the count to get specified msgs; 0 to get all if possible. * @remark user can specifies the count to get specified msgs; 0 to get all if possible.
*/ */
virtual int dump_packets(SrsMessageArray* msgs, int& count); virtual srs_error_t dump_packets(SrsMessageArray* msgs, int& count);
#ifdef SRS_PERF_QUEUE_COND_WAIT #ifdef SRS_PERF_QUEUE_COND_WAIT
/** /**
* wait for messages incomming, atleast nb_msgs and in duration. * wait for messages incomming, atleast nb_msgs and in duration.
@ -276,7 +276,7 @@ public:
/** /**
* when client send the pause message. * when client send the pause message.
*/ */
virtual int on_play_client_pause(bool is_pause); virtual srs_error_t on_play_client_pause(bool is_pause);
// ISrsWakable // ISrsWakable
public: public:
/** /**
@ -341,7 +341,7 @@ public:
* 2. clear gop when got keyframe. * 2. clear gop when got keyframe.
* @param shared_msg, directly ptr, copy it if need to save it. * @param shared_msg, directly ptr, copy it if need to save it.
*/ */
virtual int cache(SrsSharedPtrMessage* shared_msg); virtual srs_error_t cache(SrsSharedPtrMessage* shared_msg);
/** /**
* clear the gop cache. * clear the gop cache.
*/ */
@ -349,7 +349,7 @@ public:
/** /**
* dump the cached gop to consumer. * dump the cached gop to consumer.
*/ */
virtual int dump(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm); virtual srs_error_t dump(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm);
/** /**
* used for atc to get the time of gop cache, * used for atc to get the time of gop cache,
* the atc will adjust the sequence header timestamp to gop cache. * the atc will adjust the sequence header timestamp to gop cache.
@ -381,7 +381,7 @@ public:
/** /**
* when stream start publish, mount stream. * when stream start publish, mount stream.
*/ */
virtual int on_publish(SrsSource* s, SrsRequest* r) = 0; virtual srs_error_t on_publish(SrsSource* s, SrsRequest* r) = 0;
/** /**
* when stream stop publish, unmount stream. * when stream stop publish, unmount stream.
*/ */
@ -454,22 +454,22 @@ public:
virtual srs_error_t cycle(); virtual srs_error_t cycle();
public: public:
// When got a parsed metadata. // When got a parsed metadata.
virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata, SrsOnMetaDataPacket* packet); virtual srs_error_t on_meta_data(SrsSharedPtrMessage* shared_metadata, SrsOnMetaDataPacket* packet);
// When got a parsed audio packet. // When got a parsed audio packet.
virtual int on_audio(SrsSharedPtrMessage* shared_audio); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio);
// When got a parsed video packet. // When got a parsed video packet.
virtual int on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, bool is_sequence_header);
public: public:
// When start publish stream. // When start publish stream.
virtual int on_publish(); virtual srs_error_t on_publish();
// When stop publish stream. // When stop publish stream.
virtual void on_unpublish(); virtual void on_unpublish();
// Internal callback. // Internal callback.
public: public:
// for the SrsForwarder to callback to request the sequence headers. // for the SrsForwarder to callback to request the sequence headers.
virtual int on_forwarder_start(SrsForwarder* forwarder); virtual srs_error_t on_forwarder_start(SrsForwarder* forwarder);
// for the SrsDvr to callback to request the sequence headers. // for the SrsDvr to callback to request the sequence headers.
virtual int on_dvr_request_sh(); virtual srs_error_t on_dvr_request_sh();
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual srs_error_t on_reload_vhost_forward(std::string vhost); virtual srs_error_t on_reload_vhost_forward(std::string vhost);
@ -480,7 +480,7 @@ public:
virtual srs_error_t on_reload_vhost_transcode(std::string vhost); virtual srs_error_t on_reload_vhost_transcode(std::string vhost);
virtual srs_error_t on_reload_vhost_exec(std::string vhost); virtual srs_error_t on_reload_vhost_exec(std::string vhost);
private: private:
virtual int create_forwarders(); virtual srs_error_t create_forwarders();
virtual void destroy_forwarders(); virtual void destroy_forwarders();
}; };
@ -518,14 +518,14 @@ public:
// Dumps cached metadata to consumer. // Dumps cached metadata to consumer.
// @param dm Whether dumps the metadata. // @param dm Whether dumps the metadata.
// @param ds Whether dumps the sequence header. // @param ds Whether dumps the sequence header.
virtual int dumps(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds); virtual srs_error_t dumps(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds);
public: public:
// Update the cached metadata by packet. // Update the cached metadata by packet.
virtual int update_data(SrsMessageHeader* header, SrsOnMetaDataPacket* metadata, bool& updated); virtual srs_error_t update_data(SrsMessageHeader* header, SrsOnMetaDataPacket* metadata, bool& updated);
// Update the cached audio sequence header. // Update the cached audio sequence header.
virtual int update_ash(SrsSharedPtrMessage* msg); virtual srs_error_t update_ash(SrsSharedPtrMessage* msg);
// Update the cached video sequence header. // Update the cached video sequence header.
virtual int update_vsh(SrsSharedPtrMessage* msg); virtual srs_error_t update_vsh(SrsSharedPtrMessage* msg);
}; };
/** /**
@ -543,7 +543,7 @@ public:
* @param h the event handler for source. * @param h the event handler for source.
* @param pps the matched source, if success never be NULL. * @param pps the matched source, if success never be NULL.
*/ */
static int fetch_or_create(SrsRequest* r, ISrsSourceHandler* h, SrsSource** pps); static srs_error_t fetch_or_create(SrsRequest* r, ISrsSourceHandler* h, SrsSource** pps);
private: private:
/** /**
* get the exists source, NULL when not exists. * get the exists source, NULL when not exists.
@ -635,30 +635,30 @@ public:
// for the tools callback // for the tools callback
public: public:
// source id changed. // source id changed.
virtual int on_source_id_changed(int id); virtual srs_error_t on_source_id_changed(int id);
// get current source id. // get current source id.
virtual int source_id(); virtual int source_id();
virtual int pre_source_id(); virtual int pre_source_id();
// logic data methods // logic data methods
public: public:
virtual bool can_publish(bool is_edge); virtual bool can_publish(bool is_edge);
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); virtual srs_error_t on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
public: public:
virtual int on_audio(SrsCommonMessage* audio); virtual srs_error_t on_audio(SrsCommonMessage* audio);
private: private:
virtual int on_audio_imp(SrsSharedPtrMessage* audio); virtual srs_error_t on_audio_imp(SrsSharedPtrMessage* audio);
public: public:
virtual int on_video(SrsCommonMessage* video); virtual srs_error_t on_video(SrsCommonMessage* video);
private: private:
virtual int on_video_imp(SrsSharedPtrMessage* video); virtual srs_error_t on_video_imp(SrsSharedPtrMessage* video);
public: public:
virtual int on_aggregate(SrsCommonMessage* msg); virtual srs_error_t on_aggregate(SrsCommonMessage* msg);
/** /**
* publish stream event notify. * publish stream event notify.
* @param _req the request from client, the source will deep copy it, * @param _req the request from client, the source will deep copy it,
* for when reload the request of client maybe invalid. * for when reload the request of client maybe invalid.
*/ */
virtual int on_publish(); virtual srs_error_t on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
// consumer methods // consumer methods
public: public:
@ -669,16 +669,16 @@ public:
* @param dm, whether dumps the metadata. * @param dm, whether dumps the metadata.
* @param dg, whether dumps the gop cache. * @param dg, whether dumps the gop cache.
*/ */
virtual int create_consumer(SrsConnection* conn, SrsConsumer*& consumer, bool ds = true, bool dm = true, bool dg = true); virtual srs_error_t create_consumer(SrsConnection* conn, SrsConsumer*& consumer, bool ds = true, bool dm = true, bool dg = true);
virtual void on_consumer_destroy(SrsConsumer* consumer); virtual void on_consumer_destroy(SrsConsumer* consumer);
virtual void set_cache(bool enabled); virtual void set_cache(bool enabled);
virtual SrsRtmpJitterAlgorithm jitter(); virtual SrsRtmpJitterAlgorithm jitter();
// internal // internal
public: public:
// for edge, when publish edge stream, check the state // for edge, when publish edge stream, check the state
virtual int on_edge_start_publish(); virtual srs_error_t on_edge_start_publish();
// for edge, proxy the publish // for edge, proxy the publish
virtual int on_edge_proxy_publish(SrsCommonMessage* msg); virtual srs_error_t on_edge_proxy_publish(SrsCommonMessage* msg);
// for edge, proxy stop publish // for edge, proxy stop publish
virtual void on_edge_proxy_unpublish(); virtual void on_edge_proxy_unpublish();
public: public:

@ -420,30 +420,28 @@ SrsFrame::~SrsFrame()
srs_freep(codec); srs_freep(codec);
} }
int SrsFrame::initialize(SrsCodecConfig* c) srs_error_t SrsFrame::initialize(SrsCodecConfig* c)
{ {
codec = c; codec = c;
nb_samples = 0; nb_samples = 0;
dts = 0; dts = 0;
cts = 0; cts = 0;
return ERROR_SUCCESS; return srs_success;
} }
int SrsFrame::add_sample(char* bytes, int size) srs_error_t SrsFrame::add_sample(char* bytes, int size)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (nb_samples >= SrsMaxNbSamples) { if (nb_samples >= SrsMaxNbSamples) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "Frame samples overflow");
srs_error("Frame samples overflow, max=%d. ret=%d", SrsMaxNbSamples, ret);
return ret;
} }
SrsSample* sample = &samples[nb_samples++]; SrsSample* sample = &samples[nb_samples++];
sample->bytes = bytes; sample->bytes = bytes;
sample->size = size; sample->size = size;
return ret; return err;
} }
SrsAudioFrame::SrsAudioFrame() SrsAudioFrame::SrsAudioFrame()
@ -472,12 +470,12 @@ SrsVideoFrame::~SrsVideoFrame()
{ {
} }
int SrsVideoFrame::add_sample(char* bytes, int size) srs_error_t SrsVideoFrame::add_sample(char* bytes, int size)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if ((ret = SrsFrame::add_sample(bytes, size)) != ERROR_SUCCESS) { if ((err = SrsFrame::add_sample(bytes, size)) != srs_success) {
return ret; return srs_error_wrap(err, "add frame");
} }
// for video, parse the nalu type, set the IDR flag. // for video, parse the nalu type, set the IDR flag.
@ -495,7 +493,7 @@ int SrsVideoFrame::add_sample(char* bytes, int size)
first_nalu_type = nal_unit_type; first_nalu_type = nal_unit_type;
} }
return ret; return err;
} }
SrsVideoCodecConfig* SrsVideoFrame::vcodec() SrsVideoCodecConfig* SrsVideoFrame::vcodec()
@ -529,24 +527,23 @@ srs_error_t SrsFormat::initialize()
return srs_success; return srs_success;
} }
int SrsFormat::on_audio(int64_t timestamp, char* data, int size) srs_error_t SrsFormat::on_audio(int64_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if (!data || size <= 0) { if (!data || size <= 0) {
srs_trace("no audio present, ignore it."); srs_trace("no audio present, ignore it.");
return ret; return err;
} }
if ((ret = buffer->initialize(data, size)) != ERROR_SUCCESS) { if ((ret = buffer->initialize(data, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init buffer");
} }
// audio decode // audio decode
if (!buffer->require(1)) { if (!buffer->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode sound_format");
srs_error("aac decode sound_format failed. ret=%d", ret);
return ret;
} }
// @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76 // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
@ -554,7 +551,7 @@ int SrsFormat::on_audio(int64_t timestamp, char* data, int size)
SrsAudioCodecId codec = (SrsAudioCodecId)((v >> 4) & 0x0f); SrsAudioCodecId codec = (SrsAudioCodecId)((v >> 4) & 0x0f);
if (codec != SrsAudioCodecIdMP3 && codec != SrsAudioCodecIdAAC) { if (codec != SrsAudioCodecIdMP3 && codec != SrsAudioCodecIdAAC) {
return ret; return err;
} }
if (!acodec) { if (!acodec) {
@ -564,8 +561,8 @@ int SrsFormat::on_audio(int64_t timestamp, char* data, int size)
audio = new SrsAudioFrame(); audio = new SrsAudioFrame();
} }
if ((ret = audio->initialize(acodec)) != ERROR_SUCCESS) { if ((err = audio->initialize(acodec)) != srs_success) {
return ret; return srs_error_wrap(err, "init audio");
} }
// Parse by specified codec. // Parse by specified codec.
@ -578,24 +575,23 @@ int SrsFormat::on_audio(int64_t timestamp, char* data, int size)
return audio_aac_demux(buffer, timestamp); return audio_aac_demux(buffer, timestamp);
} }
int SrsFormat::on_video(int64_t timestamp, char* data, int size) srs_error_t SrsFormat::on_video(int64_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if (!data || size <= 0) { if (!data || size <= 0) {
srs_trace("no video present, ignore it."); srs_trace("no video present, ignore it.");
return ret; return err;
} }
if ((ret = buffer->initialize(data, size)) != ERROR_SUCCESS) { if ((ret = buffer->initialize(data, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init buffer");
} }
// video decode // video decode
if (!buffer->require(1)) { if (!buffer->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode frame_type");
srs_error("avc decode frame_type failed. ret=%d", ret);
return ret;
} }
// @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78 // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
@ -604,7 +600,7 @@ int SrsFormat::on_video(int64_t timestamp, char* data, int size)
// TODO: Support other codecs. // TODO: Support other codecs.
if (codec_id != SrsVideoCodecIdAVC) { if (codec_id != SrsVideoCodecIdAVC) {
return ret; return err;
} }
if (!vcodec) { if (!vcodec) {
@ -614,17 +610,17 @@ int SrsFormat::on_video(int64_t timestamp, char* data, int size)
video = new SrsVideoFrame(); video = new SrsVideoFrame();
} }
if ((ret = video->initialize(vcodec)) != ERROR_SUCCESS) { if ((err = video->initialize(vcodec)) != srs_success) {
return ret; return srs_error_wrap(err, "init video");
} }
buffer->skip(-1 * buffer->pos()); buffer->skip(-1 * buffer->pos());
return video_avc_demux(buffer, timestamp); return video_avc_demux(buffer, timestamp);
} }
int SrsFormat::on_aac_sequence_header(char* data, int size) srs_error_t SrsFormat::on_aac_sequence_header(char* data, int size)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
if (!acodec) { if (!acodec) {
acodec = new SrsAudioCodecConfig(); acodec = new SrsAudioCodecConfig();
@ -633,8 +629,8 @@ int SrsFormat::on_aac_sequence_header(char* data, int size)
audio = new SrsAudioFrame(); audio = new SrsAudioFrame();
} }
if ((ret = audio->initialize(acodec)) != ERROR_SUCCESS) { if ((err = audio->initialize(acodec)) != srs_success) {
return ret; return srs_error_wrap(err, "init audio");
} }
return audio_aac_sequence_header_demux(data, size); return audio_aac_sequence_header_demux(data, size);
@ -652,9 +648,9 @@ bool SrsFormat::is_avc_sequence_header()
&& video && video->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader; && video && video->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader;
} }
int SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp) srs_error_t SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78 // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
int8_t frame_type = stream->read_1bytes(); int8_t frame_type = stream->read_1bytes();
@ -666,22 +662,18 @@ int SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp)
// ignore info frame without error, // ignore info frame without error,
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909 // @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
if (video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) { if (video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) {
srs_warn("avc igone the info frame, ret=%d", ret); srs_warn("avc igone the info frame");
return ret; return err;
} }
// only support h.264/avc // only support h.264/avc
if (codec_id != SrsVideoCodecIdAVC) { if (codec_id != SrsVideoCodecIdAVC) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc only support video h.264/avc, actual=%d", codec_id);
srs_error("avc only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret);
return ret;
} }
vcodec->id = codec_id; vcodec->id = codec_id;
if (!stream->require(4)) { if (!stream->require(4)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode avc_packet_type");
srs_error("avc decode avc_packet_type failed. ret=%d", ret);
return ret;
} }
int8_t avc_packet_type = stream->read_1bytes(); int8_t avc_packet_type = stream->read_1bytes();
int32_t composition_time = stream->read_3bytes(); int32_t composition_time = stream->read_3bytes();
@ -696,27 +688,22 @@ int SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp)
nb_raw = stream->size() - stream->pos(); nb_raw = stream->size() - stream->pos();
if (avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader) { if (avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
if ((ret = avc_demux_sps_pps(stream)) != ERROR_SUCCESS) { if ((err = avc_demux_sps_pps(stream)) != srs_success) {
return ret; return srs_error_wrap(err, "demux SPS/PPS");
} }
} else if (avc_packet_type == SrsVideoAvcFrameTraitNALU){ } else if (avc_packet_type == SrsVideoAvcFrameTraitNALU){
if ((ret = video_nalu_demux(stream)) != ERROR_SUCCESS) { if ((err = video_nalu_demux(stream)) != srs_success) {
return ret; return srs_error_wrap(err, "demux NALU");
} }
} else { } else {
// ignored. // ignored.
} }
srs_info("avc decoded, type=%d, codec=%d, avc=%d, cts=%d, size=%d", frame_type, codec_id, avc_packet_type, return err;
composition_time, stream->size() - stream->pos());
return ret;
} }
int SrsFormat::avc_demux_sps_pps(SrsBuffer* stream) srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
{ {
int ret = ERROR_SUCCESS;
// AVCDecoderConfigurationRecord // AVCDecoderConfigurationRecord
// 5.2.4.1.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16 // 5.2.4.1.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
int avc_extra_size = stream->size() - stream->pos(); int avc_extra_size = stream->size() - stream->pos();
@ -726,9 +713,7 @@ int SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
} }
if (!stream->require(6)) { if (!stream->require(6)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode sequence header");
srs_error("avc decode sequenc header failed. ret=%d", ret);
return ret;
} }
//int8_t configurationVersion = stream->read_1bytes(); //int8_t configurationVersion = stream->read_1bytes();
stream->read_1bytes(); stream->read_1bytes();
@ -750,35 +735,25 @@ int SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
// The value of this field shall be one of 0, 1, or 3 corresponding to a // The value of this field shall be one of 0, 1, or 3 corresponding to a
// length encoded with 1, 2, or 4 bytes, respectively. // length encoded with 1, 2, or 4 bytes, respectively.
if (vcodec->NAL_unit_length == 2) { if (vcodec->NAL_unit_length == 2) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2");
srs_error("sps lengthSizeMinusOne should never be 2. ret=%d", ret);
return ret;
} }
// 1 sps, 7.3.2.1 Sequence parameter set RBSP syntax // 1 sps, 7.3.2.1 Sequence parameter set RBSP syntax
// ISO_IEC_14496-10-AVC-2003.pdf, page 45. // ISO_IEC_14496-10-AVC-2003.pdf, page 45.
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
srs_error("avc decode sequenc header sps failed. ret=%d", ret);
return ret;
} }
int8_t numOfSequenceParameterSets = stream->read_1bytes(); int8_t numOfSequenceParameterSets = stream->read_1bytes();
numOfSequenceParameterSets &= 0x1f; numOfSequenceParameterSets &= 0x1f;
if (numOfSequenceParameterSets != 1) { if (numOfSequenceParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
srs_error("avc decode sequenc header sps failed. ret=%d", ret);
return ret;
} }
if (!stream->require(2)) { if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size");
srs_error("avc decode sequenc header sps size failed. ret=%d", ret);
return ret;
} }
uint16_t sequenceParameterSetLength = stream->read_2bytes(); uint16_t sequenceParameterSetLength = stream->read_2bytes();
if (!stream->require(sequenceParameterSetLength)) { if (!stream->require(sequenceParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data");
srs_error("avc decode sequenc header sps data failed. ret=%d", ret);
return ret;
} }
if (sequenceParameterSetLength > 0) { if (sequenceParameterSetLength > 0) {
vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength); vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength);
@ -786,27 +761,19 @@ int SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
} }
// 1 pps // 1 pps
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS");
srs_error("avc decode sequenc header pps failed. ret=%d", ret);
return ret;
} }
int8_t numOfPictureParameterSets = stream->read_1bytes(); int8_t numOfPictureParameterSets = stream->read_1bytes();
numOfPictureParameterSets &= 0x1f; numOfPictureParameterSets &= 0x1f;
if (numOfPictureParameterSets != 1) { if (numOfPictureParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS");
srs_error("avc decode sequenc header pps failed. ret=%d", ret);
return ret;
} }
if (!stream->require(2)) { if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size");
srs_error("avc decode sequenc header pps size failed. ret=%d", ret);
return ret;
} }
uint16_t pictureParameterSetLength = stream->read_2bytes(); uint16_t pictureParameterSetLength = stream->read_2bytes();
if (!stream->require(pictureParameterSetLength)) { if (!stream->require(pictureParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data");
srs_error("avc decode sequenc header pps data failed. ret=%d", ret);
return ret;
} }
if (pictureParameterSetLength > 0) { if (pictureParameterSetLength > 0) {
vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength); vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength);
@ -816,45 +783,40 @@ int SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
return avc_demux_sps(); return avc_demux_sps();
} }
int SrsFormat::avc_demux_sps() srs_error_t SrsFormat::avc_demux_sps()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if (vcodec->sequenceParameterSetNALUnit.empty()) { if (vcodec->sequenceParameterSetNALUnit.empty()) {
return ret; return err;
} }
SrsBuffer stream; SrsBuffer stream;
char* sps = &vcodec->sequenceParameterSetNALUnit[0]; char* sps = &vcodec->sequenceParameterSetNALUnit[0];
int nbsps = (int)vcodec->sequenceParameterSetNALUnit.size(); int nbsps = (int)vcodec->sequenceParameterSetNALUnit.size();
if ((ret = stream.initialize(sps, nbsps)) != ERROR_SUCCESS) { if ((ret = stream.initialize(sps, nbsps)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init stream");
} }
// for NALU, 7.3.1 NAL unit syntax // for NALU, 7.3.1 NAL unit syntax
// ISO_IEC_14496-10-AVC-2012.pdf, page 61. // ISO_IEC_14496-10-AVC-2012.pdf, page 61.
if (!stream.require(1)) { if (!stream.require(1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
srs_error("avc decode sps failed. ret=%d", ret);
return ret;
} }
int8_t nutv = stream.read_1bytes(); int8_t nutv = stream.read_1bytes();
// forbidden_zero_bit shall be equal to 0. // forbidden_zero_bit shall be equal to 0.
int8_t forbidden_zero_bit = (nutv >> 7) & 0x01; int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
if (forbidden_zero_bit) { if (forbidden_zero_bit) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "forbidden_zero_bit shall be equal to 0");
srs_error("forbidden_zero_bit shall be equal to 0. ret=%d", ret);
return ret;
} }
// nal_ref_idc not equal to 0 specifies that the content of the NAL unit contains a sequence parameter set or a picture // nal_ref_idc not equal to 0 specifies that the content of the NAL unit contains a sequence parameter set or a picture
// parameter set or a slice of a reference picture or a slice data partition of a reference picture. // parameter set or a slice of a reference picture or a slice data partition of a reference picture.
int8_t nal_ref_idc = (nutv >> 5) & 0x03; int8_t nal_ref_idc = (nutv >> 5) & 0x03;
if (!nal_ref_idc) { if (!nal_ref_idc) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_ref_idc shall be not be equal to 0");
srs_error("for sps, nal_ref_idc shall be not be equal to 0. ret=%d", ret);
return ret;
} }
// 7.4.1 NAL unit semantics // 7.4.1 NAL unit semantics
@ -862,9 +824,7 @@ int SrsFormat::avc_demux_sps()
// nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1. // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(nutv & 0x1f); SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(nutv & 0x1f);
if (nal_unit_type != 7) { if (nal_unit_type != 7) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7");
srs_error("for sps, nal_unit_type shall be equal to 7. ret=%d", ret);
return ret;
} }
// decode the rbsp from sps. // decode the rbsp from sps.
@ -894,106 +854,95 @@ int SrsFormat::avc_demux_sps()
} }
int SrsFormat::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp) srs_error_t SrsFormat::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// we donot parse the detail of sps. // we donot parse the detail of sps.
// @see https://github.com/ossrs/srs/issues/474 // @see https://github.com/ossrs/srs/issues/474
if (!avc_parse_sps) { if (!avc_parse_sps) {
return ret; return err;
} }
// reparse the rbsp. // reparse the rbsp.
SrsBuffer stream; SrsBuffer stream;
if ((ret = stream.initialize(rbsp, nb_rbsp)) != ERROR_SUCCESS) { if ((ret = stream.initialize(rbsp, nb_rbsp)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init stream");
} }
// for SPS, 7.3.2.1.1 Sequence parameter set data syntax // for SPS, 7.3.2.1.1 Sequence parameter set data syntax
// ISO_IEC_14496-10-AVC-2012.pdf, page 62. // ISO_IEC_14496-10-AVC-2012.pdf, page 62.
if (!stream.require(3)) { if (!stream.require(3)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps shall atleast 3bytes");
srs_error("sps shall atleast 3bytes. ret=%d", ret);
return ret;
} }
uint8_t profile_idc = stream.read_1bytes(); uint8_t profile_idc = stream.read_1bytes();
if (!profile_idc) { if (!profile_idc) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the profile_idc invalid");
srs_error("sps the profile_idc invalid. ret=%d", ret);
return ret;
} }
int8_t flags = stream.read_1bytes(); int8_t flags = stream.read_1bytes();
if (flags & 0x03) { if (flags & 0x03) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the flags invalid");
srs_error("sps the flags invalid. ret=%d", ret);
return ret;
} }
uint8_t level_idc = stream.read_1bytes(); uint8_t level_idc = stream.read_1bytes();
if (!level_idc) { if (!level_idc) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the level_idc invalid");
srs_error("sps the level_idc invalid. ret=%d", ret);
return ret;
} }
SrsBitBuffer bs; SrsBitBuffer bs;
if ((ret = bs.initialize(&stream)) != ERROR_SUCCESS) { if ((ret = bs.initialize(&stream)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init bit buffer");
} }
int32_t seq_parameter_set_id = -1; int32_t seq_parameter_set_id = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, seq_parameter_set_id)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, seq_parameter_set_id)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read seq_parameter_set_id");
} }
if (seq_parameter_set_id < 0) { if (seq_parameter_set_id < 0) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the seq_parameter_set_id invalid");
srs_error("sps the seq_parameter_set_id invalid. ret=%d", ret);
return ret;
} }
srs_info("sps parse profile=%d, level=%d, sps_id=%d", profile_idc, level_idc, seq_parameter_set_id);
int32_t chroma_format_idc = -1; int32_t chroma_format_idc = -1;
if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244
|| profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118
|| profile_idc == 128 || profile_idc == 128) {
) {
if ((ret = srs_avc_nalu_read_uev(&bs, chroma_format_idc)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, chroma_format_idc)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read chroma_format_idc");
} }
if (chroma_format_idc == 3) { if (chroma_format_idc == 3) {
int8_t separate_colour_plane_flag = -1; int8_t separate_colour_plane_flag = -1;
if ((ret = srs_avc_nalu_read_bit(&bs, separate_colour_plane_flag)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_bit(&bs, separate_colour_plane_flag)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read separate_colour_plane_flag");
} }
} }
int32_t bit_depth_luma_minus8 = -1; int32_t bit_depth_luma_minus8 = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, bit_depth_luma_minus8)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, bit_depth_luma_minus8)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read bit_depth_luma_minus8");;
} }
int32_t bit_depth_chroma_minus8 = -1; int32_t bit_depth_chroma_minus8 = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, bit_depth_chroma_minus8)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, bit_depth_chroma_minus8)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read bit_depth_chroma_minus8");;
} }
int8_t qpprime_y_zero_transform_bypass_flag = -1; int8_t qpprime_y_zero_transform_bypass_flag = -1;
if ((ret = srs_avc_nalu_read_bit(&bs, qpprime_y_zero_transform_bypass_flag)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_bit(&bs, qpprime_y_zero_transform_bypass_flag)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read qpprime_y_zero_transform_bypass_flag");;
} }
int8_t seq_scaling_matrix_present_flag = -1; int8_t seq_scaling_matrix_present_flag = -1;
if ((ret = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read seq_scaling_matrix_present_flag");;
} }
if (seq_scaling_matrix_present_flag) { if (seq_scaling_matrix_present_flag) {
int nb_scmpfs = ((chroma_format_idc != 3)? 8:12); int nb_scmpfs = ((chroma_format_idc != 3)? 8:12);
for (int i = 0; i < nb_scmpfs; i++) { for (int i = 0; i < nb_scmpfs; i++) {
int8_t seq_scaling_matrix_present_flag_i = -1; int8_t seq_scaling_matrix_present_flag_i = -1;
if ((ret = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag_i)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag_i)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read seq_scaling_matrix_present_flag_i");;
} }
} }
} }
@ -1001,147 +950,140 @@ int SrsFormat::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp)
int32_t log2_max_frame_num_minus4 = -1; int32_t log2_max_frame_num_minus4 = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, log2_max_frame_num_minus4)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, log2_max_frame_num_minus4)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read log2_max_frame_num_minus4");;
} }
int32_t pic_order_cnt_type = -1; int32_t pic_order_cnt_type = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, pic_order_cnt_type)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, pic_order_cnt_type)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read pic_order_cnt_type");;
} }
if (pic_order_cnt_type == 0) { if (pic_order_cnt_type == 0) {
int32_t log2_max_pic_order_cnt_lsb_minus4 = -1; int32_t log2_max_pic_order_cnt_lsb_minus4 = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, log2_max_pic_order_cnt_lsb_minus4)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, log2_max_pic_order_cnt_lsb_minus4)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read log2_max_pic_order_cnt_lsb_minus4");;
} }
} else if (pic_order_cnt_type == 1) { } else if (pic_order_cnt_type == 1) {
int8_t delta_pic_order_always_zero_flag = -1; int8_t delta_pic_order_always_zero_flag = -1;
if ((ret = srs_avc_nalu_read_bit(&bs, delta_pic_order_always_zero_flag)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_bit(&bs, delta_pic_order_always_zero_flag)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read delta_pic_order_always_zero_flag");;
} }
int32_t offset_for_non_ref_pic = -1; int32_t offset_for_non_ref_pic = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_non_ref_pic)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_non_ref_pic)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read offset_for_non_ref_pic");;
} }
int32_t offset_for_top_to_bottom_field = -1; int32_t offset_for_top_to_bottom_field = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_top_to_bottom_field)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_top_to_bottom_field)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read offset_for_top_to_bottom_field");;
} }
int32_t num_ref_frames_in_pic_order_cnt_cycle = -1; int32_t num_ref_frames_in_pic_order_cnt_cycle = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, num_ref_frames_in_pic_order_cnt_cycle)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, num_ref_frames_in_pic_order_cnt_cycle)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read num_ref_frames_in_pic_order_cnt_cycle");;
} }
if (num_ref_frames_in_pic_order_cnt_cycle < 0) { if (num_ref_frames_in_pic_order_cnt_cycle < 0) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the num_ref_frames_in_pic_order_cnt_cycle");
srs_error("sps the num_ref_frames_in_pic_order_cnt_cycle invalid. ret=%d", ret);
return ret;
} }
for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) { for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
int32_t offset_for_ref_frame_i = -1; int32_t offset_for_ref_frame_i = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_ref_frame_i)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, offset_for_ref_frame_i)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read offset_for_ref_frame_i");;
} }
} }
} }
int32_t max_num_ref_frames = -1; int32_t max_num_ref_frames = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, max_num_ref_frames)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, max_num_ref_frames)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read max_num_ref_frames");;
} }
int8_t gaps_in_frame_num_value_allowed_flag = -1; int8_t gaps_in_frame_num_value_allowed_flag = -1;
if ((ret = srs_avc_nalu_read_bit(&bs, gaps_in_frame_num_value_allowed_flag)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_bit(&bs, gaps_in_frame_num_value_allowed_flag)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read gaps_in_frame_num_value_allowed_flag");;
} }
int32_t pic_width_in_mbs_minus1 = -1; int32_t pic_width_in_mbs_minus1 = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, pic_width_in_mbs_minus1)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, pic_width_in_mbs_minus1)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read pic_width_in_mbs_minus1");;
} }
int32_t pic_height_in_map_units_minus1 = -1; int32_t pic_height_in_map_units_minus1 = -1;
if ((ret = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != ERROR_SUCCESS) { if ((ret = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "read pic_height_in_map_units_minus1");;
} }
vcodec->width = (int)(pic_width_in_mbs_minus1 + 1) * 16; vcodec->width = (int)(pic_width_in_mbs_minus1 + 1) * 16;
vcodec->height = (int)(pic_height_in_map_units_minus1 + 1) * 16; vcodec->height = (int)(pic_height_in_map_units_minus1 + 1) * 16;
return ret; return err;
} }
int SrsFormat::video_nalu_demux(SrsBuffer* stream) srs_error_t SrsFormat::video_nalu_demux(SrsBuffer* stream)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// ensure the sequence header demuxed // ensure the sequence header demuxed
if (!vcodec->is_avc_codec_ok()) { if (!vcodec->is_avc_codec_ok()) {
srs_warn("avc ignore type=%d for no sequence header. ret=%d", SrsVideoAvcFrameTraitNALU, ret); srs_warn("avc ignore type=%d for no sequence header", SrsVideoAvcFrameTraitNALU);
return ret; return err;
} }
// guess for the first time. // guess for the first time.
if (vcodec->payload_format == SrsAvcPayloadFormatGuess) { if (vcodec->payload_format == SrsAvcPayloadFormatGuess) {
// One or more NALUs (Full frames are required) // One or more NALUs (Full frames are required)
// try "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211. // try "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
if ((ret = avc_demux_annexb_format(stream)) != ERROR_SUCCESS) { if ((err = avc_demux_annexb_format(stream)) != srs_success) {
// stop try when system error. // stop try when system error.
if (ret != ERROR_HLS_AVC_TRY_OTHERS) { if (srs_error_code(err) != ERROR_HLS_AVC_TRY_OTHERS) {
srs_error("avc demux for annexb failed. ret=%d", ret); return srs_error_wrap(err, "avc demux for annexb");
return ret;
} }
srs_freep(err);
// try "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20 // try "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
if ((ret = avc_demux_ibmf_format(stream)) != ERROR_SUCCESS) { if ((err = avc_demux_ibmf_format(stream)) != srs_success) {
return ret; return srs_error_wrap(err, "avc demux ibmf");
} else { } else {
vcodec->payload_format = SrsAvcPayloadFormatIbmf; vcodec->payload_format = SrsAvcPayloadFormatIbmf;
srs_info("hls guess avc payload is ibmf format.");
} }
} else { } else {
vcodec->payload_format = SrsAvcPayloadFormatAnnexb; vcodec->payload_format = SrsAvcPayloadFormatAnnexb;
srs_info("hls guess avc payload is annexb format.");
} }
} else if (vcodec->payload_format == SrsAvcPayloadFormatIbmf) { } else if (vcodec->payload_format == SrsAvcPayloadFormatIbmf) {
// try "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20 // try "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
if ((ret = avc_demux_ibmf_format(stream)) != ERROR_SUCCESS) { if ((err = avc_demux_ibmf_format(stream)) != srs_success) {
return ret; return srs_error_wrap(err, "avc demux ibmf");
} }
srs_info("hls decode avc payload in ibmf format.");
} else { } else {
// One or more NALUs (Full frames are required) // One or more NALUs (Full frames are required)
// try "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211. // try "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
if ((ret = avc_demux_annexb_format(stream)) != ERROR_SUCCESS) { if ((err = avc_demux_annexb_format(stream)) != srs_success) {
// ok, we guess out the payload is annexb, but maybe changed to ibmf. // ok, we guess out the payload is annexb, but maybe changed to ibmf.
if (ret != ERROR_HLS_AVC_TRY_OTHERS) { if (srs_error_code(err) != ERROR_HLS_AVC_TRY_OTHERS) {
srs_error("avc demux for annexb failed. ret=%d", ret); return srs_error_wrap(err, "avc demux annexb");
return ret;
} }
srs_freep(err);
// try "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20 // try "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
if ((ret = avc_demux_ibmf_format(stream)) != ERROR_SUCCESS) { if ((err = avc_demux_ibmf_format(stream)) != srs_success) {
return ret; return srs_error_wrap(err, "avc demux ibmf");
} else { } else {
vcodec->payload_format = SrsAvcPayloadFormatIbmf; vcodec->payload_format = SrsAvcPayloadFormatIbmf;
srs_warn("hls avc payload change from annexb to ibmf format.");
} }
} }
srs_info("hls decode avc payload in annexb format.");
} }
return ret; return err;
} }
int SrsFormat::avc_demux_annexb_format(SrsBuffer* stream) srs_error_t SrsFormat::avc_demux_annexb_format(SrsBuffer* stream)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
// not annexb, try others // not annexb, try others
if (!srs_avc_startswith_annexb(stream, NULL)) { if (!srs_avc_startswith_annexb(stream, NULL)) {
return ERROR_HLS_AVC_TRY_OTHERS; return srs_error_new(ERROR_HLS_AVC_TRY_OTHERS, "try others");
} }
// AnnexB // AnnexB
@ -1151,7 +1093,7 @@ int SrsFormat::avc_demux_annexb_format(SrsBuffer* stream)
// find start code // find start code
int nb_start_code = 0; int nb_start_code = 0;
if (!srs_avc_startswith_annexb(stream, &nb_start_code)) { if (!srs_avc_startswith_annexb(stream, &nb_start_code)) {
return ret; return err;
} }
// skip the start code. // skip the start code.
@ -1179,18 +1121,17 @@ int SrsFormat::avc_demux_annexb_format(SrsBuffer* stream)
} }
// got the NALU. // got the NALU.
if ((ret = video->add_sample(p, (int)(pp - p))) != ERROR_SUCCESS) { if ((err = video->add_sample(p, (int)(pp - p))) != srs_success) {
srs_error("annexb add video sample failed. ret=%d", ret); return srs_error_wrap(err, "add video frame");
return ret;
} }
} }
return ret; return err;
} }
int SrsFormat::avc_demux_ibmf_format(SrsBuffer* stream) srs_error_t SrsFormat::avc_demux_ibmf_format(SrsBuffer* stream)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
int PictureLength = stream->size() - stream->pos(); int PictureLength = stream->size() - stream->pos();
@ -1205,9 +1146,7 @@ int SrsFormat::avc_demux_ibmf_format(SrsBuffer* stream)
for (int i = 0; i < PictureLength;) { for (int i = 0; i < PictureLength;) {
// unsigned int((NAL_unit_length+1)*8) NALUnitLength; // unsigned int((NAL_unit_length+1)*8) NALUnitLength;
if (!stream->require(vcodec->NAL_unit_length + 1)) { if (!stream->require(vcodec->NAL_unit_length + 1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode NALU size");
srs_error("avc decode NALU size failed. ret=%d", ret);
return ret;
} }
int32_t NALUnitLength = 0; int32_t NALUnitLength = 0;
if (vcodec->NAL_unit_length == 3) { if (vcodec->NAL_unit_length == 3) {
@ -1221,33 +1160,28 @@ int SrsFormat::avc_demux_ibmf_format(SrsBuffer* stream)
// maybe stream is invalid format. // maybe stream is invalid format.
// see: https://github.com/ossrs/srs/issues/183 // see: https://github.com/ossrs/srs/issues/183
if (NALUnitLength < 0) { if (NALUnitLength < 0) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "maybe stream is AnnexB format");
srs_error("maybe stream is AnnexB format. ret=%d", ret);
return ret;
} }
// NALUnit // NALUnit
if (!stream->require(NALUnitLength)) { if (!stream->require(NALUnitLength)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode NALU data");
srs_error("avc decode NALU data failed. ret=%d", ret);
return ret;
} }
// 7.3.1 NAL unit syntax, ISO_IEC_14496-10-AVC-2003.pdf, page 44. // 7.3.1 NAL unit syntax, ISO_IEC_14496-10-AVC-2003.pdf, page 44.
if ((ret = video->add_sample(stream->data() + stream->pos(), NALUnitLength)) != ERROR_SUCCESS) { if ((err = video->add_sample(stream->data() + stream->pos(), NALUnitLength)) != srs_success) {
srs_error("avc add video sample failed. ret=%d", ret); return srs_error_wrap(err, "avc add video frame");
return ret;
} }
stream->skip(NALUnitLength); stream->skip(NALUnitLength);
i += vcodec->NAL_unit_length + 1 + NALUnitLength; i += vcodec->NAL_unit_length + 1 + NALUnitLength;
} }
return ret; return err;
} }
int SrsFormat::audio_aac_demux(SrsBuffer* stream, int64_t timestamp) srs_error_t SrsFormat::audio_aac_demux(SrsBuffer* stream, int64_t timestamp)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
audio->cts = 0; audio->cts = 0;
audio->dts = timestamp; audio->dts = timestamp;
@ -1269,20 +1203,16 @@ int SrsFormat::audio_aac_demux(SrsBuffer* stream, int64_t timestamp)
// we support h.264+mp3 for hls. // we support h.264+mp3 for hls.
if (codec_id == SrsAudioCodecIdMP3) { if (codec_id == SrsAudioCodecIdMP3) {
return ERROR_HLS_TRY_MP3; return srs_error_new(ERROR_HLS_TRY_MP3, "try mp3");
} }
// only support aac // only support aac
if (codec_id != SrsAudioCodecIdAAC) { if (codec_id != SrsAudioCodecIdAAC) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "not supported codec %d", codec_id);
srs_error("aac only support mp3/aac codec. actual=%d, ret=%d", codec_id, ret);
return ret;
} }
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode aac_packet_type");
srs_error("aac decode aac_packet_type failed. ret=%d", ret);
return ret;
} }
SrsAudioAacFrameTrait aac_packet_type = (SrsAudioAacFrameTrait)stream->read_1bytes(); SrsAudioAacFrameTrait aac_packet_type = (SrsAudioAacFrameTrait)stream->read_1bytes();
@ -1300,22 +1230,21 @@ int SrsFormat::audio_aac_demux(SrsBuffer* stream, int64_t timestamp)
char *copy_stream_from = stream->data() + stream->pos(); char *copy_stream_from = stream->data() + stream->pos();
acodec->aac_extra_data = std::vector<char>(copy_stream_from, copy_stream_from + aac_extra_size); acodec->aac_extra_data = std::vector<char>(copy_stream_from, copy_stream_from + aac_extra_size);
if ((ret = audio_aac_sequence_header_demux(&acodec->aac_extra_data[0], aac_extra_size)) != ERROR_SUCCESS) { if ((err = audio_aac_sequence_header_demux(&acodec->aac_extra_data[0], aac_extra_size)) != srs_success) {
return ret; return srs_error_wrap(err, "demux aac sh");
} }
} }
} else if (aac_packet_type == SrsAudioAacFrameTraitRawData) { } else if (aac_packet_type == SrsAudioAacFrameTraitRawData) {
// ensure the sequence header demuxed // ensure the sequence header demuxed
if (!acodec->is_aac_codec_ok()) { if (!acodec->is_aac_codec_ok()) {
srs_warn("aac ignore type=%d for no sequence header. ret=%d", aac_packet_type, ret); srs_warn("aac ignore type=%d for no sequence header", aac_packet_type);
return ret; return err;
} }
// Raw AAC frame data in UI8 [] // Raw AAC frame data in UI8 []
// 6.3 Raw Data, ISO_IEC_13818-7-AAC-2004.pdf, page 28 // 6.3 Raw Data, ISO_IEC_13818-7-AAC-2004.pdf, page 28
if ((ret = audio->add_sample(stream->data() + stream->pos(), stream->size() - stream->pos())) != ERROR_SUCCESS) { if ((err = audio->add_sample(stream->data() + stream->pos(), stream->size() - stream->pos())) != srs_success) {
srs_error("aac add sample failed. ret=%d", ret); return srs_error_wrap(err, "add audio frame");
return ret;
} }
} else { } else {
// ignored. // ignored.
@ -1344,15 +1273,12 @@ int SrsFormat::audio_aac_demux(SrsBuffer* stream, int64_t timestamp)
}; };
} }
srs_info("aac decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", sound_type, codec_id, sound_size, return err;
sound_rate, sound_format, stream->size() - stream->pos());
return ret;
} }
int SrsFormat::audio_mp3_demux(SrsBuffer* stream, int64_t timestamp) srs_error_t SrsFormat::audio_mp3_demux(SrsBuffer* stream, int64_t timestamp)
{ {
int ret = ERROR_SUCCESS; srs_error_t err = srs_success;
audio->cts = 0; audio->cts = 0;
audio->dts = timestamp; audio->dts = timestamp;
@ -1381,30 +1307,27 @@ int SrsFormat::audio_mp3_demux(SrsBuffer* stream, int64_t timestamp)
stream->skip(1); stream->skip(1);
if (stream->empty()) { if (stream->empty()) {
return ret; return err;
} }
char* data = stream->data() + stream->pos(); char* data = stream->data() + stream->pos();
int size = stream->size() - stream->pos(); int size = stream->size() - stream->pos();
// mp3 payload. // mp3 payload.
if ((ret = audio->add_sample(data, size)) != ERROR_SUCCESS) { if ((err = audio->add_sample(data, size)) != srs_success) {
srs_error("audio codec add mp3 sample failed. ret=%d", ret); return srs_error_wrap(err, "add audio frame");
return ret;
} }
srs_info("audio decoded, codec=%d, ssize=%d, srate=%d, channels=%d, size=%d", return err;
acodec->id, acodec->sound_size, acodec->sound_rate, acodec->sound_type, size);
return ret;
} }
int SrsFormat::audio_aac_sequence_header_demux(char* data, int size) srs_error_t SrsFormat::audio_aac_sequence_header_demux(char* data, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
if ((ret = buffer->initialize(data, size)) != ERROR_SUCCESS) { if ((ret = buffer->initialize(data, size)) != ERROR_SUCCESS) {
return ret; return srs_error_new(ret, "init buffer");
} }
// only need to decode the first 2bytes: // only need to decode the first 2bytes:
@ -1412,9 +1335,7 @@ int SrsFormat::audio_aac_sequence_header_demux(char* data, int size)
// samplingFrequencyIndex, aac_sample_rate, 4bits. // samplingFrequencyIndex, aac_sample_rate, 4bits.
// channelConfiguration, aac_channels, 4bits // channelConfiguration, aac_channels, 4bits
if (!buffer->require(2)) { if (!buffer->require(2)) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "audio codec decode aac sh");
srs_error("audio codec decode aac sequence header failed. ret=%d", ret);
return ret;
} }
uint8_t profile_ObjectType = buffer->read_1bytes(); uint8_t profile_ObjectType = buffer->read_1bytes();
uint8_t samplingFrequencyIndex = buffer->read_1bytes(); uint8_t samplingFrequencyIndex = buffer->read_1bytes();
@ -1429,10 +1350,7 @@ int SrsFormat::audio_aac_sequence_header_demux(char* data, int size)
// convert the object type in sequence header to aac profile of ADTS. // convert the object type in sequence header to aac profile of ADTS.
acodec->aac_object = (SrsAacObjectType)profile_ObjectType; acodec->aac_object = (SrsAacObjectType)profile_ObjectType;
if (acodec->aac_object == SrsAacObjectTypeReserved) { if (acodec->aac_object == SrsAacObjectTypeReserved) {
ret = ERROR_HLS_DECODE_ERROR; return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode sh object %d", profile_ObjectType);
srs_error("audio codec decode aac sequence header failed, "
"adts object=%d invalid. ret=%d", profile_ObjectType, ret);
return ret;
} }
// TODO: FIXME: to support aac he/he-v2, see: ngx_rtmp_codec_parse_aac_header // TODO: FIXME: to support aac he/he-v2, see: ngx_rtmp_codec_parse_aac_header
@ -1447,6 +1365,6 @@ int SrsFormat::audio_aac_sequence_header_demux(char* data, int size)
//aac_profile = 1; //aac_profile = 1;
//} //}
return ret; return err;
} }

@ -621,9 +621,9 @@ public:
virtual ~SrsFrame(); virtual ~SrsFrame();
public: public:
// Initialize the frame, to parse sampels. // Initialize the frame, to parse sampels.
virtual int initialize(SrsCodecConfig* c); virtual srs_error_t initialize(SrsCodecConfig* c);
// Add a sample to frame. // Add a sample to frame.
virtual int add_sample(char* bytes, int size); virtual srs_error_t add_sample(char* bytes, int size);
}; };
/** /**
@ -662,7 +662,7 @@ public:
virtual ~SrsVideoFrame(); virtual ~SrsVideoFrame();
public: public:
// Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data. // Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data.
virtual int add_sample(char* bytes, int size); virtual srs_error_t add_sample(char* bytes, int size);
public: public:
virtual SrsVideoCodecConfig* vcodec(); virtual SrsVideoCodecConfig* vcodec();
}; };
@ -696,12 +696,12 @@ public:
virtual srs_error_t initialize(); virtual srs_error_t initialize();
// When got a parsed audio packet. // When got a parsed audio packet.
// @param data The data in FLV format. // @param data The data in FLV format.
virtual int on_audio(int64_t timestamp, char* data, int size); virtual srs_error_t on_audio(int64_t timestamp, char* data, int size);
// When got a parsed video packet. // When got a parsed video packet.
// @param data The data in FLV format. // @param data The data in FLV format.
virtual int on_video(int64_t timestamp, char* data, int size); virtual srs_error_t on_video(int64_t timestamp, char* data, int size);
// When got a audio aac sequence header. // When got a audio aac sequence header.
virtual int on_aac_sequence_header(char* data, int size); virtual srs_error_t on_aac_sequence_header(char* data, int size);
public: public:
virtual bool is_aac_sequence_header(); virtual bool is_aac_sequence_header();
virtual bool is_avc_sequence_header(); virtual bool is_avc_sequence_header();
@ -710,28 +710,28 @@ private:
// The packet is muxed in FLV format, defined in flv specification. // The packet is muxed in FLV format, defined in flv specification.
// Demux the sps/pps from sequence header. // Demux the sps/pps from sequence header.
// Demux the samples from NALUs. // Demux the samples from NALUs.
virtual int video_avc_demux(SrsBuffer* stream, int64_t timestamp); virtual srs_error_t video_avc_demux(SrsBuffer* stream, int64_t timestamp);
private: private:
// Parse the H.264 SPS/PPS. // Parse the H.264 SPS/PPS.
virtual int avc_demux_sps_pps(SrsBuffer* stream); virtual srs_error_t avc_demux_sps_pps(SrsBuffer* stream);
virtual int avc_demux_sps(); virtual srs_error_t avc_demux_sps();
virtual int avc_demux_sps_rbsp(char* rbsp, int nb_rbsp); virtual srs_error_t avc_demux_sps_rbsp(char* rbsp, int nb_rbsp);
private: private:
// Parse the H.264 NALUs. // Parse the H.264 NALUs.
virtual int video_nalu_demux(SrsBuffer* stream); virtual srs_error_t video_nalu_demux(SrsBuffer* stream);
// Demux the avc NALU in "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211. // Demux the avc NALU in "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
virtual int avc_demux_annexb_format(SrsBuffer* stream); virtual srs_error_t avc_demux_annexb_format(SrsBuffer* stream);
// Demux the avc NALU in "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20 // Demux the avc NALU in "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
virtual int avc_demux_ibmf_format(SrsBuffer* stream); virtual srs_error_t avc_demux_ibmf_format(SrsBuffer* stream);
private: private:
// Demux the audio packet in AAC codec. // Demux the audio packet in AAC codec.
// Demux the asc from sequence header. // Demux the asc from sequence header.
// Demux the sampels from RAW data. // Demux the sampels from RAW data.
virtual int audio_aac_demux(SrsBuffer* stream, int64_t timestamp); virtual srs_error_t audio_aac_demux(SrsBuffer* stream, int64_t timestamp);
virtual int audio_mp3_demux(SrsBuffer* stream, int64_t timestamp); virtual srs_error_t audio_mp3_demux(SrsBuffer* stream, int64_t timestamp);
public: public:
// Directly demux the sequence header, without RTMP packet header. // Directly demux the sequence header, without RTMP packet header.
virtual int audio_aac_sequence_header_demux(char* data, int size); virtual srs_error_t audio_aac_sequence_header_demux(char* data, int size);
}; };
#endif #endif

@ -37,6 +37,12 @@ bool srs_is_system_control_error(int error_code)
|| error_code == ERROR_CONTROL_REDIRECT; || error_code == ERROR_CONTROL_REDIRECT;
} }
bool srs_is_system_control_error(srs_error_t err)
{
int error_code = srs_error_code(err);
return srs_is_system_control_error(error_code);
}
bool srs_is_client_gracefully_close(int error_code) bool srs_is_client_gracefully_close(int error_code)
{ {
return error_code == ERROR_SOCKET_READ return error_code == ERROR_SOCKET_READ
@ -44,6 +50,12 @@ bool srs_is_client_gracefully_close(int error_code)
|| error_code == ERROR_SOCKET_WRITE; || error_code == ERROR_SOCKET_WRITE;
} }
bool srs_is_client_gracefully_close(srs_error_t err)
{
int error_code = srs_error_code(err);
return srs_is_client_gracefully_close(error_code);
}
SrsCplxError::SrsCplxError() SrsCplxError::SrsCplxError()
{ {
code = ERROR_SUCCESS; code = ERROR_SUCCESS;

@ -325,7 +325,7 @@
// user-define error. // user-define error.
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
#define ERROR_USER_START 9000 #define ERROR_USER_START 9000
#define ERROR_USER_DISCONNECT 9001 //#define ERROR_USER_DISCONNECT 9001
#define ERROR_SOURCE_NOT_FOUND 9002 #define ERROR_SOURCE_NOT_FOUND 9002
#define ERROR_USER_END 9999 #define ERROR_USER_END 9999
@ -334,7 +334,9 @@
*/ */
// TODO: FIXME: Remove it from underlayer for confused with error and logger. // TODO: FIXME: Remove it from underlayer for confused with error and logger.
extern bool srs_is_system_control_error(int error_code); extern bool srs_is_system_control_error(int error_code);
extern bool srs_is_system_control_error(srs_error_t err);
extern bool srs_is_client_gracefully_close(int error_code); extern bool srs_is_client_gracefully_close(int error_code);
extern bool srs_is_client_gracefully_close(srs_error_t err);
// Use complex errors, @read https://github.com/ossrs/srs/issues/913 // Use complex errors, @read https://github.com/ossrs/srs/issues/913
class SrsCplxError class SrsCplxError
@ -374,6 +376,7 @@ public:
#define srs_error_copy(err) SrsCplxError::copy(err) #define srs_error_copy(err) SrsCplxError::copy(err)
#define srs_error_desc(err) SrsCplxError::description(err) #define srs_error_desc(err) SrsCplxError::description(err)
#define srs_error_code(err) SrsCplxError::error_code(err) #define srs_error_code(err) SrsCplxError::error_code(err)
#define srs_error_reset(err) srs_freep(err); err = srs_success
#endif #endif

@ -2957,11 +2957,10 @@ srs_error_t SrsTsTransmuxer::initialize(SrsFileWriter* fw)
srs_error_t SrsTsTransmuxer::write_audio(int64_t timestamp, char* data, int size) srs_error_t SrsTsTransmuxer::write_audio(int64_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
if ((ret = format->on_audio(timestamp, data, size)) != ERROR_SUCCESS) { if ((err = format->on_audio(timestamp, data, size)) != srs_success) {
return srs_error_new(ret, "ts: format on audio"); return srs_error_wrap(err, "ts: format on audio");
} }
// ts support audio codec: aac/mp3 // ts support audio codec: aac/mp3
@ -2994,11 +2993,10 @@ srs_error_t SrsTsTransmuxer::write_audio(int64_t timestamp, char* data, int size
srs_error_t SrsTsTransmuxer::write_video(int64_t timestamp, char* data, int size) srs_error_t SrsTsTransmuxer::write_video(int64_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success; srs_error_t err = srs_success;
if ((ret = format->on_video(timestamp, data, size)) != ERROR_SUCCESS) { if ((err = format->on_video(timestamp, data, size)) != srs_success) {
return srs_error_new(ret, "ts: on video"); return srs_error_wrap(err, "ts: on video");
} }
// ignore info frame, // ignore info frame,

@ -38,16 +38,13 @@ SrsRtmpFormat::~SrsRtmpFormat()
{ {
} }
int SrsRtmpFormat::on_metadata(SrsOnMetaDataPacket* meta) srs_error_t SrsRtmpFormat::on_metadata(SrsOnMetaDataPacket* meta)
{ {
int ret = ERROR_SUCCESS;
// TODO: FIXME: Try to initialize format from metadata. // TODO: FIXME: Try to initialize format from metadata.
return srs_success;
return ret;
} }
int SrsRtmpFormat::on_audio(SrsSharedPtrMessage* shared_audio) srs_error_t SrsRtmpFormat::on_audio(SrsSharedPtrMessage* shared_audio)
{ {
SrsSharedPtrMessage* msg = shared_audio; SrsSharedPtrMessage* msg = shared_audio;
char* data = msg->payload; char* data = msg->payload;
@ -56,12 +53,12 @@ int SrsRtmpFormat::on_audio(SrsSharedPtrMessage* shared_audio)
return SrsFormat::on_audio(msg->timestamp, data, size); return SrsFormat::on_audio(msg->timestamp, data, size);
} }
int SrsRtmpFormat::on_audio(int64_t timestamp, char* data, int size) srs_error_t SrsRtmpFormat::on_audio(int64_t timestamp, char* data, int size)
{ {
return SrsFormat::on_audio(timestamp, data, size); return SrsFormat::on_audio(timestamp, data, size);
} }
int SrsRtmpFormat::on_video(SrsSharedPtrMessage* shared_video) srs_error_t SrsRtmpFormat::on_video(SrsSharedPtrMessage* shared_video)
{ {
SrsSharedPtrMessage* msg = shared_video; SrsSharedPtrMessage* msg = shared_video;
char* data = msg->payload; char* data = msg->payload;
@ -70,7 +67,7 @@ int SrsRtmpFormat::on_video(SrsSharedPtrMessage* shared_video)
return SrsFormat::on_video(msg->timestamp, data, size); return SrsFormat::on_video(msg->timestamp, data, size);
} }
int SrsRtmpFormat::on_video(int64_t timestamp, char* data, int size) srs_error_t SrsRtmpFormat::on_video(int64_t timestamp, char* data, int size)
{ {
return SrsFormat::on_video(timestamp, data, size); return SrsFormat::on_video(timestamp, data, size);
} }

@ -41,13 +41,13 @@ public:
virtual ~SrsRtmpFormat(); virtual ~SrsRtmpFormat();
public: public:
// Initialize the format from metadata, optional. // Initialize the format from metadata, optional.
virtual int on_metadata(SrsOnMetaDataPacket* meta); virtual srs_error_t on_metadata(SrsOnMetaDataPacket* meta);
// When got a parsed audio packet. // When got a parsed audio packet.
virtual int on_audio(SrsSharedPtrMessage* shared_audio); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio);
virtual int on_audio(int64_t timestamp, char* data, int size); virtual srs_error_t on_audio(int64_t timestamp, char* data, int size);
// When got a parsed video packet. // When got a parsed video packet.
virtual int on_video(SrsSharedPtrMessage* shared_video); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video);
virtual int on_video(int64_t timestamp, char* data, int size); virtual srs_error_t on_video(int64_t timestamp, char* data, int size);
}; };
#endif #endif

@ -219,6 +219,7 @@ int SrsRtpPacket::decode(SrsBuffer* stream)
int SrsRtpPacket::decode_97(SrsBuffer* stream) int SrsRtpPacket::decode_97(SrsBuffer* stream)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
// atleast 2bytes content. // atleast 2bytes content.
if (!stream->require(2)) { if (!stream->require(2)) {
@ -265,7 +266,10 @@ int SrsRtpPacket::decode_97(SrsBuffer* stream)
return ret; return ret;
} }
if ((ret = audio->add_sample(sample, sample_size)) != ERROR_SUCCESS) { if ((err = audio->add_sample(sample, sample_size)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
srs_error("rtsp: rtp type97 add sample failed. ret=%d", ret); srs_error("rtsp: rtp type97 add sample failed. ret=%d", ret);
return ret; return ret;
} }

Loading…
Cancel
Save