Close files in Finalize for WebM segmenters.
Now Finalize() will close all the files used by the segmenters. This is important to allow WebMMuxer::FireOnMediaEndEvent to get the correct size of the media file. This also changes the WebM muxer to use 64-bit numbers for the init and index ranges to correctly support >4GB files. b/28194272 Change-Id: Ia84e4a4b0756f89644efea99a1a51968b22a1338
This commit is contained in:
parent
b7f457e368
commit
2ef100e87d
|
@ -26,6 +26,14 @@ Status MkvWriter::Open(const std::string& name) {
|
|||
return Status::OK;
|
||||
}
|
||||
|
||||
Status MkvWriter::Close() {
|
||||
const std::string file_name = file_->file_name();
|
||||
if (!file_.release()->Close()) {
|
||||
return Status(error::FILE_FAILURE, "Cannot close file " + file_name);
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
mkvmuxer::int32 MkvWriter::Write(const void* buf, mkvmuxer::uint32 len) {
|
||||
DCHECK(file_);
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ class MkvWriter : public mkvmuxer::IMkvWriter {
|
|||
/// @param name The path to the file to open.
|
||||
/// @return Whether the operation succeeded.
|
||||
Status Open(const std::string& name);
|
||||
/// Closes the file. MUST call Open before calling any other methods.
|
||||
Status Close();
|
||||
|
||||
/// Writes out @a len bytes of @a buf.
|
||||
/// @return 0 on success.
|
||||
|
|
|
@ -21,13 +21,13 @@ MultiSegmentSegmenter::MultiSegmentSegmenter(const MuxerOptions& options)
|
|||
|
||||
MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
|
||||
|
||||
bool MultiSegmentSegmenter::GetInitRangeStartAndEnd(uint32_t* start,
|
||||
uint32_t* end) {
|
||||
bool MultiSegmentSegmenter::GetInitRangeStartAndEnd(uint64_t* start,
|
||||
uint64_t* end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MultiSegmentSegmenter::GetIndexRangeStartAndEnd(uint32_t* start,
|
||||
uint32_t* end) {
|
||||
bool MultiSegmentSegmenter::GetIndexRangeStartAndEnd(uint64_t* start,
|
||||
uint64_t* end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,9 @@ Status MultiSegmentSegmenter::DoInitialize(scoped_ptr<MkvWriter> writer) {
|
|||
}
|
||||
|
||||
Status MultiSegmentSegmenter::DoFinalize() {
|
||||
return FinalizeSegment();
|
||||
Status status = FinalizeSegment();
|
||||
status.Update(writer_->Close());
|
||||
return status;
|
||||
}
|
||||
|
||||
Status MultiSegmentSegmenter::FinalizeSegment() {
|
||||
|
|
|
@ -29,8 +29,8 @@ class MultiSegmentSegmenter : public Segmenter {
|
|||
|
||||
/// @name Segmenter implementation overrides.
|
||||
/// @{
|
||||
bool GetInitRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
||||
bool GetIndexRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
||||
bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||
bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -69,11 +69,11 @@ class Segmenter {
|
|||
|
||||
/// @return true if there is an initialization range, while setting @a start
|
||||
/// and @a end; or false if initialization range does not apply.
|
||||
virtual bool GetInitRangeStartAndEnd(uint32_t* start, uint32_t* end) = 0;
|
||||
virtual bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) = 0;
|
||||
|
||||
/// @return true if there is an index byte range, while setting @a start
|
||||
/// and @a end; or false if index byte range does not apply.
|
||||
virtual bool GetIndexRangeStartAndEnd(uint32_t* start, uint32_t* end) = 0;
|
||||
virtual bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) = 0;
|
||||
|
||||
/// @return The total length, in seconds, of segmented media files.
|
||||
float GetDuration() const;
|
||||
|
|
|
@ -36,11 +36,12 @@ Status SingleSegmentSegmenter::DoFinalize() {
|
|||
if (!cues()->Write(writer_.get()))
|
||||
return Status(error::FILE_FAILURE, "Error writing Cues data.");
|
||||
|
||||
uint64_t file_size = writer_->Position();
|
||||
// The WebM index is at the end of the file.
|
||||
index_end_ = writer_->Position() - 1;
|
||||
writer_->Position(0);
|
||||
|
||||
Status status = WriteSegmentHeader(file_size, writer_.get());
|
||||
writer_->Position(file_size);
|
||||
Status status = WriteSegmentHeader(index_end_ + 1, writer_.get());
|
||||
status.Update(writer_->Close());
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -66,8 +67,8 @@ Status SingleSegmentSegmenter::NewSegment(uint64_t start_timescale) {
|
|||
return SetCluster(start_webm_timecode, position, writer_.get());
|
||||
}
|
||||
|
||||
bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint32_t* start,
|
||||
uint32_t* end) {
|
||||
bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint64_t* start,
|
||||
uint64_t* end) {
|
||||
// The init range is the header, from the start of the file to the size of
|
||||
// the header.
|
||||
*start = 0;
|
||||
|
@ -75,12 +76,12 @@ bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint32_t* start,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SingleSegmentSegmenter::GetIndexRangeStartAndEnd(uint32_t* start,
|
||||
uint32_t* end) {
|
||||
bool SingleSegmentSegmenter::GetIndexRangeStartAndEnd(uint64_t* start,
|
||||
uint64_t* end) {
|
||||
// The index is the Cues element, which is always placed at the end of the
|
||||
// file.
|
||||
*start = index_start_;
|
||||
*end = writer_->file()->Size() - 1;
|
||||
*end = index_end_;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,14 +30,15 @@ class SingleSegmentSegmenter : public Segmenter {
|
|||
|
||||
/// @name Segmenter implementation overrides.
|
||||
/// @{
|
||||
bool GetInitRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
||||
bool GetIndexRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
||||
bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||
bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
MkvWriter* writer() { return writer_.get(); }
|
||||
void set_init_end(uint64_t end) { init_end_ = end; }
|
||||
void set_index_start(uint64_t start) { index_start_ = start; }
|
||||
void set_index_end(uint64_t end) { index_end_ = end; }
|
||||
void set_writer(scoped_ptr<MkvWriter> writer) { writer_ = writer.Pass(); }
|
||||
|
||||
// Segmenter implementation overrides.
|
||||
|
@ -50,8 +51,9 @@ class SingleSegmentSegmenter : public Segmenter {
|
|||
Status NewSegment(uint64_t start_timescale) override;
|
||||
|
||||
scoped_ptr<MkvWriter> writer_;
|
||||
uint32_t init_end_;
|
||||
uint32_t index_start_;
|
||||
uint64_t init_end_;
|
||||
uint64_t index_start_;
|
||||
uint64_t index_end_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SingleSegmentSegmenter);
|
||||
};
|
||||
|
|
|
@ -127,9 +127,9 @@ Status TwoPassSingleSegmentSegmenter::DoFinalize() {
|
|||
LOG(WARNING) << "Unable to delete temporary file " << temp_file_name_;
|
||||
}
|
||||
|
||||
// Set the writer back to the real file so GetIndexRangeStartAndEnd works.
|
||||
set_writer(real_writer_.Pass());
|
||||
return Status::OK;
|
||||
// The WebM index is at the end of the file.
|
||||
set_index_end(real_writer_->file()->Size() - 1);
|
||||
return real_writer_->Close();
|
||||
}
|
||||
|
||||
bool TwoPassSingleSegmentSegmenter::CopyFileWithClusterRewrite(
|
||||
|
|
|
@ -97,13 +97,13 @@ void WebMMuxer::FireOnMediaEndEvent() {
|
|||
if (!muxer_listener())
|
||||
return;
|
||||
|
||||
uint32_t init_range_start = 0;
|
||||
uint32_t init_range_end = 0;
|
||||
uint64_t init_range_start = 0;
|
||||
uint64_t init_range_end = 0;
|
||||
const bool has_init_range =
|
||||
segmenter_->GetInitRangeStartAndEnd(&init_range_start, &init_range_end);
|
||||
|
||||
uint32_t index_range_start = 0;
|
||||
uint32_t index_range_end = 0;
|
||||
uint64_t index_range_start = 0;
|
||||
uint64_t index_range_end = 0;
|
||||
const bool has_index_range = segmenter_->GetIndexRangeStartAndEnd(
|
||||
&index_range_start, &index_range_end);
|
||||
|
||||
|
|
Loading…
Reference in New Issue