Detect VideoNow Color offset.

This commit is contained in:
2019-12-26 01:24:57 +00:00
parent 0a5d194a00
commit 271cee4d93
2 changed files with 236 additions and 168 deletions

View File

@@ -857,7 +857,7 @@ namespace DiscImageChef.Core.Devices.Dumping
false, false, true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
MmcSubchannel.None, _dev.Timeout, out _);
if(sense || !_dev.Error)
if(sense || _dev.Error)
{
videoNowColorFrame = null;
@@ -1323,153 +1323,188 @@ namespace DiscImageChef.Core.Devices.Dumping
// Check offset
if(_fixOffset)
{
// TODO: VideoNow
if(tracks.All(t => t.TrackType != TrackType.Audio))
if(dskType != MediaType.VideoNowColor)
{
// No audio tracks so no need to fix offset
_dumpLog.WriteLine("No audio tracks, disabling offset fix.");
UpdateStatus?.Invoke("No audio tracks, disabling offset fix.");
_fixOffset = false;
}
else if(!readcd)
{
_dumpLog.WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
UpdateStatus?.
Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
_fixOffset = false;
}
else
{
bool offsetFound = false;
if(tracks.Any(t => t.TrackType != TrackType.Audio))
if(tracks.All(t => t.TrackType != TrackType.Audio))
{
Track dataTrack = tracks.FirstOrDefault(t => t.TrackType != TrackType.Audio);
// No audio tracks so no need to fix offset
_dumpLog.WriteLine("No audio tracks, disabling offset fix.");
UpdateStatus?.Invoke("No audio tracks, disabling offset fix.");
if(dataTrack.TrackSequence != 0)
{
dataTrack.TrackEndSector += 149;
// Calculate MSF
ulong minute = dataTrack.TrackEndSector / 4500;
ulong second = (dataTrack.TrackEndSector - (minute * 4500)) / 75;
ulong frame = dataTrack.TrackEndSector - (minute * 4500) - (second * 75);
dataTrack.TrackEndSector -= 149;
// Convert to BCD
ulong remainder = minute % 10;
minute = ((minute / 10) * 16) + remainder;
remainder = second % 10;
second = ((second / 10) * 16) + remainder;
remainder = frame % 10;
frame = ((frame / 10) * 16) + remainder;
// Build sync
byte[] sectorSync =
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute,
(byte)second, (byte)frame
};
tmpBuf = new byte[sectorSync.Length];
// Plextor READ CDDA
if(dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
dbDev?.SCSI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
_dev.Manufacturer.ToLowerInvariant() == "plextor")
{
sense = _dev.PlextorReadCdDa(out cmdBuf, out senseBuf,
(uint)dataTrack.TrackEndSector - 2, sectorSize, 3,
PlextorSubchannel.None, _dev.Timeout, out _);
if(!sense &&
!_dev.Error)
{
for(int i = 0; i < cmdBuf.Length - sectorSync.Length; i++)
{
Array.Copy(cmdBuf, i, tmpBuf, 0, sectorSync.Length);
if(!tmpBuf.SequenceEqual(sectorSync))
continue;
offsetBytes = i - 2352;
offsetFound = true;
break;
}
}
}
if(_debug ||
dbDev?.ATAPI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
dbDev?.SCSI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
_dev.Manufacturer.ToLowerInvariant() == "hl-dt-st")
{
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)(dataTrack.TrackEndSector - 2),
sectorSize, 3, MmcSectorTypes.Cdda, false, false, false,
MmcHeaderCodes.None, true, false, MmcErrorField.None,
MmcSubchannel.None, _dev.Timeout, out _);
if(!sense &&
!_dev.Error)
{
for(int i = 0; i < cmdBuf.Length - sectorSync.Length; i++)
{
Array.Copy(cmdBuf, i, tmpBuf, 0, sectorSync.Length);
if(!tmpBuf.SequenceEqual(sectorSync))
continue;
offsetBytes = i - 2352;
offsetFound = true;
break;
}
}
}
}
_fixOffset = false;
}
if(cdOffset is null)
else if(!readcd)
{
if(offsetFound)
{
_dumpLog.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes");
UpdateStatus?.Invoke($"Combined disc and drive offsets are {offsetBytes} bytes");
}
else
{
_dumpLog.
WriteLine("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
_dumpLog.
WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
UpdateStatus?.
Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
UpdateStatus?.
Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
_fixOffset = false;
}
_fixOffset = false;
}
else
{
if(offsetFound)
bool offsetFound = false;
if(tracks.Any(t => t.TrackType != TrackType.Audio))
{
_dumpLog.WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
UpdateStatus?.Invoke($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
Track dataTrack = tracks.FirstOrDefault(t => t.TrackType != TrackType.Audio);
if(dataTrack.TrackSequence != 0)
{
dataTrack.TrackEndSector += 149;
// Calculate MSF
ulong minute = dataTrack.TrackEndSector / 4500;
ulong second = (dataTrack.TrackEndSector - (minute * 4500)) / 75;
ulong frame = dataTrack.TrackEndSector - (minute * 4500) - (second * 75);
dataTrack.TrackEndSector -= 149;
// Convert to BCD
ulong remainder = minute % 10;
minute = ((minute / 10) * 16) + remainder;
remainder = second % 10;
second = ((second / 10) * 16) + remainder;
remainder = frame % 10;
frame = ((frame / 10) * 16) + remainder;
// Build sync
byte[] sectorSync =
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
(byte)minute, (byte)second, (byte)frame
};
tmpBuf = new byte[sectorSync.Length];
// Plextor READ CDDA
if(dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
dbDev?.SCSI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
_dev.Manufacturer.ToLowerInvariant() ==
"plextor")
{
sense = _dev.PlextorReadCdDa(out cmdBuf, out senseBuf,
(uint)dataTrack.TrackEndSector - 2, sectorSize, 3,
PlextorSubchannel.None, _dev.Timeout, out _);
if(!sense &&
!_dev.Error)
{
for(int i = 0; i < cmdBuf.Length - sectorSync.Length; i++)
{
Array.Copy(cmdBuf, i, tmpBuf, 0, sectorSync.Length);
if(!tmpBuf.SequenceEqual(sectorSync))
continue;
offsetBytes = i - 2352;
offsetFound = true;
break;
}
}
}
if(_debug ||
dbDev?.ATAPI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
dbDev?.SCSI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
_dev.Manufacturer.ToLowerInvariant() == "hl-dt-st")
{
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)(dataTrack.TrackEndSector - 2),
sectorSize, 3, MmcSectorTypes.Cdda, false, false, false,
MmcHeaderCodes.None, true, false, MmcErrorField.None,
MmcSubchannel.None, _dev.Timeout, out _);
if(!sense &&
!_dev.Error)
{
for(int i = 0; i < cmdBuf.Length - sectorSync.Length; i++)
{
Array.Copy(cmdBuf, i, tmpBuf, 0, sectorSync.Length);
if(!tmpBuf.SequenceEqual(sectorSync))
continue;
offsetBytes = i - 2352;
offsetFound = true;
break;
}
}
}
}
}
if(cdOffset is null)
{
if(offsetFound)
{
_dumpLog.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes");
UpdateStatus?.Invoke($"Combined disc and drive offsets are {offsetBytes} bytes");
}
else
{
_dumpLog.
WriteLine("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
UpdateStatus?.
Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
_fixOffset = false;
}
}
else
{
_dumpLog.WriteLine("Disc write offset is unknown, dump may not be correct.");
UpdateStatus?.Invoke("Disc write offset is unknown, dump may not be correct.");
if(offsetFound)
{
_dumpLog.WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
UpdateStatus?.Invoke($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
}
else
{
_dumpLog.WriteLine("Disc write offset is unknown, dump may not be correct.");
UpdateStatus?.Invoke("Disc write offset is unknown, dump may not be correct.");
offsetBytes = cdOffset.Offset * 2 * -1;
offsetBytes = cdOffset.Offset * 2 * -1;
}
_dumpLog.WriteLine($"Offset is {offsetBytes} bytes.");
UpdateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
}
}
}
else
{
byte[] videoNowColorFrame = new byte[9 * sectorSize];
_dumpLog.WriteLine($"Offset is {offsetBytes} bytes.");
UpdateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize, 9, MmcSectorTypes.AllTypes, false,
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
MmcSubchannel.None, _dev.Timeout, out _);
if(sense || _dev.Error)
{
sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize, 9, MmcSectorTypes.Cdda, false,
false, true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
MmcSubchannel.None, _dev.Timeout, out _);
if(sense || _dev.Error)
{
videoNowColorFrame = null;
}
}
if(videoNowColorFrame is null)
{
_dumpLog.WriteLine("Could not find VideoNow Color frame offset, dump may not be correct.");
UpdateStatus?.Invoke("Could not find VideoNow Color frame offset, dump may not be correct.");
}
else
{
offsetBytes = MMC.GetVideoNowColorOffset(videoNowColorFrame);
_dumpLog.WriteLine($"VideoNow Color frame is offset {offsetBytes} bytes.");
UpdateStatus?.Invoke($"VideoNow Color frame is offset {offsetBytes} bytes.");
}
}

View File

@@ -37,79 +37,112 @@ namespace DiscImageChef.Core.Media.Detection
{
public static class MMC
{
/// <summary>
/// This is some kind of header. Every 10 bytes there's an audio byte.
/// </summary>
/// <summary>This is some kind of header. Every 10 bytes there's an audio byte.</summary>
static readonly byte[] VideoNowColorFrameMarker =
{
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81,
0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81,
0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7,
0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3,
0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7,
0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3,
0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00,
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81,
0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81,
0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xC7, 0x00, 0x00, 0x00, 0x02, 0x01, 0x04, 0x02, 0x06, 0x03, 0xFF, 0x00, 0x08, 0x04, 0x0A, 0x05, 0x0C,
0x06, 0x0E, 0x07, 0xFF, 0x00, 0x11, 0x08, 0x13, 0x09, 0x15, 0x0A, 0x17, 0x0B, 0xFF, 0x00, 0x19, 0x0C,
0x1B, 0x0D, 0x1D, 0x0E, 0x1F, 0x0F, 0xFF, 0x00, 0x00, 0x28, 0x02, 0x29, 0x04, 0x2A, 0x06, 0x2B, 0xFF,
0x00, 0x08, 0x2C, 0x0A, 0x2D, 0x0C, 0x2E, 0x0E, 0x2F, 0xFF, 0x00, 0x11, 0x30, 0x13, 0x31, 0x15, 0x32,
0x17, 0x33, 0xFF, 0x00, 0x19, 0x34, 0x1B, 0x35, 0x1D, 0x36, 0x1F, 0x37, 0xFF, 0x00, 0x00, 0x38, 0x02,
0x39, 0x04, 0x3A, 0x06, 0x3B, 0xFF, 0x00, 0x08, 0x3C, 0x0A, 0x3D, 0x0C, 0x3E, 0x0E, 0x3F, 0xFF, 0x00,
0x11, 0x40, 0x13, 0x41, 0x15, 0x42, 0x17, 0x43, 0xFF, 0x00, 0x19, 0x44, 0x1B, 0x45, 0x1D, 0x46, 0x1F,
0x47, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3,
0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00,
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3,
0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00,
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x00, 0x00, 0x02, 0x01, 0x04, 0x02, 0x06, 0x03, 0xFF, 0x00, 0x08, 0x04,
0x0A, 0x05, 0x0C, 0x06, 0x0E, 0x07, 0xFF, 0x00, 0x11, 0x08, 0x13, 0x09, 0x15, 0x0A, 0x17, 0x0B, 0xFF, 0x00,
0x19, 0x0C, 0x1B, 0x0D, 0x1D, 0x0E, 0x1F, 0x0F, 0xFF, 0x00, 0x00, 0x28, 0x02, 0x29, 0x04, 0x2A, 0x06, 0x2B,
0xFF, 0x00, 0x08, 0x2C, 0x0A, 0x2D, 0x0C, 0x2E, 0x0E, 0x2F, 0xFF, 0x00, 0x11, 0x30, 0x13, 0x31, 0x15, 0x32,
0x17, 0x33, 0xFF, 0x00, 0x19, 0x34, 0x1B, 0x35, 0x1D, 0x36, 0x1F, 0x37, 0xFF, 0x00, 0x00, 0x38, 0x02, 0x39,
0x04, 0x3A, 0x06, 0x3B, 0xFF, 0x00, 0x08, 0x3C, 0x0A, 0x3D, 0x0C, 0x3E, 0x0E, 0x3F, 0xFF, 0x00, 0x11, 0x40,
0x13, 0x41, 0x15, 0x42, 0x17, 0x43, 0xFF, 0x00, 0x19, 0x44, 0x1B, 0x45, 0x1D, 0x46, 0x1F, 0x47, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00
};
/// <summary>
/// Checks if the media corresponds to CD-i.
/// </summary>
/// <summary>Checks if the media corresponds to CD-i.</summary>
/// <param name="sector0">Contents of LBA 0, with all headers.</param>
/// <param name="sector16">Contents of LBA 0, with all headers.</param>
/// <returns><c>true</c> if it corresponds to a CD-i, <c>false</c>otherwise.</returns>
public static bool IsCdi(byte[] sector0, byte[] sector16)
{
if(sector0?.Length != 2352 || sector16?.Length != 2352) return false;
if(sector0?.Length != 2352 ||
sector16?.Length != 2352)
return false;
byte[] syncMark =
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
};
byte[] cdiMark =
{
0x01, 0x43, 0x44, 0x2D
};
byte[] syncMark = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
byte[] cdiMark = {0x01, 0x43, 0x44, 0x2D};
byte[] testMark = new byte[12];
Array.Copy(sector0, 0, testMark, 0, 12);
bool hiddenData = syncMark.SequenceEqual(testMark) &&
(sector0[0xF] == 0 || sector0[0xF] == 1 || sector0[0xF] == 2);
if(!hiddenData || sector0[0xF] != 2) return false;
if(!hiddenData ||
sector0[0xF] != 2)
return false;
testMark = new byte[4];
Array.Copy(sector16, 24, testMark, 0, 4);
return cdiMark.SequenceEqual(testMark);
}
public static bool IsVideoNowColor(byte[] videoFrame)
{
if(videoFrame is null || videoFrame.Length < VideoNowColorFrameMarker.Length) return false;
if(videoFrame is null ||
videoFrame.Length < VideoNowColorFrameMarker.Length)
return false;
byte[] buffer = new byte[VideoNowColorFrameMarker.Length];
for(int framePosition = 0; framePosition + buffer.Length < videoFrame.Length; framePosition++)
{
Array.Copy(videoFrame, framePosition, buffer, 0, buffer.Length);
for(int ab = 9; ab < buffer.Length; ab += 10) buffer[ab] = 0;
for(int ab = 9; ab < buffer.Length; ab += 10)
buffer[ab] = 0;
if(!VideoNowColorFrameMarker.SequenceEqual(buffer)) continue;
if(!VideoNowColorFrameMarker.SequenceEqual(buffer))
continue;
return true;
}
return false;
}
public static int GetVideoNowColorOffset(byte[] data)
{
byte[] buffer = new byte[VideoNowColorFrameMarker.Length];
for(int framePosition = 0; framePosition + buffer.Length < data.Length; framePosition++)
{
Array.Copy(data, framePosition, buffer, 0, buffer.Length);
for(int ab = 9; ab < buffer.Length; ab += 10)
buffer[ab] = 0;
if(!VideoNowColorFrameMarker.SequenceEqual(buffer))
continue;
return 18032 - framePosition;
}
return 0;
}
}
}