1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Refine SrsFragment.duration in time unit.

This commit is contained in:
winlin 2019-04-12 08:04:06 +08:00
parent 0879bef9b2
commit bc1189caee
8 changed files with 109 additions and 29 deletions

View file

@ -1279,6 +1279,7 @@ public:
/**
* get the hds fragment time, in seconds.
*/
// TODO: FIXME: Refine to time unit.
virtual double get_hds_fragment(const std::string &vhost);
/**
* get the hds window time, in seconds.

View file

@ -335,7 +335,7 @@ srs_error_t SrsDashController::on_audio(SrsSharedPtrMessage* shared_audio, SrsFo
return refresh_init_mp4(shared_audio, format);
}
if (acurrent->duration() >= int64_t(srsu2ms(fragment))) {
if (acurrent->duration() >= fragment) {
if ((err = acurrent->reap(audio_dts)) != srs_success) {
return srs_error_wrap(err, "reap current");
}
@ -367,7 +367,7 @@ srs_error_t SrsDashController::on_video(SrsSharedPtrMessage* shared_video, SrsFo
return refresh_init_mp4(shared_video, format);
}
bool reopen = format->video->frame_type == SrsVideoAvcFrameTypeKeyFrame && vcurrent->duration() >= int64_t(srsu2ms(fragment));
bool reopen = format->video->frame_type == SrsVideoAvcFrameTypeKeyFrame && vcurrent->duration() >= fragment;
if (reopen) {
if ((err = vcurrent->reap(video_dts)) != srs_success) {
return srs_error_wrap(err, "reap current");

View file

@ -286,7 +286,7 @@ srs_error_t SrsDvrFlvSegmenter::refresh_metadata()
}
// duration to buf
SrsAmf0Any* dur = SrsAmf0Any::number((double)fragment->duration() / 1000.0);
SrsAmf0Any* dur = SrsAmf0Any::number((double)srsu2ms(fragment->duration()) / 1000.0);
SrsAutoFree(SrsAmf0Any, dur);
stream.skip(-1 * stream.pos());
@ -831,7 +831,7 @@ srs_error_t SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
// ignore if duration ok.
SrsFragment* fragment = segment->current();
if (cduration <= 0 || fragment->duration() < int64_t(srsu2ms(cduration))) {
if (cduration <= 0 || fragment->duration() < cduration) {
return err;
}

View file

@ -44,16 +44,24 @@ SrsFragment::~SrsFragment()
void SrsFragment::append(int64_t dts)
{
// The max positive ms is 0x7fffffffffffffff/1000.
static const int64_t maxMS = 0x20c49ba5e353f7LL;
// We reset negative or overflow dts to zero.
if (dts > maxMS || dts < 0) {
dts = 0;
}
if (start_dts == -1) {
start_dts = dts;
}
// TODO: FIXME: Use cumulus dts.
start_dts = srs_min(start_dts, dts);
dur = dts - start_dts;
dur = srs_utime_t(dts - start_dts) * SRS_UTIME_MILLISECONDS;
}
int64_t SrsFragment::duration()
srs_utime_t SrsFragment::duration()
{
return dur;
}
@ -127,7 +135,7 @@ srs_error_t SrsFragment::rename()
string full_path = fullpath();
string tmp_file = tmppath();
int tempdur = (int)duration();
int tempdur = srsu2msi(duration());
if (true) {
std::stringstream ss;
ss << tempdur;
@ -195,7 +203,7 @@ void SrsFragmentWindow::append(SrsFragment* fragment)
void SrsFragmentWindow::shrink(int64_t window)
{
int64_t duration = 0;
srs_utime_t duration = 0;
int remove_index = -1;
@ -203,7 +211,7 @@ void SrsFragmentWindow::shrink(int64_t window)
SrsFragment* fragment = fragments[i];
duration += fragment->duration();
if (duration > window) {
if (srsu2ms(duration) > window) {
remove_index = i;
break;
}
@ -242,7 +250,7 @@ int64_t SrsFragmentWindow::max_duration()
for (it = fragments.begin(); it != fragments.end(); ++it) {
SrsFragment* fragment = *it;
v = srs_max(v, fragment->duration());
v = srs_max(v, srsu2ms(fragment->duration()));
}
return v;

View file

@ -36,8 +36,8 @@
class SrsFragment
{
private:
// The duration in ms.
int64_t dur;
// The duration in srs_utime_t.
srs_utime_t dur;
// The full file path of fragment.
std::string filepath;
// The start DTS in ms of segment.
@ -51,9 +51,8 @@ public:
// Append a frame with dts into fragment.
// @dts The dts of frame in ms.
virtual void append(int64_t dts);
// Get the duration of fragment in ms.
// TODO: FIXME: Refine to time unit.
virtual int64_t duration();
// Get the duration of fragment in srs_utime_t.
virtual srs_utime_t duration();
// Whether the fragment contains any sequence header.
virtual bool is_sequence_header();
// Set whether contains sequence header.

View file

@ -54,6 +54,7 @@ using namespace std;
#include <openssl/rand.h>
// drop the segment when duration of ts too small.
// TODO: FIXME: Refine to time unit.
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
// fragment plus the deviation percent.
@ -253,7 +254,7 @@ string SrsHlsMuxer::ts_url()
double SrsHlsMuxer::duration()
{
return current? current->duration()/1000.0:0;
return current? srsu2ms(current->duration())/1000.0:0;
}
int SrsHlsMuxer::deviation()
@ -483,14 +484,14 @@ bool SrsHlsMuxer::is_segment_overflow()
srs_assert(current);
// to prevent very small segment.
if (current->duration() < 2 * SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
if (srsu2msi(current->duration()) < 2 * SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
return false;
}
// use N% deviation, to smoother.
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
return current->duration() >= (hls_fragment + deviation) * 1000;
return srsu2msi(current->duration()) >= (hls_fragment + deviation) * 1000;
}
bool SrsHlsMuxer::wait_keyframe()
@ -504,14 +505,14 @@ bool SrsHlsMuxer::is_segment_absolutely_overflow()
srs_assert(current);
// to prevent very small segment.
if (current->duration() < 2 * SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
if (srsu2msi(current->duration()) < 2 * SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS) {
return false;
}
// use N% deviation, to smoother.
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
return current->duration() >= (hls_aof_ratio * hls_fragment + deviation) * 1000;
return srsu2msi(current->duration()) >= (hls_aof_ratio * hls_fragment + deviation) * 1000;
}
bool SrsHlsMuxer::pure_audio()
@ -591,10 +592,10 @@ srs_error_t SrsHlsMuxer::segment_close()
// when too small, it maybe not enough data to play.
// when too large, it maybe timestamp corrupt.
// make the segment more acceptable, when in [min, max_td * 2], it's ok.
if (current->duration() >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS && (int)current->duration() <= max_td * 2 * 1000) {
if (srsu2msi(current->duration()) >= SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS && (int)srsu2msi(current->duration()) <= max_td * 2 * 1000) {
// use async to call the http hooks, for it will cause thread switch.
if ((err = async->execute(new SrsDvrAsyncCallOnHls(_srs_context->get_id(), req, current->fullpath(),
current->uri, m3u8, m3u8_url, current->sequence_no, current->duration() / 1000.0))) != srs_success) {
current->uri, m3u8, m3u8_url, current->sequence_no, srsu2msi(current->duration()) / 1000.0))) != srs_success) {
return srs_error_wrap(err, "segment close");
}
@ -617,7 +618,8 @@ srs_error_t SrsHlsMuxer::segment_close()
// reuse current segment index.
_sequence_no--;
srs_trace("Drop ts segment, sequence_no=%d, uri=%s, duration=%" PRId64 "ms", current->sequence_no, current->uri.c_str(), current->duration());
srs_trace("Drop ts segment, sequence_no=%d, uri=%s, duration=%dms",
current->sequence_no, current->uri.c_str(), srsu2msi(current->duration()));
// rename from tmp to real path
if ((err = current->unlink_tmpfile()) != srs_success) {
@ -778,13 +780,13 @@ srs_error_t SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
// "#EXTINF:4294967295.208,\n"
ss.precision(3);
ss.setf(std::ios::fixed, std::ios::floatfield);
ss << "#EXTINF:" << segment->duration() / 1000.0 << ", no desc" << SRS_CONSTS_LF;
ss << "#EXTINF:" << srsu2msi(segment->duration()) / 1000.0 << ", no desc" << SRS_CONSTS_LF;
// {file name}\n
std::string seg_uri = segment->uri;
if (true) {
std::stringstream stemp;
stemp << (int)(segment->duration());
stemp << srsu2msi(segment->duration());
seg_uri = srs_string_replace(seg_uri, "[duration]", stemp.str());
}
//ss << segment->uri << SRS_CONSTS_LF;

View file

@ -24,6 +24,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SRS_UTEST_PUBLIC_SHARED_HPP
#define SRS_UTEST_PUBLIC_SHARED_HPP
// Public all private and protected members.
#define private public
#define protected public
/*
#include <srs_utest.hpp>
*/
@ -36,10 +40,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// we add an empty macro for upp to show the smart tips.
#define VOID
// Public all private and protected members.
#define private public
#define protected public
// the asserts of gtest:
// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2

View file

@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_app_fragment.hpp>
// Disable coroutine test for OSX.
#if !defined(SRS_OSX)
@ -307,3 +308,72 @@ VOID TEST(AppCoroutineTest, StartThread)
}
#endif
VOID TEST(AppFragmentTest, CheckDuration)
{
if (true) {
SrsFragment frg;
EXPECT_EQ(-1, frg.start_dts);
EXPECT_EQ(0, frg.dur);
EXPECT_FALSE(frg.sequence_header);
}
if (true) {
SrsFragment frg;
frg.append(0);
EXPECT_EQ(0, frg.duration());
frg.append(10);
EXPECT_EQ(10 * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(99);
EXPECT_EQ(99 * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(0x7fffffffLL);
EXPECT_EQ(0x7fffffffLL * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(0xffffffffLL);
EXPECT_EQ(0xffffffffLL * SRS_UTIME_MILLISECONDS, frg.duration());
frg.append(0x20c49ba5e353f7LL);
EXPECT_EQ(0x20c49ba5e353f7LL * SRS_UTIME_MILLISECONDS, frg.duration());
}
if (true) {
SrsFragment frg;
frg.append(0);
EXPECT_EQ(0, frg.duration());
frg.append(0x7fffffffffffffffLL);
EXPECT_EQ(0, frg.duration());
}
if (true) {
SrsFragment frg;
frg.append(100);
EXPECT_EQ(0, frg.duration());
frg.append(10);
EXPECT_EQ(0, frg.duration());
frg.append(100);
EXPECT_EQ(90 * SRS_UTIME_MILLISECONDS, frg.duration());
}
if (true) {
SrsFragment frg;
frg.append(-10);
EXPECT_EQ(0, frg.duration());
frg.append(-5);
EXPECT_EQ(0, frg.duration());
frg.append(10);
EXPECT_EQ(10 * SRS_UTIME_MILLISECONDS, frg.duration());
}
}