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:
parent
e3f33b3367
commit
ddadd8d429
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user