FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/pcm-blurayenc.c
Date: 2022-05-23 03:24:52
Exec Total Coverage
Lines: 0 170 0.0%
Branches: 0 62 0.0%

Line Branch Exec Source
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
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
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