diff --git a/packager/app/test/testdata/bear-640x360-a-live-cenc-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-a-live-cenc-golden-init.mp4 index 8baf873921..3292cd0e8d 100644 Binary files a/packager/app/test/testdata/bear-640x360-a-live-cenc-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-a-live-cenc-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-golden-init.mp4 index e0d23b00ae..fd20d26f61 100644 Binary files a/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-no-pssh-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-no-pssh-golden-init.mp4 index e0d23b00ae..fd20d26f61 100644 Binary files a/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-no-pssh-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-a-live-cenc-rotation-no-pssh-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-a-live-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-a-live-golden-init.mp4 index a703e29da8..f725c309e7 100644 Binary files a/packager/app/test/testdata/bear-640x360-a-live-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-a-live-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 index 69d5615bdb..243f4297ec 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 index cfbd64015f..36cf45c94f 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-no-pssh-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-no-pssh-golden-init.mp4 index cfbd64015f..36cf45c94f 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-no-pssh-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-no-pssh-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 index b183dc5d1c..5ed12ec053 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 differ diff --git a/packager/media/formats/mp4/multi_segment_segmenter.cc b/packager/media/formats/mp4/multi_segment_segmenter.cc index 4d92f962fe..41d4ff723d 100644 --- a/packager/media/formats/mp4/multi_segment_segmenter.cc +++ b/packager/media/formats/mp4/multi_segment_segmenter.cc @@ -11,6 +11,7 @@ #include "packager/base/strings/string_number_conversions.h" #include "packager/base/strings/string_util.h" #include "packager/file/file.h" +#include "packager/file/file_closer.h" #include "packager/media/base/buffer_writer.h" #include "packager/media/base/muxer_options.h" #include "packager/media/base/muxer_util.h" @@ -55,28 +56,15 @@ std::vector MultiSegmentSegmenter::GetSegmentRanges() { } Status MultiSegmentSegmenter::DoInitialize() { - DCHECK(ftyp()); - DCHECK(moov()); - // Generate the output file with init segment. - File* file = File::Open(options().output_file_name.c_str(), "w"); - if (file == NULL) { - return Status(error::FILE_FAILURE, - "Cannot open file for write " + options().output_file_name); - } - std::unique_ptr buffer(new BufferWriter); - ftyp()->Write(buffer.get()); - moov()->Write(buffer.get()); - Status status = buffer->WriteToFile(file); - if (!file->Close()) { - LOG(WARNING) << "Failed to close the file properly: " - << options().output_file_name; - } - return status; + return WriteInitSegment(); } Status MultiSegmentSegmenter::DoFinalize() { - SetComplete(); - return Status::OK; + // Update init segment with media duration set. + Status status = WriteInitSegment(); + if (status.ok()) + SetComplete(); + return status; } Status MultiSegmentSegmenter::DoFinalizeSegment() { @@ -140,29 +128,44 @@ Status MultiSegmentSegmenter::DoFinalizeSegment() { return WriteSegment(); } +Status MultiSegmentSegmenter::WriteInitSegment() { + DCHECK(ftyp()); + DCHECK(moov()); + // Generate the output file with init segment. + std::unique_ptr file( + File::Open(options().output_file_name.c_str(), "w")); + if (!file) { + return Status(error::FILE_FAILURE, + "Cannot open file for write " + options().output_file_name); + } + std::unique_ptr buffer(new BufferWriter); + ftyp()->Write(buffer.get()); + moov()->Write(buffer.get()); + return buffer->WriteToFile(file.get()); +} + Status MultiSegmentSegmenter::WriteSegment() { DCHECK(sidx()); DCHECK(fragment_buffer()); DCHECK(styp_); std::unique_ptr buffer(new BufferWriter()); - File* file; + std::unique_ptr file; std::string file_name; if (options().segment_template.empty()) { // Append the segment to output file if segment template is not specified. file_name = options().output_file_name.c_str(); - file = File::Open(file_name.c_str(), "a"); - if (file == NULL) { - return Status( - error::FILE_FAILURE, - "Cannot open file for append " + options().output_file_name); + file.reset(File::Open(file_name.c_str(), "a")); + if (!file) { + return Status(error::FILE_FAILURE, "Cannot open file for append " + + options().output_file_name); } } else { file_name = GetSegmentName(options().segment_template, sidx()->earliest_presentation_time, num_segments_++, options().bandwidth); - file = File::Open(file_name.c_str(), "w"); - if (file == NULL) { + file.reset(File::Open(file_name.c_str(), "w")); + if (!file) { return Status(error::FILE_FAILURE, "Cannot open file for write " + file_name); } @@ -177,7 +180,7 @@ Status MultiSegmentSegmenter::WriteSegment() { const size_t segment_size = segment_header_size + fragment_buffer()->Size(); DCHECK_NE(segment_size, 0u); - Status status = buffer->WriteToFile(file); + Status status = buffer->WriteToFile(file.get()); if (status.ok()) { if (muxer_listener()) { for (const KeyFrameInfo& key_frame_info : key_frame_infos()) { @@ -187,12 +190,9 @@ Status MultiSegmentSegmenter::WriteSegment() { key_frame_info.size); } } - status = fragment_buffer()->WriteToFile(file); + status = fragment_buffer()->WriteToFile(file.get()); } - if (!file->Close()) - LOG(WARNING) << "Failed to close the file properly: " << file_name; - if (!status.ok()) return status; diff --git a/packager/media/formats/mp4/multi_segment_segmenter.h b/packager/media/formats/mp4/multi_segment_segmenter.h index 2309d24164..5fff12d6c3 100644 --- a/packager/media/formats/mp4/multi_segment_segmenter.h +++ b/packager/media/formats/mp4/multi_segment_segmenter.h @@ -49,6 +49,7 @@ class MultiSegmentSegmenter : public Segmenter { Status DoFinalizeSegment() override; // Write segment to file. + Status WriteInitSegment(); Status WriteSegment(); std::unique_ptr styp_; diff --git a/packager/media/formats/mp4/segmenter.cc b/packager/media/formats/mp4/segmenter.cc index 46345254f9..0df407d655 100644 --- a/packager/media/formats/mp4/segmenter.cc +++ b/packager/media/formats/mp4/segmenter.cc @@ -101,7 +101,7 @@ Status Segmenter::Initialize( Status Segmenter::Finalize() { // Set movie duration. Note that the duration in mvhd, tkhd, mdhd should not // be touched, i.e. kept at 0. The updated moov box will be written to output - // file for VOD case only. + // file for VOD and static live case only. moov_->extends.header.fragment_duration = 0; for (size_t i = 0; i < stream_durations_.size(); ++i) { uint64_t duration =