mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-12 02:09:17 +00:00
Fix recording encoder selection
Codecs are identified by name, not by ID. Let's keep the ID as fallback instead.
This commit is contained in:
@@ -707,6 +707,11 @@ namespace cfg
|
||||
return *m_value.load().get();
|
||||
}
|
||||
|
||||
std::string get() const
|
||||
{
|
||||
return *m_value.load().get();
|
||||
}
|
||||
|
||||
std::string def_to_string() const override
|
||||
{
|
||||
return def;
|
||||
|
||||
@@ -1290,11 +1290,11 @@ error_code cellRecOpen(vm::cptr<char> pDirName, vm::cptr<char> pFileName, vm::cp
|
||||
rec.encoder->set_path(vfs::get(rec.param.filename));
|
||||
rec.encoder->set_framerate(rec.fps);
|
||||
rec.encoder->set_video_bitrate(rec.video_bps);
|
||||
rec.encoder->set_video_codec(rec.video_codec_id);
|
||||
rec.encoder->set_video_codec(rec.video_codec_id, "");
|
||||
rec.encoder->set_sample_rate(rec.sample_rate);
|
||||
rec.encoder->set_audio_channels(rec.channels);
|
||||
rec.encoder->set_audio_bitrate(rec.audio_bps);
|
||||
rec.encoder->set_audio_codec(rec.audio_codec_id);
|
||||
rec.encoder->set_audio_codec(rec.audio_codec_id, "");
|
||||
rec.encoder->set_output_format(rec.output_format);
|
||||
|
||||
sysutil_register_cb([&rec](ppu_thread& ppu) -> s32
|
||||
|
||||
@@ -16,7 +16,8 @@ struct cfg_recording final : cfg::node
|
||||
cfg::uint<640, 7680> width{this, "Width", 1280};
|
||||
cfg::uint<360, 4320> height{this, "Height", 720};
|
||||
cfg::uint<0, 192> pixel_format{this, "AVPixelFormat", 0}; // AVPixelFormat::AV_PIX_FMT_YUV420P
|
||||
cfg::uint<0, 0xFFFF> video_codec{this, "AVCodecID", 12}; // AVCodecID::AV_CODEC_ID_MPEG4
|
||||
cfg::string codec_name{this, "Video Codec", ""};
|
||||
cfg::uint<0, 0xFFFF> codec_id{this, "AVCodecID", 12}; // AVCodecID::AV_CODEC_ID_MPEG4
|
||||
cfg::uint<1'000'000, 60'000'000> video_bps{this, "Video Bitrate", 4'000'000};
|
||||
cfg::uint<0, 3> max_b_frames{this, "Max B-Frames", 2};
|
||||
cfg::uint<1, 120> gop_size{this, "Group of Pictures Size", 30};
|
||||
@@ -27,7 +28,8 @@ struct cfg_recording final : cfg::node
|
||||
{
|
||||
node_audio(cfg::node* _this) : cfg::node(_this, "Audio") {}
|
||||
|
||||
cfg::uint<0x10000, 0x17000> audio_codec{this, "AVCodecID", 86018}; // AVCodecID::AV_CODEC_ID_AAC
|
||||
cfg::string codec_name{this, "Audio Codec", ""};
|
||||
cfg::uint<0x10000, 0x17000> codec_id{this, "AVCodecID", 86018}; // AVCodecID::AV_CODEC_ID_AAC
|
||||
cfg::uint<64'000, 320'000> audio_bps{this, "Audio Bitrate", 192'000};
|
||||
|
||||
} audio{ this };
|
||||
|
||||
@@ -527,7 +527,7 @@ void gs_frame::toggle_recording()
|
||||
m_video_encoder->set_path(video_path);
|
||||
m_video_encoder->set_framerate(g_cfg_recording.video.framerate);
|
||||
m_video_encoder->set_video_bitrate(g_cfg_recording.video.video_bps);
|
||||
m_video_encoder->set_video_codec(g_cfg_recording.video.video_codec);
|
||||
m_video_encoder->set_video_codec(g_cfg_recording.video.codec_id, g_cfg_recording.video.codec_name.get());
|
||||
m_video_encoder->set_max_b_frames(g_cfg_recording.video.max_b_frames);
|
||||
m_video_encoder->set_gop_size(g_cfg_recording.video.gop_size);
|
||||
m_video_encoder->set_output_format(output_format);
|
||||
@@ -557,7 +557,7 @@ void gs_frame::toggle_recording()
|
||||
}
|
||||
|
||||
m_video_encoder->set_audio_bitrate(g_cfg_recording.audio.audio_bps);
|
||||
m_video_encoder->set_audio_codec(g_cfg_recording.audio.audio_codec);
|
||||
m_video_encoder->set_audio_codec(g_cfg_recording.audio.codec_id, g_cfg_recording.audio.codec_name.get());
|
||||
m_video_encoder->encode();
|
||||
|
||||
if (m_video_encoder->has_error)
|
||||
|
||||
@@ -24,6 +24,8 @@ extern "C" {
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
constexpr int codec_name_role = Qt::UserRole + 1;
|
||||
|
||||
static std::vector<const AVCodec*> get_video_codecs(const AVOutputFormat* fmt)
|
||||
{
|
||||
std::vector<const AVCodec*> codecs;
|
||||
@@ -142,36 +144,42 @@ recording_settings_dialog::recording_settings_dialog(QWidget* parent)
|
||||
{
|
||||
if (!codec) continue;
|
||||
|
||||
const std::string name = codec->long_name ? codec->long_name : avcodec_get_name(codec->id);
|
||||
const char* codec_name = avcodec_get_name(codec->id);
|
||||
const std::string name = codec->long_name ? codec->long_name : codec_name;
|
||||
ui->combo_video_codec->addItem(QString::fromStdString(name), static_cast<int>(codec->id));
|
||||
ui->combo_video_codec->setItemData(ui->combo_video_codec->findData(static_cast<int>(codec->id)), QString(codec_name), codec_name_role);
|
||||
}
|
||||
|
||||
for (const AVCodec* codec : m_audio_codecs)
|
||||
{
|
||||
if (!codec) continue;
|
||||
|
||||
const std::string name = codec->long_name ? codec->long_name : avcodec_get_name(codec->id);
|
||||
const char* codec_name = avcodec_get_name(codec->id);
|
||||
const std::string name = codec->long_name ? codec->long_name : codec_name;
|
||||
ui->combo_audio_codec->addItem(QString::fromStdString(name), static_cast<int>(codec->id));
|
||||
ui->combo_audio_codec->setItemData(ui->combo_audio_codec->findData(static_cast<int>(codec->id)), QString(codec_name), codec_name_role);
|
||||
}
|
||||
|
||||
connect(ui->combo_video_codec, &QComboBox::currentIndexChanged, this, [this](int index)
|
||||
{
|
||||
const QVariant var = ui->combo_video_codec->itemData(index);
|
||||
if (var.canConvert<int>())
|
||||
const QVariant codec_id = ui->combo_video_codec->itemData(index);
|
||||
const QVariant codec_name = ui->combo_video_codec->itemData(index, codec_name_role);
|
||||
if (codec_id.canConvert<int>() && codec_name.canConvert<QString>())
|
||||
{
|
||||
const int codec_id = var.toInt();
|
||||
g_cfg_recording.video.video_codec.set(codec_id);
|
||||
g_cfg_recording.video.codec_name.set(codec_name.toString().toStdString());
|
||||
g_cfg_recording.video.codec_id.set(codec_id.toInt());
|
||||
update_preset();
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->combo_audio_codec, &QComboBox::currentIndexChanged, this, [this](int index)
|
||||
{
|
||||
const QVariant var = ui->combo_audio_codec->itemData(index);
|
||||
if (var.canConvert<int>())
|
||||
const QVariant codec_id = ui->combo_audio_codec->itemData(index);
|
||||
const QVariant codec_name = ui->combo_audio_codec->itemData(index, codec_name_role);
|
||||
if (codec_id.canConvert<int>() && codec_name.canConvert<QString>())
|
||||
{
|
||||
const int codec_id = var.toInt();
|
||||
g_cfg_recording.audio.audio_codec.set(codec_id);
|
||||
g_cfg_recording.audio.codec_name.set(codec_name.toString().toStdString());
|
||||
g_cfg_recording.audio.codec_id.set(codec_id.toInt());
|
||||
update_preset();
|
||||
}
|
||||
});
|
||||
@@ -279,8 +287,25 @@ void recording_settings_dialog::update_ui()
|
||||
|
||||
ui->combo_resolution->setCurrentIndex(ui->combo_resolution->findData(QVariant::fromValue(QPair<int, int>(g_cfg_recording.video.width.get(), g_cfg_recording.video.height.get()))));
|
||||
ui->combo_framerate->setCurrentIndex(ui->combo_framerate->findData(static_cast<int>(g_cfg_recording.video.framerate.get())));
|
||||
ui->combo_video_codec->setCurrentIndex(ui->combo_video_codec->findData(static_cast<int>(g_cfg_recording.video.video_codec.get())));
|
||||
ui->combo_audio_codec->setCurrentIndex(ui->combo_audio_codec->findData(static_cast<int>(g_cfg_recording.audio.audio_codec.get())));
|
||||
|
||||
if (const int index = ui->combo_video_codec->findData(QString::fromStdString(g_cfg_recording.video.codec_name.get()), codec_name_role); index >= 0)
|
||||
{
|
||||
ui->combo_video_codec->setCurrentIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->combo_video_codec->setCurrentIndex(ui->combo_video_codec->findData(static_cast<int>(g_cfg_recording.video.codec_id.get())));
|
||||
}
|
||||
|
||||
if (const int index = ui->combo_audio_codec->findData(QString::fromStdString(g_cfg_recording.audio.codec_name.get()), codec_name_role); index >= 0)
|
||||
{
|
||||
ui->combo_audio_codec->setCurrentIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->combo_audio_codec->setCurrentIndex(ui->combo_audio_codec->findData(static_cast<int>(g_cfg_recording.audio.codec_id.get())));
|
||||
}
|
||||
|
||||
ui->spinbox_video_bitrate->setValue(g_cfg_recording.video.video_bps);
|
||||
ui->spinbox_audio_bitrate->setValue(g_cfg_recording.audio.audio_bps);
|
||||
ui->spinbox_gop_size->setValue(g_cfg_recording.video.gop_size);
|
||||
@@ -295,8 +320,14 @@ void recording_settings_dialog::update_ui()
|
||||
ui->spinbox_gop_size->blockSignals(false);
|
||||
ui->spinbox_max_b_frames->blockSignals(false);
|
||||
|
||||
const auto get_codec_name = [](const std::vector<const AVCodec*>& codecs, u32 id)
|
||||
const auto get_codec_name = [](const std::vector<const AVCodec*>& codecs, u32 id, const std::string& codec_name)
|
||||
{
|
||||
if (const AVCodec* codec = avcodec_find_encoder_by_name(codec_name.c_str()))
|
||||
{
|
||||
const std::string name = codec->long_name ? codec->long_name : avcodec_get_name(codec->id);
|
||||
return name;
|
||||
}
|
||||
|
||||
for (const AVCodec* codec : codecs)
|
||||
{
|
||||
if (codec && codec->id == static_cast<AVCodecID>(id))
|
||||
@@ -323,9 +354,9 @@ void recording_settings_dialog::update_ui()
|
||||
fmt::format("%d x %d\n%d fps\n%s\n%d\n%s\n%d\n%d\n%d",
|
||||
g_cfg_recording.video.width.get(), g_cfg_recording.video.height.get(),
|
||||
g_cfg_recording.video.framerate.get(),
|
||||
get_codec_name(m_video_codecs, g_cfg_recording.video.video_codec.get()),
|
||||
get_codec_name(m_video_codecs, g_cfg_recording.video.codec_id.get(), g_cfg_recording.video.codec_name.get()),
|
||||
g_cfg_recording.video.video_bps.get(),
|
||||
get_codec_name(m_audio_codecs, g_cfg_recording.audio.audio_codec.get()),
|
||||
get_codec_name(m_audio_codecs, g_cfg_recording.audio.codec_id.get(), g_cfg_recording.audio.codec_name.get()),
|
||||
g_cfg_recording.audio.audio_bps.get(),
|
||||
g_cfg_recording.video.gop_size.get(),
|
||||
g_cfg_recording.video.max_b_frames.get()
|
||||
@@ -340,10 +371,12 @@ void recording_settings_dialog::select_preset(quality_preset preset, cfg_recordi
|
||||
return;
|
||||
}
|
||||
|
||||
cfg.audio.audio_codec.set(static_cast<u32>(AVCodecID::AV_CODEC_ID_AAC));
|
||||
cfg.audio.codec_name.set("");
|
||||
cfg.audio.codec_id.set(static_cast<u32>(AVCodecID::AV_CODEC_ID_AAC));
|
||||
cfg.audio.audio_bps.set(192'000); // 192 kbps
|
||||
|
||||
cfg.video.video_codec.set(static_cast<u32>(AVCodecID::AV_CODEC_ID_MPEG4));
|
||||
cfg.video.codec_name.set("");
|
||||
cfg.video.codec_id.set(static_cast<u32>(AVCodecID::AV_CODEC_ID_MPEG4));
|
||||
cfg.video.pixel_format.set(static_cast<u32>(::AV_PIX_FMT_YUV420P));
|
||||
|
||||
switch (preset)
|
||||
@@ -437,11 +470,13 @@ recording_settings_dialog::quality_preset recording_settings_dialog::current_pre
|
||||
g_cfg_recording.video.width.get() == cfg.video.width.get() &&
|
||||
g_cfg_recording.video.height.get() == cfg.video.height.get() &&
|
||||
g_cfg_recording.video.pixel_format.get() == cfg.video.pixel_format.get() &&
|
||||
g_cfg_recording.video.video_codec.get() == cfg.video.video_codec.get() &&
|
||||
g_cfg_recording.video.codec_name.get() == cfg.video.codec_name.get() &&
|
||||
g_cfg_recording.video.codec_id.get() == cfg.video.codec_id.get() &&
|
||||
g_cfg_recording.video.video_bps.get() == cfg.video.video_bps.get() &&
|
||||
g_cfg_recording.video.max_b_frames.get() == cfg.video.max_b_frames.get() &&
|
||||
g_cfg_recording.video.gop_size.get() == cfg.video.gop_size.get() &&
|
||||
g_cfg_recording.audio.audio_codec.get() == cfg.audio.audio_codec.get() &&
|
||||
g_cfg_recording.audio.codec_name.get() == cfg.audio.codec_name.get() &&
|
||||
g_cfg_recording.audio.codec_id.get() == cfg.audio.codec_id.get() &&
|
||||
g_cfg_recording.audio.audio_bps.get() == cfg.audio.audio_bps.get())
|
||||
{
|
||||
return preset;
|
||||
|
||||
+15
-24
@@ -799,9 +799,10 @@ namespace utils
|
||||
m_out_format = std::move(format);
|
||||
}
|
||||
|
||||
void video_encoder::set_video_codec(s32 codec_id)
|
||||
void video_encoder::set_video_codec(s32 codec_id, std::string_view codec_name)
|
||||
{
|
||||
m_video_codec_id = codec_id;
|
||||
m_video_codec_name = codec_name;
|
||||
}
|
||||
|
||||
void video_encoder::set_max_b_frames(s32 max_b_frames)
|
||||
@@ -829,9 +830,10 @@ namespace utils
|
||||
m_audio_bitrate_bps = bitrate;
|
||||
}
|
||||
|
||||
void video_encoder::set_audio_codec(s32 codec_id)
|
||||
void video_encoder::set_audio_codec(s32 codec_id, std::string_view codec_name)
|
||||
{
|
||||
m_audio_codec_id = codec_id;
|
||||
m_audio_codec_name = codec_name;
|
||||
}
|
||||
|
||||
void video_encoder::pause(bool flush)
|
||||
@@ -992,9 +994,12 @@ namespace utils
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
const AVCodecID video_codec = static_cast<AVCodecID>(m_video_codec_id);
|
||||
const AVCodecID audio_codec = static_cast<AVCodecID>(m_audio_codec_id);
|
||||
const AVOutputFormat* out_format = find_format(video_codec, audio_codec);
|
||||
const AVCodec* selected_video_codec = avcodec_find_encoder_by_name(m_video_codec_name.c_str());
|
||||
const AVCodec* selected_audio_codec = avcodec_find_encoder_by_name(m_audio_codec_name.c_str());
|
||||
|
||||
const AVCodecID video_codec_id = selected_video_codec ? selected_video_codec->id : static_cast<AVCodecID>(m_video_codec_id);
|
||||
const AVCodecID audio_codec_id = selected_audio_codec ? selected_audio_codec->id : static_cast<AVCodecID>(m_audio_codec_id);
|
||||
const AVOutputFormat* out_format = find_format(video_codec_id, audio_codec_id);
|
||||
|
||||
if (out_format)
|
||||
{
|
||||
@@ -1002,7 +1007,7 @@ namespace utils
|
||||
}
|
||||
else
|
||||
{
|
||||
media_log.error("video_encoder: Could not find a format for the requested video_codec %d and audio_codec %d", m_video_codec_id, m_audio_codec_id);
|
||||
media_log.error("video_encoder: Could not find a format for the requested video_codec '%s' (ID=%d) and audio_codec '%s' (ID=%d)", m_video_codec_name, m_video_codec_id, m_audio_codec_name, m_audio_codec_id);
|
||||
|
||||
// Fallback to some other codec
|
||||
for (const AVCodec* video_codec : video_codecs)
|
||||
@@ -1014,6 +1019,8 @@ namespace utils
|
||||
if (out_format)
|
||||
{
|
||||
media_log.success("video_encoder: Found fallback output format '%s'", out_format->name);
|
||||
selected_video_codec = video_codec;
|
||||
selected_audio_codec = audio_codec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1046,27 +1053,11 @@ namespace utils
|
||||
return;
|
||||
}
|
||||
|
||||
const auto create_context = [this, &av](bool is_video) -> bool
|
||||
const auto create_context = [this, &av, &selected_video_codec, &selected_audio_codec](bool is_video) -> bool
|
||||
{
|
||||
const std::string type = is_video ? "video" : "audio";
|
||||
scoped_av::ctx& ctx = is_video ? av.video : av.audio;
|
||||
|
||||
if (is_video)
|
||||
{
|
||||
if (!(ctx.codec = avcodec_find_encoder(av.format_context->oformat->video_codec)))
|
||||
{
|
||||
media_log.error("video_encoder: avcodec_find_encoder for video failed. video_codec=%d", static_cast<int>(av.format_context->oformat->video_codec));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(ctx.codec = avcodec_find_encoder(av.format_context->oformat->audio_codec)))
|
||||
{
|
||||
media_log.error("video_encoder: avcodec_find_encoder for audio failed. audio_codec=%d", static_cast<int>(av.format_context->oformat->audio_codec));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ctx.codec = is_video ? selected_video_codec : selected_audio_codec;
|
||||
|
||||
if (!(ctx.stream = avformat_new_stream(av.format_context, nullptr)))
|
||||
{
|
||||
|
||||
@@ -111,13 +111,13 @@ namespace utils
|
||||
void set_framerate(u32 framerate);
|
||||
void set_video_bitrate(u32 bitrate);
|
||||
void set_output_format(frame_format format);
|
||||
void set_video_codec(s32 codec_id);
|
||||
void set_video_codec(s32 codec_id, std::string_view codec_name);
|
||||
void set_max_b_frames(s32 max_b_frames);
|
||||
void set_gop_size(s32 gop_size);
|
||||
void set_sample_rate(u32 sample_rate);
|
||||
void set_audio_channels(u32 channels);
|
||||
void set_audio_bitrate(u32 bitrate);
|
||||
void set_audio_codec(s32 codec_id);
|
||||
void set_audio_codec(s32 codec_id, std::string_view codec_name);
|
||||
void pause(bool flush = true) override;
|
||||
void stop(bool flush = true) override;
|
||||
void resume() override;
|
||||
@@ -135,6 +135,7 @@ namespace utils
|
||||
// Video parameters
|
||||
u32 m_video_bitrate_bps = 0;
|
||||
s32 m_video_codec_id = 12; // AV_CODEC_ID_MPEG4
|
||||
std::string m_video_codec_name;
|
||||
s32 m_max_b_frames = 2;
|
||||
s32 m_gop_size = 12;
|
||||
frame_format m_out_format{};
|
||||
@@ -143,5 +144,6 @@ namespace utils
|
||||
u32 m_channels = 2;
|
||||
u32 m_audio_bitrate_bps = 320000;
|
||||
s32 m_audio_codec_id = 86018; // AV_CODEC_ID_AAC
|
||||
std::string m_audio_codec_name;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user