Skip to content
Open
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
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,50 @@ libpisp_dep = dependency('libpisp', fallback : ['libpisp', 'libpisp_dep'])

Alternatively [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) can be used to locate ``libpisp.so`` installed in of the system directories for other build environments.

## Command-Line Tools

### convert

A simple command-line image converter that uses the PiSP Backend for hardware-accelerated format conversion and scaling.

```sh
pisp_convert input.yuv output.rgb \
--input-format 1920:1080:1920:YUV420P \
--output-format 1280:720:3840:RGB888
```

Format strings use the form `width:height:stride:format`. Use `--formats` to list available formats, or `--list` to enumerate available PiSP devices.

## GStreamer Element

libpisp includes a GStreamer element (`pispconvert`) that provides hardware-accelerated image scaling and format conversion using the PiSP Backend.

### Building with GStreamer Support

GStreamer support is enabled by default if the required dependencies are found. To explicitly enable or disable:

```sh
meson setup <build_dir> -Dgstreamer=enabled # require GStreamer support
meson setup <build_dir> -Dgstreamer=disabled # disable GStreamer support
```

### Using the Element

After installation, the element will be available as `pispconvert`:

```sh
gst-inspect-1.0 pispconvert
```

For usage examples and supported formats, see [src/gst/usage.md](src/gst/usage.md).

### Testing Without Installing

To test the plugin without installing:

```sh
GST_PLUGIN_PATH=<build_dir>/src/gst gst-inspect-1.0 pispconvert
```

## License
Copyright © 2023, Raspberry Pi Ltd. Released under the BSD-2-Clause License.
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

option('logging', type : 'feature', value : 'auto')
option('examples', type : 'boolean', value : false)
option('gstreamer', type : 'feature', value : 'auto', description : 'Build GStreamer plugin')
37 changes: 19 additions & 18 deletions src/examples/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "libpisp/common/utils.hpp"
#include "libpisp/variants/variant.hpp"

using Buffer = libpisp::helpers::Buffer;

void read_plane(uint8_t *mem, std::ifstream &in, unsigned int width, unsigned int height, unsigned int file_stride,
unsigned int buffer_stride)
{
Expand All @@ -53,7 +55,7 @@ void write_plane(std::ofstream &out, uint8_t *mem, unsigned int width, unsigned
}
}

void read_rgb888(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_rgb888(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride)
{
read_plane((uint8_t *)mem[0], in, width * 3, height, file_stride, buffer_stride);
Expand All @@ -65,7 +67,7 @@ void write_rgb888(std::ofstream &out, std::array<uint8_t *, 3> &mem, unsigned in
write_plane(out, (uint8_t *)mem[0], width * 3, height, file_stride, buffer_stride);
}

void read_32(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_32(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride)
{
read_plane((uint8_t *)mem[0], in, width * 4, height, file_stride, buffer_stride);
Expand All @@ -77,7 +79,7 @@ void write_32(std::ofstream &out, std::array<uint8_t *, 3> &mem, unsigned int wi
write_plane(out, (uint8_t *)mem[0], width * 4, height, file_stride, buffer_stride);
}

void read_yuv(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_yuv(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride, unsigned int ss_x, unsigned int ss_y)
{
uint8_t *dst = mem[0];
Expand Down Expand Up @@ -105,25 +107,25 @@ void write_yuv(std::ofstream &out, std::array<uint8_t *, 3> &mem, unsigned int w
write_plane(out, src, width / ss_x, height / ss_y, file_stride / ss_x, buffer_stride / ss_x);
}

void read_yuv420(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_yuv420(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride)
{
read_yuv(mem, in, width, height, file_stride, buffer_stride, 2, 2);
}

void read_yuv422p(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_yuv422p(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride)
{
read_yuv(mem, in, width, height, file_stride, buffer_stride, 2, 1);
}

void read_yuv444p(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_yuv444p(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride)
{
read_yuv(mem, in, width, height, file_stride, buffer_stride, 1, 1);
}

void read_yuv422i(std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
void read_yuv422i(const std::array<uint8_t *, 3> &mem, std::ifstream &in, unsigned int width, unsigned int height,
unsigned int file_stride, unsigned int buffer_stride)
{
read_plane(mem[0], in, width * 2, height, file_stride, buffer_stride);
Expand Down Expand Up @@ -155,7 +157,7 @@ void write_yuv422i(std::ofstream &out, std::array<uint8_t *, 3> &mem, unsigned i

struct FormatFuncs
{
std::function<void(std::array<uint8_t *, 3> &, std::ifstream &, unsigned int, unsigned int, unsigned int,
std::function<void(const std::array<uint8_t *, 3> &, std::ifstream &, unsigned int, unsigned int, unsigned int,
unsigned int)> read_file;
std::function<void(std::ofstream &, std::array<uint8_t *, 3> &, unsigned int, unsigned int, unsigned int,
unsigned int)> write_file;
Expand Down Expand Up @@ -364,7 +366,7 @@ int main(int argc, char *argv[])
be.Prepare(&config);

backend_device.Setup(config);
auto buffers = backend_device.AcquireBuffers();
auto buffers = backend_device.GetBufferSlice();

std::string input_filename = args["input"].as<std::string>();
std::ifstream in(input_filename, std::ios::binary);
Expand All @@ -377,10 +379,11 @@ int main(int argc, char *argv[])
std::cerr << "Reading " << input_filename << " "
<< in_file.width << ":" << in_file.height << ":" << in_file.stride << ":" << in_file.format << std::endl;

Formats.at(in_file.format)
.read_file(buffers["pispbe-input"].mem, in, in_file.width, in_file.height, in_file.stride,
i.stride);
in.close();
{
Buffer::Sync input(buffers.at("pispbe-input"), Buffer::Sync::Access::ReadWrite);
Formats.at(in_file.format).read_file(input.Get(), in, in_file.width, in_file.height, in_file.stride, i.stride);
in.close();
}

int ret = backend_device.Run(buffers);
if (ret)
Expand All @@ -397,13 +400,11 @@ int main(int argc, char *argv[])
exit(-1);
}

Formats.at(out_file.format)
.write_file(out, buffers["pispbe-output0"].mem, out_file.width, out_file.height, out_file.stride,
o.image.stride);
Buffer::Sync output(buffers.at("pispbe-output0"), Buffer::Sync::Access::Read);
Formats.at(out_file.format).write_file(out, const_cast<std::array<uint8_t *, 3> &>(output.Get()), out_file.width, out_file.height, out_file.stride,
o.image.stride);
out.close();

backend_device.ReleaseBuffer(buffers);

std::cerr << "Writing " << output_file << " "
<< out_file.width << ":" << out_file.height << ":" << out_file.stride << ":" << out_file.format << std::endl;

Expand Down
Loading
Loading