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
a50b5787dc
commit
a80e16bab0
|
@ -26,6 +26,14 @@ Status MkvWriter::Open(const std::string& name) {
|
||||||
return Status::OK;
|
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) {
|
mkvmuxer::int32 MkvWriter::Write(const void* buf, mkvmuxer::uint32 len) {
|
||||||
DCHECK(file_);
|
DCHECK(file_);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ class MkvWriter : public mkvmuxer::IMkvWriter {
|
||||||
/// @param name The path to the file to open.
|
/// @param name The path to the file to open.
|
||||||
/// @return Whether the operation succeeded.
|
/// @return Whether the operation succeeded.
|
||||||
Status Open(const std::string& name);
|
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.
|
/// Writes out @a len bytes of @a buf.
|
||||||
/// @return 0 on success.
|
/// @return 0 on success.
|
||||||
|
|
|
@ -21,13 +21,13 @@ MultiSegmentSegmenter::MultiSegmentSegmenter(const MuxerOptions& options)
|
||||||
|
|
||||||
MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
|
MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
|
||||||
|
|
||||||
bool MultiSegmentSegmenter::GetInitRangeStartAndEnd(uint32_t* start,
|
bool MultiSegmentSegmenter::GetInitRangeStartAndEnd(uint64_t* start,
|
||||||
uint32_t* end) {
|
uint64_t* end) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultiSegmentSegmenter::GetIndexRangeStartAndEnd(uint32_t* start,
|
bool MultiSegmentSegmenter::GetIndexRangeStartAndEnd(uint64_t* start,
|
||||||
uint32_t* end) {
|
uint64_t* end) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@ Status MultiSegmentSegmenter::DoInitialize(scoped_ptr<MkvWriter> writer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MultiSegmentSegmenter::DoFinalize() {
|
Status MultiSegmentSegmenter::DoFinalize() {
|
||||||
return FinalizeSegment();
|
Status status = FinalizeSegment();
|
||||||
|
status.Update(writer_->Close());
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MultiSegmentSegmenter::FinalizeSegment() {
|
Status MultiSegmentSegmenter::FinalizeSegment() {
|
||||||
|
|
|
@ -29,8 +29,8 @@ class MultiSegmentSegmenter : public Segmenter {
|
||||||
|
|
||||||
/// @name Segmenter implementation overrides.
|
/// @name Segmenter implementation overrides.
|
||||||
/// @{
|
/// @{
|
||||||
bool GetInitRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||||
bool GetIndexRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -69,11 +69,11 @@ class Segmenter {
|
||||||
|
|
||||||
/// @return true if there is an initialization range, while setting @a start
|
/// @return true if there is an initialization range, while setting @a start
|
||||||
/// and @a end; or false if initialization range does not apply.
|
/// 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
|
/// @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.
|
/// 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.
|
/// @return The total length, in seconds, of segmented media files.
|
||||||
float GetDuration() const;
|
float GetDuration() const;
|
||||||
|
|
|
@ -36,11 +36,12 @@ Status SingleSegmentSegmenter::DoFinalize() {
|
||||||
if (!cues()->Write(writer_.get()))
|
if (!cues()->Write(writer_.get()))
|
||||||
return Status(error::FILE_FAILURE, "Error writing Cues data.");
|
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);
|
writer_->Position(0);
|
||||||
|
|
||||||
Status status = WriteSegmentHeader(file_size, writer_.get());
|
Status status = WriteSegmentHeader(index_end_ + 1, writer_.get());
|
||||||
writer_->Position(file_size);
|
status.Update(writer_->Close());
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +67,8 @@ Status SingleSegmentSegmenter::NewSegment(uint64_t start_timescale) {
|
||||||
return SetCluster(start_webm_timecode, position, writer_.get());
|
return SetCluster(start_webm_timecode, position, writer_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint32_t* start,
|
bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint64_t* start,
|
||||||
uint32_t* end) {
|
uint64_t* end) {
|
||||||
// The init range is the header, from the start of the file to the size of
|
// The init range is the header, from the start of the file to the size of
|
||||||
// the header.
|
// the header.
|
||||||
*start = 0;
|
*start = 0;
|
||||||
|
@ -75,12 +76,12 @@ bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint32_t* start,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleSegmentSegmenter::GetIndexRangeStartAndEnd(uint32_t* start,
|
bool SingleSegmentSegmenter::GetIndexRangeStartAndEnd(uint64_t* start,
|
||||||
uint32_t* end) {
|
uint64_t* end) {
|
||||||
// The index is the Cues element, which is always placed at the end of the
|
// The index is the Cues element, which is always placed at the end of the
|
||||||
// file.
|
// file.
|
||||||
*start = index_start_;
|
*start = index_start_;
|
||||||
*end = writer_->file()->Size() - 1;
|
*end = index_end_;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,15 @@ class SingleSegmentSegmenter : public Segmenter {
|
||||||
|
|
||||||
/// @name Segmenter implementation overrides.
|
/// @name Segmenter implementation overrides.
|
||||||
/// @{
|
/// @{
|
||||||
bool GetInitRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||||
bool GetIndexRangeStartAndEnd(uint32_t* start, uint32_t* end) override;
|
bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MkvWriter* writer() { return writer_.get(); }
|
MkvWriter* writer() { return writer_.get(); }
|
||||||
void set_init_end(uint64_t end) { init_end_ = end; }
|
void set_init_end(uint64_t end) { init_end_ = end; }
|
||||||
void set_index_start(uint64_t start) { index_start_ = start; }
|
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(); }
|
void set_writer(scoped_ptr<MkvWriter> writer) { writer_ = writer.Pass(); }
|
||||||
|
|
||||||
// Segmenter implementation overrides.
|
// Segmenter implementation overrides.
|
||||||
|
@ -50,8 +51,9 @@ class SingleSegmentSegmenter : public Segmenter {
|
||||||
Status NewSegment(uint64_t start_timescale) override;
|
Status NewSegment(uint64_t start_timescale) override;
|
||||||
|
|
||||||
scoped_ptr<MkvWriter> writer_;
|
scoped_ptr<MkvWriter> writer_;
|
||||||
uint32_t init_end_;
|
uint64_t init_end_;
|
||||||
uint32_t index_start_;
|
uint64_t index_start_;
|
||||||
|
uint64_t index_end_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(SingleSegmentSegmenter);
|
DISALLOW_COPY_AND_ASSIGN(SingleSegmentSegmenter);
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,9 +127,9 @@ Status TwoPassSingleSegmentSegmenter::DoFinalize() {
|
||||||
LOG(WARNING) << "Unable to delete temporary file " << temp_file_name_;
|
LOG(WARNING) << "Unable to delete temporary file " << temp_file_name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the writer back to the real file so GetIndexRangeStartAndEnd works.
|
// The WebM index is at the end of the file.
|
||||||
set_writer(real_writer_.Pass());
|
set_index_end(real_writer_->file()->Size() - 1);
|
||||||
return Status::OK;
|
return real_writer_->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwoPassSingleSegmentSegmenter::CopyFileWithClusterRewrite(
|
bool TwoPassSingleSegmentSegmenter::CopyFileWithClusterRewrite(
|
||||||
|
|
|
@ -97,13 +97,13 @@ void WebMMuxer::FireOnMediaEndEvent() {
|
||||||
if (!muxer_listener())
|
if (!muxer_listener())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t init_range_start = 0;
|
uint64_t init_range_start = 0;
|
||||||
uint32_t init_range_end = 0;
|
uint64_t init_range_end = 0;
|
||||||
const bool has_init_range =
|
const bool has_init_range =
|
||||||
segmenter_->GetInitRangeStartAndEnd(&init_range_start, &init_range_end);
|
segmenter_->GetInitRangeStartAndEnd(&init_range_start, &init_range_end);
|
||||||
|
|
||||||
uint32_t index_range_start = 0;
|
uint64_t index_range_start = 0;
|
||||||
uint32_t index_range_end = 0;
|
uint64_t index_range_end = 0;
|
||||||
const bool has_index_range = segmenter_->GetIndexRangeStartAndEnd(
|
const bool has_index_range = segmenter_->GetIndexRangeStartAndEnd(
|
||||||
&index_range_start, &index_range_end);
|
&index_range_start, &index_range_end);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue