2022-08-26 15:44:59 +00:00
|
|
|
// Copyright 2015 Google LLC. All rights reserved.
|
2015-10-28 17:23:08 +00:00
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
|
|
|
#include "packager/media/formats/webm/multi_segment_segmenter.h"
|
|
|
|
|
2022-12-17 05:40:00 +00:00
|
|
|
#include "mkvmuxer/mkvmuxer.h"
|
2015-10-28 17:23:08 +00:00
|
|
|
#include "packager/media/base/muxer_options.h"
|
|
|
|
#include "packager/media/base/muxer_util.h"
|
|
|
|
#include "packager/media/base/stream_info.h"
|
|
|
|
#include "packager/media/event/muxer_listener.h"
|
2022-12-17 05:40:00 +00:00
|
|
|
#include "packager/status/status_macros.h"
|
2015-10-28 17:23:08 +00:00
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2015-10-28 17:23:08 +00:00
|
|
|
namespace media {
|
|
|
|
namespace webm {
|
2017-02-24 01:17:47 +00:00
|
|
|
|
2015-10-28 17:23:08 +00:00
|
|
|
MultiSegmentSegmenter::MultiSegmentSegmenter(const MuxerOptions& options)
|
|
|
|
: Segmenter(options), num_segment_(0) {}
|
|
|
|
|
|
|
|
MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
|
|
|
|
|
2021-08-04 18:56:44 +00:00
|
|
|
Status MultiSegmentSegmenter::FinalizeSegment(int64_t start_timestamp,
|
|
|
|
int64_t duration_timestamp,
|
2017-02-24 01:17:47 +00:00
|
|
|
bool is_subsegment) {
|
|
|
|
CHECK(cluster());
|
2018-05-01 20:16:12 +00:00
|
|
|
RETURN_IF_ERROR(Segmenter::FinalizeSegment(
|
|
|
|
start_timestamp, duration_timestamp, is_subsegment));
|
2017-02-24 01:17:47 +00:00
|
|
|
if (!cluster()->Finalize())
|
|
|
|
return Status(error::FILE_FAILURE, "Error finalizing segment.");
|
2018-05-01 20:16:12 +00:00
|
|
|
|
2017-02-24 01:17:47 +00:00
|
|
|
if (!is_subsegment) {
|
2020-07-28 04:32:56 +00:00
|
|
|
std::string segment_name =
|
|
|
|
GetSegmentName(options().segment_template, start_timestamp,
|
|
|
|
num_segment_, options().bandwidth);
|
|
|
|
|
2018-05-01 20:16:12 +00:00
|
|
|
// Close the file, which also does flushing, to make sure the file is
|
|
|
|
// written before manifest is updated.
|
|
|
|
RETURN_IF_ERROR(writer_->Close());
|
|
|
|
|
2020-07-28 04:32:56 +00:00
|
|
|
if (!File::Copy(temp_file_name_.c_str(), segment_name.c_str()))
|
|
|
|
return Status(error::FILE_FAILURE, "Failure to copy memory file.");
|
|
|
|
|
|
|
|
if (!File::Delete(temp_file_name_.c_str()))
|
|
|
|
return Status(error::FILE_FAILURE, "Failure to delete memory file.");
|
|
|
|
|
|
|
|
num_segment_++;
|
|
|
|
|
2017-02-24 01:17:47 +00:00
|
|
|
if (muxer_listener()) {
|
|
|
|
const uint64_t size = cluster()->Size();
|
2018-05-01 20:16:12 +00:00
|
|
|
muxer_listener()->OnNewSegment(segment_name, start_timestamp,
|
|
|
|
duration_timestamp, size);
|
2017-02-24 01:17:47 +00:00
|
|
|
}
|
2020-07-28 04:32:56 +00:00
|
|
|
VLOG(1) << "WEBM file '" << segment_name << "' finalized.";
|
2017-02-24 01:17:47 +00:00
|
|
|
}
|
|
|
|
return Status::OK;
|
|
|
|
}
|
|
|
|
|
2022-12-17 05:40:00 +00:00
|
|
|
bool MultiSegmentSegmenter::GetInitRangeStartAndEnd(uint64_t* /*start*/,
|
|
|
|
uint64_t* /*end*/) {
|
2015-10-28 17:23:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-12-17 05:40:00 +00:00
|
|
|
bool MultiSegmentSegmenter::GetIndexRangeStartAndEnd(uint64_t* /*start*/,
|
|
|
|
uint64_t* /*end*/) {
|
2015-10-28 17:23:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-05-01 23:17:09 +00:00
|
|
|
std::vector<Range> MultiSegmentSegmenter::GetSegmentRanges() {
|
|
|
|
return std::vector<Range>();
|
|
|
|
}
|
|
|
|
|
2017-03-16 20:56:11 +00:00
|
|
|
Status MultiSegmentSegmenter::DoInitialize() {
|
|
|
|
std::unique_ptr<MkvWriter> writer(new MkvWriter);
|
|
|
|
Status status = writer->Open(options().output_file_name);
|
|
|
|
if (!status.ok())
|
|
|
|
return status;
|
2016-08-17 17:41:40 +00:00
|
|
|
writer_ = std::move(writer);
|
2015-10-28 17:23:08 +00:00
|
|
|
return WriteSegmentHeader(0, writer_.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
Status MultiSegmentSegmenter::DoFinalize() {
|
2018-05-01 20:16:12 +00:00
|
|
|
return Status::OK;
|
2015-10-28 17:23:08 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 18:56:44 +00:00
|
|
|
Status MultiSegmentSegmenter::NewSegment(int64_t start_timestamp,
|
2017-02-24 01:17:47 +00:00
|
|
|
bool is_subsegment) {
|
|
|
|
if (!is_subsegment) {
|
2020-07-28 04:32:56 +00:00
|
|
|
temp_file_name_ =
|
|
|
|
"memory://" + GetSegmentName(options().segment_template,
|
|
|
|
start_timestamp, num_segment_,
|
|
|
|
options().bandwidth);
|
|
|
|
|
2017-02-24 01:17:47 +00:00
|
|
|
writer_.reset(new MkvWriter);
|
2020-07-28 04:32:56 +00:00
|
|
|
Status status = writer_->Open(temp_file_name_);
|
|
|
|
|
2017-02-24 01:17:47 +00:00
|
|
|
if (!status.ok())
|
|
|
|
return status;
|
2015-10-28 17:23:08 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 18:56:44 +00:00
|
|
|
const int64_t start_timecode = FromBmffTimestamp(start_timestamp);
|
2017-05-13 00:02:12 +00:00
|
|
|
return SetCluster(start_timecode, 0, writer_.get());
|
2015-10-28 17:23:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace webm
|
|
|
|
} // namespace media
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|