1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00

merge from 2.0.159

This commit is contained in:
winlin 2015-04-09 12:35:53 +08:00
commit 71e1602458
9 changed files with 91 additions and 29 deletions

View file

@ -566,6 +566,7 @@ Supported operating systems and hardware:
### SRS 2.0 history ### 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-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, 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. * v2.0, 2015-04-03, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155.

View file

@ -127,6 +127,12 @@ int proxy(srs_rtmp_t irtmp, srs_rtmp_t ortmp)
return ret; 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) { if ((ret = srs_human_print_rtmp_packet(type, timestamp, data, size)) != 0) {
srs_human_trace("print packet failed. ret=%d", ret); srs_human_trace("print packet failed. ret=%d", ret);
return ret; return ret;

View file

@ -3093,7 +3093,7 @@ bool SrsConfig::get_log_tank_file()
SrsConfDirective* conf = root->get("srs_log_tank"); SrsConfDirective* conf = root->get("srs_log_tank");
if (!conf || conf->arg0().empty()) { if (!conf || conf->arg0().empty()) {
return false; return true;
} }
return conf->arg0() != SRS_CONF_DEFAULT_LOG_TANK_CONSOLE; return conf->arg0() != SRS_CONF_DEFAULT_LOG_TANK_CONSOLE;

View file

@ -138,14 +138,14 @@ string SrsHlsCacheWriter::cache()
return data; 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; duration = 0;
sequence_no = 0; sequence_no = 0;
segment_start_dts = 0; segment_start_dts = 0;
is_sequence_header = false; is_sequence_header = false;
writer = new SrsHlsCacheWriter(write_cache, write_file); writer = new SrsHlsCacheWriter(write_cache, write_file);
muxer = new SrsTSMuxer(writer, ac, vc); muxer = new SrsTSMuxer(writer, c, ac, vc);
} }
SrsHlsSegment::~SrsHlsSegment() SrsHlsSegment::~SrsHlsSegment()
@ -236,6 +236,7 @@ SrsHlsMuxer::SrsHlsMuxer()
should_write_cache = false; should_write_cache = false;
should_write_file = true; should_write_file = true;
async = new SrsDvrAsyncCallThread(); async = new SrsDvrAsyncCallThread();
context = new SrsTsContext();
} }
SrsHlsMuxer::~SrsHlsMuxer() SrsHlsMuxer::~SrsHlsMuxer()
@ -250,6 +251,7 @@ SrsHlsMuxer::~SrsHlsMuxer()
srs_freep(current); srs_freep(current);
srs_freep(req); srs_freep(req);
srs_freep(async); srs_freep(async);
srs_freep(context);
} }
int SrsHlsMuxer::sequence_no() int SrsHlsMuxer::sequence_no()
@ -269,11 +271,21 @@ double SrsHlsMuxer::duration()
double SrsHlsMuxer::deviation() double SrsHlsMuxer::deviation()
{ {
// no floor, no deviation.
if (!hls_ts_floor) {
return 0;
}
return hls_fragment_deviation; return hls_fragment_deviation;
} }
int SrsHlsMuxer::absolute_deviation() int SrsHlsMuxer::absolute_deviation()
{ {
// no floor, no deviation.
if (!hls_ts_floor) {
return 0;
}
// accept the floor ts for the first piece. // accept the floor ts for the first piece.
int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
return (int)(accept_floor_ts - (floor_ts - 1)); return (int)(accept_floor_ts - (floor_ts - 1));
@ -391,7 +403,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
} }
// new segment. // 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->sequence_no = _sequence_no++;
current->segment_start_dts = segment_start_dts; current->segment_start_dts = segment_start_dts;

View file

@ -56,6 +56,7 @@ class SrsTsAacJitter;
class SrsTsCache; class SrsTsCache;
class SrsHlsSegment; class SrsHlsSegment;
class SrsTsCache; class SrsTsCache;
class SrsTsContext;
/** /**
* the handler for hls event. * the handler for hls event.
@ -145,7 +146,7 @@ public:
// whether current segement is sequence header. // whether current segement is sequence header.
bool is_sequence_header; bool is_sequence_header;
public: 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(); virtual ~SrsHlsSegment();
public: public:
/** /**
@ -229,6 +230,11 @@ private:
* @see https://github.com/winlinvip/simple-rtmp-server/issues/301 * @see https://github.com/winlinvip/simple-rtmp-server/issues/301
*/ */
SrsCodecAudio acodec; SrsCodecAudio acodec;
/**
* the ts context, to keep cc continous between ts.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/375
*/
SrsTsContext* context;
public: public:
SrsHlsMuxer(); SrsHlsMuxer();
virtual ~SrsHlsMuxer(); virtual ~SrsHlsMuxer();

View file

@ -51,10 +51,10 @@ using namespace std;
// the mpegts header specifed the video/audio pid. // the mpegts header specifed the video/audio pid.
#define TS_PMT_NUMBER 1 #define TS_PMT_NUMBER 1
#define TS_PMT_PID 0x100 #define TS_PMT_PID 0x1001
#define TS_VIDEO_AVC_PID 0x101 #define TS_VIDEO_AVC_PID 0x100
#define TS_AUDIO_AAC_PID 0x102 #define TS_AUDIO_AAC_PID 0x101
#define TS_AUDIO_MP3_PID 0x103 #define TS_AUDIO_MP3_PID 0x102
string srs_ts_stream2string(SrsTsStream stream) string srs_ts_stream2string(SrsTsStream stream)
{ {
@ -95,6 +95,7 @@ SrsTsMessage::SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p)
continuity_counter = 0; continuity_counter = 0;
PES_packet_length = 0; PES_packet_length = 0;
payload = new SrsSimpleBuffer(); payload = new SrsSimpleBuffer();
is_discontinuity = false;
start_pts = 0; start_pts = 0;
write_pcr = false; write_pcr = false;
@ -192,6 +193,12 @@ SrsTsContext::~SrsTsContext()
pids.clear(); pids.clear();
} }
void SrsTsContext::reset()
{
vcodec = SrsCodecVideoReserved;
acodec = SrsCodecAudioReserved1;
}
SrsTsChannel* SrsTsContext::get(int pid) SrsTsChannel* SrsTsContext::get(int pid)
{ {
if (pids.find(pid) == pids.end()) { if (pids.find(pid) == pids.end()) {
@ -251,7 +258,7 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsTsStream vs, as; SrsTsStream vs, as;
int16_t video_pid, audio_pid; int16_t video_pid = 0, audio_pid = 0;
switch (vc) { switch (vc) {
case SrsCodecVideoAVC: case SrsCodecVideoAVC:
vs = SrsTsStreamVideoH264; vs = SrsTsStreamVideoH264;
@ -401,9 +408,14 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
write_pcr = true; 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, pkt = SrsTsPacket::create_pes_first(this,
pid, msg->sid, channel->continuity_counter++, msg->discontinuity, pid, msg->sid, channel->continuity_counter++, msg->is_discontinuity,
write_pcr? msg->dts:-1, msg->dts, msg->pts, msg->payload->length() pcr, msg->dts, msg->pts, msg->payload->length()
); );
} else { } else {
pkt = SrsTsPacket::create_pes_continue(this, 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(); int nb_buf = pkt->size();
srs_assert(nb_buf < SRS_TS_PACKET_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; int nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left;
if (nb_stuffings > 0) { if (nb_stuffings > 0) {
// set all bytes to stuffings. // set all bytes to stuffings.
@ -432,7 +444,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
nb_buf = pkt->size(); nb_buf = pkt->size();
srs_assert(nb_buf < SRS_TS_PACKET_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; nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left;
srs_assert(nb_stuffings == 0); srs_assert(nb_stuffings == 0);
} }
@ -703,13 +715,18 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number,
pmt->section_number = 0; pmt->section_number = 0;
pmt->last_section_number = 0; pmt->last_section_number = 0;
pmt->program_info_length = 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) { if (vs == SrsTsStreamVideoH264) {
pmt->PCR_PID = vpid; pmt->PCR_PID = vpid;
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, 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. pmt->CRC_32 = 0; // calc in encode.
return pkt; return pkt;
} }
@ -2604,10 +2621,10 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream)
return ret; return ret;
} }
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc) SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc)
{ {
writer = w; writer = w;
context = NULL; context = c;
acodec = ac; acodec = ac;
vcodec = vc; vcodec = vc;
@ -2625,10 +2642,9 @@ int SrsTSMuxer::open(string _path)
path = _path; path = _path;
close(); close();
// use context to write ts file. // reset the context for a new ts start.
srs_freep(context); context->reset();
context = new SrsTsContext();
if ((ret = writer->open(path)) != ERROR_SUCCESS) { if ((ret = writer->open(path)) != ERROR_SUCCESS) {
return ret; return ret;
@ -2677,7 +2693,6 @@ int SrsTSMuxer::write_video(SrsTsMessage* video)
void SrsTSMuxer::close() void SrsTSMuxer::close()
{ {
srs_freep(context);
writer->close(); writer->close();
} }
@ -2911,6 +2926,8 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
// 9, SI (SI slice) // 9, SI (SI slice)
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105.
static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; 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*)fresh_nalu_header, 4);
video->payload->append((const char*)aud_nalu_7, 2); video->payload->append((const char*)aud_nalu_7, 2);
@ -2973,6 +2990,7 @@ SrsTsEncoder::SrsTsEncoder()
codec = new SrsAvcAacCodec(); codec = new SrsAvcAacCodec();
sample = new SrsCodecSample(); sample = new SrsCodecSample();
cache = new SrsTsCache(); cache = new SrsTsCache();
context = new SrsTsContext();
muxer = NULL; muxer = NULL;
} }
@ -2982,6 +3000,7 @@ SrsTsEncoder::~SrsTsEncoder()
srs_freep(sample); srs_freep(sample);
srs_freep(cache); srs_freep(cache);
srs_freep(muxer); srs_freep(muxer);
srs_freep(context);
} }
int SrsTsEncoder::initialize(SrsFileWriter* fs) int SrsTsEncoder::initialize(SrsFileWriter* fs)
@ -2999,7 +3018,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs)
_fs = fs; _fs = fs;
srs_freep(muxer); srs_freep(muxer);
muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC, SrsCodecVideoAVC); muxer = new SrsTSMuxer(fs, context, SrsCodecAudioAAC, SrsCodecVideoAVC);
if ((ret = muxer->open("")) != ERROR_SUCCESS) { if ((ret = muxer->open("")) != ERROR_SUCCESS) {
return ret; return ret;

View file

@ -47,6 +47,7 @@ class SrsTsAdaptationField;
class SrsTsPayload; class SrsTsPayload;
class SrsTsMessage; class SrsTsMessage;
class SrsTsPacket; class SrsTsPacket;
class SrsTsContext;
// Transport Stream packets are 188 bytes in length. // Transport Stream packets are 188 bytes in length.
#define SRS_TS_PACKET_SIZE 188 #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. // generally, the video IDR(I frame, the keyframe of h.264) carray the pcr info.
bool write_pcr; bool write_pcr;
// whether got discontinuity ts, for example, sequence header changed. // whether got discontinuity ts, for example, sequence header changed.
bool discontinuity; bool is_discontinuity;
public: public:
// the timestamp in 90khz // the timestamp in 90khz
int64_t dts; int64_t dts;
@ -343,6 +344,11 @@ private:
public: public:
SrsTsContext(); SrsTsContext();
virtual ~SrsTsContext(); virtual ~SrsTsContext();
public:
/**
* reset the context for a new ts segment start.
*/
virtual void reset();
// codec // codec
public: public:
/** /**
@ -1533,7 +1539,7 @@ private:
SrsFileWriter* writer; SrsFileWriter* writer;
std::string path; std::string path;
public: public:
SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc); SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc);
virtual ~SrsTSMuxer(); virtual ~SrsTSMuxer();
public: public:
/** /**
@ -1608,6 +1614,7 @@ private:
SrsCodecSample* sample; SrsCodecSample* sample;
SrsTsCache* cache; SrsTsCache* cache;
SrsTSMuxer* muxer; SrsTSMuxer* muxer;
SrsTsContext* context;
public: public:
SrsTsEncoder(); SrsTsEncoder();
virtual ~SrsTsEncoder(); virtual ~SrsTsEncoder();

View file

@ -1973,6 +1973,11 @@ int srs_utils_parse_timestamp(
return ret; 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) 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) { } else if (type == SRS_RTMP_TYPE_SCRIPT) {
srs_human_verbose("Data packet type=%s, time=%d, size=%d", 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; int nparsed = 0;
while (nparsed < size) { while (nparsed < size) {
int nb_parsed_this = 0; 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) { if (amf0 == NULL) {
break; break;
} }
nparsed += nb_parsed_this; nparsed += nb_parsed_this;
char* amf0_str = NULL; char* amf0_str = NULL;

View file

@ -655,6 +655,12 @@ extern int srs_utils_parse_timestamp(
u_int32_t time, char type, char* data, int size, u_int32_t time, char type, char* data, int size,
u_int32_t* ppts 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. * get the CodecID of video tag.