mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Fix fallback to software decoding in FFmpeg.
This commit is contained in:
parent
528a3cdca1
commit
e8748986bf
7 changed files with 70 additions and 54 deletions
|
@ -85,6 +85,62 @@ void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) {
|
||||||
#endif // LIB_FFMPEG_USE_QT_PRIVATE_API
|
#endif // LIB_FFMPEG_USE_QT_PRIVATE_API
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool InitHw(AVCodecContext *context, AVHWDeviceType type) {
|
||||||
|
auto hwDeviceContext = (AVBufferRef*)nullptr;
|
||||||
|
AvErrorWrap error = av_hwdevice_ctx_create(
|
||||||
|
&hwDeviceContext,
|
||||||
|
type,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
0);
|
||||||
|
if (error || !hwDeviceContext) {
|
||||||
|
LogError(qstr("av_hwdevice_ctx_create"), error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DEBUG_LOG(("Video Info: "
|
||||||
|
"Trying \"%1\" hardware acceleration for \"%2\" decoder."
|
||||||
|
).arg(av_hwdevice_get_type_name(type)
|
||||||
|
).arg(context->codec->name));
|
||||||
|
if (context->hw_device_ctx) {
|
||||||
|
av_buffer_unref(&context->hw_device_ctx);
|
||||||
|
}
|
||||||
|
context->hw_device_ctx = av_buffer_ref(hwDeviceContext);
|
||||||
|
av_buffer_unref(&hwDeviceContext);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] enum AVPixelFormat GetHwFormat(
|
||||||
|
AVCodecContext *context,
|
||||||
|
const enum AVPixelFormat *formats) {
|
||||||
|
const enum AVPixelFormat *p = nullptr;
|
||||||
|
for (p = formats; *p != AV_PIX_FMT_NONE; p++) {
|
||||||
|
const auto type = [&] {
|
||||||
|
switch (*p) {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
case AV_PIX_FMT_D3D11: return AV_HWDEVICE_TYPE_D3D11VA;
|
||||||
|
case AV_PIX_FMT_DXVA2_VLD: return AV_HWDEVICE_TYPE_DXVA2;
|
||||||
|
case AV_PIX_FMT_D3D11VA_VLD: return AV_HWDEVICE_TYPE_D3D11VA;
|
||||||
|
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||||
|
case AV_PIX_FMT_VIDEOTOOLBOX:
|
||||||
|
return AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
|
||||||
|
#else // Q_OS_WIN || Q_OS_MAC
|
||||||
|
case AV_PIX_FMT_VAAPI: return AV_HWDEVICE_TYPE_VAAPI;
|
||||||
|
case AV_PIX_FMT_VDPAU: return AV_HWDEVICE_TYPE_VDPAU;
|
||||||
|
#endif // Q_OS_WIN || Q_OS_MAC
|
||||||
|
case AV_PIX_FMT_CUDA: return AV_HWDEVICE_TYPE_CUDA;
|
||||||
|
}
|
||||||
|
return AV_HWDEVICE_TYPE_NONE;
|
||||||
|
}();
|
||||||
|
if (type != AV_HWDEVICE_TYPE_NONE && !InitHw(context, type)) {
|
||||||
|
continue;
|
||||||
|
} else if (type == AV_HWDEVICE_TYPE_NONE && context->hw_device_ctx) {
|
||||||
|
av_buffer_unref(&context->hw_device_ctx);
|
||||||
|
}
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
return AV_PIX_FMT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
template <AVPixelFormat Required>
|
template <AVPixelFormat Required>
|
||||||
enum AVPixelFormat GetFormatImplementation(
|
enum AVPixelFormat GetFormatImplementation(
|
||||||
AVCodecContext *ctx,
|
AVCodecContext *ctx,
|
||||||
|
@ -258,29 +314,8 @@ CodecPointer MakeCodecPointer(CodecDescriptor descriptor) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.type != AV_HWDEVICE_TYPE_NONE) {
|
if (descriptor.hwAllowed) {
|
||||||
const auto hw = ResolveHwAccel(codec, descriptor.type);
|
context->get_format = GetHwFormat;
|
||||||
if (!hw.getFormat) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
context->get_format = hw.getFormat;
|
|
||||||
auto hwDeviceContext = (AVBufferRef*)nullptr;
|
|
||||||
error = av_hwdevice_ctx_create(
|
|
||||||
&hwDeviceContext,
|
|
||||||
descriptor.type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
0);
|
|
||||||
if (error || !hwDeviceContext) {
|
|
||||||
LogError(qstr("av_hwdevice_ctx_create"), error);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
DEBUG_LOG(("Video Info: "
|
|
||||||
"Using \"%1\" hardware acceleration for \"%2\" decoder."
|
|
||||||
).arg(av_hwdevice_get_type_name(descriptor.type)
|
|
||||||
).arg(codec->name));
|
|
||||||
context->hw_device_ctx = av_buffer_ref(hwDeviceContext);
|
|
||||||
av_buffer_unref(&hwDeviceContext);
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_LOG(("Video Info: Using software \"%2\" decoder."
|
DEBUG_LOG(("Video Info: Using software \"%2\" decoder."
|
||||||
).arg(codec->name));
|
).arg(codec->name));
|
||||||
|
|
|
@ -128,7 +128,7 @@ using CodecPointer = std::unique_ptr<AVCodecContext, CodecDeleter>;
|
||||||
|
|
||||||
struct CodecDescriptor {
|
struct CodecDescriptor {
|
||||||
not_null<AVStream*> stream;
|
not_null<AVStream*> stream;
|
||||||
AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
|
bool hwAllowed = false;
|
||||||
};
|
};
|
||||||
[[nodiscard]] CodecPointer MakeCodecPointer(CodecDescriptor descriptor);
|
[[nodiscard]] CodecPointer MakeCodecPointer(CodecDescriptor descriptor);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct PlaybackOptions {
|
||||||
AudioMsgId audioId;
|
AudioMsgId audioId;
|
||||||
bool syncVideoByAudio = true;
|
bool syncVideoByAudio = true;
|
||||||
bool waitForMarkAsShown = false;
|
bool waitForMarkAsShown = false;
|
||||||
bool hwAllow = false;
|
bool hwAllowed = false;
|
||||||
bool loop = false;
|
bool loop = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -163,36 +163,15 @@ Stream File::Context::initStream(
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto info = format->streams[index];
|
const auto info = format->streams[index];
|
||||||
const auto tryCreateCodec = [&](AVHWDeviceType type) {
|
|
||||||
result.codec = FFmpeg::MakeCodecPointer({
|
|
||||||
.stream = info,
|
|
||||||
.type = type,
|
|
||||||
});
|
|
||||||
return (result.codec != nullptr);
|
|
||||||
};
|
|
||||||
if (type == AVMEDIA_TYPE_VIDEO) {
|
if (type == AVMEDIA_TYPE_VIDEO) {
|
||||||
if (info->disposition & AV_DISPOSITION_ATTACHED_PIC) {
|
if (info->disposition & AV_DISPOSITION_ATTACHED_PIC) {
|
||||||
// ignore cover streams
|
// ignore cover streams
|
||||||
return Stream();
|
return Stream();
|
||||||
}
|
}
|
||||||
const auto hwAccelTypes = std::array{
|
result.codec = FFmpeg::MakeCodecPointer({
|
||||||
#ifdef Q_OS_WIN
|
.stream = info,
|
||||||
AV_HWDEVICE_TYPE_D3D11VA,
|
.hwAllowed = hwAllowed,
|
||||||
AV_HWDEVICE_TYPE_DXVA2,
|
});
|
||||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
|
||||||
AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
|
|
||||||
#else // Q_OS_WIN || Q_OS_MAC
|
|
||||||
AV_HWDEVICE_TYPE_VAAPI,
|
|
||||||
AV_HWDEVICE_TYPE_VDPAU,
|
|
||||||
#endif // Q_OS_WIN || Q_OS_MAC
|
|
||||||
AV_HWDEVICE_TYPE_CUDA,
|
|
||||||
AV_HWDEVICE_TYPE_NONE,
|
|
||||||
};
|
|
||||||
for (const auto type : hwAccelTypes) {
|
|
||||||
if (tryCreateCodec(type)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!result.codec) {
|
if (!result.codec) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +181,9 @@ Stream File::Context::initStream(
|
||||||
result.frequency = info->codecpar->sample_rate;
|
result.frequency = info->codecpar->sample_rate;
|
||||||
if (!result.frequency) {
|
if (!result.frequency) {
|
||||||
return result;
|
return result;
|
||||||
} else if (!tryCreateCodec(AV_HWDEVICE_TYPE_NONE)) {
|
}
|
||||||
|
result.codec = FFmpeg::MakeCodecPointer({ .stream = info });
|
||||||
|
if (!result.codec) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -544,7 +544,7 @@ void Player::play(const PlaybackOptions &options) {
|
||||||
_options.speed = 1.;
|
_options.speed = 1.;
|
||||||
}
|
}
|
||||||
_stage = Stage::Initializing;
|
_stage = Stage::Initializing;
|
||||||
_file->start(delegate(), _options.position, _options.hwAllow);
|
_file->start(delegate(), _options.position, _options.hwAllowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::savePreviousReceivedTill(
|
void Player::savePreviousReceivedTill(
|
||||||
|
|
|
@ -3116,7 +3116,7 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
||||||
}
|
}
|
||||||
auto options = Streaming::PlaybackOptions();
|
auto options = Streaming::PlaybackOptions();
|
||||||
options.position = position;
|
options.position = position;
|
||||||
options.hwAllow = true;
|
options.hwAllowed = true;
|
||||||
if (!_streamed->withSound) {
|
if (!_streamed->withSound) {
|
||||||
options.mode = Streaming::Mode::Video;
|
options.mode = Streaming::Mode::Video;
|
||||||
options.loop = true;
|
options.loop = true;
|
||||||
|
|
|
@ -1604,7 +1604,7 @@ void Pip::restartAtSeekPosition(crl::time position) {
|
||||||
|
|
||||||
auto options = Streaming::PlaybackOptions();
|
auto options = Streaming::PlaybackOptions();
|
||||||
options.position = position;
|
options.position = position;
|
||||||
options.hwAllow = true;
|
options.hwAllowed = true;
|
||||||
options.audioId = _instance.player().prepareLegacyState().id;
|
options.audioId = _instance.player().prepareLegacyState().id;
|
||||||
|
|
||||||
Assert(8 && _delegate->pipPlaybackSpeed() >= 0.5
|
Assert(8 && _delegate->pipPlaybackSpeed() >= 0.5
|
||||||
|
|
Loading…
Add table
Reference in a new issue