Audacity 3.2.0
Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
FFmpegExporter Class Referencefinal

Performs actual export. More...

Collaboration diagram for FFmpegExporter:
[legend]

Public Member Functions

 FFmpegExporter (std::shared_ptr< FFmpegFunctions > ffmpeg, const wxFileNameWrapper &filename, int numChannels, int subformat)
 
bool Init (const char *shortname, AudacityProject *project, int sampleRate, const Tags *metadata, const ExportProcessor::Parameters &parameters)
 Format initialization. More...
 
bool EncodeAudioFrame (int16_t *pFrame, size_t frameSize)
 Encodes audio. More...
 
bool Finalize ()
 Flushes audio encoder. More...
 
std::unique_ptr< MixerCreateMixer (const AudacityProject &project, bool selectionOnly, double startTime, double stopTime, MixerOptions::Downmix *mixerSpec)
 

Private Member Functions

bool AddTags (const Tags *metadata)
 Writes metadata. More...
 
void SetMetadata (const Tags *tags, const char *name, const wxChar *tag)
 Sets individual metadata values. More...
 
bool CheckSampleRate (int rate, int lowrate, int highrate, const int *sampRates)
 Check whether or not current project sample rate is compatible with the export codec. More...
 
int AskResample (int bitrate, int rate, int lowrate, int highrate, const int *sampRates)
 Asks user to resample the project or cancel the export procedure. More...
 
bool InitCodecs (int sampleRate, const ExportProcessor::Parameters &parameters)
 Codec initialization. More...
 
void WritePacket (AVPacketWrapper &packet)
 
int EncodeAudio (AVPacketWrapper &pkt, int16_t *audio_samples, int nb_samples)
 

Private Attributes

std::shared_ptr< FFmpegFunctionsmFFmpeg
 
std::unique_ptr< AVOutputFormatWrappermEncFormatDesc
 
int mDefaultFrameSize {}
 
std::unique_ptr< AVStreamWrappermEncAudioStream
 
int mEncAudioFifoOutBufSize {}
 
wxFileNameWrapper mName
 
int mSubFormat {}
 
int mBitRate {}
 
int mSampleRate {}
 
unsigned mChannels {}
 
bool mSupportsUTF8 {true}
 
std::unique_ptr< FifoBuffermEncAudioFifo
 
AVDataBuffer< int16_t > mEncAudioFifoOutBuf
 
std::unique_ptr< AVFormatContextWrappermEncFormatCtx
 
std::unique_ptr< AVCodecContextWrappermEncAudioCodecCtx
 

Static Private Attributes

static constexpr auto MaxAudioPacketSize { 128 * 1024 }
 

Detailed Description

Performs actual export.

Definition at line 588 of file ExportFFmpeg.cpp.

Constructor & Destructor Documentation

◆ FFmpegExporter()

FFmpegExporter::FFmpegExporter ( std::shared_ptr< FFmpegFunctions ffmpeg,
const wxFileNameWrapper filename,
int  numChannels,
int  subformat 
)

Definition at line 714 of file ExportFFmpeg.cpp.

718 : mFFmpeg(std::move(ffmpeg))
719 , mName(filename)
720 , mChannels(numChannels)
721 , mSubFormat(subFormat)
722{
723 if (!mFFmpeg) {
725 }
726}
std::shared_ptr< FFmpegFunctions > mFFmpeg
wxFileNameWrapper mName
unsigned mChannels
static std::shared_ptr< FFmpegFunctions > Load(bool fromUserPathOnly=false)

References FFmpegFunctions::Load(), and mFFmpeg.

Here is the call graph for this function:

Member Function Documentation

◆ AddTags()

bool FFmpegExporter::AddTags ( const Tags metadata)
private

Writes metadata.

Definition at line 1694 of file ExportFFmpeg.cpp.

1695{
1696 if (tags == NULL)
1697 {
1698 return false;
1699 }
1700
1701 SetMetadata(tags, "album", TAG_ALBUM);
1702 SetMetadata(tags, "comment", TAG_COMMENTS);
1703 SetMetadata(tags, "genre", TAG_GENRE);
1704 SetMetadata(tags, "title", TAG_TITLE);
1705 SetMetadata(tags, "track", TAG_TRACK);
1706
1707 // Bug 2564: Add m4a tags
1708 if (mEncFormatDesc->GetAudioCodec() == mFFmpeg->GetAVCodecID(AUDACITY_AV_CODEC_ID_AAC))
1709 {
1710 SetMetadata(tags, "artist", TAG_ARTIST);
1711 SetMetadata(tags, "date", TAG_YEAR);
1712 }
1713 else
1714 {
1715 SetMetadata(tags, "author", TAG_ARTIST);
1716 SetMetadata(tags, "year", TAG_YEAR);
1717 }
1718
1719 return true;
1720}
@ AUDACITY_AV_CODEC_ID_AAC
Definition: AVCodecID.h:296
#define TAG_TRACK
Definition: Tags.h:61
#define TAG_COMMENTS
Definition: Tags.h:64
#define TAG_GENRE
Definition: Tags.h:63
#define TAG_ALBUM
Definition: Tags.h:60
#define TAG_YEAR
Definition: Tags.h:62
#define TAG_TITLE
Definition: Tags.h:58
#define TAG_ARTIST
Definition: Tags.h:59
void SetMetadata(const Tags *tags, const char *name, const wxChar *tag)
Sets individual metadata values.
std::unique_ptr< AVOutputFormatWrapper > mEncFormatDesc

References AUDACITY_AV_CODEC_ID_AAC, mEncFormatDesc, mFFmpeg, SetMetadata(), TAG_ALBUM, TAG_ARTIST, TAG_COMMENTS, TAG_GENRE, TAG_TITLE, TAG_TRACK, and TAG_YEAR.

Referenced by Init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AskResample()

int FFmpegExporter::AskResample ( int  bitrate,
int  rate,
int  lowrate,
int  highrate,
const int *  sampRates 
)
private

Asks user to resample the project or cancel the export procedure.

Definition at line 1740 of file ExportFFmpeg.cpp.

1741{
1742#if defined(FFMPEG_AUTO_RESAMPLE)
1743 std::vector<int> rates;
1744
1745 for (int i = 0; sampRates[i]; ++i)
1746 {
1747 rates.push_back(sampRates[i]);
1748 }
1749
1750 std::sort(rates.begin(), rates.end());
1751
1752 int bestRate = 0;
1753 for (auto i : rates)
1754 {
1755 bestRate = i;
1756 if (i > rate)
1757 {
1758 break;
1759 }
1760 }
1761
1762 return bestRate;
1763#else
1764 wxDialogWrapper d(nullptr, wxID_ANY, XO("Invalid sample rate"));
1765 d.SetName();
1766 wxChoice *choice;
1768
1769 int selected = -1;
1770
1771 S.StartVerticalLay();
1772 {
1773 S.SetBorder(10);
1774 S.StartStatic(XO("Resample"));
1775 {
1776 S.StartHorizontalLay(wxALIGN_CENTER, false);
1777 {
1778 S.AddTitle(
1779 (bitrate == 0
1780 ? XO(
1781"The project sample rate (%d) is not supported by the current output\nfile format. ")
1782 .Format( rate )
1783 : XO(
1784"The project sample rate (%d) and bit rate (%d kbps) combination is not\nsupported by the current output file format. ")
1785 .Format( rate, bitrate/1000))
1786 + XO("You may resample to one of the rates below.")
1787 );
1788 }
1789 S.EndHorizontalLay();
1790
1791 S.StartHorizontalLay(wxALIGN_CENTER, false);
1792 {
1793 choice = S.AddChoice(XO("Sample Rates"),
1794 [&]{
1795 TranslatableStrings choices;
1796 for (int i = 0; sampRates[i] > 0; i++)
1797 {
1798 int label = sampRates[i];
1799 if ((!lowrate || label >= lowrate) && (!highrate || label <= highrate))
1800 {
1801 wxString name = wxString::Format(wxT("%d"),label);
1802 choices.push_back( Verbatim( name ) );
1803 if (label <= rate)
1804 selected = i;
1805 }
1806 }
1807 return choices;
1808 }(),
1809 std::max( 0, selected )
1810 );
1811 }
1812 S.EndHorizontalLay();
1813 }
1814 S.EndStatic();
1815
1816 S.AddStandardButtons();
1817 }
1818 S.EndVerticalLay();
1819
1820 d.Layout();
1821 d.Fit();
1822 d.SetMinSize(d.GetSize());
1823 d.Center();
1824
1825 if (d.ShowModal() == wxID_CANCEL) {
1826 return 0;
1827 }
1828
1829 return wxAtoi(choice->GetStringSelection());
1830#endif
1831}
wxT("CloseDown"))
static const std::vector< int > sampRates
Definition: ExportMP3.cpp:197
XO("Cut/Copy/Paste")
@ eIsCreating
Definition: ShuttleGui.h:37
wxString name
Definition: TagsEditor.cpp:166
TranslatableString label
Definition: TagsEditor.cpp:165
#define S(N)
Definition: ToChars.cpp:64
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::vector< TranslatableString > TranslatableStrings
Abstract base class used in importing a file.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640

References eIsCreating, label, name, S, sampRates, wxDialogWrapper::SetName(), Verbatim(), wxT(), and XO().

Referenced by InitCodecs().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CheckSampleRate()

bool FFmpegExporter::CheckSampleRate ( int  rate,
int  lowrate,
int  highrate,
const int *  sampRates 
)
private

Check whether or not current project sample rate is compatible with the export codec.

Definition at line 956 of file ExportFFmpeg.cpp.

957{
958 if (lowrate && highrate)
959 {
960 if (rate < lowrate || rate > highrate)
961 {
962 return false;
963 }
964 }
965
966 if (sampRates)
967 {
968 for (int i = 0; sampRates[i] > 0; i++)
969 {
970 if (rate == sampRates[i])
971 {
972 return true;
973 }
974 }
975 }
976
977 return false;
978}

References sampRates.

Referenced by InitCodecs().

Here is the caller graph for this function:

◆ CreateMixer()

std::unique_ptr< Mixer > FFmpegExporter::CreateMixer ( const AudacityProject project,
bool  selectionOnly,
double  startTime,
double  stopTime,
MixerOptions::Downmix mixerSpec 
)

Definition at line 728 of file ExportFFmpeg.cpp.

731{
733 project, selectionOnly, startTime, stopTime, mChannels, mDefaultFrameSize,
734 true, mSampleRate, int16Sample, mixerSpec);
735}
const auto project
static std::unique_ptr< Mixer > CreateMixer(const AudacityProject &project, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerOptions::Downmix *mixerSpec)

References ExportPluginHelpers::CreateMixer(), int16Sample, mChannels, mDefaultFrameSize, mSampleRate, and project.

Here is the call graph for this function:

◆ EncodeAudio()

int FFmpegExporter::EncodeAudio ( AVPacketWrapper pkt,
int16_t *  audio_samples,
int  nb_samples 
)
private

Definition at line 1331 of file ExportFFmpeg.cpp.

1332{
1333 // Assume *pkt is already initialized.
1334
1335 int i, ch, buffer_size, ret, got_output = 0;
1336 AVDataBuffer<uint8_t> samples;
1337
1338 std::unique_ptr<AVFrameWrapper> frame;
1339
1340 if (audio_samples) {
1341 frame = mFFmpeg->CreateAVFrameWrapper();
1342
1343 if (!frame)
1344 return AUDACITY_AVERROR(ENOMEM);
1345
1346 frame->SetSamplesCount(nb_samples);
1347 frame->SetFormat(mEncAudioCodecCtx->GetSampleFmt());
1348 frame->SetChannelLayout(mEncAudioCodecCtx->GetChannelLayout());
1349
1350 buffer_size = mFFmpeg->av_samples_get_buffer_size(
1351 NULL, mEncAudioCodecCtx->GetChannels(), nb_samples,
1352 mEncAudioCodecCtx->GetSampleFmt(), 0);
1353
1354 if (buffer_size < 0) {
1355 throw ExportException(_("FFmpeg : ERROR - Could not get sample buffer size"));
1356 }
1357
1358 samples = mFFmpeg->CreateMemoryBuffer<uint8_t>(buffer_size);
1359
1360 if (samples.empty()) {
1361 throw ExportException(_("FFmpeg : ERROR - Could not allocate bytes for samples buffer"));
1362 }
1363 /* setup the data pointers in the AVFrame */
1364 ret = mFFmpeg->avcodec_fill_audio_frame(
1365 frame->GetWrappedValue(), mEncAudioCodecCtx->GetChannels(),
1366 mEncAudioCodecCtx->GetSampleFmt(), samples.data(), buffer_size, 0);
1367
1368 if (ret < 0) {
1369 throw ExportException(_("FFmpeg : ERROR - Could not setup audio frame"));
1370 }
1371
1372 const int channelsCount = mEncAudioCodecCtx->GetChannels();
1373
1374 for (ch = 0; ch < mEncAudioCodecCtx->GetChannels(); ch++)
1375 {
1376 for (i = 0; i < nb_samples; i++) {
1377 switch (static_cast<AudacityAVSampleFormat>(
1378 mEncAudioCodecCtx->GetSampleFmt()))
1379 {
1381 ((uint8_t*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount]/258 + 128;
1382 break;
1384 ((uint8_t*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount]/258 + 128;
1385 break;
1387 ((int16_t*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount];
1388 break;
1390 ((int16_t*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount];
1391 break;
1393 ((int32_t*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount]<<16;
1394 break;
1396 ((int32_t*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount]<<16;
1397 break;
1399 ((float*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount] / 32767.0;
1400 break;
1402 ((float*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount] / 32767.;
1403 break;
1404 default:
1405 wxASSERT(false);
1406 break;
1407 }
1408 }
1409 }
1410 }
1411
1412 pkt.ResetData();
1413
1414 pkt.SetStreamIndex(mEncAudioStream->GetIndex());
1415
1416 if (mFFmpeg->avcodec_send_frame != nullptr)
1417 {
1418 ret = mFFmpeg->avcodec_send_frame(
1419 mEncAudioCodecCtx->GetWrappedValue(),
1420 frame ? frame->GetWrappedValue() : nullptr);
1421
1422 while (ret >= 0)
1423 {
1424 ret = mFFmpeg->avcodec_receive_packet(
1425 mEncAudioCodecCtx->GetWrappedValue(), pkt.GetWrappedValue());
1426
1427 if (ret == AUDACITY_AVERROR(EAGAIN) || ret == AUDACITY_AVERROR_EOF)
1428 {
1429 ret = 0;
1430 break;
1431 }
1432 else if (ret < 0)
1433 break;
1434
1435 WritePacket(pkt);
1436
1437 got_output = true;
1438 }
1439 }
1440 else
1441 {
1442 ret = mFFmpeg->avcodec_encode_audio2(
1443 mEncAudioCodecCtx->GetWrappedValue(), pkt.GetWrappedValue(),
1444 frame ? frame->GetWrappedValue() : nullptr, &got_output);
1445
1446 if (ret == 0)
1447 {
1448 WritePacket(pkt);
1449 }
1450 }
1451
1452 if (ret < 0 && ret != AUDACITY_AVERROR_EOF) {
1453
1454 char buf[64];
1455 mFFmpeg->av_strerror(ret, buf, sizeof(buf));
1456 wxLogDebug(buf);
1457
1458 throw ExportException(_("FFmpeg : ERROR - encoding frame failed"));
1459 }
1460
1461 pkt.ResetTimestamps(); // We don't set frame timestamps thus don't trust the AVPacket timestamps
1462
1463 return got_output;
1464}
std::vector< T, AVAllocator< T > > AVDataBuffer
#define AUDACITY_AVERROR(e)
Definition: FFmpegTypes.h:28
#define AUDACITY_AVERROR_EOF
Definition: FFmpegTypes.h:32
AudacityAVSampleFormat
Definition: FFmpegTypes.h:148
@ AUDACITY_AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: FFmpegTypes.h:158
@ AUDACITY_AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: FFmpegTypes.h:157
@ AUDACITY_AV_SAMPLE_FMT_FLTP
float, planar
Definition: FFmpegTypes.h:159
@ AUDACITY_AV_SAMPLE_FMT_S16
signed 16 bits
Definition: FFmpegTypes.h:151
@ AUDACITY_AV_SAMPLE_FMT_S32
signed 32 bits
Definition: FFmpegTypes.h:152
@ AUDACITY_AV_SAMPLE_FMT_FLT
float
Definition: FFmpegTypes.h:153
@ AUDACITY_AV_SAMPLE_FMT_U8
unsigned 8 bits
Definition: FFmpegTypes.h:150
@ AUDACITY_AV_SAMPLE_FMT_U8P
unsigned 8 bits, planar
Definition: FFmpegTypes.h:156
#define _(s)
Definition: Internat.h:73
virtual void ResetData() noexcept=0
virtual void SetStreamIndex(int index) noexcept=0
AVPacket * GetWrappedValue() noexcept
virtual void ResetTimestamps() noexcept=0
std::unique_ptr< AVStreamWrapper > mEncAudioStream
void WritePacket(AVPacketWrapper &packet)
std::unique_ptr< AVCodecContextWrapper > mEncAudioCodecCtx

References _, AUDACITY_AV_SAMPLE_FMT_FLT, AUDACITY_AV_SAMPLE_FMT_FLTP, AUDACITY_AV_SAMPLE_FMT_S16, AUDACITY_AV_SAMPLE_FMT_S16P, AUDACITY_AV_SAMPLE_FMT_S32, AUDACITY_AV_SAMPLE_FMT_S32P, AUDACITY_AV_SAMPLE_FMT_U8, AUDACITY_AV_SAMPLE_FMT_U8P, AUDACITY_AVERROR, AUDACITY_AVERROR_EOF, AVPacketWrapper::GetWrappedValue(), mEncAudioCodecCtx, mEncAudioStream, mFFmpeg, AVPacketWrapper::ResetData(), AVPacketWrapper::ResetTimestamps(), AVPacketWrapper::SetStreamIndex(), and WritePacket().

Referenced by EncodeAudioFrame(), and Finalize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EncodeAudioFrame()

bool FFmpegExporter::EncodeAudioFrame ( int16_t *  pFrame,
size_t  frameSize 
)

Encodes audio.

Definition at line 1549 of file ExportFFmpeg.cpp.

1550{
1551 const auto frameSize = numSamples * sizeof(int16_t) * mChannels;
1552 int nBytesToWrite = 0;
1553 uint8_t *pRawSamples = nullptr;
1554 int nAudioFrameSizeOut = mDefaultFrameSize * mEncAudioCodecCtx->GetChannels() * sizeof(int16_t);
1555 int ret;
1556
1557 nBytesToWrite = frameSize;
1558 pRawSamples = (uint8_t*)pFrame;
1559
1560 // Put the raw audio samples into the FIFO.
1561 ret = mEncAudioFifo->Write(pRawSamples, nBytesToWrite);
1562
1563 if (ret != nBytesToWrite) {
1564 throw ExportErrorException("FFmpeg:913");
1565 }
1566
1567 if (nAudioFrameSizeOut > mEncAudioFifoOutBufSize) {
1568 throw ExportException(_("FFmpeg : ERROR - nAudioFrameSizeOut too large."));
1569 }
1570
1571 // Read raw audio samples out of the FIFO in nAudioFrameSizeOut byte-sized groups to encode.
1572 while (mEncAudioFifo->GetAvailable() >= nAudioFrameSizeOut)
1573 {
1574 mEncAudioFifo->Read(
1575 mEncAudioFifoOutBuf.data(), nAudioFrameSizeOut);
1576
1577 std::unique_ptr<AVPacketWrapper> pkt = mFFmpeg->CreateAVPacketWrapper();
1578
1579 ret = EncodeAudio(*pkt, // out
1580 mEncAudioFifoOutBuf.data(), // in
1582
1583 if (ret < 0)
1584 return false;
1585 }
1586 return true;
1587}
int EncodeAudio(AVPacketWrapper &pkt, int16_t *audio_samples, int nb_samples)
AVDataBuffer< int16_t > mEncAudioFifoOutBuf
std::unique_ptr< FifoBuffer > mEncAudioFifo

References _, EncodeAudio(), mChannels, mDefaultFrameSize, mEncAudioCodecCtx, mEncAudioFifo, mEncAudioFifoOutBuf, mEncAudioFifoOutBufSize, and mFFmpeg.

Here is the call graph for this function:

◆ Finalize()

bool FFmpegExporter::Finalize ( )

Flushes audio encoder.

Definition at line 1467 of file ExportFFmpeg.cpp.

1468{
1469 // Flush the audio FIFO and encoder.
1470 for (;;)
1471 {
1472 std::unique_ptr<AVPacketWrapper> pkt = mFFmpeg->CreateAVPacketWrapper();
1473
1474 const auto nFifoBytes =
1475 mEncAudioFifo->GetAvailable(); // any bytes left in audio FIFO?
1476
1477 int encodeResult = 0;
1478
1479 // Flush the audio FIFO first if necessary. It won't contain a _full_ audio frame because
1480 // if it did we'd have pulled it from the FIFO during the last encodeAudioFrame() call
1481 if (nFifoBytes > 0)
1482 {
1483 const int nAudioFrameSizeOut = mDefaultFrameSize * mEncAudioCodecCtx->GetChannels() * sizeof(int16_t);
1484
1485 if (nAudioFrameSizeOut > mEncAudioFifoOutBufSize || nFifoBytes > mEncAudioFifoOutBufSize) {
1486 throw ExportException(_("FFmpeg : ERROR - Too much remaining data."));
1487 }
1488
1489 // We have an incomplete buffer of samples left, encode it.
1490 // If codec supports CODEC_CAP_SMALL_LAST_FRAME, we can feed it with smaller frame
1491 // Or if frame_size is 1, then it's some kind of PCM codec, they don't have frames and will be fine with the samples
1492 // Otherwise we'll send a full frame of audio + silence padding to ensure all audio is encoded
1493 int frame_size = mDefaultFrameSize;
1494 if (
1495 mEncAudioCodecCtx->GetCodec()->GetCapabilities() &
1497 frame_size == 1)
1498 {
1499 frame_size = nFifoBytes /
1500 (mEncAudioCodecCtx->GetChannels() * sizeof(int16_t));
1501 }
1502
1503 wxLogDebug(wxT("FFmpeg : Audio FIFO still contains %lld bytes, writing %d sample frame ..."),
1504 nFifoBytes, frame_size);
1505
1506 // Fill audio buffer with zeroes. If codec tries to read the whole buffer,
1507 // it will just read silence. If not - who cares?
1509 //const AVCodec *codec = mEncAudioCodecCtx->codec;
1510
1511 // Pull the bytes out from the FIFO and feed them to the encoder.
1512 if (mEncAudioFifo->Read(mEncAudioFifoOutBuf.data(), nFifoBytes) == nFifoBytes)
1513 {
1514 encodeResult = EncodeAudio(*pkt, mEncAudioFifoOutBuf.data(), frame_size);
1515 }
1516 else
1517 {
1518 wxLogDebug(wxT("FFmpeg : Reading from Audio FIFO failed, aborting"));
1519 // TODO: more precise message
1520 throw ExportErrorException("FFmpeg:825");
1521 }
1522 }
1523 else
1524 {
1525 // Fifo is empty, flush encoder. May be called multiple times.
1526 encodeResult =
1527 EncodeAudio(*pkt.get(), nullptr, 0);
1528 }
1529
1530 if (encodeResult < 0) {
1531 // TODO: more precise message
1532 throw ExportErrorException("FFmpeg:837");
1533 }
1534 else if (encodeResult == 0)
1535 break;
1536 }
1537
1538 // Write any file trailers.
1539 if (mFFmpeg->av_write_trailer(mEncFormatCtx->GetWrappedValue()) != 0)
1540 {
1541 // TODO: more precise message
1542 throw ExportErrorException("FFmpeg:868");
1543 }
1544
1545 return true;
1546}
#define AUDACITY_AV_CODEC_CAP_SMALL_LAST_FRAME
Definition: FFmpegTypes.h:84
std::unique_ptr< AVFormatContextWrapper > mEncFormatCtx

References _, AUDACITY_AV_CODEC_CAP_SMALL_LAST_FRAME, EncodeAudio(), mDefaultFrameSize, mEncAudioCodecCtx, mEncAudioFifo, mEncAudioFifoOutBuf, mEncAudioFifoOutBufSize, mEncFormatCtx, mFFmpeg, and wxT().

Here is the call graph for this function:

◆ Init()

bool FFmpegExporter::Init ( const char *  shortname,
AudacityProject project,
int  sampleRate,
const Tags metadata,
const ExportProcessor::Parameters parameters 
)

Format initialization.

Definition at line 859 of file ExportFFmpeg.cpp.

864{
865 if (!mFFmpeg)
866 return false;
867
868 // See if libavformat has modules that can write our output format. If so, mEncFormatDesc
869 // will describe the functions used to write the format (used internally by libavformat)
870 // and the default video/audio codecs that the format uses.
871 const auto path = mName.GetFullPath();
872 if ((mEncFormatDesc = mFFmpeg->GuessOutputFormat(shortname, OSINPUT(path), nullptr)) == nullptr)
873 {
874 throw ExportException(_("FFmpeg : ERROR - Can't determine format description for file \"%s\".").Format(path));
875 }
876
877 // mEncFormatCtx is used by libavformat to carry around context data re our output file.
878 mEncFormatCtx = mFFmpeg->CreateAVFormatContext();
879 if (!mEncFormatCtx)
880 {
881 throw ExportException(_("FFmpeg : ERROR - Can't allocate output format context."));
882 }
883
884 // Initialise the output format context.
885 mEncFormatCtx->SetOutputFormat(mFFmpeg->CreateAVOutputFormatWrapper(mEncFormatDesc->GetWrappedValue()));
886 mEncFormatCtx->SetFilename(OSINPUT(path));
887
888 // At the moment Audacity can export only one audio stream
889 if ((mEncAudioStream = mEncFormatCtx->CreateStream()) == nullptr)
890 {
891 throw ExportException(_("FFmpeg : ERROR - Can't add audio stream to output file \"%s\"."));
892 }
893
894 // Documentation for avformat_new_stream says
895 // "User is required to call avcodec_close() and avformat_free_context() to clean
896 // up the allocation by avformat_new_stream()."
897
898 // We use smart pointers that ensure these cleanups either in their destructors or
899 // sooner if they are reset. These are std::unique_ptr with nondefault deleter
900 // template parameters.
901
902 // mEncFormatCtx takes care of avformat_free_context(), so
903 // mEncAudioStream can be a plain pointer.
904
905 // mEncAudioCodecCtx now becomes responsible for closing the codec:
906 mEncAudioCodecCtx = mEncAudioStream->GetAVCodecContext();
907 mEncAudioStream->SetId(0);
908
909 // Open the output file.
910 if (!(mEncFormatDesc->GetFlags() & AUDACITY_AVFMT_NOFILE))
911 {
913 mEncFormatCtx->OpenOutputContext(path);
914
916 {
917 throw ExportException(_("FFmpeg : ERROR - Can't open output file \"%s\" to write. Error code is %d.")
918 .Format(path, static_cast<int>(result)));
919 }
920 }
921
922 // Open the audio stream's codec and initialise any stream related data.
923 if(!InitCodecs(sampleRate, parameters))
924 return false;
925
926 if (mEncAudioStream->SetParametersFromContext(*mEncAudioCodecCtx) < 0)
927 return false;
928
929 if (metadata == NULL)
930 metadata = &Tags::Get( *project );
931
932 // Add metadata BEFORE writing the header.
933 // At the moment that works with ffmpeg-git and ffmpeg-0.5 for MP4.
935 const auto avfver = mFFmpeg->AVFormatVersion.GetIntVersion();
936 if (canmeta && (canmeta == AV_CANMETA || canmeta <= avfver))
937 {
939 AddTags(metadata);
940 }
941
942 // Write headers to the output file.
943 int err =
944 mFFmpeg->avformat_write_header(mEncFormatCtx->GetWrappedValue(), nullptr);
945
946 if (err < 0)
947 {
948 throw ExportException(XO("FFmpeg : ERROR - Can't write headers to output file \"%s\". Error code is %d.")
949 .Format( path, err )
950 .Translation());
951 }
952
953 return true;
954}
#define AV_CANMETA
Definition: FFmpegDefines.h:20
#define AUDACITY_AVFMT_NOFILE
Definition: FFmpegTypes.h:34
#define OSINPUT(X)
static ExposedFormat fmts[]
List of export types.
bool AddTags(const Tags *metadata)
Writes metadata.
bool InitCodecs(int sampleRate, const ExportProcessor::Parameters &parameters)
Codec initialization.
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:214
const int canmetadata
!=0 if format supports metadata, AV_CANMETA any avformat version, otherwise version support added
bool canutf8
true if format supports metadata in UTF-8, false otherwise

References _, AddTags(), AUDACITY_AVFMT_NOFILE, AV_CANMETA, ExposedFormat::canmetadata, ExposedFormat::canutf8, ExportFFmpegOptions::fmts, Tags::Get(), InitCodecs(), mEncAudioCodecCtx, mEncAudioStream, mEncFormatCtx, mEncFormatDesc, mFFmpeg, mName, mSubFormat, mSupportsUTF8, OSINPUT, project, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, AVIOContextWrapper::Success, and XO().

Here is the call graph for this function:

◆ InitCodecs()

bool FFmpegExporter::InitCodecs ( int  sampleRate,
const ExportProcessor::Parameters parameters 
)
private

Codec initialization.

Definition at line 980 of file ExportFFmpeg.cpp.

982{
983 std::unique_ptr<AVCodecWrapper> codec;
984
986
987 // Get the sample rate from the passed settings if we haven't set it before.
988 // Doing this only when not set allows us to carry the sample rate from one
989 // iteration of ExportMultiple to the next. This prevents multiple resampling
990 // dialogs in the event the codec can't support the specified rate.
991 if (!mSampleRate)
992 {
993 //TODO: Does not work with export multiple any more...
995 }
996
997 // Configure the audio stream's codec context.
998
999 const auto codecID = ExportFFmpegOptions::fmts[mSubFormat].codecid;
1000
1001 mEncAudioCodecCtx->SetGlobalQuality(-99999); //quality mode is off by default;
1002
1003 // Each export type has its own settings
1004 switch (mSubFormat)
1005 {
1006 case FMT_M4A:
1007 {
1009
1010 q = wxClip( q, 98 * mChannels, 160 * mChannels );
1011 // Set bit rate to between 98 kbps and 320 kbps (if two channels)
1012 mEncAudioCodecCtx->SetBitRate(q * 1000);
1014 mEncAudioCodecCtx->SetCutoff(0);
1015
1016 break;
1017 }
1018 case FMT_AC3:
1020 if (!CheckSampleRate(
1022 iAC3SampleRates[2],
1023 &iAC3SampleRates[0]))
1024 {
1026 mEncAudioCodecCtx->GetBitRate(), mSampleRate,
1027 iAC3SampleRates[0],
1028 iAC3SampleRates[2],
1029 &iAC3SampleRates[0]);
1030 }
1031 break;
1032 case FMT_AMRNB:
1033 mSampleRate = 8000;
1035 break;
1036#ifdef SHOW_FFMPEG_OPUS_EXPORT
1037 case FMT_OPUS:
1038 options.Set("b", ExportPluginHelpers::GetParameterValue<std::string>(parameters, OPUSOptionIDBitRate, "128000"), 0);
1039 options.Set("vbr", ExportPluginHelpers::GetParameterValue<std::string>(parameters, OPUSOptionIDVBRMode, "on"), 0);
1040 options.Set("compression_level", ExportPluginHelpers::GetParameterValue<std::string>(parameters, OPUSOptionIDCompression, "10"), 0);
1041 options.Set("frame_duration", ExportPluginHelpers::GetParameterValue<std::string>(parameters, OPUSOptionIDFrameDuration, "20"), 0);
1042 options.Set("application", ExportPluginHelpers::GetParameterValue<std::string>(parameters, OPUSOptionIDApplication, "audio"), 0);
1043 options.Set("cutoff", ExportPluginHelpers::GetParameterValue<std::string>(parameters, OPUSOptionIDCutoff, "0"), 0);
1044 options.Set("mapping_family", mChannels <= 2 ? "0" : "255", 0);
1045 break;
1046#endif
1047 case FMT_WMA2:
1049 if (!CheckSampleRate(
1051 iWMASampleRates[4],
1052 &iWMASampleRates[0]))
1053 {
1055 mEncAudioCodecCtx->GetBitRate(), mSampleRate,
1056 iWMASampleRates[0],
1057 iWMASampleRates[4],
1058 &iWMASampleRates[0]);
1059 }
1060 break;
1061 case FMT_OTHER:
1062 {
1063 AVDictionaryWrapper streamMetadata = mEncAudioStream->GetMetadata();
1064 streamMetadata.Set(
1065 "language",
1066 ExportPluginHelpers::GetParameterValue<std::string>(parameters, FELanguageID), 0);
1067
1068 mEncAudioStream->SetMetadata(streamMetadata);
1069
1070 mEncAudioCodecCtx->SetSampleRate(
1071 ExportPluginHelpers::GetParameterValue(parameters, FESampleRateID, 0));
1072
1073 if (mEncAudioCodecCtx->GetSampleRate() != 0)
1074 mSampleRate = mEncAudioCodecCtx->GetSampleRate();
1075
1076 mEncAudioCodecCtx->SetBitRate(
1077 ExportPluginHelpers::GetParameterValue(parameters, FEBitrateID, 0));
1078
1079 mEncAudioCodecCtx->SetCodecTagFourCC(
1080 ExportPluginHelpers::GetParameterValue<std::string>(parameters, FETagID).c_str());
1081
1082 mEncAudioCodecCtx->SetGlobalQuality(
1083 ExportPluginHelpers::GetParameterValue(parameters, FEQualityID, -99999));
1084 mEncAudioCodecCtx->SetCutoff(
1085 ExportPluginHelpers::GetParameterValue(parameters, FECutoffID, 0));
1086 mEncAudioCodecCtx->SetFlags2(0);
1087
1088 if (ExportPluginHelpers::GetParameterValue(parameters, FEBitReservoirID, true))
1089 options.Set("reservoir", "1", 0);
1090
1091 if (ExportPluginHelpers::GetParameterValue(parameters, FEVariableBlockLenID, true))
1092 mEncAudioCodecCtx->SetFlags2(
1093 mEncAudioCodecCtx->GetFlags2() | 0x0004); // WMA only?
1094
1095 mEncAudioCodecCtx->SetCompressionLevel(
1096 ExportPluginHelpers::GetParameterValue(parameters, FECompLevelID, -1));
1097 mEncAudioCodecCtx->SetFrameSize(
1098 ExportPluginHelpers::GetParameterValue(parameters, FEFrameSizeID, 0));
1099
1100 // FIXME The list of supported options for the selected encoder should be
1101 // extracted instead of a few hardcoded
1102
1103 options.Set(
1104 "lpc_coeff_precision",
1105 ExportPluginHelpers::GetParameterValue(parameters, FELPCCoeffsID, 0));
1106 options.Set(
1107 "min_prediction_order",
1108 ExportPluginHelpers::GetParameterValue(parameters, FEMinPredID, -1));
1109 options.Set(
1110 "max_prediction_order",
1111 ExportPluginHelpers::GetParameterValue(parameters, FEMaxPredID, -1));
1112 options.Set(
1113 "min_partition_order",
1114 ExportPluginHelpers::GetParameterValue(parameters, FEMinPartOrderID, -1));
1115 options.Set(
1116 "max_partition_order",
1117 ExportPluginHelpers::GetParameterValue(parameters, FEMaxPartOrderID, -1));
1118 options.Set(
1119 "prediction_order_method",
1120 ExportPluginHelpers::GetParameterValue(parameters, FEPredOrderID, 0));
1121 options.Set(
1122 "muxrate",
1123 ExportPluginHelpers::GetParameterValue(parameters, FEMuxRateID, 0));
1124
1125 mEncFormatCtx->SetPacketSize(
1126 ExportPluginHelpers::GetParameterValue(parameters, FEPacketSizeID, 0));
1127
1128 codec = mFFmpeg->CreateEncoder(
1129 ExportPluginHelpers::GetParameterValue<std::string>(parameters, FECodecID).c_str());
1130
1131 if (!codec)
1132 codec = mFFmpeg->CreateEncoder(mEncFormatDesc->GetAudioCodec());
1133 }
1134 break;
1135 default:
1136 return false;
1137 }
1138
1139 // This happens if user refused to resample the project
1140 if (mSampleRate == 0) return false;
1141
1142 if (mEncAudioCodecCtx->GetGlobalQuality() >= 0)
1143 {
1144 mEncAudioCodecCtx->SetFlags(
1146 }
1147 else
1148 {
1149 mEncAudioCodecCtx->SetGlobalQuality(0);
1150 }
1151
1152 mEncAudioCodecCtx->SetGlobalQuality(mEncAudioCodecCtx->GetGlobalQuality() * AUDACITY_FF_QP2LAMBDA);
1153 mEncAudioCodecCtx->SetSampleRate(mSampleRate);
1154 mEncAudioCodecCtx->SetChannelLayout(mFFmpeg->CreateDefaultChannelLayout(mChannels).get());
1155 mEncAudioCodecCtx->SetTimeBase({ 1, mSampleRate });
1157 mEncAudioCodecCtx->SetStrictStdCompliance(
1159
1160 if (codecID == AUDACITY_AV_CODEC_ID_AC3)
1161 {
1162 // As of Jan 4, 2011, the default AC3 encoder only accept SAMPLE_FMT_FLT samples.
1163 // But, currently, Audacity only supports SAMPLE_FMT_S16. So, for now, look for the
1164 // "older" AC3 codec. this is not a proper solution, but will suffice until other
1165 // encoders no longer support SAMPLE_FMT_S16.
1166 codec = mFFmpeg->CreateEncoder("ac3_fixed");
1167 }
1168
1169 if (!codec)
1170 {
1171 codec = mFFmpeg->CreateEncoder(mFFmpeg->GetAVCodecID(codecID));
1172 }
1173
1174 // Is the required audio codec compiled into libavcodec?
1175 if (codec == NULL)
1176 {
1177 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
1178 throw ExportException(XO("FFmpeg cannot find audio codec 0x%x.\nSupport for this codec is probably not compiled in.")
1179 .Format(static_cast<const unsigned int>(codecID.value))
1180 .Translation());
1181 }
1182
1183 if (codec->GetSampleFmts()) {
1184 for (int i = 0; codec->GetSampleFmts()[i] != AUDACITY_AV_SAMPLE_FMT_NONE; i++)
1185 {
1186 AVSampleFormatFwd fmt = codec->GetSampleFmts()[i];
1187
1188 if (
1197 {
1198 mEncAudioCodecCtx->SetSampleFmt(fmt);
1199 }
1200
1201 if (
1204 break;
1205 }
1206 }
1207
1208 if (codec->GetSupportedSamplerates())
1209 {
1210 // Workaround for crash in bug #2378. Proper fix is to get a newer version of FFmpeg.
1211 if (codec->GetId() == mFFmpeg->GetAVCodecID(AUDACITY_AV_CODEC_ID_AAC))
1212 {
1213 std::vector<int> rates;
1214 int i = 0;
1215
1216 while (codec->GetSupportedSamplerates()[i] &&
1217 codec->GetSupportedSamplerates()[i] != 7350)
1218 {
1219 rates.push_back(codec->GetSupportedSamplerates()[i++]);
1220 }
1221
1222 rates.push_back(0);
1223
1224 if (!CheckSampleRate(mSampleRate, 0, 0, rates.data()))
1225 {
1226 mSampleRate = AskResample(0, mSampleRate, 0, 0, rates.data());
1227 mEncAudioCodecCtx->SetSampleRate(mSampleRate);
1228 }
1229 }
1230 else
1231 {
1232 if (!CheckSampleRate(
1233 mSampleRate, 0, 0, codec->GetSupportedSamplerates()))
1234 {
1236 0, mSampleRate, 0, 0, codec->GetSupportedSamplerates());
1237 mEncAudioCodecCtx->SetSampleRate(mSampleRate);
1238 }
1239 }
1240
1241 // This happens if user refused to resample the project
1242 if (mSampleRate == 0)
1243 {
1244 return false;
1245 }
1246 }
1247
1248 if (mEncFormatCtx->GetOutputFormat()->GetFlags() & AUDACITY_AVFMT_GLOBALHEADER)
1249 {
1252 }
1253
1254 // Open the codec.
1255 int rc = mEncAudioCodecCtx->Open(codec.get(), &options);
1256 if (rc < 0)
1257 {
1258 TranslatableString errmsg;
1259
1260 switch (rc)
1261 {
1262 case AUDACITY_AVERROR(EPERM):
1263 errmsg = XO("The codec reported a generic error (EPERM)");
1264 break;
1265 case AUDACITY_AVERROR(EINVAL):
1266 errmsg = XO("The codec reported an invalid parameter (EINVAL)");
1267 break;
1268 default:
1269 char buf[64];
1270 mFFmpeg->av_strerror(rc, buf, sizeof(buf));
1271 errmsg = Verbatim(buf);
1272 }
1273
1274 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
1275 throw ExportException(XO("Can't open audio codec \"%s\" (0x%x)\n\n%s")
1276 .Format(codec->GetName(), codecID.value, errmsg)
1277 .Translation());
1278 }
1279
1280 mDefaultFrameSize = mEncAudioCodecCtx->GetFrameSize();
1281
1282 if (mDefaultFrameSize == 0)
1283 mDefaultFrameSize = 1024; // arbitrary non zero value;
1284
1285 wxLogDebug(
1286 wxT("FFmpeg : Audio Output Codec Frame Size: %d samples."),
1287 mEncAudioCodecCtx->GetFrameSize());
1288
1289 // The encoder may require a minimum number of raw audio samples for each encoding but we can't
1290 // guarantee we'll get this minimum each time an audio frame is decoded from the input file so
1291 // we use a FIFO to store up incoming raw samples until we have enough for one call to the codec.
1292 mEncAudioFifo = std::make_unique<FifoBuffer>(mDefaultFrameSize * mChannels * sizeof(int16_t));
1293
1295 // Allocate a buffer to read OUT of the FIFO into. The FIFO maintains its own buffer internally.
1296 mEncAudioFifoOutBuf = mFFmpeg->CreateMemoryBuffer<int16_t>(mEncAudioFifoOutBufSize);
1297
1298 if (mEncAudioFifoOutBuf.empty())
1299 {
1300 throw ExportException(_("FFmpeg : ERROR - Can't allocate buffer to read into from audio FIFO."));
1301 }
1302
1303 return true;
1304}
@ AUDACITY_AV_CODEC_ID_AC3
Definition: AVCodecID.h:297
@ FMT_M4A
@ FMT_OTHER
@ FMT_AC3
@ FMT_WMA2
@ FMT_AMRNB
#define AUDACITY_FF_PROFILE_AAC_LOW
Definition: FFmpegTypes.h:103
#define AUDACITY_AV_CODEC_FLAG_GLOBAL_HEADER
Definition: FFmpegTypes.h:115
#define AUDACITY_FF_COMPLIANCE_EXPERIMENTAL
Definition: FFmpegTypes.h:98
#define AUDACITY_FF_QP2LAMBDA
Definition: FFmpegTypes.h:89
#define AUDACITY_AV_CODEC_FLAG_QSCALE
Definition: FFmpegTypes.h:82
#define AUDACITY_AVFMT_GLOBALHEADER
Definition: FFmpegTypes.h:40
int AVSampleFormatFwd
Definition: FFmpegTypes.h:132
@ AUDACITY_AV_SAMPLE_FMT_NONE
Definition: FFmpegTypes.h:149
void Set(const std::string_view &key, const std::string &value, int flags=0) noexcept
static T GetParameterValue(const ExportProcessor::Parameters &parameters, int id, T defaultValue=T())
bool CheckSampleRate(int rate, int lowrate, int highrate, const int *sampRates)
Check whether or not current project sample rate is compatible with the export codec.
int AskResample(int bitrate, int rate, int lowrate, int highrate, const int *sampRates)
Asks user to resample the project or cancel the export procedure.
static constexpr auto MaxAudioPacketSize
Holds a msgid for the translation catalog; may also bind format arguments.
AudacityAVCodecID codecid
codec ID (see libavcodec/avcodec.h)

References _, anonymous_namespace{ExportFFmpeg.cpp}::AACOptionIDQuality, anonymous_namespace{ExportFFmpeg.cpp}::AC3OptionIDBitRate, anonymous_namespace{ExportFFmpeg.cpp}::AMRNBOptionIDBitRate, AskResample(), AUDACITY_AV_CODEC_FLAG_GLOBAL_HEADER, AUDACITY_AV_CODEC_FLAG_QSCALE, AUDACITY_AV_CODEC_ID_AAC, AUDACITY_AV_CODEC_ID_AC3, AUDACITY_AV_SAMPLE_FMT_FLT, AUDACITY_AV_SAMPLE_FMT_FLTP, AUDACITY_AV_SAMPLE_FMT_NONE, AUDACITY_AV_SAMPLE_FMT_S16, AUDACITY_AV_SAMPLE_FMT_S16P, AUDACITY_AV_SAMPLE_FMT_S32, AUDACITY_AV_SAMPLE_FMT_S32P, AUDACITY_AV_SAMPLE_FMT_U8, AUDACITY_AV_SAMPLE_FMT_U8P, AUDACITY_AVERROR, AUDACITY_AVFMT_GLOBALHEADER, AUDACITY_FF_COMPLIANCE_EXPERIMENTAL, AUDACITY_FF_PROFILE_AAC_LOW, AUDACITY_FF_QP2LAMBDA, CheckSampleRate(), ExposedFormat::codecid, FMT_AC3, FMT_AMRNB, FMT_M4A, FMT_OTHER, FMT_WMA2, ExportFFmpegOptions::fmts, ExportPluginHelpers::GetParameterValue(), anonymous_namespace{ExportFFmpeg.cpp}::iAC3SampleRates, anonymous_namespace{ExportFFmpeg.cpp}::iWMASampleRates, MaxAudioPacketSize, mChannels, mDefaultFrameSize, mEncAudioCodecCtx, mEncAudioFifo, mEncAudioFifoOutBuf, mEncAudioFifoOutBufSize, mEncAudioStream, mEncFormatCtx, mEncFormatDesc, mFFmpeg, mSampleRate, mSubFormat, anonymous_namespace{ExportOpus.cpp}::OPUSOptionIDApplication, anonymous_namespace{ExportOpus.cpp}::OPUSOptionIDBitRate, anonymous_namespace{ExportOpus.cpp}::OPUSOptionIDCutoff, anonymous_namespace{ExportOpus.cpp}::OPUSOptionIDFrameDuration, anonymous_namespace{ExportOpus.cpp}::OPUSOptionIDVBRMode, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, AVDictionaryWrapper::Set(), Verbatim(), anonymous_namespace{ExportFFmpeg.cpp}::WMAOptionIDBitRate, wxT(), and XO().

Referenced by Init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetMetadata()

void FFmpegExporter::SetMetadata ( const Tags tags,
const char *  name,
const wxChar *  tag 
)
private

Sets individual metadata values.

Definition at line 1722 of file ExportFFmpeg.cpp.

1723{
1724 if (tags->HasTag(tag))
1725 {
1726 wxString value = tags->GetTag(tag);
1727
1728 AVDictionaryWrapper metadata = mEncFormatCtx->GetMetadata();
1729
1730 metadata.Set(name, mSupportsUTF8 ? value : value.mb_str(), 0);
1731 mEncFormatCtx->SetMetadata(metadata);
1732 }
1733}
bool HasTag(const wxString &name) const
Definition: Tags.cpp:397
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:406

References Tags::GetTag(), Tags::HasTag(), mEncFormatCtx, mSupportsUTF8, name, and AVDictionaryWrapper::Set().

Referenced by AddTags().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WritePacket()

void FFmpegExporter::WritePacket ( AVPacketWrapper packet)
private

Definition at line 1306 of file ExportFFmpeg.cpp.

1307{
1308 // Set presentation time of frame (currently in the codec's timebase) in the
1309 // stream timebase.
1310 if (pkt.GetPresentationTimestamp() != AUDACITY_AV_NOPTS_VALUE)
1311 pkt.RescalePresentationTimestamp(
1312 mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
1313
1314 if (pkt.GetDecompressionTimestamp() != AUDACITY_AV_NOPTS_VALUE)
1315 pkt.RescaleDecompressionTimestamp(
1316 mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
1317
1318 if (pkt.GetDuration() > 0)
1319 pkt.RescaleDuration(
1320 mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
1321
1322 if (
1323 mFFmpeg->av_interleaved_write_frame(
1324 mEncFormatCtx->GetWrappedValue(), pkt.GetWrappedValue()) != 0)
1325 {
1326 throw ExportException(_("FFmpeg : ERROR - Couldn't write audio frame to output file."));
1327 }
1328}
#define AUDACITY_AV_NOPTS_VALUE
Definition: FFmpegTypes.h:74

References _, AUDACITY_AV_NOPTS_VALUE, AVPacketWrapper::GetDecompressionTimestamp(), AVPacketWrapper::GetDuration(), AVPacketWrapper::GetPresentationTimestamp(), AVPacketWrapper::GetWrappedValue(), mEncAudioCodecCtx, mEncAudioStream, mEncFormatCtx, mFFmpeg, AVPacketWrapper::RescaleDecompressionTimestamp(), AVPacketWrapper::RescaleDuration(), and AVPacketWrapper::RescalePresentationTimestamp().

Referenced by EncodeAudio().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ MaxAudioPacketSize

constexpr auto FFmpegExporter::MaxAudioPacketSize { 128 * 1024 }
staticconstexprprivate

Definition at line 590 of file ExportFFmpeg.cpp.

Referenced by InitCodecs().

◆ mBitRate

int FFmpegExporter::mBitRate {}
private

Definition at line 649 of file ExportFFmpeg.cpp.

◆ mChannels

unsigned FFmpegExporter::mChannels {}
private

Definition at line 651 of file ExportFFmpeg.cpp.

Referenced by CreateMixer(), EncodeAudioFrame(), and InitCodecs().

◆ mDefaultFrameSize

int FFmpegExporter::mDefaultFrameSize {}
private

Definition at line 642 of file ExportFFmpeg.cpp.

Referenced by CreateMixer(), EncodeAudioFrame(), Finalize(), and InitCodecs().

◆ mEncAudioCodecCtx

std::unique_ptr<AVCodecContextWrapper> FFmpegExporter::mEncAudioCodecCtx
private

Definition at line 658 of file ExportFFmpeg.cpp.

Referenced by EncodeAudio(), EncodeAudioFrame(), Finalize(), Init(), InitCodecs(), and WritePacket().

◆ mEncAudioFifo

std::unique_ptr<FifoBuffer> FFmpegExporter::mEncAudioFifo
private

Definition at line 655 of file ExportFFmpeg.cpp.

Referenced by EncodeAudioFrame(), Finalize(), and InitCodecs().

◆ mEncAudioFifoOutBuf

AVDataBuffer<int16_t> FFmpegExporter::mEncAudioFifoOutBuf
private

Definition at line 656 of file ExportFFmpeg.cpp.

Referenced by EncodeAudioFrame(), Finalize(), and InitCodecs().

◆ mEncAudioFifoOutBufSize

int FFmpegExporter::mEncAudioFifoOutBufSize {}
private

Definition at line 644 of file ExportFFmpeg.cpp.

Referenced by EncodeAudioFrame(), Finalize(), and InitCodecs().

◆ mEncAudioStream

std::unique_ptr<AVStreamWrapper> FFmpegExporter::mEncAudioStream
private

Definition at line 643 of file ExportFFmpeg.cpp.

Referenced by EncodeAudio(), Init(), InitCodecs(), and WritePacket().

◆ mEncFormatCtx

std::unique_ptr<AVFormatContextWrapper> FFmpegExporter::mEncFormatCtx
private

Definition at line 657 of file ExportFFmpeg.cpp.

Referenced by Finalize(), Init(), InitCodecs(), SetMetadata(), and WritePacket().

◆ mEncFormatDesc

std::unique_ptr<AVOutputFormatWrapper> FFmpegExporter::mEncFormatDesc
private

Definition at line 641 of file ExportFFmpeg.cpp.

Referenced by AddTags(), Init(), and InitCodecs().

◆ mFFmpeg

std::shared_ptr<FFmpegFunctions> FFmpegExporter::mFFmpeg
private

◆ mName

wxFileNameWrapper FFmpegExporter::mName
private

Definition at line 646 of file ExportFFmpeg.cpp.

Referenced by Init().

◆ mSampleRate

int FFmpegExporter::mSampleRate {}
private

Definition at line 650 of file ExportFFmpeg.cpp.

Referenced by CreateMixer(), and InitCodecs().

◆ mSubFormat

int FFmpegExporter::mSubFormat {}
private

Definition at line 648 of file ExportFFmpeg.cpp.

Referenced by Init(), and InitCodecs().

◆ mSupportsUTF8

bool FFmpegExporter::mSupportsUTF8 {true}
private

Definition at line 652 of file ExportFFmpeg.cpp.

Referenced by Init(), and SetMetadata().


The documentation for this class was generated from the following file: