added experimental loader for various format versions of dtv_cmdb_2.bin used by some models from Sharp,Toshiba, Dyon, Philips, OK., ...

This commit is contained in:
Horst Beham
2021-09-03 02:26:57 +02:00
parent 17761a5f81
commit 74e42f70de
12 changed files with 1389 additions and 2 deletions

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B594DDA4-7BD5-450E-B648-668E0F659813}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ChanSort.Loader.CmdbBin</RootNamespace>
<AssemblyName>ChanSort.Loader.CmdbBin</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CmdbPlugin.cs" />
<Compile Include="DvbsDataLayout.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CmdbFileSerializer.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChanSort.Api\ChanSort.Api.csproj">
<Project>{dccffa08-472b-4d17-bb90-8f513fc01392}</Project>
<Name>ChanSort.Api</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="ChanSort.Loader.CmdbBin.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,211 @@
# [dtv_chmdb_x.bin:filesize] defines the overall layout of the file
# Rabinowitsch - dtv_cmd_2.bin with 1296 KB
[dtv_cmdb_2.bin:1326665]
offChannelBitmap=8
lenChannelBitmap=752
offChannelRecord=0x2f8
lenChannelRecord=196
numChannelRecord=6000
offTransponderBitmap=0x11f4b8
lenTransponderBitmap=376
offTransponderRecord=0x11f630
lenTransponderRecord=40
numTransponderRecord=3000
offSatelliteBitmap=0x13fea8
lenSatelliteBitmap=32
offSatelliteRecord=0x13fec8
lenSatelliteRecord=64
numSatelliteRecord=254
[dvbsSatellite:64]
offName=2
lenName=16
[dvbsChannel:196]
offChannelTypeOld=13
offServiceType=15
offTransponderIndex=16
offPmtPid=18
offPcrPid=22
offVideoPid=24
offProgramNr=28
offServiceId=32
offAudioPid=48
offName=140
lenName=50
offDebug=10
lenDebug=5
# Liwest 0005 with 1296 KB
[dtv_cmdb_2.bin:1326669]
offChannelBitmap=12
lenChannelBitmap=752
offChannelRecord=0x2fc
lenChannelRecord=196
numChannelRecord=6000
offTransponderBitmap=0x11f4bc
lenTransponderBitmap=376
offTransponderRecord=0x11f634
lenTransponderRecord=40
numTransponderRecord=3000
offSatelliteBitmap=0x13feac
lenSatelliteBitmap=32
offSatelliteRecord=0x13fecc
lenSatelliteRecord=64
numSatelliteRecord=254
# overice Toshiba - dtv_cmdb_2.bin with 1322 KB
[dtv_cmdb_2.bin:1353209]
offChannelBitmap=12
lenChannelBitmap=752
offChannelRecord=0x2fc
lenChannelRecord=200
numChannelRecord=6000
offTransponderBitmap=0x12527c
lenTransponderBitmap=376
offTransponderRecord=0x1253f4
lenTransponderRecord=40
numTransponderRecord=3000
offSatelliteBitmap=0x145e68
lenSatelliteBitmap=32
offSatelliteRecord=0x145e88
lenSatelliteRecord=72
numSatelliteRecord=254
[dvbsSatellite:72]
offName=2
lenName=16
offOrbitalPos=58
[dvbsTransponder:40]
offSatelliteIndex=0
offTransportStreamId=6
offOriginalNetworkId=8
offNetworkId=10
offTransponderIndex=14
offFreqInMhz=16
offSymbolRate=28
[dvbsChannel:200]
#offChannelType=-1
offServiceType=17
offTransponderIndex=18
offPmtPid=22
offVideoPid=24
offPcrPid=26
offProgramNr=32
offServiceId=34
offAudioPid=52
offName=144
lenName=50
#offProvider=0
#lenProvider=0
# SetEdit Toshiba - dtv_cmdb_2.bin with 1684 KB
[dtv_cmdb_2.bin:1724189]
offChannelBitmap=8
lenChannelBitmap=752
offChannelRecord=0x2f8
lenChannelRecord=256
numChannelRecord=6000
offTransponderBitmap=0x1772f8
lenTransponderBitmap=376
offTransponderRecord=0x177470
lenTransponderRecord=52
numTransponderRecord=3000
offSatelliteBitmap=0x1a0b84
lenSatelliteBitmap=32
offSatelliteRecord=0x1a0ba4
lenSatelliteRecord=68
numSatelliteRecord=254
[dvbsTransponder:52]
offSatelliteIndex=0
offTransportStreamId=6
offOriginalNetworkId=8
offNetworkId=10
offTransponderIndex=20
offFreqInMhz=16
offSymbolRate=28
[dvbsChannel:256]
offChannelType=15
offServiceType=16
offTransponderIndex=20
offPmtPid=22
offPcrPid=26
offProgramNr=32
offServiceId=34
offAudioPid=58
offName=150
lenName=50
offProvider=200
lenProvider=52
# Philips format 100 lists - dtv_cmdb_2.bin with 3443 KB
#[dtv_cmdb_2.bin:3525205]
# blackbox - 4532 KB
#[dtv_cmdb_2.bin:4640189]
# OK.ODL, overice Sharp - dtv_cmdb_2.bin with 5048 KB
[dtv_cmdb_2.bin:5168189]
offChannelBitmap=8
lenChannelBitmap=752
offChannelRecord=0x2f8
lenChannelRecord=660
numChannelRecord=6000
offTransponderBitmap=0x3c6fb8
lenTransponderBitmap=376
offTransponderRecord=0x3c7130
lenTransponderRecord=392
numTransponderRecord=3000
offSatelliteBitmap=0x4e98a4
lenSatelliteBitmap=32
offSatelliteRecord=0x4e98c4
lenSatelliteRecord=68
numSatelliteRecord=254
[dvbsSatellite:68]
offName=2
lenName=32
offLowFreq=36
offHighFreq=38
[dvbsTransponder:392]
offSatelliteIndex=0
offTransportStreamId=6
offOriginalNetworkId=8
offNetworkId=10
offTransponderIndex=14
offFreqInMhz=16
offSymbolRate=28
[dvbsChannel:660]
offChannelType=15
offServiceType=16
offTransponderIndex=20
offPmtPid=22
offPcrPid=26
offProgramNr=32
offServiceId=34
offAudioPid=58
offName=246
lenName=66
offProvider=312
lenProvider=270

View File

@@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using ChanSort.Api;
namespace ChanSort.Loader.CmdbBin
{
public class CmdbFileSerializer : SerializerBase
{
private IniFile ini;
private readonly MappingPool<DataMapping> satMappings = new MappingPool<DataMapping>("dtv_cmdb_2.bin");
private readonly ChannelList dvbsTv = new ChannelList(SignalSource.DvbS | SignalSource.Tv, "Sat TV");
private readonly ChannelList dvbsRadio = new ChannelList(SignalSource.DvbS | SignalSource.Radio, "Sat Radio");
private readonly ChannelList dvbsData = new ChannelList(SignalSource.DvbS | SignalSource.Radio, "Sat Data");
private DvbStringDecoder dvbStringDecoder;
private bool loaded = false;
public CmdbFileSerializer(string inputFile) : base(inputFile)
{
this.DataRoot.AddChannelList(dvbsTv);
this.DataRoot.AddChannelList(dvbsRadio);
// this.DataRoot.AddChannelList(dvbsData); // there seem to be multiple data lists with Toshiba TVs which all have their own numbering starting at 1. Better don't show data channels at all than dupes
this.ReadConfigurationFromIniFile();
}
#region ReadConfigurationFromIniFile()
private void ReadConfigurationFromIniFile()
{
string iniFile = this.GetType().Assembly.Location.ToLowerInvariant().Replace(".dll", ".ini");
this.ini = new IniFile(iniFile);
foreach (var section in ini.Sections)
{
int idx = section.Name.IndexOf(":");
if (idx < 0)
continue;
string recordLength = idx < 0 ? "" : section.Name.Substring(idx + 1);
if (section.Name.StartsWith("dtv_cmdb_2"))
satMappings.AddMapping(recordLength, new DataMapping(section));
}
}
#endregion
#region Load()
public override void Load()
{
this.dvbStringDecoder = new DvbStringDecoder(this.DefaultEncoding);
foreach (var file in Directory.GetFiles(Path.GetDirectoryName(this.FileName)))
{
var lower = Path.GetFileName(file).ToLowerInvariant();
var size = (int)new FileInfo(file).Length;
switch (lower)
{
case "dtv_cmdb_2.bin":
LoadFile(file, this.dvbsTv, this.dvbsRadio, this.dvbsData, this.satMappings.GetMapping(size));
break;
}
}
if (!this.loaded)
throw new FileLoadException("\"" + this.FileName + "\" does not belong to a dtv_cmdb_* file system");
}
#endregion
#region LoadFile()
private void LoadFile(string file, ChannelList tvList, ChannelList radioList, ChannelList dataList, DataMapping fileMapping)
{
var data = File.ReadAllBytes(file);
var sec = fileMapping.Settings;
LoadBitmappedRecords(data, sec, "Satellite", ReadSatellite);
LoadBitmappedRecords(data, sec, "Transponder", ReadTransponder);
LoadBitmappedRecords(data, sec, "Channel", (map, index) => ReadChannel(map, tvList, radioList, dvbsData, index));
this.loaded = true;
}
#endregion
#region LoadBitmappedRecords()
private void LoadBitmappedRecords(byte[] data, IniFile.Section sec, string recordType, Action<DataMapping, int> readRecord)
{
var lenRecord = sec.GetInt($"len{recordType}Record");
var map = new DataMapping(this.ini.GetSection($"dvbs{recordType}:{lenRecord}"));
map.DefaultEncoding = this.DefaultEncoding;
map.SetDataPtr(data, sec.GetInt($"off{recordType}Record"));
var off = sec.GetInt($"off{recordType}Bitmap");
var len = sec.GetInt($"len{recordType}Bitmap");
var count = sec.GetInt($"num{recordType}Record");
int index = 0;
for (int i = 0; i < len; i++)
{
var b = data[off + i];
for (byte mask = 1; mask != 0; mask <<= 1)
{
if ((b & mask) != 0)
readRecord(map, index);
map.BaseOffset += lenRecord;
if (++index >= count)
break;
}
}
}
#endregion
private void ReadSatellite(DataMapping map, int index)
{
var sat = new Satellite(index);
sat.Name = map.GetString("offName", map.Settings.GetInt("lenName"));
this.DataRoot.AddSatellite(sat);
}
private void ReadTransponder(DataMapping map, int index)
{
//var idx = map.GetWord("offTransponderIndex"); // seems to be some logical number, skipping a new numbers here and there
var tp = new Transponder(index);
var satIndex = map.GetWord("offSatelliteIndex");
tp.Satellite = this.DataRoot.Satellites.TryGet(satIndex);
tp.OriginalNetworkId = map.GetWord("offOriginalNetworkId");
tp.TransportStreamId = map.GetWord("offTransportStreamId");
tp.FrequencyInMhz = map.GetDword("offFreqInMhz");
tp.SymbolRate = map.GetWord("offSymbolRate");
this.DataRoot.AddTransponder(tp.Satellite, tp);
}
#region ReadChannel()
private void ReadChannel(DataMapping chanMap, ChannelList tvList, ChannelList radioList, ChannelList dataList, int recordIndex)
{
var channelType = (int)chanMap.GetByte("offChannelType");
if (channelType == 0) // some file format versions store the channel type in the upper nibble of a byte
channelType = chanMap.GetByte("offChannelTypeOld") >> 4;
var serviceType = chanMap.GetByte("offServiceType");
var apid = chanMap.GetWord("offAudioPid") & 0x1FFF;
var vpid = chanMap.GetWord("offVideoPid") & 0x1FFF;
ChannelList list;
if (channelType != 0)
list = channelType == 1 ? tvList : channelType == 2 ? radioList : dataList;
else if (serviceType != 0)
{
var type = LookupData.Instance.IsRadioTvOrData(serviceType);
list = type == SignalSource.Radio ? radioList : type == SignalSource.Tv ? tvList : dataList;
}
else
{
//list = vpid != 0 && vpid != 0x1FFF ? tvList : apid != 0 && apid != 0x1FFF ? radioList : dataList;
list = tvList;
}
var progNr = (int)chanMap.GetWord("offProgramNr");
if (progNr == 0xFFFE)
progNr = -2;
var ch = new ChannelInfo(list.SignalSource, recordIndex, progNr, "");
ch.ServiceType = serviceType;
ch.ServiceTypeName = Api.LookupData.Instance.GetServiceTypeDescription(ch.ServiceType);
ch.PcrPid = chanMap.GetWord("offPcrPid") & 0x1FFF;
ch.ServiceId = chanMap.GetWord("offServiceId");
ch.AudioPid = apid;
ch.VideoPid = vpid;
var off = chanMap.BaseOffset + chanMap.GetOffsets("offName")[0];
this.dvbStringDecoder.GetChannelNames(chanMap.Data, off, chanMap.Settings.GetInt("lenName"), out var longName, out var shortName);
ch.Name = longName;
ch.ShortName = shortName;
var offProv = chanMap.GetOffsets("offProvider");
if (offProv.Length > 0)
{
off = chanMap.BaseOffset + offProv[0];
this.dvbStringDecoder.GetChannelNames(chanMap.Data, off, chanMap.Settings.GetInt("lenName"), out longName, out _);
ch.Provider = longName;
}
var offDebug = chanMap.Settings.GetInt("offDebug");
var lenDebug = chanMap.Settings.GetInt("lenDebug");
ch.AddDebug(chanMap.Data, chanMap.BaseOffset + offDebug, lenDebug);
var transponderIndex = chanMap.GetWord("offTransponderIndex");
var tp = this.DataRoot.Transponder.TryGet(transponderIndex);
if (tp != null)
{
ch.Transponder = tp;
ch.OriginalNetworkId = tp.OriginalNetworkId;
ch.TransportStreamId = tp.TransportStreamId;
ch.FreqInMhz = tp.FrequencyInMhz;
ch.SymbolRate = tp.SymbolRate;
ch.Satellite = tp.Satellite?.Name;
}
this.DataRoot.AddChannel(list, ch);
}
#endregion
public override void Save(string tvOutputFile)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,16 @@
using ChanSort.Api;
namespace ChanSort.Loader.CmdbBin
{
public class CmdbPlugin : ISerializerPlugin
{
public string DllName { get; set; }
public string PluginName => "cmdb .bin";
public string FileFilter => "*.bin";
public SerializerBase CreateSerializer(string inputFile)
{
return new CmdbFileSerializer(inputFile);
}
}
}

View File

@@ -0,0 +1,87 @@
namespace ChanSort.Loader.CmdbBin
{
public class DvbsDataLayout
{
public readonly int satCount;
public readonly int satLength;
public readonly int sizeOfTransponderBlockHeader;
public readonly int transponderCount;
public readonly int transponderLength;
public readonly int sizeOfChannelLinkedListEntry = 8;
public readonly int linkedListExtraDataLength;
public readonly int dvbsMaxChannelCount;
public readonly int dvbsChannelLength;
public readonly int lnbCount;
public readonly int lnbLength;
public readonly int[] dvbsSubblockLength;
public readonly int dvbsBlockTotalLength;
public readonly int satIndexFactor;
public int LnbBlockHeaderSize = 12;
public DvbsDataLayout(Api.IniFile.Section iniSection)
{
this.satCount = iniSection.GetInt("satCount");
this.satLength = iniSection.GetInt("satLength");
this.transponderCount = iniSection.GetInt("transponderCount");
this.transponderLength = iniSection.GetInt("transponderLength");
this.sizeOfTransponderBlockHeader = 14 + transponderCount/8 + transponderCount*6 + 2;
this.linkedListExtraDataLength = iniSection.GetInt("linkedListExtraDataLength");
this.dvbsMaxChannelCount = iniSection.GetInt("dvbsChannelCount");
this.dvbsChannelLength = iniSection.GetInt("dvbsChannelLength");
this.lnbCount = iniSection.GetInt("lnbCount");
this.lnbLength = iniSection.GetInt("lnbLength");
this.satIndexFactor = iniSection.GetInt("satIndexFactor");
if (satIndexFactor == 0)
satIndexFactor = 2;
this.dvbsSubblockLength = new[]
{
12, // header
14 + 2 + this.satCount + this.satCount*this.satLength, // satellites
sizeOfTransponderBlockHeader - 4 + transponderCount * transponderLength, // transponder
12 + dvbsMaxChannelCount/8 + dvbsMaxChannelCount*sizeOfChannelLinkedListEntry + linkedListExtraDataLength + dvbsMaxChannelCount * dvbsChannelLength, // channels
LnbBlockHeaderSize - 4 + lnbCount * lnbLength // sat/LNB-Config
};
foreach (int len in this.dvbsSubblockLength)
this.dvbsBlockTotalLength += len + 4;
}
/// <summary>
/// relative to start of DVBS-Block (including the intial 4 length bytes)
/// </summary>
public int TransponderTableOffset
{
get { return 4 + 4 + dvbsSubblockLength[0] + 4 + dvbsSubblockLength[1] + sizeOfTransponderBlockHeader; }
}
/// <summary>
/// relative to start of DVBS-Block (including the intial 4 length bytes)
/// </summary>
public int ChannelListHeaderOffset
{
get { return 4 + 4 + this.dvbsSubblockLength[0] + 4 + this.dvbsSubblockLength[1] + 4 + this.dvbsSubblockLength[2]; }
}
/// <summary>
/// relative to start of DVBS-Block (including the intial 4 length bytes)
/// </summary>
public int AllocationBitmapOffset { get { return ChannelListHeaderOffset + 16; } }
/// <summary>
/// relative to start of DVBS-Block (including the intial 4 length bytes)
/// </summary>
public int SequenceTableOffset { get { return this.AllocationBitmapOffset + dvbsMaxChannelCount/8; } }
/// <summary>
/// relative to start of DVBS-Block (including the intial 4 length bytes)
/// </summary>
public int ChannelListOffset
{
get { return SequenceTableOffset + dvbsMaxChannelCount*sizeOfChannelLinkedListEntry + linkedListExtraDataLength; }
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ChanSort.Loader.CmdbBin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanSort.Loader.CmdbBin")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b594dda4-7bd5-450e-b648-668e0f659813")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]