AI: Add utest to cover srt module.
This commit is contained in:
parent
1509fde2da
commit
809d77b662
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_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_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_app5" "srs_utest_app6" "srs_utest_app7" "srs_utest_app8" "srs_utest_app9"
|
||||||
"srs_utest_app10" "srs_utest_app11")
|
"srs_utest_app10" "srs_utest_app11" "srs_utest_app12")
|
||||||
# Always include SRT utest
|
# Always include SRT utest
|
||||||
MODULE_FILES+=("srs_utest_srt")
|
MODULE_FILES+=("srs_utest_srt")
|
||||||
if [[ $SRS_GB28181 == YES ]]; then
|
if [[ $SRS_GB28181 == YES ]]; then
|
||||||
|
|
|
||||||
|
|
@ -524,13 +524,14 @@ srs_error_t SrsMpegtsSrtConn::do_playing()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
SrsSrtConsumer *consumer_raw = NULL;
|
ISrsSrtConsumer *consumer_raw = NULL;
|
||||||
if ((err = srt_source_->create_consumer(consumer_raw)) != srs_success) {
|
if ((err = srt_source_->create_consumer(consumer_raw)) != srs_success) {
|
||||||
return srs_error_wrap(err, "create consumer, ts source=%s", req_->get_stream_url().c_str());
|
return srs_error_wrap(err, "create consumer, ts source=%s", req_->get_stream_url().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_assert(consumer_raw);
|
srs_assert(consumer_raw);
|
||||||
SrsUniquePtr<SrsSrtConsumer> consumer(consumer_raw);
|
SrsUniquePtr<ISrsSrtConsumer> consumer(consumer_raw);
|
||||||
|
SrsSrtConsumer *consumer_impl = dynamic_cast<SrsSrtConsumer *>(consumer_raw);
|
||||||
|
|
||||||
// TODO: FIXME: Dumps the SPS/PPS from gop cache, without other frames.
|
// TODO: FIXME: Dumps the SPS/PPS from gop cache, without other frames.
|
||||||
if ((err = srt_source_->consumer_dumps(consumer.get())) != srs_success) {
|
if ((err = srt_source_->consumer_dumps(consumer.get())) != srs_success) {
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,15 @@ SrsSharedPtr<SrsSrtSource> SrsSrtSourceManager::fetch(ISrsRequest *r)
|
||||||
|
|
||||||
SrsSrtSourceManager *_srs_srt_sources = NULL;
|
SrsSrtSourceManager *_srs_srt_sources = NULL;
|
||||||
|
|
||||||
SrsSrtConsumer::SrsSrtConsumer(SrsSrtSource *s)
|
ISrsSrtConsumer::ISrsSrtConsumer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsSrtConsumer::~ISrsSrtConsumer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSrtConsumer::SrsSrtConsumer(ISrsSrtSource *s)
|
||||||
{
|
{
|
||||||
source_ = s;
|
source_ = s;
|
||||||
should_update_source_id_ = false;
|
should_update_source_id_ = false;
|
||||||
|
|
@ -916,12 +924,22 @@ srs_error_t SrsSrtFrameBuilder::on_aac_frame(SrsTsMessage *msg, uint32_t pts, ch
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISrsSrtSource::ISrsSrtSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsSrtSource::~ISrsSrtSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SrsSrtSource::SrsSrtSource()
|
SrsSrtSource::SrsSrtSource()
|
||||||
{
|
{
|
||||||
req_ = NULL;
|
req_ = NULL;
|
||||||
can_publish_ = true;
|
can_publish_ = true;
|
||||||
srt_bridge_ = NULL;
|
srt_bridge_ = NULL;
|
||||||
stream_die_at_ = 0;
|
stream_die_at_ = 0;
|
||||||
|
|
||||||
|
stat_ = _srs_stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsSrtSource::~SrsSrtSource()
|
SrsSrtSource::~SrsSrtSource()
|
||||||
|
|
@ -937,6 +955,8 @@ SrsSrtSource::~SrsSrtSource()
|
||||||
if (cid.empty())
|
if (cid.empty())
|
||||||
cid = _pre_source_id;
|
cid = _pre_source_id;
|
||||||
srs_trace("free srt source id=[%s]", cid.c_str());
|
srs_trace("free srt source id=[%s]", cid.c_str());
|
||||||
|
|
||||||
|
stat_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||||
|
|
@ -995,10 +1015,13 @@ srs_error_t SrsSrtSource::on_source_id_changed(SrsContextId id)
|
||||||
_source_id = id;
|
_source_id = id;
|
||||||
|
|
||||||
// notice all consumer
|
// notice all consumer
|
||||||
std::vector<SrsSrtConsumer *>::iterator it;
|
std::vector<ISrsSrtConsumer *>::iterator it;
|
||||||
for (it = consumers_.begin(); it != consumers_.end(); ++it) {
|
for (it = consumers_.begin(); it != consumers_.end(); ++it) {
|
||||||
SrsSrtConsumer *consumer = *it;
|
ISrsSrtConsumer *consumer = *it;
|
||||||
consumer->update_source_id();
|
SrsSrtConsumer *consumer_impl = dynamic_cast<SrsSrtConsumer *>(consumer);
|
||||||
|
if (consumer_impl) {
|
||||||
|
consumer_impl->update_source_id();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -1025,7 +1048,7 @@ void SrsSrtSource::set_bridge(ISrsSrtBridge *bridge)
|
||||||
srt_bridge_ = bridge;
|
srt_bridge_ = bridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsSrtSource::create_consumer(SrsSrtConsumer *&consumer)
|
srs_error_t SrsSrtSource::create_consumer(ISrsSrtConsumer *&consumer)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
|
@ -1037,7 +1060,7 @@ srs_error_t SrsSrtSource::create_consumer(SrsSrtConsumer *&consumer)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsSrtSource::consumer_dumps(SrsSrtConsumer *consumer)
|
srs_error_t SrsSrtSource::consumer_dumps(ISrsSrtConsumer *consumer)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
|
@ -1047,9 +1070,9 @@ srs_error_t SrsSrtSource::consumer_dumps(SrsSrtConsumer *consumer)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsSrtSource::on_consumer_destroy(SrsSrtConsumer *consumer)
|
void SrsSrtSource::on_consumer_destroy(ISrsSrtConsumer *consumer)
|
||||||
{
|
{
|
||||||
std::vector<SrsSrtConsumer *>::iterator it;
|
std::vector<ISrsSrtConsumer *>::iterator it;
|
||||||
it = std::find(consumers_.begin(), consumers_.end(), consumer);
|
it = std::find(consumers_.begin(), consumers_.end(), consumer);
|
||||||
if (it != consumers_.end()) {
|
if (it != consumers_.end()) {
|
||||||
it = consumers_.erase(it);
|
it = consumers_.erase(it);
|
||||||
|
|
@ -1080,8 +1103,7 @@ srs_error_t SrsSrtSource::on_publish()
|
||||||
return srs_error_wrap(err, "bridge on publish");
|
return srs_error_wrap(err, "bridge on publish");
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsStatistic *stat = _srs_stat;
|
stat_->on_stream_publish(req_, _source_id.c_str());
|
||||||
stat->on_stream_publish(req_, _source_id.c_str());
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -1093,8 +1115,7 @@ void SrsSrtSource::on_unpublish()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsStatistic *stat = _srs_stat;
|
stat_->on_stream_close(req_);
|
||||||
stat->on_stream_close(req_);
|
|
||||||
|
|
||||||
if (srt_bridge_) {
|
if (srt_bridge_) {
|
||||||
srt_bridge_->on_unpublish();
|
srt_bridge_->on_unpublish();
|
||||||
|
|
@ -1115,7 +1136,7 @@ srs_error_t SrsSrtSource::on_packet(SrsSrtPacket *packet)
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
for (int i = 0; i < (int)consumers_.size(); i++) {
|
for (int i = 0; i < (int)consumers_.size(); i++) {
|
||||||
SrsSrtConsumer *consumer = consumers_.at(i);
|
ISrsSrtConsumer *consumer = consumers_.at(i);
|
||||||
if ((err = consumer->enqueue(packet->copy())) != srs_success) {
|
if ((err = consumer->enqueue(packet->copy())) != srs_success) {
|
||||||
return srs_error_wrap(err, "consume ts packet");
|
return srs_error_wrap(err, "consume ts packet");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ class SrsLiveSource;
|
||||||
class SrsSrtSource;
|
class SrsSrtSource;
|
||||||
class SrsAlonePithyPrint;
|
class SrsAlonePithyPrint;
|
||||||
class SrsSrtFrameBuilder;
|
class SrsSrtFrameBuilder;
|
||||||
|
class ISrsStatistic;
|
||||||
|
class ISrsSrtConsumer;
|
||||||
|
class ISrsSrtSource;
|
||||||
|
|
||||||
// The SRT packet with shared message.
|
// The SRT packet with shared message.
|
||||||
class SrsSrtPacket
|
class SrsSrtPacket
|
||||||
|
|
@ -97,15 +100,29 @@ public:
|
||||||
// Global singleton instance.
|
// Global singleton instance.
|
||||||
extern SrsSrtSourceManager *_srs_srt_sources;
|
extern SrsSrtSourceManager *_srs_srt_sources;
|
||||||
|
|
||||||
class SrsSrtConsumer
|
// The SRT consumer interface.
|
||||||
|
class ISrsSrtConsumer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsSrtConsumer(SrsSrtSource *source);
|
ISrsSrtConsumer();
|
||||||
virtual ~SrsSrtConsumer();
|
virtual ~ISrsSrtConsumer();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual srs_error_t enqueue(SrsSrtPacket *packet) = 0;
|
||||||
|
virtual srs_error_t dump_packet(SrsSrtPacket **ppkt) = 0;
|
||||||
|
virtual void wait(int nb_msgs, srs_utime_t timeout) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The SRT consumer, consume packets from SRT stream source.
|
||||||
|
class SrsSrtConsumer : public ISrsSrtConsumer
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
// Because source references to this object, so we should directly use the source ptr.
|
// Because source references to this object, so we should directly use the source ptr.
|
||||||
SrsSrtSource *source_;
|
ISrsSrtSource *source_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SrsSrtConsumer(ISrsSrtSource *source);
|
||||||
|
virtual ~SrsSrtConsumer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<SrsSrtPacket *> queue_;
|
std::vector<SrsSrtPacket *> queue_;
|
||||||
|
|
@ -185,9 +202,25 @@ private:
|
||||||
SrsAlonePithyPrint *pp_audio_duration_;
|
SrsAlonePithyPrint *pp_audio_duration_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A SRT source is a stream, to publish and to play with.
|
// The SRT source interface.
|
||||||
class SrsSrtSource : public ISrsSrtTarget
|
class ISrsSrtSource : public ISrsSrtTarget
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
ISrsSrtSource();
|
||||||
|
virtual ~ISrsSrtSource();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SrsContextId source_id() = 0;
|
||||||
|
virtual SrsContextId pre_source_id() = 0;
|
||||||
|
virtual void on_consumer_destroy(ISrsSrtConsumer *consumer) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A SRT source is a stream, to publish and to play with.
|
||||||
|
class SrsSrtSource : public ISrsSrtSource
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ISrsStatistic *stat_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SrsSrtSource();
|
SrsSrtSource();
|
||||||
virtual ~SrsSrtSource();
|
virtual ~SrsSrtSource();
|
||||||
|
|
@ -214,10 +247,10 @@ public:
|
||||||
public:
|
public:
|
||||||
// Create consumer
|
// Create consumer
|
||||||
// @param consumer, output the create consumer.
|
// @param consumer, output the create consumer.
|
||||||
virtual srs_error_t create_consumer(SrsSrtConsumer *&consumer);
|
virtual srs_error_t create_consumer(ISrsSrtConsumer *&consumer);
|
||||||
// Dumps packets in cache to consumer.
|
// Dumps packets in cache to consumer.
|
||||||
virtual srs_error_t consumer_dumps(SrsSrtConsumer *consumer);
|
virtual srs_error_t consumer_dumps(ISrsSrtConsumer *consumer);
|
||||||
virtual void on_consumer_destroy(SrsSrtConsumer *consumer);
|
virtual void on_consumer_destroy(ISrsSrtConsumer *consumer);
|
||||||
// Whether we can publish stream to the source, return false if it exists.
|
// Whether we can publish stream to the source, return false if it exists.
|
||||||
virtual bool can_publish();
|
virtual bool can_publish();
|
||||||
// When start publish stream.
|
// When start publish stream.
|
||||||
|
|
@ -235,7 +268,7 @@ private:
|
||||||
SrsContextId _pre_source_id;
|
SrsContextId _pre_source_id;
|
||||||
ISrsRequest *req_;
|
ISrsRequest *req_;
|
||||||
// To delivery packets to clients.
|
// To delivery packets to clients.
|
||||||
std::vector<SrsSrtConsumer *> consumers_;
|
std::vector<ISrsSrtConsumer *> consumers_;
|
||||||
bool can_publish_;
|
bool can_publish_;
|
||||||
// The last die time, while die means neither publishers nor players.
|
// The last die time, while die means neither publishers nor players.
|
||||||
srs_utime_t stream_die_at_;
|
srs_utime_t stream_die_at_;
|
||||||
|
|
|
||||||
1584
trunk/src/utest/srs_utest_app12.cpp
Normal file
1584
trunk/src/utest/srs_utest_app12.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
trunk/src/utest/srs_utest_app12.hpp
Normal file
111
trunk/src/utest/srs_utest_app12.hpp
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2025 The SRS Authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SRS_UTEST_APP12_HPP
|
||||||
|
#define SRS_UTEST_APP12_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <srs_utest_app12.hpp>
|
||||||
|
*/
|
||||||
|
#include <srs_utest.hpp>
|
||||||
|
|
||||||
|
#include <srs_utest_app6.hpp>
|
||||||
|
#include <srs_app_stream_bridge.hpp>
|
||||||
|
#include <srs_protocol_rtmp_stack.hpp>
|
||||||
|
|
||||||
|
// Mock frame target for testing SrsSrtFrameBuilder
|
||||||
|
class MockSrtFrameTarget : public ISrsFrameTarget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int on_frame_count_;
|
||||||
|
SrsMediaPacket *last_frame_;
|
||||||
|
srs_error_t frame_error_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockSrtFrameTarget();
|
||||||
|
virtual ~MockSrtFrameTarget();
|
||||||
|
virtual srs_error_t on_frame(SrsMediaPacket *frame);
|
||||||
|
void reset();
|
||||||
|
void set_frame_error(srs_error_t err);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock statistic for testing SrsSrtSource publish/unpublish
|
||||||
|
class MockSrtStatistic : public ISrsStatistic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int on_stream_publish_count_;
|
||||||
|
int on_stream_close_count_;
|
||||||
|
std::string last_publisher_id_;
|
||||||
|
ISrsRequest *last_publish_req_;
|
||||||
|
ISrsRequest *last_close_req_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockSrtStatistic();
|
||||||
|
virtual ~MockSrtStatistic();
|
||||||
|
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);
|
||||||
|
virtual std::string server_id();
|
||||||
|
virtual std::string service_id();
|
||||||
|
virtual std::string service_pid();
|
||||||
|
virtual SrsStatisticVhost *find_vhost_by_id(std::string vid);
|
||||||
|
virtual SrsStatisticStream *find_stream(std::string sid);
|
||||||
|
virtual SrsStatisticClient *find_client(std::string client_id);
|
||||||
|
virtual srs_error_t dumps_vhosts(SrsJsonArray *arr);
|
||||||
|
virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count);
|
||||||
|
virtual srs_error_t dumps_clients(SrsJsonArray *arr, int start, int count);
|
||||||
|
virtual srs_error_t dumps_metrics(int64_t &send_bytes, int64_t &recv_bytes, int64_t &nstreams, int64_t &nclients, int64_t &total_nclients, int64_t &nerrs);
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock SRT bridge for testing SrsSrtSource publish/unpublish
|
||||||
|
class MockSrtBridge : public ISrsSrtBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int on_publish_count_;
|
||||||
|
int on_unpublish_count_;
|
||||||
|
int on_packet_count_;
|
||||||
|
srs_error_t on_publish_error_;
|
||||||
|
srs_error_t on_packet_error_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockSrtBridge();
|
||||||
|
virtual ~MockSrtBridge();
|
||||||
|
virtual srs_error_t initialize(ISrsRequest *r);
|
||||||
|
virtual srs_error_t on_publish();
|
||||||
|
virtual void on_unpublish();
|
||||||
|
virtual srs_error_t on_packet(SrsSrtPacket *packet);
|
||||||
|
void set_on_publish_error(srs_error_t err);
|
||||||
|
void set_on_packet_error(srs_error_t err);
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock SRT consumer for testing SrsSrtSource on_packet
|
||||||
|
class MockSrtConsumer : public ISrsSrtConsumer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int enqueue_count_;
|
||||||
|
srs_error_t enqueue_error_;
|
||||||
|
std::vector<SrsSrtPacket *> packets_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockSrtConsumer();
|
||||||
|
virtual ~MockSrtConsumer();
|
||||||
|
virtual srs_error_t enqueue(SrsSrtPacket *packet);
|
||||||
|
virtual srs_error_t dump_packet(SrsSrtPacket **ppkt);
|
||||||
|
virtual void wait(int nb_msgs, srs_utime_t timeout);
|
||||||
|
void set_enqueue_error(srs_error_t err);
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user