Skip to content

Commit

Permalink
encavcodecaudio: convert the 6.1 and 7.1 channel layouts to the ones …
Browse files Browse the repository at this point in the history
…required by the alac encoder
  • Loading branch information
galad87 committed Oct 21, 2024
1 parent 0317f2e commit 7167c91
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions libhb/encavcodecaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ struct hb_work_private_s
float * input_buf;
hb_list_t * list;

AVChannelLayout in_ch_layout;
AVChannelLayout out_ch_layout;

SwrContext * swresample;

int64_t last_pts;
Expand Down Expand Up @@ -64,8 +67,10 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)

// channel count, layout and matrix encoding
int matrix_encoding;
uint64_t channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown,
&matrix_encoding);
uint64_t in_channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown,
&matrix_encoding);
uint64_t out_channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown,
&matrix_encoding);
pv->out_discrete_channels =
hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);

Expand Down Expand Up @@ -108,17 +113,17 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
}
// FFmpeg's libfdk-aac wrapper expects back channels for 5.1
// audio, and will error out unless we translate the layout
if (channel_layout == AV_CH_LAYOUT_5POINT1)
channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
if (in_channel_layout == AV_CH_LAYOUT_5POINT1)
out_channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
break;

case HB_ACODEC_FFAAC:
codec_name = "aac";
// Use 5.1 back for AAC because 5.1 side uses a
// not-so-universally supported feature to signal the
// non-standard layout
if (channel_layout == AV_CH_LAYOUT_5POINT1)
channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
if (in_channel_layout == AV_CH_LAYOUT_5POINT1)
out_channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
break;

case HB_ACODEC_FFALAC:
Expand All @@ -135,6 +140,12 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
bits_per_raw_sample = 16;
break;
}
if (in_channel_layout == AV_CH_LAYOUT_5POINT1)
out_channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
if (in_channel_layout == AV_CH_LAYOUT_6POINT1)
out_channel_layout = AV_CH_LAYOUT_6POINT1_BACK;
if (in_channel_layout == AV_CH_LAYOUT_7POINT1)
out_channel_layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK;
break;

case HB_ACODEC_FFFLAC:
Expand Down Expand Up @@ -165,9 +176,9 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
codec_name = "libopus";
// FFmpeg's libopus wrapper expects back channels for 5.1
// audio, and will error out unless we translate the layout
if (channel_layout == AV_CH_LAYOUT_5POINT1)
channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
if (hb_layout_get_discrete_channel_count(channel_layout) > 2)
if (in_channel_layout == AV_CH_LAYOUT_5POINT1)
out_channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
if (hb_layout_get_discrete_channel_count(in_channel_layout) > 2)
av_dict_set(&av_opts, "mapping_family", "1", 0);
break;

Expand Down Expand Up @@ -197,15 +208,15 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
}
}

AVChannelLayout ch_layout = {0};
av_channel_layout_from_mask(&ch_layout, channel_layout);
av_channel_layout_from_mask(&pv->in_ch_layout, in_channel_layout);
av_channel_layout_from_mask(&pv->out_ch_layout, out_channel_layout);

// allocate the context and apply the settings
context = avcodec_alloc_context3(codec);
hb_ff_set_sample_fmt(context, codec, sample_fmt);
context->bits_per_raw_sample = bits_per_raw_sample;
context->profile = profile;
context->ch_layout = ch_layout;
context->ch_layout = pv->out_ch_layout;
context->sample_rate = audio->config.out.samplerate;
context->time_base = (AVRational){1, 90000};

Expand Down Expand Up @@ -266,7 +277,8 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
av_get_bytes_per_sample(context->sample_fmt)));

// sample_fmt conversion
if (context->sample_fmt != AV_SAMPLE_FMT_FLT)
if (context->sample_fmt != AV_SAMPLE_FMT_FLT ||
av_channel_layout_compare(&pv->in_ch_layout, &pv->out_ch_layout))
{
pv->output_buf = malloc(pv->max_output_bytes);
pv->swresample = swr_alloc();
Expand All @@ -280,7 +292,7 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
av_opt_set_int(pv->swresample, "out_sample_fmt",
context->sample_fmt, 0);
av_opt_set_chlayout(pv->swresample, "in_chlayout",
&context->ch_layout, 0);
&pv->in_ch_layout, 0);
av_opt_set_chlayout(pv->swresample, "out_chlayout",
&context->ch_layout, 0);
av_opt_set_int(pv->swresample, "in_sample_rate",
Expand Down Expand Up @@ -372,6 +384,9 @@ static void encavcodecaClose(hb_work_object_t * w)
swr_free(&pv->swresample);
}

av_channel_layout_uninit(&pv->in_ch_layout);
av_channel_layout_uninit(&pv->out_ch_layout);

free(pv);
w->private_data = NULL;
}
Expand Down Expand Up @@ -443,7 +458,7 @@ static void Encode(hb_work_object_t *w, hb_buffer_list_t *list)
int out_size;
AVFrame frame = { .nb_samples = pv->samples_per_frame,
.format = pv->context->sample_fmt,
.ch_layout = pv->context->ch_layout
.ch_layout = pv->in_ch_layout
};

out_size = av_samples_get_buffer_size(NULL,
Expand Down

0 comments on commit 7167c91

Please sign in to comment.