1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-01 00:19:27 +02:00

Bug 2166 - Opus export fails - cannot open codec

This commit is contained in:
Leland Lucius 2020-03-30 12:02:03 -05:00
parent e3f33b3367
commit ddadd8d429
5 changed files with 341 additions and 9 deletions

View File

@ -967,6 +967,7 @@ bool FFmpegLibs::InitLibs(const wxString &libpath_format, bool WXUNUSED(showerr)
FFMPEG_INITALT(avutil, av_frame_free, avcodec, avcodec_free_frame);
FFMPEG_INITDYN(avutil, av_samples_get_buffer_size);
FFMPEG_INITDYN(avutil, av_get_default_channel_layout);
FFMPEG_INITDYN(avutil, av_strerror);
wxLogMessage(wxT("All symbols loaded successfully. Initializing the library."));
#endif

View File

@ -52,6 +52,7 @@ extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/error.h>
#include <libavutil/fifo.h>
#include <libavutil/mathematics.h>
@ -527,6 +528,12 @@ extern "C" {
(int nb_channels),
(nb_channels)
);
FFMPEG_FUNCTION_WITH_RETURN(
int,
av_strerror,
(int errnum, char *errbuf, size_t errbuf_size),
(errnum, errbuf, errbuf_size)
);
//
// libavcodec

View File

@ -445,6 +445,20 @@ bool ExportFFmpeg::InitCodecs(AudacityProject *project)
mSampleRate = 8000;
mEncAudioCodecCtx->bit_rate = gPrefs->Read(wxT("/FileFormats/AMRNBBitRate"), 12200);
break;
case FMT_OPUS:
av_dict_set(&options, "b", gPrefs->Read(wxT("/FileFormats/OPUSBitRate"), wxT("128000")).ToUTF8(), 0);
av_dict_set(&options, "vbr", gPrefs->Read(wxT("/FileFormats/OPUSVbrMode"), wxT("on")).ToUTF8(), 0);
av_dict_set(&options, "compression_level", gPrefs->Read(wxT("/FileFormats/OPUSCompression"), wxT("10")).ToUTF8(), 0);
av_dict_set(&options, "frame_duration", gPrefs->Read(wxT("/FileFormats/OPUSFrameDuration"), wxT("20")).ToUTF8(), 0);
av_dict_set(&options, "application", gPrefs->Read(wxT("/FileFormats/OPUSApplication"), wxT("audio")).ToUTF8(), 0);
av_dict_set(&options, "cutoff", gPrefs->Read(wxT("/FileFormats/OPUSCutoff"), wxT("0")).ToUTF8(), 0);
av_dict_set(&options, "mapping_family", mChannels <= 2 ? "0" : "255", 0);
if (!CheckSampleRate(mSampleRate, ExportFFmpegOPUSOptions::iOPUSSampleRates[4], ExportFFmpegOPUSOptions::iOPUSSampleRates[0], &ExportFFmpegOPUSOptions::iOPUSSampleRates[0]))
{
int bitrate = gPrefs->Read(wxT("/FileFormats/OPUSBitRate"), 128000);
mSampleRate = AskResample(bitrate, mSampleRate, ExportFFmpegOPUSOptions::iOPUSSampleRates[4], ExportFFmpegOPUSOptions::iOPUSSampleRates[0], &ExportFFmpegOPUSOptions::iOPUSSampleRates[0]);
}
break;
case FMT_WMA2:
mEncAudioCodecCtx->bit_rate = gPrefs->Read(wxT("/FileFormats/WMABitRate"), 198000);
if (!CheckSampleRate(mSampleRate,ExportFFmpegWMAOptions::iWMASampleRates[0], ExportFFmpegWMAOptions::iWMASampleRates[4], &ExportFFmpegWMAOptions::iWMASampleRates[0]))
@ -552,12 +566,15 @@ bool ExportFFmpeg::InitCodecs(AudacityProject *project)
}
// Open the codec.
if (avcodec_open2(mEncAudioCodecCtx.get(), codec, &options) < 0)
int rc = avcodec_open2(mEncAudioCodecCtx.get(), codec, &options);
if (rc < 0)
{
char buf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(rc, buf, sizeof(buf));
AudacityMessageBox(
/* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
XO("FFmpeg : ERROR - Can't open audio codec 0x%x.")
.Format( mEncAudioCodecCtx->codec_id ),
XO("FFmpeg : ERROR - Can't open audio codec 0x%x\n\n%s")
.Format(mEncAudioCodecCtx->codec_id, wxString(buf)),
XO("FFmpeg Error"),
wxOK|wxCENTER|wxICON_EXCLAMATION);
return false;
@ -1054,7 +1071,7 @@ int ExportFFmpeg::AskResample(int bitrate, int rate, int lowrate, int highrate,
.Format( rate )
: XO(
"The project sample rate (%d) and bit rate (%d kbps) combination is not\nsupported by the current output file format. ")
.Format( rate, bitrate/1024))
.Format( rate, bitrate/1000))
+ XO("You may resample to one of the rates below.")
);
}
@ -1123,6 +1140,12 @@ void ExportFFmpeg::OptionsCreate(ShuttleGui &S, int format)
safenew ExportFFmpegAMRNBOptions{ S.GetParent(), format } );
return;
}
else if (mSubFormat == FMT_OPUS)
{
S.AddWindow(
safenew ExportFFmpegOPUSOptions{ S.GetParent(), format });
return;
}
else if (mSubFormat == FMT_WMA2)
{
S.AddWindow(

View File

@ -26,6 +26,11 @@
*//***************************************************************//**
\class ExportFFmpegOPUSOptions
\brief Options dialog for FFmpeg exporting of OPUS format.
*//***************************************************************//**
\class ExportFFmpegWMAOptions
\brief Options dialog for FFmpeg exporting of WMA format.
@ -400,6 +405,266 @@ bool ExportFFmpegAMRNBOptions::TransferDataFromWindow()
return true;
}
//----------------------------------------------------------------------------
// ExportFFmpegOPUSOptions Class
//----------------------------------------------------------------------------
const int ExportFFmpegOPUSOptions::iOPUSSampleRates[] =
{ 48000, 24000, 16000, 12000, 8000, 0 };
namespace {
/// Bit Rates supported by OPUS encoder. Setting bit rate to other values will not result in different file size.
ChoiceSetting OPUSBitrate
{
wxT("/FileFormats/OPUSBitrate"),
{
ByColumns,
{
// i18n-hint kbps abbreviates "thousands of bits per second"
XO("24 kbps"),
XO("32 kbps"),
XO("40 kbps"),
XO("48 kbps"),
XO("64 kbps"),
XO("80 kbps"),
XO("96 kbps"),
XO("128 kbps"),
XO("160 kbps"),
XO("192 kbps"),
XO("256 kbps"),
XO("320 kbps"),
XO("510 kbps"),
},
{
wxT("24000"),
wxT("32000"),
wxT("40000"),
wxT("48000"),
wxT("64000"),
wxT("80000"),
wxT("96000"),
wxT("128000"),
wxT("160000"),
wxT("192000"),
wxT("256000"),
wxT("320000"),
wxT("510000"),
}
},
7 // "128 kbps"
};
ChoiceSetting OPUSCompression
{
wxT("/FileFormats/OPUSCompression"),
{
ByColumns,
{
XO("0"),
XO("1"),
XO("2"),
XO("3"),
XO("4"),
XO("5"),
XO("6"),
XO("7"),
XO("8"),
XO("9"),
XO("10"),
},
{
wxT("0"),
wxT("1"),
wxT("2"),
wxT("3"),
wxT("4"),
wxT("5"),
wxT("67"),
wxT("7"),
wxT("8"),
wxT("9"),
wxT("10"),
}
},
10 // "10"
};
ChoiceSetting OPUSVbrMode
{
wxT("/FileFormats/OPUSVbrMode"),
{
ByColumns,
{
XO("Off"),
XO("On"),
XO("Constrained"),
},
{
wxT("off"),
wxT("on"),
wxT("constrained"),
}
},
1 // "On"
};
ChoiceSetting OPUSApplication
{
wxT("/FileFormats/OPUSApplication"),
{
ByColumns,
{
XO("VOIP"),
XO("Audio"),
XO("Low Delay"),
},
{
wxT("voip"),
wxT("audio"),
wxT("lowdelay"),
}
},
1 // "Audio"
};
ChoiceSetting OPUSFrameDuration
{
wxT("/FileFormats/OPUSFrameDuration"),
{
ByColumns,
{
XO("2.5 ms"),
XO("5 ms"),
XO("10 ms"),
XO("20 ms"),
XO("40 ms"),
XO("60 ms"),
},
{
wxT("2.5"),
wxT("5"),
wxT("10"),
wxT("20"),
wxT("40"),
wxT("60"),
}
},
3 // "20"
};
ChoiceSetting OPUSCutoff
{
wxT("/FileFormats/OPUSCutoff"),
{
ByColumns,
{
XO("Disabled"),
XO("Narrowband"),
XO("Mediumband"),
XO("Wideband"),
XO("Super Wideband"),
XO("Fullband"),
},
{
wxT("0"),
wxT("4000"),
wxT("6000"),
wxT("8000"),
wxT("12000"),
wxT("20000"),
}
},
0 // "Disabled"
};
}
ExportFFmpegOPUSOptions::ExportFFmpegOPUSOptions(wxWindow *parent, int WXUNUSED(format))
: wxPanelWrapper(parent, wxID_ANY)
{
ShuttleGui S(this, eIsCreatingFromPrefs);
PopulateOrExchange(S);
TransferDataToWindow();
}
ExportFFmpegOPUSOptions::~ExportFFmpegOPUSOptions()
{
TransferDataFromWindow();
}
///
///
void ExportFFmpegOPUSOptions::PopulateOrExchange(ShuttleGui & S)
{
S.SetSizerProportion(1);
S.SetBorder(4);
S.StartVerticalLay();
{
S.StartHorizontalLay(wxCENTER);
{
S.StartMultiColumn(2, wxCENTER);
{
S.StartMultiColumn(2, wxCENTER);
{
S.TieChoice(
XO("Bit Rate:"),
OPUSBitrate);
S.TieChoice(
XO("Compression"),
OPUSCompression);
S.TieChoice(
XO("Frame Duration:"),
OPUSFrameDuration);
}
S.EndMultiColumn();
S.StartMultiColumn(2, wxCENTER);
{
S.TieChoice(
XO("Vbr Mode:"),
OPUSVbrMode);
S.TieChoice(
XO("Application:"),
OPUSApplication);
S.TieChoice(
XO("Cutoff:"),
OPUSCutoff);
}
S.EndMultiColumn();
}
S.EndMultiColumn();
}
S.EndHorizontalLay();
}
S.EndVerticalLay();
}
///
///
bool ExportFFmpegOPUSOptions::TransferDataToWindow()
{
return true;
}
///
///
bool ExportFFmpegOPUSOptions::TransferDataFromWindow()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);
gPrefs->Flush();
return true;
}
//----------------------------------------------------------------------------
// ExportFFmpegWMAOptions Class
//----------------------------------------------------------------------------
@ -1340,11 +1605,12 @@ ChoiceSetting AACProfiles { wxT("/FileFormats/FFmpegAACProfile"),
/// List of export types
ExposedFormat ExportFFmpegOptions::fmts[] =
{
{FMT_M4A, wxT("M4A"), wxT("m4a"), wxT("ipod"), 48, AV_CANMETA, true, XO("M4A (AAC) Files (FFmpeg)"), AV_CODEC_ID_AAC, true},
{FMT_AC3, wxT("AC3"), wxT("ac3"), wxT("ac3"), 7, AV_VERSION_INT(0,0,0), false, XO("AC3 Files (FFmpeg)"), AV_CODEC_ID_AC3, true},
{FMT_AMRNB, wxT("AMRNB"), wxT("amr"), wxT("amr"), 1, AV_VERSION_INT(0,0,0), false, XO("AMR (narrow band) Files (FFmpeg)"), AV_CODEC_ID_AMR_NB, true},
{FMT_WMA2, wxT("WMA"), wxT("wma"), wxT("asf"), 2, AV_VERSION_INT(52,53,0), false, XO("WMA (version 2) Files (FFmpeg)"), AV_CODEC_ID_WMAV2, true},
{FMT_OTHER, wxT("FFMPEG"), wxT(""), wxT(""), 255, AV_CANMETA, true, XO("Custom FFmpeg Export"), AV_CODEC_ID_NONE, true}
{FMT_M4A, wxT("M4A"), wxT("m4a"), wxT("ipod"), 48, AV_CANMETA, true, XO("M4A (AAC) Files (FFmpeg)"), AV_CODEC_ID_AAC, true},
{FMT_AC3, wxT("AC3"), wxT("ac3"), wxT("ac3"), 7, AV_VERSION_INT(0,0,0), false, XO("AC3 Files (FFmpeg)"), AV_CODEC_ID_AC3, true},
{FMT_AMRNB, wxT("AMRNB"), wxT("amr"), wxT("amr"), 1, AV_VERSION_INT(0,0,0), false, XO("AMR (narrow band) Files (FFmpeg)"), AV_CODEC_ID_AMR_NB, true},
{FMT_OPUS, wxT("OPUS"), wxT("opus"), wxT("opus"), 255, AV_CANMETA, true, XO("OPUS (OggOpus) Files (FFmpeg)"), AV_CODEC_ID_OPUS, true},
{FMT_WMA2, wxT("WMA"), wxT("wma"), wxT("asf"), 2, AV_VERSION_INT(52,53,0), false, XO("WMA (version 2) Files (FFmpeg)"), AV_CODEC_ID_WMAV2, true},
{FMT_OTHER, wxT("FFMPEG"), wxT(""), wxT(""), 255, AV_CANMETA, true, XO("Custom FFmpeg Export"), AV_CODEC_ID_NONE, true}
};
/// Sample rates supported by AAC encoder (must end with zero-element)

View File

@ -36,6 +36,7 @@ enum FFmpegExposedFormat
FMT_M4A,
FMT_AC3,
FMT_AMRNB,
FMT_OPUS,
FMT_WMA2,
FMT_OTHER,
FMT_LAST
@ -122,6 +123,40 @@ private:
int mBitRateFromChoice;
};
class ExportFFmpegOPUSOptions final : public wxPanelWrapper
{
public:
ExportFFmpegOPUSOptions(wxWindow *parent, int format);
~ExportFFmpegOPUSOptions();
void PopulateOrExchange(ShuttleGui & S);
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
static const int iOPUSSampleRates[];
private:
wxSlider *mBitRateSlider;
int mBitRateFromSlider;
wxChoice *mVbrChoice;
int mVbrFromChoice;
wxSlider *mComplexitySlider;
int mComplexityFromSlider;
wxChoice *mFramesizeChoice;
int mFramesizeFromChoice;
wxChoice *mApplicationChoice;
int mApplicationFromChoice;
wxChoice *mCuttoffChoice;
int mCutoffFromChoice;
};
class ExportFFmpegWMAOptions final : public wxPanelWrapper
{
public: