Skip to content

Commit

Permalink
Remove libavutils from the asan suppression list (#5783)
Browse files Browse the repository at this point in the history
* Remove libavutils from the asan suppression list
- keeps suppression for FFmpegDemuxer from the PyNvVideoCodec
  DALI doesn't have control on
- fixes leaks from libavutils

Signed-off-by: Janusz Lisiecki <jlisiecki@nvidia.com>
  • Loading branch information
JanuszL authored Jan 20, 2025
1 parent cfbf402 commit a4d8987
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 16 deletions.
19 changes: 12 additions & 7 deletions dali/operators/reader/loader/video/frames_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ FramesDecoder::FramesDecoder(const char *memory_file, int memory_file_size, bool

int ret = avformat_open_input(&av_state_->ctx_, "", nullptr, nullptr);
if (ret != 0) {
// av_state_->ctx_ is nullified so we need to free the memory here instead of the
// AvState destructor which cannot access it through av_state_->ctx_ anymore
av_freep(&av_io_context->buffer);
avio_context_free(&av_io_context);
DALI_WARN(make_string("Failed to open video file \"", Filename(), "\", due to ",
detail::av_error_string(ret)));
return;
Expand Down Expand Up @@ -284,13 +288,14 @@ void FramesDecoder::CreateAvState(std::unique_ptr<AvState> &av_state, bool init_
av_state->ctx_->pb = av_io_context;

int ret = avformat_open_input(&av_state->ctx_, "", nullptr, nullptr);
DALI_ENFORCE(
ret == 0,
make_string(
"Failed to open video file \"",
Filename(),
"\", due to ",
detail::av_error_string(ret)));
if (ret != 0) {
// av_state_->ctx_ is nullified so we need to free the memory here instead of the
// AvState destructor which cannot access it through av_state_->ctx_ anymore
av_freep(&av_io_context->buffer);
avio_context_free(&av_io_context);
DALI_FAIL(make_string("Failed to open video file \"", Filename(), "\", due to ",
detail::av_error_string(ret)));
}
av_state->stream_id_ = av_find_best_stream(
av_state->ctx_, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
av_state->codec_params_ = av_state->ctx_->streams[av_state->stream_id_]->codecpar;
Expand Down
11 changes: 7 additions & 4 deletions dali/operators/reader/loader/video/frames_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,15 @@ struct AvState {
avcodec_free_context(&codec_ctx_);
if (ctx_ != nullptr) {
// if we use avio_alloc_context we need a custom deallocator for ctx_->pb
if (ctx_->flags & AVFMT_FLAG_CUSTOM_IO) {
av_freep(&ctx_->pb->buffer);
av_freep(&ctx_->pb);
}
auto custom_dealloc = ctx_->flags & AVFMT_FLAG_CUSTOM_IO;
auto custom_ctx = ctx_->pb;
auto custom_buffer = ctx_->pb ? ctx_->pb->buffer : nullptr;
avformat_close_input(&ctx_);
avformat_free_context(ctx_);
if (custom_dealloc) {
av_freep(&custom_buffer);
avio_context_free(&custom_ctx);
}
}

ctx_ = nullptr;
Expand Down
19 changes: 16 additions & 3 deletions dali/operators/reader/loader/video_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@ static int64_t seek_file(void *opaque, int64_t offset, int whence) {
}
}

void clean_avformat_context(AVFormatContext **p) {
if (*p && (*p)->flags & AVFMT_FLAG_CUSTOM_IO) {
if (*p && (*p)->pb) av_freep(&(*p)->pb->buffer);
avio_context_free(&(*p)->pb);
}
avformat_close_input(p);
}

VideoFile& VideoLoader::get_or_open_file(const std::string &filename) {
static VideoFile empty_file = {};
auto& file = open_files_[filename];
Expand Down Expand Up @@ -299,12 +307,16 @@ VideoFile& VideoLoader::get_or_open_file(const std::string &filename) {
// if avformat_open_input fails it frees raw_fmt_ctx so we can release it from unique_ptr
int ret = avformat_open_input(&tmp_raw_fmt_ctx, NULL, NULL, NULL);
if (ret < 0) {
// avio_ctx->ctx_ is nullified so we need to free the memory here instead of the
// AVFormatContext destructor which cannot access it through avio_ctx->ctx_ anymore
av_freep(&avio_ctx->buffer);
avio_context_free(&avio_ctx);
DALI_WARN(make_string("Failed to open video file ", filename, " because of ",
av_err2str(ret)));
open_files_.erase(filename);
return empty_file;
}
file.fmt_ctx_ = make_unique_av<AVFormatContext>(tmp_raw_fmt_ctx, avformat_close_input);
file.fmt_ctx_ = make_unique_av<AVFormatContext>(tmp_raw_fmt_ctx, clean_avformat_context);
LOG_LINE << "File open " << filename << std::endl;

LOG_LINE << "File info fetched for " << filename << std::endl;
Expand Down Expand Up @@ -398,6 +410,8 @@ VideoFile& VideoLoader::get_or_open_file(const std::string &filename) {
if (pkt.stream_index == file.vid_stream_idx_) break;
av_packet_unref(&pkt);
}
auto pkt_duration = pkt.duration;
av_packet_unref(&pkt);

if (ret < 0) {
DALI_WARN(make_string("Unable to read frame from file :", filename));
Expand All @@ -406,10 +420,9 @@ VideoFile& VideoLoader::get_or_open_file(const std::string &filename) {
}

DALI_ENFORCE(skip_vfr_check_ ||
almost_equal(av_q2d(file.frame_base_), pkt.duration * av_q2d(file.stream_base_), 2),
almost_equal(av_q2d(file.frame_base_), pkt_duration * av_q2d(file.stream_base_), 2),
"Variable frame rate videos are unsupported. This heuristic can yield false positives. "
"The check can be disabled via the skip_vfr_check flag. Check failed for file: " + filename);
av_packet_unref(&pkt);
// empty the read buffer from av_read_frame to save the memory usage
avformat_flush(file.fmt_ctx_.get());

Expand Down
4 changes: 2 additions & 2 deletions qa/leak.sup
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ leak:numba
leak:libmxnet
leak:libtorch
leak:libc10
leak:av_realloc_f
leak:av_malloc
# we don't control FFmpegDemuxer destructor so we cannot fix that in DALI
leak:FFmpegDemuxer
# tensorflow
leak:PyInit__pywrap_debug_events_writer
leak:_pywrap
Expand Down

0 comments on commit a4d8987

Please sign in to comment.