-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add minimal support of DVB AIT #6922
Conversation
This is used by broadcast channels to provide interactive contents.
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
@googlebot I consent. |
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
Test stream: https://treble.phh.me/test-ait.ts (this link won't live very long, don't use the link for permanent tests) |
@icbaker - Could you take a look at this, since it falls under metadata? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also please look at adding some tests for AitDecoder?
There's some other metadata decoder tests in the icy
and scte35
packages for inspiration.
If you have a (short & small!) TS stream with an AIT that can be included in the PR you can also add it to TsExtractorTest which will add some nice robustness. This might be a bit awkward to get working, so feel free to reach out for help if it's not working as you'd expect.
int endOfSection = sectionData.getPosition() + (tmp & 4095) - 4 /* Ignore leading CRC */; | ||
|
||
tmp = sectionData.readUnsignedShort(); | ||
int applicationType = tmp & 0x7fff; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because a lot of the values don't fall on clean byte boundaries, but they are mostly numeric, i think you might be better off using ParsableBitArray
instead of ParsableByteArray
Then you can read and skip bits and it should be super-clear that you've implemented the spec.
It makes reading strings a bit more awkward, but you can use Util.fromUtf8Bytes
to help I suspect (or look into adding string reading methods to ParsableBitArray
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I ended up adding readString()
to ParsableBitArray
import java.util.ArrayList; | ||
|
||
public class AitDecoder implements MetadataDecoder { | ||
// Specification of AIT can be found in 5.3.4 of TS 102 809 v1.1.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is meant to be explaining the DESCRIPTOR_TRANSPORT_PROTOCOL
constant, it seems like 5.3.6 is a more precise reference?
I think we should add similar references to the other constants too to point to the relevant sections of the spec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well no I really meant to link this for global AIT documentation
I updated the documentation structure to make more sense
int label = sectionData.readUnsignedByte(); | ||
|
||
if(protocolId == TRANSPORT_PROTOCOL_HTTP) { | ||
while (sectionData.getPosition() < positionOfNextSection2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of using a 2
suffix, can we call this positionOfNextSelector
(and also rename positionOfNextSection
to positionOfNextDescriptor
above)
Same also for any of the l
or len
variables, especially if their scope is quite large, could we qualify them with what they're the length of?
(this is assuming I've correctly matched up your code with the names used in the spec! Please correct me if I'm making nonsense suggestions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that's indeed a mess, I've refactored this.
FWIW I don't end with the same renaming as you.
Hopefully I added enough comments and reference to the standard so we can converge :-)
null, | ||
}; | ||
|
||
static String readDvbString(ParsableByteArray data, int length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this method used? I couldn't see a reference to it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, it isn't used.
That was used by some dead code (there are many informations not parsed by this decoder) (namely to get the "Application name")
This will be removed, thanks
default: | ||
return null; | ||
} | ||
} | ||
|
||
public class SectionPassthrough implements SectionPayloadReader { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add some documentation about what this class is for/what it does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
public class SectionPassthrough implements SectionPayloadReader { | ||
private TimestampAdjuster timestampAdjuster = null; | ||
private final String mimeType; | ||
private TrackOutput output; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be final
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see how, since output can be created only in init() function not in constructor.
Looking at other Readers (Ac3Reader), I see that trackouput is @MonotonicNonNull
which I'll add.
@@ -96,6 +96,9 @@ | |||
public static final int TS_STREAM_TYPE_SPLICE_INFO = 0x86; | |||
public static final int TS_STREAM_TYPE_DVBSUBS = 0x59; | |||
|
|||
//Those are special IDs, which don't have actual TS definitions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does the value come from? Can you reference a spec or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this value is magic value that is beyond max standard value of TS_STREAM_TYPE which is one byte.
It is meant to carry stream type for types not defined in the spec.
Do you have a recommendation to handle that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to jump in: You can avoid the public magic value by adding a boolean in StreamInfo saying "hasApplicationSignallingDescriptor" which is true if and only if one of the descrptor uses descriptor tag 0x6F. Alternatively, you could include in stream info a list / array of all descriptor tags associated with the program, and then checking for that in the TsPayloadReaderFactory. The boolean is probably just simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what it's worth, Teletext tracks are also detected by a specific descriptor in PMT
(see https://www.etsi.org/deliver/etsi_EN/300400_300499/300472/01.03.01_60/en_300472v010301p.pdf section 4)
So the boolean way doesn't work much. I'm not a fan of including all descriptors tags.
We could have an enum ExtraType { Nope, Application, Teletext, }
but I'm not much of a fan either.
Now, in Teletext's case, descriptors contain useful information to send to Teletext{Reader,Decoder} (namely the page of the subtitle and the language). At the moment we transmit it by creating a new TelextSubtitleInfo storage-class (which inherits SubtitleInfo, and we changed DvbSubtitleInfo inherits SubtitleInfo as well). And we gave teletext track 0x102 id
I don't have strong opinion on how to handle that, though at the moment I still prefer leaving those "internal" IDs.
There I did the few bits of refactoring. I'll now add tests. |
I'm not totally sure what test you want to see in TsExtractor. |
Those test data are defined using tsduck xml format. feedInputBuffer is identical to SpliceInfoDecoderTest's, could be worth mutualizing
Looks good, thanks for making the changes! I'll work on getting this merged. |
Thanks! |
This is used by broadcast channels to provide interactive contents, through HbbTV.
There are many more informations available in this TS section, though this is enough for a minimal HbbTV implementation.