1
1
mirror of https://github.com/wader/fq.git synced 2024-11-23 00:57:15 +03:00

mp3: Error if > 5 unique header configs

Hopefully make it less likely to missprobe
This commit is contained in:
Mattias Wadman 2021-11-19 11:55:45 +01:00
parent 44251ca8bd
commit 527f917698
3 changed files with 54 additions and 6 deletions

View File

@ -165,3 +165,12 @@ type MPEGASCOut struct {
type AACFrameIn struct {
ObjectType int
}
type MP3FrameOut struct {
MPEGVersion int
ProtectionAbsent bool
BitRate int
SampleRate int
ChannelsIndex int
ChannelModeIndex int
}

View File

@ -1,9 +1,10 @@
package mp3
// TODO: vbri
// TODO: mime audio/mpeg
import (
"fmt"
"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/decode"
@ -33,6 +34,17 @@ func init() {
}
func mp3Decode(d *decode.D, in interface{}) interface{} {
// things in a mp3 stream usually have few unique combinations of.
// does not include bitrate on purpose
type headerConfig struct {
MPEGVersion int
ProtectionAbsent bool
SampleRate int
ChannelsIndex int
ChannelModeIndex int
}
uniqueHeaderConfigs := map[headerConfig]struct{}{}
// there are mp3s files in the wild with multiple headers, two id3v2 tags etc
d.FieldArray("headers", func(d *decode.D) {
for d.NotEnd() {
@ -59,16 +71,33 @@ func mp3Decode(d *decode.D, in interface{}) interface{} {
d.SeekRel(syncLen)
}
if dv, _, _ := d.FieldTryFormat("frame", mp3Frame, nil); dv == nil {
dv, v, _ := d.FieldTryFormat("frame", mp3Frame, nil)
if dv == nil {
decodeFailures++
d.SeekRel(8)
continue
}
mfo, ok := v.(format.MP3FrameOut)
if !ok {
panic(fmt.Sprintf("expected MP3FrameOut got %#+v", v))
}
uniqueHeaderConfigs[headerConfig{
MPEGVersion: mfo.MPEGVersion,
ProtectionAbsent: mfo.ProtectionAbsent,
SampleRate: mfo.SampleRate,
ChannelsIndex: mfo.ChannelsIndex,
ChannelModeIndex: mfo.ChannelModeIndex,
}] = struct{}{}
lastValidEnd = d.Pos()
validFrames++
if len(uniqueHeaderConfigs) > 5 {
d.Errorf("too many unique header configurations")
}
}
})
// TODO: better validate
if validFrames == 0 || (validFrames < 2 && decodeFailures > 0) {
d.Errorf("no frames found")
}

View File

@ -147,8 +147,11 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
var crcBytes int64
var mpegVersionNr uint64
var mpegLayerNr uint64
var protectionAbsent bool
var bitRate uint64
var sampleRate uint64
var channelsIndex uint64
var channelModeIndex uint64
var mainDataEnd uint64
var crcValue *decode.Value
@ -239,14 +242,14 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
1: "Padded",
}), d.Bin)
d.FieldU1("private")
channelsIndex := d.FieldU2("channels", d.MapUToStrSym(decode.UToStr{
channelsIndex = d.FieldU2("channels", d.MapUToStrSym(decode.UToStr{
0b00: "Stereo",
0b01: "Joint stereo",
0b10: "Dual",
0b11: "Mono",
}), d.Bin)
isStereo = channelsIndex != 0b11
d.FieldU2("channel_mode", d.MapUToStrSym(decode.UToStr{
channelModeIndex = d.FieldU2("channel_mode", d.MapUToStrSym(decode.UToStr{
0b00: "None",
0b01: "Intensity stereo",
0b10: "MS stereo",
@ -393,5 +396,12 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
}
d.FieldValueRaw("crc_calculated", crcHash.Sum(nil), d.RawHex)
return nil
return format.MP3FrameOut{
MPEGVersion: int(mpegVersionNr),
ProtectionAbsent: protectionAbsent,
BitRate: int(bitRate),
SampleRate: int(sampleRate),
ChannelsIndex: int(channelModeIndex),
ChannelModeIndex: int(channelModeIndex),
}
}