winlin

abs overflow also plus the deviation, for pure audio hls.

... ... @@ -559,7 +559,13 @@ bool SrsHlsMuxer::is_segment_absolutely_overflow()
{
// @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-83553950
srs_assert(current);
return current->duration >= hls_aof_ratio * hls_fragment;
// use N% deviation, to smoother.
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
srs_info("hls: dur=%.2f, tar=%.2f, dev=%.2fms/%dp, frag=%.2f",
current->duration, hls_fragment + deviation, deviation, deviation_ts, hls_fragment);
return current->duration >= hls_aof_ratio * hls_fragment + deviation;
}
int SrsHlsMuxer::update_acodec(SrsCodecAudio ac)
... ... @@ -968,7 +974,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
// we use absolutely overflow of segment to make jwplayer/ffplay happy
// @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184
if (cache->audio && muxer->is_segment_absolutely_overflow()) {
srs_warn("hls: absolute audio reap segment.");
srs_info("hls: absolute audio reap segment.");
if ((ret = reap_segment("audio", muxer, cache->audio->pts)) != ERROR_SUCCESS) {
return ret;
}
... ... @@ -991,7 +997,7 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
// do reap ts if any of:
// a. wait keyframe and got keyframe.
// b. always reap when not wait keyframe.
if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
if (!muxer->wait_keyframe()|| sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
// when wait keyframe, there must exists idr frame in sample.
if (!sample->has_idr && muxer->wait_keyframe()) {
srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr);
... ...
... ... @@ -78,6 +78,7 @@ SrsTsChannel::SrsTsChannel()
stream = SrsTsStreamReserved;
msg = NULL;
continuity_counter = 0;
context = NULL;
}
SrsTsChannel::~SrsTsChannel()
... ... @@ -196,6 +197,7 @@ ISrsTsHandler::~ISrsTsHandler()
SrsTsContext::SrsTsContext()
{
pure_audio = false;
vcodec = SrsCodecVideoReserved;
acodec = SrsCodecAudioReserved1;
}
... ... @@ -210,6 +212,24 @@ SrsTsContext::~SrsTsContext()
pids.clear();
}
bool SrsTsContext::is_pure_audio()
{
return pure_audio;
}
void SrsTsContext::on_pmt_parsed()
{
pure_audio = true;
std::map<int, SrsTsChannel*>::iterator it;
for (it = pids.begin(); it != pids.end(); ++it) {
SrsTsChannel* channel = it->second;
if (channel->apply == SrsTsPidApplyVideo) {
pure_audio = false;
}
}
}
void SrsTsContext::reset()
{
vcodec = SrsCodecVideoReserved;
... ... @@ -230,6 +250,7 @@ void SrsTsContext::set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream)
if (pids.find(pid) == pids.end()) {
channel = new SrsTsChannel();
channel->context = this;
pids[pid] = channel;
} else {
channel = pids[pid];
... ... @@ -2302,6 +2323,7 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
// update the apply pid table.
packet->context->set(packet->pid, SrsTsPidApplyPAT);
packet->context->on_pmt_parsed();
return ret;
}
... ...
... ... @@ -172,6 +172,7 @@ struct SrsTsChannel
SrsTsPidApply apply;
SrsTsStream stream;
SrsTsMessage* msg;
SrsTsContext* context;
// for encoder.
u_int8_t continuity_counter;
... ... @@ -343,6 +344,7 @@ class SrsTsContext
// codec
private:
std::map<int, SrsTsChannel*> pids;
bool pure_audio;
// encoder
private:
// when any codec changed, write the PAT/PMT.
... ... @@ -353,6 +355,14 @@ public:
virtual ~SrsTsContext();
public:
/**
* whether the hls stream is pure audio stream.
*/
virtual bool is_pure_audio();
/**
* when PMT table parsed, we know some info about stream.
*/
virtual void on_pmt_parsed();
/**
* reset the context for a new ts segment start.
*/
virtual void reset();
... ...
... ... @@ -561,7 +561,7 @@ void SrsIngestSrsInput::fetch_all_ts(bool fresh_m3u8)
}
// only wait for a duration of last piece.
if (i == pieces.size() - 1) {
if (i == (int)pieces.size() - 1) {
next_connect_time = srs_update_system_time_ms() + (int)tp->duration * 1000;
}
}
... ... @@ -865,28 +865,34 @@ int SrsIngestSrsOutput::parse_message_queue()
{
int ret = ERROR_SUCCESS;
if (queue.empty()) {
return ret;
}
SrsTsMessage* first_ts_msg = queue.begin()->second;
SrsTsContext* context = first_ts_msg->channel->context;
int nb_videos = 0;
int nb_audios = 0;
std::multimap<int64_t, SrsTsMessage*>::iterator it;
for (it = queue.begin(); it != queue.end(); ++it) {
SrsTsMessage* msg = it->second;
if (!context->is_pure_audio()) {
std::multimap<int64_t, SrsTsMessage*>::iterator it;
for (it = queue.begin(); it != queue.end(); ++it) {
SrsTsMessage* msg = it->second;
// publish audio or video.
if (msg->channel->stream == SrsTsStreamVideoH264) {
nb_videos++;
}
}
// publish audio or video.
if (msg->channel->stream == SrsTsStreamVideoH264) {
nb_videos++;
} else {
nb_audios++;
// always wait 2+ videos, to left one video in the queue.
// TODO: FIXME: support pure audio hls.
if (nb_videos <= 1) {
return ret;
}
}
// always wait 2+ videos, to left one video in the queue.
// TODO: FIXME: support pure audio hls.
if (nb_videos <= 1) {
return ret;
}
// parse messages util the last video.
while (nb_videos > 1 && queue.size() > 0) {
while ((nb_videos > 1 || context->is_pure_audio()) && queue.size() > 0) {
std::multimap<int64_t, SrsTsMessage*>::iterator it = queue.begin();
SrsTsMessage* msg = it->second;
... ...