audio: extended support for planar/packed formats
This commit is contained in:
@@ -455,7 +455,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector<QString> &filenames, cons
|
||||
// Create resampling context
|
||||
SwrContext* resampler = swr_alloc_set_opts(nullptr,
|
||||
params.channel_layout(),
|
||||
FFmpegUtils::GetFFmpegSampleFormat(params.format(), true),
|
||||
FFmpegUtils::GetFFmpegSampleFormat(params.format()),
|
||||
params.sample_rate(),
|
||||
channel_layout,
|
||||
static_cast<AVSampleFormat>(instance_.avstream()->codecpar->format),
|
||||
|
||||
@@ -62,6 +62,38 @@ QStringList FFmpegEncoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const
|
||||
return pix_fmts;
|
||||
}
|
||||
|
||||
std::vector<AudioParams::Format> FFmpegEncoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const
|
||||
{
|
||||
std::vector<AudioParams::Format> f;
|
||||
|
||||
if (c == ExportCodec::kCodecPCM) {
|
||||
// FFmpeg lists these as separate codecs so we need custom functionality here
|
||||
// We list signed 16 first because ExportDialog will always use the first element by default
|
||||
// (beacuse first element is the "default" in FFmpeg)
|
||||
f = {
|
||||
AudioParams::kFormatSigned16Packed,
|
||||
AudioParams::kFormatUnsigned8Packed,
|
||||
AudioParams::kFormatSigned32Packed,
|
||||
AudioParams::kFormatSigned64Packed,
|
||||
AudioParams::kFormatFloat32Packed,
|
||||
AudioParams::kFormatFloat64Packed
|
||||
};
|
||||
} else {
|
||||
const AVCodec* codec_info = GetEncoder(c, AudioParams::kFormatInvalid);
|
||||
|
||||
if (codec_info && codec_info->sample_fmts) {
|
||||
for (int i=0; codec_info->sample_fmts[i]!=-1; i++) {
|
||||
AudioParams::Format this_format = FFmpegUtils::GetNativeSampleFormat(static_cast<AVSampleFormat>(codec_info->sample_fmts[i]));
|
||||
if (this_format != AudioParams::kFormatInvalid) {
|
||||
f.push_back(this_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool FFmpegEncoder::Open()
|
||||
{
|
||||
if (open_) {
|
||||
@@ -246,14 +278,14 @@ bool FFmpegEncoder::WriteAudio(SampleBufferPtr audio)
|
||||
int input_linesize;
|
||||
|
||||
av_samples_alloc_array_and_samples(&input_data, &input_linesize, audio->audio_params().channel_count(),
|
||||
input_sample_count, FFmpegUtils::GetFFmpegSampleFormat(audio->audio_params().format(), true), 0);
|
||||
input_sample_count, FFmpegUtils::GetFFmpegSampleFormat(audio->audio_params().format()), 0);
|
||||
|
||||
for (int i=0; i<audio->audio_params().channel_count(); i++) {
|
||||
memcpy(input_data[i], audio->data(i), input_sample_count * audio->audio_params().bytes_per_sample_per_channel());
|
||||
}
|
||||
}
|
||||
|
||||
result = WriteAudioData(audio->audio_params(), true, const_cast<const uint8_t**>(input_data), input_sample_count);
|
||||
result = WriteAudioData(audio->audio_params(), const_cast<const uint8_t**>(input_data), input_sample_count);
|
||||
|
||||
if (input_data) {
|
||||
av_freep(&input_data[0]);
|
||||
@@ -263,9 +295,9 @@ bool FFmpegEncoder::WriteAudio(SampleBufferPtr audio)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FFmpegEncoder::WriteAudioData(const AudioParams &audio_params, bool planar, const uint8_t **input_data, int input_sample_count)
|
||||
bool FFmpegEncoder::WriteAudioData(const AudioParams &audio_params, const uint8_t **input_data, int input_sample_count)
|
||||
{
|
||||
if (!InitializeResampleContext(audio_params, planar)) {
|
||||
if (!InitializeResampleContext(audio_params)) {
|
||||
qCritical() << "Failed to initialize resample context";
|
||||
return false;
|
||||
}
|
||||
@@ -783,7 +815,7 @@ void FFmpegEncoder::FlushCodecCtx(AVCodecContext *codec_ctx, AVStream* stream)
|
||||
av_packet_free(&pkt);
|
||||
}
|
||||
|
||||
bool FFmpegEncoder::InitializeResampleContext(const AudioParams &audio, bool planar)
|
||||
bool FFmpegEncoder::InitializeResampleContext(const AudioParams &audio)
|
||||
{
|
||||
if (audio_resample_ctx_) {
|
||||
return true;
|
||||
@@ -795,7 +827,7 @@ bool FFmpegEncoder::InitializeResampleContext(const AudioParams &audio, bool pla
|
||||
audio_codec_ctx_->sample_fmt,
|
||||
audio_codec_ctx_->sample_rate,
|
||||
static_cast<int64_t>(audio.channel_layout()),
|
||||
FFmpegUtils::GetFFmpegSampleFormat(audio.format(), planar),
|
||||
FFmpegUtils::GetFFmpegSampleFormat(audio.format()),
|
||||
audio.sample_rate(),
|
||||
0,
|
||||
nullptr);
|
||||
@@ -875,18 +907,24 @@ const AVCodec *FFmpegEncoder::GetEncoder(ExportCodec::Codec c, AudioParams::Form
|
||||
switch (aformat) {
|
||||
case AudioParams::kFormatInvalid:
|
||||
case AudioParams::kFormatCount:
|
||||
case AudioParams::kFormatUnsigned8Planar:
|
||||
case AudioParams::kFormatSigned16Planar:
|
||||
case AudioParams::kFormatSigned32Planar:
|
||||
case AudioParams::kFormatSigned64Planar:
|
||||
case AudioParams::kFormatFloat32Planar:
|
||||
case AudioParams::kFormatFloat64Planar:
|
||||
break;
|
||||
case AudioParams::kFormatUnsigned8:
|
||||
case AudioParams::kFormatUnsigned8Packed:
|
||||
return avcodec_find_encoder(AV_CODEC_ID_PCM_U8);
|
||||
case AudioParams::kFormatSigned16:
|
||||
case AudioParams::kFormatSigned16Packed:
|
||||
return avcodec_find_encoder(AV_CODEC_ID_PCM_S16LE);
|
||||
case AudioParams::kFormatSigned32:
|
||||
case AudioParams::kFormatSigned32Packed:
|
||||
return avcodec_find_encoder(AV_CODEC_ID_PCM_S32LE);
|
||||
case AudioParams::kFormatSigned64:
|
||||
case AudioParams::kFormatSigned64Packed:
|
||||
return avcodec_find_encoder(AV_CODEC_ID_PCM_S64LE);
|
||||
case AudioParams::kFormatFloat32:
|
||||
case AudioParams::kFormatFloat32Packed:
|
||||
return avcodec_find_encoder(AV_CODEC_ID_PCM_F32LE);
|
||||
case AudioParams::kFormatFloat64:
|
||||
case AudioParams::kFormatFloat64Packed:
|
||||
return avcodec_find_encoder(AV_CODEC_ID_PCM_F64LE);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -41,13 +41,15 @@ public:
|
||||
|
||||
virtual QStringList GetPixelFormatsForCodec(ExportCodec::Codec c) const override;
|
||||
|
||||
virtual std::vector<AudioParams::Format> GetSampleFormatsForCodec(ExportCodec::Codec c) const override;
|
||||
|
||||
virtual bool Open() override;
|
||||
|
||||
virtual bool WriteFrame(olive::FramePtr frame, olive::rational time) override;
|
||||
|
||||
virtual bool WriteAudio(olive::SampleBufferPtr audio) override;
|
||||
|
||||
bool WriteAudioData(const AudioParams &audio_params, bool planar, const uint8_t **data, int input_sample_count);
|
||||
bool WriteAudioData(const AudioParams &audio_params, const uint8_t **data, int input_sample_count);
|
||||
|
||||
virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override;
|
||||
|
||||
@@ -78,7 +80,7 @@ private:
|
||||
void FlushEncoders();
|
||||
void FlushCodecCtx(AVCodecContext* codec_ctx, AVStream *stream);
|
||||
|
||||
bool InitializeResampleContext(const AudioParams &audio, bool planar);
|
||||
bool InitializeResampleContext(const AudioParams &audio);
|
||||
|
||||
static const AVCodec *GetEncoder(ExportCodec::Codec c, AudioParams::Format aformat);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user