mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-01-26 22:23:16 -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:
|
||||
RealFile(re2::StringPiece mime_type, re2::StringPiece filename,
|
||||
const struct stat &statbuf)
|
||||
: mime_type_(mime_type.as_string()),
|
||||
filename_(filename.as_string()),
|
||||
stat_(statbuf) {}
|
||||
: mime_type_(mime_type.as_string()), stat_(statbuf) {
|
||||
slice_.Init(filename, ByteRange(0, statbuf.st_size));
|
||||
}
|
||||
|
||||
~RealFile() final {}
|
||||
|
||||
int64_t size() const final { return stat_.st_size; }
|
||||
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 {
|
||||
return StrCat("\"", stat_.st_ino, ":", stat_.st_size, ":",
|
||||
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.
|
||||
bool AddRange(ByteRange range, EvBuffer *buf,
|
||||
std::string *error_message) const final {
|
||||
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.end - range.begin,
|
||||
error_message)) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
// |buf| now owns |fd|.
|
||||
return true;
|
||||
return slice_.AddRange(range, buf, error_message);
|
||||
}
|
||||
|
||||
private:
|
||||
RealFileSlice slice_;
|
||||
const std::string mime_type_;
|
||||
const std::string filename_;
|
||||
const struct stat stat_;
|
||||
};
|
||||
|
||||
@ -202,6 +192,28 @@ bool EvBuffer::AddFile(int fd, ev_off_t offset, ev_off_t length,
|
||||
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,
|
||||
std::string *error_message) const {
|
||||
std::unique_ptr<std::string> s(new std::string);
|
||||
@ -222,6 +234,19 @@ bool FillerFileSlice::AddRange(ByteRange range, EvBuffer *buf,
|
||||
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,
|
||||
std::string *error_message) const {
|
||||
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.
|
||||
};
|
||||
|
||||
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
|
||||
// slice on demand. The FillerFileSlice is responsible for subsetting.
|
||||
class FillerFileSlice : public FileSlice {
|
||||
@ -156,6 +172,32 @@ class FillerFileSlice : public FileSlice {
|
||||
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.
|
||||
class FileSlices : public FileSlice {
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user