--- /dev/null
+--- ffmpeg-4.4/libavcodec/pcm-bluenc.c 2022-04-24 09:45:43.921091116 +0300
++++ ffmpeg-4.4/libavcodec/pcm-bluenc.c 2022-04-24 16:07:28.537982120 +0300
+@@ -1,6 +1,5 @@
+ /*
+ * LPCM codecs for PCM formats found in Blu-ray m2ts streams
+- * Copyright (c) 2018 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+@@ -19,314 +18,305 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
++#include "libavutil/channel_layout.h"
+ #include "avcodec.h"
+ #include "bytestream.h"
++//#include "codec_internal.h"
++#include "encode.h"
+ #include "internal.h"
+
+-typedef struct PCMBDContext {
+- uint8_t header[4]; // Header added to every frame
+- int block_size; // Size of a block of samples in bytes
+- int samples_per_block; // Number of samples per channel per block
+- int groups_per_block; // Number of 20/24-bit sample groups per block
+- uint8_t *extra_samples; // Pointer to leftover samples from a frame
+- int extra_sample_count; // Number of leftover samples in the buffer
+-} PCMBDContext;
++typedef struct BlurayPCMEncContext {
++ uint16_t header; // Header added to every frame
++} BlurayPCMEncContext;
+
+-static av_cold int pcm_bd_encode_init(AVCodecContext *avctx)
++static av_cold int pcm_bluray_encode_init(AVCodecContext *avctx)
+ {
+- PCMBDContext *s = avctx->priv_data;
+- int quant, freq;
+- uint16_t frame_size;
+- uint8_t ch_layout = 0;
+-
++ BlurayPCMEncContext *s = avctx->priv_data;
++ uint8_t ch_layout;
++ int quant, freq, frame_size;
++
++ switch(avctx->sample_fmt) {
++ case AV_SAMPLE_FMT_S16:
++ avctx->bits_per_coded_sample = 16;
++ frame_size = 120;
++ quant =1;
++ break;
++ case AV_SAMPLE_FMT_S32:
++ avctx->bits_per_coded_sample = 24;
++ frame_size = 180;
++ quant =3;
++ break;
++ default:
++ return AVERROR_BUG;
++ }
++
+ switch (avctx->sample_rate) {
+ case 48000:
+ freq = 1;
+ break;
+ case 96000:
++ frame_size *= 2;
+ freq = 4;
+ break;
+ case 192000:
+- freq = 5;
+- break;
++ frame_size *= 4;
++ freq = 5;
++ break;
++ default:
++ return AVERROR_BUG;
+ }
+
+- switch (avctx->sample_fmt) {
+- case AV_SAMPLE_FMT_S16:
+- avctx->bits_per_coded_sample = 16;
+- quant = 1;
++ frame_size *= avctx->channels;
++
++ switch (avctx->channel_layout) {
++ case AV_CH_LAYOUT_MONO:
++ ch_layout = 1;
+ break;
+-/* case AV_SAMPLE_FMT_S20:
+- avctx->bits_per_coded_sample = 20;
+- quant = 2;
++ case AV_CH_LAYOUT_STEREO:
++ ch_layout = 3;
+ break;
+-*/
+- case AV_SAMPLE_FMT_S32:
+- avctx->bits_per_coded_sample = 24;
+- quant = 3;
++ case AV_CH_LAYOUT_SURROUND:
++ ch_layout = 4;
+ break;
+- }
+-
+- avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8;
+- avctx->bit_rate = avctx->block_align * 8LL * avctx->sample_rate;
+- if (avctx->bit_rate > 19800000) {
+- av_log(avctx, AV_LOG_ERROR, "Too big bitrate: reduce sample rate, bitdepth or channels.\n");
+- return AVERROR(EINVAL);
+- }
+-
+- if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) {
+- switch (avctx->channels) {
+- case 1:
+- s->block_size = avctx->channels * 4;
+- break;
+- default:
+- s->block_size = avctx->channels * 2;
++ case AV_CH_LAYOUT_2_1:
++ ch_layout = 5;
+ break;
+- }
+- s->samples_per_block = 1;
+- frame_size = 2008 / s->block_size;
+- } else {
+- switch (avctx->channels) {
+- case 1:
+- s->block_size = 2 * avctx->channels * avctx->bits_per_coded_sample / 8;
+- s->samples_per_block = 1;
+- break;
+- case 2:
+- case 4:
+- /* one group has all the samples needed */
+- s->block_size = avctx->channels * avctx->bits_per_coded_sample / 8;
+- s->samples_per_block = 1;
+- s->groups_per_block = 2;
+- break;
+- case 8:
+- case 6:
+- /* two groups have all the samples needed */
+- s->block_size = avctx->channels * avctx->bits_per_coded_sample / 8;
+- s->samples_per_block = 1;
+- // s->groups_per_block = 2;
+- break;
+- default:
+- /* need avctx->channels groups */
+- s->block_size = 4 * avctx->channels *
+- avctx->bits_per_coded_sample / 8;
+- s->samples_per_block = 4;
+- s->groups_per_block = avctx->channels;
+- break;
+- }
+-
+- frame_size = FFALIGN(2008 / s->block_size, s->samples_per_block);
++ case AV_CH_LAYOUT_4POINT0:
++ ch_layout = 6;
++ break;
++ case AV_CH_LAYOUT_2_2:
++ ch_layout = 7;
++ break;
++ case AV_CH_LAYOUT_5POINT0:
++ ch_layout = 8;
++ break;
++ case AV_CH_LAYOUT_5POINT1_BACK:
++ ch_layout = 9;
++ break;
++ case AV_CH_LAYOUT_7POINT0:
++ ch_layout = 10;
++ break;
++ case AV_CH_LAYOUT_7POINT1:
++ ch_layout = 11;
++ break;
++ default:
++ return AVERROR_BUG;
+ }
+
+- switch(avctx->channel_layout) {
+- case AV_CH_LAYOUT_MONO:
+- ch_layout = 1;
+- break;
+- case AV_CH_LAYOUT_STEREO:
+- ch_layout = 3;
+- break;
+- case AV_CH_LAYOUT_5POINT1:
+- case AV_CH_LAYOUT_5POINT1_BACK:
+- ch_layout = 9;
+- break;
+- case AV_CH_LAYOUT_7POINT1:
+- ch_layout = 11;
+- break;
+- default:
+- av_log(avctx, AV_LOG_ERROR, "Not yet implemented ch layout!\n");
+- }
+-// description on the web:
+-/* http://forum.doom9.org/showthread.php?t=152897
+-
+-It's a header.
+-
+-size in bytes = 16 bits (big endian)
+-channel assignment = 4 bits
+-sampling frequency = 4 bits
+-bits per sample = 2 bits
+-start flag = 1 bit
+-reserved = 5 bits
+-
+-channel assignment
+-1 = mono
+-3 = stereo
+-4 = 3/0
+-5 = 2/1
+-6 = 3/1
+-7 = 2/2
+-8 = 3/2
+-9 = 3/2+lfe
+-10 = 3/4
+-11 = 3/4+lfe
+-
+-sampling frequency
+-1 = 48 kHz
+-4 = 96 kHz
+-5 = 192 kHz
+-
+-bits per sample
+-1 = 16
+-2 = 20
+-3 = 24
+-*/
+-
+- s->header[2] = (ch_layout << 4) | (freq);
+- s->header[3] = (quant << 6) | 0x1 ;
+-
+-
+- avctx->frame_size = frame_size; // in num. of samples
++ s->header = (((ch_layout << 4) | freq) << 8) | (quant << 6);
++ avctx->frame_size = frame_size;
+
+ return 0;
+ }
+
+-static int pcm_bd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+- const AVFrame *frame, int *got_packet_ptr)
++static int pcm_bluray_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
++ const AVFrame *frame, int *got_packet_ptr)
+ {
+- PCMBDContext *s = avctx->priv_data;
+- int samples, channels;
+- int64_t pkt_size = (frame->nb_samples / s->samples_per_block) * s->block_size + 4;
++ BlurayPCMEncContext *s = avctx->priv_data;
++ int sample_size, samples, channel, num_dest_channels;
+ const int16_t *src16;
+ const int32_t *src32;
++ unsigned pkt_size;
+ PutByteContext pb;
+ int ret;
+
+- if ((ret = ff_alloc_packet2(avctx, avpkt, pkt_size, 0)) < 0)
++ num_dest_channels = FFALIGN(avctx->channels, 2);
++ sample_size = (num_dest_channels *
++ (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3;
++ samples = frame->nb_samples;
++
++ pkt_size = sample_size * samples + 4;
++
++ if ((ret = ff_get_encode_buffer(avctx, avpkt, pkt_size, 0)) < 0)
+ return ret;
+
+- AV_WB16(s->header, pkt_size - 4);
+- memcpy(avpkt->data, s->header, 4);
++ AV_WB16(avpkt->data, pkt_size - 4);
++ AV_WB16(avpkt->data + 2, s->header);
+
+ src16 = (const int16_t *)frame->data[0];
+ src32 = (const int32_t *)frame->data[0];
+
+ bytestream2_init_writer(&pb, avpkt->data + 4, avpkt->size - 4);
+
+- int num_source_channels = FFALIGN(avctx->channels, 2);
+- // int num_source_channels = avctx->channels;
+- // int sample_size = (num_source_channels *
+- // (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3;
+- samples = frame->nb_samples * num_source_channels;
+-
+- switch (avctx->sample_fmt) {
+- case AV_SAMPLE_FMT_S16:
+- switch (avctx->channels) {
+- case 1:
+- do {
+- do {
+- channels = avctx->channels;
+- bytestream2_put_be16(&pb, *src16++);
+- } while (--channels);
+- bytestream2_put_be16(&pb, 0);
+- } while (--samples);
+- break;
+- case 2:
+- do {
+- bytestream2_put_be16(&pb, *src16++);
+- } while (--samples);
+- break;
+- case 6:
+- do {
+- bytestream2_put_be16(&pb, src16[0]);
+- bytestream2_put_be16(&pb, src16[1]);
+- bytestream2_put_be16(&pb, src16[2]);
+- bytestream2_put_be16(&pb, src16[4]);
+- bytestream2_put_be16(&pb, src16[5]);
+- bytestream2_put_be16(&pb, src16[3]);
+- src16+=6;
+- } while (--samples);
+- break;
+- case 8:
+- do {
+- bytestream2_put_be16(&pb, src16[0]);
+- bytestream2_put_be16(&pb, src16[1]);
+- bytestream2_put_be16(&pb, src16[2]);
+- bytestream2_put_be16(&pb, src16[6]);
+- bytestream2_put_be16(&pb, src16[4]);
+- bytestream2_put_be16(&pb, src16[5]);
+- bytestream2_put_be16(&pb, src16[7]);
+- bytestream2_put_be16(&pb, src16[3]);
+- src16+=8;
+- } while (--samples);
+- break;
+-
+- default:
+- av_log(avctx, AV_LOG_ERROR, "this ch config not implemented for s16!\n");
++ switch (avctx->channel_layout) {
++ /* cases with same number of source and coded channels */
++ case AV_CH_LAYOUT_STEREO:
++ case AV_CH_LAYOUT_4POINT0:
++ case AV_CH_LAYOUT_2_2:
++ samples *= num_dest_channels;
++ if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
++#if HAVE_BIGENDIAN
++ bytestream2_put_bufferu(&pb, frame->data[0], samples * 2);
++#else
++ do {
++ bytestream2_put_be16u(&pb, *src16++);
++ } while (--samples);
++#endif
++ } else {
++ do {
++ bytestream2_put_be24u(&pb, (*src32++) >> 8);
++ } while (--samples);
++ }
+ break;
++ /* cases where number of source channels = coded channels + 1 */
++ case AV_CH_LAYOUT_MONO:
++ case AV_CH_LAYOUT_SURROUND:
++ case AV_CH_LAYOUT_2_1:
++ case AV_CH_LAYOUT_5POINT0:
++ if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
++ do {
++#if HAVE_BIGENDIAN
++ bytestream2_put_bufferu(&pb, (const uint8_t *)src16, avctx->ch_layout.nb_channels * 2);
++ src16 += avctx->channels;
++#else
++ channel = avctx->channels;
++ do {
++ bytestream2_put_be16u(&pb, *src16++);
++ } while (--channel);
++#endif
++ bytestream2_put_ne16(&pb, 0);
++ } while (--samples);
++ } else {
++ do {
++ channel = avctx->channels;
++ do {
++ bytestream2_put_be24u(&pb, (*src32++) >> 8);
++ } while (--channel);
++ bytestream2_put_ne24(&pb, 0);
++ } while (--samples);
+ }
+ break;
+- case AV_SAMPLE_FMT_S32:
+- switch (avctx->channels) {
+- case 2:
+- case 4:
+- do {
+- bytestream2_put_be24(&pb, (*src32++) >> 8);
+- } while (--samples);
+- break;
+- case 8:
+- do {
+- bytestream2_put_be24(&pb, src32[0] >> 8);
+- bytestream2_put_be24(&pb, src32[1] >> 8);
+- bytestream2_put_be24(&pb, src32[2] >> 8);
+- bytestream2_put_be24(&pb, src32[6] >> 8);
+- bytestream2_put_be24(&pb, src32[4] >> 8);
+- bytestream2_put_be24(&pb, src32[5] >> 8);
+- bytestream2_put_be24(&pb, src32[7] >> 8);
+- bytestream2_put_be24(&pb, src32[3] >> 8);
+- src32+=8;
+- } while (--samples);
+- break;
+- case 6:
+- do {
+- bytestream2_put_be24(&pb, src32[0] >> 8);
+- bytestream2_put_be24(&pb, src32[1] >> 8);
+- bytestream2_put_be24(&pb, src32[2] >> 8);
+- bytestream2_put_be24(&pb, src32[4] >> 8);
+- bytestream2_put_be24(&pb, src32[5] >> 8);
+- bytestream2_put_be24(&pb, src32[3] >> 8);
+- src32+=6;
+- } while (--samples);
+- break;
+- case 1:
+- do {
+- do {
+- channels = avctx->channels;
+- bytestream2_put_be24(&pb, (*src32++) >> 8);
+- } while (--channels);
+- bytestream2_put_be24(&pb, 0);
+- } while (--samples);
+- break;
+- default:
+- av_log(avctx, AV_LOG_ERROR, "this bitdepth not implemented!\n");
+- break;
+- }
+- break;
++ /* remapping: L, R, C, LBack, RBack, LF */
++ case AV_CH_LAYOUT_5POINT1_BACK:
++ if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
++ do {
++ bytestream2_put_be16u(&pb, src16[0]);
++ bytestream2_put_be16u(&pb, src16[1]);
++ bytestream2_put_be16u(&pb, src16[2]);
++ bytestream2_put_be16u(&pb, src16[4]);
++ bytestream2_put_be16u(&pb, src16[5]);
++ bytestream2_put_be16u(&pb, src16[3]);
++ src16 += 6;
++ } while (--samples);
++ } else {
++ do {
++ bytestream2_put_be24u(&pb, src32[0] >> 8);
++ bytestream2_put_be24u(&pb, src32[1] >> 8);
++ bytestream2_put_be24u(&pb, src32[2] >> 8);
++ bytestream2_put_be24u(&pb, src32[4] >> 8);
++ bytestream2_put_be24u(&pb, src32[5] >> 8);
++ bytestream2_put_be24u(&pb, src32[3] >> 8);
++ src32 += 6;
++ } while (--samples);
++ }
++ break;
++ /* remapping: L, R, C, LSide, LBack, RBack, RSide, <unused> */
++ case AV_CH_LAYOUT_7POINT0:
++ if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
++ do {
++ bytestream2_put_be16u(&pb, src16[0]);
++ bytestream2_put_be16u(&pb, src16[1]);
++ bytestream2_put_be16u(&pb, src16[2]);
++ bytestream2_put_be16u(&pb, src16[5]);
++ bytestream2_put_be16u(&pb, src16[3]);
++ bytestream2_put_be16u(&pb, src16[4]);
++ bytestream2_put_be16u(&pb, src16[6]);
++ src16 += 7;
++ bytestream2_put_ne16(&pb, 0);
++ } while (--samples);
++ } else {
++ do {
++ bytestream2_put_be24u(&pb, src32[0] >> 8);
++ bytestream2_put_be24u(&pb, src32[1] >> 8);
++ bytestream2_put_be24u(&pb, src32[2] >> 8);
++ bytestream2_put_be24u(&pb, src32[5] >> 8);
++ bytestream2_put_be24u(&pb, src32[3] >> 8);
++ bytestream2_put_be24u(&pb, src32[4] >> 8);
++ bytestream2_put_be24u(&pb, src32[6] >> 8);
++ src32 += 7;
++ bytestream2_put_ne24(&pb, 0);
++ } while (--samples);
++ }
++ break;
++ /* remapping: L, R, C, LSide, LBack, RBack, RSide, LF */
++ case AV_CH_LAYOUT_7POINT1:
++ if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
++ do {
++ bytestream2_put_be16u(&pb, src16[0]);
++ bytestream2_put_be16u(&pb, src16[1]);
++ bytestream2_put_be16u(&pb, src16[2]);
++ bytestream2_put_be16u(&pb, src16[6]);
++ bytestream2_put_be16u(&pb, src16[4]);
++ bytestream2_put_be16u(&pb, src16[5]);
++ bytestream2_put_be16u(&pb, src16[7]);
++ bytestream2_put_be16u(&pb, src16[3]);
++ src16 += 8;
++ } while (--samples);
++ } else {
++ do {
++ bytestream2_put_be24u(&pb, src32[0]);
++ bytestream2_put_be24u(&pb, src32[1]);
++ bytestream2_put_be24u(&pb, src32[2]);
++ bytestream2_put_be24u(&pb, src32[6]);
++ bytestream2_put_be24u(&pb, src32[4]);
++ bytestream2_put_be24u(&pb, src32[5]);
++ bytestream2_put_be24u(&pb, src32[7]);
++ bytestream2_put_be24u(&pb, src32[3]);
++ src32 += 8;
++ } while (--samples);
++ }
++ break;
++ default:
++ return AVERROR_BUG;
+ }
+
+- avpkt->pts = frame->pts;
+- avpkt->size = pkt_size;
++ avpkt->pts = frame->pts;
+ avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples);
+ *got_packet_ptr = 1;
+
+ return 0;
+ }
+
+-AVCodec ff_pcm_bluray_encoder = {
+- .name = "pcm_bluray",
+- .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|24-bit big-endian for bluray media"),
+- .type = AVMEDIA_TYPE_AUDIO,
+- .id = AV_CODEC_ID_PCM_BLURAY,
+- .priv_data_size = sizeof(PCMBDContext),
+- .init = pcm_bd_encode_init,
+- .encode2 = pcm_bd_encode_frame,
+- .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
+- .supported_samplerates = (const int[]) { 48000, 96000, 192000, 0},
+- .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
+- AV_CH_LAYOUT_STEREO,
+- AV_CH_LAYOUT_5POINT1,
+- AV_CH_LAYOUT_5POINT1_BACK,
+- AV_CH_LAYOUT_7POINT1,
+- 0 },
+- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+- AV_SAMPLE_FMT_S32,
+- AV_SAMPLE_FMT_NONE },
+- .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
++const AVCodec ff_pcm_bluray_encoder = {
++ .name = "pcm_bluray",
++ .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"),
++ .type = AVMEDIA_TYPE_AUDIO,
++ .id = AV_CODEC_ID_PCM_BLURAY,
++ .priv_data_size = sizeof(BlurayPCMEncContext),
++ .init = pcm_bluray_encode_init,
++ .encode2 = pcm_bluray_encode_frame,
++ .supported_samplerates = (const int[]) { 48000, 96000, 192000, 0 },
++//#define FF_API_OLD_CHANNEL_LAYOUT 1
++#if 1
++ .channel_layouts = (const uint64_t[]) {
++ AV_CH_LAYOUT_MONO,
++ AV_CH_LAYOUT_STEREO,
++ AV_CH_LAYOUT_SURROUND,
++ AV_CH_LAYOUT_2_1,
++ AV_CH_LAYOUT_4POINT0,
++ AV_CH_LAYOUT_2_2,
++ AV_CH_LAYOUT_5POINT0,
++ AV_CH_LAYOUT_5POINT1_BACK,
++ AV_CH_LAYOUT_7POINT0,
++ AV_CH_LAYOUT_7POINT1,
++ 0 },
++#endif
++#if 0
++ .p.ch_layouts = (const AVChannelLayout[]) {
++ AV_CHANNEL_LAYOUT_MONO,
++ AV_CHANNEL_LAYOUT_STEREO,
++ AV_CHANNEL_LAYOUT_SURROUND,
++ AV_CHANNEL_LAYOUT_2_1,
++ AV_CHANNEL_LAYOUT_4POINT0,
++ AV_CHANNEL_LAYOUT_2_2,
++ AV_CHANNEL_LAYOUT_5POINT0,
++ AV_CHANNEL_LAYOUT_5POINT1,
++ AV_CHANNEL_LAYOUT_7POINT0,
++ AV_CHANNEL_LAYOUT_7POINT1,
++ { 0 } },
++#endif
++ .sample_fmts = (const enum AVSampleFormat[]) {
++ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE },
++ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
++ .capabilities = AV_CODEC_CAP_DR1,
+ };