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"
28 static int nist_probe(AVProbeData
*p
)
30 if (AV_RL64(p
->buf
) == AV_RL64("NIST_1A\x0a"))
31 return AVPROBE_SCORE_MAX
;
35 static int nist_read_header(AVFormatContext
*s
)
37 char buffer
[32], coding
[32] = "pcm", format
[32] = "01";
39 int32_t header_size
= -1;
42 st
= avformat_new_stream(s
, NULL
);
44 return AVERROR(ENOMEM
);
46 st
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
48 ff_get_line(s
->pb
, buffer
, sizeof(buffer
));
49 ff_get_line(s
->pb
, buffer
, sizeof(buffer
));
50 sscanf(buffer
, "%"SCNd32
, &header_size
);
52 return AVERROR_INVALIDDATA
;
54 while (!avio_feof(s
->pb
)) {
55 ff_get_line(s
->pb
, buffer
, sizeof(buffer
));
57 if (avio_tell(s
->pb
) >= header_size
)
58 return AVERROR_INVALIDDATA
;
60 if (!memcmp(buffer
, "end_head", 8)) {
61 if (!st
->codec
->bits_per_coded_sample
)
62 st
->codec
->bits_per_coded_sample
= bps
<< 3;
64 if (!av_strcasecmp(coding
, "pcm")) {
65 st
->codec
->codec_id
= ff_get_pcm_codec_id(st
->codec
->bits_per_coded_sample
,
67 } else if (!av_strcasecmp(coding
, "alaw")) {
68 st
->codec
->codec_id
= AV_CODEC_ID_PCM_ALAW
;
69 } else if (!av_strcasecmp(coding
, "ulaw") ||
70 !av_strcasecmp(coding
, "mu-law")) {
71 st
->codec
->codec_id
= AV_CODEC_ID_PCM_MULAW
;
73 avpriv_request_sample(s
, "coding %s", coding
);
76 avpriv_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
78 st
->codec
->block_align
= st
->codec
->bits_per_coded_sample
* st
->codec
->channels
/ 8;
80 if (avio_tell(s
->pb
) > header_size
)
81 return AVERROR_INVALIDDATA
;
83 avio_skip(s
->pb
, header_size
- avio_tell(s
->pb
));
86 } else if (!memcmp(buffer
, "channel_count", 13)) {
87 sscanf(buffer
, "%*s %*s %"SCNd32
, &st
->codec
->channels
);
88 } else if (!memcmp(buffer
, "sample_byte_format", 18)) {
89 sscanf(buffer
, "%*s %*s %31s", format
);
91 if (!av_strcasecmp(format
, "01")) {
93 } else if (!av_strcasecmp(format
, "10")) {
95 } else if (av_strcasecmp(format
, "1")) {
96 avpriv_request_sample(s
, "sample byte format %s", format
);
97 return AVERROR_PATCHWELCOME
;
99 } else if (!memcmp(buffer
, "sample_coding", 13)) {
100 sscanf(buffer
, "%*s %*s %31s", coding
);
101 } else if (!memcmp(buffer
, "sample_count", 12)) {
102 sscanf(buffer
, "%*s %*s %"SCNd64
, &st
->duration
);
103 } else if (!memcmp(buffer
, "sample_n_bytes", 14)) {
104 sscanf(buffer
, "%*s %*s %"SCNd32
, &bps
);
105 } else if (!memcmp(buffer
, "sample_rate", 11)) {
106 sscanf(buffer
, "%*s %*s %"SCNd32
, &st
->codec
->sample_rate
);
107 } else if (!memcmp(buffer
, "sample_sig_bits", 15)) {
108 sscanf(buffer
, "%*s %*s %"SCNd32
, &st
->codec
->bits_per_coded_sample
);
110 char key
[32], value
[32];
111 if (sscanf(buffer
, "%31s %*s %31s", key
, value
) == 3) {
112 av_dict_set(&s
->metadata
, key
, value
, AV_DICT_APPEND
);
114 av_log(s
, AV_LOG_ERROR
, "Failed to parse '%s' as metadata\n", buffer
);
122 AVInputFormat ff_nistsphere_demuxer
= {
123 .name
= "nistsphere",
124 .long_name
= NULL_IF_CONFIG_SMALL("NIST SPeech HEader REsources"),
125 .read_probe
= nist_probe
,
126 .read_header
= nist_read_header
,
127 .read_packet
= ff_pcm_read_packet
,
128 .read_seek
= ff_pcm_read_seek
,
129 .extensions
= "nist,sph",
130 .flags
= AVFMT_GENERIC_INDEX
,