Skip to content

Commit

Permalink
mp3: Error if > 5 unique header configs
Browse files Browse the repository at this point in the history
Hopefully make it less likely to missprobe
  • Loading branch information
wader committed Nov 19, 2021
1 parent 44251ca commit 527f917
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 6 deletions.
9 changes: 9 additions & 0 deletions format/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
35 changes: 32 additions & 3 deletions format/mp3/mp3.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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() {
Expand All @@ -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")
}
Expand Down
16 changes: 13 additions & 3 deletions format/mpeg/mp3_frame.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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),
}
}

0 comments on commit 527f917

Please sign in to comment.