-
Notifications
You must be signed in to change notification settings - Fork 295
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mp3 config decode and bug fix (#358)
* mp3 config decode and bug fix * revert audio transrater changes * review comments * revert ts fix in audiodecoder worker * return error message
- Loading branch information
Showing
7 changed files
with
243 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#ifndef MP3CONFIG_H | ||
#define MP3CONFIG_H | ||
|
||
#include "config.h" | ||
#include "bitstream/BitReader.h" | ||
#include "bitstream/BitWriter.h" | ||
|
||
class MP3Config | ||
{ | ||
public: | ||
enum class MPEGAudioVersion { | ||
MPEGVersion2, | ||
MPEGVersion1, | ||
MPEGVersionReserved | ||
}; | ||
enum class MPEGAudioLayer { | ||
MPEGLayer3, | ||
MPEGLayerReserved | ||
}; | ||
|
||
static constexpr std::array<DWORD, 3> Mpeg1SamplingRates = {44100, 48000, 32000}; | ||
static constexpr std::array<DWORD, 15> Mpeg1Bitrates = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; | ||
|
||
static constexpr std::array<DWORD, 3> Mpeg2SamplingRates = {22050, 24000, 16000}; | ||
static constexpr std::array<DWORD, 15> Mpeg2Bitrates = {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}; | ||
public: | ||
|
||
MP3Config() = default; | ||
MP3Config(DWORD rate, BYTE channels) | ||
{ | ||
this->samplingRate = rate; | ||
this->channels = channels; | ||
} | ||
|
||
bool Decode(const BYTE* data,const DWORD size) | ||
{ | ||
if (size != 4) | ||
return Error("-MP3Config::Decode() config data must be size of 4 bytes\n"); | ||
|
||
//Create bit reader | ||
BufferReader reader(data,size); | ||
BitReader r(reader); | ||
|
||
try{ | ||
auto frameSync = r.Get(11); | ||
if (frameSync != 0x7FF) | ||
return Error("-MP3Config::Decode() Wrong FrameSync\n"); | ||
|
||
auto ver = r.Get(2); | ||
switch (ver) { | ||
case 2: | ||
audioVersion = MPEGAudioVersion::MPEGVersion2; | ||
break; | ||
case 3: | ||
audioVersion = MPEGAudioVersion::MPEGVersion1; | ||
break; | ||
default: | ||
return Error("-MP3Config::Decode() MPEG audio version not supported\n"); | ||
}; | ||
auto layer = r.Get(2); | ||
if (layer == 1) | ||
{ | ||
audioLayer = MPEGAudioLayer::MPEGLayer3; | ||
frameLength = audioVersion == MPEGAudioVersion::MPEGVersion1 ? 1152 : 576; | ||
} | ||
else | ||
{ | ||
return Error("-MP3Config::Decode() MPEG audio layer not supported\n"); | ||
} | ||
r.Skip(1); | ||
|
||
auto bitrateIdx = r.Get(4); | ||
if (bitrateIdx >= 15) | ||
return Error("-MP3Config::Decode() bitrate idx out of range\n"); | ||
else if (bitrateIdx == 0) | ||
return Error("-MP3Config::Decode() free bitrate idx not supported\n"); | ||
|
||
bitrate = audioVersion == MPEGAudioVersion::MPEGVersion1 ? Mpeg1Bitrates[bitrateIdx] : Mpeg2Bitrates[bitrateIdx]; | ||
|
||
auto samplingRateIdx = r.Get(2); | ||
if (samplingRateIdx >= 3) | ||
return Error("-MP3Config::Decode() invalid sampling rate idx\n"); | ||
|
||
samplingRate = audioVersion == MPEGAudioVersion::MPEGVersion1 ? Mpeg1SamplingRates[samplingRateIdx] : Mpeg2SamplingRates[samplingRateIdx]; | ||
|
||
padding = r.Get(1); | ||
if (padding) | ||
paddingSize = 1; | ||
|
||
r.Skip(1); | ||
auto channelMode = r.Get(2); | ||
if (channelMode == 3) | ||
channels = 1; | ||
else | ||
channels = 2; | ||
} | ||
catch (std::exception& e) | ||
{ | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
void Dump() const | ||
{ | ||
Debug("[MP3Config \n"); | ||
Debug("\t mpegVersion=%u\n" , audioVersion); | ||
Debug("\t mpegLayer=%u\n" , audioLayer); | ||
Debug("\t rate=%u\n" , samplingRate); | ||
Debug("\t channels=%u\n" , channels); | ||
Debug("\t paddingSize=%u\n" , paddingSize); | ||
Debug("\t frameLength=%u\n" , frameLength); | ||
Debug("/]\n"); | ||
} | ||
MPEGAudioVersion GetAudioVersion() const {return audioVersion;} | ||
MPEGAudioLayer GetAudioLayer() const {return audioLayer;} | ||
DWORD GetRate() const { return samplingRate; } | ||
BYTE GetChannels() const { return channels; } | ||
DWORD GetPaddingSize() const { return padding ? paddingSize:0; } | ||
DWORD GetFrameLength() const { return frameLength; } | ||
DWORD GetBitrate() const { return bitrate * 1000; } | ||
|
||
private: | ||
MPEGAudioVersion audioVersion = MPEGAudioVersion::MPEGVersionReserved; | ||
MPEGAudioLayer audioLayer = MPEGAudioLayer::MPEGLayerReserved; | ||
bool padding; | ||
BYTE paddingSize; | ||
DWORD samplingRate = 0; | ||
DWORD bitrate = 0; | ||
BYTE channels = 0; | ||
DWORD frameLength = 0; | ||
}; | ||
#endif /* MPEGCONFIG_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#include "TestCommon.h" | ||
|
||
#include "config.h" | ||
#include "log.h" | ||
#include "mp3/MP3Config.h" | ||
#include <algorithm> | ||
|
||
TEST(TestMP3Config, SupportedMP3Config) | ||
{ | ||
{ | ||
BYTE mp3[4] = { 0xff, 0xfb, 0x74, 0xc4 }; | ||
MP3Config config; | ||
ASSERT_TRUE(config.Decode(mp3, sizeof(mp3))); | ||
/* | ||
[MP3Config | ||
mpegVersion = 1 | ||
mpegLayer = layerIII | ||
rate = 48000 | ||
channels = 1 | ||
paddingSize = 0 | ||
frameLength = 1152 | ||
/ ] | ||
*/ | ||
ASSERT_EQ(config.GetAudioVersion() , MP3Config::MPEGAudioVersion::MPEGVersion1); | ||
ASSERT_EQ(config.GetAudioLayer() , MP3Config::MPEGAudioLayer::MPEGLayer3); | ||
ASSERT_EQ(config.GetRate() , 48000); | ||
ASSERT_EQ(config.GetChannels() , 1); | ||
ASSERT_EQ(config.GetFrameLength() , 1152); | ||
ASSERT_EQ(config.GetBitrate() , 96000); | ||
|
||
} | ||
{ | ||
BYTE mp3[4] = { 0xff, 0xf3, 0x44, 0xc4 }; | ||
MP3Config config; | ||
ASSERT_TRUE(config.Decode(mp3, sizeof(mp3))); | ||
/* | ||
[MP3Config | ||
mpegVersion = 2 | ||
mpegLayer = layerIII | ||
rate = 24000 | ||
channels = 1 | ||
paddingSize = 0 | ||
frameLength = 576 | ||
bitrate = 96000 | ||
/ ] | ||
*/ | ||
ASSERT_EQ(config.GetAudioVersion() , MP3Config::MPEGAudioVersion::MPEGVersion2); | ||
ASSERT_EQ(config.GetAudioLayer() , MP3Config::MPEGAudioLayer::MPEGLayer3); | ||
ASSERT_EQ(config.GetRate() , 24000); | ||
ASSERT_EQ(config.GetChannels() , 1); | ||
ASSERT_EQ(config.GetFrameLength() , 576); | ||
ASSERT_EQ(config.GetBitrate() , 32000); | ||
} | ||
{ | ||
BYTE mp3[4] = { 0xff, 0xfb, 0x70, 0x64 }; | ||
MP3Config config; | ||
ASSERT_TRUE(config.Decode(mp3, sizeof(mp3))); | ||
/* | ||
[MP3Config | ||
mpegVersion = 1 | ||
mpegLayer = layerIII | ||
rate = 44100 | ||
channels = 2 | ||
paddingSize = 0 | ||
frameLength = 1152 | ||
bitrate = 96000 | ||
/ ] | ||
*/ | ||
ASSERT_EQ(config.GetAudioVersion() , MP3Config::MPEGAudioVersion::MPEGVersion1); | ||
ASSERT_EQ(config.GetAudioLayer() , MP3Config::MPEGAudioLayer::MPEGLayer3); | ||
ASSERT_EQ(config.GetRate() , 44100); | ||
ASSERT_EQ(config.GetChannels() , 2); | ||
ASSERT_EQ(config.GetFrameLength() , 1152); | ||
ASSERT_EQ(config.GetBitrate() , 96000); | ||
} | ||
} | ||
|
||
TEST(TestMP3Config, UnsupportedMP3Config) | ||
{ | ||
{ | ||
// mpeg version : mpeg2extension | ||
BYTE mp3[4] = { 0xff, 0xe3, 0x74, 0xc4 }; | ||
MP3Config config; | ||
ASSERT_FALSE(config.Decode(mp3, sizeof(mp3))); | ||
} | ||
{ | ||
// mpeg layer I | ||
BYTE mp3[4] = { 0xff, 0xf7, 0x44, 0xc4 }; | ||
MP3Config config; | ||
ASSERT_FALSE(config.Decode(mp3, sizeof(mp3))); | ||
} | ||
} |