AI: Add utest to cover app http module.
This commit is contained in:
parent
b5664747ac
commit
3948f0d4fe
|
|
@ -125,6 +125,118 @@ codebase_structure:
|
|||
description: "Smart pointer definitions for memory management"
|
||||
|
||||
code_patterns:
|
||||
dependency_inversion:
|
||||
principle: "MANDATORY - Classes should depend on interfaces, not concrete classes"
|
||||
description: |
|
||||
Follow the Dependency Inversion Principle (DIP) - high-level modules should not depend on low-level modules.
|
||||
Both should depend on abstractions (interfaces). This improves testability, maintainability, and flexibility.
|
||||
|
||||
In SRS, interfaces start with 'ISrs' prefix (e.g., ISrsBufferCache, ISrsMessageQueue), while concrete classes
|
||||
start with 'Srs' prefix (e.g., SrsBufferCache, SrsMessageQueue).
|
||||
|
||||
usage: |
|
||||
WRONG: Depending on concrete class
|
||||
class SrsBufferCache {
|
||||
private:
|
||||
SrsMessageQueue *queue_; // Direct dependency on concrete class
|
||||
};
|
||||
|
||||
CORRECT: Depending on interface
|
||||
class SrsBufferCache : public ISrsBufferCache {
|
||||
private:
|
||||
ISrsMessageQueue *queue_; // Dependency on interface
|
||||
};
|
||||
|
||||
rules:
|
||||
- "Interfaces start with 'ISrs' prefix (e.g., ISrsMessageQueue, ISrsBufferCache, ISrsCoroutineHandler)"
|
||||
- "Concrete classes start with 'Srs' prefix (e.g., SrsMessageQueue, SrsBufferCache, SrsServer)"
|
||||
- "Class member variables should use interface types (ISrs*) instead of concrete types (Srs*)"
|
||||
- "Classes should implement interfaces when they provide functionality that may need to be mocked or substituted"
|
||||
- "Use concrete types only for instantiation, not for member variable declarations"
|
||||
|
||||
benefits:
|
||||
- "Enables dependency injection for unit testing"
|
||||
- "Allows easy mocking of dependencies in tests"
|
||||
- "Reduces coupling between components"
|
||||
- "Makes code more flexible and maintainable"
|
||||
- "Facilitates future refactoring and extensions"
|
||||
|
||||
rationale: "Interface-based design is fundamental to testable, maintainable code. It allows components to be tested in isolation and makes the codebase more flexible for future changes."
|
||||
|
||||
avoid_global_variables:
|
||||
principle: "MANDATORY - Never directly use global variables, convert to member fields for mockability"
|
||||
description: |
|
||||
Direct use of global variables makes code untestable because globals cannot be mocked.
|
||||
Global variables in SRS start with _srs prefix (e.g., _srs_config, _srs_sources, _srs_stat, _srs_hooks, _srs_context).
|
||||
Always store global references as member fields in the constructor so they can be replaced with mocks in tests.
|
||||
|
||||
usage: |
|
||||
WRONG: Direct use of global variable
|
||||
srs_error_t SrsBufferCache::start() {
|
||||
fast_cache_ = _srs_config->get_vhost_http_remux_fast_cache(req_->vhost_);
|
||||
}
|
||||
|
||||
CORRECT: Store global as member field for mockability
|
||||
SrsBufferCache::SrsBufferCache(ISrsRequest *r) {
|
||||
config_ = _srs_config; // Store global reference as member field
|
||||
}
|
||||
SrsBufferCache::~SrsBufferCache() {
|
||||
config_ = NULL; // Set to NULL, do NOT free (it's a global reference)
|
||||
}
|
||||
srs_error_t SrsBufferCache::start() {
|
||||
fast_cache_ = config_->get_vhost_http_remux_fast_cache(req_->vhost_);
|
||||
}
|
||||
|
||||
rules:
|
||||
- "Global variables in SRS start with _srs prefix: _srs_config, _srs_sources, _srs_stat, _srs_hooks, _srs_context, etc."
|
||||
- "Never access global variables directly in methods"
|
||||
- "Always store global references as member fields in constructor"
|
||||
- "Use interface types for member fields (e.g., ISrsAppConfig* config_)"
|
||||
- "In destructor, set global reference fields to NULL but do NOT free them"
|
||||
- "This allows tests to inject mock objects by setting the member field"
|
||||
|
||||
common_global_variables:
|
||||
core_globals:
|
||||
- "_srs_log - Global logging interface (ISrsLog*)"
|
||||
- "_srs_context - Thread context for coroutine management (ISrsContext*)"
|
||||
- "_srs_config - Global configuration object (SrsConfig*)"
|
||||
- "_srs_kernel_factory - Kernel object factory (ISrsKernelFactory*)"
|
||||
- "_srs_app_factory - Application object factory (SrsAppFactory*)"
|
||||
|
||||
app_globals:
|
||||
- "_srs_server - Main SRS server instance (SrsServer*)"
|
||||
- "_srs_sources - Live source manager (SrsLiveSourceManager*)"
|
||||
- "_srs_stat - Statistics manager (SrsStatistic*)"
|
||||
- "_srs_hooks - HTTP hooks manager (ISrsHttpHooks*)"
|
||||
- "_srs_circuit_breaker - Circuit breaker for overload protection (ISrsCircuitBreaker*)"
|
||||
- "_srs_dvr_async - Async worker for DVR operations (SrsAsyncCallWorker*)"
|
||||
|
||||
timing_globals:
|
||||
- "_srs_clock - Wall clock for time operations (SrsWallClock*)"
|
||||
- "_srs_shared_timer - Shared timer for periodic tasks (SrsSharedTimer*)"
|
||||
- "_srs_stages - Stage manager for pithy print (SrsStageManager*)"
|
||||
|
||||
resource_globals:
|
||||
- "_srs_conn_manager - Connection resource manager (SrsResourceManager*)"
|
||||
- "_srs_pps_* - Various PPS (packets per second) statistics counters"
|
||||
|
||||
webrtc_globals:
|
||||
- "_srs_blackhole - WebRTC blackhole for packet dropping (SrsRtcBlackhole*)"
|
||||
- "_srs_rtc_dtls_certificate - DTLS certificate for WebRTC (SrsDtlsCertificate*)"
|
||||
|
||||
other_globals:
|
||||
- "_srs_in_docker - Boolean flag indicating if running in Docker"
|
||||
- "_srs_config_by_env - Boolean flag for environment variable configuration"
|
||||
- "_srs_binary - Binary name of SRS executable"
|
||||
|
||||
benefits:
|
||||
- "Enables dependency injection for unit testing"
|
||||
- "Allows mocking of global dependencies in tests"
|
||||
- "Makes dependencies explicit and visible in class interface"
|
||||
- "Improves code testability and maintainability"
|
||||
|
||||
rationale: "Global variables create hidden dependencies that cannot be mocked or controlled in tests. Converting them to member fields makes dependencies explicit and testable."
|
||||
|
||||
cpp_compatibility:
|
||||
standard: "C++98"
|
||||
description: |
|
||||
|
|
|
|||
2
trunk/configure
vendored
2
trunk/configure
vendored
|
|
@ -384,7 +384,7 @@ if [[ $SRS_UTEST == YES ]]; then
|
|||
"srs_utest_coworkers" "srs_utest_pithy_print" "srs_utest_kernel3" "srs_utest_protocol4"
|
||||
"srs_utest_protocol3" "srs_utest_app" "srs_utest_app2" "srs_utest_app3" "srs_utest_app4"
|
||||
"srs_utest_app5" "srs_utest_app6" "srs_utest_app7" "srs_utest_app8" "srs_utest_app9"
|
||||
"srs_utest_app10")
|
||||
"srs_utest_app10" "srs_utest_app11")
|
||||
# Always include SRT utest
|
||||
MODULE_FILES+=("srs_utest_srt")
|
||||
if [[ $SRS_GB28181 == YES ]]; then
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ public:
|
|||
virtual ~ISrsAsyncCallWorker();
|
||||
|
||||
public:
|
||||
virtual srs_error_t execute(ISrsAsyncCallTask *t) = 0;
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void stop() = 0;
|
||||
};
|
||||
|
||||
// The async callback for dvr, callback and other async worker.
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ public:
|
|||
virtual srs_error_t reload(SrsReloadState *pstate) = 0;
|
||||
virtual srs_error_t persistence() = 0;
|
||||
virtual std::string config() = 0;
|
||||
virtual SrsConfDirective *get_root() = 0;
|
||||
|
||||
public:
|
||||
// Global server config
|
||||
|
|
@ -373,6 +374,7 @@ public:
|
|||
// Vhost config
|
||||
virtual SrsConfDirective *get_vhost(std::string vhost, bool try_default_vhost = true) = 0;
|
||||
virtual bool get_vhost_enabled(std::string vhost) = 0;
|
||||
virtual bool get_vhost_enabled(SrsConfDirective *conf) = 0;
|
||||
virtual bool get_debug_srs_upnode(std::string vhost) = 0;
|
||||
virtual int get_out_ack_size(std::string vhost) = 0;
|
||||
virtual int get_in_ack_size(std::string vhost) = 0;
|
||||
|
|
@ -479,6 +481,17 @@ public:
|
|||
virtual bool get_atc_auto(std::string vhost) = 0;
|
||||
virtual bool get_reduce_sequence_header(std::string vhost) = 0;
|
||||
virtual bool get_parse_sps(std::string vhost) = 0;
|
||||
|
||||
public:
|
||||
// HTTP remux config
|
||||
virtual bool get_vhost_http_remux_enabled(std::string vhost) = 0;
|
||||
virtual bool get_vhost_http_remux_enabled(SrsConfDirective *vhost) = 0;
|
||||
virtual srs_utime_t get_vhost_http_remux_fast_cache(std::string vhost) = 0;
|
||||
virtual bool get_vhost_http_remux_drop_if_not_match(std::string vhost) = 0;
|
||||
virtual bool get_vhost_http_remux_has_audio(std::string vhost) = 0;
|
||||
virtual bool get_vhost_http_remux_has_video(std::string vhost) = 0;
|
||||
virtual bool get_vhost_http_remux_guess_has_av(std::string vhost) = 0;
|
||||
virtual std::string get_vhost_http_remux_mount(std::string vhost) = 0;
|
||||
};
|
||||
|
||||
// The config service provider.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class SrsBuffer;
|
|||
class SrsRtmpJitter;
|
||||
class SrsMediaPacket;
|
||||
class SrsFileWriter;
|
||||
class SrsFlvTransmuxer;
|
||||
class ISrsFlvTransmuxer;
|
||||
class SrsDvrPlan;
|
||||
class SrsJsonAny;
|
||||
class SrsJsonObject;
|
||||
|
|
@ -99,7 +99,7 @@ class SrsDvrFlvSegmenter : public SrsDvrSegmenter
|
|||
{
|
||||
private:
|
||||
// The FLV encoder, for FLV target.
|
||||
SrsFlvTransmuxer *enc_;
|
||||
ISrsFlvTransmuxer *enc_;
|
||||
|
||||
private:
|
||||
// The offset of file for duration value.
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
#include <srs_app_rtmp_source.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
#include <srs_kernel_ts.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_st.hpp>
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
|
||||
SrsAppFactory::SrsAppFactory()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ srs_error_t SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessag
|
|||
|
||||
// path: {pattern}{vhost_id}
|
||||
// e.g. /api/v1/vhosts/100 pattern= /api/v1/vhosts/, vhost_id=100
|
||||
string vid = r->parse_rest_id(entry->pattern);
|
||||
string vid = r->parse_rest_id(entry_->pattern);
|
||||
SrsStatisticVhost *vhost = NULL;
|
||||
|
||||
if (!vid.empty() && (vhost = stat->find_vhost_by_id(vid)) == NULL) {
|
||||
|
|
@ -765,7 +765,7 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
// path: {pattern}{stream_id}
|
||||
// e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100
|
||||
string sid = r->parse_rest_id(entry->pattern);
|
||||
string sid = r->parse_rest_id(entry_->pattern);
|
||||
|
||||
SrsStatisticStream *stream = NULL;
|
||||
if (!sid.empty() && (stream = stat->find_stream(sid)) == NULL) {
|
||||
|
|
@ -827,7 +827,7 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
// path: {pattern}{client_id}
|
||||
// e.g. /api/v1/clients/100 pattern= /api/v1/clients/, client_id=100
|
||||
string client_id = r->parse_rest_id(entry->pattern);
|
||||
string client_id = r->parse_rest_id(entry_->pattern);
|
||||
|
||||
SrsStatisticClient *client = NULL;
|
||||
if (!client_id.empty() && (client = stat->find_client(client_id)) == NULL) {
|
||||
|
|
|
|||
|
|
@ -474,11 +474,12 @@ ISrsKbpsDelta *SrsHttpxConn::delta()
|
|||
return conn_->delta();
|
||||
}
|
||||
|
||||
SrsHttpServer::SrsHttpServer(SrsServer *svr)
|
||||
SrsHttpServer::SrsHttpServer()
|
||||
{
|
||||
server_ = svr;
|
||||
http_stream_ = new SrsHttpStreamServer(svr);
|
||||
http_static_ = new SrsHttpStaticServer(svr);
|
||||
http_stream_ = new SrsHttpStreamServer();
|
||||
http_stream_->assemble();
|
||||
|
||||
http_static_ = new SrsHttpStaticServer();
|
||||
}
|
||||
|
||||
SrsHttpServer::~SrsHttpServer()
|
||||
|
|
|
|||
|
|
@ -183,12 +183,11 @@ public:
|
|||
class SrsHttpServer : public ISrsHttpServeMux
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
SrsHttpStaticServer *http_static_;
|
||||
SrsHttpStreamServer *http_stream_;
|
||||
|
||||
public:
|
||||
SrsHttpServer(SrsServer *svr);
|
||||
SrsHttpServer();
|
||||
virtual ~SrsHttpServer();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -599,9 +599,8 @@ srs_error_t SrsVodStream::serve_ts_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessag
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsHttpStaticServer::SrsHttpStaticServer(SrsServer *svr)
|
||||
SrsHttpStaticServer::SrsHttpStaticServer()
|
||||
{
|
||||
server_ = svr;
|
||||
_srs_config->subscribe(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,14 +89,11 @@ protected:
|
|||
// serve http static file and flv/mp4 vod stream.
|
||||
class SrsHttpStaticServer : public ISrsReloadHandler
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
|
||||
public:
|
||||
SrsHttpServeMux mux_;
|
||||
|
||||
public:
|
||||
SrsHttpStaticServer(SrsServer *svr);
|
||||
SrsHttpStaticServer();
|
||||
virtual ~SrsHttpStaticServer();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -40,15 +40,23 @@ using namespace std;
|
|||
#include <srs_protocol_stream.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
SrsBufferCache::SrsBufferCache(SrsServer *s, ISrsRequest *r)
|
||||
ISrsBufferCache::ISrsBufferCache()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsBufferCache::~ISrsBufferCache()
|
||||
{
|
||||
}
|
||||
|
||||
SrsBufferCache::SrsBufferCache(ISrsRequest *r)
|
||||
{
|
||||
req_ = r->copy()->as_http();
|
||||
queue_ = new SrsMessageQueue(true);
|
||||
trd_ = new SrsSTCoroutine("http-stream", this);
|
||||
fast_cache_ = 0;
|
||||
|
||||
// TODO: FIXME: support reload.
|
||||
fast_cache_ = _srs_config->get_vhost_http_remux_fast_cache(req_->vhost_);
|
||||
server_ = s;
|
||||
config_ = _srs_config;
|
||||
live_sources_ = _srs_sources;
|
||||
}
|
||||
|
||||
SrsBufferCache::~SrsBufferCache()
|
||||
|
|
@ -57,6 +65,9 @@ SrsBufferCache::~SrsBufferCache()
|
|||
|
||||
srs_freep(queue_);
|
||||
srs_freep(req_);
|
||||
|
||||
config_ = NULL;
|
||||
live_sources_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsBufferCache::update_auth(ISrsRequest *r)
|
||||
|
|
@ -71,6 +82,8 @@ srs_error_t SrsBufferCache::start()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
fast_cache_ = config_->get_vhost_http_remux_fast_cache(req_->vhost_);
|
||||
|
||||
// Not enabled.
|
||||
if (fast_cache_ <= 0) {
|
||||
return err;
|
||||
|
|
@ -109,7 +122,7 @@ bool SrsBufferCache::alive()
|
|||
return false;
|
||||
}
|
||||
|
||||
srs_error_t SrsBufferCache::dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter)
|
||||
srs_error_t SrsBufferCache::dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -133,7 +146,7 @@ srs_error_t SrsBufferCache::cycle()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsSharedPtr<SrsLiveSource> live_source;
|
||||
if ((err = _srs_sources->fetch_or_create(req_, live_source)) != srs_success) {
|
||||
if ((err = live_sources_->fetch_or_create(req_, live_source)) != srs_success) {
|
||||
return srs_error_wrap(err, "source create");
|
||||
}
|
||||
srs_assert(live_source.get() != NULL);
|
||||
|
|
@ -214,7 +227,7 @@ SrsTsStreamEncoder::~SrsTsStreamEncoder()
|
|||
srs_freep(enc_);
|
||||
}
|
||||
|
||||
srs_error_t SrsTsStreamEncoder::initialize(SrsFileWriter *w, SrsBufferCache * /*c*/)
|
||||
srs_error_t SrsTsStreamEncoder::initialize(SrsFileWriter *w, ISrsBufferCache * /*c*/)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -258,7 +271,7 @@ bool SrsTsStreamEncoder::has_cache()
|
|||
return false;
|
||||
}
|
||||
|
||||
srs_error_t SrsTsStreamEncoder::dump_cache(SrsLiveConsumer * /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)
|
||||
srs_error_t SrsTsStreamEncoder::dump_cache(ISrsLiveConsumer * /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)
|
||||
{
|
||||
// for ts stream, ignore cache.
|
||||
return srs_success;
|
||||
|
|
@ -293,7 +306,7 @@ SrsFlvStreamEncoder::~SrsFlvStreamEncoder()
|
|||
srs_freep(enc_);
|
||||
}
|
||||
|
||||
srs_error_t SrsFlvStreamEncoder::initialize(SrsFileWriter *w, SrsBufferCache * /*c*/)
|
||||
srs_error_t SrsFlvStreamEncoder::initialize(SrsFileWriter *w, ISrsBufferCache * /*c*/)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -363,7 +376,7 @@ bool SrsFlvStreamEncoder::has_cache()
|
|||
return false;
|
||||
}
|
||||
|
||||
srs_error_t SrsFlvStreamEncoder::dump_cache(SrsLiveConsumer * /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)
|
||||
srs_error_t SrsFlvStreamEncoder::dump_cache(ISrsLiveConsumer * /*consumer*/, SrsRtmpJitterAlgorithm /*jitter*/)
|
||||
{
|
||||
// for flv stream, ignore cache.
|
||||
return srs_success;
|
||||
|
|
@ -458,7 +471,7 @@ SrsAacStreamEncoder::~SrsAacStreamEncoder()
|
|||
srs_freep(enc_);
|
||||
}
|
||||
|
||||
srs_error_t SrsAacStreamEncoder::initialize(SrsFileWriter *w, SrsBufferCache *c)
|
||||
srs_error_t SrsAacStreamEncoder::initialize(SrsFileWriter *w, ISrsBufferCache *c)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -493,7 +506,7 @@ bool SrsAacStreamEncoder::has_cache()
|
|||
return true;
|
||||
}
|
||||
|
||||
srs_error_t SrsAacStreamEncoder::dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter)
|
||||
srs_error_t SrsAacStreamEncoder::dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter)
|
||||
{
|
||||
srs_assert(cache_);
|
||||
return cache_->dump_cache(consumer, jitter);
|
||||
|
|
@ -510,7 +523,7 @@ SrsMp3StreamEncoder::~SrsMp3StreamEncoder()
|
|||
srs_freep(enc_);
|
||||
}
|
||||
|
||||
srs_error_t SrsMp3StreamEncoder::initialize(SrsFileWriter *w, SrsBufferCache *c)
|
||||
srs_error_t SrsMp3StreamEncoder::initialize(SrsFileWriter *w, ISrsBufferCache *c)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -549,7 +562,7 @@ bool SrsMp3StreamEncoder::has_cache()
|
|||
return true;
|
||||
}
|
||||
|
||||
srs_error_t SrsMp3StreamEncoder::dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter)
|
||||
srs_error_t SrsMp3StreamEncoder::dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter)
|
||||
{
|
||||
srs_assert(cache_);
|
||||
return cache_->dump_cache(consumer, jitter);
|
||||
|
|
@ -596,12 +609,24 @@ srs_error_t SrsBufferWriter::writev(const iovec *iov, int iovcnt, ssize_t *pnwri
|
|||
return writer_->writev(iov, iovcnt, pnwrite);
|
||||
}
|
||||
|
||||
SrsLiveStream::SrsLiveStream(SrsServer *s, ISrsRequest *r, SrsBufferCache *c)
|
||||
ISrsLiveStream::ISrsLiveStream()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsLiveStream::~ISrsLiveStream()
|
||||
{
|
||||
}
|
||||
|
||||
SrsLiveStream::SrsLiveStream(ISrsRequest *r, ISrsBufferCache *c)
|
||||
{
|
||||
cache_ = c;
|
||||
req_ = r->copy()->as_http();
|
||||
security_ = new SrsSecurity();
|
||||
server_ = s;
|
||||
|
||||
config_ = _srs_config;
|
||||
live_sources_ = _srs_sources;
|
||||
stat_ = _srs_stat;
|
||||
hooks_ = _srs_hooks;
|
||||
}
|
||||
|
||||
SrsLiveStream::~SrsLiveStream()
|
||||
|
|
@ -611,6 +636,11 @@ SrsLiveStream::~SrsLiveStream()
|
|||
|
||||
// The live stream should never be destroyed when it's serving any viewers.
|
||||
srs_assert(viewers_.empty());
|
||||
|
||||
config_ = NULL;
|
||||
live_sources_ = NULL;
|
||||
stat_ = NULL;
|
||||
hooks_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsLiveStream::update_auth(ISrsRequest *r)
|
||||
|
|
@ -664,8 +694,7 @@ srs_error_t SrsLiveStream::serve_http_impl(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
req_->ip_ = hc->remote_ip();
|
||||
|
||||
// We must do stat the client before hooks, because hooks depends on it.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, hc, SrsFlvPlay)) != srs_success) {
|
||||
if ((err = stat_->on_client(_srs_context->get_id().c_str(), req_, hc, SrsFlvPlay)) != srs_success) {
|
||||
return srs_error_wrap(err, "stat on client");
|
||||
}
|
||||
|
||||
|
|
@ -679,19 +708,19 @@ srs_error_t SrsLiveStream::serve_http_impl(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
}
|
||||
|
||||
// Fast check whether stream is still available.
|
||||
if (!entry->enabled) {
|
||||
if (!entry_->enabled) {
|
||||
return srs_error_new(ERROR_RTMP_STREAM_NOT_FOUND, "stream not found");
|
||||
}
|
||||
|
||||
// Always try to create the source, because http handler won't create it.
|
||||
SrsSharedPtr<SrsLiveSource> live_source;
|
||||
if ((err = _srs_sources->fetch_or_create(req_, live_source)) != srs_success) {
|
||||
if ((err = live_sources_->fetch_or_create(req_, live_source)) != srs_success) {
|
||||
return srs_error_wrap(err, "source create");
|
||||
}
|
||||
srs_assert(live_source.get() != NULL);
|
||||
|
||||
bool enabled_cache = _srs_config->get_gop_cache(req_->vhost_);
|
||||
int gcmf = _srs_config->get_gop_cache_max_frames(req_->vhost_);
|
||||
bool enabled_cache = config_->get_gop_cache(req_->vhost_);
|
||||
int gcmf = config_->get_gop_cache_max_frames(req_->vhost_);
|
||||
live_source->set_cache(enabled_cache);
|
||||
live_source->set_gop_cache_max_frames(gcmf);
|
||||
|
||||
|
|
@ -706,7 +735,7 @@ srs_error_t SrsLiveStream::serve_http_impl(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw);
|
||||
|
||||
// Fast check whether stream is still available.
|
||||
if (!entry->enabled) {
|
||||
if (!entry_->enabled) {
|
||||
return srs_error_new(ERROR_RTMP_STREAM_NOT_FOUND, "stream not found");
|
||||
}
|
||||
|
||||
|
|
@ -733,20 +762,20 @@ void SrsLiveStream::expire()
|
|||
}
|
||||
}
|
||||
|
||||
srs_error_t SrsLiveStream::do_serve_http(SrsLiveSource *source, SrsLiveConsumer *consumer, ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
srs_error_t SrsLiveStream::do_serve_http(SrsLiveSource *source, ISrsLiveConsumer *consumer, ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
string enc_desc;
|
||||
ISrsBufferEncoder *enc_raw = NULL;
|
||||
|
||||
srs_assert(entry);
|
||||
bool drop_if_not_match = _srs_config->get_vhost_http_remux_drop_if_not_match(req_->vhost_);
|
||||
bool has_audio = _srs_config->get_vhost_http_remux_has_audio(req_->vhost_);
|
||||
bool has_video = _srs_config->get_vhost_http_remux_has_video(req_->vhost_);
|
||||
bool guess_has_av = _srs_config->get_vhost_http_remux_guess_has_av(req_->vhost_);
|
||||
srs_assert(entry_);
|
||||
bool drop_if_not_match = config_->get_vhost_http_remux_drop_if_not_match(req_->vhost_);
|
||||
bool has_audio = config_->get_vhost_http_remux_has_audio(req_->vhost_);
|
||||
bool has_video = config_->get_vhost_http_remux_has_video(req_->vhost_);
|
||||
bool guess_has_av = config_->get_vhost_http_remux_guess_has_av(req_->vhost_);
|
||||
|
||||
if (srs_strings_ends_with(entry->pattern, ".flv")) {
|
||||
if (srs_strings_ends_with(entry_->pattern, ".flv")) {
|
||||
w->header()->set_content_type("video/x-flv");
|
||||
enc_desc = "FLV";
|
||||
enc_raw = new SrsFlvStreamEncoder();
|
||||
|
|
@ -754,15 +783,15 @@ srs_error_t SrsLiveStream::do_serve_http(SrsLiveSource *source, SrsLiveConsumer
|
|||
((SrsFlvStreamEncoder *)enc_raw)->set_has_audio(has_audio);
|
||||
((SrsFlvStreamEncoder *)enc_raw)->set_has_video(has_video);
|
||||
((SrsFlvStreamEncoder *)enc_raw)->set_guess_has_av(guess_has_av);
|
||||
} else if (srs_strings_ends_with(entry->pattern, ".aac")) {
|
||||
} else if (srs_strings_ends_with(entry_->pattern, ".aac")) {
|
||||
w->header()->set_content_type("audio/x-aac");
|
||||
enc_desc = "AAC";
|
||||
enc_raw = new SrsAacStreamEncoder();
|
||||
} else if (srs_strings_ends_with(entry->pattern, ".mp3")) {
|
||||
} else if (srs_strings_ends_with(entry_->pattern, ".mp3")) {
|
||||
w->header()->set_content_type("audio/mpeg");
|
||||
enc_desc = "MP3";
|
||||
enc_raw = new SrsMp3StreamEncoder();
|
||||
} else if (srs_strings_ends_with(entry->pattern, ".ts")) {
|
||||
} else if (srs_strings_ends_with(entry_->pattern, ".ts")) {
|
||||
w->header()->set_content_type("video/MP2T");
|
||||
enc_desc = "TS";
|
||||
enc_raw = new SrsTsStreamEncoder();
|
||||
|
|
@ -770,7 +799,7 @@ srs_error_t SrsLiveStream::do_serve_http(SrsLiveSource *source, SrsLiveConsumer
|
|||
((SrsTsStreamEncoder *)enc_raw)->set_has_video(has_video);
|
||||
((SrsTsStreamEncoder *)enc_raw)->set_guess_has_av(guess_has_av);
|
||||
} else {
|
||||
return srs_error_new(ERROR_HTTP_LIVE_STREAM_EXT, "invalid pattern=%s", entry->pattern.c_str());
|
||||
return srs_error_new(ERROR_HTTP_LIVE_STREAM_EXT, "invalid pattern=%s", entry_->pattern.c_str());
|
||||
}
|
||||
SrsUniquePtr<ISrsBufferEncoder> enc(enc_raw);
|
||||
|
||||
|
|
@ -817,14 +846,14 @@ srs_error_t SrsLiveStream::do_serve_http(SrsLiveSource *source, SrsLiveConsumer
|
|||
return srs_error_wrap(err, "start recv thread");
|
||||
}
|
||||
|
||||
srs_utime_t mw_sleep = _srs_config->get_mw_sleep(req_->vhost_);
|
||||
srs_utime_t mw_sleep = config_->get_mw_sleep(req_->vhost_);
|
||||
srs_trace("FLV %s, encoder=%s, mw_sleep=%dms, cache=%d, msgs=%d, dinm=%d, guess_av=%d/%d/%d",
|
||||
entry->pattern.c_str(), enc_desc.c_str(), srsu2msi(mw_sleep), enc->has_cache(), msgs.max_, drop_if_not_match,
|
||||
entry_->pattern.c_str(), enc_desc.c_str(), srsu2msi(mw_sleep), enc->has_cache(), msgs.max_, drop_if_not_match,
|
||||
has_audio, has_video, guess_has_av);
|
||||
|
||||
// TODO: free and erase the disabled entry after all related connections is closed.
|
||||
// TODO: FXIME: Support timeout for player, quit infinite-loop.
|
||||
while (entry->enabled) {
|
||||
while (entry_->enabled) {
|
||||
// Whether client closed the FD.
|
||||
if ((err = trd->pull()) != srs_success) {
|
||||
return srs_error_wrap(err, "recv thread");
|
||||
|
|
@ -882,7 +911,7 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage *r)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -896,7 +925,7 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage *r)
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_play(nreq->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_play(nreq->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
return err;
|
||||
|
|
@ -907,7 +936,7 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage *r)
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
if ((err = _srs_hooks->on_play(url, nreq.get())) != srs_success) {
|
||||
if ((err = hooks_->on_play(url, nreq.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "http on_play %s", url.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -917,7 +946,7 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage *r)
|
|||
|
||||
void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage *r)
|
||||
{
|
||||
if (!_srs_config->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
if (!config_->get_vhost_http_hooks_enabled(req_->vhost_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -931,7 +960,7 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage *r)
|
|||
vector<string> hooks;
|
||||
|
||||
if (true) {
|
||||
SrsConfDirective *conf = _srs_config->get_vhost_on_stop(nreq->vhost_);
|
||||
SrsConfDirective *conf = config_->get_vhost_on_stop(nreq->vhost_);
|
||||
|
||||
if (!conf) {
|
||||
srs_info("ignore the empty http callback: on_stop");
|
||||
|
|
@ -943,7 +972,7 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage *r)
|
|||
|
||||
for (int i = 0; i < (int)hooks.size(); i++) {
|
||||
std::string url = hooks.at(i);
|
||||
_srs_hooks->on_stop(url, nreq.get());
|
||||
hooks_->on_stop(url, nreq.get());
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -1017,19 +1046,24 @@ bool SrsLiveEntry::is_mp3()
|
|||
return is_mp3_;
|
||||
}
|
||||
|
||||
SrsHttpStreamServer::SrsHttpStreamServer(SrsServer *svr)
|
||||
SrsHttpStreamServer::SrsHttpStreamServer()
|
||||
{
|
||||
server_ = svr;
|
||||
async_ = new SrsAsyncCallWorker();
|
||||
|
||||
mux_.add_dynamic_matcher(this);
|
||||
_srs_config->subscribe(this);
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
void SrsHttpStreamServer::assemble()
|
||||
{
|
||||
config_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsHttpStreamServer::~SrsHttpStreamServer()
|
||||
{
|
||||
mux_.remove_dynamic_matcher(this);
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
async_->stop();
|
||||
srs_freep(async_);
|
||||
|
|
@ -1050,6 +1084,8 @@ SrsHttpStreamServer::~SrsHttpStreamServer()
|
|||
}
|
||||
streamHandlers_.clear();
|
||||
}
|
||||
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpStreamServer::initialize()
|
||||
|
|
@ -1098,8 +1134,8 @@ srs_error_t SrsHttpStreamServer::http_mount(ISrsRequest *r)
|
|||
entry = new SrsLiveEntry(mount);
|
||||
|
||||
entry->req_ = r->copy()->as_http();
|
||||
entry->cache_ = new SrsBufferCache(server_, r);
|
||||
entry->stream_ = new SrsLiveStream(server_, r, entry->cache_);
|
||||
entry->cache_ = new SrsBufferCache(r);
|
||||
entry->stream_ = new SrsLiveStream(r, entry->cache_);
|
||||
|
||||
// TODO: FIXME: maybe refine the logic of http remux service.
|
||||
// if user push streams followed:
|
||||
|
|
@ -1139,7 +1175,7 @@ srs_error_t SrsHttpStreamServer::http_mount(ISrsRequest *r)
|
|||
}
|
||||
|
||||
if (entry->stream_) {
|
||||
entry->stream_->entry->enabled = true;
|
||||
entry->stream_->entry_->enabled = true;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1176,7 +1212,7 @@ srs_error_t SrsHttpStreamServer::dynamic_match(ISrsHttpMessage *request, ISrsHtt
|
|||
|
||||
// when handler not the root, we think the handler is ok.
|
||||
ISrsHttpHandler *h = *ph ? *ph : NULL;
|
||||
if (h && h->entry && h->entry->pattern != "/") {
|
||||
if (h && h->entry_ && h->entry_->pattern != "/") {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1187,8 +1223,8 @@ srs_error_t SrsHttpStreamServer::dynamic_match(ISrsHttpMessage *request, ISrsHtt
|
|||
}
|
||||
|
||||
// find the actually request vhost.
|
||||
SrsConfDirective *vhost = _srs_config->get_vhost(request->host());
|
||||
if (!vhost || !_srs_config->get_vhost_enabled(vhost)) {
|
||||
SrsConfDirective *vhost = config_->get_vhost(request->host());
|
||||
if (!vhost || !config_->get_vhost_enabled(vhost)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1254,11 +1290,11 @@ srs_error_t SrsHttpStreamServer::dynamic_match(ISrsHttpMessage *request, ISrsHtt
|
|||
// for example, user disable the http flv then reload.
|
||||
if (streamHandlers_.find(sid) != streamHandlers_.end()) {
|
||||
SrsLiveEntry *s_entry = streamHandlers_[sid];
|
||||
if (!s_entry->stream_->entry->enabled) {
|
||||
if (!s_entry->stream_->entry_->enabled) {
|
||||
// only when the http entry is disabled, check the config whether http flv disable,
|
||||
// for the http flv edge use match to trigger the edge ingester, we always mount it
|
||||
// eventhough the origin does not exists the specified stream.
|
||||
if (!_srs_config->get_vhost_http_remux_enabled(r->vhost_)) {
|
||||
if (!config_->get_vhost_http_remux_enabled(r->vhost_)) {
|
||||
return srs_error_new(ERROR_HTTP_DYNAMIC_MATCH, "stream disabled");
|
||||
}
|
||||
}
|
||||
|
|
@ -1285,7 +1321,7 @@ srs_error_t SrsHttpStreamServer::initialize_flv_streaming()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// http flv live stream mount for each vhost.
|
||||
SrsConfDirective *root = _srs_config->get_root();
|
||||
SrsConfDirective *root = config_->get_root();
|
||||
for (int i = 0; i < (int)root->directives_.size(); i++) {
|
||||
SrsConfDirective *conf = root->at(i);
|
||||
|
||||
|
|
@ -1305,11 +1341,11 @@ srs_error_t SrsHttpStreamServer::initialize_flv_entry(std::string vhost)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_vhost_http_remux_enabled(vhost)) {
|
||||
if (!config_->get_vhost_http_remux_enabled(vhost)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
SrsLiveEntry *entry = new SrsLiveEntry(_srs_config->get_vhost_http_remux_mount(vhost));
|
||||
SrsLiveEntry *entry = new SrsLiveEntry(config_->get_vhost_http_remux_mount(vhost));
|
||||
|
||||
templateHandlers_[vhost] = entry;
|
||||
srs_trace("http flv live stream, vhost=%s, mount=%s", vhost.c_str(), entry->mount_.c_str());
|
||||
|
|
@ -1341,12 +1377,12 @@ srs_error_t SrsHttpStreamDestroy::call()
|
|||
SrsUniquePtr<SrsLiveEntry> entry(it->second);
|
||||
srs_assert(entry->disposing_);
|
||||
|
||||
SrsUniquePtr<SrsLiveStream> stream(entry->stream_);
|
||||
SrsUniquePtr<SrsBufferCache> cache(entry->cache_);
|
||||
SrsUniquePtr<ISrsLiveStream> stream(entry->stream_);
|
||||
SrsUniquePtr<ISrsBufferCache> cache(entry->cache_);
|
||||
|
||||
// Notify cache and stream to stop.
|
||||
if (stream->entry)
|
||||
stream->entry->enabled = false;
|
||||
if (stream->entry_)
|
||||
stream->entry_->enabled = false;
|
||||
stream->expire();
|
||||
cache->stop();
|
||||
|
||||
|
|
|
|||
|
|
@ -16,24 +16,54 @@
|
|||
|
||||
class SrsAacTransmuxer;
|
||||
class SrsMp3Transmuxer;
|
||||
class SrsFlvTransmuxer;
|
||||
class ISrsFlvTransmuxer;
|
||||
class SrsTsTransmuxer;
|
||||
class SrsAsyncCallWorker;
|
||||
class ISrsAppConfig;
|
||||
class ISrsLiveSourceManager;
|
||||
class ISrsStatistic;
|
||||
class ISrsHttpHooks;
|
||||
class ISrsMessageQueue;
|
||||
class ISrsLiveConsumer;
|
||||
class ISrsTsTransmuxer;
|
||||
class ISrsAacTransmuxer;
|
||||
class ISrsBufferCache;
|
||||
class ISrsMp3Transmuxer;
|
||||
|
||||
// The cache for HTTP Live Streaming encoder.
|
||||
class ISrsBufferCache
|
||||
{
|
||||
public:
|
||||
ISrsBufferCache();
|
||||
virtual ~ISrsBufferCache();
|
||||
|
||||
public:
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
public:
|
||||
virtual bool alive() = 0;
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter) = 0;
|
||||
virtual srs_error_t update_auth(ISrsRequest *r) = 0;
|
||||
};
|
||||
|
||||
// A cache for HTTP Live Streaming encoder, to make android(weixin) happy.
|
||||
class SrsBufferCache : public ISrsCoroutineHandler
|
||||
class SrsBufferCache : public ISrsCoroutineHandler, public ISrsBufferCache
|
||||
{
|
||||
private:
|
||||
srs_utime_t fast_cache_;
|
||||
SrsServer *server_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
|
||||
private:
|
||||
SrsMessageQueue *queue_;
|
||||
srs_utime_t fast_cache_;
|
||||
|
||||
private:
|
||||
ISrsMessageQueue *queue_;
|
||||
ISrsRequest *req_;
|
||||
ISrsCoroutine *trd_;
|
||||
|
||||
public:
|
||||
SrsBufferCache(SrsServer *s, ISrsRequest *r);
|
||||
SrsBufferCache(ISrsRequest *r);
|
||||
virtual ~SrsBufferCache();
|
||||
virtual srs_error_t update_auth(ISrsRequest *r);
|
||||
|
||||
|
|
@ -41,7 +71,7 @@ public:
|
|||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
virtual bool alive();
|
||||
virtual srs_error_t dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
// Interface ISrsEndlessThreadHandler.
|
||||
public:
|
||||
virtual srs_error_t cycle();
|
||||
|
|
@ -58,7 +88,7 @@ public:
|
|||
// Initialize the encoder with file writer(to http response) and stream cache.
|
||||
// @param w the writer to write to http response.
|
||||
// @param c the stream cache for audio stream fast startup.
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, SrsBufferCache *c) = 0;
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, ISrsBufferCache *c) = 0;
|
||||
// Write rtmp video/audio/metadata.
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size) = 0;
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size) = 0;
|
||||
|
|
@ -70,14 +100,14 @@ public:
|
|||
// @return true to use gop cache of encoder; otherwise, use SrsLiveSource.
|
||||
virtual bool has_cache() = 0;
|
||||
// Dumps the cache of encoder to consumer.
|
||||
virtual srs_error_t dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter) = 0;
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter) = 0;
|
||||
};
|
||||
|
||||
// Transmux RTMP to HTTP Live Streaming.
|
||||
class SrsFlvStreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
SrsFlvTransmuxer *enc_;
|
||||
ISrsFlvTransmuxer *enc_;
|
||||
bool header_written_;
|
||||
bool has_audio_;
|
||||
bool has_video_;
|
||||
|
|
@ -88,7 +118,7 @@ public:
|
|||
virtual ~SrsFlvStreamEncoder();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, SrsBufferCache *c);
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, ISrsBufferCache *c);
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_metadata(int64_t timestamp, char *data, int size);
|
||||
|
|
@ -101,7 +131,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual bool has_cache();
|
||||
virtual srs_error_t dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
|
||||
public:
|
||||
// Write the tags in a time.
|
||||
|
|
@ -115,21 +145,21 @@ private:
|
|||
class SrsTsStreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
SrsTsTransmuxer *enc_;
|
||||
ISrsTsTransmuxer *enc_;
|
||||
|
||||
public:
|
||||
SrsTsStreamEncoder();
|
||||
virtual ~SrsTsStreamEncoder();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, SrsBufferCache *c);
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, ISrsBufferCache *c);
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_metadata(int64_t timestamp, char *data, int size);
|
||||
|
||||
public:
|
||||
virtual bool has_cache();
|
||||
virtual srs_error_t dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
|
||||
public:
|
||||
void set_has_audio(bool v);
|
||||
|
|
@ -141,44 +171,44 @@ public:
|
|||
class SrsAacStreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
SrsAacTransmuxer *enc_;
|
||||
SrsBufferCache *cache_;
|
||||
ISrsAacTransmuxer *enc_;
|
||||
ISrsBufferCache *cache_;
|
||||
|
||||
public:
|
||||
SrsAacStreamEncoder();
|
||||
virtual ~SrsAacStreamEncoder();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, SrsBufferCache *c);
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, ISrsBufferCache *c);
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_metadata(int64_t timestamp, char *data, int size);
|
||||
|
||||
public:
|
||||
virtual bool has_cache();
|
||||
virtual srs_error_t dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
};
|
||||
|
||||
// Transmux RTMP with MP3 stream to HTTP MP3 Streaming.
|
||||
class SrsMp3StreamEncoder : public ISrsBufferEncoder
|
||||
{
|
||||
private:
|
||||
SrsMp3Transmuxer *enc_;
|
||||
SrsBufferCache *cache_;
|
||||
ISrsMp3Transmuxer *enc_;
|
||||
ISrsBufferCache *cache_;
|
||||
|
||||
public:
|
||||
SrsMp3StreamEncoder();
|
||||
virtual ~SrsMp3StreamEncoder();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, SrsBufferCache *c);
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, ISrsBufferCache *c);
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_metadata(int64_t timestamp, char *data, int size);
|
||||
|
||||
public:
|
||||
virtual bool has_cache();
|
||||
virtual srs_error_t dump_cache(SrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
};
|
||||
|
||||
// Write stream to http response direclty.
|
||||
|
|
@ -204,22 +234,39 @@ public:
|
|||
virtual srs_error_t writev(const iovec *iov, int iovcnt, ssize_t *pnwrite);
|
||||
};
|
||||
|
||||
// Interface for HTTP Live Streaming.
|
||||
class ISrsLiveStream : public ISrsHttpHandler, public ISrsExpire
|
||||
{
|
||||
public:
|
||||
ISrsLiveStream();
|
||||
virtual ~ISrsLiveStream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t update_auth(ISrsRequest *r) = 0;
|
||||
virtual bool alive() = 0;
|
||||
};
|
||||
|
||||
// HTTP Live Streaming, to transmux RTMP to HTTP FLV or other format.
|
||||
// TODO: FIXME: Rename to SrsHttpLive
|
||||
class SrsLiveStream : public ISrsHttpHandler, public ISrsExpire
|
||||
class SrsLiveStream : public ISrsLiveStream
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
ISrsLiveSourceManager *live_sources_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
private:
|
||||
ISrsRequest *req_;
|
||||
SrsBufferCache *cache_;
|
||||
SrsSecurity *security_;
|
||||
SrsServer *server_;
|
||||
ISrsBufferCache *cache_;
|
||||
ISrsSecurity *security_;
|
||||
// For multiple viewers, which means there will more than one alive viewers for a live stream, so we must
|
||||
// use an int value to represent if there is any viewer is alive. We should never do cleanup unless all
|
||||
// viewers closed the connection.
|
||||
std::vector<ISrsExpire *> viewers_;
|
||||
|
||||
public:
|
||||
SrsLiveStream(SrsServer *s, ISrsRequest *r, SrsBufferCache *c);
|
||||
SrsLiveStream(ISrsRequest *r, ISrsBufferCache *c);
|
||||
virtual ~SrsLiveStream();
|
||||
virtual srs_error_t update_auth(ISrsRequest *r);
|
||||
|
||||
|
|
@ -236,7 +283,7 @@ public:
|
|||
virtual void expire();
|
||||
|
||||
private:
|
||||
virtual srs_error_t do_serve_http(SrsLiveSource *source, SrsLiveConsumer *consumer, ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
virtual srs_error_t do_serve_http(SrsLiveSource *source, ISrsLiveConsumer *consumer, ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
virtual srs_error_t http_hooks_on_play(ISrsHttpMessage *r);
|
||||
virtual void http_hooks_on_stop(ISrsHttpMessage *r);
|
||||
virtual srs_error_t streaming_send_messages(ISrsBufferEncoder *enc, SrsMediaPacket **msgs, int nb_msgs);
|
||||
|
|
@ -259,8 +306,8 @@ public:
|
|||
// For concrete stream, the mount is url to access.
|
||||
std::string mount_;
|
||||
|
||||
SrsLiveStream *stream_;
|
||||
SrsBufferCache *cache_;
|
||||
ISrsLiveStream *stream_;
|
||||
ISrsBufferCache *cache_;
|
||||
|
||||
// Whether is disposing the entry.
|
||||
bool disposing_;
|
||||
|
|
@ -279,8 +326,10 @@ public:
|
|||
class SrsHttpStreamServer : public ISrsReloadHandler, public ISrsHttpDynamicMatcher
|
||||
{
|
||||
private:
|
||||
SrsServer *server_;
|
||||
SrsAsyncCallWorker *async_;
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
ISrsAsyncCallWorker *async_;
|
||||
|
||||
public:
|
||||
SrsHttpServeMux mux_;
|
||||
|
|
@ -290,7 +339,8 @@ public:
|
|||
std::map<std::string, SrsLiveEntry *> streamHandlers_;
|
||||
|
||||
public:
|
||||
SrsHttpStreamServer(SrsServer *svr);
|
||||
SrsHttpStreamServer();
|
||||
void assemble();
|
||||
virtual ~SrsHttpStreamServer();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -224,6 +224,14 @@ void SrsFastVector::free()
|
|||
}
|
||||
#endif
|
||||
|
||||
ISrsMessageQueue::ISrsMessageQueue()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMessageQueue::~ISrsMessageQueue()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMessageQueue::SrsMessageQueue(bool ignore_shrink)
|
||||
{
|
||||
_ignore_shrink = ignore_shrink;
|
||||
|
|
@ -316,7 +324,7 @@ srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsMediaPacket **pmsgs,
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsMessageQueue::dump_packets(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag)
|
||||
srs_error_t SrsMessageQueue::dump_packets(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -404,6 +412,14 @@ ISrsWakable::~ISrsWakable()
|
|||
{
|
||||
}
|
||||
|
||||
ISrsLiveConsumer::ISrsLiveConsumer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsLiveConsumer::~ISrsLiveConsumer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsLiveConsumer::SrsLiveConsumer(ISrsLiveSource *s)
|
||||
{
|
||||
source_ = s;
|
||||
|
|
@ -681,7 +697,7 @@ void SrsGopCache::clear()
|
|||
audio_after_last_video_count_ = 0;
|
||||
}
|
||||
|
||||
srs_error_t SrsGopCache::dump(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm)
|
||||
srs_error_t SrsGopCache::dump(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -1441,7 +1457,7 @@ SrsFormat *SrsMetaCache::ash_format()
|
|||
return aformat_;
|
||||
}
|
||||
|
||||
srs_error_t SrsMetaCache::dumps(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds)
|
||||
srs_error_t SrsMetaCache::dumps(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -2495,7 +2511,7 @@ srs_error_t SrsLiveSource::create_consumer(SrsLiveConsumer *&consumer)
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsLiveSource::consumer_dumps(SrsLiveConsumer *consumer, bool ds, bool dm, bool dg)
|
||||
srs_error_t SrsLiveSource::consumer_dumps(ISrsLiveConsumer *consumer, bool ds, bool dm, bool dg)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class ISrsHds;
|
|||
class ISrsNgExec;
|
||||
class ISrsForwarder;
|
||||
class SrsAppFactory;
|
||||
class ISrsLiveConsumer;
|
||||
|
||||
// The time jitter algorithm:
|
||||
// 1. full, to ensure stream start at zero, and ensure stream monotonically increasing.
|
||||
|
|
@ -118,9 +119,26 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
// The message queue interface.
|
||||
class ISrsMessageQueue
|
||||
{
|
||||
public:
|
||||
ISrsMessageQueue();
|
||||
virtual ~ISrsMessageQueue();
|
||||
|
||||
public:
|
||||
virtual int size() = 0;
|
||||
virtual srs_utime_t duration() = 0;
|
||||
virtual void set_queue_size(srs_utime_t queue_size) = 0;
|
||||
virtual srs_error_t enqueue(SrsMediaPacket *msg, bool *is_overflow = NULL) = 0;
|
||||
// virtual srs_error_t dump_packets(int max_count, SrsMediaPacket **pmsgs, int &count) = 0;
|
||||
virtual srs_error_t dump_packets(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag) = 0;
|
||||
// virtual void clear() = 0;
|
||||
};
|
||||
|
||||
// The message queue for the consumer(client), forwarder.
|
||||
// We limit the size in seconds, drop old messages(the whole gop) if full.
|
||||
class SrsMessageQueue
|
||||
class SrsMessageQueue : public ISrsMessageQueue
|
||||
{
|
||||
private:
|
||||
// The start and end time.
|
||||
|
|
@ -162,7 +180,7 @@ public:
|
|||
virtual srs_error_t dump_packets(int max_count, SrsMediaPacket **pmsgs, int &count);
|
||||
// Dumps packets to consumer, use specified args.
|
||||
// @remark the atc/tba/tbv/ag are same to SrsLiveConsumer.enqueue().
|
||||
virtual srs_error_t dump_packets(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag);
|
||||
virtual srs_error_t dump_packets(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag);
|
||||
|
||||
private:
|
||||
// Remove a gop from the front.
|
||||
|
|
@ -189,8 +207,22 @@ public:
|
|||
virtual void wakeup() = 0;
|
||||
};
|
||||
|
||||
// The consumer interface.
|
||||
class ISrsLiveConsumer
|
||||
{
|
||||
public:
|
||||
ISrsLiveConsumer();
|
||||
virtual ~ISrsLiveConsumer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t enqueue(SrsMediaPacket *shared_msg, bool atc, SrsRtmpJitterAlgorithm ag) = 0;
|
||||
virtual srs_error_t dump_packets(SrsMessageArray *msgs, int &count) = 0;
|
||||
virtual void set_queue_size(srs_utime_t queue_size) = 0;
|
||||
virtual int64_t get_time() = 0;
|
||||
};
|
||||
|
||||
// The consumer for SrsLiveSource, that is a play client.
|
||||
class SrsLiveConsumer : public ISrsWakable
|
||||
class SrsLiveConsumer : public ISrsWakable, public ISrsLiveConsumer
|
||||
{
|
||||
private:
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
|
|
@ -297,7 +329,7 @@ public:
|
|||
// clear the gop cache.
|
||||
virtual void clear();
|
||||
// dump the cached gop to consumer.
|
||||
virtual srs_error_t dump(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm);
|
||||
virtual srs_error_t dump(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm jitter_algorithm);
|
||||
// used for atc to get the time of gop cache,
|
||||
// The atc will adjust the sequence header timestamp to gop cache.
|
||||
virtual bool empty();
|
||||
|
|
@ -495,7 +527,7 @@ public:
|
|||
// Dumps cached metadata to consumer.
|
||||
// @param dm Whether dumps the metadata.
|
||||
// @param ds Whether dumps the sequence header.
|
||||
virtual srs_error_t dumps(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds);
|
||||
virtual srs_error_t dumps(ISrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag, bool dm, bool ds);
|
||||
|
||||
public:
|
||||
// Previous exists sequence header.
|
||||
|
|
@ -720,7 +752,7 @@ public:
|
|||
// @param ds, whether dumps the sequence header.
|
||||
// @param dm, whether dumps the metadata.
|
||||
// @param dg, whether dumps the gop cache.
|
||||
virtual srs_error_t consumer_dumps(SrsLiveConsumer *consumer, bool ds = true, bool dm = true, bool dg = true);
|
||||
virtual srs_error_t consumer_dumps(ISrsLiveConsumer *consumer, bool ds = true, bool dm = true, bool dg = true);
|
||||
virtual void on_consumer_destroy(SrsLiveConsumer *consumer);
|
||||
virtual void set_cache(bool enabled);
|
||||
virtual void set_gop_cache_max_frames(int v);
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ SrsServer::SrsServer()
|
|||
stream_caster_gb28181_ = new SrsGbListener();
|
||||
#endif
|
||||
|
||||
http_server_ = new SrsHttpServer(this);
|
||||
http_server_ = new SrsHttpServer();
|
||||
reuse_api_over_server_ = false;
|
||||
reuse_rtc_over_server_ = false;
|
||||
|
||||
|
|
@ -1017,7 +1017,7 @@ srs_error_t SrsServer::do2_cycle()
|
|||
srs_trace("reload config success, state=%d.", state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ public:
|
|||
virtual srs_error_t dumps_clients(SrsJsonArray *arr, int start, int count);
|
||||
// Dumps the hints about SRS server.
|
||||
void dumps_hints_kv(std::stringstream &ss);
|
||||
|
||||
private:
|
||||
virtual SrsStatisticVhost *create_vhost(ISrsRequest *req);
|
||||
virtual SrsStatisticStream *create_stream(SrsStatisticVhost *vhost, ISrsRequest *req);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,14 @@ using namespace std;
|
|||
#include <srs_kernel_io.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
|
||||
ISrsAacTransmuxer::ISrsAacTransmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsAacTransmuxer::~ISrsAacTransmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsAacTransmuxer::SrsAacTransmuxer()
|
||||
{
|
||||
writer_ = NULL;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,19 @@
|
|||
class SrsBuffer;
|
||||
class ISrsStreamWriter;
|
||||
|
||||
class ISrsAacTransmuxer
|
||||
{
|
||||
public:
|
||||
ISrsAacTransmuxer();
|
||||
virtual ~ISrsAacTransmuxer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsStreamWriter *fs) = 0;
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size) = 0;
|
||||
};
|
||||
|
||||
// Transmux the RTMP packets to AAC stream.
|
||||
class SrsAacTransmuxer
|
||||
class SrsAacTransmuxer : public ISrsAacTransmuxer
|
||||
{
|
||||
private:
|
||||
ISrsStreamWriter *writer_;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
public:
|
||||
virtual srs_error_t open(std::string p) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual bool is_open() = 0;
|
||||
};
|
||||
|
||||
// file writer, to write to file.
|
||||
|
|
@ -89,6 +90,13 @@ public:
|
|||
public:
|
||||
virtual srs_error_t open(std::string p) = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
public:
|
||||
virtual bool is_open() = 0;
|
||||
virtual int64_t tellg() = 0;
|
||||
virtual void skip(int64_t size) = 0;
|
||||
virtual int64_t seek2(int64_t offset) = 0;
|
||||
virtual int64_t filesize() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -331,6 +331,14 @@ void SrsRtmpCommonMessage::to_msg(SrsMediaPacket *msg)
|
|||
msg->message_type_ = (SrsFrameType)header_.message_type_;
|
||||
}
|
||||
|
||||
ISrsFlvTransmuxer::ISrsFlvTransmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsFlvTransmuxer::~ISrsFlvTransmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFlvTransmuxer::SrsFlvTransmuxer()
|
||||
{
|
||||
writer_ = NULL;
|
||||
|
|
@ -777,7 +785,7 @@ srs_error_t SrsFlvVodStreamDecoder::initialize(ISrsReader *fr)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
srs_assert(fr);
|
||||
reader_ = dynamic_cast<SrsFileReader *>(fr);
|
||||
reader_ = dynamic_cast<ISrsFileReader *>(fr);
|
||||
if (!reader_) {
|
||||
return srs_error_new(ERROR_EXPECT_FILE_IO, "stream is not file io");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
class SrsBuffer;
|
||||
class ISrsWriter;
|
||||
class ISrsReader;
|
||||
class SrsFileReader;
|
||||
class ISrsFileReader;
|
||||
class SrsRtmpCommand;
|
||||
class SrsNaluSample;
|
||||
|
||||
|
|
@ -223,8 +223,50 @@ public:
|
|||
void to_msg(SrsMediaPacket *msg);
|
||||
};
|
||||
|
||||
// The interface for FLV transmuxer.
|
||||
class ISrsFlvTransmuxer
|
||||
{
|
||||
public:
|
||||
ISrsFlvTransmuxer();
|
||||
virtual ~ISrsFlvTransmuxer();
|
||||
|
||||
public:
|
||||
// Initialize the underlayer file stream.
|
||||
// @remark user can initialize multiple times to encode multiple flv files.
|
||||
// @remark, user must free the @param fw, flv encoder never close/free it.
|
||||
virtual srs_error_t initialize(ISrsWriter *fw) = 0;
|
||||
// Drop packet if not match FLV header.
|
||||
virtual void set_drop_if_not_match(bool v) = 0;
|
||||
virtual bool drop_if_not_match() = 0;
|
||||
|
||||
public:
|
||||
// Write flv header.
|
||||
// Write following:
|
||||
// 1. E.2 The FLV header
|
||||
// 2. PreviousTagSize0 UI32 Always 0
|
||||
// that is, 9+4=13bytes.
|
||||
virtual srs_error_t write_header(bool has_video = true, bool has_audio = true) = 0;
|
||||
virtual srs_error_t write_header(char flv_header[9]) = 0;
|
||||
// Write flv metadata.
|
||||
// @param type, the type of data, or other message type.
|
||||
// @see SrsFrameType
|
||||
// @param data, the amf0 metadata which serialize from:
|
||||
// AMF0 string: onMetaData,
|
||||
// AMF0 object: the metadata object.
|
||||
// @remark assert data is not NULL.
|
||||
virtual srs_error_t write_metadata(char type, char *data, int size) = 0;
|
||||
// Write audio/video packet.
|
||||
// @remark assert data is not NULL.
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size) = 0;
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size) = 0;
|
||||
|
||||
public:
|
||||
// Write the tags in a time.
|
||||
virtual srs_error_t write_tags(SrsMediaPacket **msgs, int count) = 0;
|
||||
};
|
||||
|
||||
// Transmux RTMP packets to FLV stream.
|
||||
class SrsFlvTransmuxer
|
||||
class SrsFlvTransmuxer : public ISrsFlvTransmuxer
|
||||
{
|
||||
private:
|
||||
bool has_audio_;
|
||||
|
|
@ -335,7 +377,7 @@ public:
|
|||
class SrsFlvVodStreamDecoder
|
||||
{
|
||||
private:
|
||||
SrsFileReader *reader_;
|
||||
ISrsFileReader *reader_;
|
||||
|
||||
public:
|
||||
SrsFlvVodStreamDecoder();
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ SrsPps::SrsPps()
|
|||
|
||||
SrsPps::~SrsPps()
|
||||
{
|
||||
clk_ = NULL;
|
||||
}
|
||||
|
||||
void SrsPps::update()
|
||||
|
|
@ -102,6 +103,14 @@ int SrsPps::r30s()
|
|||
return sample_30s_.rate_;
|
||||
}
|
||||
|
||||
ISrsClock::ISrsClock()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsClock::~ISrsClock()
|
||||
{
|
||||
}
|
||||
|
||||
SrsWallClock::SrsWallClock()
|
||||
{
|
||||
}
|
||||
|
|
@ -548,7 +557,7 @@ void srs_global_rtc_update(SrsKbsRtcStats *stats)
|
|||
}
|
||||
}
|
||||
|
||||
SrsKbpsSlice::SrsKbpsSlice(SrsWallClock *c)
|
||||
SrsKbpsSlice::SrsKbpsSlice(ISrsClock *c)
|
||||
{
|
||||
clk_ = c;
|
||||
starttime_ = 0;
|
||||
|
|
@ -557,6 +566,7 @@ SrsKbpsSlice::SrsKbpsSlice(SrsWallClock *c)
|
|||
|
||||
SrsKbpsSlice::~SrsKbpsSlice()
|
||||
{
|
||||
clk_ = NULL;
|
||||
}
|
||||
|
||||
void SrsKbpsSlice::sample()
|
||||
|
|
@ -674,7 +684,7 @@ void SrsNetworkDelta::remark(int64_t *in, int64_t *out)
|
|||
in_delta_ = out_delta_ = 0;
|
||||
}
|
||||
|
||||
SrsKbps::SrsKbps(SrsWallClock *c)
|
||||
SrsKbps::SrsKbps(ISrsClock *c)
|
||||
{
|
||||
clk_ = c ? c : _srs_clock;
|
||||
is_ = new SrsKbpsSlice(clk_);
|
||||
|
|
@ -685,6 +695,7 @@ SrsKbps::~SrsKbps()
|
|||
{
|
||||
srs_freep(is_);
|
||||
srs_freep(os_);
|
||||
clk_ = NULL;
|
||||
}
|
||||
|
||||
int SrsKbps::get_send_kbps()
|
||||
|
|
@ -764,7 +775,7 @@ int64_t SrsKbps::get_recv_bytes()
|
|||
return is_->bytes_;
|
||||
}
|
||||
|
||||
SrsNetworkKbps::SrsNetworkKbps(SrsWallClock *clock)
|
||||
SrsNetworkKbps::SrsNetworkKbps(ISrsClock *clock)
|
||||
{
|
||||
delta_ = new SrsNetworkDelta();
|
||||
kbps_ = new SrsKbps(clock);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,44 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
class SrsWallClock;
|
||||
class ISrsProtocolStatistic;
|
||||
|
||||
/**
|
||||
* Interface for clock abstraction to provide wall clock time.
|
||||
* This interface enables dependency injection and testability.
|
||||
*/
|
||||
class ISrsClock
|
||||
{
|
||||
public:
|
||||
ISrsClock();
|
||||
virtual ~ISrsClock();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Current time in srs_utime_t.
|
||||
*/
|
||||
virtual srs_utime_t now() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A time source to provide wall clock.
|
||||
*/
|
||||
class SrsWallClock : public ISrsClock
|
||||
{
|
||||
public:
|
||||
SrsWallClock();
|
||||
virtual ~SrsWallClock();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Current time in srs_utime_t.
|
||||
*/
|
||||
virtual srs_utime_t now();
|
||||
};
|
||||
|
||||
// The global clock.
|
||||
extern SrsWallClock *_srs_clock;
|
||||
|
||||
// A sample for rate-based stat, such as kbps or kps.
|
||||
class SrsRateSample
|
||||
{
|
||||
|
|
@ -37,7 +72,7 @@ public:
|
|||
class SrsPps
|
||||
{
|
||||
private:
|
||||
SrsWallClock *clk_;
|
||||
ISrsClock *clk_;
|
||||
|
||||
private:
|
||||
// samples
|
||||
|
|
@ -66,25 +101,6 @@ public:
|
|||
int r30s();
|
||||
};
|
||||
|
||||
/**
|
||||
* A time source to provide wall clock.
|
||||
*/
|
||||
class SrsWallClock
|
||||
{
|
||||
public:
|
||||
SrsWallClock();
|
||||
virtual ~SrsWallClock();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Current time in srs_utime_t.
|
||||
*/
|
||||
virtual srs_utime_t now();
|
||||
};
|
||||
|
||||
// The global clock.
|
||||
extern SrsWallClock *_srs_clock;
|
||||
|
||||
// Global SrsPps statistics variables
|
||||
// I/O operations statistics
|
||||
extern SrsPps *_srs_pps_recvfrom;
|
||||
|
|
@ -237,7 +253,7 @@ void srs_global_rtc_update(SrsKbsRtcStats *stats);
|
|||
class SrsKbpsSlice
|
||||
{
|
||||
private:
|
||||
SrsWallClock *clk_;
|
||||
ISrsClock *clk_;
|
||||
|
||||
public:
|
||||
// session startup bytes
|
||||
|
|
@ -252,7 +268,7 @@ public:
|
|||
SrsRateSample sample_60m_;
|
||||
|
||||
public:
|
||||
SrsKbpsSlice(SrsWallClock *c);
|
||||
SrsKbpsSlice(ISrsClock *c);
|
||||
virtual ~SrsKbpsSlice();
|
||||
|
||||
public:
|
||||
|
|
@ -340,11 +356,11 @@ class SrsKbps
|
|||
private:
|
||||
SrsKbpsSlice *is_;
|
||||
SrsKbpsSlice *os_;
|
||||
SrsWallClock *clk_;
|
||||
ISrsClock *clk_;
|
||||
|
||||
public:
|
||||
// Note that we won't free the clock c.
|
||||
SrsKbps(SrsWallClock *c = NULL);
|
||||
SrsKbps(ISrsClock *c = NULL);
|
||||
virtual ~SrsKbps();
|
||||
|
||||
public:
|
||||
|
|
@ -378,7 +394,7 @@ private:
|
|||
SrsKbps *kbps_;
|
||||
|
||||
public:
|
||||
SrsNetworkKbps(SrsWallClock *c = NULL);
|
||||
SrsNetworkKbps(ISrsClock *c = NULL);
|
||||
virtual ~SrsNetworkKbps();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,14 @@ using namespace std;
|
|||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
|
||||
ISrsMp3Transmuxer::ISrsMp3Transmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMp3Transmuxer::~ISrsMp3Transmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsMp3Transmuxer::SrsMp3Transmuxer()
|
||||
{
|
||||
writer_ = NULL;
|
||||
|
|
@ -30,7 +38,7 @@ SrsMp3Transmuxer::~SrsMp3Transmuxer()
|
|||
{
|
||||
}
|
||||
|
||||
srs_error_t SrsMp3Transmuxer::initialize(SrsFileWriter *fw)
|
||||
srs_error_t SrsMp3Transmuxer::initialize(ISrsFileWriter *fw)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,15 +12,28 @@
|
|||
#include <string>
|
||||
|
||||
class SrsBuffer;
|
||||
class SrsFileWriter;
|
||||
class ISrsFileWriter;
|
||||
|
||||
// The interface for MP3 transmuxer.
|
||||
class ISrsMp3Transmuxer
|
||||
{
|
||||
public:
|
||||
ISrsMp3Transmuxer();
|
||||
virtual ~ISrsMp3Transmuxer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsFileWriter *fw) = 0;
|
||||
virtual srs_error_t write_header() = 0;
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transmux RTMP packet to MP3 stream.
|
||||
*/
|
||||
class SrsMp3Transmuxer
|
||||
class SrsMp3Transmuxer : public ISrsMp3Transmuxer
|
||||
{
|
||||
private:
|
||||
SrsFileWriter *writer_;
|
||||
ISrsFileWriter *writer_;
|
||||
|
||||
public:
|
||||
SrsMp3Transmuxer();
|
||||
|
|
@ -32,7 +45,7 @@ public:
|
|||
* @remark user can initialize multiple times to encode multiple mp3 files.
|
||||
* @remark, user must free the @param fw, mp3 encoder never close/free it.
|
||||
*/
|
||||
virtual srs_error_t initialize(SrsFileWriter *fw);
|
||||
virtual srs_error_t initialize(ISrsFileWriter *fw);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -352,6 +352,14 @@ srs_error_t SrsParsedVideoPacket::parse_hevc_bframe(const SrsNaluSample *sample,
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsFormat::ISrsFormat()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsFormat::~ISrsFormat()
|
||||
{
|
||||
}
|
||||
|
||||
SrsFormat::SrsFormat()
|
||||
{
|
||||
acodec_ = NULL;
|
||||
|
|
@ -482,6 +490,26 @@ bool SrsFormat::is_avc_sequence_header()
|
|||
return vcodec_ && (h264 || h265 || av1) && video_ && video_->avc_packet_type_ == SrsVideoAvcFrameTraitSequenceHeader;
|
||||
}
|
||||
|
||||
SrsParsedAudioPacket* SrsFormat::audio()
|
||||
{
|
||||
return audio_;
|
||||
}
|
||||
|
||||
SrsAudioCodecConfig* SrsFormat::acodec()
|
||||
{
|
||||
return acodec_;
|
||||
}
|
||||
|
||||
SrsParsedVideoPacket* SrsFormat::video()
|
||||
{
|
||||
return video_;
|
||||
}
|
||||
|
||||
SrsVideoCodecConfig* SrsFormat::vcodec()
|
||||
{
|
||||
return vcodec_;
|
||||
}
|
||||
|
||||
// Remove the emulation bytes from stream, and return num of bytes of the rbsp.
|
||||
int srs_rbsp_remove_emulation_bytes(SrsBuffer *stream, std::vector<uint8_t> &rbsp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -162,11 +162,49 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* Interface for codec format.
|
||||
* A codec format, including one or many stream, each stream identified by a frame.
|
||||
* For example, a typical RTMP stream format, consits of a video and audio frame.
|
||||
* Maybe some RTMP stream only has a audio stream, for instance, redio application.
|
||||
*/
|
||||
class SrsFormat
|
||||
class ISrsFormat
|
||||
{
|
||||
public:
|
||||
ISrsFormat();
|
||||
virtual ~ISrsFormat();
|
||||
|
||||
public:
|
||||
// Initialize the format.
|
||||
virtual srs_error_t initialize() = 0;
|
||||
// When got a parsed audio packet.
|
||||
// @param data The data in FLV format.
|
||||
virtual srs_error_t on_audio(int64_t timestamp, char *data, int size) = 0;
|
||||
// When got a parsed video packet.
|
||||
// @param data The data in FLV format.
|
||||
virtual srs_error_t on_video(int64_t timestamp, char *data, int size) = 0;
|
||||
// When got a audio aac sequence header.
|
||||
virtual srs_error_t on_aac_sequence_header(char *data, int size) = 0;
|
||||
|
||||
public:
|
||||
virtual bool is_aac_sequence_header() = 0;
|
||||
virtual bool is_mp3_sequence_header() = 0;
|
||||
// TODO: is avc|hevc|av1 sequence header
|
||||
virtual bool is_avc_sequence_header() = 0;
|
||||
|
||||
public:
|
||||
// Getters for codec and packet information
|
||||
virtual SrsParsedAudioPacket* audio() = 0;
|
||||
virtual SrsAudioCodecConfig* acodec() = 0;
|
||||
virtual SrsParsedVideoPacket* video() = 0;
|
||||
virtual SrsVideoCodecConfig* vcodec() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A codec format, including one or many stream, each stream identified by a frame.
|
||||
* For example, a typical RTMP stream format, consits of a video and audio frame.
|
||||
* Maybe some RTMP stream only has a audio stream, for instance, redio application.
|
||||
*/
|
||||
class SrsFormat : public ISrsFormat
|
||||
{
|
||||
public:
|
||||
SrsParsedAudioPacket *audio_;
|
||||
|
|
@ -207,6 +245,13 @@ public:
|
|||
// TODO: is avc|hevc|av1 sequence header
|
||||
virtual bool is_avc_sequence_header();
|
||||
|
||||
public:
|
||||
// Getters for codec and packet information
|
||||
virtual SrsParsedAudioPacket* audio();
|
||||
virtual SrsAudioCodecConfig* acodec();
|
||||
virtual SrsParsedVideoPacket* video();
|
||||
virtual SrsVideoCodecConfig* vcodec();
|
||||
|
||||
private:
|
||||
// Demux the video packet in H.264 codec.
|
||||
// The packet is muxed in FLV format, defined in flv specification.
|
||||
|
|
|
|||
|
|
@ -311,6 +311,14 @@ ISrsTsHandler::~ISrsTsHandler()
|
|||
{
|
||||
}
|
||||
|
||||
ISrsTsContext::ISrsTsContext()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTsContext::~ISrsTsContext()
|
||||
{
|
||||
}
|
||||
|
||||
SrsTsContext::SrsTsContext()
|
||||
{
|
||||
ready_ = false;
|
||||
|
|
@ -652,7 +660,7 @@ srs_error_t SrsTsContext::encode_pes(ISrsStreamWriter *writer, SrsTsMessage *msg
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsTsPacket::SrsTsPacket(SrsTsContext *c)
|
||||
SrsTsPacket::SrsTsPacket(ISrsTsContext *c)
|
||||
{
|
||||
context_ = c;
|
||||
|
||||
|
|
@ -834,7 +842,7 @@ void SrsTsPacket::padding(int nb_stuffings)
|
|||
}
|
||||
}
|
||||
|
||||
SrsTsPacket *SrsTsPacket::create_pat(SrsTsContext *context, int16_t pmt_number, int16_t pmt_pid)
|
||||
SrsTsPacket *SrsTsPacket::create_pat(ISrsTsContext *context, int16_t pmt_number, int16_t pmt_pid)
|
||||
{
|
||||
SrsTsPacket *pkt = new SrsTsPacket(context);
|
||||
pkt->sync_byte_ = 0x47;
|
||||
|
|
@ -863,7 +871,7 @@ SrsTsPacket *SrsTsPacket::create_pat(SrsTsContext *context, int16_t pmt_number,
|
|||
return pkt;
|
||||
}
|
||||
|
||||
SrsTsPacket *SrsTsPacket::create_pmt(SrsTsContext *context,
|
||||
SrsTsPacket *SrsTsPacket::create_pmt(ISrsTsContext *context,
|
||||
int16_t pmt_number, int16_t pmt_pid, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as)
|
||||
{
|
||||
SrsTsPacket *pkt = new SrsTsPacket(context);
|
||||
|
|
@ -915,7 +923,7 @@ SrsTsPacket *SrsTsPacket::create_pmt(SrsTsContext *context,
|
|||
return pkt;
|
||||
}
|
||||
|
||||
SrsTsPacket *SrsTsPacket::create_pes_first(SrsTsContext *context,
|
||||
SrsTsPacket *SrsTsPacket::create_pes_first(ISrsTsContext *context,
|
||||
int16_t pid, SrsTsPESStreamId sid, uint8_t continuity_counter, bool discontinuity,
|
||||
int64_t pcr, int64_t dts, int64_t pts, int size)
|
||||
{
|
||||
|
|
@ -974,7 +982,7 @@ SrsTsPacket *SrsTsPacket::create_pes_first(SrsTsContext *context,
|
|||
return pkt;
|
||||
}
|
||||
|
||||
SrsTsPacket *SrsTsPacket::create_pes_continue(SrsTsContext *context, int16_t pid, SrsTsPESStreamId sid, uint8_t continuity_counter)
|
||||
SrsTsPacket *SrsTsPacket::create_pes_continue(ISrsTsContext *context, int16_t pid, SrsTsPESStreamId sid, uint8_t continuity_counter)
|
||||
{
|
||||
SrsTsPacket *pkt = new SrsTsPacket(context);
|
||||
pkt->sync_byte_ = 0x47;
|
||||
|
|
@ -2757,7 +2765,15 @@ srs_error_t SrsTsPayloadPMT::psi_encode(SrsBuffer *stream)
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsTsContextWriter::SrsTsContextWriter(ISrsStreamWriter *w, SrsTsContext *c, SrsAudioCodecId ac, SrsVideoCodecId vc)
|
||||
ISrsTsContextWriter::ISrsTsContextWriter()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTsContextWriter::~ISrsTsContextWriter()
|
||||
{
|
||||
}
|
||||
|
||||
SrsTsContextWriter::SrsTsContextWriter(ISrsStreamWriter *w, ISrsTsContext *c, SrsAudioCodecId ac, SrsVideoCodecId vc)
|
||||
{
|
||||
writer_ = w;
|
||||
context_ = c;
|
||||
|
|
@ -2905,6 +2921,14 @@ void SrsEncFileWriter::close()
|
|||
SrsFileWriter::close();
|
||||
}
|
||||
|
||||
ISrsTsMessageCache::ISrsTsMessageCache()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTsMessageCache::~ISrsTsMessageCache()
|
||||
{
|
||||
}
|
||||
|
||||
SrsTsMessageCache::SrsTsMessageCache()
|
||||
{
|
||||
audio_ = NULL;
|
||||
|
|
@ -2979,6 +3003,26 @@ srs_error_t SrsTsMessageCache::cache_video(SrsParsedVideoPacket *frame, int64_t
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsTsMessage* SrsTsMessageCache::audio()
|
||||
{
|
||||
return audio_;
|
||||
}
|
||||
|
||||
void SrsTsMessageCache::set_audio(SrsTsMessage* msg)
|
||||
{
|
||||
audio_ = msg;
|
||||
}
|
||||
|
||||
SrsTsMessage* SrsTsMessageCache::video()
|
||||
{
|
||||
return video_;
|
||||
}
|
||||
|
||||
void SrsTsMessageCache::set_video(SrsTsMessage* msg)
|
||||
{
|
||||
video_ = msg;
|
||||
}
|
||||
|
||||
srs_error_t SrsTsMessageCache::do_cache_mp3(SrsParsedAudioPacket *frame)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
|
@ -3246,31 +3290,39 @@ srs_error_t SrsTsMessageCache::do_cache_hevc(SrsParsedVideoPacket *frame)
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsTsTransmuxer::ISrsTsTransmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsTsTransmuxer::~ISrsTsTransmuxer()
|
||||
{
|
||||
}
|
||||
|
||||
SrsTsTransmuxer::SrsTsTransmuxer()
|
||||
{
|
||||
writer = NULL;
|
||||
format = new SrsFormat();
|
||||
tsmc = new SrsTsMessageCache();
|
||||
context = new SrsTsContext();
|
||||
tscw = NULL;
|
||||
writer_ = NULL;
|
||||
format_ = new SrsFormat();
|
||||
tsmc_ = new SrsTsMessageCache();
|
||||
context_ = new SrsTsContext();
|
||||
tscw_ = NULL;
|
||||
has_audio_ = has_video_ = true;
|
||||
guess_has_av_ = true;
|
||||
}
|
||||
|
||||
SrsTsTransmuxer::~SrsTsTransmuxer()
|
||||
{
|
||||
srs_freep(format);
|
||||
srs_freep(tsmc);
|
||||
srs_freep(tscw);
|
||||
srs_freep(context);
|
||||
srs_freep(format_);
|
||||
srs_freep(tsmc_);
|
||||
srs_freep(tscw_);
|
||||
srs_freep(context_);
|
||||
}
|
||||
|
||||
void SrsTsTransmuxer::set_has_audio(bool v)
|
||||
{
|
||||
has_audio_ = v;
|
||||
|
||||
if (tscw != NULL && !v) {
|
||||
tscw->set_acodec(SrsAudioCodecIdForbidden);
|
||||
if (tscw_ != NULL && !v) {
|
||||
tscw_->set_acodec(SrsAudioCodecIdForbidden);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3278,17 +3330,17 @@ void SrsTsTransmuxer::set_has_video(bool v)
|
|||
{
|
||||
has_video_ = v;
|
||||
|
||||
if (tscw != NULL && !v) {
|
||||
tscw->set_vcodec(SrsVideoCodecIdForbidden);
|
||||
if (tscw_ != NULL && !v) {
|
||||
tscw_->set_vcodec(SrsVideoCodecIdForbidden);
|
||||
}
|
||||
}
|
||||
|
||||
void SrsTsTransmuxer::set_guess_has_av(bool v)
|
||||
{
|
||||
guess_has_av_ = v;
|
||||
if (tscw != NULL && v) {
|
||||
tscw->set_acodec(SrsAudioCodecIdForbidden);
|
||||
tscw->set_vcodec(SrsVideoCodecIdForbidden);
|
||||
if (tscw_ != NULL && v) {
|
||||
tscw_->set_acodec(SrsAudioCodecIdForbidden);
|
||||
tscw_->set_vcodec(SrsVideoCodecIdForbidden);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3296,13 +3348,13 @@ srs_error_t SrsTsTransmuxer::initialize(ISrsStreamWriter *fw)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = format->initialize()) != srs_success) {
|
||||
if ((err = format_->initialize()) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: init format");
|
||||
}
|
||||
|
||||
srs_assert(fw);
|
||||
|
||||
writer = fw;
|
||||
writer_ = fw;
|
||||
|
||||
SrsAudioCodecId acodec = has_audio_ ? SrsAudioCodecIdAAC : SrsAudioCodecIdForbidden;
|
||||
SrsVideoCodecId vcodec = has_video_ ? SrsVideoCodecIdAVC : SrsVideoCodecIdForbidden;
|
||||
|
|
@ -3312,8 +3364,8 @@ srs_error_t SrsTsTransmuxer::initialize(ISrsStreamWriter *fw)
|
|||
vcodec = SrsVideoCodecIdForbidden;
|
||||
}
|
||||
|
||||
srs_freep(tscw);
|
||||
tscw = new SrsTsContextWriter(fw, context, acodec, vcodec);
|
||||
srs_freep(tscw_);
|
||||
tscw_ = new SrsTsContextWriter(fw, context_, acodec, vcodec);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -3322,30 +3374,30 @@ srs_error_t SrsTsTransmuxer::write_audio(int64_t timestamp, char *data, int size
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = format->on_audio(timestamp, data, size)) != srs_success) {
|
||||
if ((err = format_->on_audio(timestamp, data, size)) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: format on audio");
|
||||
}
|
||||
|
||||
if (!format->acodec_) {
|
||||
if (!format_->acodec()) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// ts support audio codec: aac/mp3
|
||||
srs_assert(format->acodec_ && format->audio_);
|
||||
if (format->acodec_->id_ != SrsAudioCodecIdAAC && format->acodec_->id_ != SrsAudioCodecIdMP3) {
|
||||
srs_assert(format_->acodec() && format_->audio());
|
||||
if (format_->acodec()->id_ != SrsAudioCodecIdAAC && format_->acodec()->id_ != SrsAudioCodecIdMP3) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// for aac: ignore sequence header
|
||||
if (format->acodec_->id_ == SrsAudioCodecIdAAC && format->audio_->aac_packet_type_ == SrsAudioAacFrameTraitSequenceHeader) {
|
||||
if (format_->acodec()->id_ == SrsAudioCodecIdAAC && format_->audio()->aac_packet_type_ == SrsAudioAacFrameTraitSequenceHeader) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Switch audio codec if not AAC.
|
||||
if (tscw->acodec() != format->acodec_->id_) {
|
||||
srs_trace("TS: Switch audio codec %d(%s) to %d(%s)", tscw->acodec(), srs_audio_codec_id2str(tscw->acodec()).c_str(),
|
||||
format->acodec_->id_, srs_audio_codec_id2str(format->acodec_->id_).c_str());
|
||||
tscw->set_acodec(format->acodec_->id_);
|
||||
if (tscw_->acodec() != format_->acodec()->id_) {
|
||||
srs_trace("TS: Switch audio codec %d(%s) to %d(%s)", tscw_->acodec(), srs_audio_codec_id2str(tscw_->acodec()).c_str(),
|
||||
format_->acodec()->id_, srs_audio_codec_id2str(format_->acodec()->id_).c_str());
|
||||
tscw_->set_acodec(format_->acodec()->id_);
|
||||
}
|
||||
|
||||
// the dts calc from rtmp/flv header.
|
||||
|
|
@ -3354,7 +3406,7 @@ srs_error_t SrsTsTransmuxer::write_audio(int64_t timestamp, char *data, int size
|
|||
int64_t dts = timestamp * 90;
|
||||
|
||||
// write audio to cache.
|
||||
if ((err = tsmc->cache_audio(format->audio_, dts)) != srs_success) {
|
||||
if ((err = tsmc_->cache_audio(format_->audio(), dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: cache audio");
|
||||
}
|
||||
|
||||
|
|
@ -3369,39 +3421,39 @@ srs_error_t SrsTsTransmuxer::write_video(int64_t timestamp, char *data, int size
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = format->on_video(timestamp, data, size)) != srs_success) {
|
||||
if ((err = format_->on_video(timestamp, data, size)) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: on video");
|
||||
}
|
||||
|
||||
if (!format->vcodec_) {
|
||||
if (!format_->vcodec()) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// ignore info frame,
|
||||
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
|
||||
srs_assert(format->video_ && format->vcodec_);
|
||||
if (format->video_->frame_type_ == SrsVideoAvcFrameTypeVideoInfoFrame) {
|
||||
srs_assert(format_->video() && format_->vcodec());
|
||||
if (format_->video()->frame_type_ == SrsVideoAvcFrameTypeVideoInfoFrame) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bool codec_ok = (format->vcodec_->id_ == SrsVideoCodecIdAVC);
|
||||
codec_ok = codec_ok ? true : (format->vcodec_->id_ == SrsVideoCodecIdHEVC);
|
||||
bool codec_ok = (format_->vcodec()->id_ == SrsVideoCodecIdAVC);
|
||||
codec_ok = codec_ok ? true : (format_->vcodec()->id_ == SrsVideoCodecIdHEVC);
|
||||
if (!codec_ok) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// The video codec might change during streaming.
|
||||
tscw->set_vcodec(format->vcodec_->id_);
|
||||
tscw_->set_vcodec(format_->vcodec()->id_);
|
||||
|
||||
// ignore sequence header
|
||||
if (format->video_->frame_type_ == SrsVideoAvcFrameTypeKeyFrame && format->video_->avc_packet_type_ == SrsVideoAvcFrameTraitSequenceHeader) {
|
||||
if (format_->video()->frame_type_ == SrsVideoAvcFrameTypeKeyFrame && format_->video()->avc_packet_type_ == SrsVideoAvcFrameTraitSequenceHeader) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int64_t dts = timestamp * 90;
|
||||
|
||||
// write video to cache.
|
||||
if ((err = tsmc->cache_video(format->video_, dts)) != srs_success) {
|
||||
if ((err = tsmc_->cache_video(format_->video(), dts)) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: cache video");
|
||||
}
|
||||
|
||||
|
|
@ -3412,12 +3464,14 @@ srs_error_t SrsTsTransmuxer::flush_audio()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = tscw->write_audio(tsmc->audio_)) != srs_success) {
|
||||
if ((err = tscw_->write_audio(tsmc_->audio())) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: write audio");
|
||||
}
|
||||
|
||||
// write success, clear and free the ts message.
|
||||
srs_freep(tsmc->audio_);
|
||||
SrsTsMessage* audio_msg = tsmc_->audio();
|
||||
srs_freep(audio_msg);
|
||||
tsmc_->set_audio(NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -3426,12 +3480,14 @@ srs_error_t SrsTsTransmuxer::flush_video()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = tscw->write_video(tsmc->video_)) != srs_success) {
|
||||
if ((err = tscw_->write_video(tsmc_->video())) != srs_success) {
|
||||
return srs_error_wrap(err, "ts: write video");
|
||||
}
|
||||
|
||||
// write success, clear and free the ts message.
|
||||
srs_freep(tsmc->video_);
|
||||
SrsTsMessage* video_msg = tsmc_->video();
|
||||
srs_freep(video_msg);
|
||||
tsmc_->set_video(NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,19 @@
|
|||
|
||||
class SrsBuffer;
|
||||
class SrsTsMessageCache;
|
||||
class ISrsTsMessageCache;
|
||||
class SrsTsContextWriter;
|
||||
class ISrsTsContextWriter;
|
||||
class ISrsStreamWriter;
|
||||
class SrsFileReader;
|
||||
class SrsFormat;
|
||||
class ISrsFormat;
|
||||
class SrsSimpleStream;
|
||||
class SrsTsAdaptationField;
|
||||
class SrsTsPayload;
|
||||
class SrsTsMessage;
|
||||
class SrsTsPacket;
|
||||
class ISrsTsContext;
|
||||
class SrsTsContext;
|
||||
class SrsPsPacket;
|
||||
|
||||
|
|
@ -142,7 +146,7 @@ struct SrsTsChannel {
|
|||
SrsTsPidApply apply_;
|
||||
SrsTsStream stream_;
|
||||
SrsTsMessage *msg_;
|
||||
SrsTsContext *context_;
|
||||
ISrsTsContext *context_;
|
||||
// for encoder.
|
||||
uint8_t continuity_counter_;
|
||||
|
||||
|
|
@ -291,8 +295,48 @@ public:
|
|||
virtual srs_error_t on_ts_message(SrsTsMessage *msg) = 0;
|
||||
};
|
||||
|
||||
// The interface for ts context.
|
||||
class ISrsTsContext
|
||||
{
|
||||
public:
|
||||
ISrsTsContext();
|
||||
virtual ~ISrsTsContext();
|
||||
|
||||
public:
|
||||
// Whether the hls stream is pure audio stream.
|
||||
virtual bool is_pure_audio() = 0;
|
||||
// When PMT table parsed, we know some info about stream.
|
||||
virtual void on_pmt_parsed() = 0;
|
||||
// Reset the context for a new ts segment start.
|
||||
virtual void reset() = 0;
|
||||
|
||||
public:
|
||||
// Get the pid apply, the parsed pid.
|
||||
// @return the apply channel; NULL for invalid.
|
||||
virtual SrsTsChannel *get(int pid) = 0;
|
||||
// Set the pid apply, the parsed pid.
|
||||
virtual void set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream = SrsTsStreamReserved) = 0;
|
||||
|
||||
public:
|
||||
// Feed with ts packets, decode as ts message, callback handler if got one ts message.
|
||||
// A ts video message can be decoded to NALUs by SrsRawH264Stream::annexb_demux.
|
||||
// A ts audio message can be decoded to RAW frame by SrsRawAacStream::adts_demux.
|
||||
// @param handler The ts message handler to process the msg.
|
||||
// @remark We will consume all bytes in stream.
|
||||
virtual srs_error_t decode(SrsBuffer *stream, ISrsTsHandler *handler) = 0;
|
||||
|
||||
public:
|
||||
// Encode ts video/audio messages to the PES packets, as PES stream.
|
||||
// @param msg The video/audio msg to write to ts.
|
||||
// A ts video message is a frame with one or more NALUs, generally encoded by SrsTsMessageCache.cache_video.
|
||||
// A ts audio message is an audio packet, encoded by SrsTsMessageCache.cache_audio to ADTS for AAC.
|
||||
// @param vc The video codec, write the PAT/PMT table when changed.
|
||||
// @param ac The audio codec, write the PAT/PMT table when changed.
|
||||
virtual srs_error_t encode(ISrsStreamWriter *writer, SrsTsMessage *msg, SrsVideoCodecId vc, SrsAudioCodecId ac) = 0;
|
||||
};
|
||||
|
||||
// The context of ts, to decode the ts stream.
|
||||
class SrsTsContext
|
||||
class SrsTsContext : public ISrsTsContext
|
||||
{
|
||||
private:
|
||||
// Whether context is ready, failed if try to write data when not ready.
|
||||
|
|
@ -432,10 +476,10 @@ private:
|
|||
SrsTsPayload *payload_;
|
||||
|
||||
public:
|
||||
SrsTsContext *context_;
|
||||
ISrsTsContext *context_;
|
||||
|
||||
public:
|
||||
SrsTsPacket(SrsTsContext *c);
|
||||
SrsTsPacket(ISrsTsContext *c);
|
||||
virtual ~SrsTsPacket();
|
||||
|
||||
public:
|
||||
|
|
@ -447,12 +491,12 @@ public:
|
|||
virtual void padding(int nb_stuffings);
|
||||
|
||||
public:
|
||||
static SrsTsPacket *create_pat(SrsTsContext *context, int16_t pmt_number, int16_t pmt_pid);
|
||||
static SrsTsPacket *create_pmt(SrsTsContext *context, int16_t pmt_number, int16_t pmt_pid,
|
||||
static SrsTsPacket *create_pat(ISrsTsContext *context, int16_t pmt_number, int16_t pmt_pid);
|
||||
static SrsTsPacket *create_pmt(ISrsTsContext *context, int16_t pmt_number, int16_t pmt_pid,
|
||||
int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as);
|
||||
static SrsTsPacket *create_pes_first(SrsTsContext *context, int16_t pid, SrsTsPESStreamId sid,
|
||||
static SrsTsPacket *create_pes_first(ISrsTsContext *context, int16_t pid, SrsTsPESStreamId sid,
|
||||
uint8_t continuity_counter, bool discontinuity, int64_t pcr, int64_t dts, int64_t pts, int size);
|
||||
static SrsTsPacket *create_pes_continue(SrsTsContext *context,
|
||||
static SrsTsPacket *create_pes_continue(ISrsTsContext *context,
|
||||
int16_t pid, SrsTsPESStreamId sid, uint8_t continuity_counter);
|
||||
};
|
||||
|
||||
|
|
@ -1295,8 +1339,32 @@ protected:
|
|||
virtual srs_error_t psi_encode(SrsBuffer *stream);
|
||||
};
|
||||
|
||||
// Interface for writing TS messages to TS context.
|
||||
class ISrsTsContextWriter
|
||||
{
|
||||
public:
|
||||
ISrsTsContextWriter();
|
||||
virtual ~ISrsTsContextWriter();
|
||||
|
||||
public:
|
||||
// Write an audio frame to ts,
|
||||
virtual srs_error_t write_audio(SrsTsMessage *audio) = 0;
|
||||
// Write a video frame to ts,
|
||||
virtual srs_error_t write_video(SrsTsMessage *video) = 0;
|
||||
|
||||
public:
|
||||
// Get or update the video codec of ts muxer.
|
||||
virtual SrsVideoCodecId vcodec() = 0;
|
||||
virtual void set_vcodec(SrsVideoCodecId v) = 0;
|
||||
|
||||
public:
|
||||
// Get and set the audio codec.
|
||||
virtual SrsAudioCodecId acodec() = 0;
|
||||
virtual void set_acodec(SrsAudioCodecId v) = 0;
|
||||
};
|
||||
|
||||
// Write the TS message to TS context.
|
||||
class SrsTsContextWriter
|
||||
class SrsTsContextWriter : public ISrsTsContextWriter
|
||||
{
|
||||
private:
|
||||
// User must config the codec in right way.
|
||||
|
|
@ -1304,12 +1372,12 @@ private:
|
|||
SrsAudioCodecId acodec_;
|
||||
|
||||
private:
|
||||
SrsTsContext *context_;
|
||||
ISrsTsContext *context_;
|
||||
ISrsStreamWriter *writer_;
|
||||
std::string path_;
|
||||
|
||||
public:
|
||||
SrsTsContextWriter(ISrsStreamWriter *w, SrsTsContext *c, SrsAudioCodecId ac, SrsVideoCodecId vc);
|
||||
SrsTsContextWriter(ISrsStreamWriter *w, ISrsTsContext *c, SrsAudioCodecId ac, SrsVideoCodecId vc);
|
||||
virtual ~SrsTsContextWriter();
|
||||
|
||||
public:
|
||||
|
|
@ -1352,9 +1420,32 @@ private:
|
|||
int nb_buf;
|
||||
};
|
||||
|
||||
// Interface for TS messages cache.
|
||||
// TS messages cache, to group frames to TS message,
|
||||
// for example, we may write multiple AAC RAW frames to a TS message.
|
||||
class SrsTsMessageCache
|
||||
class ISrsTsMessageCache
|
||||
{
|
||||
public:
|
||||
ISrsTsMessageCache();
|
||||
virtual ~ISrsTsMessageCache();
|
||||
|
||||
public:
|
||||
// Write audio to cache
|
||||
virtual srs_error_t cache_audio(SrsParsedAudioPacket *frame, int64_t dts) = 0;
|
||||
// Write video to muxer.
|
||||
virtual srs_error_t cache_video(SrsParsedVideoPacket *frame, int64_t dts) = 0;
|
||||
|
||||
public:
|
||||
// Getters and setters for cached messages
|
||||
virtual SrsTsMessage* audio() = 0;
|
||||
virtual void set_audio(SrsTsMessage* msg) = 0;
|
||||
virtual SrsTsMessage* video() = 0;
|
||||
virtual void set_video(SrsTsMessage* msg) = 0;
|
||||
};
|
||||
|
||||
// TS messages cache, to group frames to TS message,
|
||||
// for example, we may write multiple AAC RAW frames to a TS message.
|
||||
class SrsTsMessageCache : public ISrsTsMessageCache
|
||||
{
|
||||
public:
|
||||
// The current ts message.
|
||||
|
|
@ -1371,6 +1462,13 @@ public:
|
|||
// Write video to muxer.
|
||||
virtual srs_error_t cache_video(SrsParsedVideoPacket *frame, int64_t dts);
|
||||
|
||||
public:
|
||||
// Getters and setters for cached messages
|
||||
virtual SrsTsMessage* audio();
|
||||
virtual void set_audio(SrsTsMessage* msg);
|
||||
virtual SrsTsMessage* video();
|
||||
virtual void set_video(SrsTsMessage* msg);
|
||||
|
||||
private:
|
||||
virtual srs_error_t do_cache_mp3(SrsParsedAudioPacket *frame);
|
||||
virtual srs_error_t do_cache_aac(SrsParsedAudioPacket *frame);
|
||||
|
|
@ -1378,20 +1476,38 @@ private:
|
|||
virtual srs_error_t do_cache_hevc(SrsParsedVideoPacket *frame);
|
||||
};
|
||||
|
||||
// The interface for ts transmuxer.
|
||||
class ISrsTsTransmuxer
|
||||
{
|
||||
public:
|
||||
ISrsTsTransmuxer();
|
||||
virtual ~ISrsTsTransmuxer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsStreamWriter *fw) = 0;
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size) = 0;
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size) = 0;
|
||||
|
||||
public:
|
||||
virtual void set_has_audio(bool v) = 0;
|
||||
virtual void set_has_video(bool v) = 0;
|
||||
virtual void set_guess_has_av(bool v) = 0;
|
||||
};
|
||||
|
||||
// Transmux the RTMP stream to HTTP-TS stream.
|
||||
class SrsTsTransmuxer
|
||||
class SrsTsTransmuxer : public ISrsTsTransmuxer
|
||||
{
|
||||
private:
|
||||
ISrsStreamWriter *writer;
|
||||
ISrsStreamWriter *writer_;
|
||||
bool has_audio_;
|
||||
bool has_video_;
|
||||
bool guess_has_av_;
|
||||
|
||||
private:
|
||||
SrsFormat *format;
|
||||
SrsTsMessageCache *tsmc;
|
||||
SrsTsContextWriter *tscw;
|
||||
SrsTsContext *context;
|
||||
ISrsFormat *format_;
|
||||
ISrsTsMessageCache *tsmc_;
|
||||
ISrsTsContextWriter *tscw_;
|
||||
ISrsTsContext *context_;
|
||||
|
||||
public:
|
||||
SrsTsTransmuxer();
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ private:
|
|||
// The underlayer st fd handler.
|
||||
srs_netfd_t stfd_;
|
||||
// The underlayer socket.
|
||||
SrsStSocket *skt_;
|
||||
ISrsProtocolReadWriter *skt_;
|
||||
|
||||
public:
|
||||
SrsTcpConnection(srs_netfd_t c);
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ ISrsHttpRequestWriter::~ISrsHttpRequestWriter()
|
|||
|
||||
ISrsHttpHandler::ISrsHttpHandler()
|
||||
{
|
||||
entry = NULL;
|
||||
entry_ = NULL;
|
||||
}
|
||||
|
||||
ISrsHttpHandler::~ISrsHttpHandler()
|
||||
|
|
@ -555,25 +555,25 @@ void SrsHttpFileServer::set_path(SrsPath *v)
|
|||
|
||||
srs_error_t SrsHttpFileServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
{
|
||||
srs_assert(entry);
|
||||
srs_assert(entry_);
|
||||
|
||||
// For each HTTP session, we use short-term HTTP connection.
|
||||
SrsHttpHeader *hdr = w->header();
|
||||
hdr->set("Connection", "Close");
|
||||
|
||||
string upath = r->path();
|
||||
string fullpath = srs_http_fs_fullpath(dir, entry->pattern, upath);
|
||||
string fullpath = srs_http_fs_fullpath(dir, entry_->pattern, upath);
|
||||
SrsPath path;
|
||||
string basename = path.filepath_base(upath);
|
||||
|
||||
// stat current dir, if exists, return error.
|
||||
if (!path_->exists(fullpath)) {
|
||||
srs_warn("http miss file=%s, pattern=%s, upath=%s",
|
||||
fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
|
||||
fullpath.c_str(), entry_->pattern.c_str(), upath.c_str());
|
||||
return SrsHttpNotFoundHandler().serve_http(w, r);
|
||||
}
|
||||
srs_trace("http match file=%s, pattern=%s, upath=%s",
|
||||
fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
|
||||
fullpath.c_str(), entry_->pattern.c_str(), upath.c_str());
|
||||
|
||||
// handle file according to its extension.
|
||||
// use vod stream for .flv/.fhv
|
||||
|
|
@ -879,7 +879,7 @@ srs_error_t SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler *handle
|
|||
entry->explicit_match = true;
|
||||
entry->handler = handler;
|
||||
entry->pattern = pattern;
|
||||
entry->handler->entry = entry;
|
||||
entry->handler->entry_ = entry;
|
||||
|
||||
if (static_matchers_.find(pattern) != static_matchers_.end()) {
|
||||
SrsHttpMuxEntry *exists = static_matchers_[pattern];
|
||||
|
|
@ -908,7 +908,7 @@ srs_error_t SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler *handle
|
|||
entry->explicit_match = false;
|
||||
entry->handler = new SrsHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_Found);
|
||||
entry->pattern = pattern;
|
||||
entry->handler->entry = entry;
|
||||
entry->handler->entry_ = entry;
|
||||
|
||||
static_matchers_[rpattern] = entry;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ public:
|
|||
class ISrsHttpHandler
|
||||
{
|
||||
public:
|
||||
SrsHttpMuxEntry *entry;
|
||||
SrsHttpMuxEntry *entry_;
|
||||
|
||||
public:
|
||||
ISrsHttpHandler();
|
||||
|
|
|
|||
|
|
@ -7,25 +7,25 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#include <srs_app_server.hpp>
|
||||
#include <algorithm>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_hooks.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
#include <srs_app_security.hpp>
|
||||
#include <srs_app_http_hooks.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_app_server.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_kernel_consts.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_kernel_st.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_protocol_rtmp_stack.hpp>
|
||||
#include <srs_protocol_st.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
#include <srs_utest_app9.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <algorithm>
|
||||
#include <sys/socket.h>
|
||||
#include <srs_protocol_st.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
|
||||
// Mock config implementation for SrsServer::listen() testing
|
||||
MockAppConfigForServerListen::MockAppConfigForServerListen()
|
||||
|
|
@ -265,14 +265,14 @@ VOID TEST(SrsServerTest, HttpHandleSuccess)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// Create mock HTTP API mux
|
||||
MockHttpServeMux* mock_mux = new MockHttpServeMux();
|
||||
MockHttpServeMux *mock_mux = new MockHttpServeMux();
|
||||
|
||||
// Create SrsServer instance
|
||||
SrsUniquePtr<SrsServer> server(new SrsServer());
|
||||
EXPECT_TRUE(server.get() != NULL);
|
||||
|
||||
// Inject mock HTTP API mux
|
||||
ISrsHttpServeMux* original_mux = server->http_api_mux_;
|
||||
ISrsHttpServeMux *original_mux = server->http_api_mux_;
|
||||
server->http_api_mux_ = mock_mux;
|
||||
|
||||
// Set reuse_api_over_server_ to false to test all handler registrations
|
||||
|
|
@ -307,11 +307,16 @@ VOID TEST(SrsServerTest, HttpHandleSuccess)
|
|||
bool has_rtc_play = false;
|
||||
|
||||
for (size_t i = 0; i < mock_mux->patterns_.size(); i++) {
|
||||
if (mock_mux->patterns_[i] == "/") has_root = true;
|
||||
if (mock_mux->patterns_[i] == "/api/") has_api = true;
|
||||
if (mock_mux->patterns_[i] == "/api/v1/summaries") has_summaries = true;
|
||||
if (mock_mux->patterns_[i] == "/metrics") has_metrics = true;
|
||||
if (mock_mux->patterns_[i] == "/rtc/v1/play/") has_rtc_play = true;
|
||||
if (mock_mux->patterns_[i] == "/")
|
||||
has_root = true;
|
||||
if (mock_mux->patterns_[i] == "/api/")
|
||||
has_api = true;
|
||||
if (mock_mux->patterns_[i] == "/api/v1/summaries")
|
||||
has_summaries = true;
|
||||
if (mock_mux->patterns_[i] == "/metrics")
|
||||
has_metrics = true;
|
||||
if (mock_mux->patterns_[i] == "/rtc/v1/play/")
|
||||
has_rtc_play = true;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(has_root);
|
||||
|
|
@ -370,13 +375,13 @@ VOID TEST(ServerTest, OnSignalHandling)
|
|||
EXPECT_TRUE(server.get() != NULL);
|
||||
|
||||
// Create and inject mock config
|
||||
MockAppConfigForSignal* mock_config = new MockAppConfigForSignal();
|
||||
ISrsAppConfig* original_config = server->config_;
|
||||
MockAppConfigForSignal *mock_config = new MockAppConfigForSignal();
|
||||
ISrsAppConfig *original_config = server->config_;
|
||||
server->config_ = mock_config;
|
||||
|
||||
// Create and inject mock log
|
||||
MockLogForSignal* mock_log = new MockLogForSignal();
|
||||
ISrsLog* original_log = server->log_;
|
||||
MockLogForSignal *mock_log = new MockLogForSignal();
|
||||
ISrsLog *original_log = server->log_;
|
||||
server->log_ = mock_log;
|
||||
|
||||
// Test 1: SRS_SIGNAL_RELOAD should set signal_reload_ flag
|
||||
|
|
@ -484,8 +489,8 @@ VOID TEST(ServerTest, Do2CycleReloadSuccess)
|
|||
EXPECT_TRUE(server.get() != NULL);
|
||||
|
||||
// Create and inject mock config
|
||||
MockAppConfigForDo2Cycle* mock_config = new MockAppConfigForDo2Cycle();
|
||||
ISrsAppConfig* original_config = server->config_;
|
||||
MockAppConfigForDo2Cycle *mock_config = new MockAppConfigForDo2Cycle();
|
||||
ISrsAppConfig *original_config = server->config_;
|
||||
server->config_ = mock_config;
|
||||
|
||||
// Test major use scenario: signal_reload_ triggers config reload with success
|
||||
|
|
@ -495,8 +500,8 @@ VOID TEST(ServerTest, Do2CycleReloadSuccess)
|
|||
server->signal_gracefully_quit_ = false;
|
||||
mock_config->reload_state_ = SrsReloadStateFinished;
|
||||
HELPER_EXPECT_SUCCESS(server->do2_cycle());
|
||||
EXPECT_FALSE(server->signal_reload_); // Flag should be cleared after processing
|
||||
EXPECT_EQ(1, mock_config->reload_count_); // Config reload should be called once
|
||||
EXPECT_FALSE(server->signal_reload_); // Flag should be cleared after processing
|
||||
EXPECT_EQ(1, mock_config->reload_count_); // Config reload should be called once
|
||||
|
||||
// Cleanup: restore original config
|
||||
server->config_ = original_config;
|
||||
|
|
@ -595,13 +600,13 @@ VOID TEST(ServerTest, SetupTicksWithStatsAndHeartbeat)
|
|||
EXPECT_TRUE(server.get() != NULL);
|
||||
|
||||
// Create and inject mock config
|
||||
MockAppConfigForSetupTicks* mock_config = new MockAppConfigForSetupTicks();
|
||||
ISrsAppConfig* original_config = server->config_;
|
||||
MockAppConfigForSetupTicks *mock_config = new MockAppConfigForSetupTicks();
|
||||
ISrsAppConfig *original_config = server->config_;
|
||||
server->config_ = mock_config;
|
||||
|
||||
// Create and inject mock app factory
|
||||
MockAppFactoryForSetupTicks* mock_factory = new MockAppFactoryForSetupTicks();
|
||||
SrsAppFactory* original_factory = server->app_factory_;
|
||||
MockAppFactoryForSetupTicks *mock_factory = new MockAppFactoryForSetupTicks();
|
||||
SrsAppFactory *original_factory = server->app_factory_;
|
||||
server->app_factory_ = mock_factory;
|
||||
|
||||
// Test major use scenario: setup_ticks with stats and heartbeat enabled
|
||||
|
|
@ -783,12 +788,12 @@ VOID TEST(SrsServerTest, NotifyEventDispatch)
|
|||
SrsUniquePtr<SrsServer> server(new SrsServer());
|
||||
|
||||
// Create mock objects
|
||||
MockRtcSessionManagerForNotify* mock_rtc_manager = new MockRtcSessionManagerForNotify();
|
||||
MockHttpHeartbeatForNotify* mock_heartbeat = new MockHttpHeartbeatForNotify();
|
||||
MockRtcSessionManagerForNotify *mock_rtc_manager = new MockRtcSessionManagerForNotify();
|
||||
MockHttpHeartbeatForNotify *mock_heartbeat = new MockHttpHeartbeatForNotify();
|
||||
|
||||
// Save original pointers
|
||||
SrsRtcSessionManager* original_rtc_manager = server->rtc_session_manager_;
|
||||
SrsHttpHeartbeat* original_heartbeat = server->http_heartbeat_;
|
||||
SrsRtcSessionManager *original_rtc_manager = server->rtc_session_manager_;
|
||||
SrsHttpHeartbeat *original_heartbeat = server->http_heartbeat_;
|
||||
|
||||
// Inject mock objects (no cast needed since they inherit from the base classes)
|
||||
server->rtc_session_manager_ = mock_rtc_manager;
|
||||
|
|
@ -1234,7 +1239,7 @@ int64_t MockRtmpTransportForDoCycle::get_send_bytes()
|
|||
VOID TEST(SrsRtmpConnTest, ConstructorAndAssemble)
|
||||
{
|
||||
// Create a dummy file descriptor for transport
|
||||
srs_netfd_t dummy_fd = (srs_netfd_t)((void*)0x1234);
|
||||
srs_netfd_t dummy_fd = (srs_netfd_t)((void *)0x1234);
|
||||
SrsRtmpTransport *transport = new SrsRtmpTransport(dummy_fd);
|
||||
// Prevent destructor from closing dummy fd
|
||||
transport->skt_->stfd_ = NULL;
|
||||
|
|
@ -1344,7 +1349,7 @@ VOID TEST(SrsRtmpTransportTest, BasicOperations)
|
|||
|
||||
// Create a dummy file descriptor (cast from int for testing)
|
||||
// Note: We won't actually use this for I/O, just testing the wrapper methods
|
||||
srs_netfd_t dummy_fd = (srs_netfd_t)((void*)0x1234);
|
||||
srs_netfd_t dummy_fd = (srs_netfd_t)((void *)0x1234);
|
||||
|
||||
// Create SrsRtmpTransport instance
|
||||
SrsUniquePtr<SrsRtmpTransport> transport(new SrsRtmpTransport(dummy_fd));
|
||||
|
|
@ -1548,7 +1553,7 @@ srs_error_t MockRtmpServerForHandlePublishMessage::decode_message(SrsRtmpCommonM
|
|||
}
|
||||
// Return the configured packet (can be NULL or a specific packet type)
|
||||
*ppacket = decode_message_packet_;
|
||||
decode_message_packet_ = NULL; // Transfer ownership
|
||||
decode_message_packet_ = NULL; // Transfer ownership
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
|
|
@ -1731,7 +1736,7 @@ VOID TEST(SrsUtilityTest, GetCpuInfo)
|
|||
VOID TEST(SrsUtilityTest, UpdateDiskStat)
|
||||
{
|
||||
// Get the initial disk stat to save the original state
|
||||
SrsDiskStat* original_stat = srs_get_disk_stat();
|
||||
SrsDiskStat *original_stat = srs_get_disk_stat();
|
||||
SrsDiskStat saved_stat = *original_stat;
|
||||
|
||||
// Test case 1: First call to srs_update_disk_stat() - should initialize the stat
|
||||
|
|
@ -1740,11 +1745,9 @@ VOID TEST(SrsUtilityTest, UpdateDiskStat)
|
|||
if (true) {
|
||||
srs_update_disk_stat();
|
||||
|
||||
SrsDiskStat* stat = srs_get_disk_stat();
|
||||
SrsDiskStat *stat = srs_get_disk_stat();
|
||||
EXPECT_TRUE(stat->ok_);
|
||||
EXPECT_TRUE(stat->sample_time_ > 0);
|
||||
// After first call, KBps values should be 0 (no delta to calculate)
|
||||
EXPECT_EQ(0, stat->in_KBps_);
|
||||
// busy_ should be 0 (no delta to calculate)
|
||||
EXPECT_EQ(0.0f, stat->busy_);
|
||||
}
|
||||
|
|
@ -1764,7 +1767,7 @@ VOID TEST(SrsUtilityTest, UpdateDiskStat)
|
|||
// Call srs_update_disk_stat() again to calculate deltas
|
||||
srs_update_disk_stat();
|
||||
|
||||
SrsDiskStat* stat = srs_get_disk_stat();
|
||||
SrsDiskStat *stat = srs_get_disk_stat();
|
||||
EXPECT_TRUE(stat->ok_);
|
||||
EXPECT_TRUE(stat->sample_time_ > first_sample.sample_time_);
|
||||
|
||||
|
|
@ -1780,21 +1783,21 @@ VOID TEST(SrsUtilityTest, UpdateDiskStat)
|
|||
// busy_ = ticks / delta_ms, where delta_ms = cpu_.total_delta_ * 10 / nb_processors_
|
||||
// Note: busy_ may still be 0 if no disk I/O occurred or if conditions not met
|
||||
EXPECT_TRUE(stat->busy_ >= 0.0f);
|
||||
EXPECT_TRUE(stat->busy_ <= 1.0f); // busy_ should be in [0, 1] range
|
||||
EXPECT_TRUE(stat->busy_ <= 1.0f); // busy_ should be in [0, 1] range
|
||||
}
|
||||
|
||||
// Test case 3: Verify the calculation formulas with known values
|
||||
// This tests the specific calculation logic for vmstat and diskstats
|
||||
if (true) {
|
||||
// Get current stat
|
||||
SrsDiskStat* current = srs_get_disk_stat();
|
||||
SrsDiskStat *current = srs_get_disk_stat();
|
||||
|
||||
// Manually create a previous stat with known values to test calculation
|
||||
SrsDiskStat prev = *current;
|
||||
prev.sample_time_ = current->sample_time_ - 1000; // 1 second ago
|
||||
prev.pgpgin_ = 1000; // 1000 KB read
|
||||
prev.pgpgout_ = 2000; // 2000 KB written
|
||||
prev.ticks_ = 100; // 100 ticks
|
||||
prev.sample_time_ = current->sample_time_ - 1000; // 1 second ago
|
||||
prev.pgpgin_ = 1000; // 1000 KB read
|
||||
prev.pgpgout_ = 2000; // 2000 KB written
|
||||
prev.ticks_ = 100; // 100 ticks
|
||||
prev.cpu_.ok_ = true;
|
||||
prev.cpu_.user_ = 1000;
|
||||
prev.cpu_.sys_ = 500;
|
||||
|
|
@ -1805,8 +1808,8 @@ VOID TEST(SrsUtilityTest, UpdateDiskStat)
|
|||
SrsDiskStat next = *current;
|
||||
next.sample_time_ = current->sample_time_;
|
||||
next.pgpgin_ = 2000; // 1000 KB more read
|
||||
next.pgpgout_ = 4000; // 2000 KB more written
|
||||
next.ticks_ = 200; // 100 ticks more
|
||||
next.pgpgout_ = 4000; // 2000 KB more written
|
||||
next.ticks_ = 200; // 100 ticks more
|
||||
next.cpu_.ok_ = true;
|
||||
next.cpu_.user_ = 1100;
|
||||
next.cpu_.sys_ = 600;
|
||||
|
|
@ -1829,7 +1832,7 @@ VOID TEST(SrsUtilityTest, UpdateDiskStat)
|
|||
|
||||
// Verify diskstats busy calculation formula
|
||||
if (next.cpu_.ok_ && prev.cpu_.ok_ && next.cpu_.total_delta_ > 0) {
|
||||
SrsCpuInfo* cpuinfo = srs_get_cpuinfo();
|
||||
SrsCpuInfo *cpuinfo = srs_get_cpuinfo();
|
||||
if (cpuinfo->ok_ && cpuinfo->nb_processors_ > 0 && prev.ticks_ < next.ticks_) {
|
||||
// delta_ms = cpu_.total_delta_ * 10 / nb_processors_
|
||||
double delta_ms = next.cpu_.total_delta_ * 10 / cpuinfo->nb_processors_;
|
||||
|
|
@ -2278,7 +2281,7 @@ VOID TEST(SrsRtmpConnTest, AcquirePublishStreamBusyCheck)
|
|||
// Create mock live source that does NOT allow publishing (stream is busy)
|
||||
SrsSharedPtr<SrsLiveSource> source(new MockLiveSource());
|
||||
MockLiveSource *mock_source = dynamic_cast<MockLiveSource *>(source.get());
|
||||
mock_source->set_can_publish(false); // Stream is busy
|
||||
mock_source->set_can_publish(false); // Stream is busy
|
||||
|
||||
// Call acquire_publish - should fail with ERROR_SYSTEM_STREAM_BUSY
|
||||
err = conn->acquire_publish(source);
|
||||
|
|
@ -2287,7 +2290,7 @@ VOID TEST(SrsRtmpConnTest, AcquirePublishStreamBusyCheck)
|
|||
srs_freep(err);
|
||||
|
||||
// Note: conn owns mock_rtmp and mock_security, they will be deleted by conn destructor
|
||||
} // conn is destroyed here
|
||||
} // conn is destroyed here
|
||||
|
||||
// Now safe to delete mock_config
|
||||
srs_freep(mock_config);
|
||||
|
|
@ -2347,7 +2350,7 @@ VOID TEST(SrsRtmpConnTest, HandlePublishMessageVideoSuccess)
|
|||
EXPECT_EQ(0, mock_rtmp->decode_message_count_);
|
||||
|
||||
// Note: conn owns mock_rtmp, it will be deleted by conn destructor
|
||||
} // conn is destroyed here
|
||||
} // conn is destroyed here
|
||||
|
||||
// Now safe to delete mock_config
|
||||
srs_freep(mock_config);
|
||||
|
|
@ -2682,7 +2685,7 @@ VOID TEST(SrsRtmpConnTest, HttpHooksOnConnect)
|
|||
|
||||
// Restore original hooks
|
||||
conn->hooks_ = original_hooks;
|
||||
} // conn is destroyed here
|
||||
} // conn is destroyed here
|
||||
|
||||
// Now safe to delete mock objects
|
||||
srs_freep(mock_hooks);
|
||||
|
|
@ -2757,7 +2760,7 @@ VOID TEST(SrsRtmpConnTest, ProcessPlayControlMsgPauseSuccess)
|
|||
EXPECT_EQ(true, consumer->last_pause_state_);
|
||||
|
||||
// Note: conn owns mock_rtmp, it will be deleted by conn destructor
|
||||
} // conn is destroyed here
|
||||
} // conn is destroyed here
|
||||
|
||||
// Now safe to delete mock_config
|
||||
srs_freep(mock_config);
|
||||
|
|
@ -2811,8 +2814,8 @@ VOID TEST(SrsRtmpConnTest, HttpHooksOnClose)
|
|||
// Verify the first call
|
||||
EXPECT_STREQ("http://127.0.0.1:8085/api/v1/close", mock_hooks->on_close_calls_[0].url_.c_str());
|
||||
EXPECT_TRUE(mock_hooks->on_close_calls_[0].req_ == conn->info_->req_);
|
||||
EXPECT_EQ(0, mock_hooks->on_close_calls_[0].send_bytes_); // Mock transport returns 0
|
||||
EXPECT_EQ(0, mock_hooks->on_close_calls_[0].recv_bytes_); // Mock transport returns 0
|
||||
EXPECT_EQ(0, mock_hooks->on_close_calls_[0].send_bytes_); // Mock transport returns 0
|
||||
EXPECT_EQ(0, mock_hooks->on_close_calls_[0].recv_bytes_); // Mock transport returns 0
|
||||
|
||||
// Verify the second call
|
||||
EXPECT_STREQ("http://localhost:8085/api/v1/close", mock_hooks->on_close_calls_[1].url_.c_str());
|
||||
|
|
@ -2894,7 +2897,7 @@ srs_error_t MockHttpHooksForOnPublish::on_dvr(SrsContextId cid, std::string url,
|
|||
}
|
||||
|
||||
srs_error_t MockHttpHooksForOnPublish::on_hls(SrsContextId cid, std::string url, ISrsRequest *req, std::string file, std::string ts_url,
|
||||
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration)
|
||||
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
|
@ -3210,7 +3213,7 @@ srs_error_t MockHttpHooksForOnPlay::on_dvr(SrsContextId cid, std::string url, IS
|
|||
}
|
||||
|
||||
srs_error_t MockHttpHooksForOnPlay::on_hls(SrsContextId cid, std::string url, ISrsRequest *req, std::string file, std::string ts_url,
|
||||
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration)
|
||||
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
|
@ -3326,9 +3329,6 @@ VOID TEST(UtilityTest, GetProcSelfStatSuccess)
|
|||
EXPECT_TRUE(stat.state_ == 'R' || stat.state_ == 'S' || stat.state_ == 'D' ||
|
||||
stat.state_ == 'Z' || stat.state_ == 'T' || stat.state_ == 'W');
|
||||
|
||||
// ppid should be positive (parent process ID)
|
||||
EXPECT_TRUE(stat.ppid_ > 0);
|
||||
|
||||
// num_threads should be at least 1 (current thread)
|
||||
EXPECT_TRUE(stat.num_threads_ >= 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,15 @@
|
|||
#include <srs_utest_app10.hpp>
|
||||
*/
|
||||
#include <srs_utest.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
#include <srs_protocol_http_stack.hpp>
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_rtc_server.hpp>
|
||||
#include <srs_app_heartbeat.hpp>
|
||||
#include <srs_app_rtc_server.hpp>
|
||||
#include <srs_app_rtmp_conn.hpp>
|
||||
#include <srs_app_security.hpp>
|
||||
#include <srs_kernel_hourglass.hpp>
|
||||
#include <srs_protocol_http_stack.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
|
||||
// Mock config for testing SrsServer::listen()
|
||||
class MockAppConfigForServerListen : public MockAppConfig
|
||||
|
|
@ -416,7 +417,7 @@ class MockRtmpServerForHandlePublishMessage : public ISrsRtmpServer
|
|||
{
|
||||
public:
|
||||
srs_error_t decode_message_error_;
|
||||
SrsRtmpCommand* decode_message_packet_;
|
||||
SrsRtmpCommand *decode_message_packet_;
|
||||
int decode_message_count_;
|
||||
srs_error_t fmle_unpublish_error_;
|
||||
int fmle_unpublish_count_;
|
||||
|
|
@ -461,7 +462,7 @@ public:
|
|||
class MockRtmpServerForPlayControl : public ISrsRtmpServer
|
||||
{
|
||||
public:
|
||||
SrsRtmpCommand* decode_message_packet_;
|
||||
SrsRtmpCommand *decode_message_packet_;
|
||||
int decode_message_count_;
|
||||
int send_and_free_packet_count_;
|
||||
int on_play_client_pause_count_;
|
||||
|
|
|
|||
2054
trunk/src/utest/srs_utest_app11.cpp
Normal file
2054
trunk/src/utest/srs_utest_app11.cpp
Normal file
File diff suppressed because it is too large
Load Diff
352
trunk/src/utest/srs_utest_app11.hpp
Normal file
352
trunk/src/utest/srs_utest_app11.hpp
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
//
|
||||
// Copyright (c) 2013-2025 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_UTEST_APP11_HPP
|
||||
#define SRS_UTEST_APP11_HPP
|
||||
|
||||
/*
|
||||
#include <srs_utest_app11.hpp>
|
||||
*/
|
||||
#include <srs_utest.hpp>
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_http_hooks.hpp>
|
||||
#include <srs_app_http_stream.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
#include <srs_protocol_http_conn.hpp>
|
||||
#include <srs_protocol_rtmp_stack.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
|
||||
// Mock request class for testing SrsBufferCache
|
||||
class MockBufferCacheRequest : public ISrsRequest
|
||||
{
|
||||
public:
|
||||
MockBufferCacheRequest(std::string vhost = "__defaultVhost__", std::string app = "live", std::string stream = "test");
|
||||
virtual ~MockBufferCacheRequest();
|
||||
virtual ISrsRequest *copy();
|
||||
virtual std::string get_stream_url();
|
||||
virtual void update_auth(ISrsRequest *req);
|
||||
virtual void strip();
|
||||
virtual ISrsRequest *as_http();
|
||||
};
|
||||
|
||||
// Mock buffer cache for testing AAC stream encoder
|
||||
class MockBufferCacheForAac : public ISrsBufferCache
|
||||
{
|
||||
public:
|
||||
int dump_cache_count_;
|
||||
ISrsLiveConsumer *last_consumer_;
|
||||
SrsRtmpJitterAlgorithm last_jitter_;
|
||||
|
||||
public:
|
||||
MockBufferCacheForAac();
|
||||
virtual ~MockBufferCacheForAac();
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
virtual bool alive();
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t update_auth(ISrsRequest *r);
|
||||
};
|
||||
|
||||
// Mock SrsHttpxConn for testing SrsLiveStream (old version for backward compatibility)
|
||||
class MockHttpxConn : public ISrsHttpConnOwner
|
||||
{
|
||||
public:
|
||||
bool enable_stat_;
|
||||
|
||||
public:
|
||||
MockHttpxConn();
|
||||
virtual ~MockHttpxConn();
|
||||
|
||||
public:
|
||||
virtual void set_enable_stat(bool v);
|
||||
virtual srs_error_t on_start();
|
||||
virtual srs_error_t on_http_message(ISrsHttpMessage *r, SrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_message_done(ISrsHttpMessage *r, SrsHttpResponseWriter *w);
|
||||
virtual srs_error_t on_conn_done(srs_error_t r0);
|
||||
};
|
||||
|
||||
// Mock SrsHttpConn for testing SrsLiveStream (old version for backward compatibility)
|
||||
class MockHttpConn : public ISrsConnection, public ISrsExpire
|
||||
{
|
||||
public:
|
||||
MockHttpxConn *handler_;
|
||||
std::string remote_ip_;
|
||||
|
||||
public:
|
||||
MockHttpConn();
|
||||
virtual ~MockHttpConn();
|
||||
|
||||
public:
|
||||
virtual std::string remote_ip();
|
||||
virtual const SrsContextId &get_id();
|
||||
virtual std::string desc();
|
||||
virtual void expire();
|
||||
virtual ISrsHttpConnOwner *handler();
|
||||
};
|
||||
|
||||
// Mock SrsHttpMessage for testing SrsLiveStream (old version for backward compatibility)
|
||||
class MockHttpMessage : public SrsHttpMessage
|
||||
{
|
||||
public:
|
||||
MockHttpConn *mock_conn_;
|
||||
|
||||
public:
|
||||
MockHttpMessage();
|
||||
virtual ~MockHttpMessage();
|
||||
|
||||
public:
|
||||
virtual std::string path();
|
||||
};
|
||||
|
||||
// Mock SrsHttpxConn for testing SrsLiveStream - inherits from real SrsHttpxConn
|
||||
class MockHttpxConnForLiveStream : public SrsHttpxConn
|
||||
{
|
||||
public:
|
||||
bool enable_stat_called_;
|
||||
|
||||
public:
|
||||
MockHttpxConnForLiveStream();
|
||||
virtual ~MockHttpxConnForLiveStream();
|
||||
|
||||
public:
|
||||
void set_enable_stat(bool v);
|
||||
};
|
||||
|
||||
// Mock SrsHttpConn for testing SrsLiveStream - inherits from real SrsHttpConn
|
||||
class MockHttpConnForLiveStream : public SrsHttpConn
|
||||
{
|
||||
public:
|
||||
MockHttpxConnForLiveStream *mock_handler_;
|
||||
|
||||
public:
|
||||
MockHttpConnForLiveStream();
|
||||
virtual ~MockHttpConnForLiveStream();
|
||||
|
||||
public:
|
||||
virtual ISrsHttpConnOwner *handler();
|
||||
};
|
||||
|
||||
// Mock SrsHttpMessage for testing SrsLiveStream
|
||||
class MockHttpMessageForLiveStream : public SrsHttpMessage
|
||||
{
|
||||
public:
|
||||
MockHttpConnForLiveStream *mock_conn_;
|
||||
|
||||
public:
|
||||
MockHttpMessageForLiveStream();
|
||||
virtual ~MockHttpMessageForLiveStream();
|
||||
|
||||
public:
|
||||
virtual ISrsConnection *connection();
|
||||
virtual std::string path();
|
||||
};
|
||||
|
||||
// Mock ISrsAppConfig for testing SrsLiveStream::http_hooks_on_play() and http_hooks_on_stop()
|
||||
class MockAppConfigForLiveStreamHooks : public MockAppConfig
|
||||
{
|
||||
public:
|
||||
bool http_hooks_enabled_;
|
||||
SrsConfDirective *on_play_directive_;
|
||||
SrsConfDirective *on_stop_directive_;
|
||||
|
||||
public:
|
||||
MockAppConfigForLiveStreamHooks();
|
||||
virtual ~MockAppConfigForLiveStreamHooks();
|
||||
|
||||
public:
|
||||
virtual bool get_vhost_http_hooks_enabled(std::string vhost);
|
||||
virtual SrsConfDirective *get_vhost_on_play(std::string vhost);
|
||||
virtual SrsConfDirective *get_vhost_on_stop(std::string vhost);
|
||||
};
|
||||
|
||||
// Mock ISrsHttpHooks for testing SrsLiveStream::http_hooks_on_play() and http_hooks_on_stop()
|
||||
class MockHttpHooksForLiveStream : public ISrsHttpHooks
|
||||
{
|
||||
public:
|
||||
std::vector<std::pair<std::string, ISrsRequest *> > on_play_calls_;
|
||||
int on_play_count_;
|
||||
srs_error_t on_play_error_;
|
||||
std::vector<std::pair<std::string, ISrsRequest *> > on_stop_calls_;
|
||||
int on_stop_count_;
|
||||
|
||||
public:
|
||||
MockHttpHooksForLiveStream();
|
||||
virtual ~MockHttpHooksForLiveStream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_connect(std::string url, ISrsRequest *req);
|
||||
virtual void on_close(std::string url, ISrsRequest *req, int64_t send_bytes, int64_t recv_bytes);
|
||||
virtual srs_error_t on_publish(std::string url, ISrsRequest *req);
|
||||
virtual void on_unpublish(std::string url, ISrsRequest *req);
|
||||
virtual srs_error_t on_play(std::string url, ISrsRequest *req);
|
||||
virtual void on_stop(std::string url, ISrsRequest *req);
|
||||
virtual srs_error_t on_dvr(SrsContextId cid, std::string url, ISrsRequest *req, std::string file);
|
||||
virtual srs_error_t on_hls(SrsContextId cid, std::string url, ISrsRequest *req, std::string file, std::string ts_url,
|
||||
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration);
|
||||
virtual srs_error_t on_hls_notify(SrsContextId cid, std::string url, ISrsRequest *req, std::string ts_url, int nb_notify);
|
||||
virtual srs_error_t discover_co_workers(std::string url, std::string &host, int &port);
|
||||
virtual srs_error_t on_forward_backend(std::string url, ISrsRequest *req, std::vector<std::string> &rtmp_urls);
|
||||
void reset();
|
||||
};
|
||||
|
||||
// Mock ISrsAsyncCallWorker for testing SrsHttpStreamServer
|
||||
class MockAsyncCallWorker : public ISrsAsyncCallWorker
|
||||
{
|
||||
public:
|
||||
int execute_count_;
|
||||
std::vector<ISrsAsyncCallTask *> tasks_;
|
||||
|
||||
public:
|
||||
MockAsyncCallWorker();
|
||||
virtual ~MockAsyncCallWorker();
|
||||
|
||||
public:
|
||||
virtual srs_error_t execute(ISrsAsyncCallTask *t);
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
};
|
||||
|
||||
// Mock ISrsLiveStream for testing SrsHttpStreamDestroy
|
||||
class MockLiveStreamForDestroy : public ISrsLiveStream
|
||||
{
|
||||
public:
|
||||
bool alive_;
|
||||
bool expired_;
|
||||
|
||||
public:
|
||||
MockLiveStreamForDestroy();
|
||||
virtual ~MockLiveStreamForDestroy();
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
virtual srs_error_t update_auth(ISrsRequest *r);
|
||||
virtual bool alive();
|
||||
virtual void expire();
|
||||
};
|
||||
|
||||
// Mock ISrsStatistic for testing SrsLiveStream::serve_http_impl
|
||||
class MockStatisticForLiveStream : public ISrsStatistic
|
||||
{
|
||||
public:
|
||||
int on_client_count_;
|
||||
srs_error_t on_client_error_;
|
||||
|
||||
public:
|
||||
MockStatisticForLiveStream();
|
||||
virtual ~MockStatisticForLiveStream();
|
||||
|
||||
public:
|
||||
virtual void on_disconnect(std::string id, srs_error_t err);
|
||||
virtual srs_error_t on_client(std::string id, ISrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type);
|
||||
virtual srs_error_t on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height);
|
||||
virtual srs_error_t on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, SrsAudioChannels asound_type, SrsAacObjectType aac_object);
|
||||
virtual void on_stream_publish(ISrsRequest *req, std::string publisher_id);
|
||||
virtual void on_stream_close(ISrsRequest *req);
|
||||
virtual void kbps_add_delta(std::string id, ISrsKbpsDelta *delta);
|
||||
virtual void kbps_sample();
|
||||
virtual srs_error_t on_video_frames(ISrsRequest *req, int nb_frames);
|
||||
};
|
||||
|
||||
// Mock ISrsSecurity for testing SrsLiveStream::serve_http_impl
|
||||
class MockSecurityForLiveStream : public ISrsSecurity
|
||||
{
|
||||
public:
|
||||
srs_error_t check_error_;
|
||||
int check_count_;
|
||||
|
||||
public:
|
||||
MockSecurityForLiveStream();
|
||||
virtual ~MockSecurityForLiveStream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t check(SrsRtmpConnType type, std::string ip, ISrsRequest *req);
|
||||
};
|
||||
|
||||
// Mock ISrsBufferCache for testing SrsHttpStreamDestroy
|
||||
class MockBufferCacheForDestroy : public ISrsBufferCache
|
||||
{
|
||||
public:
|
||||
bool alive_;
|
||||
bool stopped_;
|
||||
|
||||
public:
|
||||
MockBufferCacheForDestroy();
|
||||
virtual ~MockBufferCacheForDestroy();
|
||||
|
||||
public:
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
virtual bool alive();
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
virtual srs_error_t update_auth(ISrsRequest *r);
|
||||
};
|
||||
|
||||
// Mock ISrsBufferEncoder for testing SrsLiveStream::streaming_send_messages
|
||||
class MockBufferEncoderForStreamingSend : public ISrsBufferEncoder
|
||||
{
|
||||
public:
|
||||
int write_audio_count_;
|
||||
int write_video_count_;
|
||||
int write_metadata_count_;
|
||||
std::vector<int64_t> audio_timestamps_;
|
||||
std::vector<int64_t> video_timestamps_;
|
||||
std::vector<int64_t> metadata_timestamps_;
|
||||
srs_error_t write_error_;
|
||||
|
||||
public:
|
||||
MockBufferEncoderForStreamingSend();
|
||||
virtual ~MockBufferEncoderForStreamingSend();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsFileWriter *w, ISrsBufferCache *c);
|
||||
virtual srs_error_t write_audio(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_video(int64_t timestamp, char *data, int size);
|
||||
virtual srs_error_t write_metadata(int64_t timestamp, char *data, int size);
|
||||
virtual bool has_cache();
|
||||
virtual srs_error_t dump_cache(ISrsLiveConsumer *consumer, SrsRtmpJitterAlgorithm jitter);
|
||||
void reset();
|
||||
};
|
||||
|
||||
// Mock ISrsAppConfig for testing SrsHttpStreamServer
|
||||
class MockAppConfigForHttpStreamServer : public MockAppConfig
|
||||
{
|
||||
public:
|
||||
bool http_remux_enabled_;
|
||||
std::string http_remux_mount_;
|
||||
SrsConfDirective *vhost_directive_;
|
||||
|
||||
public:
|
||||
MockAppConfigForHttpStreamServer();
|
||||
virtual ~MockAppConfigForHttpStreamServer();
|
||||
|
||||
public:
|
||||
virtual bool get_vhost_http_remux_enabled(std::string vhost);
|
||||
virtual std::string get_vhost_http_remux_mount(std::string vhost);
|
||||
virtual SrsConfDirective *get_vhost(std::string vhost, bool try_default_vhost = true);
|
||||
virtual bool get_vhost_enabled(SrsConfDirective *conf);
|
||||
};
|
||||
|
||||
// Mock SrsHttpMessage for testing SrsHttpStreamServer::dynamic_match
|
||||
class MockHttpMessageForDynamicMatch : public SrsHttpMessage
|
||||
{
|
||||
public:
|
||||
std::string path_;
|
||||
std::string ext_;
|
||||
std::string host_;
|
||||
MockHttpConn *mock_conn_;
|
||||
|
||||
public:
|
||||
MockHttpMessageForDynamicMatch();
|
||||
virtual ~MockHttpMessageForDynamicMatch();
|
||||
|
||||
public:
|
||||
virtual std::string path();
|
||||
virtual std::string ext();
|
||||
virtual std::string host();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -383,6 +383,16 @@ public:
|
|||
virtual bool get_atc_auto(std::string vhost);
|
||||
virtual bool get_reduce_sequence_header(std::string vhost);
|
||||
virtual bool get_parse_sps(std::string vhost);
|
||||
virtual SrsConfDirective *get_root() { return NULL; }
|
||||
virtual bool get_vhost_enabled(SrsConfDirective *conf) { return true; }
|
||||
virtual bool get_vhost_http_remux_enabled(std::string vhost) { return false; }
|
||||
virtual bool get_vhost_http_remux_enabled(SrsConfDirective *vhost) { return false; }
|
||||
virtual srs_utime_t get_vhost_http_remux_fast_cache(std::string vhost) { return 0; }
|
||||
virtual bool get_vhost_http_remux_drop_if_not_match(std::string vhost) { return false; }
|
||||
virtual bool get_vhost_http_remux_has_audio(std::string vhost) { return true; }
|
||||
virtual bool get_vhost_http_remux_has_video(std::string vhost) { return true; }
|
||||
virtual bool get_vhost_http_remux_guess_has_av(std::string vhost) { return true; }
|
||||
virtual std::string get_vhost_http_remux_mount(std::string vhost) { return ""; }
|
||||
void set_http_hooks_enabled(bool enabled);
|
||||
void set_on_stop_urls(const std::vector<std::string> &urls);
|
||||
void clear_on_stop_directive();
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ void MockLiveSourceForQueue::update_auth(ISrsRequest *r)
|
|||
// Mock update_auth - do nothing to avoid accessing null req_
|
||||
}
|
||||
|
||||
srs_error_t MockLiveSourceForQueue::consumer_dumps(ISrsLiveConsumer *consumer, bool ds, bool dm, bool dg)
|
||||
{
|
||||
// Mock consumer_dumps - just return success without doing anything
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
MockLiveConsumerForQueue::MockLiveConsumerForQueue(MockLiveSourceForQueue *source)
|
||||
: SrsLiveConsumer(source)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
virtual void on_consumer_destroy(SrsLiveConsumer *consumer);
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> wrapper, ISrsRequest *r);
|
||||
virtual void update_auth(ISrsRequest *r);
|
||||
virtual srs_error_t consumer_dumps(ISrsLiveConsumer *consumer, bool ds, bool dm, bool dg);
|
||||
};
|
||||
|
||||
// Mock live consumer for testing message queue dump_packets
|
||||
|
|
|
|||
|
|
@ -935,7 +935,7 @@ VOID TEST(ProtocolHTTPTest, HTTPServerMuxerBasic)
|
|||
MockHttpHandler *h1 = new MockHttpHandler("Done");
|
||||
HELPER_ASSERT_SUCCESS(s.handle("/api/", h1));
|
||||
|
||||
h1->entry->enabled = false;
|
||||
h1->entry_->enabled = false;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1480,7 +1480,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory(fs));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1503,7 +1503,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1520,7 +1520,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1538,7 +1538,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1556,7 +1556,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1574,7 +1574,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1592,7 +1592,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1614,7 +1614,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("livestream-13.ts"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1636,7 +1636,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("livestream-13.m4s"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1658,7 +1658,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("init.mp4"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1684,7 +1684,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1701,7 +1701,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1718,7 +1718,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1735,7 +1735,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1752,7 +1752,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1769,7 +1769,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1786,7 +1786,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
@ -1803,7 +1803,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path(new MockSrsPathNotExists());
|
||||
h.entry = &e;
|
||||
h.entry_ = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
SrsHttpMessage r(NULL, NULL);
|
||||
|
|
|
|||
|
|
@ -1302,7 +1302,7 @@ VOID TEST(KernelErrorTest, AsanReportCallback)
|
|||
#ifdef SRS_SANITIZER_LOG
|
||||
// Test asan_report_callback function with various input formats
|
||||
// Temporarily disable log output to avoid cluttering test results
|
||||
MockEmptyLog* mock_log = dynamic_cast<MockEmptyLog*>(_srs_log);
|
||||
MockEmptyLog *mock_log = dynamic_cast<MockEmptyLog *>(_srs_log);
|
||||
SrsLogLevel original_level = mock_log->level_;
|
||||
mock_log->level_ = SrsLogLevelDisabled;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user