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:
parent
0879bef9b2
commit
bc1189caee
8 changed files with 109 additions and 29 deletions
|
@ -1279,6 +1279,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* get the hds fragment time, in seconds.
|
* get the hds fragment time, in seconds.
|
||||||
*/
|
*/
|
||||||
|
// TODO: FIXME: Refine to time unit.
|
||||||
virtual double get_hds_fragment(const std::string &vhost);
|
virtual double get_hds_fragment(const std::string &vhost);
|
||||||
/**
|
/**
|
||||||
* get the hds window time, in seconds.
|
* get the hds window time, in seconds.
|
||||||
|
|
|
@ -335,7 +335,7 @@ srs_error_t SrsDashController::on_audio(SrsSharedPtrMessage* shared_audio, SrsFo
|
||||||
return refresh_init_mp4(shared_audio, format);
|
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) {
|
if ((err = acurrent->reap(audio_dts)) != srs_success) {
|
||||||
return srs_error_wrap(err, "reap current");
|
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);
|
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 (reopen) {
|
||||||
if ((err = vcurrent->reap(video_dts)) != srs_success) {
|
if ((err = vcurrent->reap(video_dts)) != srs_success) {
|
||||||
return srs_error_wrap(err, "reap current");
|
return srs_error_wrap(err, "reap current");
|
||||||
|
|
|
@ -286,7 +286,7 @@ srs_error_t SrsDvrFlvSegmenter::refresh_metadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
// duration to buf
|
// 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);
|
SrsAutoFree(SrsAmf0Any, dur);
|
||||||
|
|
||||||
stream.skip(-1 * stream.pos());
|
stream.skip(-1 * stream.pos());
|
||||||
|
@ -831,7 +831,7 @@ srs_error_t SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
|
||||||
|
|
||||||
// ignore if duration ok.
|
// ignore if duration ok.
|
||||||
SrsFragment* fragment = segment->current();
|
SrsFragment* fragment = segment->current();
|
||||||
if (cduration <= 0 || fragment->duration() < int64_t(srsu2ms(cduration))) {
|
if (cduration <= 0 || fragment->duration() < cduration) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,16 +44,24 @@ SrsFragment::~SrsFragment()
|
||||||
|
|
||||||
void SrsFragment::append(int64_t dts)
|
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) {
|
if (start_dts == -1) {
|
||||||
start_dts = dts;
|
start_dts = dts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: Use cumulus dts.
|
// TODO: FIXME: Use cumulus dts.
|
||||||
start_dts = srs_min(start_dts, 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;
|
return dur;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +135,7 @@ srs_error_t SrsFragment::rename()
|
||||||
|
|
||||||
string full_path = fullpath();
|
string full_path = fullpath();
|
||||||
string tmp_file = tmppath();
|
string tmp_file = tmppath();
|
||||||
int tempdur = (int)duration();
|
int tempdur = srsu2msi(duration());
|
||||||
if (true) {
|
if (true) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << tempdur;
|
ss << tempdur;
|
||||||
|
@ -195,7 +203,7 @@ void SrsFragmentWindow::append(SrsFragment* fragment)
|
||||||
|
|
||||||
void SrsFragmentWindow::shrink(int64_t window)
|
void SrsFragmentWindow::shrink(int64_t window)
|
||||||
{
|
{
|
||||||
int64_t duration = 0;
|
srs_utime_t duration = 0;
|
||||||
|
|
||||||
int remove_index = -1;
|
int remove_index = -1;
|
||||||
|
|
||||||
|
@ -203,7 +211,7 @@ void SrsFragmentWindow::shrink(int64_t window)
|
||||||
SrsFragment* fragment = fragments[i];
|
SrsFragment* fragment = fragments[i];
|
||||||
duration += fragment->duration();
|
duration += fragment->duration();
|
||||||
|
|
||||||
if (duration > window) {
|
if (srsu2ms(duration) > window) {
|
||||||
remove_index = i;
|
remove_index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +250,7 @@ int64_t SrsFragmentWindow::max_duration()
|
||||||
|
|
||||||
for (it = fragments.begin(); it != fragments.end(); ++it) {
|
for (it = fragments.begin(); it != fragments.end(); ++it) {
|
||||||
SrsFragment* fragment = *it;
|
SrsFragment* fragment = *it;
|
||||||
v = srs_max(v, fragment->duration());
|
v = srs_max(v, srsu2ms(fragment->duration()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
class SrsFragment
|
class SrsFragment
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// The duration in ms.
|
// The duration in srs_utime_t.
|
||||||
int64_t dur;
|
srs_utime_t dur;
|
||||||
// The full file path of fragment.
|
// The full file path of fragment.
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
// The start DTS in ms of segment.
|
// The start DTS in ms of segment.
|
||||||
|
@ -51,9 +51,8 @@ public:
|
||||||
// Append a frame with dts into fragment.
|
// Append a frame with dts into fragment.
|
||||||
// @dts The dts of frame in ms.
|
// @dts The dts of frame in ms.
|
||||||
virtual void append(int64_t dts);
|
virtual void append(int64_t dts);
|
||||||
// Get the duration of fragment in ms.
|
// Get the duration of fragment in srs_utime_t.
|
||||||
// TODO: FIXME: Refine to time unit.
|
virtual srs_utime_t duration();
|
||||||
virtual int64_t duration();
|
|
||||||
// Whether the fragment contains any sequence header.
|
// Whether the fragment contains any sequence header.
|
||||||
virtual bool is_sequence_header();
|
virtual bool is_sequence_header();
|
||||||
// Set whether contains sequence header.
|
// Set whether contains sequence header.
|
||||||
|
|
|
@ -54,6 +54,7 @@ using namespace std;
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
// drop the segment when duration of ts too small.
|
// drop the segment when duration of ts too small.
|
||||||
|
// TODO: FIXME: Refine to time unit.
|
||||||
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
|
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
|
||||||
|
|
||||||
// fragment plus the deviation percent.
|
// fragment plus the deviation percent.
|
||||||
|
@ -253,7 +254,7 @@ string SrsHlsMuxer::ts_url()
|
||||||
|
|
||||||
double SrsHlsMuxer::duration()
|
double SrsHlsMuxer::duration()
|
||||||
{
|
{
|
||||||
return current? current->duration()/1000.0:0;
|
return current? srsu2ms(current->duration())/1000.0:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHlsMuxer::deviation()
|
int SrsHlsMuxer::deviation()
|
||||||
|
@ -483,14 +484,14 @@ bool SrsHlsMuxer::is_segment_overflow()
|
||||||
srs_assert(current);
|
srs_assert(current);
|
||||||
|
|
||||||
// to prevent very small segment.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use N% deviation, to smoother.
|
// use N% deviation, to smoother.
|
||||||
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
|
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()
|
bool SrsHlsMuxer::wait_keyframe()
|
||||||
|
@ -504,14 +505,14 @@ bool SrsHlsMuxer::is_segment_absolutely_overflow()
|
||||||
srs_assert(current);
|
srs_assert(current);
|
||||||
|
|
||||||
// to prevent very small segment.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use N% deviation, to smoother.
|
// use N% deviation, to smoother.
|
||||||
double deviation = hls_ts_floor? SRS_HLS_FLOOR_REAP_PERCENT * deviation_ts * hls_fragment : 0.0;
|
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()
|
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 small, it maybe not enough data to play.
|
||||||
// when too large, it maybe timestamp corrupt.
|
// when too large, it maybe timestamp corrupt.
|
||||||
// make the segment more acceptable, when in [min, max_td * 2], it's ok.
|
// 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.
|
// 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(),
|
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");
|
return srs_error_wrap(err, "segment close");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +618,8 @@ srs_error_t SrsHlsMuxer::segment_close()
|
||||||
// reuse current segment index.
|
// reuse current segment index.
|
||||||
_sequence_no--;
|
_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
|
// rename from tmp to real path
|
||||||
if ((err = current->unlink_tmpfile()) != srs_success) {
|
if ((err = current->unlink_tmpfile()) != srs_success) {
|
||||||
|
@ -778,13 +780,13 @@ srs_error_t SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
|
||||||
// "#EXTINF:4294967295.208,\n"
|
// "#EXTINF:4294967295.208,\n"
|
||||||
ss.precision(3);
|
ss.precision(3);
|
||||||
ss.setf(std::ios::fixed, std::ios::floatfield);
|
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
|
// {file name}\n
|
||||||
std::string seg_uri = segment->uri;
|
std::string seg_uri = segment->uri;
|
||||||
if (true) {
|
if (true) {
|
||||||
std::stringstream stemp;
|
std::stringstream stemp;
|
||||||
stemp << (int)(segment->duration());
|
stemp << srsu2msi(segment->duration());
|
||||||
seg_uri = srs_string_replace(seg_uri, "[duration]", stemp.str());
|
seg_uri = srs_string_replace(seg_uri, "[duration]", stemp.str());
|
||||||
}
|
}
|
||||||
//ss << segment->uri << SRS_CONSTS_LF;
|
//ss << segment->uri << SRS_CONSTS_LF;
|
||||||
|
|
|
@ -24,6 +24,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#ifndef SRS_UTEST_PUBLIC_SHARED_HPP
|
#ifndef SRS_UTEST_PUBLIC_SHARED_HPP
|
||||||
#define 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>
|
#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.
|
// we add an empty macro for upp to show the smart tips.
|
||||||
#define VOID
|
#define VOID
|
||||||
|
|
||||||
// Public all private and protected members.
|
|
||||||
#define private public
|
|
||||||
#define protected public
|
|
||||||
|
|
||||||
// the asserts of gtest:
|
// the asserts of gtest:
|
||||||
// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
|
// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
|
||||||
// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
|
// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
|
||||||
|
|
|
@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
|
#include <srs_app_fragment.hpp>
|
||||||
|
|
||||||
// Disable coroutine test for OSX.
|
// Disable coroutine test for OSX.
|
||||||
#if !defined(SRS_OSX)
|
#if !defined(SRS_OSX)
|
||||||
|
@ -307,3 +308,72 @@ VOID TEST(AppCoroutineTest, StartThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue