7#include <packager/media/formats/packed_audio/packed_audio_writer.h>
15#include <absl/log/check.h>
17#include <packager/file.h>
18#include <packager/file/file_closer.h>
19#include <packager/macros/status.h>
20#include <packager/media/base/media_handler.h>
21#include <packager/media/base/muxer.h>
22#include <packager/media/base/muxer_options.h>
23#include <packager/media/base/muxer_util.h>
24#include <packager/media/base/range.h>
25#include <packager/media/event/muxer_listener.h>
26#include <packager/media/formats/packed_audio/packed_audio_segmenter.h>
27#include <packager/status.h>
33 :
Muxer(muxer_options),
34 transport_stream_timestamp_offset_(
35 muxer_options.transport_stream_timestamp_offset_ms *
36 kPackedAudioTimescale / 1000),
40PackedAudioWriter::~PackedAudioWriter() =
default;
42Status PackedAudioWriter::InitializeMuxer() {
43 if (streams().size() > 1u)
44 return Status(error::MUXER_FAILURE,
"Cannot handle more than one streams.");
46 RETURN_IF_ERROR(segmenter_->Initialize(*streams()[0]));
48 if (options().segment_template.empty()) {
50 DCHECK(!file_name.empty());
51 output_file_.reset(File::Open(file_name.c_str(),
"w"));
53 return Status(error::FILE_FAILURE,
54 "Cannot open file for write " + file_name);
58 if (muxer_listener()) {
59 muxer_listener()->
OnMediaStart(options(), *streams().front(),
60 kPackedAudioTimescale,
61 MuxerListener::kContainerPackedAudio);
66Status PackedAudioWriter::Finalize() {
68 RETURN_IF_ERROR(CloseFile(std::move(output_file_)));
70 if (muxer_listener()) {
72 media_ranges_, total_duration_ * segmenter_->TimescaleScale());
77Status PackedAudioWriter::AddMediaSample(
size_t stream_id,
78 const MediaSample& sample) {
79 DCHECK_EQ(stream_id, 0u);
80 return segmenter_->AddSample(sample);
83Status PackedAudioWriter::FinalizeSegment(
size_t stream_id,
84 const SegmentInfo& segment_info) {
85 DCHECK_EQ(stream_id, 0u);
87 if (segment_info.is_subsegment)
90 RETURN_IF_ERROR(segmenter_->FinalizeSegment());
92 const int64_t segment_timestamp =
93 segment_info.start_timestamp * segmenter_->TimescaleScale();
94 std::string segment_path =
97 : GetSegmentName(options().segment_template, segment_timestamp,
98 segment_info.segment_number, options().bandwidth);
101 const size_t segment_size = segmenter_->segment_buffer()->Size();
103 RETURN_IF_ERROR(WriteSegment(segment_path, segmenter_->segment_buffer()));
104 total_duration_ += segment_info.duration;
106 if (muxer_listener()) {
108 segment_path, segment_timestamp + transport_stream_timestamp_offset_,
109 segment_info.duration * segmenter_->TimescaleScale(), segment_size,
110 segment_info.segment_number);
115Status PackedAudioWriter::WriteSegment(
const std::string& segment_path,
116 BufferWriter* segment_buffer) {
117 std::unique_ptr<File, FileCloser> file;
124 range.end = range.start + segment_buffer->Size() - 1;
127 file.reset(File::Open(segment_path.c_str(),
"w"));
129 return Status(error::FILE_FAILURE,
130 "Cannot open file for write " + segment_path);
134 RETURN_IF_ERROR(segment_buffer->WriteToFile(output_file_ ? output_file_.get()
138 RETURN_IF_ERROR(CloseFile(std::move(file)));
142Status PackedAudioWriter::CloseFile(std::unique_ptr<File, FileCloser> file) {
143 std::string file_name = file->file_name();
144 if (!file.release()->Close()) {
147 "Cannot close file " + file_name +
148 ", possibly file permission issue or running out of disk space.");
All the methods that are virtual are virtual for mocking.