mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
add ts mux framework
This commit is contained in:
parent
4af3982721
commit
385394315d
5 changed files with 155 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -23,6 +23,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_core_hls.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <srs_core_error.hpp>
|
||||
#include <srs_core_codec.hpp>
|
||||
#include <srs_core_amf0.hpp>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue