Skip to content

Commit

Permalink
fallback to CPU decoding
Browse files Browse the repository at this point in the history
fix memory leak&cleanup

add output
  • Loading branch information
deanlee committed Nov 16, 2021
1 parent 867d5ef commit ec5915d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 17 deletions.
31 changes: 15 additions & 16 deletions selfdrive/ui/replay/framereader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ int readFunction(void *opaque, uint8_t *buf, int buf_size) {
enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts) {
enum AVPixelFormat *hw_pix_fmt = reinterpret_cast<enum AVPixelFormat *>(ctx->opaque);
for (const enum AVPixelFormat *p = pix_fmts; *p != -1; p++) {
if (*p == *hw_pix_fmt) {
return *p;
}
if (*p == *hw_pix_fmt) return *p;
}
printf("Please run replay with the --no-cuda flag!\n");
assert(0);
return AV_PIX_FMT_NONE;
}
Expand All @@ -26,14 +25,12 @@ enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *

FrameReader::FrameReader(bool local_cache, int chunk_size, int retries) : FileReader(local_cache, chunk_size, retries) {
input_ctx = avformat_alloc_context();
av_frame_.reset(av_frame_alloc());
yuv_frame.reset(av_frame_alloc());
rgb_frame.reset(av_frame_alloc());
sws_frame.reset(av_frame_alloc());
}

FrameReader::~FrameReader() {
for (auto &f : frames_) {
av_free_packet(&f.pkt);
av_packet_unref(&f.pkt);
}

if (decoder_ctx) avcodec_free_context(&decoder_ctx);
Expand All @@ -45,7 +42,7 @@ FrameReader::~FrameReader() {

if (avio_ctx_) {
av_freep(&avio_ctx_->buffer);
av_freep(&avio_ctx_);
avio_context_free(&avio_ctx_);
}
}

Expand Down Expand Up @@ -75,7 +72,7 @@ bool FrameReader::load(const std::string &url, bool no_cuda, std::atomic<bool> *
}

AVStream *video = input_ctx->streams[0];
auto decoder = avcodec_find_decoder(video->codec->codec_id);
AVCodec *decoder = avcodec_find_decoder(video->codec->codec_id);
if (!decoder) return false;

decoder_ctx = avcodec_alloc_context3(decoder);
Expand All @@ -87,7 +84,7 @@ bool FrameReader::load(const std::string &url, bool no_cuda, std::atomic<bool> *

if (!no_cuda) {
if (!initHardwareDecoder(AV_HWDEVICE_TYPE_CUDA)) {
return false;
printf("No CUDA capable device was found. fallback to CPU decoding.\n");
}
}

Expand Down Expand Up @@ -119,8 +116,6 @@ bool FrameReader::load(const std::string &url, bool no_cuda, std::atomic<bool> *
}

bool FrameReader::initHardwareDecoder(AVHWDeviceType hw_device_type) {
decoder_ctx->opaque = &hw_pix_fmt;
decoder_ctx->get_format = get_hw_format;
for (int i = 0;; i++) {
const AVCodecHWConfig *config = avcodec_get_hw_config(decoder_ctx->codec, i);
if (!config) {
Expand Down Expand Up @@ -149,8 +144,11 @@ bool FrameReader::initHardwareDecoder(AVHWDeviceType hw_device_type) {
break;
}
}
av_hwframe_constraints_free(&hw_frames_const);

decoder_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
decoder_ctx->opaque = &hw_pix_fmt;
decoder_ctx->get_format = get_hw_format;
return true;
}

Expand Down Expand Up @@ -197,6 +195,7 @@ AVFrame *FrameReader::decodeFrame(AVPacket *pkt) {
return nullptr;
}

av_frame_.reset(av_frame_alloc());
ret = avcodec_receive_frame(decoder_ctx, av_frame_.get());
if (ret != 0) {
return nullptr;
Expand All @@ -217,12 +216,12 @@ AVFrame *FrameReader::decodeFrame(AVPacket *pkt) {
bool FrameReader::copyBuffers(AVFrame *f, uint8_t *rgb, uint8_t *yuv) {
// images is going to be written to output buffers, no alignment (align = 1)
if (yuv) {
av_image_fill_arrays(yuv_frame->data, yuv_frame->linesize, yuv, AV_PIX_FMT_YUV420P, width, height, 1);
int ret = sws_scale(yuv_sws_ctx_, (const uint8_t **)f->data, f->linesize, 0, f->height, yuv_frame->data, yuv_frame->linesize);
av_image_fill_arrays(sws_frame->data, sws_frame->linesize, yuv, AV_PIX_FMT_YUV420P, width, height, 1);
int ret = sws_scale(yuv_sws_ctx_, (const uint8_t **)f->data, f->linesize, 0, f->height, sws_frame->data, sws_frame->linesize);
if (ret < 0) return false;
}

av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, rgb, AV_PIX_FMT_BGR24, width, height, 1);
int ret = sws_scale(rgb_sws_ctx_, (const uint8_t **)f->data, f->linesize, 0, f->height, rgb_frame->data, rgb_frame->linesize);
av_image_fill_arrays(sws_frame->data, sws_frame->linesize, rgb, AV_PIX_FMT_BGR24, width, height, 1);
int ret = sws_scale(rgb_sws_ctx_, (const uint8_t **)f->data, f->linesize, 0, f->height, sws_frame->data, sws_frame->linesize);
return ret >= 0;
}
2 changes: 1 addition & 1 deletion selfdrive/ui/replay/framereader.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class FrameReader : protected FileReader {
std::vector<Frame> frames_;
AVPixelFormat sws_src_format = AV_PIX_FMT_YUV420P;
SwsContext *rgb_sws_ctx_ = nullptr, *yuv_sws_ctx_ = nullptr;
std::unique_ptr<AVFrame, AVFrameDeleter>av_frame_, rgb_frame, yuv_frame, hw_frame;
std::unique_ptr<AVFrame, AVFrameDeleter>av_frame_, sws_frame, hw_frame;
AVFormatContext *input_ctx = nullptr;
AVCodecContext *decoder_ctx = nullptr;
int key_frames_count_ = 0;
Expand Down

0 comments on commit ec5915d

Please sign in to comment.