Audacity  3.0.3
ExportFFmpeg.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  ExportFFmpeg.cpp
6 
7  Audacity(R) is copyright (c) 1999-2009 Audacity Team.
8  License: GPL v2. See License.txt.
9 
10  LRN
11 
12 ******************************************************************//*******************************************************************/
20 
21 
22 
23 
24 #include "../FFmpeg.h"
25 #include "FFmpegFunctions.h"
26 
27 #include <wx/choice.h>
28 #include <wx/log.h>
29 #include <wx/intl.h>
30 #include <wx/timer.h>
31 #include <wx/string.h>
32 #include <wx/textctrl.h>
33 #include <wx/listbox.h>
34 #include <wx/window.h>
35 #include <wx/spinctrl.h>
36 #include <wx/combobox.h>
37 
38 #include "../Mix.h"
39 #include "ProjectRate.h"
40 #include "ProjectSettings.h"
41 #include "../Tags.h"
42 #include "../Track.h"
43 #include "../widgets/AudacityMessageBox.h"
44 #include "../widgets/ProgressDialog.h"
45 #include "wxFileNameWrapper.h"
46 
47 #include "Export.h"
48 
49 #include "ExportFFmpegDialogs.h"
50 #include "SelectFile.h"
51 
52 #if defined(WIN32) && _MSC_VER < 1900
53 #define snprintf _snprintf
54 #endif
55 
56 #if defined(USE_FFMPEG)
57 
58 // Define this to automatically resample audio to the nearest supported sample rate
59 #define FFMPEG_AUTO_RESAMPLE 1
60 
61 static bool CheckFFmpegPresence(bool quiet = false)
62 {
63  bool result = true;
64  auto ffmpeg = FFmpegFunctions::Load();
65 
66  if (!ffmpeg)
67  {
68  if (!quiet)
69  {
71 "Properly configured FFmpeg is required to proceed.\nYou can configure it at Preferences > Libraries."));
72  }
73  result = false;
74  }
75 
76  return result;
77 }
78 
79 static int AdjustFormatIndex(int format)
80 {
81  int subFormat = -1;
82  for (int i = 0; i <= FMT_OTHER; i++)
83  {
84  if (ExportFFmpegOptions::fmts[i].compiledIn) subFormat++;
85  if (subFormat == format || i == FMT_OTHER)
86  {
87  subFormat = i;
88  break;
89  }
90  }
91  return subFormat;
92 }
93 
94 //----------------------------------------------------------------------------
95 // ExportFFmpeg
96 //----------------------------------------------------------------------------
97 
98 class ExportFFmpeg final : public ExportPlugin
99 {
100 public:
101 
102  ExportFFmpeg();
103  ~ExportFFmpeg() override;
104 
106  bool CheckFileName(wxFileName &filename, int format = 0) override;
107 
109  bool Init(const char *shortname, AudacityProject *project, const Tags *metadata, int subformat);
110 
112  bool AddTags(const Tags *metadata);
113 
115  void SetMetadata(const Tags *tags, const char *name, const wxChar *tag);
116 
118  bool EncodeAudioFrame(int16_t *pFrame, size_t frameSize);
119 
121  bool Finalize();
122 
123  void FreeResources();
124 
127  void OptionsCreate(ShuttleGui &S, int format) override;
128 
130  bool CheckSampleRate(int rate, int lowrate, int highrate, const int *sampRates);
131 
133  int AskResample(int bitrate, int rate, int lowrate, int highrate, const int *sampRates);
134 
146  std::unique_ptr<ProgressDialog> &pDialog,
147  unsigned channels,
148  const wxFileNameWrapper &fName,
149  bool selectedOnly,
150  double t0,
151  double t1,
152  MixerSpec *mixerSpec = NULL,
153  const Tags *metadata = NULL,
154  int subformat = 0) override;
155 
156 private:
158  bool InitCodecs(AudacityProject* project);
159 
160  std::shared_ptr<FFmpegFunctions> mFFmpeg;
161 
162  std::unique_ptr<AVOutputFormatWrapper> mEncFormatDesc; // describes our output file to libavformat
164  std::unique_ptr<AVStreamWrapper> mEncAudioStream; // the output audio stream (may remain NULL)
166 
168 
169  int mSubFormat{};
170  int mBitRate{};
171  int mSampleRate{};
172  unsigned mChannels{};
174 
175  // Smart pointer fields, their order is the reverse in which they are reset in FreeResources():
176  std::unique_ptr<AVFifoBufferWrapper> mEncAudioFifo; // FIFO to write incoming audio samples into
177  AVDataBuffer<int16_t> mEncAudioFifoOutBuf; // buffer to read _out_ of the FIFO into
178  std::unique_ptr<AVFormatContextWrapper> mEncFormatCtx; // libavformat's context for our output file
179  std::unique_ptr<AVCodecContextWrapper> mEncAudioCodecCtx; // the encoder for the output audio stream
180 };
181 
183 : ExportPlugin()
184 {
185  mEncFormatDesc = NULL; // describes our output file to libavformat
186  mEncAudioStream = NULL; // the output audio stream (may remain NULL)
187  #define MAX_AUDIO_PACKET_SIZE (128 * 1024)
189 
190  mSampleRate = 0;
191  mSupportsUTF8 = true;
192 
194 
195  int avfver = mFFmpeg ? mFFmpeg->AVFormatVersion.GetIntVersion() : 0;
196 
197  int newfmt;
198  // Adds export types from the export type list
199  for (newfmt = 0; newfmt < FMT_LAST; newfmt++)
200  {
201  wxString shortname(ExportFFmpegOptions::fmts[newfmt].shortname);
202  //Don't hide export types when there's no av-libs, and don't hide FMT_OTHER
203  if (newfmt < FMT_OTHER && mFFmpeg)
204  {
205  // Format/Codec support is compiled in?
206  auto avoformat = mFFmpeg->GuessOutputFormat(shortname.mb_str(), nullptr, nullptr);
207  auto avcodec = mFFmpeg->CreateEncoder(mFFmpeg->GetAVCodecID(ExportFFmpegOptions::fmts[newfmt].codecid));
208 
209  if (avoformat == NULL || avcodec == NULL)
210  {
211  ExportFFmpegOptions::fmts[newfmt].compiledIn = false;
212  continue;
213  }
214  }
215  int fmtindex = AddFormat() - 1;
216  SetFormat(ExportFFmpegOptions::fmts[newfmt].name,fmtindex);
217  AddExtension(ExportFFmpegOptions::fmts[newfmt].extension,fmtindex);
218  // For some types add other extensions
219  switch(newfmt)
220  {
221  case FMT_M4A:
222  AddExtension(wxT("3gp"),fmtindex);
223  AddExtension(wxT("m4r"),fmtindex);
224  AddExtension(wxT("mp4"),fmtindex);
225  break;
226  case FMT_WMA2:
227  AddExtension(wxT("asf"),fmtindex);
228  AddExtension(wxT("wmv"),fmtindex);
229  break;
230  default:
231  break;
232  }
233 
234  SetMaxChannels(ExportFFmpegOptions::fmts[newfmt].maxchannels,fmtindex);
235  SetDescription(ExportFFmpegOptions::fmts[newfmt].description, fmtindex);
236 
237  int canmeta = ExportFFmpegOptions::fmts[newfmt].canmetadata;
238  if (canmeta && (canmeta == AV_CANMETA || canmeta <= avfver))
239  {
240  SetCanMetaData(true,fmtindex);
241  }
242  else
243  {
244  SetCanMetaData(false,fmtindex);
245  }
246  }
247 }
248 
250 {
251 }
252 
253 bool ExportFFmpeg::CheckFileName(wxFileName & WXUNUSED(filename), int WXUNUSED(format))
254 {
255  bool result = true;
256 
257  // Show "Locate FFmpeg" dialog
258  if (!CheckFFmpegPresence(true))
259  {
260  FindFFmpegLibs();
262 
263  return LoadFFmpeg(true);
264  }
265 
266  return result;
267 }
268 
269 bool ExportFFmpeg::Init(const char *shortname, AudacityProject *project, const Tags *metadata, int subformat)
270 {
271  // This will undo the acquisition of resources along any early exit path:
272  auto deleter = [](ExportFFmpeg *This) {
273  if (This)
274  This->FreeResources();
275  };
276  std::unique_ptr<ExportFFmpeg, decltype(deleter)> cleanup{ this, deleter };
277  //FFmpegLibsInst()->LoadLibs(NULL,true); //Loaded at startup or from Prefs now
278 
279  if (!mFFmpeg)
280  return false;
281 
282 
283  // See if libavformat has modules that can write our output format. If so, mEncFormatDesc
284  // will describe the functions used to write the format (used internally by libavformat)
285  // and the default video/audio codecs that the format uses.
286  const auto path = mName.GetFullPath();
287  if ((mEncFormatDesc = mFFmpeg->GuessOutputFormat(shortname, OSINPUT(path), nullptr)) == nullptr)
288  {
290  XO(
291 "FFmpeg : ERROR - Can't determine format description for file \"%s\".")
292  .Format( path ),
293  XO("FFmpeg Error"),
294  wxOK|wxCENTER|wxICON_EXCLAMATION );
295  return false;
296  }
297 
298  // mEncFormatCtx is used by libavformat to carry around context data re our output file.
299  mEncFormatCtx = mFFmpeg->CreateAVFormatContext();
300  if (!mEncFormatCtx)
301  {
303  XO("FFmpeg : ERROR - Can't allocate output format context."),
304  XO("FFmpeg Error"),
305  wxOK|wxCENTER|wxICON_EXCLAMATION);
306  return false;
307  }
308 
309  // Initialise the output format context.
310  mEncFormatCtx->SetOutputFormat(mFFmpeg->CreateAVOutputFormatWrapper(mEncFormatDesc->GetWrappedValue()));
311  mEncFormatCtx->SetFilename(OSINPUT(path));
312 
313  // At the moment Audacity can export only one audio stream
314  if ((mEncAudioStream = mEncFormatCtx->CreateStream()) == nullptr)
315  {
317  XO("FFmpeg : ERROR - Can't add audio stream to output file \"%s\".")
318  .Format( path ),
319  XO("FFmpeg Error"),
320  wxOK|wxCENTER|wxICON_EXCLAMATION);
321  return false;
322  }
323 
324  // Documentation for avformat_new_stream says
325  // "User is required to call avcodec_close() and avformat_free_context() to clean
326  // up the allocation by avformat_new_stream()."
327 
328  // We use smart pointers that ensure these cleanups either in their destructors or
329  // sooner if they are reset. These are std::unique_ptr with nondefault deleter
330  // template parameters.
331 
332  // mEncFormatCtx takes care of avformat_free_context(), so
333  // mEncAudioStream can be a plain pointer.
334 
335  // mEncAudioCodecCtx now becomes responsible for closing the codec:
336  mEncAudioCodecCtx = mEncAudioStream->GetAVCodecContext();
337  mEncAudioStream->SetId(0);
338 
339  // Open the output file.
340  if (!(mEncFormatDesc->GetFlags() & AUDACITY_AVFMT_NOFILE))
341  {
343  mEncFormatCtx->OpenOutputContext(path);
344 
346  {
348  XO("FFmpeg : ERROR - Can't open output file \"%s\" to write. Error code is %d.")
349  .Format(path, static_cast<int>(result)),
350  XO("FFmpeg Error"),
351  wxOK|wxCENTER|wxICON_EXCLAMATION);
352 
353  return false;
354  }
355  }
356 
357  // Open the audio stream's codec and initialise any stream related data.
358  if (!InitCodecs(project))
359  return false;
360 
361  if (metadata == NULL)
362  metadata = &Tags::Get( *project );
363 
364  // Add metadata BEFORE writing the header.
365  // At the moment that works with ffmpeg-git and ffmpeg-0.5 for MP4.
366  if (GetCanMetaData(subformat))
367  {
369  AddTags(metadata);
370  }
371 
372  // Write headers to the output file.
373  int err =
374  mFFmpeg->avformat_write_header(mEncFormatCtx->GetWrappedValue(), nullptr);
375 
376  if (err < 0)
377  {
379  XO("FFmpeg : ERROR - Can't write headers to output file \"%s\". Error code is %d.")
380  .Format( path, err ),
381  XO("FFmpeg Error"),
382  wxOK|wxCENTER|wxICON_EXCLAMATION);
383  return false;
384  }
385 
386  // Only now, we can keep all the resources until after Finalize().
387  // Cancel the local cleanup.
388  cleanup.release();
389 
390  return true;
391 }
392 
393 bool ExportFFmpeg::CheckSampleRate(int rate, int lowrate, int highrate, const int *sampRates)
394 {
395  if (lowrate && highrate)
396  {
397  if (rate < lowrate || rate > highrate)
398  {
399  return false;
400  }
401  }
402 
403  if (sampRates)
404  {
405  for (int i = 0; sampRates[i] > 0; i++)
406  {
407  if (rate == sampRates[i])
408  {
409  return true;
410  }
411  }
412  }
413 
414  return false;
415 }
416 
418 {
419  const auto &settings = ProjectSettings::Get( *project );
420  std::unique_ptr<AVCodecWrapper> codec;
421 
422  AVDictionaryWrapper options(*mFFmpeg);
423 
424  // Get the sample rate from the passed settings if we haven't set it before.
425  // Doing this only when not set allows us to carry the sample rate from one
426  // iteration of ExportMultiple to the next. This prevents multiple resampling
427  // dialogs in the event the codec can't support the specified rate.
428  if (!mSampleRate)
429  {
430  mSampleRate = (int)ProjectRate::Get(*project).GetRate();
431  }
432 
433  // Configure the audio stream's codec context.
434 
435  const auto codecID = ExportFFmpegOptions::fmts[mSubFormat].codecid;
436 
437  mEncAudioCodecCtx->SetGlobalQuality(-99999); //quality mode is off by default;
438 
439  // Each export type has its own settings
440  switch (mSubFormat)
441  {
442  case FMT_M4A:
443  {
444  int q = gPrefs->Read(wxT("/FileFormats/AACQuality"),-99999);
445  mEncAudioCodecCtx->SetGlobalQuality(q);
446 
447  q = wxClip( q, 98 * mChannels, 160 * mChannels );
448  // Set bit rate to between 98 kbps and 320 kbps (if two channels)
449  mEncAudioCodecCtx->SetBitRate(q * 1000);
451  mEncAudioCodecCtx->SetCutoff(0);
452 
453  break;
454  }
455  case FMT_AC3:
456  mEncAudioCodecCtx->SetBitRate(gPrefs->Read(wxT("/FileFormats/AC3BitRate"), 192000));
457  if (!CheckSampleRate(
461  {
463  mEncAudioCodecCtx->GetBitRate(), mSampleRate,
467  }
468  break;
469  case FMT_AMRNB:
470  mSampleRate = 8000;
471  mEncAudioCodecCtx->SetBitRate(gPrefs->Read(wxT("/FileFormats/AMRNBBitRate"), 12200));
472  break;
473  case FMT_OPUS:
474  options.Set("b", gPrefs->Read(wxT("/FileFormats/OPUSBitRate"), wxT("128000")), 0);
475  options.Set("vbr", gPrefs->Read(wxT("/FileFormats/OPUSVbrMode"), wxT("on")), 0);
476  options.Set("compression_level", gPrefs->Read(wxT("/FileFormats/OPUSCompression"), wxT("10")), 0);
477  options.Set("frame_duration", gPrefs->Read(wxT("/FileFormats/OPUSFrameDuration"), wxT("20")), 0);
478  options.Set("application", gPrefs->Read(wxT("/FileFormats/OPUSApplication"), wxT("audio")), 0);
479  options.Set("cutoff", gPrefs->Read(wxT("/FileFormats/OPUSCutoff"), wxT("0")), 0);
480  options.Set("mapping_family", mChannels <= 2 ? "0" : "255", 0);
481  break;
482  case FMT_WMA2:
483  mEncAudioCodecCtx->SetBitRate(gPrefs->Read(wxT("/FileFormats/WMABitRate"), 198000));
484  if (!CheckSampleRate(
488  {
490  mEncAudioCodecCtx->GetBitRate(), mSampleRate,
494  }
495  break;
496  case FMT_OTHER:
497  {
498  AVDictionaryWrapper streamMetadata = mEncAudioStream->GetMetadata();
499  streamMetadata.Set(
500  "language",
501  gPrefs->Read(wxT("/FileFormats/FFmpegLanguage"), wxT("")), 0);
502 
503  mEncAudioStream->SetMetadata(streamMetadata);
504 
505  mEncAudioCodecCtx->SetSampleRate(
506  gPrefs->Read(wxT("/FileFormats/FFmpegSampleRate"), (long)0));
507 
508  if (mEncAudioCodecCtx->GetSampleRate() != 0)
509  mSampleRate = mEncAudioCodecCtx->GetSampleRate();
510 
511  mEncAudioCodecCtx->SetBitRate(
512  gPrefs->Read(wxT("/FileFormats/FFmpegBitRate"), (long)0));
513 
514  mEncAudioCodecCtx->SetCodecTagFourCC(
515  gPrefs->Read(wxT("/FileFormats/FFmpegTag"), wxT(""))
516  .mb_str(wxConvUTF8));
517 
518  mEncAudioCodecCtx->SetGlobalQuality(
519  gPrefs->Read(wxT("/FileFormats/FFmpegQuality"), (long)-99999));
520  mEncAudioCodecCtx->SetCutoff(
521  gPrefs->Read(wxT("/FileFormats/FFmpegCutOff"), (long)0));
522  mEncAudioCodecCtx->SetFlags2(0);
523 
524  if (gPrefs->Read(wxT("/FileFormats/FFmpegBitReservoir"), true))
525  options.Set("reservoir", "1", 0);
526 
527  if (gPrefs->Read(wxT("/FileFormats/FFmpegVariableBlockLen"), true))
528  mEncAudioCodecCtx->SetFlags2(
529  mEncAudioCodecCtx->GetFlags2() | 0x0004); // WMA only?
530 
531  mEncAudioCodecCtx->SetCompressionLevel(
532  gPrefs->Read(wxT("/FileFormats/FFmpegCompLevel"), -1));
533  mEncAudioCodecCtx->SetFrameSize(
534  gPrefs->Read(wxT("/FileFormats/FFmpegFrameSize"), (long)0));
535 
536  // FIXME The list of supported options for the selected encoder should be
537  // extracted instead of a few hardcoded
538  options.Set(
539  "lpc_coeff_precision",
540  gPrefs->Read(wxT("/FileFormats/FFmpegLPCCoefPrec"), (long)0));
541  options.Set(
542  "min_prediction_order",
543  gPrefs->Read(wxT("/FileFormats/FFmpegMinPredOrder"), (long)-1));
544  options.Set(
545  "max_prediction_order",
546  gPrefs->Read(wxT("/FileFormats/FFmpegMaxPredOrder"), (long)-1));
547  options.Set(
548  "min_partition_order",
549  gPrefs->Read(wxT("/FileFormats/FFmpegMinPartOrder"), (long)-1));
550  options.Set(
551  "max_partition_order",
552  gPrefs->Read(wxT("/FileFormats/FFmpegMaxPartOrder"), (long)-1));
553  options.Set(
554  "prediction_order_method",
555  gPrefs->Read(wxT("/FileFormats/FFmpegPredOrderMethod"), (long)0));
556  options.Set(
557  "muxrate", gPrefs->Read(wxT("/FileFormats/FFmpegMuxRate"), (long)0));
558 
559  mEncFormatCtx->SetPacketSize(
560  gPrefs->Read(wxT("/FileFormats/FFmpegPacketSize"), (long)0));
561 
562  codec = mFFmpeg->CreateEncoder(
563  gPrefs->Read(wxT("/FileFormats/FFmpegCodec")));
564 
565  if (!codec)
566  codec = mFFmpeg->CreateEncoder(mEncFormatDesc->GetAudioCodec());
567  }
568  break;
569  default:
570  return false;
571  }
572 
573  // This happens if user refused to resample the project
574  if (mSampleRate == 0) return false;
575 
576  if (mEncAudioCodecCtx->GetGlobalQuality() >= 0)
577  {
578  mEncAudioCodecCtx->SetFlags(
580  }
581  else
582  {
583  mEncAudioCodecCtx->SetGlobalQuality(0);
584  }
585 
586  mEncAudioCodecCtx->SetGlobalQuality(mEncAudioCodecCtx->GetGlobalQuality() * AUDACITY_FF_QP2LAMBDA);
587  mEncAudioCodecCtx->SetSampleRate(mSampleRate);
588  mEncAudioCodecCtx->SetChannels(mChannels);
589  mEncAudioCodecCtx->SetChannelLayout(mFFmpeg->av_get_default_channel_layout(mChannels));
590  mEncAudioCodecCtx->SetTimeBase({ 1, mSampleRate });
592  mEncAudioCodecCtx->SetStrictStdCompliance(
594 
595  if (codecID == AUDACITY_AV_CODEC_ID_AC3)
596  {
597  // As of Jan 4, 2011, the default AC3 encoder only accept SAMPLE_FMT_FLT samples.
598  // But, currently, Audacity only supports SAMPLE_FMT_S16. So, for now, look for the
599  // "older" AC3 codec. this is not a proper solution, but will suffice until other
600  // encoders no longer support SAMPLE_FMT_S16.
601  codec = mFFmpeg->CreateEncoder("ac3_fixed");
602  }
603 
604  if (!codec)
605  {
606  codec = mFFmpeg->CreateEncoder(mFFmpeg->GetAVCodecID(codecID));
607  }
608 
609  // Is the required audio codec compiled into libavcodec?
610  if (codec == NULL)
611  {
613  XO(
614 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
615 "FFmpeg cannot find audio codec 0x%x.\nSupport for this codec is probably not compiled in.")
616  .Format(static_cast<const unsigned int>(codecID.value)),
617  XO("FFmpeg Error"),
618  wxOK|wxCENTER|wxICON_EXCLAMATION);
619  return false;
620  }
621 
622  if (codec->GetSampleFmts()) {
623  for (int i = 0; codec->GetSampleFmts()[i] != AUDACITY_AV_SAMPLE_FMT_NONE; i++)
624  {
625  AVSampleFormatFwd fmt = codec->GetSampleFmts()[i];
626 
627  if (
628  fmt == AUDACITY_AV_SAMPLE_FMT_U8 ||
636  {
637  mEncAudioCodecCtx->SetSampleFmt(fmt);
638  }
639 
640  if (
643  break;
644  }
645  }
646 
647  if (codec->GetSupportedSamplerates())
648  {
649  // Workaround for crash in bug #2378. Proper fix is to get a newer version of FFmpeg.
650  if (codec->GetId() == mFFmpeg->GetAVCodecID(AUDACITY_AV_CODEC_ID_AAC))
651  {
652  std::vector<int> rates;
653  int i = 0;
654 
655  while (codec->GetSupportedSamplerates()[i] &&
656  codec->GetSupportedSamplerates()[i] != 7350)
657  {
658  rates.push_back(codec->GetSupportedSamplerates()[i++]);
659  }
660 
661  rates.push_back(0);
662 
663  if (!CheckSampleRate(mSampleRate, 0, 0, rates.data()))
664  {
665  mSampleRate = AskResample(0, mSampleRate, 0, 0, rates.data());
666  mEncAudioCodecCtx->SetSampleRate(mSampleRate);
667  }
668  }
669  else
670  {
671  if (!CheckSampleRate(
672  mSampleRate, 0, 0, codec->GetSupportedSamplerates()))
673  {
675  0, mSampleRate, 0, 0, codec->GetSupportedSamplerates());
676  mEncAudioCodecCtx->SetSampleRate(mSampleRate);
677  }
678  }
679 
680  // This happens if user refused to resample the project
681  if (mSampleRate == 0)
682  {
683  return false;
684  }
685  }
686 
687  if (mEncFormatCtx->GetOutputFormat()->GetFlags() & AUDACITY_AVFMT_GLOBALHEADER)
688  {
691  }
692 
693  // Open the codec.
694  int rc = mEncAudioCodecCtx->Open(codec.get(), &options);
695  if (rc < 0)
696  {
697  TranslatableString errmsg;
698 
699  switch (rc)
700  {
701  case AUDACITY_AVERROR(EPERM):
702  errmsg = XO("The codec reported a generic error (EPERM)");
703  break;
704  case AUDACITY_AVERROR(EINVAL):
705  errmsg = XO("The codec reported an invalid parameter (EINVAL)");
706  break;
707  default:
708  char buf[64];
709  mFFmpeg->av_strerror(rc, buf, sizeof(buf));
710  errmsg = Verbatim(buf);
711  }
712 
714  /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
715  XO("Can't open audio codec \"%s\" (0x%x)\n\n%s")
716  .Format(codec->GetName(), codecID.value, errmsg),
717  XO("FFmpeg Error"),
718  wxOK|wxCENTER|wxICON_EXCLAMATION);
719  return false;
720  }
721 
722  mDefaultFrameSize = mEncAudioCodecCtx->GetFrameSize();
723 
724  if (mDefaultFrameSize == 0)
725  mDefaultFrameSize = 1024; // arbitrary non zero value;
726 
727  wxLogDebug(
728  wxT("FFmpeg : Audio Output Codec Frame Size: %d samples."),
729  mEncAudioCodecCtx->GetFrameSize());
730 
731  // The encoder may require a minimum number of raw audio samples for each encoding but we can't
732  // guarantee we'll get this minimum each time an audio frame is decoded from the input file so
733  // we use a FIFO to store up incoming raw samples until we have enough for one call to the codec.
734  mEncAudioFifo = mFFmpeg->CreateFifoBuffer(mDefaultFrameSize);
735 
737  // Allocate a buffer to read OUT of the FIFO into. The FIFO maintains its own buffer internally.
738  mEncAudioFifoOutBuf = mFFmpeg->CreateMemoryBuffer<int16_t>(mEncAudioFifoOutBufSize);
739 
740  if (mEncAudioFifoOutBuf.empty())
741  {
743  XO("FFmpeg : ERROR - Can't allocate buffer to read into from audio FIFO."),
744  XO("FFmpeg Error"),
745  wxOK|wxCENTER|wxICON_EXCLAMATION
746  );
747  return false;
748  }
749 
750  return true;
751 }
752 
753 // Returns 0 if no more output, 1 if more output, negative if error
754 static int encode_audio(const FFmpegFunctions& ffmpeg, AVCodecContextWrapper*avctx, AVPacketWrapper *pkt, int16_t *audio_samples, int nb_samples)
755 {
756  // Assume *pkt is already initialized.
757 
758  int i, ch, buffer_size, ret, got_output = 0;
759  AVDataBuffer<uint8_t> samples;
760 
761  std::unique_ptr<AVFrameWrapper> frame;
762 
763  if (audio_samples) {
764  frame = ffmpeg.CreateAVFrameWrapper();
765 
766  if (!frame)
767  return AUDACITY_AVERROR(ENOMEM);
768 
769  frame->SetSamplesCount(nb_samples);
770  frame->SetFormat(avctx->GetSampleFmt());
771  frame->SetChannelLayout(avctx->GetChannelLayout());
772 
773  buffer_size = ffmpeg.av_samples_get_buffer_size(
774  NULL, avctx->GetChannels(), nb_samples, avctx->GetSampleFmt(), 0);
775 
776  if (buffer_size < 0) {
778  XO("FFmpeg : ERROR - Could not get sample buffer size"),
779  XO("FFmpeg Error"),
780  wxOK|wxCENTER|wxICON_EXCLAMATION
781  );
782  return buffer_size;
783  }
784 
785  samples = ffmpeg.CreateMemoryBuffer<uint8_t>(buffer_size);
786 
787  if (samples.empty()) {
789  XO("FFmpeg : ERROR - Could not allocate bytes for samples buffer"),
790  XO("FFmpeg Error"),
791  wxOK|wxCENTER|wxICON_EXCLAMATION
792  );
793 
794  return AUDACITY_AVERROR(ENOMEM);
795  }
796  /* setup the data pointers in the AVFrame */
797  ret = ffmpeg.avcodec_fill_audio_frame(
798  frame->GetWrappedValue(), avctx->GetChannels(), avctx->GetSampleFmt(),
799  samples.data(), buffer_size, 0);
800 
801  if (ret < 0) {
803  XO("FFmpeg : ERROR - Could not setup audio frame"),
804  XO("FFmpeg Error"),
805  wxOK|wxCENTER|wxICON_EXCLAMATION
806  );
807  return ret;
808  }
809 
810  const int channelsCount = avctx->GetChannels();
811 
812  for (ch = 0; ch < avctx->GetChannels(); ch++) {
813  for (i = 0; i < nb_samples; i++) {
814  switch(static_cast<AudacityAVSampleFormat>(avctx->GetSampleFmt())) {
816  ((uint8_t*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount]/258 + 128;
817  break;
819  ((uint8_t*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount]/258 + 128;
820  break;
822  ((int16_t*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount];
823  break;
825  ((int16_t*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount];
826  break;
828  ((int32_t*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount]<<16;
829  break;
831  ((int32_t*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount]<<16;
832  break;
834  ((float*)(frame->GetData(0)))[ch + i*channelsCount] = audio_samples[ch + i*channelsCount] / 32767.0;
835  break;
837  ((float*)(frame->GetData(ch)))[i] = audio_samples[ch + i*channelsCount] / 32767.;
838  break;
839  default:
840  wxASSERT(false);
841  break;
842  }
843  }
844  }
845  }
846 
847  pkt->ResetData();
848 
849  ret = ffmpeg.avcodec_encode_audio2(
850  avctx->GetWrappedValue(), pkt->GetWrappedValue(),
851  frame ? frame->GetWrappedValue() : nullptr, &got_output);
852 
853  if (ret < 0) {
855  XO("FFmpeg : ERROR - encoding frame failed"),
856  XO("FFmpeg Error"),
857  wxOK|wxCENTER|wxICON_EXCLAMATION
858  );
859 
860  char buf[64];
861  ffmpeg.av_strerror(ret, buf, sizeof(buf));
862  wxLogDebug(buf);
863 
864  return ret;
865  }
866 
867  pkt->ResetTimestamps(); // we dont set frame timestamps thus dont trust the AVPacket timestamps
868 
869  return got_output;
870 }
871 
872 
874 {
875  // Flush the audio FIFO and encoder.
876  for (;;)
877  {
878  std::unique_ptr<AVPacketWrapper> pkt = mFFmpeg->CreateAVPacketWrapper();
879 
880  const int nFifoBytes = mFFmpeg->av_fifo_size(
881  mEncAudioFifo->GetWrappedValue()); // any bytes left in audio FIFO?
882 
883  int encodeResult = 0;
884 
885  // Flush the audio FIFO first if necessary. It won't contain a _full_ audio frame because
886  // if it did we'd have pulled it from the FIFO during the last encodeAudioFrame() call
887  if (nFifoBytes > 0)
888  {
889  const int nAudioFrameSizeOut = mDefaultFrameSize * mEncAudioCodecCtx->GetChannels() * sizeof(int16_t);
890 
891  if (nAudioFrameSizeOut > mEncAudioFifoOutBufSize || nFifoBytes > mEncAudioFifoOutBufSize) {
893  XO("FFmpeg : ERROR - Too much remaining data."),
894  XO("FFmpeg Error"),
895  wxOK | wxCENTER | wxICON_EXCLAMATION
896  );
897  return false;
898  }
899 
900  // We have an incomplete buffer of samples left, encode it.
901  // If codec supports CODEC_CAP_SMALL_LAST_FRAME, we can feed it with smaller frame
902  // 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
903  // Otherwise we'll send a full frame of audio + silence padding to ensure all audio is encoded
904  int frame_size = mDefaultFrameSize;
905  if (
906  mEncAudioCodecCtx->GetCodec()->GetCapabilities() &
908  frame_size == 1)
909  {
910  frame_size = nFifoBytes /
911  (mEncAudioCodecCtx->GetChannels() * sizeof(int16_t));
912  }
913 
914  wxLogDebug(wxT("FFmpeg : Audio FIFO still contains %d bytes, writing %d sample frame ..."),
915  nFifoBytes, frame_size);
916 
917  // Fill audio buffer with zeroes. If codec tries to read the whole buffer,
918  // it will just read silence. If not - who cares?
919  memset(mEncAudioFifoOutBuf.data(), 0, mEncAudioFifoOutBufSize);
920  //const AVCodec *codec = mEncAudioCodecCtx->codec;
921 
922  // Pull the bytes out from the FIFO and feed them to the encoder.
923  if (mFFmpeg->av_fifo_generic_read(mEncAudioFifo->GetWrappedValue(), mEncAudioFifoOutBuf.data(), nFifoBytes, NULL) == 0)
924  {
925  encodeResult = encode_audio(*mFFmpeg, mEncAudioCodecCtx.get(), pkt.get(), mEncAudioFifoOutBuf.data(), frame_size);
926  }
927  else
928  {
929  wxLogDebug(wxT("FFmpeg : Reading from Audio FIFO failed, aborting"));
930  // TODO: more precise message
931  ShowExportErrorDialog("FFmpeg:825");
932  return false;
933  }
934  }
935  else
936  {
937  // Fifo is empty, flush encoder. May be called multiple times.
938  encodeResult =
939  encode_audio(*mFFmpeg, mEncAudioCodecCtx.get(), pkt.get(), NULL, 0);
940  }
941 
942  if (encodeResult < 0) {
943  // TODO: more precise message
944  ShowExportErrorDialog("FFmpeg:837");
945  return false;
946  }
947  else if (encodeResult == 0)
948  break;
949 
950  // We have a packet, send to the muxer
951  pkt->SetStreamIndex(mEncAudioStream->GetIndex());
952 
953  // Set presentation time of frame (currently in the codec's timebase) in the stream timebase.
955  pkt->RescalePresentationTimestamp(mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
956 
958  pkt->RescaleDecompressionTimestamp(mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
959 
960  if (pkt->GetDuration() > 0)
961  pkt->RescaleDuration(mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
962 
963  if (mFFmpeg->av_interleaved_write_frame(mEncFormatCtx->GetWrappedValue(), pkt->GetWrappedValue()) != 0)
964  {
966  XO("FFmpeg : ERROR - Couldn't write last audio frame to output file."),
967  XO("FFmpeg Error"),
968  wxOK | wxCENTER | wxICON_EXCLAMATION
969  );
970  return false;
971  }
972  }
973 
974  // Write any file trailers.
975  if (mFFmpeg->av_write_trailer(mEncFormatCtx->GetWrappedValue()) != 0)
976  {
977  // TODO: more precise message
978  ShowExportErrorDialog("FFmpeg:868");
979  return false;
980  }
981 
982  return true;
983 }
984 
986 {
987 
988 }
989 
990 // All paths in this that fail must report their error to the user.
991 bool ExportFFmpeg::EncodeAudioFrame(int16_t *pFrame, size_t frameSize)
992 {
993  int nBytesToWrite = 0;
994  uint8_t *pRawSamples = nullptr;
995  int nAudioFrameSizeOut = mDefaultFrameSize * mEncAudioCodecCtx->GetChannels() * sizeof(int16_t);
996  int ret;
997 
998  nBytesToWrite = frameSize;
999  pRawSamples = (uint8_t*)pFrame;
1000  if (mFFmpeg->av_fifo_realloc2(mEncAudioFifo->GetWrappedValue(), mFFmpeg->av_fifo_size(mEncAudioFifo->GetWrappedValue()) + frameSize) < 0) {
1001  ShowExportErrorDialog("FFmpeg:905");
1002  return false;
1003  }
1004 
1005  // Put the raw audio samples into the FIFO.
1006  ret = mFFmpeg->av_fifo_generic_write(
1007  mEncAudioFifo->GetWrappedValue(), pRawSamples, nBytesToWrite, nullptr);
1008 
1009  if (ret != nBytesToWrite) {
1010  ShowExportErrorDialog("FFmpeg:913");
1011  return false;
1012  }
1013 
1014  if (nAudioFrameSizeOut > mEncAudioFifoOutBufSize) {
1016  XO("FFmpeg : ERROR - nAudioFrameSizeOut too large."),
1017  XO("FFmpeg Error"),
1018  wxOK|wxCENTER|wxICON_EXCLAMATION
1019  );
1020  return false;
1021  }
1022 
1023  // Read raw audio samples out of the FIFO in nAudioFrameSizeOut byte-sized groups to encode.
1024  while (mFFmpeg->av_fifo_size(mEncAudioFifo->GetWrappedValue()) >= nAudioFrameSizeOut)
1025  {
1026  ret = mFFmpeg->av_fifo_generic_read(
1027  mEncAudioFifo->GetWrappedValue(), mEncAudioFifoOutBuf.data(),
1028  nAudioFrameSizeOut, nullptr);
1029 
1030  std::unique_ptr<AVPacketWrapper> pkt = mFFmpeg->CreateAVPacketWrapper();
1031 
1032  ret = encode_audio(
1033  *mFFmpeg, mEncAudioCodecCtx.get(),
1034  pkt.get(), // out
1035  mEncAudioFifoOutBuf.data(), // in
1037 
1038  if (ret < 0)
1039  {
1041  XO("FFmpeg : ERROR - Can't encode audio frame."),
1042  XO("FFmpeg Error"),
1043  wxOK|wxCENTER|wxICON_EXCLAMATION
1044  );
1045  return false;
1046  }
1047  if (ret == 0)
1048  continue;
1049 
1050  // Rescale from the codec time_base to the AVStream time_base.
1052  pkt->RescalePresentationTimestamp(mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
1053 
1055  pkt->RescaleDecompressionTimestamp(mEncAudioCodecCtx->GetTimeBase(), mEncAudioStream->GetTimeBase());
1056  //wxLogDebug(wxT("FFmpeg : (%d) Writing audio frame with PTS: %lld."), mEncAudioCodecCtx->frame_number, (long long) pkt.pts);
1057 
1058  pkt->SetStreamIndex(mEncAudioStream->GetIndex());
1059 
1060  // Write the encoded audio frame to the output file.
1061  if ((ret = mFFmpeg->av_interleaved_write_frame(mEncFormatCtx->GetWrappedValue(), pkt->GetWrappedValue())) < 0)
1062  {
1064  return false;
1065  }
1066  }
1067  return true;
1068 }
1069 
1070 
1072  std::unique_ptr<ProgressDialog> &pDialog,
1073  unsigned channels, const wxFileNameWrapper &fName,
1074  bool selectionOnly, double t0, double t1,
1075  MixerSpec *mixerSpec, const Tags *metadata, int subformat)
1076 {
1077  if (!CheckFFmpegPresence())
1079  mChannels = channels;
1080  // subformat index may not correspond directly to fmts[] index, convert it
1081  mSubFormat = AdjustFormatIndex(subformat);
1082  if (channels > ExportFFmpegOptions::fmts[mSubFormat].maxchannels)
1083  {
1085  XO(
1086 "Attempted to export %d channels, but maximum number of channels for selected output format is %d")
1087  .Format(
1088  channels,
1089  ExportFFmpegOptions::fmts[mSubFormat].maxchannels ),
1090  XO("Error"));
1092  }
1093  mName = fName;
1094  const auto &tracks = TrackList::Get( *project );
1095  bool ret = true;
1096 
1097  if (mSubFormat >= FMT_LAST) {
1098  // TODO: more precise message
1099  ShowExportErrorDialog("FFmpeg:996");
1101  }
1102 
1103  wxString shortname(ExportFFmpegOptions::fmts[mSubFormat].shortname);
1104  if (mSubFormat == FMT_OTHER)
1105  shortname = gPrefs->Read(wxT("/FileFormats/FFmpegFormat"),wxT("matroska"));
1106  ret = Init(shortname.mb_str(),project, metadata, subformat);
1107  auto cleanup = finally ( [&] { FreeResources(); } );
1108 
1109  if (!ret) {
1110  // TODO: more precise message
1111  ShowExportErrorDialog("FFmpeg:1008");
1113  }
1114 
1115  size_t pcmBufferSize = mDefaultFrameSize;
1116 
1117  auto mixer = CreateMixer(tracks, selectionOnly,
1118  t0, t1,
1119  channels, pcmBufferSize, true,
1120  mSampleRate, int16Sample, mixerSpec);
1121 
1122  auto updateResult = ProgressResult::Success;
1123  {
1124  InitProgress( pDialog, fName,
1125  selectionOnly
1126  ? XO("Exporting selected audio as %s")
1128  : XO("Exporting the audio as %s")
1129  .Format( ExportFFmpegOptions::fmts[mSubFormat].description ) );
1130  auto &progress = *pDialog;
1131 
1132  while (updateResult == ProgressResult::Success) {
1133  auto pcmNumSamples = mixer->Process(pcmBufferSize);
1134 
1135  if (pcmNumSamples == 0)
1136  break;
1137 
1138  short *pcmBuffer = (short *)mixer->GetBuffer();
1139 
1140  if (!EncodeAudioFrame(
1141  pcmBuffer, (pcmNumSamples)*sizeof(int16_t)*mChannels)) {
1142  // All errors should already have been reported.
1143  //ShowDiskFullExportErrorDialog(mName);
1144  updateResult = ProgressResult::Cancelled;
1145  break;
1146  }
1147 
1148  updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
1149  }
1150  }
1151 
1152  if ( updateResult != ProgressResult::Cancelled )
1153  if ( !Finalize() ) // Finalize makes its own messages
1155 
1156  // Flush the file
1157  mEncFormatCtx.reset();
1158 
1159  return updateResult;
1160 }
1161 
1162 void AddStringTagUTF8(char field[], int size, wxString value)
1163 {
1164  memset(field,0,size);
1165  memcpy(field,value.ToUTF8(),(int)strlen(value.ToUTF8()) > size -1 ? size -1 : strlen(value.ToUTF8()));
1166 }
1167 
1168 void AddStringTagANSI(char field[], int size, wxString value)
1169 {
1170  memset(field,0,size);
1171  memcpy(field,value.mb_str(),(int)strlen(value.mb_str()) > size -1 ? size -1 : strlen(value.mb_str()));
1172 }
1173 
1174 bool ExportFFmpeg::AddTags(const Tags *tags)
1175 {
1176  if (tags == NULL)
1177  {
1178  return false;
1179  }
1180 
1181  SetMetadata(tags, "album", TAG_ALBUM);
1182  SetMetadata(tags, "comment", TAG_COMMENTS);
1183  SetMetadata(tags, "genre", TAG_GENRE);
1184  SetMetadata(tags, "title", TAG_TITLE);
1185  SetMetadata(tags, "track", TAG_TRACK);
1186 
1187  // Bug 2564: Add m4a tags
1188  if (mEncFormatDesc->GetAudioCodec() == mFFmpeg->GetAVCodecID(AUDACITY_AV_CODEC_ID_AAC))
1189  {
1190  SetMetadata(tags, "artist", TAG_ARTIST);
1191  SetMetadata(tags, "date", TAG_YEAR);
1192  }
1193  else
1194  {
1195  SetMetadata(tags, "author", TAG_ARTIST);
1196  SetMetadata(tags, "year", TAG_YEAR);
1197  }
1198 
1199  return true;
1200 }
1201 
1202 void ExportFFmpeg::SetMetadata(const Tags *tags, const char *name, const wxChar *tag)
1203 {
1204  if (tags->HasTag(tag))
1205  {
1206  wxString value = tags->GetTag(tag);
1207 
1208  AVDictionaryWrapper metadata = mEncFormatCtx->GetMetadata();
1209 
1210  metadata.Set(name, mSupportsUTF8 ? value : value.mb_str(), 0);
1211  mEncFormatCtx->SetMetadata(metadata);
1212  }
1213 }
1214 
1215 
1216 //----------------------------------------------------------------------------
1217 // AskResample dialog
1218 //----------------------------------------------------------------------------
1219 
1220 int ExportFFmpeg::AskResample(int bitrate, int rate, int lowrate, int highrate, const int *sampRates)
1221 {
1222 #if defined(FFMPEG_AUTO_RESAMPLE)
1223  std::vector<int> rates;
1224 
1225  for (int i = 0; sampRates[i]; ++i)
1226  {
1227  rates.push_back(sampRates[i]);
1228  }
1229 
1230  std::sort(rates.begin(), rates.end());
1231 
1232  int bestRate = 0;
1233  for (auto i : rates)
1234  {
1235  bestRate = i;
1236  if (i > rate)
1237  {
1238  break;
1239  }
1240  }
1241 
1242  return bestRate;
1243 #else
1244  wxDialogWrapper d(nullptr, wxID_ANY, XO("Invalid sample rate"));
1245  d.SetName();
1246  wxChoice *choice;
1247  ShuttleGui S(&d, eIsCreating);
1248 
1249  int selected = -1;
1250 
1251  S.StartVerticalLay();
1252  {
1253  S.SetBorder(10);
1254  S.StartStatic(XO("Resample"));
1255  {
1256  S.StartHorizontalLay(wxALIGN_CENTER, false);
1257  {
1258  S.AddTitle(
1259  (bitrate == 0
1260  ? XO(
1261 "The project sample rate (%d) is not supported by the current output\nfile format. ")
1262  .Format( rate )
1263  : XO(
1264 "The project sample rate (%d) and bit rate (%d kbps) combination is not\nsupported by the current output file format. ")
1265  .Format( rate, bitrate/1000))
1266  + XO("You may resample to one of the rates below.")
1267  );
1268  }
1269  S.EndHorizontalLay();
1270 
1271  S.StartHorizontalLay(wxALIGN_CENTER, false);
1272  {
1273  choice = S.AddChoice(XO("Sample Rates"),
1274  [&]{
1275  TranslatableStrings choices;
1276  for (int i = 0; sampRates[i] > 0; i++)
1277  {
1278  int label = sampRates[i];
1279  if ((!lowrate || label >= lowrate) && (!highrate || label <= highrate))
1280  {
1281  wxString name = wxString::Format(wxT("%d"),label);
1282  choices.push_back( Verbatim( name ) );
1283  if (label <= rate)
1284  selected = i;
1285  }
1286  }
1287  return choices;
1288  }(),
1289  std::max( 0, selected )
1290  );
1291  }
1292  S.EndHorizontalLay();
1293  }
1294  S.EndStatic();
1295 
1296  S.AddStandardButtons();
1297  }
1298  S.EndVerticalLay();
1299 
1300  d.Layout();
1301  d.Fit();
1302  d.SetMinSize(d.GetSize());
1303  d.Center();
1304 
1305  if (d.ShowModal() == wxID_CANCEL) {
1306  return 0;
1307  }
1308 
1309  return wxAtoi(choice->GetStringSelection());
1310 #endif
1311 }
1312 
1314 {
1315  // subformat index may not correspond directly to fmts[] index, convert it
1317  if (mSubFormat == FMT_M4A)
1318  {
1319  S.AddWindow(
1321  return;
1322  }
1323  else if (mSubFormat == FMT_AC3)
1324  {
1325  S.AddWindow(
1327  return;
1328  }
1329  else if (mSubFormat == FMT_AMRNB)
1330  {
1331  S.AddWindow(
1333  return;
1334  }
1335  else if (mSubFormat == FMT_OPUS)
1336  {
1337  S.AddWindow(
1339  return;
1340  }
1341  else if (mSubFormat == FMT_WMA2)
1342  {
1343  S.AddWindow(
1345  return;
1346  }
1347  else if (mSubFormat == FMT_OTHER)
1348  {
1349  S.AddWindow(
1351  return;
1352  }
1353 
1355 }
1356 
1358  []{ return std::make_unique< ExportFFmpeg >(); }
1359 };
1360 
1361 #endif
1362 
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
ExportFFmpeg
Controlling class for FFmpeg exporting. Creates the options dialog of the appropriate type,...
Definition: ExportFFmpeg.cpp:99
ExportFFmpeg::mEncAudioFifoOutBuf
AVDataBuffer< int16_t > mEncAudioFifoOutBuf
Definition: ExportFFmpeg.cpp:177
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
field
#define field(n, t)
Definition: ImportAUP.cpp:167
AUDACITY_AV_CODEC_FLAG_GLOBAL_HEADER
#define AUDACITY_AV_CODEC_FLAG_GLOBAL_HEADER
Definition: FFmpegTypes.h:110
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
ExportFFmpegWMAOptions::iWMASampleRates
static const int iWMASampleRates[]
Definition: ExportFFmpegDialogs.h:166
AVCodecContextWrapper::GetChannelLayout
virtual uint64_t GetChannelLayout() const noexcept=0
ShuttleGuiBase::AddChoice
wxChoice * AddChoice(const TranslatableString &Prompt, const TranslatableStrings &choices, int Selected=-1)
Definition: ShuttleGui.cpp:398
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
AVPacketWrapper::ResetData
virtual void ResetData() noexcept=0
OSINPUT
#define OSINPUT(X)
Definition: SelectFile.h:55
AUDACITY_FF_PROFILE_AAC_LOW
#define AUDACITY_FF_PROFILE_AAC_LOW
Definition: FFmpegTypes.h:98
wxFileNameWrapper.h
ExportFFmpeg::mName
wxFileNameWrapper mName
Definition: ExportFFmpeg.cpp:167
BasicUI::ProgressResult::Success
@ Success
ExportFFmpeg::mEncFormatDesc
std::unique_ptr< AVOutputFormatWrapper > mEncFormatDesc
Definition: ExportFFmpeg.cpp:162
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
sRegisteredPlugin
static Exporter::RegisteredExportPlugin sRegisteredPlugin
Definition: ExportFFmpeg.cpp:1357
wxFileNameWrapper
Definition: wxFileNameWrapper.h:21
AVPacketWrapper::GetDecompressionTimestamp
virtual int64_t GetDecompressionTimestamp() const noexcept=0
ShuttleGuiBase::AddTitle
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:281
CheckFFmpegPresence
static bool CheckFFmpegPresence(bool quiet=false)
Definition: ExportFFmpeg.cpp:61
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
ExposedFormat::compiledIn
bool compiledIn
support for this codec/format is compiled in (checked at runtime)
Definition: ExportFFmpegDialogs.h:58
AUDACITY_AV_SAMPLE_FMT_NONE
@ AUDACITY_AV_SAMPLE_FMT_NONE
Definition: FFmpegTypes.h:144
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
FMT_AC3
@ FMT_AC3
Definition: ExportFFmpegDialogs.h:36
ExportPlugin::AddExtension
void AddExtension(const FileExtension &extension, int index)
Definition: Export.cpp:127
ShowExportErrorDialog
void ShowExportErrorDialog(wxString ErrorCode, TranslatableString message, const TranslatableString &caption)
Definition: Export.cpp:1519
AVUtilFunctions::av_strerror
int(* av_strerror)(int errnum, char *errbuf, size_t errbuf_size)
Definition: AVUtilFunctions.h:43
ProjectRate::Get
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:42
Tags::HasTag
bool HasTag(const wxString &name) const
Definition: Tags.cpp:452
Tags
ID3 Tags (for MP3)
Definition: Tags.h:74
AVDictionaryWrapper
Definition: AVDictionaryWrapper.h:24
Format
Abstract base class used in importing a file.
TAG_TRACK
#define TAG_TRACK
Definition: Tags.h:63
AUDACITY_FF_COMPLIANCE_EXPERIMENTAL
#define AUDACITY_FF_COMPLIANCE_EXPERIMENTAL
Definition: FFmpegTypes.h:93
ExportFFmpegCustomOptions
Definition: ExportFFmpegDialogs.h:175
BasicUI::ProgressResult
ProgressResult
Definition: BasicUI.h:145
ExportFFmpeg::mChannels
unsigned mChannels
Definition: ExportFFmpeg.cpp:172
ExportFFmpegAMRNBOptions
Options dialog for FFmpeg exporting of AMRNB format.
Definition: ExportFFmpegDialogs.h:105
AddStringTagANSI
void AddStringTagANSI(char field[], int size, wxString value)
Definition: ExportFFmpeg.cpp:1168
AUDACITY_AV_SAMPLE_FMT_S16P
@ AUDACITY_AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: FFmpegTypes.h:152
ExportFFmpegAC3Options::iAC3SampleRates
static const int iAC3SampleRates[]
Definition: ExportFFmpegDialogs.h:84
AUDACITY_AV_SAMPLE_FMT_U8
@ AUDACITY_AV_SAMPLE_FMT_U8
unsigned 8 bits
Definition: FFmpegTypes.h:145
AVPacketWrapper
Definition: AVPacketWrapper.h:21
AVCodecWrapper::GetName
virtual const char * GetName() const noexcept=0
AUDACITY_AV_SAMPLE_FMT_FLT
@ AUDACITY_AV_SAMPLE_FMT_FLT
float
Definition: FFmpegTypes.h:148
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
XO
#define XO(s)
Definition: Internat.h:31
ExportFFmpeg::AskResample
int AskResample(int bitrate, int rate, int lowrate, int highrate, const int *sampRates)
Asks user to resample the project or cancel the export procedure.
Definition: ExportFFmpeg.cpp:1220
AUDACITY_AV_CODEC_ID_AAC
@ AUDACITY_AV_CODEC_ID_AAC
Definition: AVCodecID.h:296
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:44
AUDACITY_AV_CODEC_ID_AC3
@ AUDACITY_AV_CODEC_ID_AC3
Definition: AVCodecID.h:297
AUDACITY_AV_NOPTS_VALUE
#define AUDACITY_AV_NOPTS_VALUE
Definition: FFmpegTypes.h:69
ProjectSettings.h
ExposedFormat::canmetadata
const int canmetadata
!=0 if format supports metadata, AV_CANMETA any avformat version, otherwise version support added
Definition: ExportFFmpegDialogs.h:54
ExportPlugin::GetCanMetaData
virtual bool GetCanMetaData(int index)
Definition: Export.cpp:185
ExportFFmpeg::mEncAudioCodecCtx
std::unique_ptr< AVCodecContextWrapper > mEncAudioCodecCtx
Definition: ExportFFmpeg.cpp:179
AVFrameWrapper::SetSamplesCount
virtual void SetSamplesCount(int count) noexcept=0
ExportFFmpeg::InitCodecs
bool InitCodecs(AudacityProject *project)
Codec initialization.
Definition: ExportFFmpeg.cpp:417
AUDACITY_FF_QP2LAMBDA
#define AUDACITY_FF_QP2LAMBDA
Definition: FFmpegTypes.h:84
Tags::GetTag
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:461
ExportFFmpeg::mEncAudioFifo
std::unique_ptr< AVFifoBufferWrapper > mEncAudioFifo
Definition: ExportFFmpeg.cpp:176
sampRates
static const std::vector< int > sampRates
Definition: ExportMP3.cpp:207
ExportFFmpeg::FreeResources
void FreeResources()
Definition: ExportFFmpeg.cpp:985
Tags::Get
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:237
ExportFFmpeg::mSupportsUTF8
bool mSupportsUTF8
Definition: ExportFFmpeg.cpp:173
ExportFFmpeg::Export
ProgressResult Export(AudacityProject *project, std::unique_ptr< ProgressDialog > &pDialog, unsigned channels, const wxFileNameWrapper &fName, bool selectedOnly, double t0, double t1, MixerSpec *mixerSpec=NULL, const Tags *metadata=NULL, int subformat=0) override
Definition: ExportFFmpeg.cpp:1071
AUDACITY_AVERROR
#define AUDACITY_AVERROR(e)
Definition: FFmpegTypes.h:25
AVCodecFunctions::avcodec_encode_audio2
int(* avcodec_encode_audio2)(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_output)
Definition: AVCodecFunctions.h:32
LoadFFmpeg
bool LoadFFmpeg(bool showerror)
Definition: FFmpeg.cpp:46
AV_CANMETA
#define AV_CANMETA
Definition: ExportFFmpegDialogs.h:44
ExportFFmpeg::mFFmpeg
std::shared_ptr< FFmpegFunctions > mFFmpeg
Definition: ExportFFmpeg.cpp:160
AVCodecFunctions::avcodec_fill_audio_frame
int(* avcodec_fill_audio_frame)(AVFrame *frame, int nb_channels, AVSampleFormatFwd sample_fmt, const uint8_t *buf, int buf_size, int align)
Definition: AVCodecFunctions.h:37
FFmpegFunctions::CreateAVFrameWrapper
std::unique_ptr< AVFrameWrapper > CreateAVFrameWrapper() const
Definition: FFmpegFunctions.cpp:347
AVFrameWrapper::SetFormat
virtual void SetFormat(AVSampleFormatFwd format) noexcept=0
ShowDiskFullExportErrorDialog
void ShowDiskFullExportErrorDialog(const wxFileNameWrapper &fileName)
Definition: Export.cpp:1531
AVCodecContextWrapper
Definition: AVCodecContextWrapper.h:30
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
ExportFFmpegAACOptions
Options dialog for FFmpeg exporting of AAC format.
Definition: ExportFFmpegDialogs.h:93
ExportPlugin::InitProgress
static void InitProgress(std::unique_ptr< ProgressDialog > &pDialog, const TranslatableString &title, const TranslatableString &message)
Definition: Export.cpp:251
AVFrameWrapper::GetData
virtual uint8_t * GetData(int index) const noexcept=0
label
TranslatableString label
Definition: Tags.cpp:756
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
AUDACITY_AVFMT_GLOBALHEADER
#define AUDACITY_AVFMT_GLOBALHEADER
Definition: FFmpegTypes.h:35
AVCodecContextWrapper::GetWrappedValue
AVCodecContext * GetWrappedValue() noexcept
Definition: AVCodecContextWrapper.cpp:37
ExportPlugin::SetFormat
void SetFormat(const wxString &format, int index)
Definition: Export.cpp:117
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
int16Sample
@ int16Sample
Definition: SampleFormat.h:32
ExportFFmpeg::Finalize
bool Finalize()
Flushes audio encoder.
Definition: ExportFFmpeg.cpp:873
AVPacketWrapper::RescaleDuration
virtual void RescaleDuration(AudacityAVRational bq, AudacityAVRational cq) noexcept=0
FMT_OTHER
@ FMT_OTHER
Definition: ExportFFmpegDialogs.h:40
ExportFFmpeg::SetMetadata
void SetMetadata(const Tags *tags, const char *name, const wxChar *tag)
Sets individual metadata values.
Definition: ExportFFmpeg.cpp:1202
ExportFFmpegAC3Options
AC3 export options dialog.
Definition: ExportFFmpegDialogs.h:72
FMT_AMRNB
@ FMT_AMRNB
Definition: ExportFFmpegDialogs.h:37
FFmpegFunctions
Definition: FFmpegFunctions.h:85
name
const TranslatableString name
Definition: Distortion.cpp:98
SelectFile.h
AVPacketWrapper::ResetTimestamps
virtual void ResetTimestamps() noexcept=0
AUDACITY_AV_SAMPLE_FMT_S16
@ AUDACITY_AV_SAMPLE_FMT_S16
signed 16 bits
Definition: FFmpegTypes.h:146
AVIOContextWrapper::OpenResult::Success
@ Success
TAG_GENRE
#define TAG_GENRE
Definition: Tags.h:65
format
int format
Definition: ExportPCM.cpp:56
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
ExportFFmpeg::mEncFormatCtx
std::unique_ptr< AVFormatContextWrapper > mEncFormatCtx
Definition: ExportFFmpeg.cpp:178
AUDACITY_AV_SAMPLE_FMT_FLTP
@ AUDACITY_AV_SAMPLE_FMT_FLTP
float, planar
Definition: FFmpegTypes.h:154
Export.h
AVIOContextWrapper::OpenResult
OpenResult
Definition: AVIOContextWrapper.h:25
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:299
TAG_YEAR
#define TAG_YEAR
Definition: Tags.h:64
ExportPlugin::SetDescription
void SetDescription(const TranslatableString &description, int index)
Definition: Export.cpp:122
FindFFmpegLibs
bool FindFFmpegLibs(wxWindow *parent)
Definition: FFmpeg.cpp:306
AUDACITY_AV_CODEC_CAP_SMALL_LAST_FRAME
#define AUDACITY_AV_CODEC_CAP_SMALL_LAST_FRAME
Definition: FFmpegTypes.h:79
ProjectRate::GetRate
double GetRate() const
Definition: ProjectRate.cpp:68
ExportFFmpeg::CheckFileName
bool CheckFileName(wxFileName &filename, int format=0) override
Callback, called from GetFilename.
Definition: ExportFFmpeg.cpp:253
wxDialogWrapper::SetName
void SetName(const TranslatableString &title)
Definition: wxPanelWrapper.cpp:76
AUDACITY_AV_SAMPLE_FMT_S32
@ AUDACITY_AV_SAMPLE_FMT_S32
signed 32 bits
Definition: FFmpegTypes.h:147
ExportFFmpeg::ExportFFmpeg
ExportFFmpeg()
Definition: ExportFFmpeg.cpp:182
ExportFFmpeg::mSubFormat
int mSubFormat
Definition: ExportFFmpeg.cpp:169
ExportFFmpeg::AddTags
bool AddTags(const Tags *metadata)
Writes metadata.
Definition: ExportFFmpeg.cpp:1174
AVDataBuffer
std::vector< T, AVAllocator< T > > AVDataBuffer
Definition: FFmpegFunctions.h:79
ExportFFmpeg::EncodeAudioFrame
bool EncodeAudioFrame(int16_t *pFrame, size_t frameSize)
Encodes audio.
Definition: ExportFFmpeg.cpp:991
ExportFFmpegOptions::fmts
static ExposedFormat fmts[]
List of export types.
Definition: ExportFFmpegDialogs.h:231
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
ExportFFmpeg::Init
bool Init(const char *shortname, AudacityProject *project, const Tags *metadata, int subformat)
Format initialization.
Definition: ExportFFmpeg.cpp:269
ExportPlugin::SetMaxChannels
void SetMaxChannels(unsigned maxchannels, unsigned index)
Definition: Export.cpp:142
ExportFFmpegDialogs.h
AVFrameWrapper::GetWrappedValue
AVFrame * GetWrappedValue() noexcept
Definition: AVFrameWrapper.cpp:21
wxDialogWrapper
Definition: wxPanelWrapper.h:81
Exporter::RegisteredExportPlugin
Definition: Export.h:177
AVDictionaryWrapper::Set
void Set(const std::string_view &key, const std::string &value, int flags=0) noexcept
Definition: AVDictionaryWrapper.cpp:81
ExportFFmpegWMAOptions
Options dialog for FFmpeg exporting of WMA format.
Definition: ExportFFmpegDialogs.h:156
AVCodecContextWrapper::GetChannels
virtual int GetChannels() const noexcept=0
AVPacketWrapper::GetPresentationTimestamp
virtual int64_t GetPresentationTimestamp() const noexcept=0
AVUtilFunctions::av_samples_get_buffer_size
int(* av_samples_get_buffer_size)(int *linesize, int nb_channels, int nb_samples, AVSampleFormatFwd sample_fmt, int align)
Definition: AVUtilFunctions.h:41
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
AVCodecWrapper::GetId
virtual AVCodecIDFwd GetId() const noexcept=0
AUDACITY_AV_SAMPLE_FMT_U8P
@ AUDACITY_AV_SAMPLE_FMT_U8P
unsigned 8 bits, planar
Definition: FFmpegTypes.h:151
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
FFmpegFunctions::Load
static std::shared_ptr< FFmpegFunctions > Load()
Definition: FFmpegFunctions.cpp:262
AVSampleFormatFwd
int AVSampleFormatFwd
Definition: FFmpegTypes.h:127
ExportPlugin::CreateMixer
std::unique_ptr< Mixer > CreateMixer(const TrackList &tracks, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerSpec *mixerSpec)
Definition: Export.cpp:223
AVCodecWrapper::GetSupportedSamplerates
virtual const int * GetSupportedSamplerates() const noexcept=0
ExposedFormat::canutf8
bool canutf8
true if format supports metadata in UTF-8, false otherwise
Definition: ExportFFmpegDialogs.h:55
ExportPlugin::SetCanMetaData
void SetCanMetaData(bool canmetadata, int index)
Definition: Export.cpp:147
AVFrameWrapper::SetChannelLayout
virtual void SetChannelLayout(uint64_t layout) noexcept=0
ExportPlugin::OptionsCreate
virtual void OptionsCreate(ShuttleGui &S, int format)=0
Definition: Export.cpp:209
AUDACITY_AVFMT_NOFILE
#define AUDACITY_AVFMT_NOFILE
Definition: FFmpegTypes.h:29
TAG_COMMENTS
#define TAG_COMMENTS
Definition: Tags.h:66
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
ProjectRate.h
an object holding per-project preferred sample rate
TAG_ARTIST
#define TAG_ARTIST
Definition: Tags.h:61
ExportFFmpeg::OptionsCreate
void OptionsCreate(ShuttleGui &S, int format) override
Definition: ExportFFmpeg.cpp:1313
ExportPlugin::AddFormat
int AddFormat()
Add a NEW entry to the list of formats this plug-in can export.
Definition: Export.cpp:101
AVPacketWrapper::RescalePresentationTimestamp
virtual void RescalePresentationTimestamp(AudacityAVRational bq, AudacityAVRational cq) noexcept=0
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2444
AudacityAVSampleFormat
AudacityAVSampleFormat
Definition: FFmpegTypes.h:143
AVPacketWrapper::GetWrappedValue
AVPacket * GetWrappedValue() noexcept
Definition: AVPacketWrapper.cpp:20
AVPacketWrapper::GetDuration
virtual int GetDuration() const noexcept=0
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
AVCodecWrapper::GetSampleFmts
virtual const AVSampleFormatFwd * GetSampleFmts() const noexcept=0
FFmpegFunctions.h
MixerSpec
Class used with Mixer.
Definition: Mix.h:55
FMT_LAST
@ FMT_LAST
Definition: ExportFFmpegDialogs.h:41
ExportPlugin
Definition: Export.h:65
FMT_OPUS
@ FMT_OPUS
Definition: ExportFFmpegDialogs.h:38
AddStringTagUTF8
void AddStringTagUTF8(char field[], int size, wxString value)
Definition: ExportFFmpeg.cpp:1162
AVPacketWrapper::RescaleDecompressionTimestamp
virtual void RescaleDecompressionTimestamp(AudacityAVRational bq, AudacityAVRational cq) noexcept=0
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
safenew
#define safenew
Definition: MemoryX.h:10
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
AVPacketWrapper::SetStreamIndex
virtual void SetStreamIndex(int index) noexcept=0
MAX_AUDIO_PACKET_SIZE
#define MAX_AUDIO_PACKET_SIZE
ExportFFmpegOPUSOptions
Options dialog for FFmpeg exporting of OPUS format.
Definition: ExportFFmpegDialogs.h:122
AUDACITY_AV_CODEC_FLAG_QSCALE
#define AUDACITY_AV_CODEC_FLAG_QSCALE
Definition: FFmpegTypes.h:77
ExposedFormat::codecid
AudacityAVCodecID codecid
codec ID (see libavcodec/avcodec.h)
Definition: ExportFFmpegDialogs.h:57
ExportFFmpeg::mEncAudioStream
std::unique_ptr< AVStreamWrapper > mEncAudioStream
Definition: ExportFFmpeg.cpp:164
AdjustFormatIndex
static int AdjustFormatIndex(int format)
Definition: ExportFFmpeg.cpp:79
encode_audio
static int encode_audio(const FFmpegFunctions &ffmpeg, AVCodecContextWrapper *avctx, AVPacketWrapper *pkt, int16_t *audio_samples, int nb_samples)
Definition: ExportFFmpeg.cpp:754
FMT_M4A
@ FMT_M4A
Definition: ExportFFmpegDialogs.h:35
ExportFFmpeg::~ExportFFmpeg
~ExportFFmpeg() override
Definition: ExportFFmpeg.cpp:249
AVCodecContextWrapper::GetSampleFmt
virtual AVSampleFormatFwd GetSampleFmt() const noexcept=0
TAG_TITLE
#define TAG_TITLE
Definition: Tags.h:60
ExportFFmpeg::mSampleRate
int mSampleRate
Definition: ExportFFmpeg.cpp:171
ExportFFmpeg::CheckSampleRate
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.
Definition: ExportFFmpeg.cpp:393
AUDACITY_AV_SAMPLE_FMT_S32P
@ AUDACITY_AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: FFmpegTypes.h:153
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
ExportFFmpeg::mBitRate
int mBitRate
Definition: ExportFFmpeg.cpp:170
ExportFFmpeg::mEncAudioFifoOutBufSize
int mEncAudioFifoOutBufSize
Definition: ExportFFmpeg.cpp:165
FFmpegFunctions::CreateMemoryBuffer
AVDataBuffer< T > CreateMemoryBuffer(int preallocatedSize) const
Definition: FFmpegFunctions.h:125
FMT_WMA2
@ FMT_WMA2
Definition: ExportFFmpegDialogs.h:39
ExportFFmpeg::mDefaultFrameSize
int mDefaultFrameSize
Definition: ExportFFmpeg.cpp:163
TAG_ALBUM
#define TAG_ALBUM
Definition: Tags.h:62