From ce5531cbf81159634ac811baaa3eb2d8efd221e4 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Wed, 27 Mar 2024 20:55:14 +0200 Subject: [PATCH] Add timed text init packaging --- include/packager/live_packager.h | 3 +- include/packager/live_packager_export.h | 7 ++ packager/live_packager.cc | 16 ++-- packager/live_packager_export.cc | 26 ++++++- packager/live_packager_test.cc | 98 ++++++++++++------------- 5 files changed, 92 insertions(+), 58 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index 4ebf2a6651..bf062f1984 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -35,6 +35,7 @@ class SegmentData final : public Segment { class SegmentBuffer final : public Segment { public: SegmentBuffer() = default; + SegmentBuffer(const uint8_t* data, size_t size); ~SegmentBuffer() = default; void AppendData(const uint8_t* data, size_t size); @@ -140,7 +141,7 @@ class LivePackager { const Segment& media_segment, SegmentBuffer& output); - Status PackageTimedText(const Segment& media_segment, SegmentBuffer& output); + Status PackageTimedText(const Segment& media_segment, FullSegmentBuffer& output); LivePackager(const LivePackager&) = delete; LivePackager& operator=(const LivePackager&) = delete; diff --git a/include/packager/live_packager_export.h b/include/packager/live_packager_export.h index 611cff0e99..17e31dec25 100644 --- a/include/packager/live_packager_export.h +++ b/include/packager/live_packager_export.h @@ -82,12 +82,19 @@ bool livepackager_package_init(LivePackager_t lp, uint8_t* init, size_t init_len, LivePackagerBuffer_t dest); + bool livepackager_package(LivePackager_t lp, uint8_t* init, size_t init_len, uint8_t* media, size_t media_len, LivePackagerBuffer_t dest); + +bool livepackager_package_timedtext_init(LivePackager_t lp, + uint8_t* seg, + size_t seg_len, + LivePackagerBuffer_t dest); + bool livepackager_package_timedtext(LivePackager_t lp, uint8_t* seg, size_t seg_len, diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 64d1889d9c..781a862144 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -226,6 +226,9 @@ size_t SegmentData::Size() const { return size_; } +SegmentBuffer::SegmentBuffer(const uint8_t* data, size_t size) + : buffer_(data, data + size) {} + void SegmentBuffer::AppendData(const uint8_t* data, size_t size) { std::copy(data, data + size, std::back_inserter(buffer_)); } @@ -414,7 +417,8 @@ Status LivePackager::Package(const Segment& init_segment, return packager.Run(); } -Status LivePackager::PackageTimedText(const Segment& in, SegmentBuffer& out) { +Status LivePackager::PackageTimedText(const Segment& in, + FullSegmentBuffer& out) { SegmentDataReader reader(in); shaka::BufferCallbackParams callback_params; callback_params.read_func = [&reader](const std::string& name, void* buffer, @@ -429,11 +433,11 @@ Status LivePackager::PackageTimedText(const Segment& in, SegmentBuffer& out) { }; shaka::BufferCallbackParams init_callback_params; - init_callback_params.write_func = [](const std::string& name, - const void* data, uint64_t size) { - // if (out.InitSegmentSize() == 0) { - // out.SetInitSegment(reinterpret_cast(data), size); - // } + init_callback_params.write_func = [&out](const std::string& name, + const void* data, uint64_t size) { + if (out.InitSegmentSize() == 0) { + out.SetInitSegment(reinterpret_cast(data), size); + } return size; }; diff --git a/packager/live_packager_export.cc b/packager/live_packager_export.cc index b3bcf6be50..a25da0acd9 100644 --- a/packager/live_packager_export.cc +++ b/packager/live_packager_export.cc @@ -1,6 +1,8 @@ #include #include +#include + struct LivePackager_instance_s { std::unique_ptr inner; }; @@ -73,10 +75,32 @@ bool livepackager_package(LivePackager_t lp, return lp->inner->Package(input_init, input_media, *dest->inner).ok(); } +bool livepackager_package_timedtext_init(LivePackager_t lp, + uint8_t* seg, + size_t seg_len, + LivePackagerBuffer_t dest) { + shaka::SegmentData input_seg(seg, seg_len); + shaka::FullSegmentBuffer out; + if (!lp->inner->PackageTimedText(input_seg, out).ok()) { + return false; + } + + dest->inner = std::make_unique(out.InitSegmentData(), + out.InitSegmentSize()); + return true; +} + bool livepackager_package_timedtext(LivePackager_t lp, uint8_t* seg, size_t seg_len, LivePackagerBuffer_t dest) { shaka::SegmentData input_seg(seg, seg_len); - return lp->inner->PackageTimedText(input_seg, *dest->inner).ok(); + shaka::FullSegmentBuffer out; + if (!lp->inner->PackageTimedText(input_seg, out).ok()) { + return false; + } + + dest->inner = std::make_unique(out.SegmentData(), + out.SegmentSize()); + return true; } \ No newline at end of file diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index e049348111..e8ad4295a3 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -313,46 +313,45 @@ void CheckVideoInitSegment(const SegmentBuffer& buffer, media::FourCC format) { } } -// TODO(sasha): must be used when PackageTimedTextInit is added. -// void CheckTextInitSegment(const FullSegmentBuffer& buffer, -// media::FourCC handler, -// media::FourCC format) { -// bool err(true); -// size_t bytes_to_read(buffer.InitSegmentSize()); -// const uint8_t* data(buffer.InitSegmentData()); -// -// { -// std::unique_ptr reader( -// media::mp4::BoxReader::ReadBox(data, bytes_to_read, &err)); -// EXPECT_FALSE(err); -// -// FileTypeBoxChecker checker; -// checker.Check(reader.get()); -// -// data += reader->size(); -// bytes_to_read -= reader->size(); -// } -// -// { -// std::unique_ptr reader( -// media::mp4::BoxReader::ReadBox(data, bytes_to_read, &err)); -// EXPECT_FALSE(err); -// -// media::mp4::TextSampleEntry entry; -// entry.format = format; -// -// media::mp4::Track track; -// track.media.handler.handler_type = handler; -// track.media.information.sample_table.description.text_entries.push_back( -// entry); -// -// media::mp4::Movie expected; -// expected.tracks.push_back(track); -// -// MovieBoxChecker checker(expected); -// checker.Check(reader.get()); -// } -// } +void CheckTextInitSegment(const FullSegmentBuffer& buffer, + media::FourCC handler, + media::FourCC format) { + bool err(true); + size_t bytes_to_read(buffer.InitSegmentSize()); + const uint8_t* data(buffer.InitSegmentData()); + + { + std::unique_ptr reader( + media::mp4::BoxReader::ReadBox(data, bytes_to_read, &err)); + EXPECT_FALSE(err); + + FileTypeBoxChecker checker; + checker.Check(reader.get()); + + data += reader->size(); + bytes_to_read -= reader->size(); + } + + { + std::unique_ptr reader( + media::mp4::BoxReader::ReadBox(data, bytes_to_read, &err)); + EXPECT_FALSE(err); + + media::mp4::TextSampleEntry entry; + entry.format = format; + + media::mp4::Track track; + track.media.handler.handler_type = handler; + track.media.information.sample_table.description.text_entries.push_back( + entry); + + media::mp4::Movie expected; + expected.tracks.push_back(track); + + MovieBoxChecker checker(expected); + checker.Check(reader.get()); + } +} void CheckSegment(const LiveConfig& config, const SegmentBuffer& buffer, @@ -1030,7 +1029,7 @@ TEST_P(TimedTextParameterizedTest, VerifyTimedText) { ASSERT_FALSE(segment_buffer.empty()); SegmentData media_seg(segment_buffer.data(), segment_buffer.size()); - SegmentBuffer out; + FullSegmentBuffer out; LiveConfig live_config; live_config.protection_scheme = LiveConfig::EncryptionScheme::NONE; @@ -1047,17 +1046,15 @@ TEST_P(TimedTextParameterizedTest, VerifyTimedText) { ASSERT_EQ(GetParam().expected_status, live_packager_->PackageTimedText(media_seg, out)); if (GetParam().expected_status == Status::OK) { - ASSERT_GT(out.Size(), 0); + ASSERT_GT(out.SegmentSize(), 0); if (live_config.format == LiveConfig::OutputFormat::VTTMP4 || live_config.format == LiveConfig::OutputFormat::TTMLMP4) { - CheckSegment(live_config, out, 1000, true); + SegmentBuffer seg(out.SegmentData(), out.SegmentSize()); + CheckSegment(live_config, seg, 1000, true); - // TODO(sasha): must be checked separately when PackageTimedTextInit is - // added. - // if (i == 0) { - // CheckTextInitSegment(out, GetParam().handler_type, - // GetParam().format); - //} + if (i == 0) { + CheckTextInitSegment(out, GetParam().handler_type, GetParam().format); + } std::string expected_fname; ASSERT_TRUE(FormatWithIndex(GetParam().expected_segment_format, i + 1, @@ -1066,7 +1063,8 @@ TEST_P(TimedTextParameterizedTest, VerifyTimedText) { std::vector expected_buf(ReadTestDataFile(expected_fname)); ASSERT_FALSE(expected_buf.empty()); - std::vector actual_buf(out.Data(), out.Data() + out.Size()); + std::vector actual_buf(out.SegmentData(), + out.SegmentData() + out.SegmentSize()); ASSERT_EQ(expected_buf, actual_buf); } }