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:
parent
79b3d184d3
commit
db418ab14e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -11,6 +11,7 @@
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "packager/base/strings/string_util.h"
|
#include "packager/base/strings/string_util.h"
|
||||||
#include "packager/file/file.h"
|
#include "packager/file/file.h"
|
||||||
|
#include "packager/file/file_closer.h"
|
||||||
#include "packager/media/base/buffer_writer.h"
|
#include "packager/media/base/buffer_writer.h"
|
||||||
#include "packager/media/base/muxer_options.h"
|
#include "packager/media/base/muxer_options.h"
|
||||||
#include "packager/media/base/muxer_util.h"
|
#include "packager/media/base/muxer_util.h"
|
||||||
|
@ -55,28 +56,15 @@ std::vector<Range> MultiSegmentSegmenter::GetSegmentRanges() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MultiSegmentSegmenter::DoInitialize() {
|
Status MultiSegmentSegmenter::DoInitialize() {
|
||||||
DCHECK(ftyp());
|
return WriteInitSegment();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MultiSegmentSegmenter::DoFinalize() {
|
Status MultiSegmentSegmenter::DoFinalize() {
|
||||||
|
// Update init segment with media duration set.
|
||||||
|
Status status = WriteInitSegment();
|
||||||
|
if (status.ok())
|
||||||
SetComplete();
|
SetComplete();
|
||||||
return Status::OK;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MultiSegmentSegmenter::DoFinalizeSegment() {
|
Status MultiSegmentSegmenter::DoFinalizeSegment() {
|
||||||
|
@ -140,29 +128,44 @@ Status MultiSegmentSegmenter::DoFinalizeSegment() {
|
||||||
return WriteSegment();
|
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() {
|
Status MultiSegmentSegmenter::WriteSegment() {
|
||||||
DCHECK(sidx());
|
DCHECK(sidx());
|
||||||
DCHECK(fragment_buffer());
|
DCHECK(fragment_buffer());
|
||||||
DCHECK(styp_);
|
DCHECK(styp_);
|
||||||
|
|
||||||
std::unique_ptr<BufferWriter> buffer(new BufferWriter());
|
std::unique_ptr<BufferWriter> buffer(new BufferWriter());
|
||||||
File* file;
|
std::unique_ptr<File, FileCloser> file;
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
if (options().segment_template.empty()) {
|
if (options().segment_template.empty()) {
|
||||||
// Append the segment to output file if segment template is not specified.
|
// Append the segment to output file if segment template is not specified.
|
||||||
file_name = options().output_file_name.c_str();
|
file_name = options().output_file_name.c_str();
|
||||||
file = File::Open(file_name.c_str(), "a");
|
file.reset(File::Open(file_name.c_str(), "a"));
|
||||||
if (file == NULL) {
|
if (!file) {
|
||||||
return Status(
|
return Status(error::FILE_FAILURE, "Cannot open file for append " +
|
||||||
error::FILE_FAILURE,
|
options().output_file_name);
|
||||||
"Cannot open file for append " + options().output_file_name);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file_name = GetSegmentName(options().segment_template,
|
file_name = GetSegmentName(options().segment_template,
|
||||||
sidx()->earliest_presentation_time,
|
sidx()->earliest_presentation_time,
|
||||||
num_segments_++, options().bandwidth);
|
num_segments_++, options().bandwidth);
|
||||||
file = File::Open(file_name.c_str(), "w");
|
file.reset(File::Open(file_name.c_str(), "w"));
|
||||||
if (file == NULL) {
|
if (!file) {
|
||||||
return Status(error::FILE_FAILURE,
|
return Status(error::FILE_FAILURE,
|
||||||
"Cannot open file for write " + file_name);
|
"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();
|
const size_t segment_size = segment_header_size + fragment_buffer()->Size();
|
||||||
DCHECK_NE(segment_size, 0u);
|
DCHECK_NE(segment_size, 0u);
|
||||||
|
|
||||||
Status status = buffer->WriteToFile(file);
|
Status status = buffer->WriteToFile(file.get());
|
||||||
if (status.ok()) {
|
if (status.ok()) {
|
||||||
if (muxer_listener()) {
|
if (muxer_listener()) {
|
||||||
for (const KeyFrameInfo& key_frame_info : key_frame_infos()) {
|
for (const KeyFrameInfo& key_frame_info : key_frame_infos()) {
|
||||||
|
@ -187,12 +190,9 @@ Status MultiSegmentSegmenter::WriteSegment() {
|
||||||
key_frame_info.size);
|
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())
|
if (!status.ok())
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ class MultiSegmentSegmenter : public Segmenter {
|
||||||
Status DoFinalizeSegment() override;
|
Status DoFinalizeSegment() override;
|
||||||
|
|
||||||
// Write segment to file.
|
// Write segment to file.
|
||||||
|
Status WriteInitSegment();
|
||||||
Status WriteSegment();
|
Status WriteSegment();
|
||||||
|
|
||||||
std::unique_ptr<SegmentType> styp_;
|
std::unique_ptr<SegmentType> styp_;
|
||||||
|
|
|
@ -101,7 +101,7 @@ Status Segmenter::Initialize(
|
||||||
Status Segmenter::Finalize() {
|
Status Segmenter::Finalize() {
|
||||||
// Set movie duration. Note that the duration in mvhd, tkhd, mdhd should not
|
// 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
|
// 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;
|
moov_->extends.header.fragment_duration = 0;
|
||||||
for (size_t i = 0; i < stream_durations_.size(); ++i) {
|
for (size_t i = 0; i < stream_durations_.size(); ++i) {
|
||||||
uint64_t duration =
|
uint64_t duration =
|
||||||
|
|
Loading…
Reference in New Issue