It turned out that some h.264 streams are hard to segment. Instead
of having periodic IDR frames, they only contain very first IDR
frame, and just I frames after that. Technically, some of these I
frames are equivalent of IDR ones (after them there are no inter
predictions to previous frames), but aren't coded as such.
Unfortunately, h.264 standard says that every compliant stream
should start with IDR frame. And thus, some software (including
ffmpeg used by LPMS, as well as ffplay) refuse to decode or play
back streams that our segmenter produces. This in turn leads to
dreaded "ZeroSegments" errors.
Code in this commit is an attempt to fix this problem. It works
as follows:
- Fresh h264Fixer object should be created for each new segment
- NALs from segment should be fed into said object via its
process_nal() method
- If the first Intra-coded frame of the segment is an I frame, it
will get converted to the IDR frame. Then all following reference
rames will have their frame_num fields changed accordingly
- On detecting IDR frame Fixer will go into bypass mode, not
changing anything on the stream. Therefore, it is safe to use
Fixer with any stream - most of the time it will detect that the
stream starts with the IDR frame and just do nothing
Notes:
- Please take care to call process_nal() properly, that is with
at least four extra bytes in front of NAL in the supplied buffer
This is because sometimes slice header will "grow" due to the
changes that Fixer makes, and we want to avoid copying huge
Intra-coded slices
- This is not done yet, but Fixer can be easily modified to
perform some additional tasks, such as making sure no extra
copies of SPS/PPS are issued. To that effect, code should not
write SPS/PPS immediately, but only after slice requesting
particular SPS/PPS pair is observed. Then that particular SPS/PPS
should be marked as "present" in the stream and not written
anymore