Skip to content

[WIP] snake_case #617

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions src/torchcodec/_core/AVIOBytesContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,56 @@

namespace facebook::torchcodec {

AVIOBytesContext::AVIOBytesContext(const void* data, int64_t dataSize)
: dataContext_{static_cast<const uint8_t*>(data), dataSize, 0} {
AVIOBytesContext::AVIOBytesContext(const void* data, int64_t data_size)
: data_context_{static_cast<const uint8_t*>(data), data_size, 0} {
TORCH_CHECK(data != nullptr, "Video data buffer cannot be nullptr!");
TORCH_CHECK(dataSize > 0, "Video data size must be positive");
createAVIOContext(&read, &seek, &dataContext_);
create_avio_context(&read, &seek, &dataContext_);
}

// The signature of this function is defined by FFMPEG.
int AVIOBytesContext::read(void* opaque, uint8_t* buf, int buf_size) {
auto dataContext = static_cast<DataContext*>(opaque);
auto data_context = static_cast<_data_context*>(opaque);
TORCH_CHECK(
dataContext->current <= dataContext->size,
data_context->current <= data_context->size,
"Tried to read outside of the buffer: current=",
dataContext->current,
data_context->current,
", size=",
dataContext->size);
data_context->size);

int64_t numBytesRead = std::min(
static_cast<int64_t>(buf_size), dataContext->size - dataContext->current);
int64_t num_bytes_read = std::min(
static_cast<int64_t>(buf_size),
data_context->size - data_context->current);

TORCH_CHECK(
numBytesRead >= 0,
"Tried to read negative bytes: numBytesRead=",
numBytesRead,
num_bytes_read >= 0,
"Tried to read negative bytes: num_bytes_read=",
num_bytes_read,
", size=",
dataContext->size,
data_context->size,
", current=",
dataContext->current);
data_context->current);

if (numBytesRead == 0) {
return AVERROR_EOF;
}

std::memcpy(buf, dataContext->data + dataContext->current, numBytesRead);
dataContext->current += numBytesRead;
return numBytesRead;
std::memcpy(buf, data_context->data + data_context->current, num_bytes_read);
data_context->current += num_bytes_read;
return num_bytes_read;
}

// The signature of this function is defined by FFMPEG.
int64_t AVIOBytesContext::seek(void* opaque, int64_t offset, int whence) {
auto dataContext = static_cast<DataContext*>(opaque);
auto data_context = static_cast<_data_context*>(opaque);
int64_t ret = -1;

switch (whence) {
case AVSEEK_SIZE:
ret = dataContext->size;
ret = data_context->size;
break;
case SEEK_SET:
dataContext->current = offset;
data_context->current = offset;
ret = offset;
break;
default:
Expand Down
4 changes: 2 additions & 2 deletions src/torchcodec/_core/AVIOBytesContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace facebook::torchcodec {
// functions then traverse the bytes in memory.
class AVIOBytesContext : public AVIOContextHolder {
public:
explicit AVIOBytesContext(const void* data, int64_t dataSize);
explicit AVIOBytesContext(const void* data, int64_t data_size);

private:
struct DataContext {
Expand All @@ -26,7 +26,7 @@ class AVIOBytesContext : public AVIOContextHolder {
static int read(void* opaque, uint8_t* buf, int buf_size);
static int64_t seek(void* opaque, int64_t offset, int whence);

DataContext dataContext_;
DataContext data_context_;
};

} // namespace facebook::torchcodec
26 changes: 13 additions & 13 deletions src/torchcodec/_core/AVIOContextHolder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@

namespace facebook::torchcodec {

void AVIOContextHolder::createAVIOContext(
void AVIOContextHolder::create_avio_context(
AVIOReadFunction read,
AVIOSeekFunction seek,
void* heldData,
int bufferSize) {
void* held_data,
int buffer_size) {
TORCH_CHECK(
bufferSize > 0,
"Buffer size must be greater than 0; is " + std::to_string(bufferSize));
auto buffer = static_cast<uint8_t*>(av_malloc(bufferSize));
buffer_size > 0,
"Buffer size must be greater than 0; is " + std::to_string(buffer_size));
auto buffer = static_cast<uint8_t*>(av_malloc(buffer_size));
TORCH_CHECK(
buffer != nullptr,
"Failed to allocate buffer of size " + std::to_string(bufferSize));
"Failed to allocate buffer of size " + std::to_string(buffer_size));

avioContext_.reset(avio_alloc_context(
avio_context_.reset(avio_alloc_context(
buffer,
bufferSize,
buffer_size,
0,
heldData,
held_data,
read,
nullptr, // write function; not supported yet
seek));
Expand All @@ -39,12 +39,12 @@ void AVIOContextHolder::createAVIOContext(

AVIOContextHolder::~AVIOContextHolder() {
if (avioContext_) {
av_freep(&avioContext_->buffer);
av_freep(&avio_context_->buffer);
}
}

AVIOContext* AVIOContextHolder::getAVIOContext() {
return avioContext_.get();
AVIOContext* AVIOContextHolder::get_avio_context() {
return avio_context_.get();
}

} // namespace facebook::torchcodec
54 changes: 27 additions & 27 deletions src/torchcodec/_core/AVIOContextHolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,31 @@ namespace facebook::torchcodec {

// The AVIOContextHolder serves several purposes:
//
// 1. It is a smart pointer for the AVIOContext. It has the logic to create
// a new AVIOContext and will appropriately free the AVIOContext when it
// goes out of scope. Note that this requires more than just having a
// UniqueAVIOContext, as the AVIOContext points to a buffer which must be
// freed.
// 2. It is a base class for AVIOContext specializations. When specializing a
// AVIOContext, we need to provide four things:
// 1. A read callback function.
// 2. A seek callback function.
// 3. A write callback function. (Not supported yet; it's for encoding.)
// 4. A pointer to some context object that has the same lifetime as the
// AVIOContext itself. This context object holds the custom state that
// tracks the custom behavior of reading, seeking and writing. It is
// provided upon AVIOContext creation and to the read, seek and
// write callback functions.
// While it's not required, it is natural for the derived classes to make
// all of the above members. Base classes need to call
// createAVIOContext(), ideally in their constructor.
// 3. A generic handle for those that just need to manage having access to an
// AVIOContext, but aren't necessarily concerned with how it was customized:
// typically, the SingleStreamDecoder.
// 1. It is a smart pointer for the AVIOContext. It has the logic to create
// a new AVIOContext and will appropriately free the AVIOContext when it
// goes out of scope. Note that this requires more than just having a
// UniqueAVIOContext, as the AVIOContext points to a buffer which must be
// freed.
// 2. It is a base class for AVIOContext specializations. When specializing a
// AVIOContext, we need to provide four things:
// 1. A read callback function.
// 2. A seek callback function.
// 3. A write callback function. (Not supported yet; it's for encoding.)
// 4. A pointer to some context object that has the same lifetime as the
// AVIOContext itself. This context object holds the custom state that
// tracks the custom behavior of reading, seeking and writing. It is
// provided upon AVIOContext creation and to the read, seek and
// write callback functions.
// While it's not required, it is natural for the derived classes to make
// all of the above members. Base classes need to call
// createAVIOContext(), ideally in their constructor.
// 3. A generic handle for those that just need to manage having access to an
// AVIOContext, but aren't necessarily concerned with how it was customized:
// typically, the SingleStreamDecoder.
class AVIOContextHolder {
public:
virtual ~AVIOContextHolder();
AVIOContext* getAVIOContext();
AVIOContext* get_avio_context();

protected:
// Make constructor protected to prevent anyone from constructing
Expand All @@ -49,17 +49,17 @@ class AVIOContextHolder {
using AVIOSeekFunction = int64_t (*)(void*, int64_t, int);

// Deriving classes should call this function in their constructor.
void createAVIOContext(
void create_avio_context(
AVIOReadFunction read,
AVIOSeekFunction seek,
void* heldData,
int bufferSize = defaultBufferSize);
void* held_data,
int buffer_size = default_buffer_size);

private:
UniqueAVIOContext avioContext_;
UniqueAVIOContext avio_context_;

// Defaults to 64 KB
static const int defaultBufferSize = 64 * 1024;
static const int default_buffer_size = 64 * 1024;
};

} // namespace facebook::torchcodec
39 changes: 20 additions & 19 deletions src/torchcodec/_core/AVIOFileLikeContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,61 +9,62 @@

namespace facebook::torchcodec {

AVIOFileLikeContext::AVIOFileLikeContext(py::object fileLike)
: fileLike_{UniquePyObject(new py::object(fileLike))} {
AVIOFileLikeContext::AVIOFileLikeContext(py::object file_like)
: file_like_{UniquePyObject(new py::object(file_like))} {
{
// TODO: Is it necessary to acquire the GIL here? Is it maybe even
// harmful? At the moment, this is only called from within a pybind
// function, and pybind guarantees we have the GIL.
py::gil_scoped_acquire gil;
TORCH_CHECK(
py::hasattr(fileLike, "read"),
py::hasattr(file_like, "read"),
"File like object must implement a read method.");
TORCH_CHECK(
py::hasattr(fileLike, "seek"),
py::hasattr(file_like, "seek"),
"File like object must implement a seek method.");
}
createAVIOContext(&read, &seek, &fileLike_);
create_avio_context(&read, &seek, &fileLike_);
}

int AVIOFileLikeContext::read(void* opaque, uint8_t* buf, int buf_size) {
auto fileLike = static_cast<UniquePyObject*>(opaque);
auto file_like = static_cast<UniquePyObject*>(opaque);

// Note that we acquire the GIL outside of the loop. This is likely more
// efficient than releasing and acquiring it each loop iteration.
py::gil_scoped_acquire gil;

int totalNumRead = 0;
int total_num_read = 0;
while (totalNumRead < buf_size) {
int request = buf_size - totalNumRead;
int request = buf_size - total_num_read;

// The Python method returns the actual bytes, which we access through the
// py::bytes wrapper. That wrapper, however, does not provide us access to
// the underlying data pointer, which we need for the memcpy below. So we
// convert the bytes to a string_view to get access to the data pointer.
// Becauase it's a view and not a copy, it should be cheap.
auto bytesRead = static_cast<py::bytes>((*fileLike)->attr("read")(request));
auto bytesView = static_cast<std::string_view>(bytesRead);
auto bytes_read =
static_cast<py::bytes>((*file_like)->attr("read")(request));
auto bytes_view = static_cast<std::string_view>(bytes_read);

int numBytesRead = static_cast<int>(bytesView.size());
int num_bytes_read = static_cast<int>(bytes_view.size());
if (numBytesRead == 0) {
break;
}

TORCH_CHECK(
numBytesRead <= request,
num_bytes_read <= request,
"Requested up to ",
request,
" bytes but, received ",
numBytesRead,
num_bytes_read,
" bytes. The given object does not conform to read protocol of file object.");

std::memcpy(buf, bytesView.data(), numBytesRead);
buf += numBytesRead;
totalNumRead += numBytesRead;
std::memcpy(buf, bytes_view.data(), num_bytes_read);
buf += num_bytes_read;
total_num_read += num_bytes_read;
}

return totalNumRead == 0 ? AVERROR_EOF : totalNumRead;
return total_num_read == 0 ? AVERROR_EOF : total_num_read;
}

int64_t AVIOFileLikeContext::seek(void* opaque, int64_t offset, int whence) {
Expand All @@ -72,9 +73,9 @@ int64_t AVIOFileLikeContext::seek(void* opaque, int64_t offset, int whence) {
return AVERROR(EIO);
}

auto fileLike = static_cast<UniquePyObject*>(opaque);
auto file_like = static_cast<UniquePyObject*>(opaque);
py::gil_scoped_acquire gil;
return py::cast<int64_t>((*fileLike)->attr("seek")(offset, whence));
return py::cast<int64_t>((*file_like)->attr("seek")(offset, whence));
}

} // namespace facebook::torchcodec
6 changes: 3 additions & 3 deletions src/torchcodec/_core/AVIOFileLikeContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace facebook::torchcodec {
// and seek calls back up to the methods on the Python object.
class AVIOFileLikeContext : public AVIOContextHolder {
public:
explicit AVIOFileLikeContext(py::object fileLike);
explicit AVIOFileLikeContext(py::object file_like);

private:
static int read(void* opaque, uint8_t* buf, int buf_size);
Expand All @@ -32,7 +32,7 @@ class AVIOFileLikeContext : public AVIOContextHolder {
// we'd have to ensure whatever enclosing scope holds the object has the GIL,
// and that's, at least, hard. For all of the common pitfalls, see:
//
// https://pybind11.readthedocs.io/en/stable/advanced/misc.html#common-sources-of-global-interpreter-lock-errors
// https://pybind11.readthedocs.io/en/stable/advanced/misc.html#common-sources-of-global-interpreter-lock-errors
//
// We maintain a reference to the file-like object because the file-like
// object that was created on the Python side must live as long as our
Expand All @@ -48,7 +48,7 @@ class AVIOFileLikeContext : public AVIOContextHolder {
};

using UniquePyObject = std::unique_ptr<py::object, PyObjectDeleter>;
UniquePyObject fileLike_;
UniquePyObject file_like_;
};

} // namespace facebook::torchcodec
32 changes: 16 additions & 16 deletions src/torchcodec/_core/CPUOnlyDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,39 @@ namespace facebook::torchcodec {
// So all functions will throw an error because they should only be called if
// the device is not CPU.

[[noreturn]] void throwUnsupportedDeviceError(const torch::Device& device) {
[[noreturn]] void throw_unsupported_device_error(const torch::Device& device) {
TORCH_CHECK(
device.type() != torch::kCPU,
"Device functions should only be called if the device is not CPU.")
TORCH_CHECK(false, "Unsupported device: " + device.str());
}

void convertAVFrameToFrameOutputOnCuda(
void convert_avframe_to_frame_output_on_cuda(
const torch::Device& device,
[[maybe_unused]] const SingleStreamDecoder::VideoStreamOptions&
videoStreamOptions,
[[maybe_unused]] UniqueAVFrame& avFrame,
[[maybe_unused]] SingleStreamDecoder::FrameOutput& frameOutput,
[[maybe_unused]] std::optional<torch::Tensor> preAllocatedOutputTensor) {
throwUnsupportedDeviceError(device);
video_stream_options,
[[maybe_unused]] UniqueAVFrame& avframe,
[[maybe_unused]] SingleStreamDecoder::FrameOutput& frame_output,
[[maybe_unused]] std::optional<torch::Tensor> pre_allocated_output_tensor) {
throw_unsupported_device_error(device);
}

void initializeContextOnCuda(
void initialize_context_on_cuda(
const torch::Device& device,
[[maybe_unused]] AVCodecContext* codecContext) {
throwUnsupportedDeviceError(device);
[[maybe_unused]] AVCodecContext* codec_context) {
throw_unsupported_device_error(device);
}

void releaseContextOnCuda(
void release_context_on_cuda(
const torch::Device& device,
[[maybe_unused]] AVCodecContext* codecContext) {
throwUnsupportedDeviceError(device);
[[maybe_unused]] AVCodecContext* codec_context) {
throw_unsupported_device_error(device);
}

std::optional<const AVCodec*> findCudaCodec(
std::optional<const AVCodec*> find_cuda_codec(
const torch::Device& device,
[[maybe_unused]] const AVCodecID& codecId) {
throwUnsupportedDeviceError(device);
[[maybe_unused]] const AVCodecID& codec_id) {
throw_unsupported_device_error(device);
}

} // namespace facebook::torchcodec
Loading