mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-01-27 14:43:19 -05:00
A few types of FileSlice useful for mp4 building.
This commit is contained in:
parent
eed2a69f7a
commit
29054d42a0
63
src/http.cc
63
src/http.cc
@ -58,41 +58,31 @@ class RealFile : public VirtualFile {
|
|||||||
public:
|
public:
|
||||||
RealFile(re2::StringPiece mime_type, re2::StringPiece filename,
|
RealFile(re2::StringPiece mime_type, re2::StringPiece filename,
|
||||||
const struct stat &statbuf)
|
const struct stat &statbuf)
|
||||||
: mime_type_(mime_type.as_string()),
|
: mime_type_(mime_type.as_string()), stat_(statbuf) {
|
||||||
filename_(filename.as_string()),
|
slice_.Init(filename, ByteRange(0, statbuf.st_size));
|
||||||
stat_(statbuf) {}
|
}
|
||||||
|
|
||||||
~RealFile() final {}
|
~RealFile() final {}
|
||||||
|
|
||||||
int64_t size() const final { return stat_.st_size; }
|
int64_t size() const final { return stat_.st_size; }
|
||||||
time_t last_modified() const final { return stat_.st_mtime; }
|
time_t last_modified() const final { return stat_.st_mtime; }
|
||||||
|
std::string mime_type() const final { return mime_type_; }
|
||||||
|
std::string filename() const final { return slice_.filename(); }
|
||||||
|
|
||||||
std::string etag() const final {
|
std::string etag() const final {
|
||||||
return StrCat("\"", stat_.st_ino, ":", stat_.st_size, ":",
|
return StrCat("\"", stat_.st_ino, ":", stat_.st_size, ":",
|
||||||
stat_.st_mtim.tv_sec, ":", stat_.st_mtim.tv_nsec, "\"");
|
stat_.st_mtim.tv_sec, ":", stat_.st_mtim.tv_nsec, "\"");
|
||||||
}
|
}
|
||||||
std::string mime_type() const final { return mime_type_; }
|
|
||||||
std::string filename() const final { return filename_; }
|
|
||||||
|
|
||||||
// Add the given range of the file to the buffer.
|
// Add the given range of the file to the buffer.
|
||||||
bool AddRange(ByteRange range, EvBuffer *buf,
|
bool AddRange(ByteRange range, EvBuffer *buf,
|
||||||
std::string *error_message) const final {
|
std::string *error_message) const final {
|
||||||
int fd = open(filename_.c_str(), O_RDONLY);
|
return slice_.AddRange(range, buf, error_message);
|
||||||
if (fd < 0) {
|
|
||||||
int err = errno;
|
|
||||||
*error_message = StrCat("open: ", strerror(err));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!buf->AddFile(fd, range.begin, range.end - range.begin,
|
|
||||||
error_message)) {
|
|
||||||
close(fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// |buf| now owns |fd|.
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
RealFileSlice slice_;
|
||||||
const std::string mime_type_;
|
const std::string mime_type_;
|
||||||
const std::string filename_;
|
|
||||||
const struct stat stat_;
|
const struct stat stat_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -202,6 +192,28 @@ bool EvBuffer::AddFile(int fd, ev_off_t offset, ev_off_t length,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RealFileSlice::Init(re2::StringPiece filename, ByteRange range) {
|
||||||
|
filename_ = filename.as_string();
|
||||||
|
range_ = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RealFileSlice::AddRange(ByteRange range, EvBuffer *buf,
|
||||||
|
std::string *error_message) const {
|
||||||
|
int fd = open(filename_.c_str(), O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
int err = errno;
|
||||||
|
*error_message = StrCat("open: ", strerror(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!buf->AddFile(fd, range_.begin + range.begin, range.size(),
|
||||||
|
error_message)) {
|
||||||
|
close(fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// |buf| now owns |fd|.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool FillerFileSlice::AddRange(ByteRange range, EvBuffer *buf,
|
bool FillerFileSlice::AddRange(ByteRange range, EvBuffer *buf,
|
||||||
std::string *error_message) const {
|
std::string *error_message) const {
|
||||||
std::unique_ptr<std::string> s(new std::string);
|
std::unique_ptr<std::string> s(new std::string);
|
||||||
@ -222,6 +234,19 @@ bool FillerFileSlice::AddRange(ByteRange range, EvBuffer *buf,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StaticStringPieceSlice::AddRange(ByteRange range, EvBuffer *buf,
|
||||||
|
std::string *error_message) const {
|
||||||
|
buf->AddReference(piece_.data() + range.begin, range.size(), nullptr,
|
||||||
|
nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CopyingStringPieceSlice::AddRange(ByteRange range, EvBuffer *buf,
|
||||||
|
std::string *error_message) const {
|
||||||
|
buf->Add(re2::StringPiece(piece_.data() + range.begin, range.size()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool FileSlices::AddRange(ByteRange range, EvBuffer *buf,
|
bool FileSlices::AddRange(ByteRange range, EvBuffer *buf,
|
||||||
std::string *error_message) const {
|
std::string *error_message) const {
|
||||||
if (range.begin < 0 || range.begin > range.end || range.end > size_) {
|
if (range.begin < 0 || range.begin > range.end || range.end > size_) {
|
||||||
|
42
src/http.h
42
src/http.h
@ -134,6 +134,22 @@ class VirtualFile : public FileSlice {
|
|||||||
virtual std::string filename() const = 0; // for logging.
|
virtual std::string filename() const = 0; // for logging.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RealFileSlice : public FileSlice {
|
||||||
|
public:
|
||||||
|
void Init(re2::StringPiece filename, ByteRange range);
|
||||||
|
|
||||||
|
const std::string filename() const { return filename_; }
|
||||||
|
|
||||||
|
int64_t size() const final { return range_.size(); }
|
||||||
|
|
||||||
|
bool AddRange(ByteRange range, EvBuffer *buf,
|
||||||
|
std::string *error_message) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string filename_;
|
||||||
|
ByteRange range_;
|
||||||
|
};
|
||||||
|
|
||||||
// A FileSlice of a pre-defined length which calls a function which fills the
|
// A FileSlice of a pre-defined length which calls a function which fills the
|
||||||
// slice on demand. The FillerFileSlice is responsible for subsetting.
|
// slice on demand. The FillerFileSlice is responsible for subsetting.
|
||||||
class FillerFileSlice : public FileSlice {
|
class FillerFileSlice : public FileSlice {
|
||||||
@ -156,6 +172,32 @@ class FillerFileSlice : public FileSlice {
|
|||||||
size_t size_;
|
size_t size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A FileSlice backed by in-memory data which lives forever (static data).
|
||||||
|
class StaticStringPieceSlice : public FileSlice {
|
||||||
|
public:
|
||||||
|
explicit StaticStringPieceSlice(re2::StringPiece piece) : piece_(piece) {}
|
||||||
|
|
||||||
|
int64_t size() const final { return piece_.size(); }
|
||||||
|
bool AddRange(ByteRange range, EvBuffer *buf,
|
||||||
|
std::string *error_message) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
re2::StringPiece piece_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A FileSlice backed by in-memory data which should be copied.
|
||||||
|
class CopyingStringPieceSlice : public FileSlice {
|
||||||
|
public:
|
||||||
|
explicit CopyingStringPieceSlice(re2::StringPiece piece) : piece_(piece) {}
|
||||||
|
|
||||||
|
int64_t size() const final { return piece_.size(); }
|
||||||
|
bool AddRange(ByteRange range, EvBuffer *buf,
|
||||||
|
std::string *error_message) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
re2::StringPiece piece_;
|
||||||
|
};
|
||||||
|
|
||||||
// A slice composed of other slices.
|
// A slice composed of other slices.
|
||||||
class FileSlices : public FileSlice {
|
class FileSlices : public FileSlice {
|
||||||
public:
|
public:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user