Skip to content

Commit

Permalink
Merge pull request #229 from MediaPortal/MP1-5180-Add_HEVC_support_fo…
Browse files Browse the repository at this point in the history
…r_BDReader_directshow_filter

MP1-5180: Add HEVC support for BDReader directshow filter
  • Loading branch information
andrewjswan authored Nov 13, 2023
2 parents 58639f2 + 8e6a827 commit 99c36e2
Show file tree
Hide file tree
Showing 20 changed files with 2,490 additions and 283 deletions.
6 changes: 6 additions & 0 deletions DirectShowFilters/BDReader/BDReader.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@
<ClCompile Include="source\FrameHeaderParser.cpp" />
<ClCompile Include="source\GolombBuffer.cpp" />
<ClCompile Include="source\H264Nalu.cpp" />
<ClCompile Include="source\HEVC\BitstreamReader.cpp" />
<ClCompile Include="source\HEVC\Hevc.cpp" />
<ClCompile Include="source\HEVC\HevcNalDecode.cpp" />
<ClCompile Include="source\LibBlurayWrapper.cpp" />
<ClCompile Include="source\OverlayRenderer.cpp" />
<ClCompile Include="source\Packet.cpp" />
Expand All @@ -377,6 +380,9 @@
<ClInclude Include="source\FrameHeaderParser.h" />
<ClInclude Include="source\GolombBuffer.h" />
<ClInclude Include="source\H264Nalu.h" />
<ClInclude Include="source\HEVC\BitstreamReader.h" />
<ClInclude Include="source\HEVC\Hevc.h" />
<ClInclude Include="source\HEVC\HevcNalDecode.h" />
<ClInclude Include="source\IAudioStream.h" />
<ClInclude Include="source\ISubtitleStream.h" />
<ClInclude Include="source\LibBlurayWrapper.h" />
Expand Down
1 change: 1 addition & 0 deletions DirectShowFilters/BDReader/source/BDReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ STDMETHODIMP CBDReaderFilter::SetVideoDecoder(int format, GUID* decoder)
{
if (format != BLURAY_STREAM_TYPE_VIDEO_H264 &&
format != BLURAY_STREAM_TYPE_VIDEO_VC1 &&
format != BLURAY_STREAM_TYPE_VIDEO_HEVC &&
format != BLURAY_STREAM_TYPE_VIDEO_MPEG2)
return E_INVALIDARG;

Expand Down
89 changes: 44 additions & 45 deletions DirectShowFilters/BDReader/source/Clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,21 @@ CClip::CClip(int clipNumber, int playlistNumber, REFERENCE_TIME firstPacketTime,
audioPlaybackPosition = playlistFirstPacketTime;
videoPlaybackPosition = playlistFirstPacketTime;

earliestPacketAccepted = _I64_MAX;
m_rtEarliestPacketAccepted = _I64_MAX;
firstVideoPosition = _I64_MAX;
firstAudioPosition = _I64_MAX;

clipDuration = duration;
clipPlaylistOffset = totalStreamOffset;
m_rtClipPlaylistOffset = totalStreamOffset;
m_rtStreamStartOffset = streamStartOffset;

m_playlistOffset = clipOffset;
m_rtPlayedDuration = 0;
m_rtPrevAudioStart = 0;
m_rtClipVideoStartingOffset = 0LL;
m_rtClipAudioStartingOffset = 0LL;

m_bCalculateAudioOffset = true;
m_bCalculateVideoOffset = true;

m_rtClipStartingOffset = 0LL;

m_bCalculateOffset = true;

noAudio =! audioPresent;

clipInterrupted = interrupted;
Expand All @@ -70,8 +68,8 @@ CClip::CClip(int clipNumber, int playlistNumber, REFERENCE_TIME firstPacketTime,

firstAudio = true;
firstVideo = true;
firstPacketAccepted = false;
firstPacketReturned = false;
m_bFirstPacketAccepted = false;
m_bFirstPacketReturned = false;

clipReset = false;
//LogDebug("CClip:: New Clip (%d,%d) stream Offset %I64d", nPlaylist, nClip, totalStreamOffset);
Expand All @@ -94,8 +92,8 @@ Packet* CClip::ReturnNextAudioPacket(REFERENCE_TIME playlistOffset)
if (noAudio)
{
ret = GenerateFakeAudio(audioPlaybackPosition);
if (earliestPacketAccepted == INT64_MAX)
earliestPacketAccepted = audioPlaybackPosition;
if (m_rtEarliestPacketAccepted == INT64_MAX)
m_rtEarliestPacketAccepted = audioPlaybackPosition;
}
else
{
Expand All @@ -122,20 +120,20 @@ Packet* CClip::ReturnNextAudioPacket(REFERENCE_TIME playlistOffset)
if (clipInterrupted)
ret->nNewSegment |= NS_INTERRUPTED;

if (m_bCalculateAudioOffset && (abs(earliestPacketAccepted - ret->rtStart) > 0))
m_rtClipAudioStartingOffset = earliestPacketAccepted - ret->rtStart;
if (m_bCalculateOffset && (abs(m_rtEarliestPacketAccepted - ret->rtStart) > 0))
m_rtClipStartingOffset = m_rtEarliestPacketAccepted - ret->rtStart;

m_bCalculateAudioOffset = false;
m_bCalculateOffset = false;
}

if (!firstPacketReturned)
firstPacketReturned = true;
if (!m_bFirstPacketReturned)
m_bFirstPacketReturned = true;

ret->rtPlaylistTime = ret->rtStart - m_playlistOffset;

ret->rtClipStartTime = ret->rtStart - earliestPacketAccepted + m_rtClipAudioStartingOffset;
ret->rtStart += clipPlaylistOffset - earliestPacketAccepted + m_rtClipAudioStartingOffset;
ret->rtStop += clipPlaylistOffset - earliestPacketAccepted + m_rtClipAudioStartingOffset;
ret->rtClipStartTime = ret->rtStart - m_rtEarliestPacketAccepted + m_rtClipStartingOffset;
ret->rtStart += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset;
ret->rtStop += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset;

if (m_rtPrevAudioStart == 0)
m_rtPrevAudioStart = ret->rtStart;
Expand Down Expand Up @@ -178,10 +176,10 @@ Packet* CClip::ReturnNextVideoPacket(REFERENCE_TIME playlistOffset)
firstVideo = false;
ret->pmt = CreateMediaType(m_videoPmt);

if (m_bCalculateVideoOffset && (abs(earliestPacketAccepted - ret->rtStart) > 0))
m_rtClipVideoStartingOffset = earliestPacketAccepted - ret->rtStart;
if (m_bCalculateOffset && (abs(m_rtEarliestPacketAccepted - ret->rtStart) > 0))
m_rtClipStartingOffset = m_rtEarliestPacketAccepted - ret->rtStart;

m_bCalculateVideoOffset = false;
m_bCalculateOffset = false;
}

if (ret->rtStart > videoPlaybackPosition)
Expand All @@ -190,14 +188,14 @@ Packet* CClip::ReturnNextVideoPacket(REFERENCE_TIME playlistOffset)
//LogDebug("Videoplayback position (%d,%d) %I64d", nPlaylist, nClip, videoPlaybackPosition);
}

if (!firstPacketReturned)
firstPacketReturned = true;
if (!m_bFirstPacketReturned)
m_bFirstPacketReturned = true;

ret->rtPlaylistTime = ret->rtStart - m_playlistOffset;

ret->rtClipStartTime = ret->rtStart - earliestPacketAccepted + m_rtClipVideoStartingOffset;
ret->rtStart += clipPlaylistOffset - earliestPacketAccepted + m_rtClipVideoStartingOffset;
ret->rtStop += clipPlaylistOffset - earliestPacketAccepted + m_rtClipVideoStartingOffset;
ret->rtClipStartTime = ret->rtStart - m_rtEarliestPacketAccepted + m_rtClipStartingOffset;
ret->rtStart += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset;
ret->rtStop += m_rtClipPlaylistOffset - m_rtEarliestPacketAccepted + m_rtClipStartingOffset;
}
}
// LogDebug("Clip: vid: return Packet rtStart: %I64d offset: %I64d seekRequired %d",ret->rtStart, ret->rtOffset,ret->bSeekRequired);
Expand Down Expand Up @@ -245,10 +243,10 @@ Packet* CClip::GenerateFakeAudio(REFERENCE_TIME rtStart)
packet->pmt = CreateMediaType(&pmt);
}

if (earliestPacketAccepted == INT64_MAX)
earliestPacketAccepted = audioPlaybackPosition;
if (m_rtEarliestPacketAccepted == INT64_MAX)
m_rtEarliestPacketAccepted = audioPlaybackPosition;

firstPacketAccepted = true;
m_bFirstPacketAccepted = true;

lastAudioPosition += FAKE_AUDIO_DURATION;
audioPlaybackPosition += FAKE_AUDIO_DURATION;
Expand All @@ -274,10 +272,12 @@ bool CClip::AcceptAudioPacket(Packet* packet)
else
{
//CAutoLock lock(m_sectionRead);
if (!firstPacketReturned)
if (!m_bFirstPacketReturned)
{
if (earliestPacketAccepted > packet->rtStart) earliestPacketAccepted = packet->rtStart;
firstPacketAccepted = true;
if (m_rtEarliestPacketAccepted > packet->rtStart)
m_rtEarliestPacketAccepted = packet->rtStart;

m_bFirstPacketAccepted = true;
}

packet->nClipNumber = nClip;
Expand All @@ -304,12 +304,12 @@ bool CClip::AcceptVideoPacket(Packet* packet)
}
else
{
if (!firstPacketReturned && packet->rtStart != Packet::INVALID_TIME && earliestPacketAccepted > packet->rtStart)
earliestPacketAccepted = packet->rtStart;
if (!m_bFirstPacketReturned && packet->rtStart != Packet::INVALID_TIME && m_rtEarliestPacketAccepted > packet->rtStart)
m_rtEarliestPacketAccepted = packet->rtStart;

if (!firstPacketAccepted && packet->rtStart != Packet::INVALID_TIME)
if (!m_bFirstPacketAccepted && packet->rtStart != Packet::INVALID_TIME)
{
firstPacketAccepted = true;
m_bFirstPacketAccepted = true;
lastVideoPosition = packet->rtStart;
}

Expand Down Expand Up @@ -392,23 +392,22 @@ void CClip::Reset(REFERENCE_TIME totalStreamOffset)
lastVideoPosition = playlistFirstPacketTime;
lastAudioPosition = playlistFirstPacketTime;

firstPacketAccepted ? clipReset = true : clipReset = false;
m_bFirstPacketAccepted ? clipReset = true : clipReset = false;

clipPlaylistOffset = totalStreamOffset;
m_rtClipPlaylistOffset = totalStreamOffset;

audioPlaybackPosition = playlistFirstPacketTime;
videoPlaybackPosition = playlistFirstPacketTime;
m_rtClipAudioStartingOffset = 0LL;
m_rtClipVideoStartingOffset = 0LL;
m_rtClipStartingOffset = 0LL;

earliestPacketAccepted = INT64_MAX;
m_rtEarliestPacketAccepted = INT64_MAX;

superseded = NO_SUPERSEDE;

firstAudio = true;
firstVideo = true;
firstPacketAccepted = false;
firstPacketReturned = false;
m_bFirstPacketAccepted = false;
m_bFirstPacketReturned = false;
}

bool CClip::HasAudio()
Expand Down
16 changes: 7 additions & 9 deletions DirectShowFilters/BDReader/source/Clip.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class CClip
void Supersede(int supersedeType);
bool IsSuperseded(int supersedeType);
REFERENCE_TIME playlistFirstPacketTime;
REFERENCE_TIME clipPlaylistOffset;
REFERENCE_TIME m_rtClipPlaylistOffset;
void Reset(REFERENCE_TIME totalStreamOffset);
bool HasAudio();
bool HasVideo();
Expand All @@ -85,7 +85,7 @@ class CClip
// starttime of the last video packet returned from the clip to the pin
REFERENCE_TIME videoPlaybackPosition;

REFERENCE_TIME earliestPacketAccepted;
REFERENCE_TIME m_rtEarliestPacketAccepted;

// Clip duration as provided by libbluray
REFERENCE_TIME clipDuration;
Expand All @@ -98,9 +98,8 @@ class CClip

// Accurate clip starting time (when known).
// Not set when selecting chapter from the menu
REFERENCE_TIME m_rtClipAudioStartingOffset;
REFERENCE_TIME m_rtClipVideoStartingOffset;

REFERENCE_TIME m_rtClipStartingOffset;

// true would indicate that this is the first audio packet
bool firstAudio;
// true would indicate that this is the first video packet
Expand All @@ -120,13 +119,12 @@ class CClip
CCritSec m_sectionVectorAudio;
CCritSec m_sectionVectorVideo;

bool m_bCalculateAudioOffset;
bool m_bCalculateVideoOffset;
bool m_bCalculateOffset;

// indicates if this is the first packet to be buffered in clip
bool firstPacketAccepted;
bool m_bFirstPacketAccepted;
// indicates if this is the first packet to be returned from the clip
bool firstPacketReturned;
bool m_bFirstPacketReturned;

REFERENCE_TIME m_rtPrevAudioStart;
REFERENCE_TIME m_rtPlayedDuration; // Do not zero on reset as this should be cumulative
Expand Down
26 changes: 20 additions & 6 deletions DirectShowFilters/BDReader/source/DeMultiplexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ void CDeMultiplexer::FlushPESBuffers(bool bDiscardData, bool bSetCurrentClipFill
if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_MPEG1 ||
m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_MPEG2)
FillVideoMPEG2(NULL, NULL, true);
else if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_H264)
else if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_H264 || m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_HEVC)
FillVideoH264PESPacket(NULL, m_pBuild, true);
else if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_VC1)
FillVideoVC1PESPacket(NULL, m_pBuild, true);
Expand Down Expand Up @@ -996,10 +996,22 @@ void CDeMultiplexer::FillVideoH264PESPacket(CTsHeader* header, CAutoPtr<Packet>
if (!pData)
continue;

if ((pData[4]&0x1f) == 0x09)
m_fHasAccessUnitDelimiters = true;
bool bFlag = false;
if (m_videoServiceType == BLURAY_STREAM_TYPE_VIDEO_HEVC)
{
if (((pData[4] >> 1) & 0x3f) == HEVC::NAL_AUD)
{
m_fHasAccessUnitDelimiters = true;
bFlag = true;
}
}
else if ((pData[4] & 0x1f) == NALU_TYPE_AUD)
{
m_fHasAccessUnitDelimiters = true;
bFlag = true;
}

if ((pData[4]&0x1f) == 0x09 || !m_fHasAccessUnitDelimiters && pPacket->rtStart != Packet::INVALID_TIME)
if (bFlag || !m_fHasAccessUnitDelimiters && pPacket->rtStart != Packet::INVALID_TIME)
{
p = m_pl.RemoveHead();

Expand Down Expand Up @@ -1263,8 +1275,8 @@ void CDeMultiplexer::FillVideoH264(CTsHeader* header, byte* tsPacket)

if (m_pBuild->GetCount() && m_videoServiceType != BLURAY_STREAM_TYPE_VIDEO_VC1)
{
FillVideoH264PESPacket(header, m_pBuild);
m_pBuild.Free();
FillVideoH264PESPacket(header, m_pBuild);
m_pBuild.Free();
}
}

Expand Down Expand Up @@ -1716,6 +1728,8 @@ char* CDeMultiplexer::StreamFormatAsString(int pStreamType)
return "H264";
case BLURAY_STREAM_TYPE_VIDEO_VC1:
return "VC1";
case BLURAY_STREAM_TYPE_VIDEO_HEVC:
return "HEVC";
case BLURAY_STREAM_TYPE_AUDIO_LPCM:
return "LPCM";
case BLURAY_STREAM_TYPE_AUDIO_AC3:
Expand Down
Loading

0 comments on commit 99c36e2

Please sign in to comment.