I needed a program to demultiplex MPEG-2 Program Streams that I’ve recorded with a Hauppauge WinTV PVR 350 MPEG-2 hardware encoder card and the free MythTV PVR software, so that I could remultiplex the stream for DVD burning using mplex (part of the mjpeg tools package.
I found several MPEG demultiplexers out there, but they all were unsatisfactory for one reason or another:
- they were slow
- some only handled MPEG-1 system streams
- none of them would output the offset between the first audio and video\
presentation time stamps, which is needed to remultiplex
Not printing the offset was really aggravating. There are no presentation time stamps (PTS) in MPEG-2 audio and video elementary streams; these are only added when the streams are multiplexed. So when you demultiplex a program stream into the elementary streams, the audio/video synchronization information is lost. If you remultiplex the streams without telling the multiplexer an initial offset, it is not uncommon for the resulting program stream to be out of sync by up to half a second.
Necessity being the mother of invention, I started writing my own program to inspect the program stream and print the offset. Soon I realized that to make it work, I had to do 95% of the work of writing a demultiplexer, and decided that I might as well do the whole job.
MPEG streams contain a lot of bit fields, so most software that processes them spends a lot of time extracting bit fields. In a demultiplexer, most of this is unnecessary, as all of the important fields are actually aligned on byte boundaries. This is one reason most of the available demultiplexers are much slower than they could be. Some shifts, masks, and logical operations are needed, but not nearly as many as if a general bit field extraction macro (or function call) were used for everything.
An MPEG 2 program stream consists of chunks of audio and video “elementary streams” put into packets, and the packets assembled into “packs”. Packs can in principle be of varying sizes, but it is very common to use fixed 2048-byte packs. This is required for MPEG-2 on DVDs, so almost all encoders default to 2K pack size. Currently I don’t have anything that produced program streams with a different pack size, so my program ONLY handles 2K packs.
The resulting program is m2psd, and is, of course, GPL’d.
Of course, now that it’s written and debugged, I find that it is not sufficient. In principle, when an MPEG-2 program stream is initially recorded, the audio and video encoders operate from a common 27 MHz timebase, so the audio/video synchronization should not change over time. In practice, however, it appears that the sync varies. The presentation time stamps in the program stream allow the decoder to accomodate this. But even though I get the initial offset form m2psd, over the course of an hour long program stream remultiplexed from the m2psd output the sync diverges by about 1/3 of a second.
Apparently I need to find a multiplexer that can accept packetized elementary streams (PES) and preserve the PTSes. Or figure out how to insert DVD NAV packs without remultiplexing.