FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/pcm-dvdenc.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 88 91 96.7%
Functions: 2 2 100.0%
Branches: 26 32 81.2%

Line Branch Exec Source
1 /*
2 * LPCM codecs for PCM formats found in Video DVD streams
3 * Copyright (c) 2018 Paul B Mahol
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "libavutil/channel_layout.h"
23 #include "avcodec.h"
24 #include "bytestream.h"
25 #include "codec_internal.h"
26 #include "encode.h"
27
28 typedef struct PCMDVDContext {
29 uint8_t header[3]; // Header added to every frame
30 int block_size; // Size of a block of samples in bytes
31 int samples_per_block; // Number of samples per channel per block
32 int groups_per_block; // Number of 20/24-bit sample groups per block
33 } PCMDVDContext;
34
35 10 static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx)
36 {
37 10 PCMDVDContext *s = avctx->priv_data;
38 int quant, freq, frame_size;
39
40
2/3
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
10 switch (avctx->sample_rate) {
41 8 case 48000:
42 8 freq = 0;
43 8 break;
44 2 case 96000:
45 2 freq = 1;
46 2 break;
47 10 default:
48 av_assert1(0);
49 }
50
51
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
10 switch (avctx->sample_fmt) {
52 6 case AV_SAMPLE_FMT_S16:
53 6 avctx->bits_per_coded_sample = 16;
54 6 quant = 0;
55 6 break;
56 4 case AV_SAMPLE_FMT_S32:
57 4 avctx->bits_per_coded_sample = 24;
58 4 quant = 2;
59 4 break;
60 10 default:
61 av_assert1(0);
62 }
63
64 10 avctx->bits_per_coded_sample = 16 + quant * 4;
65 10 avctx->block_align = avctx->ch_layout.nb_channels * avctx->bits_per_coded_sample / 8;
66 10 avctx->bit_rate = avctx->block_align * 8LL * avctx->sample_rate;
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (avctx->bit_rate > 9800000) {
68 av_log(avctx, AV_LOG_ERROR, "Too big bitrate: reduce sample rate, bitdepth or channels.\n");
69 return AVERROR(EINVAL);
70 }
71
72
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) {
73 6 s->samples_per_block = 1;
74 6 s->block_size = avctx->ch_layout.nb_channels * 2;
75 6 frame_size = 2008 / s->block_size;
76 } else {
77
3/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
4 switch (avctx->ch_layout.nb_channels) {
78 2 case 1:
79 case 2:
80 case 4:
81 /* one group has all the samples needed */
82 2 s->block_size = 4 * avctx->bits_per_coded_sample / 8;
83 2 s->samples_per_block = 4 / avctx->ch_layout.nb_channels;
84 2 s->groups_per_block = 1;
85 2 break;
86 1 case 8:
87 /* two groups have all the samples needed */
88 1 s->block_size = 8 * avctx->bits_per_coded_sample / 8;
89 1 s->samples_per_block = 1;
90 1 s->groups_per_block = 2;
91 1 break;
92 1 default:
93 /* need avctx->ch_layout.nb_channels groups */
94 1 s->block_size = 4 * avctx->ch_layout.nb_channels *
95 1 avctx->bits_per_coded_sample / 8;
96 1 s->samples_per_block = 4;
97 1 s->groups_per_block = avctx->ch_layout.nb_channels;
98 1 break;
99 }
100
101 4 frame_size = FFALIGN(2008 / s->block_size, s->samples_per_block);
102 }
103
104 10 s->header[0] = 0x0c;
105 10 s->header[1] = (quant << 6) | (freq << 4) | (avctx->ch_layout.nb_channels - 1);
106 10 s->header[2] = 0x80;
107
108
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (!avctx->frame_size)
109 10 avctx->frame_size = frame_size;
110
111 10 return 0;
112 }
113
114 15338 static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
115 const AVFrame *frame, int *got_packet_ptr)
116 {
117 15338 PCMDVDContext *s = avctx->priv_data;
118 15338 int samples = frame->nb_samples * avctx->ch_layout.nb_channels;
119 15338 int64_t pkt_size = (int64_t)(frame->nb_samples / s->samples_per_block) * s->block_size + 3;
120 15338 int blocks = (pkt_size - 3) / s->block_size;
121 const int16_t *src16;
122 const int32_t *src32;
123 PutByteContext pb;
124 int ret;
125
126
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15338 times.
15338 if ((ret = ff_get_encode_buffer(avctx, avpkt, pkt_size, 0)) < 0)
127 return ret;
128
129 15338 memcpy(avpkt->data, s->header, 3);
130
131 15338 src16 = (const int16_t *)frame->data[0];
132 15338 src32 = (const int32_t *)frame->data[0];
133
134 15338 bytestream2_init_writer(&pb, avpkt->data + 3, avpkt->size - 3);
135
136
2/3
✓ Branch 0 taken 2198 times.
✓ Branch 1 taken 13140 times.
✗ Branch 2 not taken.
15338 switch (avctx->sample_fmt) {
137 2202820 case AV_SAMPLE_FMT_S16:
138 do {
139 2202820 bytestream2_put_be16(&pb, *src16++);
140
2/2
✓ Branch 0 taken 2200622 times.
✓ Branch 1 taken 2198 times.
2202820 } while (--samples);
141 2198 break;
142 13140 case AV_SAMPLE_FMT_S32:
143
2/2
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 12934 times.
13140 if (avctx->ch_layout.nb_channels == 1) {
144 do {
145
2/2
✓ Branch 0 taken 17280 times.
✓ Branch 1 taken 8640 times.
25920 for (int i = 2; i; i--) {
146 17280 bytestream2_put_be16(&pb, src32[0] >> 16);
147 17280 bytestream2_put_be16(&pb, src32[1] >> 16);
148 17280 bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8));
149 17280 bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8));
150 }
151
2/2
✓ Branch 0 taken 8434 times.
✓ Branch 1 taken 206 times.
8640 } while (--blocks);
152 } else {
153 do {
154
2/2
✓ Branch 0 taken 886839 times.
✓ Branch 1 taken 711219 times.
1598058 for (int i = s->groups_per_block; i; i--) {
155 886839 bytestream2_put_be16(&pb, src32[0] >> 16);
156 886839 bytestream2_put_be16(&pb, src32[1] >> 16);
157 886839 bytestream2_put_be16(&pb, src32[2] >> 16);
158 886839 bytestream2_put_be16(&pb, src32[3] >> 16);
159 886839 bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8));
160 886839 bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8));
161 886839 bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8));
162 886839 bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8));
163 }
164
2/2
✓ Branch 0 taken 698285 times.
✓ Branch 1 taken 12934 times.
711219 } while (--blocks);
165 }
166 13140 break;
167 }
168
169 15338 *got_packet_ptr = 1;
170
171 15338 return 0;
172 }
173
174 const FFCodec ff_pcm_dvd_encoder = {
175 .p.name = "pcm_dvd",
176 CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for DVD media"),
177 .p.type = AVMEDIA_TYPE_AUDIO,
178 .p.id = AV_CODEC_ID_PCM_DVD,
179 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
180 AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
181 .priv_data_size = sizeof(PCMDVDContext),
182 .init = pcm_dvd_encode_init,
183 FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame),
184 .p.supported_samplerates = (const int[]) { 48000, 96000, 0},
185 .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO,
186 AV_CHANNEL_LAYOUT_STEREO,
187 AV_CHANNEL_LAYOUT_5POINT1,
188 AV_CHANNEL_LAYOUT_7POINT1,
189 { 0 } },
190 .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
191 AV_SAMPLE_FMT_S32,
192 AV_SAMPLE_FMT_NONE },
193 };
194