| 1465 | |
| 1466 | |
| 1467 | bool FFmpegExporter::Finalize() |
| 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() & |
| 1496 | AUDACITY_AV_CODEC_CAP_SMALL_LAST_FRAME || |
| 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? |
| 1508 | memset(mEncAudioFifoOutBuf.data(), 0, mEncAudioFifoOutBufSize); |
| 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 | { |
no test coverage detected