3 * Copyright (c) 2012 Paul B Mahol
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/avstring.h"
23 #include "libavutil/intreadwrite.h"
29 static int nist_probe(const AVProbeData
*p
)
31 if (AV_RL64(p
->buf
) == AV_RL64("NIST_1A\x0a"))
32 return AVPROBE_SCORE_MAX
;
36 static int nist_read_header(AVFormatContext
*s
)
38 char buffer
[256]= {0}, coding
[32] = "pcm", format
[32] = "01";
40 int32_t header_size
= -1;
43 st
= avformat_new_stream(s
, NULL
);
45 return AVERROR(ENOMEM
);
47 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
49 ff_get_line(s
->pb
, buffer
, sizeof(buffer
));
50 ff_get_line(s
->pb
, buffer
, sizeof(buffer
));
51 sscanf(buffer
, "%"SCNd32
, &header_size
);
53 return AVERROR_INVALIDDATA
;
55 while (!avio_feof(s
->pb
)) {
56 ff_get_line(s
->pb
, buffer
, sizeof(buffer
));
58 if (avio_tell(s
->pb
) >= header_size
)
59 return AVERROR_INVALIDDATA
;
61 if (!memcmp(buffer
, "end_head", 8)) {
62 if (!st
->codecpar
->bits_per_coded_sample
)
63 st
->codecpar
->bits_per_coded_sample
= bps
<< 3;
65 if (!av_strcasecmp(coding
, "pcm")) {
66 if (st
->codecpar
->codec_id
== AV_CODEC_ID_NONE
)
67 st
->codecpar
->codec_id
= ff_get_pcm_codec_id(st
->codecpar
->bits_per_coded_sample
,
69 } else if (!av_strcasecmp(coding
, "alaw")) {
70 st
->codecpar
->codec_id
= AV_CODEC_ID_PCM_ALAW
;
71 } else if (!av_strcasecmp(coding
, "ulaw") ||
72 !av_strcasecmp(coding
, "mu-law")) {
73 st
->codecpar
->codec_id
= AV_CODEC_ID_PCM_MULAW
;
74 } else if (!av_strncasecmp(coding
, "pcm,embedded-shorten", 20)) {
75 st
->codecpar
->codec_id
= AV_CODEC_ID_SHORTEN
;
76 if (ff_alloc_extradata(st
->codecpar
, 1))
77 st
->codecpar
->extradata
[0] = 1;
79 avpriv_request_sample(s
, "coding %s", coding
);
82 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
84 st
->codecpar
->block_align
= st
->codecpar
->bits_per_coded_sample
*
85 st
->codecpar
->ch_layout
.nb_channels
/ 8;
87 if (avio_tell(s
->pb
) > header_size
)
88 return AVERROR_INVALIDDATA
;
90 avio_skip(s
->pb
, header_size
- avio_tell(s
->pb
));
93 } else if (!memcmp(buffer
, "channel_count", 13)) {
94 sscanf(buffer
, "%*s %*s %u", &st
->codecpar
->ch_layout
.nb_channels
);
95 if (st
->codecpar
->ch_layout
.nb_channels
<= 0 || st
->codecpar
->ch_layout
.nb_channels
> INT16_MAX
)
96 return AVERROR_INVALIDDATA
;
97 } else if (!memcmp(buffer
, "sample_byte_format", 18)) {
98 sscanf(buffer
, "%*s %*s %31s", format
);
100 if (!av_strcasecmp(format
, "01")) {
102 } else if (!av_strcasecmp(format
, "10")) {
104 } else if (!av_strcasecmp(format
, "mu-law")) {
105 st
->codecpar
->codec_id
= AV_CODEC_ID_PCM_MULAW
;
106 } else if (av_strcasecmp(format
, "1")) {
107 avpriv_request_sample(s
, "sample byte format %s", format
);
108 return AVERROR_PATCHWELCOME
;
110 } else if (!memcmp(buffer
, "sample_coding", 13)) {
111 sscanf(buffer
, "%*s %*s %31s", coding
);
112 } else if (!memcmp(buffer
, "sample_count", 12)) {
113 sscanf(buffer
, "%*s %*s %"SCNd64
, &st
->duration
);
114 } else if (!memcmp(buffer
, "sample_n_bytes", 14)) {
115 sscanf(buffer
, "%*s %*s %d", &bps
);
116 if (bps
> INT16_MAX
/8U)
117 return AVERROR_INVALIDDATA
;
118 } else if (!memcmp(buffer
, "sample_rate", 11)) {
119 sscanf(buffer
, "%*s %*s %d", &st
->codecpar
->sample_rate
);
120 } else if (!memcmp(buffer
, "sample_sig_bits", 15)) {
121 sscanf(buffer
, "%*s %*s %d", &st
->codecpar
->bits_per_coded_sample
);
122 if (st
->codecpar
->bits_per_coded_sample
<= 0 || st
->codecpar
->bits_per_coded_sample
> INT16_MAX
)
123 return AVERROR_INVALIDDATA
;
125 char key
[32], value
[32];
126 if (sscanf(buffer
, "%31s %*s %31s", key
, value
) == 2) {
127 av_dict_set(&s
->metadata
, key
, value
, AV_DICT_APPEND
);
129 av_log(s
, AV_LOG_ERROR
, "Failed to parse '%s' as metadata\n", buffer
);
137 const FFInputFormat ff_nistsphere_demuxer
= {
138 .p
.name
= "nistsphere",
139 .p
.long_name
= NULL_IF_CONFIG_SMALL("NIST SPeech HEader REsources"),
140 .p
.extensions
= "nist,sph",
141 .p
.flags
= AVFMT_GENERIC_INDEX
,
142 .read_probe
= nist_probe
,
143 .read_header
= nist_read_header
,
144 .read_packet
= ff_pcm_read_packet
,
145 .read_seek
= ff_pcm_read_seek
,