-
Notifications
You must be signed in to change notification settings - Fork 31
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
SCTE-35 messages inside the DSM-CC stream (was Buffer overflow in TransportStream's packet_pid) #60
Comments
Thank you for reporting this. Looks like there is something strange in your file, it has more TS packets then DVB Inspector is expecting. So there is probably something wrong in the file, but DVB inspector should be able to handle it (and report it) I would like to ask you to provide the file for testing, but as it has 33.345.520 packets of at least 188 bytes, it will be over 6 GB inn size. So sharing it may not be trivial. |
Yes it was a big file, unfortunately I had to delete it to save space. Btw if we find some way to share them, I have 2 TS files from Italian muxes, Rai (Italian public broadcasting company) and Mediaset (a private one). I wanted to analyze how the DVB TA (targeted advertising) is implemented. Mediaset seems to be wrapping SCTE-35 messages in DSM-CC objects, tag id 70. For Rai something like that but can't figure that out. I found some more details in the reverse-engineered HbbTV app for Mediaset. If you are interested (to add DVB TA parsing and stuff and to figure stuff out for those broadcasters), I can share the files with you with some kind of link in Google Drive maybe |
Yes, I am interested in these files. Sharing using Google drive should work (or https://wetransfer.com/ or any other file sharing service like you prefer). |
@EricBerendsen here they are https://drive.google.com/drive/folders/12Oyz6ZVUtDhd2suqzvX7ouwObpeSqmyc?usp=sharing |
@jxxp9 Thank you very much for the streams, and the extra information. A lot of new information (at least for me). |
Found some more stuff. Here: https://dvb.org/wp-content/uploads/2021/03/dvbscene-57.pdf search for "DSMCC Moreover, I found this in the PID section: |
@EricBerendsen I've added I've also found the actual DSM-CC stuff that contains the SCTE data, it's this pid stream here: The data after the So, taking a further look at the standard (https://dvb.org/wp-content/uploads/2020/12/A178-1r1_Dynamic-substitution-of-content-in-linear-broadcast_Part1_Signalling_Draft-TS-103-752-1v121_Feb-2021.pdf), the So, if my analysis is correct, mediaset should be using:
The calculation with the ad duration and so on are in the unobfuscated js file, The standard says (chapter 6.3.1):
Here the latter is used. The stream event is Other signalling method usedThere is also another option, they seem to also use another signalling method (when in js code
In this latter signalling method (the one with The former implementation (the one with data wrapped in SCTE-35) seems to be 100% standard, the other one is not I think. Both are available in the analyzed stream. (for your interest, the unobfuscated js files can be found by heading to http://hbbtv.mediaset.net/app/mplayhbbtvgoldzoo/dev/index.html, in the source HTML you can find these commented out references: |
@EricBerendsen added some more stuff to the previous post, that should be enough detail for now 😄 |
Yes, that is more than enough detail for now! Thank you very much, interesting stuff. Very nice and detailed analysis! Thinking about if and how it is possible to use this in DVB Inspector, but there does not appear to be a way to determine from the .ts alone what stream_events are used for and in what format. Just looking for the string "AQEA" is not enough, when TEMI is used the first bytes will be different. So the parsing as CC_stream_event_payload_binary has to be optional, or configurable. So maybe a right-click menu option "Interpret as DSM-CC_stream_event_payload_binary" on a DSM-CC Stream Descriptor List? I have to think about it some more. |
@EricBerendsen I thought we might try and parse the packets and guess if it is a valid packet. I wrote this (pseudo)(C | Java) function to parse/check this packet type. Offset/indexes etc might be wrong (as one might expect, didn't try it). All this because other types of streams/packet types might need an heuristic test to be identified, since they might not have a defined PID number in the standard. That would genericize the stream identification. boolean isValid_DSM_CC_stream_event_payload_binary(byte[] packet) {
byte field_DVB_data_length = packet[0];
byte field_reserved_zero_future_use1 = (packet[1] & 0b11100000) >> 5; // TODO CHECK ENDIANNESS!!
assert(field_reserved_zero_future_use1 == 0);
byte field_event_type = (packet[1] & 0b00010000) >> 4; // TODO CHECK ENDIANNESS!!
byte field_timeline_type = packet[1] & 0b00001111; // TODO CHECK ENDIANNESS!!
assert(timeline_type < 2);
byte field_temi_component_tag = 0;
byte field_temi_timeline_id = 0;
// used to add a byte offset to parse fields after the timeline_type field
int offset_timeline_type = 0;
if (timeline_type == 0x2) {
// in this case we have 2 bytes more
offset_timeline_type = 2;
byte field_temi_component_tag = packet[2];
byte field_temi_timeline_id = packet[3];
}
byte field_reserved_zero_future_use2 = packet[2 + offset_timeline_type];
assert(field_reserved_zero_future_use2 == 0);
// this is because
// DVB_data_length:= "This 8-bit number gives the length, in bytes, of the fields following the DVB_data_length field
// prior to the private_data_length field."
assert(field_DVB_data_length == 1 + offset_timeline_type);
byte field_private_data_length = packet[3 + offset_timeline_type];
uint field_private_data_specifier = 0;
byte[] private_data_byte = new byte[field_private_data_length];
// used to add a byte offset to parse fields after the field_private_data_length field
int offset_private_data_length = 0;
if (field_private_data_length > 0) {
offset_private_data_length = sizeof(field_private_data_specifier) + field_private_data_length;
field_private_data_specifier = parseUInt(packet[4 + offset_timeline_type]);
for (int i = 0; i < private_data_length - 4; i++) {
private_data_byte[i] = packet[4 + offset_timeline_type + i]
}
}
// used to add a byte offset to parse fields after the private_data_length field
int offset_event_type = 0;
byte carousel_object_name_length = 0;
// in the standard, unnamed, only marked as byte array
byte[] carousel_object_name = new byte[carousel_object_name_length];
if (field_event_type == 1) {
for (int i = 0; i < carousel_object_name_length; i++) {
carousel_object_name[i] = packet[5 + offset_timeline_type + offset_private_data_length + i];
}
}
boolean validSCTE35;
int lengthSCTE35;
if (field_event_type == 0) {
validSCTE35 = checkSCTE35(packet[5 + offset_timeline_type + offset_private_data_length]);
lengthSCTE35 = parseSCTE35(packet[5 + offset_timeline_type + offset_private_data_length])
assert(validSCTE35);
}
assert(packet.length == 5 + offset_timeline_type + offset_private_data_length +
(field_event_type == 1 ? carousel_object_name_length :
lengthSCTE35)
);
} Moreover, we could cross-check the SCTE35 message content (or the carousel_object_name) to find the referenced stuff in there and show the info to the user in a more user-friendly way. The related Event could be found by looking at event objects (from all event streams) with PTS near or equal to that of the SCTE35 message (or using the other time-signaling methods defined in the standard). Of course before parsing the packet using my function, one will need to check if it's valid base64 content and if yes decode it, then pass the result to the function. |
I have made a first attempt at just trying to parse the stream events, and if it happens to be a valid DSM-CC_stream_event_payload_binary then show it. That works, not sure how to proceed. I can not connect that event to one of the services, as they all use the same event stream. Inside the Splice_info_section there are two descriptors, the second a normal segmentation_descriptor. The first is strange, it has tag 0x70, but certainly is not a adaptation_field_data_descriptor. From the .js I can see it is used to check whether the event is for the selected channel;
So the Splice sections can not be matched to a service, and do not fit into the normal SCTE-35 structure; |
The 0x70 (112) descriptor is a custom one from Mediaset as far as I can understand it, and using the tag 0x70 is not standard, as far as I can see. The DVB-TA specification seems not to define a link to the associated program PID (couldn't find it in the standard, please double check if you can), that may be the reason why Mediaset decided to use a custom descriptor with a channel code in it (it contains private data with a spot UUID and a code with the channel name, and maybe other stuff) |
Btw great work! Would like to give it a try |
@jxxp9 I merged my updates into master. You can find the build result at the bottom left (snapshot) here; https://github.com/EricBerendsen/dvbinspector/actions/runs/5637062199 Let me know what you think. |
Hi, just got this exception:
Probably the problem is the index increment. Dunno what the DVB/TS standard says on this
The text was updated successfully, but these errors were encountered: