1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * LPCM codecs for PCM formats found in Blu-ray m2ts streams 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 22cabdff1aSopenharmony_ci#include "avcodec.h" 23cabdff1aSopenharmony_ci#include "bytestream.h" 24cabdff1aSopenharmony_ci#include "codec_internal.h" 25cabdff1aSopenharmony_ci#include "encode.h" 26cabdff1aSopenharmony_ci#include "internal.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_citypedef struct BlurayPCMEncContext { 29cabdff1aSopenharmony_ci uint16_t header; // Header added to every frame 30cabdff1aSopenharmony_ci} BlurayPCMEncContext; 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_cistatic av_cold int pcm_bluray_encode_init(AVCodecContext *avctx) 33cabdff1aSopenharmony_ci{ 34cabdff1aSopenharmony_ci BlurayPCMEncContext *s = avctx->priv_data; 35cabdff1aSopenharmony_ci uint8_t ch_layout; 36cabdff1aSopenharmony_ci int quant, freq, frame_size; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci switch (avctx->sample_fmt) { 39cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S16: 40cabdff1aSopenharmony_ci avctx->bits_per_coded_sample = 16; 41cabdff1aSopenharmony_ci frame_size = 240; 42cabdff1aSopenharmony_ci quant = 1; 43cabdff1aSopenharmony_ci break; 44cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S32: 45cabdff1aSopenharmony_ci frame_size = 360; 46cabdff1aSopenharmony_ci avctx->bits_per_coded_sample = 24; 47cabdff1aSopenharmony_ci quant = 3; 48cabdff1aSopenharmony_ci break; 49cabdff1aSopenharmony_ci default: 50cabdff1aSopenharmony_ci return AVERROR_BUG; 51cabdff1aSopenharmony_ci } 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci switch (avctx->sample_rate) { 54cabdff1aSopenharmony_ci case 48000: 55cabdff1aSopenharmony_ci freq = 1; 56cabdff1aSopenharmony_ci break; 57cabdff1aSopenharmony_ci case 96000: 58cabdff1aSopenharmony_ci freq = 4; 59cabdff1aSopenharmony_ci break; 60cabdff1aSopenharmony_ci case 192000: 61cabdff1aSopenharmony_ci freq = 5; 62cabdff1aSopenharmony_ci break; 63cabdff1aSopenharmony_ci default: 64cabdff1aSopenharmony_ci return AVERROR_BUG; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci switch (avctx->ch_layout.u.mask) { 68cabdff1aSopenharmony_ci case AV_CH_LAYOUT_MONO: 69cabdff1aSopenharmony_ci ch_layout = 1; 70cabdff1aSopenharmony_ci break; 71cabdff1aSopenharmony_ci case AV_CH_LAYOUT_STEREO: 72cabdff1aSopenharmony_ci ch_layout = 3; 73cabdff1aSopenharmony_ci break; 74cabdff1aSopenharmony_ci case AV_CH_LAYOUT_SURROUND: 75cabdff1aSopenharmony_ci ch_layout = 4; 76cabdff1aSopenharmony_ci break; 77cabdff1aSopenharmony_ci case AV_CH_LAYOUT_2_1: 78cabdff1aSopenharmony_ci ch_layout = 5; 79cabdff1aSopenharmony_ci break; 80cabdff1aSopenharmony_ci case AV_CH_LAYOUT_4POINT0: 81cabdff1aSopenharmony_ci ch_layout = 6; 82cabdff1aSopenharmony_ci break; 83cabdff1aSopenharmony_ci case AV_CH_LAYOUT_2_2: 84cabdff1aSopenharmony_ci ch_layout = 7; 85cabdff1aSopenharmony_ci break; 86cabdff1aSopenharmony_ci case AV_CH_LAYOUT_5POINT0: 87cabdff1aSopenharmony_ci ch_layout = 8; 88cabdff1aSopenharmony_ci break; 89cabdff1aSopenharmony_ci case AV_CH_LAYOUT_5POINT1: 90cabdff1aSopenharmony_ci ch_layout = 9; 91cabdff1aSopenharmony_ci break; 92cabdff1aSopenharmony_ci case AV_CH_LAYOUT_7POINT0: 93cabdff1aSopenharmony_ci ch_layout = 10; 94cabdff1aSopenharmony_ci break; 95cabdff1aSopenharmony_ci case AV_CH_LAYOUT_7POINT1: 96cabdff1aSopenharmony_ci ch_layout = 11; 97cabdff1aSopenharmony_ci break; 98cabdff1aSopenharmony_ci default: 99cabdff1aSopenharmony_ci return AVERROR_BUG; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci s->header = (((ch_layout << 4) | freq) << 8) | (quant << 6); 103cabdff1aSopenharmony_ci avctx->frame_size = frame_size; 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci return 0; 106cabdff1aSopenharmony_ci} 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_cistatic int pcm_bluray_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, 109cabdff1aSopenharmony_ci const AVFrame *frame, int *got_packet_ptr) 110cabdff1aSopenharmony_ci{ 111cabdff1aSopenharmony_ci BlurayPCMEncContext *s = avctx->priv_data; 112cabdff1aSopenharmony_ci int sample_size, samples, channel, num_dest_channels; 113cabdff1aSopenharmony_ci const int16_t *src16; 114cabdff1aSopenharmony_ci const int32_t *src32; 115cabdff1aSopenharmony_ci unsigned pkt_size; 116cabdff1aSopenharmony_ci PutByteContext pb; 117cabdff1aSopenharmony_ci int ret; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci num_dest_channels = FFALIGN(avctx->ch_layout.nb_channels, 2); 120cabdff1aSopenharmony_ci sample_size = (num_dest_channels * 121cabdff1aSopenharmony_ci (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3; 122cabdff1aSopenharmony_ci samples = frame->nb_samples; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci pkt_size = sample_size * samples + 4; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci if ((ret = ff_get_encode_buffer(avctx, avpkt, pkt_size, 0)) < 0) 127cabdff1aSopenharmony_ci return ret; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci AV_WB16(avpkt->data, pkt_size - 4); 130cabdff1aSopenharmony_ci AV_WB16(avpkt->data + 2, s->header); 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci src16 = (const int16_t *)frame->data[0]; 133cabdff1aSopenharmony_ci src32 = (const int32_t *)frame->data[0]; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, avpkt->data + 4, avpkt->size - 4); 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci switch (avctx->ch_layout.u.mask) { 138cabdff1aSopenharmony_ci /* cases with same number of source and coded channels */ 139cabdff1aSopenharmony_ci case AV_CH_LAYOUT_STEREO: 140cabdff1aSopenharmony_ci case AV_CH_LAYOUT_4POINT0: 141cabdff1aSopenharmony_ci case AV_CH_LAYOUT_2_2: 142cabdff1aSopenharmony_ci samples *= num_dest_channels; 143cabdff1aSopenharmony_ci if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { 144cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN 145cabdff1aSopenharmony_ci bytestream2_put_bufferu(&pb, frame->data[0], samples * 2); 146cabdff1aSopenharmony_ci#else 147cabdff1aSopenharmony_ci do { 148cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, *src16++); 149cabdff1aSopenharmony_ci } while (--samples); 150cabdff1aSopenharmony_ci#endif 151cabdff1aSopenharmony_ci } else { 152cabdff1aSopenharmony_ci do { 153cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, (*src32++) >> 8); 154cabdff1aSopenharmony_ci } while (--samples); 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci break; 157cabdff1aSopenharmony_ci /* cases where number of source channels = coded channels + 1 */ 158cabdff1aSopenharmony_ci case AV_CH_LAYOUT_MONO: 159cabdff1aSopenharmony_ci case AV_CH_LAYOUT_SURROUND: 160cabdff1aSopenharmony_ci case AV_CH_LAYOUT_2_1: 161cabdff1aSopenharmony_ci case AV_CH_LAYOUT_5POINT0: 162cabdff1aSopenharmony_ci if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { 163cabdff1aSopenharmony_ci do { 164cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN 165cabdff1aSopenharmony_ci bytestream2_put_bufferu(&pb, (const uint8_t *)src16, avctx->ch_layout.nb_channels * 2); 166cabdff1aSopenharmony_ci src16 += avctx->ch_layout.nb_channels; 167cabdff1aSopenharmony_ci#else 168cabdff1aSopenharmony_ci channel = avctx->ch_layout.nb_channels; 169cabdff1aSopenharmony_ci do { 170cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, *src16++); 171cabdff1aSopenharmony_ci } while (--channel); 172cabdff1aSopenharmony_ci#endif 173cabdff1aSopenharmony_ci bytestream2_put_ne16(&pb, 0); 174cabdff1aSopenharmony_ci } while (--samples); 175cabdff1aSopenharmony_ci } else { 176cabdff1aSopenharmony_ci do { 177cabdff1aSopenharmony_ci channel = avctx->ch_layout.nb_channels; 178cabdff1aSopenharmony_ci do { 179cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, (*src32++) >> 8); 180cabdff1aSopenharmony_ci } while (--channel); 181cabdff1aSopenharmony_ci bytestream2_put_ne24(&pb, 0); 182cabdff1aSopenharmony_ci } while (--samples); 183cabdff1aSopenharmony_ci } 184cabdff1aSopenharmony_ci break; 185cabdff1aSopenharmony_ci /* remapping: L, R, C, LBack, RBack, LF */ 186cabdff1aSopenharmony_ci case AV_CH_LAYOUT_5POINT1: 187cabdff1aSopenharmony_ci if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { 188cabdff1aSopenharmony_ci do { 189cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[0]); 190cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[1]); 191cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[2]); 192cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[4]); 193cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[5]); 194cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[3]); 195cabdff1aSopenharmony_ci src16 += 6; 196cabdff1aSopenharmony_ci } while (--samples); 197cabdff1aSopenharmony_ci } else { 198cabdff1aSopenharmony_ci do { 199cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[0] >> 8); 200cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[1] >> 8); 201cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[2] >> 8); 202cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[4] >> 8); 203cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[5] >> 8); 204cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[3] >> 8); 205cabdff1aSopenharmony_ci src32 += 6; 206cabdff1aSopenharmony_ci } while (--samples); 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci break; 209cabdff1aSopenharmony_ci /* remapping: L, R, C, LSide, LBack, RBack, RSide, <unused> */ 210cabdff1aSopenharmony_ci case AV_CH_LAYOUT_7POINT0: 211cabdff1aSopenharmony_ci if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { 212cabdff1aSopenharmony_ci do { 213cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[0]); 214cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[1]); 215cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[2]); 216cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[5]); 217cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[3]); 218cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[4]); 219cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[6]); 220cabdff1aSopenharmony_ci src16 += 7; 221cabdff1aSopenharmony_ci bytestream2_put_ne16(&pb, 0); 222cabdff1aSopenharmony_ci } while (--samples); 223cabdff1aSopenharmony_ci } else { 224cabdff1aSopenharmony_ci do { 225cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[0] >> 8); 226cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[1] >> 8); 227cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[2] >> 8); 228cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[5] >> 8); 229cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[3] >> 8); 230cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[4] >> 8); 231cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[6] >> 8); 232cabdff1aSopenharmony_ci src32 += 7; 233cabdff1aSopenharmony_ci bytestream2_put_ne24(&pb, 0); 234cabdff1aSopenharmony_ci } while (--samples); 235cabdff1aSopenharmony_ci } 236cabdff1aSopenharmony_ci break; 237cabdff1aSopenharmony_ci /* remapping: L, R, C, LSide, LBack, RBack, RSide, LF */ 238cabdff1aSopenharmony_ci case AV_CH_LAYOUT_7POINT1: 239cabdff1aSopenharmony_ci if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { 240cabdff1aSopenharmony_ci do { 241cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[0]); 242cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[1]); 243cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[2]); 244cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[6]); 245cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[4]); 246cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[5]); 247cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[7]); 248cabdff1aSopenharmony_ci bytestream2_put_be16u(&pb, src16[3]); 249cabdff1aSopenharmony_ci src16 += 8; 250cabdff1aSopenharmony_ci } while (--samples); 251cabdff1aSopenharmony_ci } else { 252cabdff1aSopenharmony_ci do { 253cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[0]); 254cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[1]); 255cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[2]); 256cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[6]); 257cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[4]); 258cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[5]); 259cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[7]); 260cabdff1aSopenharmony_ci bytestream2_put_be24u(&pb, src32[3]); 261cabdff1aSopenharmony_ci src32 += 8; 262cabdff1aSopenharmony_ci } while (--samples); 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci break; 265cabdff1aSopenharmony_ci default: 266cabdff1aSopenharmony_ci return AVERROR_BUG; 267cabdff1aSopenharmony_ci } 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci avpkt->pts = frame->pts; 270cabdff1aSopenharmony_ci avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); 271cabdff1aSopenharmony_ci *got_packet_ptr = 1; 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci return 0; 274cabdff1aSopenharmony_ci} 275cabdff1aSopenharmony_ci 276cabdff1aSopenharmony_ciconst FFCodec ff_pcm_bluray_encoder = { 277cabdff1aSopenharmony_ci .p.name = "pcm_bluray", 278cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), 279cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_AUDIO, 280cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_PCM_BLURAY, 281cabdff1aSopenharmony_ci .priv_data_size = sizeof(BlurayPCMEncContext), 282cabdff1aSopenharmony_ci .init = pcm_bluray_encode_init, 283cabdff1aSopenharmony_ci FF_CODEC_ENCODE_CB(pcm_bluray_encode_frame), 284cabdff1aSopenharmony_ci .p.supported_samplerates = (const int[]) { 48000, 96000, 192000, 0 }, 285cabdff1aSopenharmony_ci#if FF_API_OLD_CHANNEL_LAYOUT 286cabdff1aSopenharmony_ci .p.channel_layouts = (const uint64_t[]) { 287cabdff1aSopenharmony_ci AV_CH_LAYOUT_MONO, 288cabdff1aSopenharmony_ci AV_CH_LAYOUT_STEREO, 289cabdff1aSopenharmony_ci AV_CH_LAYOUT_SURROUND, 290cabdff1aSopenharmony_ci AV_CH_LAYOUT_2_1, 291cabdff1aSopenharmony_ci AV_CH_LAYOUT_4POINT0, 292cabdff1aSopenharmony_ci AV_CH_LAYOUT_2_2, 293cabdff1aSopenharmony_ci AV_CH_LAYOUT_5POINT0, 294cabdff1aSopenharmony_ci AV_CH_LAYOUT_5POINT1, 295cabdff1aSopenharmony_ci AV_CH_LAYOUT_7POINT0, 296cabdff1aSopenharmony_ci AV_CH_LAYOUT_7POINT1, 297cabdff1aSopenharmony_ci 0 }, 298cabdff1aSopenharmony_ci#endif 299cabdff1aSopenharmony_ci .p.ch_layouts = (const AVChannelLayout[]) { 300cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_MONO, 301cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_STEREO, 302cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_SURROUND, 303cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_2_1, 304cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_4POINT0, 305cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_2_2, 306cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_5POINT0, 307cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_5POINT1, 308cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_7POINT0, 309cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_7POINT1, 310cabdff1aSopenharmony_ci { 0 } }, 311cabdff1aSopenharmony_ci .p.sample_fmts = (const enum AVSampleFormat[]) { 312cabdff1aSopenharmony_ci AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, 313cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 314cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 315cabdff1aSopenharmony_ci}; 316