Skip to content

Commit

Permalink
B Fixed H265 SPS/VPS parsing, fixed timescale calculation for H265
Browse files Browse the repository at this point in the history
  • Loading branch information
jimm98y committed Jun 3, 2023
1 parent aafce5d commit ba73ad0
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using SharpMp4Parser.IsoParser.Tools;
using SharpMp4Parser.Java;
using SharpMp4Parser.Muxer.Tracks.H264.Parsing.Read;
using System;

namespace SharpMp4Parser.Muxer.Tracks.H265
{
Expand All @@ -14,6 +13,10 @@ public class VideoParameterSet
public long general_profile_compatibility_flags;
public long general_profile_constraint_indicator_flags;

public bool vps_timing_info_present_flag;
public int vps_num_units_in_tick;
public int vps_time_scale;

public VideoParameterSet(ByteBuffer vps)
{
this.vps = vps;
Expand Down Expand Up @@ -47,11 +50,11 @@ public VideoParameterSet(ByteBuffer vps)
layer_id_included_flag[i, j] = r.readBool("layer_id_included_flag[" + i + "][" + j + "]");
}
}
bool vps_timing_info_present_flag = r.readBool("vps_timing_info_present_flag");
vps_timing_info_present_flag = r.readBool("vps_timing_info_present_flag");
if (vps_timing_info_present_flag)
{
long vps_num_units_in_tick = r.readU(32, "vps_num_units_in_tick");
long vps_time_scale = r.readU(32, "vps_time_scale");
vps_num_units_in_tick = r.readU(32, "vps_num_units_in_tick");
vps_time_scale = r.readU(32, "vps_time_scale");
bool vps_poc_proportional_to_timing_flag = r.readBool("vps_poc_proportional_to_timing_flag");
if (vps_poc_proportional_to_timing_flag)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ sequences of 00 00 03 and remove the 03 byte beofre passing the NAL unit further
if (nal[i + 2] == 3)
{
removeNext3 = true;

// special case for 0 0 3 ending, early return here
if (i + 2 == nal.Length - 1)
{
return ms.ToArray();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,23 +90,29 @@ protected void consumeNal(ByteBuffer nal)
nal.position(0);
pps.Add(nal.slice());
((Java.Buffer)nal).position(2);
byte[] bPPS = Streaming.Input.AnnexBUtils.RemoveEmulationPreventionBytes(pps[pps.Count - 1].array().Skip(pps[pps.Count - 1].arrayOffset() + 2).Take(pps[pps.Count - 1].limit()).Concat(new byte[] { 0, 0 }).ToArray());
// emulation prevention bytes are already removed here, do not remove them again as it would have corrupted the PPS
// TODO: appending zeroes at the end seems to be required because of the current parsing logic in order to prevent exception being thrown
byte[] bPPS = pps[pps.Count - 1].array().Skip(pps[pps.Count - 1].arrayOffset() + 2).Take(pps[pps.Count - 1].limit()).Concat(new byte[] { 0 }).ToArray();
parsedPPS = new PictureParameterSetRbsp(ByteBuffer.wrap(bPPS));
Java.LOG.debug("Stored PPS");
break;
case H265NalUnitTypes.NAL_TYPE_VPS_NUT:
nal.position(0);
vps.Add(nal.slice());
((Java.Buffer)nal).position(2);
byte[] bVPS = Streaming.Input.AnnexBUtils.RemoveEmulationPreventionBytes(vps[vps.Count - 1].array().Skip(vps[vps.Count - 1].arrayOffset() + 2).Take(vps[vps.Count - 1].limit()).Concat(new byte[] { 0, 0 }).ToArray());
// emulation prevention bytes are already removed here, do not remove them again as it would have corrupted the PPS
// TODO: appending zeroes at the end seems to be required because of the current parsing logic in order to prevent exception being thrown
byte[] bVPS = vps[vps.Count - 1].array().Skip(vps[vps.Count - 1].arrayOffset() + 2).Take(vps[vps.Count - 1].limit()).Concat(new byte[] { 0 }).ToArray();
parsedVPS = new VideoParameterSet(ByteBuffer.wrap(bVPS));
Java.LOG.debug("Stored VPS");
break;
case H265NalUnitTypes.NAL_TYPE_SPS_NUT:
nal.position(0);
sps.Add(nal.slice());
((Java.Buffer)nal).position(2);
byte[] bSPS = Streaming.Input.AnnexBUtils.RemoveEmulationPreventionBytes(sps[sps.Count - 1].array().Skip(sps[sps.Count - 1].arrayOffset() + 2).Take(sps[sps.Count - 1].limit()).Concat(new byte[] { 0, 0 }).ToArray());
// emulation prevention bytes are already removed here, do not remove them again as it would have corrupted the PPS
// TODO: appending zeroes at the end seems to be required because of the current parsing logic in order to prevent exception being thrown
byte[] bSPS = sps[sps.Count - 1].array().Skip(sps[sps.Count - 1].arrayOffset() + 2).Take(sps[sps.Count - 1].limit()).Concat(new byte[] { 0 }).ToArray();
parsedSPS = new SequenceParameterSetRbsp(new ByteBufferByteChannel(bSPS));
Java.LOG.debug("Stored SPS");
break;
Expand Down Expand Up @@ -220,13 +226,15 @@ public void configure()

long _timescale;
long _frametick;
if (parsedSPS.vuiParameters != null)

if (parsedVPS.vps_timing_info_present_flag)
{
_timescale = parsedSPS.vuiParameters.vui_time_scale;
_frametick = parsedSPS.vuiParameters.vui_num_units_in_tick;
_timescale = parsedVPS.vps_time_scale;
_frametick = parsedVPS.vps_num_units_in_tick;

if (_timescale == 0 || _frametick == 0)
{
Java.LOG.warn("vuiParams contain invalid values: time_scale: " + _timescale + " and frame_tick: " + _frametick + ". Setting frame rate to 25fps");
Java.LOG.warn("vps contains invalid values: time_scale: " + _timescale + " and frame_tick: " + _frametick + ". Setting frame rate to 25fps");
_timescale = 0;
_frametick = 0;
}
Expand All @@ -244,10 +252,36 @@ public void configure()
}
else
{
Java.LOG.warn("Can't determine frame rate as SPS does not contain vuiParama");
_timescale = 0;
_frametick = 0;
if (parsedSPS.vuiParameters != null && parsedSPS.vuiParameters.vui_timing_info_present_flag)
{
_timescale = parsedSPS.vuiParameters.vui_time_scale;
_frametick = parsedSPS.vuiParameters.vui_num_units_in_tick;
if (_timescale == 0 || _frametick == 0)
{
Java.LOG.warn("vuiParams contain invalid values: time_scale: " + _timescale + " and frame_tick: " + _frametick + ". Setting frame rate to 25fps");
_timescale = 0;
_frametick = 0;
}
if (_frametick > 0)
{
if (_timescale / _frametick > 100)
{
Java.LOG.warn("Framerate is " + (_timescale / _frametick) + ". That is suspicious.");
}
}
else
{
Java.LOG.warn("Frametick is " + _frametick + ". That is suspicious.");
}
}
else
{
Java.LOG.warn("Can't determine frame rate as SPS does not contain vuiParam");
_timescale = 0;
_frametick = 0;
}
}

if (timescale == 0)
{
timescale = _timescale;
Expand Down

0 comments on commit ba73ad0

Please sign in to comment.