ERROR while decoding TS: 21 since v.2.2.09
Closed this issue · 11 comments
When running examples/multicast/ts_scte_parser.py
I only see ERROR while decoding TS: 21
for each SCTE-35 packet, using v.2.2.25 on Python 3.6. The latest working release is v.2.2.01, v.2.2.09 is the first release with this error.
I think I see the issue. I'll let you know shortly.
This is the previous multicast example from 2.2.01
it calls Stream.decode(func = foundit)
instead of Stream.decode_next()
Does this work correctly for you?
I had another guy have a similar issue today, I just pushed a new pip build, 2.2.29,
he's testing it now.
No difference with either 2.2.29 or 2.2.31 with the latest or old (2.2.01) multicast example, the same error appears in all cases. What can I do to help find what's happening?
Richard,
Do you have a lot of programs in the stream?
Can you run ffprobe for me and post the output?
With that info, I should be able to offer a solution.
Don't worry man, this won't take long.
Don't use 239.0.0.1, try 239.255.0.1
What is serving the multicast stream and what OS are you using?
I tested the script below with 2.2.33 tonight.
I've run it dozens of times without any issues.
I subclassed Stream so that the video pts is
displayed in the terminal so you can see progress..
import io
import socket
import struct
import threefive
def foundit(cue):
print("""\n\t\tthis function was passed into Stream.decode
it gets called with the cue instance as an arg
for custom handling when a SCTE-35 packet is found\n""")
print(f'\nCue methods can be called\n\tcue.get_command() returns:\n\t\t\t {cue.get_command()}')
print(f'\nCue vars can be read.\n\t cue.command.name\n\t\t\t {cue.command.name}')
class StreamFu(threefive.Stream):
'''
StreamFu is a subclass of threefive.Stream.
the _parse_pts method is modified so
that the video PTS is displayed at the
bottom of the screen to show progress
'''
def _parse_pts(self, pkt, pid):
"""
parse pts with output
"""
pts = ((pkt[13] >> 1) & 7) << 30
pts |= ((pkt[14] << 7) | (pkt[15] >> 1)) << 15
pts |= (pkt[16] << 7) | (pkt[17] >> 1)
pts /= 90000.0
ppp = self._pid_prog[pid]
self._prog_pts[ppp] = pts
print(f'PTS: \033[92m{round(pts,3)}\033[0m',end='\r\r\r')
class MCastParser():
def __init__(self, mcast_ip, if_ip="0.0.0.0", hostname="0.0.0.0", port=9000):
self.HOST = hostname
self.PORT = port
self.MCAST_IP = mcast_ip
self.IF_IP = if_ip
def do(self):
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as sock:
self.set_socket_options(sock)
sock.bind((self.HOST, self.PORT))
with sock.makefile(mode="rb") as socket_file:
ts = StreamFu(socket_file)
ts.decode() # without a function being passed in.
# other method call examples
# ts.decode(func=foundit) # with a function passed in.
# ts.show() # will display stream types by program.
def set_socket_options(self, sock):
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self.MCAST_IP)+socket.inet_aton(self.HOST))
if __name__ == "__main__":
MCastParser(mcast_ip="239.255.0.1").do()
Richard,
you have figured out more than you realize.
I like your fix, but shouldn't it be
The issue you're describing shouldn't be able to happen,
but obviously is happening.
No I see what I broke.
in Stream._parser, I added returns after each if conditional,
that prevented the packets from also being checked for pts.
I added the returns in 2.2.1.
Nice work man.
If want to commit directly to this repo,
I'll add you.
I am adding you to the repo, I want you on the team.
All I ask is that you commit early and often,
and use black to format code.
Thanks for adding me!
In case of video and SCTE-35 in the same PID there will always be PTS. However in many cases the SCTE-35 data is on a separate PID without PTS and that's also normal. We could perhaps also try to read the PCR timestamps.