DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs
file.cc
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/file/file.h"
8 
9 #include <gflags/gflags.h>
10 #include "packager/base/logging.h"
11 #include "packager/base/memory/scoped_ptr.h"
12 #include "packager/media/file/local_file.h"
13 #include "packager/media/file/threaded_io_file.h"
14 #include "packager/media/file/udp_file.h"
15 #include "packager/base/strings/string_util.h"
16 
17 DEFINE_uint64(io_cache_size,
18  32ULL << 20,
19  "Size of the threaded I/O cache, in bytes. Specify 0 to disable "
20  "threaded I/O.");
21 DEFINE_uint64(io_block_size,
22  2ULL << 20,
23  "Size of the block size used for threaded I/O, in bytes.");
24 
25 namespace edash_packager {
26 namespace media {
27 
28 const char* kLocalFilePrefix = "file://";
29 const char* kUdpFilePrefix = "udp://";
30 
31 namespace {
32 
33 typedef File* (*FileFactoryFunction)(const char* file_name, const char* mode);
34 typedef bool (*FileDeleteFunction)(const char* file_name);
35 
36 struct SupportedTypeInfo {
37  const char* type;
38  size_t type_length;
39  const FileFactoryFunction factory_function;
40  const FileDeleteFunction delete_function;
41 };
42 
43 File* CreateLocalFile(const char* file_name, const char* mode) {
44  return new LocalFile(file_name, mode);
45 }
46 
47 bool DeleteLocalFile(const char* file_name) {
48  return LocalFile::Delete(file_name);
49 }
50 
51 File* CreateUdpFile(const char* file_name, const char* mode) {
52  if (base::strcasecmp(mode, "r")) {
53  NOTIMPLEMENTED() << "UdpFile only supports read (receive) mode.";
54  return NULL;
55  }
56  return new UdpFile(file_name);
57 }
58 
59 static const SupportedTypeInfo kSupportedTypeInfo[] = {
60  {
61  kLocalFilePrefix,
62  strlen(kLocalFilePrefix),
63  &CreateLocalFile,
64  &DeleteLocalFile
65  },
66  {
67  kUdpFilePrefix,
68  strlen(kUdpFilePrefix),
69  &CreateUdpFile,
70  NULL
71  },
72 };
73 
74 } // namespace
75 
76 File* File::Create(const char* file_name, const char* mode) {
77  scoped_ptr<File, FileCloser> internal_file(
78  CreateInternalFile(file_name, mode));
79 
80  if (FLAGS_io_cache_size) {
81  // Enable threaded I/O for "r", "w", and "a" modes only.
82  if (!strcmp(mode, "r")) {
83  return new ThreadedIoFile(internal_file.Pass(),
84  ThreadedIoFile::kInputMode,
85  FLAGS_io_cache_size,
86  FLAGS_io_block_size);
87  } else if (!strcmp(mode, "w") || !strcmp(mode, "a")) {
88  return new ThreadedIoFile(internal_file.Pass(),
89  ThreadedIoFile::kOutputMode,
90  FLAGS_io_cache_size,
91  FLAGS_io_block_size);
92  }
93  }
94 
95  // Threaded I/O is disabled.
96  DLOG(WARNING) << "Threaded I/O is disabled. Performance may be decreased.";
97  return internal_file.release();
98 }
99 
100 File* File::CreateInternalFile(const char* file_name, const char* mode) {
101  scoped_ptr<File, FileCloser> internal_file;
102  for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
103  const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
104  if (strncmp(type_info.type, file_name, type_info.type_length) == 0) {
105  internal_file.reset(type_info.factory_function(
106  file_name + type_info.type_length, mode));
107  }
108  }
109  // Otherwise we assume it is a local file
110  if (!internal_file)
111  internal_file.reset(CreateLocalFile(file_name, mode));
112 
113  return internal_file.release();
114 }
115 
116 File* File::Open(const char* file_name, const char* mode) {
117  File* file = File::Create(file_name, mode);
118  if (!file)
119  return NULL;
120  if (!file->Open()) {
121  delete file;
122  return NULL;
123  }
124  return file;
125 }
126 
127 File* File::OpenWithNoBuffering(const char* file_name, const char* mode) {
128  File* file = File::CreateInternalFile(file_name, mode);
129  if (!file)
130  return NULL;
131  if (!file->Open()) {
132  delete file;
133  return NULL;
134  }
135  return file;
136 }
137 
138 bool File::Delete(const char* file_name) {
139  for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
140  const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
141  if (strncmp(type_info.type, file_name, type_info.type_length) == 0) {
142  return type_info.delete_function ?
143  type_info.delete_function(file_name + type_info.type_length) :
144  false;
145  }
146  }
147  // Otherwise we assume it is a local file
148  return DeleteLocalFile(file_name);
149 }
150 
151 int64_t File::GetFileSize(const char* file_name) {
152  File* file = File::Open(file_name, "r");
153  if (!file)
154  return -1;
155  int64_t res = file->Size();
156  file->Close();
157  return res;
158 }
159 
160 bool File::ReadFileToString(const char* file_name, std::string* contents) {
161  DCHECK(contents);
162 
163  File* file = File::Open(file_name, "r");
164  if (!file)
165  return false;
166 
167  const size_t kBufferSize = 0x40000; // 256KB.
168  scoped_ptr<char[]> buf(new char[kBufferSize]);
169 
170  int64_t len;
171  while ((len = file->Read(buf.get(), kBufferSize)) > 0)
172  contents->append(buf.get(), len);
173 
174  file->Close();
175  return len == 0;
176 }
177 
178 } // namespace media
179 } // namespace edash_packager
static bool ReadFileToString(const char *file_name, std::string *contents)
Definition: file.cc:160
virtual int64_t Read(void *buffer, uint64_t length)=0
static bool Delete(const char *file_name)
Definition: file.cc:138
Define an abstract file interface.
Definition: file.h:22
virtual bool Open()=0
Internal open. Should not be used directly.
static File * Open(const char *file_name, const char *mode)
Definition: file.cc:116
virtual int64_t Size()=0
static bool Delete(const char *file_name)
Definition: local_file.cc:84
static int64_t GetFileSize(const char *file_name)
Definition: file.cc:151
static File * OpenWithNoBuffering(const char *file_name, const char *mode)
Definition: file.cc:127