Support custom deleter for SrsUniquePtr. (#4309)
SrsUniquePtr does not support array or object created by malloc, because
we only use delete to dispose the resource. You can use a custom
function to free the memory allocated by malloc or other allocators.
```cpp
char* p = (char*)malloc(1024);
SrsUniquePtr<char> ptr(p, your_free_chars);
```
This is used to replace the SrsAutoFreeH. For example:
```cpp
addrinfo* r = NULL;
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
getaddrinfo("127.0.0.1", NULL, &hints, &r);
```
Now, this can be replaced by:
```cpp
addrinfo* r = NULL;
getaddrinfo("127.0.0.1", NULL, &hints, &r);
SrsUniquePtr<addrinfo> r2(r, freeaddrinfo);
```
Please aware that there is a slight difference between SrsAutoFreeH and
SrsUniquePtr. SrsAutoFreeH will track the address of pointer, while
SrsUniquePtr will not.
```cpp
addrinfo* r = NULL;
SrsAutoFreeH(addrinfo, r, freeaddrinfo); // r will be freed even r is changed later.
SrsUniquePtr<addrinfo> ptr(r, freeaddrinfo); // crash because r is an invalid pointer.
```
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
This commit is contained in:
parent
5881155095
commit
4e55bc83b7
20
.vscode/settings.json
vendored
20
.vscode/settings.json
vendored
|
|
@ -1,5 +1,23 @@
|
|||
{
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/trunk/ide/srs_clion",
|
||||
"cmake.buildDirectory": "${workspaceFolder}/trunk/ide/vscode-build",
|
||||
"cmake.configureOnOpen": false
|
||||
"cmake.configureOnOpen": false,
|
||||
"files.associations": {
|
||||
"vector": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"__tree": "cpp",
|
||||
"array": "cpp",
|
||||
"bitset": "cpp",
|
||||
"deque": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"queue": "cpp",
|
||||
"set": "cpp",
|
||||
"stack": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"unordered_map": "cpp"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
73
trunk/3rdparty/st-srs/utest/st_utest.hpp
vendored
73
trunk/3rdparty/st-srs/utest/st_utest.hpp
vendored
|
|
@ -50,78 +50,5 @@ extern std::ostream& operator<<(std::ostream& out, const ErrorObject* err);
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
// To free the instance in the current scope, for instance, MyClass* ptr,
|
||||
// which is a ptr and this class will:
|
||||
// 1. free the ptr.
|
||||
// 2. set ptr to NULL.
|
||||
//
|
||||
// Usage:
|
||||
// MyClass* po = new MyClass();
|
||||
// // ...... use po
|
||||
// SrsAutoFree(MyClass, po);
|
||||
//
|
||||
// Usage for array:
|
||||
// MyClass** pa = new MyClass*[size];
|
||||
// // ....... use pa
|
||||
// SrsAutoFreeA(MyClass*, pa);
|
||||
//
|
||||
// @remark the MyClass can be basic type, for instance, SrsAutoFreeA(char, pstr),
|
||||
// where the char* pstr = new char[size].
|
||||
// To delete object.
|
||||
#define SrsAutoFree(className, instance) \
|
||||
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, NULL)
|
||||
// To delete array.
|
||||
#define SrsAutoFreeA(className, instance) \
|
||||
impl_SrsAutoFree<className> _auto_free_array_##instance(&instance, true, false, NULL)
|
||||
// Use free instead of delete.
|
||||
#define SrsAutoFreeF(className, instance) \
|
||||
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, true, NULL)
|
||||
// Use hook instead of delete.
|
||||
#define SrsAutoFreeH(className, instance, hook) \
|
||||
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, hook)
|
||||
// The template implementation.
|
||||
template<class T>
|
||||
class impl_SrsAutoFree
|
||||
{
|
||||
private:
|
||||
T** ptr;
|
||||
bool is_array;
|
||||
bool _use_free;
|
||||
void (*_hook)(T*);
|
||||
public:
|
||||
// If use_free, use free(void*) to release the p.
|
||||
// If specified hook, use hook(p) to release it.
|
||||
// Use delete to release p, or delete[] if p is an array.
|
||||
impl_SrsAutoFree(T** p, bool array, bool use_free, void (*hook)(T*)) {
|
||||
ptr = p;
|
||||
is_array = array;
|
||||
_use_free = use_free;
|
||||
_hook = hook;
|
||||
}
|
||||
|
||||
virtual ~impl_SrsAutoFree() {
|
||||
if (ptr == NULL || *ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_use_free) {
|
||||
free(*ptr);
|
||||
} else if (_hook) {
|
||||
_hook(*ptr);
|
||||
} else {
|
||||
if (is_array) {
|
||||
delete[] *ptr;
|
||||
} else {
|
||||
delete *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// The time unit in ms, for example 100 * SRS_UTIME_MILLISECONDS means 100ms.
|
||||
#define SRS_UTIME_MILLISECONDS 1000
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -360,6 +360,7 @@ function parse_user_option() {
|
|||
--gmp) SRS_GPERF_MP=$(switch2value $value) ;;
|
||||
--gcp) SRS_GPERF_CP=$(switch2value $value) ;;
|
||||
--gprof) SRS_GPROF=$(switch2value $value) ;;
|
||||
--asan) SRS_SANITIZER=$(switch2value $value) ;;
|
||||
--sanitizer) SRS_SANITIZER=$(switch2value $value) ;;
|
||||
--sanitizer-static) SRS_SANITIZER_STATIC=$(switch2value $value) ;;
|
||||
--sanitizer-log) SRS_SANITIZER_LOG=$(switch2value $value) ;;
|
||||
|
|
|
|||
|
|
@ -1638,41 +1638,15 @@ srs_error_t SrsRtcFrameBuilder::packet_video_key_frame(SrsRtpPacket* pkt)
|
|||
return srs_error_new(ERROR_RTC_RTP_MUXER, "no sps or pps in stap-a rtp. sps: %p, pps:%p", sps, pps);
|
||||
}
|
||||
|
||||
// Reset SPS/PPS cache, ensuring that the next SPS/PPS will be handled when both are received.
|
||||
// Note that we should use SrsAutoFree to set the ptr to NULL.
|
||||
SrsAutoFree(SrsRtpPacket, obs_whip_sps_);
|
||||
SrsAutoFree(SrsRtpPacket, obs_whip_pps_);
|
||||
// Packet SPS/PPS to RTMP keyframe.
|
||||
err = packet_sps_pps(pkt, sps, pps);
|
||||
|
||||
// h264 raw to h264 packet.
|
||||
std::string sh;
|
||||
SrsUniquePtr<SrsRawH264Stream> avc(new SrsRawH264Stream());
|
||||
|
||||
if ((err = avc->mux_sequence_header(string(sps->bytes, sps->size), string(pps->bytes, pps->size), sh)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux sequence header");
|
||||
}
|
||||
|
||||
// h264 packet to flv packet.
|
||||
char* flv = NULL;
|
||||
int nb_flv = 0;
|
||||
if ((err = avc->mux_avc2flv(sh, SrsVideoAvcFrameTypeKeyFrame, SrsVideoAvcFrameTraitSequenceHeader, pkt->get_avsync_time(),
|
||||
pkt->get_avsync_time(), &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "avc to flv");
|
||||
}
|
||||
|
||||
SrsMessageHeader header;
|
||||
header.initialize_video(nb_flv, pkt->get_avsync_time(), 1);
|
||||
SrsCommonMessage rtmp;
|
||||
if ((err = rtmp.create(&header, flv, nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "create rtmp");
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage msg;
|
||||
if ((err = msg.create(&rtmp)) != srs_success) {
|
||||
return srs_error_wrap(err, "create message");
|
||||
}
|
||||
|
||||
if ((err = bridge_->on_frame(&msg)) != srs_success) {
|
||||
return err;
|
||||
// Always reset the SPS/PPS cache after used it.
|
||||
srs_freep(obs_whip_sps_);
|
||||
srs_freep(obs_whip_pps_);
|
||||
|
||||
if (err != srs_success) {
|
||||
return srs_error_wrap(err, "packet sps/pps");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1729,6 +1703,48 @@ srs_error_t SrsRtcFrameBuilder::packet_video_key_frame(SrsRtpPacket* pkt)
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcFrameBuilder::packet_sps_pps(SrsRtpPacket* pkt, SrsSample* sps, SrsSample* pps)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// h264 raw to h264 packet.
|
||||
std::string sh;
|
||||
SrsUniquePtr<SrsRawH264Stream> avc(new SrsRawH264Stream());
|
||||
|
||||
string sps2 = string(sps->bytes, sps->size);
|
||||
string pps2 = string(pps->bytes, pps->size);
|
||||
if ((err = avc->mux_sequence_header(sps2, pps2, sh)) != srs_success) {
|
||||
return srs_error_wrap(err, "mux sequence header");
|
||||
}
|
||||
|
||||
// h264 packet to flv packet.
|
||||
char* flv = NULL;
|
||||
int nb_flv = 0;
|
||||
if ((err = avc->mux_avc2flv(sh, SrsVideoAvcFrameTypeKeyFrame,
|
||||
SrsVideoAvcFrameTraitSequenceHeader, pkt->get_avsync_time(),
|
||||
pkt->get_avsync_time(), &flv, &nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "avc to flv");
|
||||
}
|
||||
|
||||
SrsMessageHeader header;
|
||||
header.initialize_video(nb_flv, pkt->get_avsync_time(), 1);
|
||||
SrsCommonMessage rtmp;
|
||||
if ((err = rtmp.create(&header, flv, nb_flv)) != srs_success) {
|
||||
return srs_error_wrap(err, "create rtmp");
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage msg;
|
||||
if ((err = msg.create(&rtmp)) != srs_success) {
|
||||
return srs_error_wrap(err, "create message");
|
||||
}
|
||||
|
||||
if ((err = bridge_->on_frame(&msg)) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcFrameBuilder::packet_video_rtmp(const uint16_t start, const uint16_t end)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
|
|
|||
|
|
@ -356,6 +356,8 @@ private:
|
|||
private:
|
||||
srs_error_t packet_video(SrsRtpPacket* pkt);
|
||||
srs_error_t packet_video_key_frame(SrsRtpPacket* pkt);
|
||||
srs_error_t packet_sps_pps(SrsRtpPacket* pkt, SrsSample* sps, SrsSample* pps);
|
||||
private:
|
||||
inline uint16_t cache_index(uint16_t current_sn) {
|
||||
return current_sn % s_cache_size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,23 +16,36 @@
|
|||
// SrsUniquePtr<MyClass> ptr(new MyClass());
|
||||
// ptr->do_something();
|
||||
//
|
||||
// Note that the ptr should be initialized before use it, or it will crash if not set, for example:
|
||||
// Note that the p should be initialized before use it, or it will crash if not set, for example:
|
||||
// Myclass* p;
|
||||
// SrsUniquePtr<MyClass> ptr(p); // crash because p is an invalid pointer.
|
||||
//
|
||||
// Note that do not support array or object created by malloc, because we only use delete to dispose
|
||||
// the resource.
|
||||
// the resource. You can use a custom function to free the memory allocated by malloc or other
|
||||
// allocators.
|
||||
// char* p = (char*)malloc(1024);
|
||||
// SrsUniquePtr<char> ptr(p, your_free_chars);
|
||||
// Or to free a specific object:
|
||||
// addrinfo* r = NULL;
|
||||
// getaddrinfo("127.0.0.1", NULL, &hints, &r);
|
||||
// SrsUniquePtr<addrinfo> ptr(r, freeaddrinfo);
|
||||
template<class T>
|
||||
class SrsUniquePtr
|
||||
{
|
||||
private:
|
||||
T* ptr_;
|
||||
void (*deleter_)(T*);
|
||||
public:
|
||||
SrsUniquePtr(T* ptr = NULL) {
|
||||
SrsUniquePtr(T* ptr = NULL, void (*deleter)(T*) = NULL) {
|
||||
ptr_ = ptr;
|
||||
deleter_ = deleter;
|
||||
}
|
||||
virtual ~SrsUniquePtr() {
|
||||
delete ptr_;
|
||||
if (!deleter_) {
|
||||
delete ptr_;
|
||||
} else {
|
||||
deleter_(ptr_);
|
||||
}
|
||||
}
|
||||
public:
|
||||
// Get the object.
|
||||
|
|
@ -68,6 +81,10 @@ private:
|
|||
// Usage:
|
||||
// SrsUniquePtr<MyClass[]> ptr(new MyClass[10]);
|
||||
// ptr[0]->do_something();
|
||||
//
|
||||
// Note that the p should be initialized before use it, or it will crash if not set, for example:
|
||||
// Myclass* p;
|
||||
// SrsUniquePtr<MyClass[]> ptr(p); // crash because p is an invalid pointer.
|
||||
template<class T>
|
||||
class SrsUniquePtr<T[]>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,85 +11,93 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Note that the SrsAutoFree is deprecated, please use SrsUniquePtr instead.
|
||||
// Note that the SrsAutoFree is deprecated, please use SrsUniquePtr instead. For example:
|
||||
// MyClass* p = new MyClass();
|
||||
// SrsAutoFree(MyClass, p);
|
||||
// This can be replaced by:
|
||||
// SrsUniquePtr<MyClass> p(new MyClass());
|
||||
//
|
||||
// Note: Please use SrsUniquePtr if possible. Please aware that there is a slight difference between SrsAutoFree
|
||||
// and SrsUniquePtr. SrsAutoFree will track the address of pointer, while SrsUniquePtr will not.
|
||||
// Note: Please aware that there is a slight difference between SrsAutoFree and SrsUniquePtr.
|
||||
// SrsAutoFree will track the address of pointer, while SrsUniquePtr will not.
|
||||
// MyClass* p;
|
||||
// SrsAutoFree(MyClass, p); // p will be freed even p is changed later.
|
||||
// SrsUniquePtr ptr(p); // crash because p is an invalid pointer.
|
||||
//
|
||||
// The auto free helper, which is actually the unique ptr, without the move feature,
|
||||
// see https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107
|
||||
//
|
||||
// To free the instance in the current scope, for instance, MyClass* ptr,
|
||||
// which is a ptr and this class will:
|
||||
// 1. free the ptr.
|
||||
// 2. set ptr to NULL.
|
||||
//
|
||||
// Usage:
|
||||
// MyClass* po = new MyClass();
|
||||
// // ...... use po
|
||||
// SrsAutoFree(MyClass, po);
|
||||
//
|
||||
// Usage for array:
|
||||
// See https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107 for more details.
|
||||
//#define SrsAutoFree(className, instance) \
|
||||
// impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, NULL)
|
||||
// To delete array. Please use SrsUniquePtr instead. For example:
|
||||
// MyClass** pa = new MyClass*[size];
|
||||
// // ....... use pa
|
||||
// SrsAutoFreeA(MyClass*, pa);
|
||||
// This can be replaced by:
|
||||
// SrsUniquePtr<MyClass[]> pa(new MyClass[10]);
|
||||
//
|
||||
// @remark the MyClass can be basic type, for instance, SrsAutoFreeA(char, pstr),
|
||||
// where the char* pstr = new char[size].
|
||||
// To delete object.
|
||||
#define SrsAutoFree(className, instance) \
|
||||
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, NULL)
|
||||
// To delete array.
|
||||
#define SrsAutoFreeA(className, instance) \
|
||||
impl_SrsAutoFree<className> _auto_free_array_##instance(&instance, true, false, NULL)
|
||||
// Use free instead of delete.
|
||||
#define SrsAutoFreeF(className, instance) \
|
||||
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, true, NULL)
|
||||
// Use hook instead of delete.
|
||||
#define SrsAutoFreeH(className, instance, hook) \
|
||||
impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, hook)
|
||||
// Note: Please aware that there is a slight difference between SrsAutoFreeA and SrsUniquePtr.
|
||||
// SrsAutoFreeA will track the address of pointer, while SrsUniquePtr will not.
|
||||
// MyClass** pa;
|
||||
// SrsAutoFreeA(MyClass*, pa); // pa will be freed even pa is changed later.
|
||||
// SrsUniquePtr<MyClass[]> ptr(pa); // crash because pa is an invalid pointer.
|
||||
//
|
||||
// See https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107 for more details.
|
||||
//#define SrsAutoFreeA(className, instance) \
|
||||
// impl_SrsAutoFree<className> _auto_free_array_##instance(&instance, true, false, NULL)
|
||||
// Use hook instead of delete. Please use SrsUniquePtr instead. For example:
|
||||
// addrinfo* r = NULL;
|
||||
// SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
// getaddrinfo("127.0.0.1", NULL, &hints, &r);
|
||||
// This can be replaced by:
|
||||
// addrinfo* r = NULL;
|
||||
// getaddrinfo("127.0.0.1", NULL, &hints, &r);
|
||||
// SrsUniquePtr<addrinfo> ptr(r, freeaddrinfo);
|
||||
//
|
||||
// Note: Please aware that there is a slight difference between SrsAutoFreeH and SrsUniquePtr.
|
||||
// SrsAutoFreeH will track the address of pointer, while SrsUniquePtr will not.
|
||||
// addrinfo* r = NULL;
|
||||
// SrsAutoFreeH(addrinfo, r, freeaddrinfo); // r will be freed even r is changed later.
|
||||
// SrsUniquePtr<addrinfo> ptr(r, freeaddrinfo); // crash because r is an invalid pointer.
|
||||
//
|
||||
// See https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107 for more details.
|
||||
//#define SrsAutoFreeH(className, instance, hook) \
|
||||
// impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, hook)
|
||||
// The template implementation.
|
||||
template<class T>
|
||||
class impl_SrsAutoFree
|
||||
{
|
||||
private:
|
||||
T** ptr;
|
||||
bool is_array;
|
||||
bool _use_free;
|
||||
void (*_hook)(T*);
|
||||
public:
|
||||
// If use_free, use free(void*) to release the p.
|
||||
// If specified hook, use hook(p) to release it.
|
||||
// Use delete to release p, or delete[] if p is an array.
|
||||
impl_SrsAutoFree(T** p, bool array, bool use_free, void (*hook)(T*)) {
|
||||
ptr = p;
|
||||
is_array = array;
|
||||
_use_free = use_free;
|
||||
_hook = hook;
|
||||
}
|
||||
|
||||
virtual ~impl_SrsAutoFree() {
|
||||
if (ptr == NULL || *ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_use_free) {
|
||||
free(*ptr);
|
||||
} else if (_hook) {
|
||||
_hook(*ptr);
|
||||
} else {
|
||||
if (is_array) {
|
||||
delete[] *ptr;
|
||||
} else {
|
||||
delete *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = NULL;
|
||||
}
|
||||
};
|
||||
//template<class T>
|
||||
//class impl_SrsAutoFree
|
||||
//{
|
||||
//private:
|
||||
// T** ptr;
|
||||
// bool is_array;
|
||||
// bool _use_free;
|
||||
// void (*_hook)(T*);
|
||||
//public:
|
||||
// // If use_free, use free(void*) to release the p.
|
||||
// // If specified hook, use hook(p) to release it.
|
||||
// // Use delete to release p, or delete[] if p is an array.
|
||||
// impl_SrsAutoFree(T** p, bool array, bool use_free, void (*hook)(T*)) {
|
||||
// ptr = p;
|
||||
// is_array = array;
|
||||
// _use_free = use_free;
|
||||
// _hook = hook;
|
||||
// }
|
||||
//
|
||||
// virtual ~impl_SrsAutoFree() {
|
||||
// if (ptr == NULL || *ptr == NULL) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (_use_free) {
|
||||
// free(*ptr);
|
||||
// } else if (_hook) {
|
||||
// _hook(*ptr);
|
||||
// } else {
|
||||
// if (is_array) {
|
||||
// delete[] *ptr;
|
||||
// } else {
|
||||
// delete *ptr;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// *ptr = NULL;
|
||||
// }
|
||||
//};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5315,9 +5315,21 @@ srs_error_t SrsMp4BoxReader::read(SrsSimpleStream* stream, SrsMp4Box** ppbox)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsMp4Box* box = NULL;
|
||||
// Note that we should use SrsAutoFree to free the ptr which is set later.
|
||||
SrsAutoFree(SrsMp4Box, box);
|
||||
if ((err = do_read(stream, box)) == srs_success) {
|
||||
*ppbox = box;
|
||||
return err;
|
||||
}
|
||||
|
||||
// When error, free the created box.
|
||||
srs_freep(box);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsMp4BoxReader::do_read(SrsSimpleStream* stream, SrsMp4Box*& box)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
while (true) {
|
||||
// For the first time to read the box, maybe it's a basic box which is only 4bytes header.
|
||||
// When we disconvery the real box, we know the size of the whole box, then read again and decode it.
|
||||
|
|
@ -5357,11 +5369,6 @@ srs_error_t SrsMp4BoxReader::read(SrsSimpleStream* stream, SrsMp4Box** ppbox)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (err == srs_success) {
|
||||
*ppbox = box;
|
||||
box = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -5651,18 +5658,17 @@ srs_error_t SrsMp4Decoder::load_next_box(SrsMp4Box** ppbox, uint32_t required_bo
|
|||
|
||||
while (true) {
|
||||
SrsMp4Box* box = NULL;
|
||||
// Note that we should use SrsAutoFree to free the ptr which is set later.
|
||||
SrsAutoFree(SrsMp4Box, box);
|
||||
|
||||
if ((err = do_load_next_box(&box, required_box_type)) != srs_success) {
|
||||
return srs_error_wrap(err, "load box");
|
||||
}
|
||||
|
||||
if (!required_box_type || (uint32_t)box->type == required_box_type) {
|
||||
*ppbox = box;
|
||||
box = NULL;
|
||||
break;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Free the box is not matched the required type.
|
||||
srs_freep(box);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -1963,6 +1963,9 @@ public:
|
|||
public:
|
||||
// Read a MP4 box to pbox, the stream is fill with the bytes of box to decode.
|
||||
virtual srs_error_t read(SrsSimpleStream* stream, SrsMp4Box** ppbox);
|
||||
private:
|
||||
srs_error_t do_read(SrsSimpleStream* stream, SrsMp4Box*& box);
|
||||
public:
|
||||
// Skip the box from stream, and skip in file if need.
|
||||
virtual srs_error_t skip(SrsMp4Box* box, SrsSimpleStream* stream);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -156,11 +156,11 @@ string srs_dns_resolve(string host, int& family)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
if(getaddrinfo(host.c_str(), NULL, &hints, &r)) {
|
||||
addrinfo* r_raw = NULL;
|
||||
if(getaddrinfo(host.c_str(), NULL, &hints, &r_raw)) {
|
||||
return "";
|
||||
}
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
char shost[64];
|
||||
memset(shost, 0, sizeof(shost));
|
||||
|
|
|
|||
|
|
@ -60,23 +60,23 @@ srs_error_t parse(std::string mp4_file, bool verbose)
|
|||
|
||||
fprintf(stderr, "\n%s\n", mp4_file.c_str());
|
||||
while (true) {
|
||||
SrsMp4Box* box = NULL;
|
||||
// Note that we should use SrsAutoFree to free the ptr which is set later.
|
||||
SrsAutoFree(SrsMp4Box, box);
|
||||
|
||||
if ((err = br.read(stream.get(), &box)) != srs_success) {
|
||||
SrsMp4Box* box_raw = NULL;
|
||||
if ((err = br.read(stream.get(), &box_raw)) != srs_success) {
|
||||
if (srs_error_code(err) == ERROR_SYSTEM_FILE_EOF) {
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return srs_error_wrap(err, "read box");
|
||||
}
|
||||
|
||||
// Should use unique pointer after box is created.
|
||||
SrsUniquePtr box(box_raw);
|
||||
|
||||
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer(stream->bytes(), stream->length()));
|
||||
if ((err = box->decode(buffer.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "decode box");
|
||||
}
|
||||
|
||||
if ((err = br.skip(box, stream.get())) != srs_success) {
|
||||
if ((err = br.skip(box.get(), stream.get())) != srs_success) {
|
||||
return srs_error_wrap(err, "skip box");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,14 +198,14 @@ srs_error_t srs_srt_listen(srs_srt_t srt_fd, std::string ip, int port)
|
|||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
if(getaddrinfo(ip.c_str(), sport, (const addrinfo*)&hints, &r)) {
|
||||
addrinfo* r_raw = NULL;
|
||||
if(getaddrinfo(ip.c_str(), sport, (const addrinfo*)&hints, &r_raw)) {
|
||||
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "getaddrinfo hints=(%d,%d,%d)",
|
||||
hints.ai_family, hints.ai_socktype, hints.ai_flags);
|
||||
}
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
if ((err = do_srs_srt_listen(srt_fd, r)) != srs_success) {
|
||||
if ((err = do_srs_srt_listen(srt_fd, r.get())) != srs_success) {
|
||||
srt_close(srt_fd);
|
||||
return srs_error_wrap(err, "srt_fd=%d", srt_fd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,11 +213,11 @@ srs_error_t srs_tcp_connect(string server, int port, srs_utime_t tm, srs_netfd_t
|
|||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
if(getaddrinfo(server.c_str(), sport, (const addrinfo*)&hints, &r)) {
|
||||
addrinfo* r_raw = NULL;
|
||||
if(getaddrinfo(server.c_str(), sport, (const addrinfo*)&hints, &r_raw)) {
|
||||
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "get address info");
|
||||
}
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
int sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
|
||||
if(sock == -1){
|
||||
|
|
@ -291,12 +291,12 @@ srs_error_t srs_tcp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
|||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
if(getaddrinfo(ip.c_str(), sport, (const addrinfo*)&hints, &r)) {
|
||||
addrinfo* r_raw = NULL;
|
||||
if(getaddrinfo(ip.c_str(), sport, (const addrinfo*)&hints, &r_raw)) {
|
||||
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "getaddrinfo hints=(%d,%d,%d)",
|
||||
hints.ai_family, hints.ai_socktype, hints.ai_flags);
|
||||
}
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
int fd = 0;
|
||||
if ((fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1) {
|
||||
|
|
@ -304,7 +304,7 @@ srs_error_t srs_tcp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
|||
r->ai_family, r->ai_socktype, r->ai_protocol);
|
||||
}
|
||||
|
||||
if ((err = do_srs_tcp_listen(fd, r, pfd)) != srs_success) {
|
||||
if ((err = do_srs_tcp_listen(fd, r.get(), pfd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "fd=%d", fd);
|
||||
}
|
||||
|
|
@ -353,12 +353,12 @@ srs_error_t srs_udp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
|||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
if(getaddrinfo(ip.c_str(), sport, (const addrinfo*)&hints, &r)) {
|
||||
addrinfo* r_raw = NULL;
|
||||
if(getaddrinfo(ip.c_str(), sport, (const addrinfo*)&hints, &r_raw)) {
|
||||
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "getaddrinfo hints=(%d,%d,%d)",
|
||||
hints.ai_family, hints.ai_socktype, hints.ai_flags);
|
||||
}
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
int fd = 0;
|
||||
if ((fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1) {
|
||||
|
|
@ -366,7 +366,7 @@ srs_error_t srs_udp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
|||
r->ai_family, r->ai_socktype, r->ai_protocol);
|
||||
}
|
||||
|
||||
if ((err = do_srs_udp_listen(fd, r, pfd)) != srs_success) {
|
||||
if ((err = do_srs_udp_listen(fd, r.get(), pfd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "fd=%d", fd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,6 @@ VOID TEST(CoreAutoFreeTest, Free)
|
|||
char* data = new char[32];
|
||||
srs_freepa(data);
|
||||
EXPECT_TRUE(data == NULL);
|
||||
|
||||
if (true) {
|
||||
data = new char[32];
|
||||
SrsAutoFreeA(char, data);
|
||||
}
|
||||
EXPECT_TRUE(data == NULL);
|
||||
}
|
||||
|
||||
VOID TEST(CoreMacroseTest, Check)
|
||||
|
|
@ -489,3 +483,120 @@ VOID TEST(CoreSmartPtr, UniquePtrArray)
|
|||
EXPECT_EQ(100, *ptr);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
void mock_free_chars(char* p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
VOID TEST(CoreSmartPtr, UniquePtrDeleterExample)
|
||||
{
|
||||
if (true) {
|
||||
char* p = (char*)malloc(1024);
|
||||
SrsUniquePtr<char> ptr(p, mock_free_chars);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
addrinfo* r = NULL;
|
||||
getaddrinfo("127.0.0.1", NULL, NULL, &r);
|
||||
SrsUniquePtr<addrinfo> ptr(r, freeaddrinfo);
|
||||
}
|
||||
}
|
||||
|
||||
class MockSlice
|
||||
{
|
||||
public:
|
||||
const char* bytes_;
|
||||
public:
|
||||
MockSlice(const char* bytes) {
|
||||
bytes_ = bytes;
|
||||
}
|
||||
virtual ~MockSlice() {
|
||||
}
|
||||
public:
|
||||
static void deleter(MockSlice* p) {
|
||||
p->bytes_ = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
VOID TEST(CoreSmartPtr, UniquePtrDeleterSlice)
|
||||
{
|
||||
MockSlice p("Hello");
|
||||
EXPECT_TRUE(p.bytes_ != NULL);
|
||||
|
||||
if (true) {
|
||||
SrsUniquePtr<MockSlice> ptr(&p, MockSlice::deleter);
|
||||
}
|
||||
EXPECT_TRUE(p.bytes_ == NULL);
|
||||
}
|
||||
|
||||
class MockSpecialPacket
|
||||
{
|
||||
public:
|
||||
char* bytes_;
|
||||
int size_;
|
||||
public:
|
||||
MockSpecialPacket(char* bytes, int size) {
|
||||
bytes_ = bytes;
|
||||
size_ = size;
|
||||
}
|
||||
virtual ~MockSpecialPacket() {
|
||||
srs_freep(bytes_);
|
||||
}
|
||||
public:
|
||||
static void deleter(vector<MockSpecialPacket*>* pkts) {
|
||||
vector<MockSpecialPacket*>::iterator it;
|
||||
for (it = pkts->begin(); it != pkts->end(); ++it) {
|
||||
MockSpecialPacket* pkt = *it;
|
||||
srs_freep(pkt);
|
||||
}
|
||||
pkts->clear();
|
||||
}
|
||||
};
|
||||
|
||||
VOID TEST(CoreSmartPtr, UniquePtrDeleterVector)
|
||||
{
|
||||
vector<MockSpecialPacket*> pkts;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
char* bytes = new char[1024];
|
||||
MockSpecialPacket* pkt = new MockSpecialPacket(bytes, 1024);
|
||||
pkts.push_back(pkt);
|
||||
}
|
||||
EXPECT_EQ(10, (int)pkts.size());
|
||||
|
||||
if (true) {
|
||||
SrsUniquePtr<vector<MockSpecialPacket*>> ptr(&pkts, MockSpecialPacket::deleter);
|
||||
}
|
||||
EXPECT_EQ(0, (int)pkts.size());
|
||||
}
|
||||
|
||||
class MockMalloc
|
||||
{
|
||||
public:
|
||||
const char* bytes_;
|
||||
public:
|
||||
MockMalloc(int size) {
|
||||
bytes_ = (char*)malloc(size);
|
||||
}
|
||||
virtual ~MockMalloc() {
|
||||
}
|
||||
public:
|
||||
static void deleter(MockMalloc* p) {
|
||||
free((void*)p->bytes_);
|
||||
p->bytes_ = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
VOID TEST(CoreSmartPtr, UniquePtrDeleterMalloc)
|
||||
{
|
||||
MockMalloc p(1024);
|
||||
EXPECT_TRUE(p.bytes_ != NULL);
|
||||
|
||||
if (true) {
|
||||
SrsUniquePtr<MockMalloc> ptr(&p, MockMalloc::deleter);
|
||||
}
|
||||
EXPECT_TRUE(p.bytes_ == NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -626,7 +626,7 @@ VOID TEST(ProtocolMsgArrayTest, MessageArray)
|
|||
SrsMessageArray arr(3);
|
||||
|
||||
SrsMessageArray* parr = &arr;
|
||||
SrsAutoFreeH(SrsMessageArray, parr, srs_utest_free_message_array);
|
||||
SrsUniquePtr<SrsMessageArray> parr2(parr, srs_utest_free_message_array);
|
||||
|
||||
arr.msgs[0] = msg.copy();
|
||||
EXPECT_EQ(1, msg.count());
|
||||
|
|
@ -643,7 +643,7 @@ VOID TEST(ProtocolMsgArrayTest, MessageArray)
|
|||
SrsMessageArray arr(3);
|
||||
|
||||
SrsMessageArray* parr = &arr;
|
||||
SrsAutoFreeH(SrsMessageArray, parr, srs_utest_free_message_array);
|
||||
SrsUniquePtr<SrsMessageArray> parr2(parr, srs_utest_free_message_array);
|
||||
|
||||
arr.msgs[0] = msg.copy();
|
||||
EXPECT_EQ(1, msg.count());
|
||||
|
|
|
|||
|
|
@ -2999,7 +2999,7 @@ VOID TEST(ProtocolRTMPTest, OthersAll)
|
|||
SrsMessageArray h(10);
|
||||
|
||||
SrsMessageArray* parr = &h;
|
||||
SrsAutoFreeH(SrsMessageArray, parr, srs_utest_free_message_array);
|
||||
SrsUniquePtr<SrsMessageArray> parr2(parr, srs_utest_free_message_array);
|
||||
|
||||
h.msgs[0] = new SrsSharedPtrMessage();
|
||||
h.msgs[1] = new SrsSharedPtrMessage();
|
||||
|
|
|
|||
|
|
@ -1118,9 +1118,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("127.0.0.1", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("127.0.0.1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1131,9 +1131,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("192.168.0.1", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("192.168.0.1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1176,9 +1176,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("2001:da8:6000:291:21f:d0ff:fed4:928c", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("2001:da8:6000:291:21f:d0ff:fed4:928c", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1187,9 +1187,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("3ffe:dead:beef::1", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("3ffe:dead:beef::1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1200,9 +1200,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("::", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("::", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1213,9 +1213,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("fec0::", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("fec0::", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1226,9 +1226,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("FE80::", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("FE80::", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
@ -1239,9 +1239,9 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
|
||||
ASSERT_TRUE(!getaddrinfo("::1", NULL, &hints, &r));
|
||||
addrinfo* r_raw = NULL;
|
||||
ASSERT_TRUE(!getaddrinfo("::1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ VOID TEST(StTest, StUtimePerformance)
|
|||
|
||||
EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
|
||||
gettimeofday_elapsed_time - st_utime_elapsed_time :
|
||||
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);
|
||||
st_utime_elapsed_time - gettimeofday_elapsed_time, 30);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user