7 #include "packager/media/file/file.h"
9 #include <gflags/gflags.h>
12 #include "packager/base/logging.h"
13 #include "packager/base/strings/string_util.h"
14 #include "packager/media/file/local_file.h"
15 #include "packager/media/file/memory_file.h"
16 #include "packager/media/file/threaded_io_file.h"
17 #include "packager/media/file/udp_file.h"
19 DEFINE_uint64(io_cache_size,
21 "Size of the threaded I/O cache, in bytes. Specify 0 to disable "
23 DEFINE_uint64(io_block_size,
25 "Size of the block size used for threaded I/O, in bytes.");
35 const char* kLocalFilePrefix =
"file://";
36 const char* kUdpFilePrefix =
"udp://";
37 const char* kMemoryFilePrefix =
"memory://";
41 typedef File* (*FileFactoryFunction)(
const char* file_name,
const char* mode);
42 typedef bool (*FileDeleteFunction)(
const char* file_name);
44 struct SupportedTypeInfo {
47 const FileFactoryFunction factory_function;
48 const FileDeleteFunction delete_function;
51 File* CreateLocalFile(
const char* file_name,
const char* mode) {
52 return new LocalFile(file_name, mode);
55 bool DeleteLocalFile(
const char* file_name) {
59 File* CreateUdpFile(
const char* file_name,
const char* mode) {
60 if (base::strcasecmp(mode,
"r")) {
61 NOTIMPLEMENTED() <<
"UdpFile only supports read (receive) mode.";
64 return new UdpFile(file_name);
67 File* CreateMemoryFile(
const char* file_name,
const char* mode) {
68 return new MemoryFile(file_name, mode);
71 bool DeleteMemoryFile(
const char* file_name) {
76 static const SupportedTypeInfo kSupportedTypeInfo[] = {
79 strlen(kLocalFilePrefix),
85 strlen(kUdpFilePrefix),
91 strlen(kMemoryFilePrefix),
99 File* File::Create(
const char* file_name,
const char* mode) {
100 std::unique_ptr<File, FileCloser> internal_file(
101 CreateInternalFile(file_name, mode));
103 if (!strncmp(file_name, kMemoryFilePrefix, strlen(kMemoryFilePrefix))) {
105 return internal_file.release();
108 if (FLAGS_io_cache_size) {
110 if (!strcmp(mode,
"r")) {
111 return new ThreadedIoFile(std::move(internal_file),
112 ThreadedIoFile::kInputMode, FLAGS_io_cache_size,
113 FLAGS_io_block_size);
114 }
else if (!strcmp(mode,
"w") || !strcmp(mode,
"a")) {
115 return new ThreadedIoFile(std::move(internal_file),
116 ThreadedIoFile::kOutputMode,
117 FLAGS_io_cache_size, FLAGS_io_block_size);
122 DLOG(WARNING) <<
"Threaded I/O is disabled. Performance may be decreased.";
123 return internal_file.release();
126 File* File::CreateInternalFile(
const char* file_name,
const char* mode) {
127 std::unique_ptr<File, FileCloser> internal_file;
128 for (
size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
129 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
130 if (strncmp(type_info.type, file_name, type_info.type_length) == 0) {
131 internal_file.reset(type_info.factory_function(
132 file_name + type_info.type_length, mode));
137 internal_file.reset(CreateLocalFile(file_name, mode));
139 return internal_file.release();
143 File* file = File::Create(file_name, mode);
154 File* file = File::CreateInternalFile(file_name, mode);
165 for (
size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
166 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
167 if (strncmp(type_info.type, file_name, type_info.type_length) == 0) {
168 return type_info.delete_function ?
169 type_info.delete_function(file_name + type_info.type_length) :
174 return DeleteLocalFile(file_name);
181 int64_t res = file->
Size();
193 const size_t kBufferSize = 0x40000;
194 std::unique_ptr<char[]> buf(
new char[kBufferSize]);
197 while ((len = file->
Read(buf.get(), kBufferSize)) > 0)
198 contents->append(buf.get(), len);
204 bool File::Copy(
const char* from_file_name,
const char* to_file_name) {
207 LOG(ERROR) <<
"Failed to open file " << from_file_name;
211 std::unique_ptr<File, FileCloser> output_file(
File::Open(to_file_name,
"w"));
213 LOG(ERROR) <<
"Failed to write to " << to_file_name;
217 uint64_t bytes_left = content.size();
218 uint64_t total_bytes_written = 0;
219 const char* content_cstr = content.c_str();
220 while (bytes_left > total_bytes_written) {
221 const int64_t bytes_written =
222 output_file->Write(content_cstr + total_bytes_written, bytes_left);
223 if (bytes_written < 0) {
224 LOG(ERROR) <<
"Failure while writing to " << to_file_name;
228 total_bytes_written += bytes_written;
234 return CopyFile(source, destination, kWholeFile);
241 max_copy = std::numeric_limits<int64_t>::max();
243 const int64_t kBufferSize = 0x40000;
244 std::unique_ptr<uint8_t[]> buffer(
new uint8_t[kBufferSize]);
245 int64_t bytes_copied = 0;
246 while (bytes_copied < max_copy) {
247 const int64_t size = std::min(kBufferSize, max_copy - bytes_copied);
248 const int64_t bytes_read = source->
Read(buffer.get(), size);
254 int64_t total_bytes_written = 0;
255 while (total_bytes_written < bytes_read) {
256 const int64_t bytes_written = destination->
Write(
257 buffer.get() + total_bytes_written, bytes_read - total_bytes_written);
258 if (bytes_written < 0)
259 return bytes_written;
261 total_bytes_written += bytes_written;
264 DCHECK_EQ(total_bytes_written, bytes_read);
265 bytes_copied += bytes_read;