FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/pcmdec.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 19 42 45.2%
Functions: 1 1 100.0%
Branches: 4 28 14.3%

Line Branch Exec Source
1 /*
2 * RAW PCM demuxers
3 * Copyright (c) 2002 Fabrice Bellard
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 "config_components.h"
23
24 #include "libavutil/avstring.h"
25 #include "libavutil/channel_layout.h"
26 #include "libavutil/mem.h"
27 #include "avformat.h"
28 #include "demux.h"
29 #include "internal.h"
30 #include "pcm.h"
31 #include "libavutil/log.h"
32 #include "libavutil/opt.h"
33 #include "libavutil/avassert.h"
34
35 typedef struct PCMAudioDemuxerContext {
36 AVClass *class;
37 int sample_rate;
38 AVChannelLayout ch_layout;
39 } PCMAudioDemuxerContext;
40
41 70 static int pcm_read_header(AVFormatContext *s)
42 {
43 70 PCMAudioDemuxerContext *s1 = s->priv_data;
44 AVCodecParameters *par;
45 AVStream *st;
46 70 uint8_t *mime_type = NULL;
47 int ret;
48
49 70 st = avformat_new_stream(s, NULL);
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (!st)
51 return AVERROR(ENOMEM);
52 70 par = st->codecpar;
53
54 70 par->codec_type = AVMEDIA_TYPE_AUDIO;
55 70 par->codec_id = ffifmt(s->iformat)->raw_codec_id;
56 70 par->sample_rate = s1->sample_rate;
57 70 ret = av_channel_layout_copy(&par->ch_layout, &s1->ch_layout);
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (ret < 0)
59 return ret;
60
61 70 av_opt_get(s->pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type);
62
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
70 if (mime_type && s->iformat->mime_type) {
63 int rate = 0, channels = 0, little_endian = 0;
64 const char *options;
65 if (av_stristart(mime_type, s->iformat->mime_type, &options)) { /* audio/L16 */
66 while (options = strchr(options, ';')) {
67 options++;
68 if (!rate)
69 sscanf(options, " rate=%d", &rate);
70 if (!channels)
71 sscanf(options, " channels=%d", &channels);
72 if (!little_endian) {
73 char val[sizeof("little-endian")];
74 if (sscanf(options, " endianness=%13s", val) == 1) {
75 little_endian = strcmp(val, "little-endian") == 0;
76 }
77 }
78 }
79 if (rate <= 0) {
80 av_log(s, AV_LOG_ERROR,
81 "Invalid sample_rate found in mime_type \"%s\"\n",
82 mime_type);
83 av_freep(&mime_type);
84 return AVERROR_INVALIDDATA;
85 }
86 par->sample_rate = rate;
87 if (channels > 0) {
88 av_channel_layout_uninit(&par->ch_layout);
89 par->ch_layout.nb_channels = channels;
90 }
91 if (little_endian)
92 par->codec_id = AV_CODEC_ID_PCM_S16LE;
93 }
94 }
95 70 av_freep(&mime_type);
96
97 70 par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
98
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 av_assert0(par->bits_per_coded_sample > 0);
100
101 70 par->block_align = par->bits_per_coded_sample * par->ch_layout.nb_channels / 8;
102
103 70 avpriv_set_pts_info(st, 64, 1, par->sample_rate);
104 70 return 0;
105 }
106
107 static const AVOption pcm_options[] = {
108 { "sample_rate", "", offsetof(PCMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 44100}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
109 { "ch_layout", "", offsetof(PCMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "mono"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
110 { NULL },
111 };
112 static const AVClass pcm_demuxer_class = {
113 .class_name = "pcm demuxer",
114 .item_name = av_default_item_name,
115 .option = pcm_options,
116 .version = LIBAVUTIL_VERSION_INT,
117 };
118
119 #define PCMDEF_0(name_, long_name_, ext, codec, ...)
120 #define PCMDEF_1(name_, long_name_, ext, codec, ...) \
121 const FFInputFormat ff_pcm_ ## name_ ## _demuxer = { \
122 .p.name = #name_, \
123 .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
124 .p.flags = AVFMT_GENERIC_INDEX, \
125 .p.extensions = ext, \
126 .p.priv_class = &pcm_demuxer_class, \
127 .priv_data_size = sizeof(PCMAudioDemuxerContext), \
128 .read_header = pcm_read_header, \
129 .read_packet = ff_pcm_read_packet, \
130 .read_seek = ff_pcm_read_seek, \
131 .raw_codec_id = codec, \
132 __VA_ARGS__ \
133 };
134 #define PCMDEF_2(name, long_name, ext, codec, enabled, ...) \
135 PCMDEF_ ## enabled(name, long_name, ext, codec, __VA_ARGS__)
136 #define PCMDEF_3(name, long_name, ext, codec, config, ...) \
137 PCMDEF_2(name, long_name, ext, codec, config, __VA_ARGS__)
138 #define PCMDEF_EXT(name, long_name, ext, uppercase, ...) \
139 PCMDEF_3(name, long_name, ext, AV_CODEC_ID_PCM_ ## uppercase, \
140 CONFIG_PCM_ ## uppercase ## _DEMUXER, __VA_ARGS__)
141 #define PCMDEF(name, long_name, ext, uppercase) \
142 PCMDEF_EXT(name, long_name, ext, uppercase, )
143
144 PCMDEF(f64be, "PCM 64-bit floating-point big-endian", NULL, F64BE)
145 PCMDEF(f64le, "PCM 64-bit floating-point little-endian", NULL, F64LE)
146 PCMDEF(f32be, "PCM 32-bit floating-point big-endian", NULL, F32BE)
147 PCMDEF(f32le, "PCM 32-bit floating-point little-endian", NULL, F32LE)
148 PCMDEF(s32be, "PCM signed 32-bit big-endian", NULL, S32BE)
149 PCMDEF(s32le, "PCM signed 32-bit little-endian", NULL, S32LE)
150 PCMDEF(s24be, "PCM signed 24-bit big-endian", NULL, S24BE)
151 PCMDEF(s24le, "PCM signed 24-bit little-endian", NULL, S24LE)
152 PCMDEF_EXT(s16be, "PCM signed 16-bit big-endian",
153 AV_NE("sw", NULL), S16BE, .p.mime_type = "audio/L16")
154 PCMDEF(s16le, "PCM signed 16-bit little-endian", AV_NE(NULL, "sw"), S16LE)
155 PCMDEF(s8, "PCM signed 8-bit", "sb", S8)
156 PCMDEF(u32be, "PCM unsigned 32-bit big-endian", NULL, U32BE)
157 PCMDEF(u32le, "PCM unsigned 32-bit little-endian", NULL, U32LE)
158 PCMDEF(u24be, "PCM unsigned 24-bit big-endian", NULL, U24BE)
159 PCMDEF(u24le, "PCM unsigned 24-bit little-endian", NULL, U24LE)
160 PCMDEF(u16be, "PCM unsigned 16-bit big-endian", AV_NE("uw", NULL), U16BE)
161 PCMDEF(u16le, "PCM unsigned 16-bit little-endian", AV_NE(NULL, "uw"), U16LE)
162 PCMDEF(u8, "PCM unsigned 8-bit", "ub", U8)
163 PCMDEF(alaw, "PCM A-law", "al", ALAW)
164 PCMDEF(mulaw, "PCM mu-law", "ul", MULAW)
165 PCMDEF(vidc, "PCM Archimedes VIDC", NULL, VIDC)
166
167 #if CONFIG_SLN_DEMUXER
168 static const AVOption sln_options[] = {
169 { "sample_rate", "", offsetof(PCMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 8000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
170 { "ch_layout", "", offsetof(PCMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "mono"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
171 { NULL },
172 };
173
174 static const AVClass sln_demuxer_class = {
175 .class_name = "sln demuxer",
176 .item_name = av_default_item_name,
177 .option = sln_options,
178 .version = LIBAVUTIL_VERSION_INT,
179 };
180
181 const FFInputFormat ff_sln_demuxer = {
182 .p.name = "sln",
183 .p.long_name = NULL_IF_CONFIG_SMALL("Asterisk raw pcm"),
184 .p.flags = AVFMT_GENERIC_INDEX,
185 .p.extensions = "sln",
186 .p.priv_class = &sln_demuxer_class,
187 .priv_data_size = sizeof(PCMAudioDemuxerContext),
188 .read_header = pcm_read_header,
189 .read_packet = ff_pcm_read_packet,
190 .read_seek = ff_pcm_read_seek,
191 .raw_codec_id = AV_CODEC_ID_PCM_S16LE,
192 };
193 #endif
194