From 385394315dfa8751c68b9c87dc9934676daf1c65 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 24 Nov 2013 17:53:36 +0800 Subject: [PATCH] add ts mux framework --- trunk/src/core/srs_core_codec.cpp | 17 ++++- trunk/src/core/srs_core_codec.hpp | 11 +++ trunk/src/core/srs_core_error.hpp | 2 + trunk/src/core/srs_core_hls.cpp | 122 +++++++++++++++++++++++++++++- trunk/src/core/srs_core_hls.hpp | 7 +- 5 files changed, 155 insertions(+), 4 deletions(-) diff --git a/trunk/src/core/srs_core_codec.cpp b/trunk/src/core/srs_core_codec.cpp index 8177f6e55..a38c9e964 100644 --- a/trunk/src/core/srs_core_codec.cpp +++ b/trunk/src/core/srs_core_codec.cpp @@ -41,8 +41,13 @@ SrsCodecSample::~SrsCodecSample() void SrsCodecSample::clear() { - cts = 0; + is_video = false; nb_buffers = 0; + + cts = 0; + frame_type = SrsCodecVideoAVCFrameReserved; + codec_id = SrsCodecVideoReserved; + avc_packet_type = SrsCodecVideoAVCTypeReserved; } int SrsCodecSample::add_sample(char* bytes, int size) @@ -99,6 +104,8 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; + sample->is_video = false; + if (!data || size <= 0) { srs_trace("no audio present, hls ignore it."); return ret; @@ -176,6 +183,8 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; + sample->is_video = true; + if (!data || size <= 0) { srs_trace("no video present, hls ignore it."); return ret; @@ -196,13 +205,16 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) int8_t codec_id = frame_type & 0x0f; frame_type = (frame_type >> 4) & 0x0f; - video_codec_id = codec_id; + sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; + sample->codec_id = (SrsCodecVideo)codec_id; + // only support h.264/avc if (codec_id != SrsCodecVideoAVC) { ret = ERROR_HLS_DECODE_ERROR; srs_error("hls only support video h.264/avc codec. ret=%d", ret); return ret; } + video_codec_id = codec_id; if (!stream->require(4)) { ret = ERROR_HLS_DECODE_ERROR; @@ -214,6 +226,7 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) // pts = dts + cts. sample->cts = composition_time; + sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { // AVCDecoderConfigurationRecord diff --git a/trunk/src/core/srs_core_codec.hpp b/trunk/src/core/srs_core_codec.hpp index ad164283a..64a390026 100644 --- a/trunk/src/core/srs_core_codec.hpp +++ b/trunk/src/core/srs_core_codec.hpp @@ -45,6 +45,8 @@ class SrsStream; // 7 = AVC enum SrsCodecVideo { + SrsCodecVideoReserved = 0, + SrsCodecVideoSorensonH263 = 2, SrsCodecVideoScreenVideo = 3, SrsCodecVideoOn2VP6 = 4, @@ -63,6 +65,8 @@ enum SrsCodecVideo // 5 = video info/command frame enum SrsCodecVideoAVCFrame { + SrsCodecVideoAVCFrameReserved = 0, + SrsCodecVideoAVCFrameKeyFrame = 1, SrsCodecVideoAVCFrameInterFrame = 2, SrsCodecVideoAVCFrameDisposableInterFrame = 3, @@ -78,6 +82,8 @@ enum SrsCodecVideoAVCFrame // not required or supported) enum SrsCodecVideoAVCType { + SrsCodecVideoAVCTypeReserved = -1, + SrsCodecVideoAVCTypeSequenceHeader = 0, SrsCodecVideoAVCTypeNALU = 1, SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, @@ -180,9 +186,14 @@ class SrsCodecSample public: int nb_buffers; SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; +public: + bool is_video; // CompositionTime, video_file_format_spec_v10_1.pdf, page 78. // cts = pts - dts, where dts = flvheader->timestamp. int32_t cts; + SrsCodecVideoAVCFrame frame_type; + SrsCodecVideo codec_id; + SrsCodecVideoAVCType avc_packet_type; public: SrsCodecSample(); virtual ~SrsCodecSample(); diff --git a/trunk/src/core/srs_core_error.hpp b/trunk/src/core/srs_core_error.hpp index 3d1813366..710665350 100644 --- a/trunk/src/core/srs_core_error.hpp +++ b/trunk/src/core/srs_core_error.hpp @@ -110,5 +110,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_HLS_METADATA 600 #define ERROR_HLS_DECODE_ERROR 601 #define ERROR_HLS_BUSY 602 +#define ERROR_HLS_OPEN_FAILED 603 +#define ERROR_HLS_WRITE_FAILED 604 #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_hls.cpp b/trunk/src/core/srs_core_hls.cpp index 596ba718f..c07935df5 100644 --- a/trunk/src/core/srs_core_hls.cpp +++ b/trunk/src/core/srs_core_hls.cpp @@ -23,6 +23,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include +#include +#include + #include #include #include @@ -63,6 +67,9 @@ int SrsHLS::on_publish(std::string _vhost) if (!conf && conf->arg0() == "off") { return ret; } + + // TODO: check the audio and video, ensure both exsists. + // for use fixed mpegts header specifeid the audio and video pid. hls_enabled = true; @@ -71,6 +78,9 @@ int SrsHLS::on_publish(std::string _vhost) path = conf->arg0(); } + // TODO: generate by m3u8 muxer. + path += "/1.ts"; + if ((ret = muxer->open(path)) != ERROR_SUCCESS) { srs_error("open hls muxer failed. ret=%d", ret); return ret; @@ -82,6 +92,7 @@ int SrsHLS::on_publish(std::string _vhost) void SrsHLS::on_unpublish() { hls_enabled = false; + muxer->close(); srs_freep(muxer); } @@ -185,6 +196,10 @@ int SrsHLS::on_audio(SrsCommonMessage* audio) return ret; } + if ((ret = muxer->write(codec, sample)) != ERROR_SUCCESS) { + return ret; + } + return ret; } @@ -206,20 +221,125 @@ int SrsHLS::on_video(SrsCommonMessage* video) return ret; } + if ((ret = muxer->write(codec, sample)) != ERROR_SUCCESS) { + return ret; + } + return ret; } +// @see: ngx_rtmp_mpegts_header +static u_char mpegts_header[] = { + /* TS */ + 0x47, 0x40, 0x00, 0x10, 0x00, + /* PSI */ + 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00, + /* PAT */ + 0x00, 0x01, 0xf0, 0x01, + /* CRC */ + 0x2e, 0x70, 0x19, 0x05, + /* stuffing 167 bytes */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + + /* TS */ + 0x47, 0x50, 0x01, 0x10, 0x00, + /* PSI */ + 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00, + /* PMT */ + 0xe1, 0x00, + 0xf0, 0x00, + 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */ + 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */ + /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */ + /* CRC */ + 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */ + /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */ + /* stuffing 157 bytes */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +// the mpegts header specifed the video/audio pid. +#define TS_VIDEO_PID 256 +#define TS_AUDIO_PID 257 + SrsTSMuxer::SrsTSMuxer() { + fd = -1; } SrsTSMuxer::~SrsTSMuxer() { + close(); } -int SrsTSMuxer::open(std::string path) +int SrsTSMuxer::open(std::string _path) +{ + int ret = ERROR_SUCCESS; + + path = _path; + + close(); + + int flags = O_CREAT|O_WRONLY|O_TRUNC; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; + if ((fd = ::open(path.c_str(), flags, mode)) < 0) { + ret = ERROR_HLS_OPEN_FAILED; + srs_error("open ts file %s failed. ret=%d", path.c_str(), ret); + return ret; + } + + // write mpegts header + if (::write(fd, mpegts_header, sizeof(mpegts_header)) != sizeof(mpegts_header)) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write ts file header %s failed. ret=%d", path.c_str(), ret); + return ret; + } + + return ret; +} + +int SrsTSMuxer::write(SrsCodec* codec, SrsCodecSample* sample) { int ret = ERROR_SUCCESS; return ret; } +void SrsTSMuxer::close() +{ + if (fd > 0) { + ::close(fd); + fd = -1; + } +} + diff --git a/trunk/src/core/srs_core_hls.hpp b/trunk/src/core/srs_core_hls.hpp index 14ef95da7..60201841b 100644 --- a/trunk/src/core/srs_core_hls.hpp +++ b/trunk/src/core/srs_core_hls.hpp @@ -58,11 +58,16 @@ public: class SrsTSMuxer { +private: + int fd; + std::string path; public: SrsTSMuxer(); virtual ~SrsTSMuxer(); public: - virtual int open(std::string path); + virtual int open(std::string _path); + virtual int write(SrsCodec* codec, SrsCodecSample* sample); + virtual void close(); }; #endif \ No newline at end of file