protected override bool BuildFrames()
{
//1. Build the map with frame sizes
InitFrameSizes();
//2. Go to the beginning of the file
if (!MediaFile.SeekBegin())
{
Logger.FATAL("Unable to seek in file");
return false;
}
if (!ParseMetadata())
{
Logger.WARN("Invalid metadata");
if (!FindFrameData())
{
Logger.FATAL("Unable to position on frame data");
return false;
}
}
var firstBytes = new byte[4];
double totalDuration = 0;
var frame = new MediaFrame
{
Type = MediaFrameType.Audio,
IsKeyFrame = true,
DeltaTime = 0,
IsBinaryHeader = false
};
while (MediaFile.Position < MediaFile.Length)
{
//3. Read the first 4 bytes
if (!MediaFile.ReadBuffer(firstBytes, 4))
{
Logger.FATAL("Unable to read 4 byte");
return false;
}
if ((firstBytes[0] == 0xff) &&
((firstBytes[1] >> 5) == 7))
{
//4. Possible frame. Read the header
byte version = (byte)((firstBytes[1] >> 3) & 0x03);
byte layer = (byte)((firstBytes[1] >> 1) & 0x03);
byte bitRateIndex = (byte)(firstBytes[2] >> 4);
byte sampleRateIndex = (byte)((firstBytes[2] >> 2) & 0x03);
byte paddingBit = (byte)((firstBytes[2] >> 1) & 0x01);
//5. get the freame length
frame.Start = (uint)(MediaFile.Position - 4);
frame.Length = _frameSizes[version,layer,bitRateIndex,sampleRateIndex,paddingBit];
if (frame.Length == 0)
{
Logger.FATAL("Invalid frame length: {0}:{1}:{2}:{3}:{4}; Cusror: {5}",
version, layer, bitRateIndex, sampleRateIndex,
paddingBit, MediaFile.Position);
return false;
}
//6. Compute the frame duration and save the frame start
var samplesCount = layer == LAYER_1 ? 384 : 1152;
frame.AbsoluteTime = (uint) (totalDuration * 1000);
totalDuration += samplesCount /
(double)(_samplingRates[version, sampleRateIndex]);
//7. Seek to the next frame
if (!MediaFile.SeekTo((long)(frame.Start + frame.Length)))
{
Logger.WARN("Unable to seek to {0}", frame.Start + frame.Length);
break;
}
//8. All good. Save the frame
_frames.Add(frame);
}
else
{
break;
}
}
return true;
}