--- 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, */ + 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, };