ffmpeg: Properly handle non-planar formats
For non-planar formats, only the first data plane is used. Therefore, they need to be handled differently in certain places.
This commit is contained in:
parent
c9c26955d2
commit
a28eac08ae
|
@ -227,20 +227,7 @@ bool FFmpegAudioStream::Init(AVFormatContext* format_context) {
|
||||||
codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
|
codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
codec_context->bit_rate = Settings::values.audio_bitrate;
|
codec_context->bit_rate = Settings::values.audio_bitrate;
|
||||||
if (codec->sample_fmts) {
|
if (codec->sample_fmts) {
|
||||||
codec_context->sample_fmt = AV_SAMPLE_FMT_NONE;
|
codec_context->sample_fmt = codec->sample_fmts[0];
|
||||||
// Use any planar format
|
|
||||||
const AVSampleFormat* ptr = codec->sample_fmts;
|
|
||||||
while ((*ptr) != -1) {
|
|
||||||
if (av_sample_fmt_is_planar((*ptr))) {
|
|
||||||
codec_context->sample_fmt = (*ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
if (codec_context->sample_fmt == AV_SAMPLE_FMT_NONE) {
|
|
||||||
LOG_ERROR(Render, "Specified audio encoder does not support any planar format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
codec_context->sample_fmt = AV_SAMPLE_FMT_S16P;
|
codec_context->sample_fmt = AV_SAMPLE_FMT_S16P;
|
||||||
}
|
}
|
||||||
|
@ -341,8 +328,14 @@ void FFmpegAudioStream::ProcessFrame(const VariableAudioFrame& channel0,
|
||||||
const auto sample_size = av_get_bytes_per_sample(codec_context->sample_fmt);
|
const auto sample_size = av_get_bytes_per_sample(codec_context->sample_fmt);
|
||||||
std::array<const u8*, 2> src_data = {reinterpret_cast<const u8*>(channel0.data()),
|
std::array<const u8*, 2> src_data = {reinterpret_cast<const u8*>(channel0.data()),
|
||||||
reinterpret_cast<const u8*>(channel1.data())};
|
reinterpret_cast<const u8*>(channel1.data())};
|
||||||
std::array<u8*, 2> dst_data = {resampled_data[0] + sample_size * offset,
|
|
||||||
|
std::array<u8*, 2> dst_data;
|
||||||
|
if (av_sample_fmt_is_planar(codec_context->sample_fmt)) {
|
||||||
|
dst_data = {resampled_data[0] + sample_size * offset,
|
||||||
resampled_data[1] + sample_size * offset};
|
resampled_data[1] + sample_size * offset};
|
||||||
|
} else {
|
||||||
|
dst_data = {resampled_data[0] + sample_size * offset * 2}; // 2 channels
|
||||||
|
}
|
||||||
|
|
||||||
auto resampled_count = swr_convert(swr_context.get(), dst_data.data(), frame_size - offset,
|
auto resampled_count = swr_convert(swr_context.get(), dst_data.data(), frame_size - offset,
|
||||||
src_data.data(), channel0.size());
|
src_data.data(), channel0.size());
|
||||||
|
@ -360,7 +353,9 @@ void FFmpegAudioStream::ProcessFrame(const VariableAudioFrame& channel0,
|
||||||
// Prepare frame
|
// Prepare frame
|
||||||
audio_frame->nb_samples = frame_size;
|
audio_frame->nb_samples = frame_size;
|
||||||
audio_frame->data[0] = resampled_data[0];
|
audio_frame->data[0] = resampled_data[0];
|
||||||
|
if (av_sample_fmt_is_planar(codec_context->sample_fmt)) {
|
||||||
audio_frame->data[1] = resampled_data[1];
|
audio_frame->data[1] = resampled_data[1];
|
||||||
|
}
|
||||||
audio_frame->pts = frame_count * frame_size;
|
audio_frame->pts = frame_count * frame_size;
|
||||||
frame_count++;
|
frame_count++;
|
||||||
|
|
||||||
|
@ -383,7 +378,9 @@ void FFmpegAudioStream::Flush() {
|
||||||
// Send the last samples
|
// Send the last samples
|
||||||
audio_frame->nb_samples = offset;
|
audio_frame->nb_samples = offset;
|
||||||
audio_frame->data[0] = resampled_data[0];
|
audio_frame->data[0] = resampled_data[0];
|
||||||
|
if (av_sample_fmt_is_planar(codec_context->sample_fmt)) {
|
||||||
audio_frame->data[1] = resampled_data[1];
|
audio_frame->data[1] = resampled_data[1];
|
||||||
|
}
|
||||||
audio_frame->pts = frame_count * frame_size;
|
audio_frame->pts = frame_count * frame_size;
|
||||||
|
|
||||||
SendFrame(audio_frame.get());
|
SendFrame(audio_frame.get());
|
||||||
|
|
Reference in New Issue