private bool BuildMOOVFrames(bool audio)
{
var track = GetTRAK(audio);
if (track == null)
{
FATAL("no track");
return false;
}
var stsz = (AtomSTSZ) track.GetPath(4, MDIA, MINF, STBL,
STSZ);
if (stsz == null)
{
FATAL("no STSZ");
return false;
}
AtomCO64 co64 = null;
var stco = (AtomSTCO) track.GetPath(4, MDIA, MINF, STBL,
STCO);
if (stco == null)
{
co64 = (AtomCO64)track.GetPath(4, MDIA, MINF, STBL, CO64);
if (co64 == null)
{
FATAL("no CO64");
return false;
}
}
//4. Get the atom containing the distribution of samples per corresponding
//chunks
var pSTSC = (AtomSTSC ) track.GetPath(4, MDIA, MINF, STBL,
STSC);
if (pSTSC == null) {
FATAL("no STSC");
return false;
}
//5. Get the atom containing the delta time of each sample
var pSTTS = (AtomSTTS ) track.GetPath(4, MDIA, MINF, STBL,
STTS);
if (pSTTS == null) {
FATAL("no STTS");
return false;
}
//6. Get the atom containing the time scale of each delta time
var pMDHD = (AtomMdhd ) track.GetPath(2, MDIA, MDHD);
if (pMDHD == null) {
FATAL("no MDHD");
return false;
}
//7. Get the table containing the samples marked as key frames. It can be null
//It can be null
var pSTSS = (AtomSTSS ) track.GetPath(4, MDIA, MINF, STBL,
STSS);
//8. Get the composition timestamps
var pCTSS = (AtomCTTS ) track.GetPath(4, MDIA, MINF, STBL,
CTTS);
var sampleSize = stsz.Entries;
if (audio)
{
_audioSamplesCount = (uint) sampleSize.Length;
}else _videoSamplesCount =(uint) sampleSize.Length;
var sampleDeltaTime = pSTTS.Entries;
var chunckOffsets = stco?.Entries.Cast<ulong>().ToList() ?? co64.Entries;
var sample2Chunk = pSTSC.GetEntries( chunckOffsets.Count);
List<uint> keyFrames = null;
if (pSTSS != null)
{
keyFrames = pSTSS.Entries;
}
List<int> compositionOffsets = null;
if (pCTSS != null)
{
compositionOffsets = pCTSS.GetEntries();
if (sampleSize.Length == compositionOffsets.Count)
{
for (var i = compositionOffsets.Count; i < sampleSize.Length; i++)
{
compositionOffsets.Add(0);
}
}
}
var timeScale = pMDHD.TimeScale;
ulong totalTime = 0;
uint localOffset = 0;
var startIndex = _frames.Count;
for (var i = 0; i < sampleSize.Length; i++)
{
MediaFrame frame;
frame.Start = (uint) (chunckOffsets[sample2Chunk[i]] + localOffset);
if (pSTSS != null)
{
var doubleVal = ((double) compositionOffsets[i]/(double) timeScale)*(double) 1000.00;
frame.CompositionOffset = (int) doubleVal;
}
else
{
frame.CompositionOffset = 0;
}
if (i <= sampleSize.Length - 2)
{
//not the last frame
var currentChunck = sample2Chunk[i];
var nextChunck = sample2Chunk[i + 1];
if (currentChunck == nextChunck) {
//not changing the chunk
localOffset += (uint) sampleSize[i];
} else {
//changing the chunck
localOffset = 0;
}
}
else
{
localOffset += (uint)sampleSize[i];
}
frame.Length = (uint)sampleSize[i];
frame.Type = audio ? MediaFrameType.Audio : MediaFrameType.Video;
frame.IsKeyFrame = pSTSS == null;
frame.DeltaTime= (sampleDeltaTime[i] / (double) timeScale)*1000.00;
frame.AbsoluteTime= (uint) ((totalTime / timeScale)*1000);
frame.IsBinaryHeader = false;
totalTime += sampleDeltaTime[i];
_frames.Add(frame);
}
if (pSTSS != null)
foreach (var keyFrame in keyFrames)
{
var x = _frames[(int) (startIndex + keyFrame - 1)];
x.IsKeyFrame = true;
_frames[(int) (startIndex + keyFrame - 1)] = x;
}
return true;
}