3 * Copyright (c) 2016 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/intreadwrite.h"
23 #include "avio_internal.h"
30 static int bonk_probe(const AVProbeData
*p
)
32 for (int i
= 0; i
< p
->buf_size
- 22; i
++) {
33 if (!p
->buf
[i
] && AV_RL32(p
->buf
+ i
+ 1) == MKTAG('B','O','N','K')) {
36 if (AV_RL32(p
->buf
+ i
+ 6) == 0)
38 if (AV_RL32(p
->buf
+ i
+ 10) == 0)
40 if (p
->buf
[i
+ 14] == 0)
42 if (AV_RL16(p
->buf
+ i
+ 17) == 0 ||
43 AV_RL16(p
->buf
+ i
+ 17) > 2048)
45 if (p
->buf
[i
+ 19] == 0)
47 if (AV_RL16(p
->buf
+ i
+ 20) == 0)
49 return AVPROBE_SCORE_MAX
;
56 static int bonk_read_header(AVFormatContext
*s
)
58 ID3v2ExtraMeta
*extra_meta
;
62 while (!avio_feof(s
->pb
)) {
63 const int b
= avio_r8(s
->pb
);
66 int ret
= ffio_ensure_seekback(s
->pb
, 3);
72 if (t
== MKTAG('B','O','N','K')) {
74 } else if (t
== MKTAG(' ','I','D','3')) {
75 avio_seek(s
->pb
, -3, SEEK_CUR
);
76 ff_id3v2_read(s
, ID3v2_DEFAULT_MAGIC
, &extra_meta
, 0);
78 ff_id3v2_parse_apic(s
, extra_meta
);
79 ff_id3v2_parse_priv(s
, extra_meta
);
80 ff_id3v2_free_extra_meta(&extra_meta
);
84 return AVERROR_INVALIDDATA
;
89 st
= avformat_new_stream(s
, NULL
);
91 return AVERROR(ENOMEM
);
92 if ((ret
= ff_get_extradata(s
, st
->codecpar
, s
->pb
, 17)) < 0)
94 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
95 st
->codecpar
->codec_id
= AV_CODEC_ID_BONK
;
96 st
->codecpar
->sample_rate
= AV_RL32(st
->codecpar
->extradata
+ 5);
97 st
->codecpar
->ch_layout
.nb_channels
= st
->codecpar
->extradata
[9];
98 if (st
->codecpar
->ch_layout
.nb_channels
== 0)
99 return AVERROR_INVALIDDATA
;
100 st
->duration
= AV_RL32(st
->codecpar
->extradata
+ 1) / st
->codecpar
->ch_layout
.nb_channels
;
101 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
106 const FFInputFormat ff_bonk_demuxer
= {
108 .p
.long_name
= NULL_IF_CONFIG_SMALL("raw Bonk"),
109 .p
.extensions
= "bonk",
110 .p
.flags
= AVFMT_NOBINSEARCH
| AVFMT_NOGENSEARCH
| AVFMT_NO_BYTE_SEEK
| AVFMT_NOTIMESTAMPS
,
111 .p
.priv_class
= &ff_raw_demuxer_class
,
112 .read_probe
= bonk_probe
,
113 .read_header
= bonk_read_header
,
114 .read_packet
= ff_raw_read_partial_packet
,
115 .raw_codec_id
= AV_CODEC_ID_BONK
,
116 .priv_data_size
= sizeof(FFRawDemuxerContext
),