From 733ba73d543c498a41a87f89e743373e618809ea Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Feb 2017 09:15:46 +0800 Subject: [PATCH] for #738, write mp4 samples. --- trunk/research/librtmp/srs_ingest_mp4.c | 5 ++- trunk/src/app/srs_app_config.cpp | 16 +++---- trunk/src/app/srs_app_recv_thread.cpp | 2 +- trunk/src/app/srs_app_recv_thread.hpp | 2 +- trunk/src/kernel/srs_kernel_consts.hpp | 4 +- trunk/src/kernel/srs_kernel_mp4.cpp | 60 +++++++++++++++++++++++-- trunk/src/kernel/srs_kernel_mp4.hpp | 13 +++++- trunk/src/protocol/srs_protocol_io.hpp | 4 +- 8 files changed, 87 insertions(+), 19 deletions(-) diff --git a/trunk/research/librtmp/srs_ingest_mp4.c b/trunk/research/librtmp/srs_ingest_mp4.c index d24448111..ea4256a7b 100644 --- a/trunk/research/librtmp/srs_ingest_mp4.c +++ b/trunk/research/librtmp/srs_ingest_mp4.c @@ -26,9 +26,13 @@ #include "../../objs/include/srs_librtmp.h" +int64_t tools_main_entrance_startup_time; int proxy(srs_mp4_t mp4, srs_rtmp_t ortmp); int main(int argc, char** argv) { + // main function + tools_main_entrance_startup_time = srs_utils_time_ms(); + printf("Ingest mp4 file and publish to RTMP server like FFMPEG.\n"); printf("SRS(OSSRS) client librtmp library.\n"); printf("Version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); @@ -129,7 +133,6 @@ int connect_oc(srs_rtmp_t ortmp) #define RE_PULSE_MS 300 #define RE_PULSE_JITTER_MS 3000 -int64_t tools_main_entrance_startup_time; int64_t re_create() { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 50ec88522..4960b7089 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4462,7 +4462,7 @@ bool SrsConfig::get_gop_cache(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return SRS_PERF_GOP_CACHE; } @@ -4484,7 +4484,7 @@ bool SrsConfig::get_debug_srs_upnode(string vhost) } conf = conf->get("cluster"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return DEFAULT; } @@ -4506,7 +4506,7 @@ bool SrsConfig::get_atc(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return DEFAULT; } @@ -4528,7 +4528,7 @@ bool SrsConfig::get_atc_auto(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return DEFAULT; } @@ -4550,7 +4550,7 @@ int SrsConfig::get_time_jitter(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return _srs_time_jitter_string2int(DEFAULT); } @@ -4572,7 +4572,7 @@ bool SrsConfig::get_mix_correct(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return DEFAULT; } @@ -4594,7 +4594,7 @@ double SrsConfig::get_queue_length(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return DEFAULT; } @@ -4807,7 +4807,7 @@ int SrsConfig::get_mw_sleep_ms(string vhost) } conf = conf->get("play"); - if (!conf || conf->arg0().empty()) { + if (!conf) { return SRS_PERF_MW_SLEEP; } diff --git a/trunk/src/app/srs_app_recv_thread.cpp b/trunk/src/app/srs_app_recv_thread.cpp index 869a40a01..434421cf6 100644 --- a/trunk/src/app/srs_app_recv_thread.cpp +++ b/trunk/src/app/srs_app_recv_thread.cpp @@ -288,7 +288,7 @@ SrsPublishRecvThread::~SrsPublishRecvThread() st_cond_destroy(error); } -int SrsPublishRecvThread::wait(int timeout_ms) +int SrsPublishRecvThread::wait(uint64_t timeout_ms) { if (recv_error_code != ERROR_SUCCESS) { return recv_error_code; diff --git a/trunk/src/app/srs_app_recv_thread.hpp b/trunk/src/app/srs_app_recv_thread.hpp index f268b0ebf..54d5750de 100644 --- a/trunk/src/app/srs_app_recv_thread.hpp +++ b/trunk/src/app/srs_app_recv_thread.hpp @@ -196,7 +196,7 @@ public: /** * wait for error for some timeout. */ - virtual int wait(int timeout_ms); + virtual int wait(uint64_t timeout_ms); virtual int64_t nb_msgs(); virtual int error_code(); virtual void set_cid(int v); diff --git a/trunk/src/kernel/srs_kernel_consts.hpp b/trunk/src/kernel/srs_kernel_consts.hpp index 03db74ad9..461fc1b4f 100644 --- a/trunk/src/kernel/srs_kernel_consts.hpp +++ b/trunk/src/kernel/srs_kernel_consts.hpp @@ -68,7 +68,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // the following is the timeout for rtmp protocol, // to avoid death connection. -// Never timeout in ms. +// Never timeout in ms +// @remake Rename from SRS_CONSTS_NO_TIMEOUT +// @see ST_UTIME_NO_TIMEOUT #define SRS_CONSTS_NO_TMMS ((int64_t) -1LL) // the common io timeout, for both recv and send. diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index fc02b9586..339f54760 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -3184,12 +3184,12 @@ SrsMp4Sample::~SrsMp4Sample() srs_freepa(data); } -uint32_t SrsMp4Sample::get_dts() +uint32_t SrsMp4Sample::dts_ms() { return (uint32_t)(dts * 1000 / tbn); } -uint32_t SrsMp4Sample::get_pts() +uint32_t SrsMp4Sample::pts_ms() { return (uint32_t)(pts * 1000 / tbn); } @@ -3237,6 +3237,14 @@ int SrsMp4SampleManager::load(SrsMp4MovieBox* moov) return ret; } +SrsMp4Sample* SrsMp4SampleManager::at(uint32_t index) +{ + if (index >= samples.size() - 1) { + return NULL; + } + return samples.at(index); +} + int SrsMp4SampleManager::do_load(map& tses, SrsMp4MovieBox* moov) { int ret = ERROR_SUCCESS; @@ -3349,6 +3357,10 @@ int SrsMp4SampleManager::load_trak(map& tses, SrsCodecF } } + // Only set the sample size, read data from io when needed. + sample->nb_data = sample_size; + sample->data = NULL; + previous = sample; tses[sample->offset] = sample; } @@ -3379,6 +3391,8 @@ SrsMp4Decoder::SrsMp4Decoder() sound_bits = SrsCodecAudioSampleSizeForbidden; channels = SrsCodecAudioSoundTypeForbidden; samples = new SrsMp4SampleManager(); + current_index = 0; + current_offset = 0; } SrsMp4Decoder::~SrsMp4Decoder() @@ -3437,7 +3451,7 @@ int SrsMp4Decoder::initialize(ISrsReadSeeker* rs) // Set the offset to the mdat. if (offset >= 0) { - return rsio->lseek(offset, SEEK_SET, NULL); + return rsio->lseek(offset, SEEK_SET, ¤t_offset); } return ret; @@ -3478,6 +3492,46 @@ int SrsMp4Decoder::read_sample(SrsMp4HandlerType* pht, return ret; } + SrsMp4Sample* ps = samples->at(current_index++); + if (!ps) { + return ERROR_SYSTEM_FILE_EOF; + } + + if (ps->type == SrsCodecFlvTagVideo) { + *pht = SrsMp4HandlerTypeVIDE; + *pct = SrsCodecVideoAVCTypeNALU; + } else { + *pht = SrsMp4HandlerTypeSOUN; + *pct = SrsCodecAudioTypeRawData; + } + *pdts = ps->dts_ms(); + *ppts = ps->pts_ms(); + *pft = ps->frame_type; + + if (ps->type == SrsCodecFlvTagAudio) { + *pdts = ps->dts_ms() + 34; + *ppts = ps->pts_ms() + 34; + } + + // Read sample from io, for we never preload the samples(too large). + if (ps->offset != current_offset) { + if ((ret = rsio->lseek(ps->offset, SEEK_SET, ¤t_offset)) != ERROR_SUCCESS) { + return ret; + } + } + + uint32_t nb_sample = ps->nb_data; + uint8_t* sample = new uint8_t[nb_sample]; + // TODO: FIXME: Use fully read. + if ((ret = rsio->read(sample, nb_sample, NULL)) != ERROR_SUCCESS) { + srs_freepa(sample); + return ret; + } + + *psample = sample; + *pnb_sample = nb_sample; + current_offset += nb_sample; + return ret; } diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index a9c48bdc4..16a590c34 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -1435,9 +1435,9 @@ public: virtual ~SrsMp4Sample(); public: // Get the dts in ms. - virtual uint32_t get_dts(); + virtual uint32_t dts_ms(); // Get the pts in ms. - virtual uint32_t get_pts(); + virtual uint32_t pts_ms(); }; /** @@ -1464,6 +1464,11 @@ public: * There must be atleast one track. */ virtual int load(SrsMp4MovieBox* moov); + /** + * Get the sample at index position. + * @remark NULL if exceed the max index. + */ + virtual SrsMp4Sample* at(uint32_t index); private: virtual int do_load(std::map& tses, SrsMp4MovieBox* moov); private: @@ -1484,7 +1489,11 @@ class SrsMp4Decoder private: // The major brand of decoder, parse from ftyp. SrsMp4BoxBrand brand; + // The samples build from moov. SrsMp4SampleManager* samples; + // The current written sample information. + uint32_t current_index; + off_t current_offset; public: // The video codec of first track, generally there is zero or one track. // Forbidden if no video stream. diff --git a/trunk/src/protocol/srs_protocol_io.hpp b/trunk/src/protocol/srs_protocol_io.hpp index 8939061b1..27d6b7e61 100644 --- a/trunk/src/protocol/srs_protocol_io.hpp +++ b/trunk/src/protocol/srs_protocol_io.hpp @@ -94,7 +94,7 @@ public: public: /** * Set the timeout tm in ms for recv bytes from peer. - * @remark Use SRS_CONSTS_NO_TIMEOUT to never timeout. + * @remark Use SRS_CONSTS_NO_TMMS to never timeout. */ virtual void set_recv_timeout(int64_t tm) = 0; /** @@ -122,7 +122,7 @@ public: public: /** * Set the timeout tm in ms for send bytes to peer. - * @remark Use SRS_CONSTS_NO_TIMEOUT to never timeout. + * @remark Use SRS_CONSTS_NO_TMMS to never timeout. */ virtual void set_send_timeout(int64_t tm) = 0; /**