mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 20:31:56 +00:00
merge from 2.0.159
This commit is contained in:
commit
71e1602458
9 changed files with 91 additions and 29 deletions
|
@ -566,6 +566,7 @@ Supported operating systems and hardware:
|
|||
|
||||
### SRS 2.0 history
|
||||
|
||||
* v2.0, 2015-04-08, for [#375](https://github.com/winlinvip/simple-rtmp-server/issues/375), fix hls bug, keep cc continous between ts files. 2.0.159.
|
||||
* v2.0, 2015-04-04, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), rewrite annexb mux for ts, refer to apple sample. 2.0.157.
|
||||
* v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156.
|
||||
* v2.0, 2015-04-03, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155.
|
||||
|
|
|
@ -127,6 +127,12 @@ int proxy(srs_rtmp_t irtmp, srs_rtmp_t ortmp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!srs_utils_flv_tag_is_ok(type)) {
|
||||
srs_human_trace("ignore invalid flv tag=%d, dts=%d, %d bytes", type, timestamp, size);
|
||||
free(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ret = srs_human_print_rtmp_packet(type, timestamp, data, size)) != 0) {
|
||||
srs_human_trace("print packet failed. ret=%d", ret);
|
||||
return ret;
|
||||
|
|
|
@ -3093,7 +3093,7 @@ bool SrsConfig::get_log_tank_file()
|
|||
|
||||
SrsConfDirective* conf = root->get("srs_log_tank");
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return conf->arg0() != SRS_CONF_DEFAULT_LOG_TANK_CONSOLE;
|
||||
|
|
|
@ -138,14 +138,14 @@ string SrsHlsCacheWriter::cache()
|
|||
return data;
|
||||
}
|
||||
|
||||
SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc)
|
||||
SrsHlsSegment::SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc)
|
||||
{
|
||||
duration = 0;
|
||||
sequence_no = 0;
|
||||
segment_start_dts = 0;
|
||||
is_sequence_header = false;
|
||||
writer = new SrsHlsCacheWriter(write_cache, write_file);
|
||||
muxer = new SrsTSMuxer(writer, ac, vc);
|
||||
muxer = new SrsTSMuxer(writer, c, ac, vc);
|
||||
}
|
||||
|
||||
SrsHlsSegment::~SrsHlsSegment()
|
||||
|
@ -236,6 +236,7 @@ SrsHlsMuxer::SrsHlsMuxer()
|
|||
should_write_cache = false;
|
||||
should_write_file = true;
|
||||
async = new SrsDvrAsyncCallThread();
|
||||
context = new SrsTsContext();
|
||||
}
|
||||
|
||||
SrsHlsMuxer::~SrsHlsMuxer()
|
||||
|
@ -250,6 +251,7 @@ SrsHlsMuxer::~SrsHlsMuxer()
|
|||
srs_freep(current);
|
||||
srs_freep(req);
|
||||
srs_freep(async);
|
||||
srs_freep(context);
|
||||
}
|
||||
|
||||
int SrsHlsMuxer::sequence_no()
|
||||
|
@ -269,11 +271,21 @@ double SrsHlsMuxer::duration()
|
|||
|
||||
double SrsHlsMuxer::deviation()
|
||||
{
|
||||
// no floor, no deviation.
|
||||
if (!hls_ts_floor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hls_fragment_deviation;
|
||||
}
|
||||
|
||||
int SrsHlsMuxer::absolute_deviation()
|
||||
{
|
||||
// no floor, no deviation.
|
||||
if (!hls_ts_floor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// accept the floor ts for the first piece.
|
||||
int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
|
||||
return (int)(accept_floor_ts - (floor_ts - 1));
|
||||
|
@ -391,7 +403,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
|
|||
}
|
||||
|
||||
// new segment.
|
||||
current = new SrsHlsSegment(should_write_cache, should_write_file, default_acodec, default_vcodec);
|
||||
current = new SrsHlsSegment(context, should_write_cache, should_write_file, default_acodec, default_vcodec);
|
||||
current->sequence_no = _sequence_no++;
|
||||
current->segment_start_dts = segment_start_dts;
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ class SrsTsAacJitter;
|
|||
class SrsTsCache;
|
||||
class SrsHlsSegment;
|
||||
class SrsTsCache;
|
||||
class SrsTsContext;
|
||||
|
||||
/**
|
||||
* the handler for hls event.
|
||||
|
@ -145,7 +146,7 @@ public:
|
|||
// whether current segement is sequence header.
|
||||
bool is_sequence_header;
|
||||
public:
|
||||
SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc);
|
||||
SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc);
|
||||
virtual ~SrsHlsSegment();
|
||||
public:
|
||||
/**
|
||||
|
@ -229,6 +230,11 @@ private:
|
|||
* @see https://github.com/winlinvip/simple-rtmp-server/issues/301
|
||||
*/
|
||||
SrsCodecAudio acodec;
|
||||
/**
|
||||
* the ts context, to keep cc continous between ts.
|
||||
* @see https://github.com/winlinvip/simple-rtmp-server/issues/375
|
||||
*/
|
||||
SrsTsContext* context;
|
||||
public:
|
||||
SrsHlsMuxer();
|
||||
virtual ~SrsHlsMuxer();
|
||||
|
|
|
@ -51,10 +51,10 @@ using namespace std;
|
|||
|
||||
// the mpegts header specifed the video/audio pid.
|
||||
#define TS_PMT_NUMBER 1
|
||||
#define TS_PMT_PID 0x100
|
||||
#define TS_VIDEO_AVC_PID 0x101
|
||||
#define TS_AUDIO_AAC_PID 0x102
|
||||
#define TS_AUDIO_MP3_PID 0x103
|
||||
#define TS_PMT_PID 0x1001
|
||||
#define TS_VIDEO_AVC_PID 0x100
|
||||
#define TS_AUDIO_AAC_PID 0x101
|
||||
#define TS_AUDIO_MP3_PID 0x102
|
||||
|
||||
string srs_ts_stream2string(SrsTsStream stream)
|
||||
{
|
||||
|
@ -95,6 +95,7 @@ SrsTsMessage::SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p)
|
|||
continuity_counter = 0;
|
||||
PES_packet_length = 0;
|
||||
payload = new SrsSimpleBuffer();
|
||||
is_discontinuity = false;
|
||||
|
||||
start_pts = 0;
|
||||
write_pcr = false;
|
||||
|
@ -192,6 +193,12 @@ SrsTsContext::~SrsTsContext()
|
|||
pids.clear();
|
||||
}
|
||||
|
||||
void SrsTsContext::reset()
|
||||
{
|
||||
vcodec = SrsCodecVideoReserved;
|
||||
acodec = SrsCodecAudioReserved1;
|
||||
}
|
||||
|
||||
SrsTsChannel* SrsTsContext::get(int pid)
|
||||
{
|
||||
if (pids.find(pid) == pids.end()) {
|
||||
|
@ -251,7 +258,7 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo
|
|||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsTsStream vs, as;
|
||||
int16_t video_pid, audio_pid;
|
||||
int16_t video_pid = 0, audio_pid = 0;
|
||||
switch (vc) {
|
||||
case SrsCodecVideoAVC:
|
||||
vs = SrsTsStreamVideoH264;
|
||||
|
@ -401,9 +408,14 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
|
|||
write_pcr = true;
|
||||
}
|
||||
|
||||
// it's ok to set pcr equals to dts,
|
||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/311
|
||||
int64_t pcr = write_pcr? msg->dts : -1;
|
||||
|
||||
// TODO: FIXME: finger it why use discontinuity of msg.
|
||||
pkt = SrsTsPacket::create_pes_first(this,
|
||||
pid, msg->sid, channel->continuity_counter++, msg->discontinuity,
|
||||
write_pcr? msg->dts:-1, msg->dts, msg->pts, msg->payload->length()
|
||||
pid, msg->sid, channel->continuity_counter++, msg->is_discontinuity,
|
||||
pcr, msg->dts, msg->pts, msg->payload->length()
|
||||
);
|
||||
} else {
|
||||
pkt = SrsTsPacket::create_pes_continue(this,
|
||||
|
@ -419,7 +431,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
|
|||
int nb_buf = pkt->size();
|
||||
srs_assert(nb_buf < SRS_TS_PACKET_SIZE);
|
||||
|
||||
int left = srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf);
|
||||
int left = (int)srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf);
|
||||
int nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left;
|
||||
if (nb_stuffings > 0) {
|
||||
// set all bytes to stuffings.
|
||||
|
@ -432,7 +444,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
|
|||
nb_buf = pkt->size();
|
||||
srs_assert(nb_buf < SRS_TS_PACKET_SIZE);
|
||||
|
||||
left = srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf);
|
||||
left = (int)srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf);
|
||||
nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left;
|
||||
srs_assert(nb_stuffings == 0);
|
||||
}
|
||||
|
@ -703,13 +715,18 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number,
|
|||
pmt->section_number = 0;
|
||||
pmt->last_section_number = 0;
|
||||
pmt->program_info_length = 0;
|
||||
|
||||
// use audio to carray pcr by default.
|
||||
// for hls, there must be atleast one audio channel.
|
||||
pmt->PCR_PID = apid;
|
||||
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid));
|
||||
|
||||
// if h.264 specified, use video to carry pcr.
|
||||
if (vs == SrsTsStreamVideoH264) {
|
||||
pmt->PCR_PID = vpid;
|
||||
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid));
|
||||
} else {
|
||||
pmt->PCR_PID = apid;
|
||||
}
|
||||
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid));
|
||||
|
||||
pmt->CRC_32 = 0; // calc in encode.
|
||||
return pkt;
|
||||
}
|
||||
|
@ -2604,10 +2621,10 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc)
|
||||
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc)
|
||||
{
|
||||
writer = w;
|
||||
context = NULL;
|
||||
context = c;
|
||||
|
||||
acodec = ac;
|
||||
vcodec = vc;
|
||||
|
@ -2625,10 +2642,9 @@ int SrsTSMuxer::open(string _path)
|
|||
path = _path;
|
||||
|
||||
close();
|
||||
|
||||
// use context to write ts file.
|
||||
srs_freep(context);
|
||||
context = new SrsTsContext();
|
||||
|
||||
// reset the context for a new ts start.
|
||||
context->reset();
|
||||
|
||||
if ((ret = writer->open(path)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
|
@ -2677,7 +2693,6 @@ int SrsTSMuxer::write_video(SrsTsMessage* video)
|
|||
|
||||
void SrsTSMuxer::close()
|
||||
{
|
||||
srs_freep(context);
|
||||
writer->close();
|
||||
}
|
||||
|
||||
|
@ -2911,6 +2926,8 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
|||
// 9, SI (SI slice)
|
||||
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105.
|
||||
static u_int8_t aud_nalu_7[] = { 0x09, 0xf0};
|
||||
|
||||
// always append a aud nalu for each frame.
|
||||
video->payload->append((const char*)fresh_nalu_header, 4);
|
||||
video->payload->append((const char*)aud_nalu_7, 2);
|
||||
|
||||
|
@ -2973,6 +2990,7 @@ SrsTsEncoder::SrsTsEncoder()
|
|||
codec = new SrsAvcAacCodec();
|
||||
sample = new SrsCodecSample();
|
||||
cache = new SrsTsCache();
|
||||
context = new SrsTsContext();
|
||||
muxer = NULL;
|
||||
}
|
||||
|
||||
|
@ -2982,6 +3000,7 @@ SrsTsEncoder::~SrsTsEncoder()
|
|||
srs_freep(sample);
|
||||
srs_freep(cache);
|
||||
srs_freep(muxer);
|
||||
srs_freep(context);
|
||||
}
|
||||
|
||||
int SrsTsEncoder::initialize(SrsFileWriter* fs)
|
||||
|
@ -2999,7 +3018,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs)
|
|||
_fs = fs;
|
||||
|
||||
srs_freep(muxer);
|
||||
muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC, SrsCodecVideoAVC);
|
||||
muxer = new SrsTSMuxer(fs, context, SrsCodecAudioAAC, SrsCodecVideoAVC);
|
||||
|
||||
if ((ret = muxer->open("")) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
|
|
|
@ -47,6 +47,7 @@ class SrsTsAdaptationField;
|
|||
class SrsTsPayload;
|
||||
class SrsTsMessage;
|
||||
class SrsTsPacket;
|
||||
class SrsTsContext;
|
||||
|
||||
// Transport Stream packets are 188 bytes in length.
|
||||
#define SRS_TS_PACKET_SIZE 188
|
||||
|
@ -258,7 +259,7 @@ public:
|
|||
// generally, the video IDR(I frame, the keyframe of h.264) carray the pcr info.
|
||||
bool write_pcr;
|
||||
// whether got discontinuity ts, for example, sequence header changed.
|
||||
bool discontinuity;
|
||||
bool is_discontinuity;
|
||||
public:
|
||||
// the timestamp in 90khz
|
||||
int64_t dts;
|
||||
|
@ -343,6 +344,11 @@ private:
|
|||
public:
|
||||
SrsTsContext();
|
||||
virtual ~SrsTsContext();
|
||||
public:
|
||||
/**
|
||||
* reset the context for a new ts segment start.
|
||||
*/
|
||||
virtual void reset();
|
||||
// codec
|
||||
public:
|
||||
/**
|
||||
|
@ -1533,7 +1539,7 @@ private:
|
|||
SrsFileWriter* writer;
|
||||
std::string path;
|
||||
public:
|
||||
SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc);
|
||||
SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc);
|
||||
virtual ~SrsTSMuxer();
|
||||
public:
|
||||
/**
|
||||
|
@ -1608,6 +1614,7 @@ private:
|
|||
SrsCodecSample* sample;
|
||||
SrsTsCache* cache;
|
||||
SrsTSMuxer* muxer;
|
||||
SrsTsContext* context;
|
||||
public:
|
||||
SrsTsEncoder();
|
||||
virtual ~SrsTsEncoder();
|
||||
|
|
|
@ -1973,6 +1973,11 @@ int srs_utils_parse_timestamp(
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_bool srs_utils_flv_tag_is_ok(char type)
|
||||
{
|
||||
return type == SRS_RTMP_TYPE_AUDIO || type == SRS_RTMP_TYPE_VIDEO || type == SRS_RTMP_TYPE_SCRIPT;
|
||||
}
|
||||
|
||||
char srs_utils_flv_video_codec_id(char* data, int size)
|
||||
{
|
||||
|
@ -2324,7 +2329,7 @@ int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int
|
|||
);
|
||||
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
|
||||
srs_human_verbose("Data packet type=%s, time=%d, size=%d",
|
||||
srs_human_flv_tag_type2string(type), timestamp, size);
|
||||
srs_human_flv_tag_type2string(type), timestamp, size);
|
||||
int nparsed = 0;
|
||||
while (nparsed < size) {
|
||||
int nb_parsed_this = 0;
|
||||
|
@ -2332,7 +2337,7 @@ int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int
|
|||
if (amf0 == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
nparsed += nb_parsed_this;
|
||||
|
||||
char* amf0_str = NULL;
|
||||
|
|
|
@ -655,6 +655,12 @@ extern int srs_utils_parse_timestamp(
|
|||
u_int32_t time, char type, char* data, int size,
|
||||
u_int32_t* ppts
|
||||
);
|
||||
|
||||
/**
|
||||
* whether the flv tag specified by param type is ok.
|
||||
* @return true when tag is video/audio/script-data; otherwise, false.
|
||||
*/
|
||||
extern srs_bool srs_utils_flv_tag_is_ok(char type);
|
||||
|
||||
/**
|
||||
* get the CodecID of video tag.
|
||||
|
|
Loading…
Reference in a new issue