Skip to content

Commit dc7de79

Browse files
authored
replay: use VideoToolbox HW decoder on Mac (commaai#23832)
* replay: support VideoToolbox HW decoding * rename flag * remove debug assert
1 parent cc1aab2 commit dc7de79

File tree

5 files changed

+23
-15
lines changed

5 files changed

+23
-15
lines changed

selfdrive/ui/replay/framereader.cc

+17-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66

77
#include "cereal/visionipc/visionbuf.h"
88

9+
#ifdef __APPLE__
10+
#define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_VIDEOTOOLBOX
11+
#define HW_PIX_FMT AV_PIX_FMT_VIDEOTOOLBOX
12+
#else
13+
#define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_CUDA
14+
#define HW_PIX_FMT AV_PIX_FMT_CUDA
15+
#endif
16+
917
namespace {
1018

1119
struct buffer_data {
@@ -30,7 +38,7 @@ enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *
3038
for (const enum AVPixelFormat *p = pix_fmts; *p != -1; p++) {
3139
if (*p == *hw_pix_fmt) return *p;
3240
}
33-
rWarning("Please run replay with the --no-cuda flag!");
41+
rWarning("Please run replay with the --no-hw-decoder flag!");
3442
// fallback to YUV420p
3543
*hw_pix_fmt = AV_PIX_FMT_NONE;
3644
return AV_PIX_FMT_YUV420P;
@@ -57,15 +65,15 @@ FrameReader::~FrameReader() {
5765
}
5866
}
5967

60-
bool FrameReader::load(const std::string &url, bool no_cuda, std::atomic<bool> *abort, bool local_cache, int chunk_size, int retries) {
68+
bool FrameReader::load(const std::string &url, bool no_hw_decoder, std::atomic<bool> *abort, bool local_cache, int chunk_size, int retries) {
6169
FileReader f(local_cache, chunk_size, retries);
6270
std::string data = f.read(url, abort);
6371
if (data.empty()) return false;
6472

65-
return load((std::byte *)data.data(), data.size(), no_cuda, abort);
73+
return load((std::byte *)data.data(), data.size(), no_hw_decoder, abort);
6674
}
6775

68-
bool FrameReader::load(const std::byte *data, size_t size, bool no_cuda, std::atomic<bool> *abort) {
76+
bool FrameReader::load(const std::byte *data, size_t size, bool no_hw_decoder, std::atomic<bool> *abort) {
6977
input_ctx = avformat_alloc_context();
7078
if (!input_ctx) return false;
7179

@@ -106,9 +114,9 @@ bool FrameReader::load(const std::byte *data, size_t size, bool no_cuda, std::at
106114
height = decoder_ctx->height;
107115
visionbuf_compute_aligned_width_and_height(width, height, &aligned_width, &aligned_height);
108116

109-
if (has_cuda_device && !no_cuda) {
110-
if (!initHardwareDecoder(AV_HWDEVICE_TYPE_CUDA)) {
111-
rWarning("No CUDA capable device was found. fallback to CPU decoding.");
117+
if (has_hw_decoder && !no_hw_decoder) {
118+
if (!initHardwareDecoder(HW_DEVICE_TYPE)) {
119+
rWarning("No device with hardware decoder found. fallback to CPU decoding.");
112120
} else {
113121
nv12toyuv_buffer.resize(getYUVSize());
114122
}
@@ -151,7 +159,7 @@ bool FrameReader::initHardwareDecoder(AVHWDeviceType hw_device_type) {
151159
int ret = av_hwdevice_ctx_create(&hw_device_ctx, hw_device_type, nullptr, nullptr, 0);
152160
if (ret < 0) {
153161
hw_pix_fmt = AV_PIX_FMT_NONE;
154-
has_cuda_device = false;
162+
has_hw_decoder = false;
155163
rWarning("Failed to create specified HW device %d.", ret);
156164
return false;
157165
}
@@ -219,7 +227,7 @@ AVFrame *FrameReader::decodeFrame(AVPacket *pkt) {
219227
}
220228

221229
bool FrameReader::copyBuffers(AVFrame *f, uint8_t *rgb, uint8_t *yuv) {
222-
if (hw_pix_fmt == AV_PIX_FMT_CUDA) {
230+
if (hw_pix_fmt == HW_PIX_FMT) {
223231
uint8_t *y = yuv ? yuv : nv12toyuv_buffer.data();
224232
uint8_t *u = y + width * height;
225233
uint8_t *v = u + (width / 2) * (height / 2);

selfdrive/ui/replay/framereader.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ class FrameReader {
1919
public:
2020
FrameReader();
2121
~FrameReader();
22-
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);
23-
bool load(const std::byte *data, size_t size, bool no_cuda = false, std::atomic<bool> *abort = nullptr);
22+
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);
23+
bool load(const std::byte *data, size_t size, bool no_hw_decoder = false, std::atomic<bool> *abort = nullptr);
2424
bool get(int idx, uint8_t *rgb, uint8_t *yuv);
2525
int getRGBSize() const { return aligned_width * aligned_height * 3; }
2626
int getYUVSize() const { return width * height * 3 / 2; }
@@ -48,5 +48,5 @@ class FrameReader {
4848
AVBufferRef *hw_device_ctx = nullptr;
4949
std::vector<uint8_t> nv12toyuv_buffer;
5050
int prev_idx = -1;
51-
inline static std::atomic<bool> has_cuda_device = true;
51+
inline static std::atomic<bool> has_hw_decoder = true;
5252
};

selfdrive/ui/replay/main.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
1616
{"no-cache", REPLAY_FLAG_NO_FILE_CACHE, "turn off local cache"},
1717
{"qcam", REPLAY_FLAG_QCAMERA, "load qcamera"},
1818
{"yuv", REPLAY_FLAG_SEND_YUV, "send yuv frame"},
19-
{"no-cuda", REPLAY_FLAG_NO_CUDA, "disable CUDA"},
19+
{"no-hw-decoder", REPLAY_FLAG_NO_HW_DECODER, "disable HW video decoding"},
2020
{"no-vipc", REPLAY_FLAG_NO_VIPC, "do not output video"},
2121
};
2222

selfdrive/ui/replay/replay.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ enum REPLAY_FLAGS {
1818
REPLAY_FLAG_NO_FILE_CACHE = 0x0020,
1919
REPLAY_FLAG_QCAMERA = 0x0040,
2020
REPLAY_FLAG_SEND_YUV = 0x0080,
21-
REPLAY_FLAG_NO_CUDA = 0x0100,
21+
REPLAY_FLAG_NO_HW_DECODER = 0x0100,
2222
REPLAY_FLAG_FULL_SPEED = 0x0200,
2323
REPLAY_FLAG_NO_VIPC = 0x0400,
2424
};

selfdrive/ui/replay/route.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void Segment::loadFile(int id, const std::string file) {
117117
bool success = false;
118118
if (id < MAX_CAMERAS) {
119119
frames[id] = std::make_unique<FrameReader>();
120-
success = frames[id]->load(file, flags & REPLAY_FLAG_NO_CUDA, &abort_, local_cache, 20 * 1024 * 1024, 3);
120+
success = frames[id]->load(file, flags & REPLAY_FLAG_NO_HW_DECODER, &abort_, local_cache, 20 * 1024 * 1024, 3);
121121
} else {
122122
log = std::make_unique<LogReader>();
123123
success = log->load(file, &abort_, local_cache, 0, 3);

0 commit comments

Comments
 (0)