[WebM] Use system temp directory if temp_dir is not specified

The original code creates temporary file in the current directory,
which may not always be writable.

Change-Id: Icc278dd5db6be6206ae29defbb7423bae39cc978
This commit is contained in:
Kongqun Yang 2016-10-04 15:46:02 -07:00 committed by KongQun Yang
parent 472fae24f2
commit 6dbcf27f82
7 changed files with 94 additions and 60 deletions

View File

@ -15,6 +15,8 @@
'sources': [ 'sources': [
'file.cc', 'file.cc',
'file.h', 'file.h',
'file_util.cc',
'file_util.h',
'file_closer.h', 'file_closer.h',
'io_cache.cc', 'io_cache.cc',
'io_cache.h', 'io_cache.h',
@ -48,6 +50,7 @@
'type': '<(gtest_target_type)', 'type': '<(gtest_target_type)',
'sources': [ 'sources': [
'file_unittest.cc', 'file_unittest.cc',
'file_util_unittest.cc',
'io_cache_unittest.cc', 'io_cache_unittest.cc',
'memory_file_unittest.cc', 'memory_file_unittest.cc',
], ],

View File

@ -0,0 +1,44 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// 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/file/file_util.h"
#include <inttypes.h>
#include "packager/base/files/file_path.h"
#include "packager/base/files/file_util.h"
#include "packager/base/strings/stringprintf.h"
#include "packager/base/threading/platform_thread.h"
#include "packager/base/time/time.h"
namespace shaka {
namespace {
// Create a temp file name using process/thread id and current time.
std::string TempFileName() {
const int32_t tid = static_cast<int32_t>(base::PlatformThread::CurrentId());
const int64_t current_time = base::Time::Now().ToInternalValue();
return base::StringPrintf("packager-tempfile-%x-%" PRIx64, tid, current_time);
}
} // namespace
bool TempFilePath(const std::string& temp_dir, std::string* temp_file_path) {
if (temp_dir.empty()) {
base::FilePath file_path;
if (!base::CreateTemporaryFile(&file_path)) {
LOG(ERROR) << "Failed to create temporary file.";
return false;
}
*temp_file_path = file_path.AsUTF8Unsafe();
} else {
*temp_file_path =
base::FilePath::FromUTF8Unsafe(temp_dir)
.Append(base::FilePath::FromUTF8Unsafe(TempFileName()))
.AsUTF8Unsafe();
}
return true;
}
} // namespace shaka

View File

@ -0,0 +1,18 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// 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 <string>
namespace shaka {
/// Create a temp file name in directory @a temp_dir. Generate the temp file
/// in os specific temporary directory if @a temp_dir is empty.
/// @param temp_dir specifies the directory where the file should go.
/// @param temp_file_path is the result temp file path on success.
/// @returns true on success, false otherwise.
bool TempFilePath(const std::string& temp_dir, std::string* temp_file_path);
} // namespace shaka

View File

@ -0,0 +1,22 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// 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/file/file_util.h"
#include <gtest/gtest.h>
namespace shaka {
TEST(FileUtilTest, Basic) {
std::string temp_file_path;
EXPECT_TRUE(TempFilePath("test", &temp_file_path));
EXPECT_EQ(temp_file_path.find("test"), 0u);
EXPECT_TRUE(TempFilePath("", &temp_file_path));
// temp_file_path should be created in a system specific temp directory.
}
} // namespace shaka

View File

@ -6,38 +6,18 @@
#include "packager/media/formats/mp4/single_segment_segmenter.h" #include "packager/media/formats/mp4/single_segment_segmenter.h"
#include <inttypes.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "packager/base/files/file_util.h"
#include "packager/base/strings/stringprintf.h"
#include "packager/base/threading/platform_thread.h"
#include "packager/base/time/time.h"
#include "packager/media/base/buffer_writer.h" #include "packager/media/base/buffer_writer.h"
#include "packager/media/base/media_stream.h" #include "packager/media/base/media_stream.h"
#include "packager/media/base/muxer_options.h" #include "packager/media/base/muxer_options.h"
#include "packager/media/event/muxer_listener.h" #include "packager/media/event/muxer_listener.h"
#include "packager/media/event/progress_listener.h" #include "packager/media/event/progress_listener.h"
#include "packager/media/file/file.h" #include "packager/media/file/file.h"
#include "packager/media/file/file_util.h"
#include "packager/media/formats/mp4/box_definitions.h" #include "packager/media/formats/mp4/box_definitions.h"
namespace shaka { namespace shaka {
namespace media { namespace media {
namespace mp4 { namespace mp4 {
namespace {
// Create a temp file name using process/thread id and current time.
std::string TempFileName() {
int32_t tid = static_cast<int32_t>(base::PlatformThread::CurrentId());
int64_t rand = 0;
if (RAND_bytes(reinterpret_cast<uint8_t*>(&rand), sizeof(rand)) != 1) {
LOG(WARNING) << "RAND_bytes failed with error: "
<< ERR_error_string(ERR_get_error(), NULL);
rand = base::Time::Now().ToInternalValue();
}
return base::StringPrintf("packager-tempfile-%x-%" PRIx64, tid, rand);
}
} // namespace
SingleSegmentSegmenter::SingleSegmentSegmenter(const MuxerOptions& options, SingleSegmentSegmenter::SingleSegmentSegmenter(const MuxerOptions& options,
std::unique_ptr<FileType> ftyp, std::unique_ptr<FileType> ftyp,
@ -77,18 +57,8 @@ Status SingleSegmentSegmenter::DoInitialize() {
// progress_target was set for stage 1. Times two to account for stage 2. // progress_target was set for stage 1. Times two to account for stage 2.
set_progress_target(progress_target() * 2); set_progress_target(progress_target() * 2);
if (options().temp_dir.empty()) { if (!TempFilePath(options().temp_dir, &temp_file_name_))
base::FilePath temp_file_path; return Status(error::FILE_FAILURE, "Unable to create temporary file.");
if (!base::CreateTemporaryFile(&temp_file_path)) {
LOG(ERROR) << "Failed to create temporary file.";
return Status(error::FILE_FAILURE, "Unable to create temporary file.");
}
temp_file_name_ = temp_file_path.AsUTF8Unsafe();
} else {
temp_file_name_ =
base::FilePath::FromUTF8Unsafe(options().temp_dir)
.Append(base::FilePath::FromUTF8Unsafe(TempFileName())).AsUTF8Unsafe();
}
temp_file_.reset(File::Open(temp_file_name_.c_str(), "w")); temp_file_.reset(File::Open(temp_file_name_.c_str(), "w"));
return temp_file_ return temp_file_
? Status::OK ? Status::OK

View File

@ -52,8 +52,7 @@ bool SeekHead::Write(mkvmuxer::IMkvWriter* writer) {
uint64_t payload_size = 0; uint64_t payload_size = 0;
for (const SeekHead::SeekElement& seek_element : seek_elements) { for (const SeekHead::SeekElement& seek_element : seek_elements) {
payload_size += payload_size +=
seek_element.size + EbmlMasterElementWithPayloadSize(mkvmuxer::kMkvSeek, seek_element.size);
EbmlMasterElementSize(mkvmuxer::kMkvSeek, seek_element.size);
} }
const int64_t start_pos = writer->Position(); const int64_t start_pos = writer->Position();

View File

@ -6,20 +6,13 @@
#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h" #include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
#include <inttypes.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <algorithm> #include <algorithm>
#include "packager/base/files/file_path.h"
#include "packager/base/strings/stringprintf.h"
#include "packager/base/threading/platform_thread.h"
#include "packager/base/time/time.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
#include "packager/media/base/media_stream.h" #include "packager/media/base/media_stream.h"
#include "packager/media/base/muxer_options.h" #include "packager/media/base/muxer_options.h"
#include "packager/media/base/stream_info.h" #include "packager/media/base/stream_info.h"
#include "packager/media/file/file_util.h"
#include "packager/third_party/libwebm/src/mkvmuxer.hpp" #include "packager/third_party/libwebm/src/mkvmuxer.hpp"
#include "packager/third_party/libwebm/src/mkvmuxerutil.hpp" #include "packager/third_party/libwebm/src/mkvmuxerutil.hpp"
#include "packager/third_party/libwebm/src/webmids.hpp" #include "packager/third_party/libwebm/src/webmids.hpp"
@ -48,22 +41,6 @@ uint64_t UpdateCues(mkvmuxer::Cues* cues) {
return cues_size; return cues_size;
} }
/// Create the temp file name using process/thread id and current time.
std::string TempFileName(const MuxerOptions& options) {
// TODO: Move to a common util function and remove other uses.
int32_t tid = static_cast<int32_t>(base::PlatformThread::CurrentId());
int64_t rand = 0;
if (RAND_bytes(reinterpret_cast<uint8_t*>(&rand), sizeof(rand)) != 1) {
LOG(WARNING) << "RAND_bytes failed with error: "
<< ERR_error_string(ERR_get_error(), NULL);
rand = base::Time::Now().ToInternalValue();
}
std::string file_prefix =
base::StringPrintf("packager-tempfile-%x-%" PRIx64 ".tmp", tid, rand);
return base::FilePath::FromUTF8Unsafe(options.temp_dir).Append(
base::FilePath::FromUTF8Unsafe(file_prefix)).AsUTF8Unsafe();
}
// Skips a given number of bytes in a file by reading. This allows // Skips a given number of bytes in a file by reading. This allows
// forward-seeking in non-seekable files. // forward-seeking in non-seekable files.
bool ReadSkip(File* file, int64_t byte_count) { bool ReadSkip(File* file, int64_t byte_count) {
@ -100,7 +77,8 @@ Status TwoPassSingleSegmentSegmenter::DoInitialize(
real_writer_ = std::move(writer); real_writer_ = std::move(writer);
temp_file_name_ = TempFileName(options()); if (!TempFilePath(options().temp_dir, &temp_file_name_))
return Status(error::FILE_FAILURE, "Unable to create temporary file.");
std::unique_ptr<MkvWriter> temp(new MkvWriter); std::unique_ptr<MkvWriter> temp(new MkvWriter);
Status status = temp->Open(temp_file_name_); Status status = temp->Open(temp_file_name_);
if (!status.ok()) if (!status.ok())