Skip to content
Merged
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
13 changes: 9 additions & 4 deletions Project/GNU/CLI/test/decoders.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ pushd "${files_path}" >/dev/null 2>&1

internal_us=0 # Duration of a frame with our decoder alone, in microseconds
vulkan_ms=0 # Duration with the vulkan decoder alone, including its initialization
for decoder in internal ffmpeg vulkan internal+vulkan internal+ffmpeg ffmpeg+vulkan internal+ffmpeg+vulkan auto ; do
for decoder in internal ffmpeg vulkan vulkan+vulkan internal+vulkan internal+vulkan+vulkan internal+ffmpeg ffmpeg+vulkan internal+ffmpeg+vulkan auto ; do
test="decoders (${decoder})"
input="${file}"
count="${frames}"
if [ "${decoder}" == "ffmpeg" ] || [ "${decoder}" == "vulkan" ] ; then
if [ "${decoder}" == "ffmpeg" ] || [ "${decoder}" == "vulkan" ] || [ "${decoder}" == "vulkan+vulkan" ] ; then
input="${alone_file}"
count="${alone_frames}"
fi
Expand All @@ -74,19 +74,24 @@ pushd "${files_path}" >/dev/null 2>&1
read_duration "${temp_path}/time"

# maximum duration: less than 3 ms per frame with our decoder alone (less than the timeout), other decoders less than 5 times our decoder alone per frame plus 5 s (one-time costs, slower FFmpeg decoder),
# plus with the vulkan decoder in parallel with other decoders the duration of the vulkan decoder alone (the end waits for the first frame given to the vulkan decoder during its initialization, long e.g. with lavapipe)
# except the vulkan decoder alone, its duration with small frames is not representative
# plus with the vulkan decoder in parallel with other decoders the duration of the vulkan decoder alone for each vulkan decoder (the end waits for the first frame given to a vulkan decoder during its initialization, long e.g. with lavapipe)
# except the vulkan decoders alone, their duration with small frames is not representative
if [ "${decoder}" == "internal" ] ; then
internal_us=$((duration_ms * 1000 / count))
max_ms=$((count * 3))
elif [ "${decoder}" == "vulkan" ] ; then
vulkan_ms="${duration_ms}"
max_ms=
elif [ "${decoder}" == "vulkan+vulkan" ] ; then
max_ms=
else
max_ms=$((count * internal_us * 5 / 1000 + 5000))
if contains "vulkan" "${decoder}" || [ "${decoder}" == "auto" ] ; then
max_ms=$((max_ms + vulkan_ms))
fi
if contains "vulkan+vulkan" "${decoder}" || [ "${decoder}" == "auto" ] ; then
max_ms=$((max_ms + vulkan_ms))
fi
fi

check_success "mkv check failed" "mkv checked" || continue
Expand Down
14 changes: 7 additions & 7 deletions Source/CLI/Global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,10 +423,10 @@ int global::SetFileOpenMethod(const char* Value)
//---------------------------------------------------------------------------
int global::SetDecoder(const char* Value)
{
// auto (resolved when a decoder is needed), or decoders in parallel: internal, ffmpeg, vulkan or a combination of them with + (e.g. internal+vulkan), in any order
static const char* const Names[] = { "internal", "ffmpeg", "vulkan" };
static const action Decoders_Actions[] = { Action_InternalDecoder, Action_FFmpegDecoder, Action_VulkanDecoder };
bool Decoders[3] = {};
// auto (resolved when a decoder is needed), or decoders in parallel: internal, ffmpeg, vulkan or a combination of them with + (e.g. internal+vulkan), in any order, vulkan twice for 2 vulkan decoders
static const char* const Names[] = { "internal", "ffmpeg", "vulkan", "vulkan" };
static const action Decoders_Actions[] = { Action_InternalDecoder, Action_FFmpegDecoder, Action_VulkanDecoder, Action_VulkanDecoder2 };
bool Decoders[4] = {};
auto IsAuto = strcmp(Value, "auto") == 0;
if (IsAuto)
Decoders[0] = true;
Expand All @@ -436,9 +436,9 @@ int global::SetDecoder(const char* Value)
auto Name_End = strchr(Name, '+');
auto Name_Size = Name_End ? (size_t)(Name_End - Name) : strlen(Name);
size_t i = 0;
while (i < 3 && (Decoders[i] || strlen(Names[i]) != Name_Size || strncmp(Name, Names[i], Name_Size)))
while (i < 4 && (Decoders[i] || strlen(Names[i]) != Name_Size || strncmp(Name, Names[i], Name_Size)))
i++;
if (i == 3)
if (i == 4)
{
cerr << "Error: unknown decoder value '" << Value << "'." << endl;
return 1;
Expand All @@ -448,7 +448,7 @@ int global::SetDecoder(const char* Value)
break;
Name = Name_End + 1;
}
for (size_t i = 0; i < 3; i++)
for (size_t i = 0; i < 4; i++)
Actions.set(Decoders_Actions[i], Decoders[i]);
Actions.set(Action_AutoDecoder, IsAuto);
Decoder_IsProvided = true;
Expand Down
9 changes: 6 additions & 3 deletions Source/CLI/Help.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,12 @@ ReturnValue Help(const char* /*Name*/)
" with Vulkan hardware decoding), a combination of them with +\n"
" (internal+ffmpeg, internal+vulkan, ffmpeg+vulkan or\n"
" internal+ffmpeg+vulkan: decoders in parallel, each frame is\n"
" decoded by the first available decoder) and auto\n"
" (internal+vulkan if FFmpeg libraries and a Vulkan GPU are\n"
" available, else internal).\n"
" decoded by the first available decoder; vulkan twice e.g.\n"
" internal+vulkan+vulkan: 2 vulkan decoders on the same\n"
" device, faster with big GPUs) and auto (internal+vulkan if\n"
" FFmpeg libraries and a Vulkan GPU are available, with a\n"
" second vulkan decoder if the GPU is an NVIDIA GPU with at\n"
" least 64 streaming multiprocessors, else internal).\n"
" Values with vulkan use any Vulkan device, including a CPU\n"
" implementation (e.g. lavapipe), auto uses a CPU\n"
" implementation only if the video encoder is ffv1_vulkan.\n"
Expand Down
2 changes: 1 addition & 1 deletion Source/CLI/rawcooked.1
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ The default name is \fI${Input}.rawcooked_reversibility_data\fR.
.B --decoder \fIvalue\fR
Set the FFV1 decoder used for decoding and checking to \fIvalue\fR.
.br
Possible values are \fIinternal\fR (RAWcooked decoder), \fIffmpeg\fR (FFmpeg libavcodec decoder), \fIvulkan\fR (FFmpeg libavcodec decoder with Vulkan hardware decoding), a combination of them with \fI+\fR (\fIinternal+ffmpeg\fR, \fIinternal+vulkan\fR, \fIffmpeg+vulkan\fR or \fIinternal+ffmpeg+vulkan\fR: decoders in parallel, each frame is decoded by the first available decoder) and \fIauto\fR (\fIinternal+vulkan\fR if FFmpeg libraries and a Vulkan GPU are available, else \fIinternal\fR).
Possible values are \fIinternal\fR (RAWcooked decoder), \fIffmpeg\fR (FFmpeg libavcodec decoder), \fIvulkan\fR (FFmpeg libavcodec decoder with Vulkan hardware decoding), a combination of them with \fI+\fR (\fIinternal+ffmpeg\fR, \fIinternal+vulkan\fR, \fIffmpeg+vulkan\fR or \fIinternal+ffmpeg+vulkan\fR: decoders in parallel, each frame is decoded by the first available decoder; \fIvulkan\fR twice e.g. \fIinternal+vulkan+vulkan\fR: 2 vulkan decoders on the same device, faster with big GPUs) and \fIauto\fR (\fIinternal+vulkan\fR if FFmpeg libraries and a Vulkan GPU are available, with a second vulkan decoder if the GPU is an NVIDIA GPU with at least 64 streaming multiprocessors, else \fIinternal\fR).
.br
Values with \fIvulkan\fR use any Vulkan device, including a CPU implementation (e.g. lavapipe), \fIauto\fR uses a CPU implementation only if the video encoder is ffv1_vulkan. Values with \fIffmpeg\fR or \fIvulkan\fR need FFmpeg libavcodec and libavutil libraries, searched in the directory of the executable, in its ffmpeg, ffmpeg/lib and ffmpeg/bin subdirectories, then in PATH on Windows, or in the directory of the executable, in its ffmpeg, ffmpeg/lib and ffmpeg/bin subdirectories, then in the library paths of the system on Linux or in Homebrew and MacPorts library directories on macOS, libraries of the ffmpeg-ma package first, only if available in this build.
.br
Expand Down
10 changes: 8 additions & 2 deletions Source/Lib/CoDec/FFV1/FFV1_Frame_FFmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static AVPixelFormat Vulkan_Format(AVCodecContext*, const AVPixelFormat* Formats
}

//---------------------------------------------------------------------------
ffv1_frame_ffmpeg::ffv1_frame_ffmpeg(ThreadPool* Pool_, bool Vulkan) :
ffv1_frame_ffmpeg::ffv1_frame_ffmpeg(ThreadPool* Pool_, bool Vulkan, AVBufferRef* VulkanDevice) :
RawFrame(nullptr),
Pool(Pool_),
Context(ffmpeg::avcodec_alloc_context3(ffmpeg::avcodec_find_decoder(AV_CODEC_ID_FFV1))),
Expand All @@ -63,7 +63,7 @@ ffv1_frame_ffmpeg::ffv1_frame_ffmpeg(ThreadPool* Pool_, bool Vulkan) :
Context->thread_count = Pool ? 0 : 1;
if (Vulkan)
{
Context->hw_device_ctx = FFmpeg_Library_VulkanDevice(); // Maybe already created if the decoder was selected automatically
Context->hw_device_ctx = VulkanDevice ? ffmpeg::av_buffer_ref(VulkanDevice) : FFmpeg_Library_VulkanDevice(); // Maybe already created if the decoder was selected automatically
Context->get_format = Vulkan_Format;
}
}
Expand All @@ -77,6 +77,12 @@ ffv1_frame_ffmpeg::~ffv1_frame_ffmpeg()
ffmpeg::avcodec_free_context(&Context);
}

//---------------------------------------------------------------------------
AVBufferRef* ffv1_frame_ffmpeg::VulkanDevice()
{
return Context->hw_device_ctx ? ffmpeg::av_buffer_ref(Context->hw_device_ctx) : nullptr;
}

//***************************************************************************
// External metadata
//***************************************************************************
Expand Down
3 changes: 2 additions & 1 deletion Source/Lib/CoDec/FFV1/FFV1_Frame_FFmpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ class ffv1_frame_ffmpeg
{
public:
// Constructor/Destructor
ffv1_frame_ffmpeg(ThreadPool* Pool, bool Vulkan); // Vulkan: hardware decoding with Vulkan
ffv1_frame_ffmpeg(ThreadPool* Pool, bool Vulkan, AVBufferRef* VulkanDevice = nullptr); // Vulkan: hardware decoding with Vulkan, on VulkanDevice if set (the decoder has its own reference)
~ffv1_frame_ffmpeg();
AVBufferRef* VulkanDevice(); // New reference to the Vulkan device, nullptr if none

// External metadata
void SetWidth(uint32_t width);
Expand Down
Loading
Loading