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