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

UniquePtr: Support SrsUniquePtr to replace SrsAutoFree. v6.0.136 (#4109)

To manage an object:

```cpp
// Before
MyClass* ptr = new MyClass();
SrsAutoFree(MyClass, ptr);
ptr->do_something();

// Now
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
```

To manage an array of objects:

```cpp
// Before
char* ptr = new char[10];
SrsAutoFreeA(char, ptr);
ptr[0] = 0xf;

// Now
SrsUniquePtr<char[]> ptr(new char[10]);
ptr[0] = 0xf;
```

In fact, SrsUniquePtr is a limited subset of SrsAutoFree, mainly
managing pointers and arrays. SrsUniquePtr is better than SrsAutoFree
because it has the same API to standard unique ptr.

```cpp
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
MyClass* p = ptr.get();
```

SrsAutoFree actually uses a pointer to a pointer, so it can be set to
NULL, allowing the pointer's value to be changed later (this usage is
different from SrsUniquePtr).

```cpp
// OK to free ptr correctly.
MyClass* ptr;
SrsAutoFree(MyClass, ptr);
ptr = new MyClass();

// Crash because ptr is an invalid pointer.
MyClass* ptr;
SrsUniquePtr<MyClass> ptr(ptr);
ptr = new MyClass();
```

Additionally, SrsAutoFreeH can use specific release functions, which
SrsUniquePtr does not support.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-07-09 10:29:36 +08:00 committed by GitHub
parent baf22d01c1
commit 23d2602c34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
72 changed files with 1720 additions and 1669 deletions

View file

@ -13,6 +13,7 @@
#include <srs_kernel_io.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_kernel_buffer.hpp>
#include <srs_core_deprecated.hpp>
#include <string.h>
#include <sstream>
@ -36,10 +37,8 @@ srs_error_t srs_mp4_write_box(ISrsWriter* writer, ISrsCodec* box)
int nb_data = box->nb_bytes();
std::vector<char> data(nb_data);
SrsBuffer* buffer = new SrsBuffer(&data[0], nb_data);
SrsAutoFree(SrsBuffer, buffer);
if ((err = box->encode(buffer)) != srs_success) {
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer(&data[0], nb_data));
if ((err = box->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode box");
}
@ -5316,6 +5315,7 @@ 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);
while (true) {
@ -5338,12 +5338,11 @@ srs_error_t SrsMp4BoxReader::read(SrsSimpleStream* stream, SrsMp4Box** ppbox)
srs_assert(nread > 0);
stream->append(buf, (int)nread);
}
SrsBuffer* buffer = new SrsBuffer(stream->bytes(), stream->length());
SrsAutoFree(SrsBuffer, buffer);
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer(stream->bytes(), stream->length()));
// Discovery the box with basic header.
if (!box && (err = SrsMp4Box::discovery(buffer, &box)) != srs_success) {
if (!box && (err = SrsMp4Box::discovery(buffer.get(), &box)) != srs_success) {
if (srs_error_code(err) == ERROR_MP4_BOX_REQUIRE_SPACE) {
srs_freep(err);
continue;
@ -5431,15 +5430,14 @@ srs_error_t SrsMp4Decoder::initialize(ISrsReadSeeker* rs)
off_t offset = -1;
while (true) {
SrsMp4Box* box = NULL;
SrsAutoFree(SrsMp4Box, box);
if ((err = load_next_box(&box, 0)) != srs_success) {
SrsMp4Box* box_raw = NULL;
if ((err = load_next_box(&box_raw, 0)) != srs_success) {
return srs_error_wrap(err, "load box");
}
SrsUniquePtr<SrsMp4Box> box(box_raw);
if (box->is_ftyp()) {
SrsMp4FileTypeBox* ftyp = dynamic_cast<SrsMp4FileTypeBox*>(box);
SrsMp4FileTypeBox* ftyp = dynamic_cast<SrsMp4FileTypeBox*>(box.get());
if ((err = parse_ftyp(ftyp)) != srs_success) {
return srs_error_wrap(err, "parse ftyp");
}
@ -5450,7 +5448,7 @@ srs_error_t SrsMp4Decoder::initialize(ISrsReadSeeker* rs)
}
offset = off_t(cur - box->sz());
} else if (box->is_moov()) {
SrsMp4MovieBox* moov = dynamic_cast<SrsMp4MovieBox*>(box);
SrsMp4MovieBox* moov = dynamic_cast<SrsMp4MovieBox*>(box.get());
if ((err = parse_moov(moov)) != srs_success) {
return srs_error_wrap(err, "parse moov");
}
@ -5653,6 +5651,7 @@ 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) {
@ -5679,16 +5678,15 @@ srs_error_t SrsMp4Decoder::do_load_next_box(SrsMp4Box** ppbox, uint32_t required
if ((err = br->read(stream, &box)) != srs_success) {
return srs_error_wrap(err, "read box");
}
SrsBuffer* buffer = new SrsBuffer(stream->bytes(), stream->length());
SrsAutoFree(SrsBuffer, buffer);
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer(stream->bytes(), stream->length()));
// Decode the box:
// 1. Any box, when no box type is required.
// 2. Matched box, when box type match the required type.
// 3. Mdat box, always decode the mdat because we only decode the header of it.
if (!required_box_type || (uint32_t)box->type == required_box_type || box->is_mdat()) {
err = box->decode(buffer);
err = box->decode(buffer.get());
}
// Skip the box from stream, move stream to next box.
@ -5741,20 +5739,17 @@ srs_error_t SrsMp4Encoder::initialize(ISrsWriteSeeker* ws)
// Write ftyp box.
if (true) {
SrsMp4FileTypeBox* ftyp = new SrsMp4FileTypeBox();
SrsAutoFree(SrsMp4FileTypeBox, ftyp);
SrsUniquePtr<SrsMp4FileTypeBox> ftyp(new SrsMp4FileTypeBox());
ftyp->major_brand = SrsMp4BoxBrandISOM;
ftyp->minor_version = 512;
ftyp->set_compatible_brands(SrsMp4BoxBrandISOM, SrsMp4BoxBrandISO2, SrsMp4BoxBrandMP41);
int nb_data = ftyp->nb_bytes();
std::vector<char> data(nb_data);
SrsBuffer* buffer = new SrsBuffer(&data[0], nb_data);
SrsAutoFree(SrsBuffer, buffer);
if ((err = ftyp->encode(buffer)) != srs_success) {
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer(&data[0], nb_data));
if ((err = ftyp->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode ftyp");
}
@ -5766,16 +5761,13 @@ srs_error_t SrsMp4Encoder::initialize(ISrsWriteSeeker* ws)
// 8B reserved free box.
if (true) {
SrsMp4FreeSpaceBox* freeb = new SrsMp4FreeSpaceBox(SrsMp4BoxTypeFREE);
SrsAutoFree(SrsMp4FreeSpaceBox, freeb);
SrsUniquePtr<SrsMp4FreeSpaceBox> freeb(new SrsMp4FreeSpaceBox(SrsMp4BoxTypeFREE));
int nb_data = freeb->nb_bytes();
std::vector<char> data(nb_data);
SrsBuffer* buffer = new SrsBuffer(&data[0], nb_data);
SrsAutoFree(SrsBuffer, buffer);
if ((err = freeb->encode(buffer)) != srs_success) {
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer(&data[0], nb_data));
if ((err = freeb->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode free box");
}
@ -5789,27 +5781,23 @@ srs_error_t SrsMp4Encoder::initialize(ISrsWriteSeeker* ws)
// Write empty mdat box,
// its payload will be writen by samples,
// and we will update its header(size) when flush.
SrsMp4MediaDataBox* mdat = new SrsMp4MediaDataBox();
SrsAutoFree(SrsMp4MediaDataBox, mdat);
SrsUniquePtr<SrsMp4MediaDataBox> mdat(new SrsMp4MediaDataBox());
// Update the mdat box from this offset.
if ((err = wsio->lseek(0, SEEK_CUR, &mdat_offset)) != srs_success) {
return srs_error_wrap(err, "seek to mdat");
}
int nb_data = mdat->sz_header();
uint8_t* data = new uint8_t[nb_data];
SrsAutoFreeA(uint8_t, data);
SrsBuffer* buffer = new SrsBuffer((char*)data, nb_data);
SrsAutoFree(SrsBuffer, buffer);
if ((err = mdat->encode(buffer)) != srs_success) {
SrsUniquePtr<uint8_t[]> data(new uint8_t[nb_data]);
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer((char*)data.get(), nb_data));
if ((err = mdat->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode mdat");
}
// TODO: FIXME: Ensure all bytes are writen.
if ((err = wsio->write(data, nb_data, NULL)) != srs_success) {
if ((err = wsio->write(data.get(), nb_data, NULL)) != srs_success) {
return srs_error_wrap(err, "write mdat");
}
@ -5874,9 +5862,8 @@ srs_error_t SrsMp4Encoder::flush()
// Write moov.
if (true) {
SrsMp4MovieBox* moov = new SrsMp4MovieBox();
SrsAutoFree(SrsMp4MovieBox, moov);
SrsUniquePtr<SrsMp4MovieBox> moov(new SrsMp4MovieBox());
SrsMp4MovieHeaderBox* mvhd = new SrsMp4MovieHeaderBox();
moov->set_mvhd(mvhd);
@ -6057,23 +6044,20 @@ srs_error_t SrsMp4Encoder::flush()
}
}
if ((err = samples->write(moov)) != srs_success) {
if ((err = samples->write(moov.get())) != srs_success) {
return srs_error_wrap(err, "write samples");
}
int nb_data = moov->nb_bytes();
uint8_t* data = new uint8_t[nb_data];
SrsAutoFreeA(uint8_t, data);
SrsBuffer* buffer = new SrsBuffer((char*)data, nb_data);
SrsAutoFree(SrsBuffer, buffer);
if ((err = moov->encode(buffer)) != srs_success) {
SrsUniquePtr<uint8_t[]> data(new uint8_t[nb_data]);
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer((char*)data.get(), nb_data));
if ((err = moov->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode moov");
}
// TODO: FIXME: Ensure all bytes are writen.
if ((err = wsio->write(data, nb_data, NULL)) != srs_success) {
if ((err = wsio->write(data.get(), nb_data, NULL)) != srs_success) {
return srs_error_wrap(err, "write moov");
}
}
@ -6083,21 +6067,17 @@ srs_error_t SrsMp4Encoder::flush()
// Write mdat box with size of data,
// its payload already writen by samples,
// and we will update its header(size) when flush.
SrsMp4MediaDataBox* mdat = new SrsMp4MediaDataBox();
SrsAutoFree(SrsMp4MediaDataBox, mdat);
SrsUniquePtr<SrsMp4MediaDataBox> mdat(new SrsMp4MediaDataBox());
// Update the size of mdat first, for over 2GB file.
mdat->nb_data = mdat_bytes;
mdat->update_size();
int nb_data = mdat->sz_header();
uint8_t* data = new uint8_t[nb_data];
SrsAutoFreeA(uint8_t, data);
SrsBuffer* buffer = new SrsBuffer((char*)data, nb_data);
SrsAutoFree(SrsBuffer, buffer);
SrsUniquePtr<uint8_t[]> data(new uint8_t[nb_data]);
if ((err = mdat->encode(buffer)) != srs_success) {
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer((char*)data.get(), nb_data));
if ((err = mdat->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode mdat");
}
@ -6117,7 +6097,7 @@ srs_error_t SrsMp4Encoder::flush()
}
// TODO: FIXME: Ensure all bytes are writen.
if ((err = wsio->write(data, nb_data, NULL)) != srs_success) {
if ((err = wsio->write(data.get(), nb_data, NULL)) != srs_success) {
return srs_error_wrap(err, "write mdat");
}
}
@ -6231,22 +6211,20 @@ srs_error_t SrsMp4M2tsInitEncoder::write(SrsFormat* format, bool video, int tid)
// Write ftyp box.
if (true) {
SrsMp4FileTypeBox* ftyp = new SrsMp4FileTypeBox();
SrsAutoFree(SrsMp4FileTypeBox, ftyp);
SrsUniquePtr<SrsMp4FileTypeBox> ftyp(new SrsMp4FileTypeBox());
ftyp->major_brand = SrsMp4BoxBrandISO5;
ftyp->minor_version = 512;
ftyp->set_compatible_brands(SrsMp4BoxBrandISO6, SrsMp4BoxBrandMP41);
if ((err = srs_mp4_write_box(writer, ftyp)) != srs_success) {
if ((err = srs_mp4_write_box(writer, ftyp.get())) != srs_success) {
return srs_error_wrap(err, "write ftyp");
}
}
// Write moov.
if (true) {
SrsMp4MovieBox* moov = new SrsMp4MovieBox();
SrsAutoFree(SrsMp4MovieBox, moov);
SrsUniquePtr<SrsMp4MovieBox> moov(new SrsMp4MovieBox());
SrsMp4MovieHeaderBox* mvhd = new SrsMp4MovieHeaderBox();
moov->set_mvhd(mvhd);
@ -6456,7 +6434,7 @@ srs_error_t SrsMp4M2tsInitEncoder::write(SrsFormat* format, bool video, int tid)
trex->default_sample_description_index = 1;
}
if ((err = srs_mp4_write_box(writer, moov)) != srs_success) {
if ((err = srs_mp4_write_box(writer, moov.get())) != srs_success) {
return srs_error_wrap(err, "write moov");
}
}
@ -6492,9 +6470,8 @@ srs_error_t SrsMp4M2tsSegmentEncoder::initialize(ISrsWriter* w, uint32_t sequenc
// Write styp box.
if (true) {
SrsMp4SegmentTypeBox* styp = new SrsMp4SegmentTypeBox();
SrsAutoFree(SrsMp4SegmentTypeBox, styp);
SrsUniquePtr<SrsMp4SegmentTypeBox> styp(new SrsMp4SegmentTypeBox());
styp->major_brand = SrsMp4BoxBrandMSDH;
styp->minor_version = 0;
styp->set_compatible_brands(SrsMp4BoxBrandMSDH, SrsMp4BoxBrandMSIX);
@ -6502,7 +6479,7 @@ srs_error_t SrsMp4M2tsSegmentEncoder::initialize(ISrsWriter* w, uint32_t sequenc
// Used for sidx to calcalute the referenced size.
styp_bytes = styp->nb_bytes();
if ((err = srs_mp4_write_box(writer, styp)) != srs_success) {
if ((err = srs_mp4_write_box(writer, styp.get())) != srs_success) {
return srs_error_wrap(err, "write styp");
}
}
@ -6556,8 +6533,7 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
}
// Although the sidx is not required to start play DASH, but it's required for AV sync.
SrsMp4SegmentIndexBox* sidx = new SrsMp4SegmentIndexBox();
SrsAutoFree(SrsMp4SegmentIndexBox, sidx);
SrsUniquePtr<SrsMp4SegmentIndexBox> sidx(new SrsMp4SegmentIndexBox());
if (true) {
sidx->version = 1;
sidx->reference_id = 1;
@ -6580,14 +6556,12 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
// Create a mdat box.
// its payload will be writen by samples,
// and we will update its header(size) when flush.
SrsMp4MediaDataBox* mdat = new SrsMp4MediaDataBox();
SrsAutoFree(SrsMp4MediaDataBox, mdat);
SrsUniquePtr<SrsMp4MediaDataBox> mdat(new SrsMp4MediaDataBox());
// Write moof.
if (true) {
SrsMp4MovieFragmentBox* moof = new SrsMp4MovieFragmentBox();
SrsAutoFree(SrsMp4MovieFragmentBox, moof);
SrsUniquePtr<SrsMp4MovieFragmentBox> moof(new SrsMp4MovieFragmentBox());
SrsMp4MovieFragmentHeaderBox* mfhd = new SrsMp4MovieFragmentHeaderBox();
moof->set_mfhd(mfhd);
@ -6611,7 +6585,7 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
SrsMp4TrackFragmentRunBox* trun = new SrsMp4TrackFragmentRunBox();
traf->set_trun(trun);
if ((err = samples->write(moof, dts)) != srs_success) {
if ((err = samples->write(moof.get(), dts)) != srs_success) {
return srs_error_wrap(err, "write samples");
}
@ -6623,11 +6597,11 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
// Update the size of sidx.
SrsMp4SegmentIndexEntry* entry = &sidx->entries[0];
entry->referenced_size = moof_bytes + mdat->nb_bytes();
if ((err = srs_mp4_write_box(writer, sidx)) != srs_success) {
if ((err = srs_mp4_write_box(writer, sidx.get())) != srs_success) {
return srs_error_wrap(err, "write sidx");
}
if ((err = srs_mp4_write_box(writer, moof)) != srs_success) {
if ((err = srs_mp4_write_box(writer, moof.get())) != srs_success) {
return srs_error_wrap(err, "write moof");
}
}
@ -6635,18 +6609,15 @@ srs_error_t SrsMp4M2tsSegmentEncoder::flush(uint64_t& dts)
// Write mdat.
if (true) {
int nb_data = mdat->sz_header();
uint8_t* data = new uint8_t[nb_data];
SrsAutoFreeA(uint8_t, data);
SrsBuffer* buffer = new SrsBuffer((char*)data, nb_data);
SrsAutoFree(SrsBuffer, buffer);
if ((err = mdat->encode(buffer)) != srs_success) {
SrsUniquePtr<uint8_t[]> data(new uint8_t[nb_data]);
SrsUniquePtr<SrsBuffer> buffer(new SrsBuffer((char*)data.get(), nb_data));
if ((err = mdat->encode(buffer.get())) != srs_success) {
return srs_error_wrap(err, "encode mdat");
}
// TODO: FIXME: Ensure all bytes are writen.
if ((err = writer->write(data, nb_data, NULL)) != srs_success) {
if ((err = writer->write(data.get(), nb_data, NULL)) != srs_success) {
return srs_error_wrap(err, "write mdat");
}