2 * MIDI Sample Dump Standard format demuxer
3 * Copyright (c) 2017 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"
26 typedef struct SDSContext
{
30 void (*read_block
)(const uint8_t *src
, uint32_t *dst
);
33 static int sds_probe(const AVProbeData
*p
)
35 if (AV_RB32(p
->buf
) == 0xF07E0001 && p
->buf
[20] == 0xF7 &&
36 p
->buf
[6] >= 8 && p
->buf
[6] <= 28)
37 return AVPROBE_SCORE_EXTENSION
;
41 static void byte2_read(const uint8_t *src
, uint32_t *dst
)
45 for (i
= 0; i
< 120; i
+= 2) {
46 unsigned sample
= ((unsigned)src
[i
+ 0] << 25) + ((unsigned)src
[i
+ 1] << 18);
52 static void byte3_read(const uint8_t *src
, uint32_t *dst
)
56 for (i
= 0; i
< 120; i
+= 3) {
59 sample
= ((unsigned)src
[i
+ 0] << 25) | ((unsigned)src
[i
+ 1] << 18) | ((unsigned)src
[i
+ 2] << 11);
64 static void byte4_read(const uint8_t *src
, uint32_t *dst
)
68 for (i
= 0; i
< 120; i
+= 4) {
71 sample
= ((unsigned)src
[i
+ 0] << 25) | ((unsigned)src
[i
+ 1] << 18) | ((unsigned)src
[i
+ 2] << 11) | ((unsigned)src
[i
+ 3] << 4);
76 #define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2))
78 static int sds_read_header(AVFormatContext
*ctx
)
80 SDSContext
*s
= ctx
->priv_data
;
81 unsigned sample_period
;
82 AVIOContext
*pb
= ctx
->pb
;
85 st
= avformat_new_stream(ctx
, NULL
);
87 return AVERROR(ENOMEM
);
92 s
->bit_depth
= avio_r8(pb
);
93 if (s
->bit_depth
< 8 || s
->bit_depth
> 28)
94 return AVERROR_INVALIDDATA
;
96 if (s
->bit_depth
< 14) {
97 s
->read_block
= byte2_read
;
99 } else if (s
->bit_depth
< 21) {
100 s
->read_block
= byte3_read
;
103 s
->read_block
= byte4_read
;
106 st
->codecpar
->codec_id
= AV_CODEC_ID_PCM_U32LE
;
108 sample_period
= avio_rl24(pb
);
109 sample_period
= SDS_3BYTE_TO_INT_DECODE(sample_period
);
112 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
113 st
->codecpar
->channels
= 1;
114 st
->codecpar
->sample_rate
= sample_period
? 1000000000 / sample_period
: 16000;
115 st
->duration
= av_rescale((avio_size(pb
) - 21) / 127, s
->size
, 4);
117 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
122 static int sds_read_packet(AVFormatContext
*ctx
, AVPacket
*pkt
)
124 SDSContext
*s
= ctx
->priv_data
;
125 AVIOContext
*pb
= ctx
->pb
;
133 if (avio_rb16(pb
) != 0xF07E)
134 return AVERROR_INVALIDDATA
;
137 ret
= av_new_packet(pkt
, s
->size
);
141 ret
= avio_read(pb
, s
->data
, 120);
143 s
->read_block(s
->data
, (uint32_t *)pkt
->data
);
145 avio_skip(pb
, 1); // checksum
146 if (avio_r8(pb
) != 0xF7)
147 return AVERROR_INVALIDDATA
;
149 pkt
->flags
&= ~AV_PKT_FLAG_CORRUPT
;
150 pkt
->stream_index
= 0;
156 AVInputFormat ff_sds_demuxer
= {
158 .long_name
= NULL_IF_CONFIG_SMALL("MIDI Sample Dump Standard"),
159 .priv_data_size
= sizeof(SDSContext
),
160 .read_probe
= sds_probe
,
161 .read_header
= sds_read_header
,
162 .read_packet
= sds_read_packet
,
164 .flags
= AVFMT_GENERIC_INDEX
,