using JT1078.FMp4.Interfaces;
using JT1078.FMp4.MessagePack;
using System;
using System.Collections.Generic;
using System.Text;
namespace JT1078.FMp4
{
///
/// trun
///
public class TrackRunBox : FullBox, IFMp4MessagePackFormatter
{
///
/// trun
/// 201 205 1
/// 201 0010 0000 0001
/// 205 0010 0000 0101
/// 1 0000 0000 0001
/// tr_flags 是用来表示下列 sample 相关的标识符是否应用到每个字段中:
/// 0x000001-0000 0000 0001: data-offset-present,只应用 data-offset
/// 0x000004-0000 0000 0100: 只对第一个 sample 应用对应的 flags。剩余 sample flags 就不管了。
/// 0x000100-0001 0000 0000: 这个比较重要,表示每个 sample 都有自己的 duration,否则使用默认的
/// 0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。
/// 0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。
/// 0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值
/// 0x000f01-1111 0000 0001
///
///
///
public TrackRunBox(byte version=0, uint flags= 0x000f01) : base("trun", version, flags)
{
}
///
///
///
public uint SampleCount { get; set; }
///
/// 可选的
/// 用来表示和该moof配套的mdat中实际数据内容距moof开头有多少byte
/// 相当于就是 moof.byteLength + mdat.headerSize(8)
///
public int DataOffset { get; set; }
///
/// 可选的
///
public uint FirstSampleFlags { get; set; }
///
/// 可选的
/// length:SampleCount
///
public List TrackRunInfos { get; set; }
public void ToBuffer(ref FMp4MessagePackWriter writer)
{
Start(ref writer);
WriterFullBoxToBuffer(ref writer);
bool tmpFlag = TrackRunInfos != null && TrackRunInfos.Count > 0;
if (tmpFlag)
{
writer.WriteUInt32((uint)TrackRunInfos.Count);
}
else
{
writer.WriteUInt32(0);
}
if((Flags & FMp4Constants.TRUN_FLAG_DATA_OFFSET_PRESENT) > 0)
{
if (DataOffset > 0)
{
//人工
writer.WriteInt32(DataOffset);
}
else
{
//程序自动计算
writer.CreateTrunOffsetPosition();
writer.Skip(4, out _);
}
}
if ((Flags & FMp4Constants.TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) > 0)
{
writer.WriteUInt32(FirstSampleFlags);
}
if (tmpFlag)
{
foreach(var trun in TrackRunInfos)
{
if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_DURATION_PRESENT) > 0)
{
writer.WriteUInt32(trun.SampleDuration);
}
if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_SIZE_PRESENT) > 0)
{
writer.WriteUInt32(trun.SampleSize);
}
if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_FLAGS_PRESENT) > 0)
{
writer.WriteUInt32(trun.SampleFlags);
}
if ((Flags & FMp4Constants.TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) > 0)
{
if (Version == 0)
{
writer.WriteUInt32((uint)trun.SampleCompositionTimeOffset);
}
else
{
writer.WriteInt32((int)trun.SampleCompositionTimeOffset);
}
}
}
}
End(ref writer);
}
public class TrackRunInfo
{
public uint SampleDuration { get; set; }
public uint SampleSize { get; set; }
public uint SampleFlags { get; set; }
///
/// cts
/// version == 0
/// 0:uint
/// >0:int
///
public long SampleCompositionTimeOffset { get; set; }
}
}
}