Rewrite init segment in MultiSegmentSegmenter::DoFinalize

This is called when reaching end of the file of the media. The duration
of the media is updated.

Fixes #340.

Change-Id: I446f2d341b02125d4a7d8c958bda269b5403cb9c
This commit is contained in:
KongQun Yang 2018-03-05 09:44:22 -08:00
parent 76d68de6c1
commit b24a95b1aa
25 changed files with 34 additions and 33 deletions

View File

@ -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<Range> 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<BufferWriter> 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, FileCloser> 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<BufferWriter> 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<BufferWriter> buffer(new BufferWriter());
File* file;
std::unique_ptr<File, FileCloser> 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;

View File

@ -49,6 +49,7 @@ class MultiSegmentSegmenter : public Segmenter {
Status DoFinalizeSegment() override;
// Write segment to file.
Status WriteInitSegment();
Status WriteSegment();
std::unique_ptr<SegmentType> styp_;

View File

@ -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 =