mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-06-28 01:52:06 +08:00
replay: use VideoToolbox HW decoder on Mac (#23832)
* replay: support VideoToolbox HW decoding * rename flag * remove debug assert old-commit-hash: dc7de79dc9d546465030acab1df1d9cc36e1d4d6
This commit is contained in:
@@ -6,6 +6,14 @@
|
||||
|
||||
#include "cereal/visionipc/visionbuf.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_VIDEOTOOLBOX
|
||||
#define HW_PIX_FMT AV_PIX_FMT_VIDEOTOOLBOX
|
||||
#else
|
||||
#define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_CUDA
|
||||
#define HW_PIX_FMT AV_PIX_FMT_CUDA
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
struct buffer_data {
|
||||
@@ -30,7 +38,7 @@ enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *
|
||||
for (const enum AVPixelFormat *p = pix_fmts; *p != -1; p++) {
|
||||
if (*p == *hw_pix_fmt) return *p;
|
||||
}
|
||||
rWarning("Please run replay with the --no-cuda flag!");
|
||||
rWarning("Please run replay with the --no-hw-decoder flag!");
|
||||
// fallback to YUV420p
|
||||
*hw_pix_fmt = AV_PIX_FMT_NONE;
|
||||
return AV_PIX_FMT_YUV420P;
|
||||
@@ -57,15 +65,15 @@ FrameReader::~FrameReader() {
|
||||
}
|
||||
}
|
||||
|
||||
bool FrameReader::load(const std::string &url, bool no_cuda, std::atomic<bool> *abort, bool local_cache, int chunk_size, int retries) {
|
||||
bool FrameReader::load(const std::string &url, bool no_hw_decoder, std::atomic<bool> *abort, bool local_cache, int chunk_size, int retries) {
|
||||
FileReader f(local_cache, chunk_size, retries);
|
||||
std::string data = f.read(url, abort);
|
||||
if (data.empty()) return false;
|
||||
|
||||
return load((std::byte *)data.data(), data.size(), no_cuda, abort);
|
||||
return load((std::byte *)data.data(), data.size(), no_hw_decoder, abort);
|
||||
}
|
||||
|
||||
bool FrameReader::load(const std::byte *data, size_t size, bool no_cuda, std::atomic<bool> *abort) {
|
||||
bool FrameReader::load(const std::byte *data, size_t size, bool no_hw_decoder, std::atomic<bool> *abort) {
|
||||
input_ctx = avformat_alloc_context();
|
||||
if (!input_ctx) return false;
|
||||
|
||||
@@ -106,9 +114,9 @@ bool FrameReader::load(const std::byte *data, size_t size, bool no_cuda, std::at
|
||||
height = decoder_ctx->height;
|
||||
visionbuf_compute_aligned_width_and_height(width, height, &aligned_width, &aligned_height);
|
||||
|
||||
if (has_cuda_device && !no_cuda) {
|
||||
if (!initHardwareDecoder(AV_HWDEVICE_TYPE_CUDA)) {
|
||||
rWarning("No CUDA capable device was found. fallback to CPU decoding.");
|
||||
if (has_hw_decoder && !no_hw_decoder) {
|
||||
if (!initHardwareDecoder(HW_DEVICE_TYPE)) {
|
||||
rWarning("No device with hardware decoder found. fallback to CPU decoding.");
|
||||
} else {
|
||||
nv12toyuv_buffer.resize(getYUVSize());
|
||||
}
|
||||
@@ -151,7 +159,7 @@ bool FrameReader::initHardwareDecoder(AVHWDeviceType hw_device_type) {
|
||||
int ret = av_hwdevice_ctx_create(&hw_device_ctx, hw_device_type, nullptr, nullptr, 0);
|
||||
if (ret < 0) {
|
||||
hw_pix_fmt = AV_PIX_FMT_NONE;
|
||||
has_cuda_device = false;
|
||||
has_hw_decoder = false;
|
||||
rWarning("Failed to create specified HW device %d.", ret);
|
||||
return false;
|
||||
}
|
||||
@@ -219,7 +227,7 @@ AVFrame *FrameReader::decodeFrame(AVPacket *pkt) {
|
||||
}
|
||||
|
||||
bool FrameReader::copyBuffers(AVFrame *f, uint8_t *rgb, uint8_t *yuv) {
|
||||
if (hw_pix_fmt == AV_PIX_FMT_CUDA) {
|
||||
if (hw_pix_fmt == HW_PIX_FMT) {
|
||||
uint8_t *y = yuv ? yuv : nv12toyuv_buffer.data();
|
||||
uint8_t *u = y + width * height;
|
||||
uint8_t *v = u + (width / 2) * (height / 2);
|
||||
|
||||
@@ -19,8 +19,8 @@ class FrameReader {
|
||||
public:
|
||||
FrameReader();
|
||||
~FrameReader();
|
||||
bool load(const std::string &url, bool no_cuda = false, std::atomic<bool> *abort = nullptr, bool local_cache = false, int chunk_size = -1, int retries = 0);
|
||||
bool load(const std::byte *data, size_t size, bool no_cuda = false, std::atomic<bool> *abort = nullptr);
|
||||
bool load(const std::string &url, bool no_hw_decoder = false, std::atomic<bool> *abort = nullptr, bool local_cache = false, int chunk_size = -1, int retries = 0);
|
||||
bool load(const std::byte *data, size_t size, bool no_hw_decoder = false, std::atomic<bool> *abort = nullptr);
|
||||
bool get(int idx, uint8_t *rgb, uint8_t *yuv);
|
||||
int getRGBSize() const { return aligned_width * aligned_height * 3; }
|
||||
int getYUVSize() const { return width * height * 3 / 2; }
|
||||
@@ -48,5 +48,5 @@ private:
|
||||
AVBufferRef *hw_device_ctx = nullptr;
|
||||
std::vector<uint8_t> nv12toyuv_buffer;
|
||||
int prev_idx = -1;
|
||||
inline static std::atomic<bool> has_cuda_device = true;
|
||||
inline static std::atomic<bool> has_hw_decoder = true;
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
|
||||
{"no-cache", REPLAY_FLAG_NO_FILE_CACHE, "turn off local cache"},
|
||||
{"qcam", REPLAY_FLAG_QCAMERA, "load qcamera"},
|
||||
{"yuv", REPLAY_FLAG_SEND_YUV, "send yuv frame"},
|
||||
{"no-cuda", REPLAY_FLAG_NO_CUDA, "disable CUDA"},
|
||||
{"no-hw-decoder", REPLAY_FLAG_NO_HW_DECODER, "disable HW video decoding"},
|
||||
{"no-vipc", REPLAY_FLAG_NO_VIPC, "do not output video"},
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ enum REPLAY_FLAGS {
|
||||
REPLAY_FLAG_NO_FILE_CACHE = 0x0020,
|
||||
REPLAY_FLAG_QCAMERA = 0x0040,
|
||||
REPLAY_FLAG_SEND_YUV = 0x0080,
|
||||
REPLAY_FLAG_NO_CUDA = 0x0100,
|
||||
REPLAY_FLAG_NO_HW_DECODER = 0x0100,
|
||||
REPLAY_FLAG_FULL_SPEED = 0x0200,
|
||||
REPLAY_FLAG_NO_VIPC = 0x0400,
|
||||
};
|
||||
|
||||
@@ -117,7 +117,7 @@ void Segment::loadFile(int id, const std::string file) {
|
||||
bool success = false;
|
||||
if (id < MAX_CAMERAS) {
|
||||
frames[id] = std::make_unique<FrameReader>();
|
||||
success = frames[id]->load(file, flags & REPLAY_FLAG_NO_CUDA, &abort_, local_cache, 20 * 1024 * 1024, 3);
|
||||
success = frames[id]->load(file, flags & REPLAY_FLAG_NO_HW_DECODER, &abort_, local_cache, 20 * 1024 * 1024, 3);
|
||||
} else {
|
||||
log = std::make_unique<LogReader>();
|
||||
success = log->load(file, &abort_, local_cache, 0, 3);
|
||||
|
||||
Reference in New Issue
Block a user