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 
28 typedef struct BlurayPCMEncContext {
29     uint16_t header;      // Header added to every frame
30 } BlurayPCMEncContext;
31 
pcm_bluray_encode_init(AVCodecContext *avctx)32 static 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 
pcm_bluray_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr)108 static 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 
276 const 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