Skip to content

Commit 76d9893

Browse files
committed
Add logical channel numbering support
1 parent 822ea77 commit 76d9893

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/**
4+
* MIT License
5+
*
6+
* Copyright (c) 2018 Samuel CHEMLA
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
* SOFTWARE.
25+
*/
26+
27+
namespace PhpBg\DvbPsi\Descriptors\PrivateDescriptors\EACEM;
28+
29+
/**
30+
* Class LogicalChannel
31+
* @see EACEM IEC/CENELEC 62 216: « Baseline Digital Terrestrial TV Receiver Specification »
32+
*/
33+
class LogicalChannel
34+
{
35+
/**
36+
* Array of <service id> => <logical channel number>
37+
* @var array
38+
*/
39+
public $services = [];
40+
41+
/**
42+
* NetworkName constructor.
43+
* @param $data
44+
* @throws \PhpBg\DvbPsi\Exception
45+
*/
46+
public function __construct($data)
47+
{
48+
$len = strlen($data);
49+
$currentPointer = 0;
50+
while ($currentPointer < $len) {
51+
$serviceId = unpack('n', substr($data, $currentPointer, 2))[1];
52+
$currentPointer += 2;
53+
54+
$tmp = unpack('n', substr($data, $currentPointer, 2))[1];
55+
$currentPointer += 2;
56+
$lcn = $tmp & 0b1111111111;
57+
58+
$this->services[$serviceId] = $lcn;
59+
}
60+
}
61+
62+
public function __toString()
63+
{
64+
$msg = "Logical channels numbers:\n";
65+
$msg .= "\tService ID > channel number\n";
66+
foreach ($this->services as $serviceId => $lcn) {
67+
$msg .= sprintf("\t%d (0x%x) > %d\n", $serviceId, $serviceId, $lcn);
68+
}
69+
return $msg;
70+
}
71+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# EACEM private descriptors
2+
3+
All descriptors here belong to private_data_specifier `0x00000028`
4+
5+
See `PhpBg\DvbPsi\Descriptors\PrivateDataSpecifier`

src/TableParsers/TableParserAbstract.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use PhpBg\DvbPsi\Descriptors\NetworkName;
3434
use PhpBg\DvbPsi\Descriptors\ParentalRating;
3535
use PhpBg\DvbPsi\Descriptors\PrivateDataSpecifier;
36+
use PhpBg\DvbPsi\Descriptors\PrivateDescriptors\EACEM\LogicalChannel;
3637
use PhpBg\DvbPsi\Descriptors\ServiceList;
3738
use PhpBg\DvbPsi\Descriptors\ShortEvent;
3839
use PhpBg\DvbPsi\Descriptors\TerrestrialDeliverySystem;
@@ -41,6 +42,12 @@
4142
abstract class TableParserAbstract implements TableParserInterface
4243
{
4344

45+
/**
46+
* Private data specifier, used to select private descriptors parsers
47+
* @var int | null
48+
*/
49+
protected $privateDataSpecifier;
50+
4451
/**
4552
* Parse a descriptor loop
4653
* @param string $data
@@ -61,6 +68,8 @@ protected function parseDescriptorsLoop(string $data, int $currentPointer, int $
6168
if ($descriptorsEnd > $dataLen) {
6269
throw new Exception("Descriptors loop parse overflow (data length exceeded)");
6370
}
71+
// Reset private data specifier
72+
$this->privateDataSpecifier = null;
6473
while ($currentPointer < $descriptorsEnd) {
6574
// Safeguard, again
6675
if ($currentPointer >= $dataLen) {
@@ -104,15 +113,16 @@ protected function parseDescriptor(int $descriptorId, string $data, int $current
104113
$descriptorData = substr($data, $currentPointer, $descriptorLength);
105114

106115
switch ($descriptorId) {
107-
//TODO handle private descriptor tag : 0x83 in case data specifier is 0x00000028 EACEM. In that case it provides logical channel numbering
108116
case Identifier::TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR:
109117
return new TerrestrialDeliverySystem($descriptorData);
110118

111119
case Identifier::NETWORK_NAME_DESCRIPTOR:
112120
return new NetworkName($descriptorData);
113121

114122
case Identifier::PRIVATE_DATA_SPECIFIER_DESCRIPTOR:
115-
return new PrivateDataSpecifier($descriptorData);
123+
$pds = new PrivateDataSpecifier($descriptorData);
124+
$this->privateDataSpecifier = $pds->private_data_specifier;
125+
return $pds;
116126

117127
case Identifier::SERVICE_LIST_DESCRIPTOR:
118128
return new ServiceList($descriptorData);
@@ -132,6 +142,14 @@ protected function parseDescriptor(int $descriptorId, string $data, int $current
132142
case Identifier::CONTENT_DESCRIPTOR:
133143
return new Content($descriptorData);
134144

145+
146+
// Private descriptors
147+
case 0x83:
148+
if (empty($this->privateDataSpecifier) || $this->privateDataSpecifier !== 0x28) {
149+
throw new Exception(sprintf("Unhandled descriptor tag : 0x%x", $descriptorId));
150+
}
151+
return new LogicalChannel($descriptorData);
152+
135153
default:
136154
throw new Exception(sprintf("Unhandled descriptor tag : 0x%x", $descriptorId));
137155
}

tests/ParserTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
namespace PhpBg\DvbPsi\Tests;
2828

2929
use PhpBg\DvbPsi\Descriptors\NetworkName;
30+
use PhpBg\DvbPsi\Descriptors\PrivateDescriptors\EACEM\LogicalChannel;
3031
use PhpBg\DvbPsi\Descriptors\TerrestrialDeliverySystem;
3132
use PhpBg\DvbPsi\Parser;
3233
use PhpBg\DvbPsi\ParserFactory;
@@ -271,19 +272,25 @@ public function testParseNit()
271272
$this->assertInstanceOf(NitTs::class, $stream004);
272273
$this->assertSame(0x20fa, $stream004->networkId);
273274

274-
// There are 4 descriptors, but the 0x83 one is not yet supported
275-
$this->assertSame(3, count($stream004->descriptors));
275+
$this->assertSame(4, count($stream004->descriptors));
276276

277277
$tds = null;
278+
$lcn = null;
278279
foreach ($stream004->descriptors as $descriptor) {
279280
if ($descriptor instanceof TerrestrialDeliverySystem) {
280281
$tds = $descriptor;
281282
}
283+
if ($descriptor instanceof LogicalChannel) {
284+
$lcn = $descriptor;
285+
}
282286
}
283287
$this->assertInstanceOf(TerrestrialDeliverySystem::class, $tds);
284288
$this->assertSame(42949672950, $tds->centreFrequency);
285289
$this->assertSame(8000000, $tds->bandwidth);
286290
$this->assertSame('64-QAM', TerrestrialDeliverySystem::CONSTELLATION_MAPPING[$tds->constellation]);
287291
$this->assertSame('1/8', TerrestrialDeliverySystem::GUARD_INTERVAL_MAPPING[$tds->guardInterval]);
292+
293+
$this->assertInstanceOf(LogicalChannel::class, $lcn);
294+
$this->assertSame(5, count($lcn->services));
288295
}
289296
}

0 commit comments

Comments
 (0)