diff --git a/DirectShowFilters/BDReader/BDReader.vcxproj b/DirectShowFilters/BDReader/BDReader.vcxproj index 51daeb26d41..727a6f02089 100644 --- a/DirectShowFilters/BDReader/BDReader.vcxproj +++ b/DirectShowFilters/BDReader/BDReader.vcxproj @@ -353,6 +353,9 @@ + + + @@ -377,6 +380,9 @@ + + + diff --git a/DirectShowFilters/BDReader/source/BDReader.cpp b/DirectShowFilters/BDReader/source/BDReader.cpp index 7ed561c2b9f..37017dc6cf1 100644 --- a/DirectShowFilters/BDReader/source/BDReader.cpp +++ b/DirectShowFilters/BDReader/source/BDReader.cpp @@ -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; diff --git a/DirectShowFilters/BDReader/source/Clip.cpp b/DirectShowFilters/BDReader/source/Clip.cpp index ef4c7f80bf6..06c57605177 100644 --- a/DirectShowFilters/BDReader/source/Clip.cpp +++ b/DirectShowFilters/BDReader/source/Clip.cpp @@ -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; @@ -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); @@ -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 { @@ -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; @@ -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) @@ -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); @@ -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; @@ -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; @@ -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; } @@ -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() diff --git a/DirectShowFilters/BDReader/source/Clip.h b/DirectShowFilters/BDReader/source/Clip.h index 79aeb09569f..cb9cbd5bdd6 100644 --- a/DirectShowFilters/BDReader/source/Clip.h +++ b/DirectShowFilters/BDReader/source/Clip.h @@ -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(); @@ -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; @@ -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 @@ -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 diff --git a/DirectShowFilters/BDReader/source/DeMultiplexer.cpp b/DirectShowFilters/BDReader/source/DeMultiplexer.cpp index 957a7fb9c22..771f1df06a0 100644 --- a/DirectShowFilters/BDReader/source/DeMultiplexer.cpp +++ b/DirectShowFilters/BDReader/source/DeMultiplexer.cpp @@ -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); @@ -996,10 +996,22 @@ void CDeMultiplexer::FillVideoH264PESPacket(CTsHeader* header, CAutoPtr 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(); @@ -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(); } } @@ -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: diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp index fa2ade00410..cf317bc16ac 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.cpp @@ -35,12 +35,16 @@ #include #include #include +#include "HEVC\Hevc.h" +#include "HEVC\HevcNalDecode.h" // For more details for memory leak detection see the alloctracing.h header #include "..\..\alloctracing.h" extern void LogDebug(const char *fmt, ...) ; +#define LOG_HEVC_FHP //LogDebug + #define countof(array) (sizeof(array)/sizeof(array[0])) #define DNew new @@ -48,6 +52,14 @@ extern void LogDebug(const char *fmt, ...) ; #define TRUEHD_SYNC_WORD 0xf8726f +//AVC Chroma format IDC definitions +#define YUV400 0 +#define YUV420 1 +#define YUV422 2 +#define YUV444 3 + +using namespace HEVC; + // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 static const UINT8 thd_chancount[13] = {2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1}; static const UINT8 mlp_quants[16] = {16, 20, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; @@ -1665,6 +1677,187 @@ bool CFrameHeaderParser::Read(avchdr& h, int len, CMediaType* pmt) return true; } +bool CFrameHeaderParser::Read(hevchdr& h, int len, CMediaType* pmt) +{ + if ((len <= 6) || (len > 65534)) + return(false); //Sanity check + + memset(&h, 0, sizeof(h)); + h.progressive = true; + h.AvgTimePerFrame = 370000; //27 Hz + + while (GetRemaining() > 4 && (h.spslen == 0 || h.ppslen == 0 || h.vpslen == 0)) + { + const int nal_len = BitRead(32); + const INT64 nal_pos = GetPos(); + const INT64 next_nal = nal_pos + nal_len; + + NALUnitType nal_type = HevcNalDecode::processNALUnit(GetBufferPos(), nal_len, h); + + if (nal_type == NAL_FAIL) //NAL decoding error + { + return(false); + } + else if (nal_type == NAL_SPS) + { + LOG_HEVC_FHP("SPS found"); + //Copy SPS to buffer + h.sps = (BYTE*)malloc(nal_len); + if (h.sps == NULL) + { + //malloc error... + h.spslen = 0; + return(false); + } + ByteRead(h.sps, nal_len); + h.spslen = nal_len; + } + else if (nal_type == NAL_PPS) + { + LOG_HEVC_FHP("PPS found"); + //Copy PPS to new buffer + h.pps = (BYTE*)malloc(nal_len); + if (h.pps == NULL) + { + //malloc error... + h.ppslen = 0; + return(false); + } + ByteRead(h.pps, nal_len); + h.ppslen = nal_len; + } + else if (nal_type == NAL_VPS) + { + LOG_HEVC_FHP("VPS found"); + //Copy VPS to new buffer + h.vps = (BYTE*)malloc(nal_len); + if (h.vps == NULL) + { + //malloc error... + h.vpslen = 0; + return(false); + } + ByteRead(h.vps, nal_len); + h.vpslen = nal_len; + } + + Seek(next_nal); + } + + if (!h.spslen || !h.ppslen || !h.vpslen || h.height < 100 || h.width < 100 || h.AvgTimePerFrame < 1000) + return(false); + + if (!pmt) + return(true); + + { + + int extra = h.spslen + 4 + h.ppslen + 4 + h.vpslen + 4; + pmt->SetType(&MEDIATYPE_Video); + //pmt->SetSubtype(&MEDIASUBTYPE_H264); + pmt->SetSubtype(&HEVC_SubType); + pmt->formattype = FORMAT_MPEG2_VIDEO; + pmt->bTemporalCompression = true; + + int len = FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + extra; + MPEG2VIDEOINFO* vi = (MPEG2VIDEOINFO*)pmt->AllocFormatBuffer(len); + memset(vi, 0, len); + vi->hdr.AvgTimePerFrame = h.AvgTimePerFrame; + + /* + h.ar=h.width/h.height; + struct {DWORD x, y;} ar[] = {{h.width,h.height},{4,3},{16,9},{221,100},{h.width,h.height}}; + int i = min(max(h.ar, 1), 5)-1; + */ + struct { DWORD x, y; } ar[] = { {1,1},{1,1},{12,11},{10,11},{16,11},{40,33},{24,11},{20,11},{32,11},{80,33},{18,11},{15,11},{64,33},{160,99},{1,1},{1,1} }; + if (h.ar == 255) + { + // make sure that both are 0 or none + if (h.arx == 0 || h.ary == 0) + h.arx = h.ary = 0; + // h.arx and h.ary now contain sample aspect ratio + } + else if (h.ar < 1 || h.ar > 13) + { + // aspect ratio unspecified or reserved + h.ar = 0; + h.arx = h.ary = 0; + } + else + { + // use preset aspect ratio + h.arx = ar[h.ar].x; + h.ary = ar[h.ar].y; + } + + h.arx *= h.width; + h.ary *= h.height; + + DWORD a = h.arx, b = h.ary; + while (a) { DWORD tmp = a; a = b % tmp; b = tmp; } + if (b) h.arx /= b, h.ary /= b; + vi->hdr.dwPictAspectRatioX = h.arx; + vi->hdr.dwPictAspectRatioY = h.ary; + vi->hdr.bmiHeader.biSize = sizeof(vi->hdr.bmiHeader); + vi->hdr.bmiHeader.biWidth = h.width; + vi->hdr.bmiHeader.biHeight = h.height; + vi->hdr.rcSource.right = h.width; + vi->hdr.rcSource.bottom = h.height; + vi->hdr.rcTarget.right = h.width; + vi->hdr.rcTarget.bottom = h.height; + vi->hdr.bmiHeader.biCompression = 'CVEH'; + vi->hdr.bmiHeader.biPlanes = 1; + + + switch (h.chromaFormat) + { + case YUV420: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + (h.chromaDepth / 2); + break; + case YUV422: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + h.chromaDepth; + break; + case YUV444: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + (2 * h.chromaDepth); + break; + case YUV400: //Monochrome + vi->hdr.bmiHeader.biBitCount = h.lumaDepth; + break; + default: + vi->hdr.bmiHeader.biBitCount = h.lumaDepth + (h.chromaDepth / 2); + } + + vi->hdr.bmiHeader.biClrUsed = 0; + vi->hdr.bmiHeader.biSizeImage = DIBSIZE(vi->hdr.bmiHeader); + vi->dwProfile = h.profile; + vi->dwFlags = 0; + vi->dwLevel = h.level; + vi->cbSequenceHeader = extra; + vi->dwStartTimeCode = 0; + BYTE* p = (BYTE*)&vi->dwSequenceHeader[0]; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + memcpy(p, h.sps, (size_t)h.spslen); + p += h.spslen; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + memcpy(p, h.pps, (size_t)h.ppslen); + p += h.ppslen; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 1; + memcpy(p, h.vps, (size_t)h.vpslen); + + pmt->SetFormat((BYTE*)vi, len); + } + + return true; +} bool CFrameHeaderParser::Read(vc1hdr& h, int len, CMediaType* pmt) { @@ -1994,10 +2187,10 @@ bool CFrameHeaderParser::Read(bdlpcmhdr& h, int len, CMediaType* pmt) wfe.Samples.wSamplesPerBlock = 0; wfe.Samples.wValidBitsPerSample = bitspersample[h.bitpersample]; - wfe.SubFormat = MEDIASUBTYPE_PCM; + wfe.SubFormat = MEDIASUBTYPE_BD_LPCM_AUDIO; //MEDIASUBTYPE_PCM; pmt->majortype = MEDIATYPE_Audio; - pmt->subtype = MEDIASUBTYPE_PCM; + pmt->subtype = MEDIASUBTYPE_BD_LPCM_AUDIO; //MEDIASUBTYPE_PCM; pmt->formattype = FORMAT_WaveFormatEx; pmt->SetFormat((BYTE*)&wfe, sizeof(wfe)); @@ -2042,4 +2235,3 @@ void CFrameHeaderParser::DumpAvcHeader(avchdr h) */ LogDebug("================================="); } - diff --git a/DirectShowFilters/BDReader/source/FrameHeaderParser.h b/DirectShowFilters/BDReader/source/FrameHeaderParser.h index f539e750fa7..9247ce42845 100644 --- a/DirectShowFilters/BDReader/source/FrameHeaderParser.h +++ b/DirectShowFilters/BDReader/source/FrameHeaderParser.h @@ -29,6 +29,11 @@ #include #include "GolombBuffer.h" +#include "HEVC\Hevc.h" +#include "HEVC\HevcNalDecode.h" + +using namespace HEVC; + static const byte pixel_aspect[17][2]={ {0, 1}, {1, 1}, @@ -429,7 +434,7 @@ struct BasicVideoInfo } }; -class CFrameHeaderParser:public CGolombBuffer +class CFrameHeaderParser:public CGolombBuffer, public HEVC::HevcNalDecode { int m_tslen; // transport stream packet length (188 or 192 bytes, auto-detected) @@ -460,6 +465,7 @@ class CFrameHeaderParser:public CGolombBuffer bool Read(vc1hdr& h, int len, CMediaType* pmt = NULL); bool Read(bdlpcmhdr& h, int len, CMediaType* pmt = NULL); bool Read(thdhdr& h, int len, CMediaType* pmt = NULL); + bool Read(hevchdr& h, int len, CMediaType* pmt); void RemoveMpegEscapeCode(BYTE* dst, BYTE* src, int length); diff --git a/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp new file mode 100644 index 00000000000..838dbf147a8 --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.cpp @@ -0,0 +1,189 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + + +#include "BitstreamReader.h" + +#include +#include +#include + + +BitstreamReader::BitstreamReader(const uint8_t *ptr, std::size_t size): + m_ptr(ptr) + ,m_size(size) + ,m_posBase(0) + ,m_posInBase(CHAR_BIT - 1) +{ +} + +std::size_t BitstreamReader::available() +{ + return (m_size - m_posBase -1) * CHAR_BIT + m_posInBase + 1; +} + +std::size_t BitstreamReader::availableInNalU() +{ + std::size_t pos = m_posBase; + if(m_posInBase) + pos++; + for(; pos<(m_size - 3); pos++) + { + bool naluFinded = m_ptr[pos] == 0 && m_ptr[pos+1] == 0 && m_ptr[pos+2] == 1; + + if(!naluFinded) + { + if(m_size - pos >= 4 && m_ptr[pos] == 0 && m_ptr[pos+1] == 0 && m_ptr[pos+2] == 0 && m_ptr[pos+3] == 1) + naluFinded = true; + } + + if(naluFinded) + { + return (pos - m_posBase - 1) * CHAR_BIT + m_posInBase + 1; + } + + } + + return m_size; +} + + +bool BitstreamReader::getBit() +{ + if(m_posBase >= m_size) + throw std::runtime_error("BitstreamReader: not enough data"); + + bool res = (m_ptr[m_posBase] & (1 << m_posInBase)) != 0; + + m_posInBase--; + + if(m_posInBase > CHAR_BIT) + { + m_posInBase = CHAR_BIT-1; + m_posBase++; + + if(m_posBase >= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + } + + return res; +} + + +uint32_t BitstreamReader::getBits(std::size_t num) +{ + assert(num <= 32); + + uint32_t result = 0; + for(std::size_t i=0; i= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + + uint32_t scipBytes = (uint32_t)(num / 8); + + + while(scipBytes) + { + scipBytes--; + m_posBase++; + if(m_posBase >= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + } + + if(m_posInBase > num % 8) + m_posInBase -= num % 8; + else + { + m_posBase++; + m_posInBase = m_posInBase - num % 8 + 8; + } + +} + +uint32_t BitstreamReader::showBits(std::size_t num) +{ + assert(num <= 32); + + std::size_t posBasePrev = m_posBase; + std::size_t posInBasePrev = m_posInBase; + + uint32_t result = 0; + for(std::size_t i=0; i= 32) + return 0; +// throw std::range_error("Golomb: size of value more then 32 bits"); + + return (1 << numZeroBits) - 1 + getBits(numZeroBits); +} + + + +int32_t BitstreamReader::getGolombS() +{ + int32_t buf = getGolombU(); + + if (buf & 1) + buf = (buf + 1) >> 1; + else + buf = -(buf >> 1); + + return buf; +} + diff --git a/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h new file mode 100644 index 00000000000..556ba2ebcf8 --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/BitstreamReader.h @@ -0,0 +1,54 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#ifndef BITSTREAM_READER_H_ +#define BITSTREAM_READER_H_ + +#include +#include + +class BitstreamReader +{ +public: + BitstreamReader(const uint8_t *ptr, std::size_t size); + bool getBit(); + uint32_t getBits(std::size_t num); + void skipBits(std::size_t num); + uint32_t showBits(std::size_t num); + uint32_t getGolombU(); + int32_t getGolombS(); + + std::size_t available(); + std::size_t availableInNalU(); + +private: + const uint8_t *m_ptr; + std::size_t m_size; + std::size_t m_posBase; + std::size_t m_posInBase; +}; + + +#endif \ No newline at end of file diff --git a/DirectShowFilters/BDReader/source/HEVC/Hevc.cpp b/DirectShowFilters/BDReader/source/HEVC/Hevc.cpp new file mode 100644 index 00000000000..25cffabeb02 --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/Hevc.cpp @@ -0,0 +1,339 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#include "Hevc.h" + +#include + +using namespace HEVC; + +NALUnit::NALUnit(NALUnitType type): + m_nalUnitType(type) + ,m_processFailed(false) +{ +} + + +NALUnit::~NALUnit() +{ +} + + +NALUnitType NALUnit::getType() const +{ + return m_nalUnitType; +} + + + +HEVC::VPS::VPS(): NALUnit(HEVC::NAL_VPS) +{ + toDefault(); +} + + +HEVC::SPS::SPS(): NALUnit(NAL_SPS) +{ + toDefault(); +} + + +HEVC::PPS::PPS(): NALUnit(NAL_PPS) +{ + toDefault(); +}; + + +HEVC::AUD::AUD(): NALUnit(NAL_AUD) +{ + toDefault(); +}; + + +void ProfileTierLevel::toDefault() +{ + general_profile_space = 0; + general_tier_flag = 0; + general_profile_idc = 0; + general_profile_compatibility_flag[32]; + general_progressive_source_flag = 0; + general_interlaced_source_flag = 0; + general_non_packed_constraint_flag = 0; + general_frame_only_constraint_flag = 0; + general_level_idc = 0; + sub_layer_profile_present_flag.clear(); + sub_layer_level_present_flag.clear(); + sub_layer_profile_space.clear(); + sub_layer_tier_flag.clear(); + sub_layer_profile_idc.clear(); + sub_layer_profile_compatibility_flag.clear(); + sub_layer_progressive_source_flag.clear(); + sub_layer_interlaced_source_flag.clear(); + sub_layer_non_packed_constraint_flag.clear(); + sub_layer_frame_only_constraint_flag.clear(); + sub_layer_level_idc.clear(); +} + + +void SubLayerHrdParameters::toDefault() +{ + bit_rate_value_minus1.clear(); + cpb_size_value_minus1.clear(); + cpb_size_du_value_minus1.clear(); + bit_rate_du_value_minus1.clear(); + cbr_flag.clear(); +} + + +void HrdParameters::toDefault() +{ + nal_hrd_parameters_present_flag = 0; + vcl_hrd_parameters_present_flag = 0; + sub_pic_hrd_params_present_flag = 0; + tick_divisor_minus2 = 0; + du_cpb_removal_delay_increment_length_minus1 = 0; + sub_pic_cpb_params_in_pic_timing_sei_flag = 0; + dpb_output_delay_du_length_minus1 = 0; + bit_rate_scale = 0; + cpb_size_scale = 0; + cpb_size_du_scale = 0; + initial_cpb_removal_delay_length_minus1 = 23; + au_cpb_removal_delay_length_minus1 = 23; + dpb_output_delay_length_minus1 = 23; + fixed_pic_rate_general_flag.clear(); + fixed_pic_rate_within_cvs_flag.clear(); + elemental_duration_in_tc_minus1.clear(); + low_delay_hrd_flag.clear(); + cpb_cnt_minus1.clear(); + nal_sub_layer_hrd_parameters.clear(); + vcl_sub_layer_hrd_parameters.clear(); +} + + +void ShortTermRefPicSet::toDefault() +{ + inter_ref_pic_set_prediction_flag = 0; + delta_idx_minus1 = 0; + delta_rps_sign = 0; + abs_delta_rps_minus1 = 0; + used_by_curr_pic_flag.clear(); + use_delta_flag.clear(); + num_negative_pics = 0; + num_positive_pics = 0; + delta_poc_s0_minus1.clear(); + used_by_curr_pic_s0_flag.clear(); + delta_poc_s1_minus1.clear(); + used_by_curr_pic_s1_flag.clear(); +} + + + +void VuiParameters::toDefault() +{ + aspect_ratio_info_present_flag = 0; + aspect_ratio_idc = 0; + sar_width = 0; + sar_height = 0; + overscan_info_present_flag = 0; + overscan_appropriate_flag = 0; + video_signal_type_present_flag = 0; + video_format = 5; + video_full_range_flag = 0; + colour_description_present_flag = 0; + colour_primaries = 2; + transfer_characteristics = 2; + matrix_coeffs = 2; + chroma_loc_info_present_flag = 0; + chroma_sample_loc_type_top_field = 0; + chroma_sample_loc_type_bottom_field = 0; + neutral_chroma_indication_flag = 0; + field_seq_flag = 0; + frame_field_info_present_flag = 0; + default_display_window_flag = 0; + def_disp_win_left_offset = 0; + def_disp_win_right_offset = 0; + def_disp_win_top_offset = 0; + def_disp_win_bottom_offset = 0; + vui_timing_info_present_flag = 0; + vui_num_units_in_tick = 0; + vui_time_scale = 0; + vui_poc_proportional_to_timing_flag = 0; + vui_num_ticks_poc_diff_one_minus1 = 0; + vui_hrd_parameters_present_flag = 0; + hrd_parameters.toDefault(); + bitstream_restriction_flag = 0; + tiles_fixed_structure_flag = 0; + motion_vectors_over_pic_boundaries_flag = 0; + restricted_ref_pic_lists_flag = 0; + min_spatial_segmentation_idc = 0; + max_bytes_per_pic_denom = 2; + max_bits_per_min_cu_denom = 1; + log2_max_mv_length_horizontal = 15; + log2_max_mv_length_vertical = 15; +} + + + +void VPS::toDefault() +{ + vps_video_parameter_set_id = 0; + vps_max_layers_minus1 = 0; + vps_max_sub_layers_minus1 = 0; + vps_temporal_id_nesting_flag = 0; + profile_tier_level.toDefault(); + vps_sub_layer_ordering_info_present_flag = 0; + vps_max_dec_pic_buffering_minus1.clear(); + vps_max_num_reorder_pics.clear(); + vps_max_latency_increase_plus1.clear(); + vps_max_layer_id = 0; + vps_num_layer_sets_minus1 = 0; + layer_id_included_flag.clear(); + vps_timing_info_present_flag = 0; + vps_num_units_in_tick = 0; + vps_time_scale = 0; + vps_poc_proportional_to_timing_flag = 0; + vps_num_ticks_poc_diff_one_minus1 = 0; + vps_num_hrd_parameters = 0; + hrd_layer_set_idx.clear(); + cprms_present_flag.clear(); + hrd_parameters.clear(); + vps_extension_flag = 0; +} + + +void SPS::toDefault() +{ + sps_video_parameter_set_id = 0; + sps_max_sub_layers_minus1 = 0; + sps_temporal_id_nesting_flag = 0; + profile_tier_level.toDefault(); + sps_seq_parameter_set_id = 0; + chroma_format_idc = 0; + separate_colour_plane_flag = 0; + pic_width_in_luma_samples = 0; + pic_height_in_luma_samples = 0; + conformance_window_flag = 0; + conf_win_left_offset = 0; + conf_win_right_offset = 0; + conf_win_top_offset = 0; + conf_win_bottom_offset = 0; + bit_depth_luma_minus8 = 0; + bit_depth_chroma_minus8 = 0; + log2_max_pic_order_cnt_lsb_minus4 = 0; + sps_sub_layer_ordering_info_present_flag = 0; + sps_max_dec_pic_buffering_minus1.clear(); + sps_max_num_reorder_pics.clear(); + sps_max_latency_increase_plus1.clear(); + log2_min_luma_coding_block_size_minus3 = 0; + log2_diff_max_min_luma_coding_block_size = 0; + log2_min_transform_block_size_minus2 = 0; + log2_diff_max_min_transform_block_size = 0; + max_transform_hierarchy_depth_inter = 0; + max_transform_hierarchy_depth_intra = 0; + scaling_list_enabled_flag = 0; + scaling_list_data.toDefault(); + sps_scaling_list_data_present_flag = 0; + amp_enabled_flag = 0; + sample_adaptive_offset_enabled_flag = 0; + pcm_enabled_flag = 0; + pcm_sample_bit_depth_luma_minus1 = 0; + pcm_sample_bit_depth_chroma_minus1 = 0; + log2_min_pcm_luma_coding_block_size_minus3 = 0; + log2_diff_max_min_pcm_luma_coding_block_size = 0; + pcm_loop_filter_disabled_flag = 0; + num_short_term_ref_pic_sets = 0; + short_term_ref_pic_set.clear(); + long_term_ref_pics_present_flag = 0; + num_long_term_ref_pics_sps = 0; + lt_ref_pic_poc_lsb_sps.clear(); + used_by_curr_pic_lt_sps_flag.clear(); + sps_temporal_mvp_enabled_flag = 0; + strong_intra_smoothing_enabled_flag = 0; + vui_parameters_present_flag = 0; + vui_parameters.toDefault(); + sps_extension_flag = 0; +} + + + +void PPS::toDefault() +{ + pps_pic_parameter_set_id = 0; + pps_seq_parameter_set_id = 0; + dependent_slice_segments_enabled_flag = 0; + output_flag_present_flag = 0; + num_extra_slice_header_bits = 0; + sign_data_hiding_flag = 0; + cabac_init_present_flag = 0; + num_ref_idx_l0_default_active_minus1 = 0; + num_ref_idx_l1_default_active_minus1 = 0; + init_qp_minus26 = 0; + constrained_intra_pred_flag = 0; + transform_skip_enabled_flag = 0; + cu_qp_delta_enabled_flag = 0; + diff_cu_qp_delta_depth = 0; + pps_cb_qp_offset = 0; + pps_cr_qp_offset = 0; + pps_slice_chroma_qp_offsets_present_flag = 0; + weighted_pred_flag = 0; + weighted_bipred_flag = 0; + transquant_bypass_enabled_flag = 0; + tiles_enabled_flag = 0; + entropy_coding_sync_enabled_flag = 0; + num_tile_columns_minus1 = 0; + num_tile_rows_minus1 = 0; + uniform_spacing_flag = 1; + column_width_minus1.clear(); + row_height_minus1.clear(); + loop_filter_across_tiles_enabled_flag = 0; + pps_loop_filter_across_slices_enabled_flag = 0; + deblocking_filter_control_present_flag = 0; + deblocking_filter_override_enabled_flag = 0; + pps_deblocking_filter_disabled_flag = 0; + pps_beta_offset_div2 = 0; + pps_tc_offset_div2 = 0; + pps_scaling_list_data_present_flag = 0; + lists_modification_present_flag = 0; + log2_parallel_merge_level_minus2 = 0; + slice_segment_header_extension_present_flag = 0; + pps_extension_flag = 0; +} + + +void ScalingListData::toDefault() +{ + scaling_list_delta_coef.clear(); + scaling_list_pred_mode_flag.clear(); + scaling_list_pred_matrix_id_delta.clear(); + scaling_list_dc_coef_minus8.clear(); +} + + +void AUD::toDefault() +{ + pic_type = 0; +} + + diff --git a/DirectShowFilters/BDReader/source/HEVC/Hevc.h b/DirectShowFilters/BDReader/source/HEVC/Hevc.h new file mode 100644 index 00000000000..e9d48ecdc7e --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/Hevc.h @@ -0,0 +1,476 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#ifndef HEVC_H_ +#define HEVC_H_ + +//#include +#include +#include +#include +#include +#include + +namespace HEVC +{ + + struct hevchdr + { + uint8_t profile, level; + uint64_t chromaFormat; + uint16_t lumaDepth, chromaDepth; + unsigned int width, height; + bool progressive; + uint8_t * sps; + uint8_t * pps; + uint8_t * vps; + __int64 spslen; + __int64 ppslen; + __int64 vpslen; + __int64 AvgTimePerFrame; + int arx, ary; + uint8_t ar; + hevchdr() + { + profile = 0; + level = 0; + chromaFormat = 0; + lumaDepth = 0; + chromaDepth = 0; + progressive = true; + sps = NULL; + pps = NULL; + vps = NULL; + spslen = 0; + ppslen = 0; + vpslen = 0; + AvgTimePerFrame = 370000; //27 Hz + ar = 0; + arx = 0; + ary = 0; + width = 0; + height = 0; + } + + ~hevchdr() + { + if (sps != NULL) free(sps); + if (pps != NULL) free(pps); + if (vps != NULL) free(vps); + sps = NULL; + pps = NULL; + vps = NULL; + } + }; + + enum NALUnitType + { + NAL_FAIL = -1, + NAL_TRAIL_N = 0, + NAL_TRAIL_R = 1, + NAL_TSA_N = 2, + NAL_TSA_R = 3, + NAL_STSA_N = 4, + NAL_STSA_R = 5, + NAL_RADL_N = 6, + NAL_RADL_R = 7, + NAL_RASL_N = 8, + NAL_RASL_R = 9, + NAL_BLA_W_LP = 16, + NAL_BLA_W_RADL = 17, + NAL_BLA_N_LP = 18, + NAL_IDR_W_RADL = 19, + NAL_IDR_N_LP = 20, + NAL_CRA_NUT = 21, + NAL_IRAP_VCL23 = 23, + NAL_VPS = 32, + NAL_SPS = 33, + NAL_PPS = 34, + NAL_AUD = 35, + NAL_EOS_NUT = 36, + NAL_EOB_NUT = 37, + NAL_FD_NUT = 38, + NAL_SEI_PREFIX = 39, + NAL_SEI_SUFFIX = 40, + NAL_RESERVED = 255 + }; + + class ProfileTierLevel + { + public: + uint8_t general_profile_space; + uint8_t general_tier_flag; + uint8_t general_profile_idc; + uint8_t general_profile_compatibility_flag[32]; + uint8_t general_progressive_source_flag; + uint8_t general_interlaced_source_flag; + uint8_t general_non_packed_constraint_flag; + uint8_t general_frame_only_constraint_flag; + uint8_t general_level_idc; + std::vector sub_layer_profile_present_flag; + std::vector sub_layer_level_present_flag; + std::vector sub_layer_profile_space; + std::vector sub_layer_tier_flag; + std::vector sub_layer_profile_idc; + std::vector< std::vector< uint8_t> > + sub_layer_profile_compatibility_flag; + std::vector sub_layer_progressive_source_flag; + std::vector sub_layer_interlaced_source_flag; + std::vector sub_layer_non_packed_constraint_flag; + std::vector sub_layer_frame_only_constraint_flag; + std::vector sub_layer_level_idc; + + void toDefault(); + + //bool operator == (const ProfileTierLevel &) const; + }; + + class SubLayerHrdParameters + { + public: + std::vector bit_rate_value_minus1; + std::vector cpb_size_value_minus1; + std::vector cpb_size_du_value_minus1; + std::vector bit_rate_du_value_minus1; + std::vector cbr_flag; + + void toDefault(); + + //bool operator == (const SubLayerHrdParameters &) const; + }; + + + class ScalingListData + { + public: + std::vector< std::vector< uint8_t> > scaling_list_pred_mode_flag; + std::vector< std::vector< uint32_t> > scaling_list_pred_matrix_id_delta; + std::vector< std::vector< uint32_t> > scaling_list_dc_coef_minus8; + std::vector > > + scaling_list_delta_coef; + + void toDefault(); + + //bool operator == (const ScalingListData &) const; + }; + + class HrdParameters + { + public: + uint8_t nal_hrd_parameters_present_flag; + uint8_t vcl_hrd_parameters_present_flag; + uint8_t sub_pic_hrd_params_present_flag; + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t sub_pic_cpb_params_in_pic_timing_sei_flag; + uint8_t dpb_output_delay_du_length_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + std::vector fixed_pic_rate_general_flag; + std::vector fixed_pic_rate_within_cvs_flag; + std::vector elemental_duration_in_tc_minus1; + std::vector low_delay_hrd_flag; + std::vector cpb_cnt_minus1; + std::vector + nal_sub_layer_hrd_parameters; + std::vector + vcl_sub_layer_hrd_parameters; + + void toDefault(); + + //bool operator == (const HrdParameters &) const; + }; + + class ShortTermRefPicSet + { + public: + uint8_t inter_ref_pic_set_prediction_flag; + uint32_t delta_idx_minus1; + uint8_t delta_rps_sign; + uint32_t abs_delta_rps_minus1; + std::vector used_by_curr_pic_flag; + std::vector use_delta_flag; + uint32_t num_negative_pics; + uint32_t num_positive_pics; + std::vector delta_poc_s0_minus1; + std::vector used_by_curr_pic_s0_flag; + std::vector delta_poc_s1_minus1; + std::vector used_by_curr_pic_s1_flag; + + void toDefault(); + + //bool operator == (const ShortTermRefPicSet &) const; + }; + + class RefPicListModification + { + public: + uint8_t ref_pic_list_modification_flag_l0; + std::vector list_entry_l0; + uint8_t ref_pic_list_modification_flag_l1; + std::vector list_entry_l1; + + void toDefault(); + + //bool operator == (const RefPicListModification &) const; + }; + + class VuiParameters + { + public: + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coeffs; + uint8_t chroma_loc_info_present_flag; + uint32_t chroma_sample_loc_type_top_field; + uint32_t chroma_sample_loc_type_bottom_field; + uint8_t neutral_chroma_indication_flag; + uint8_t field_seq_flag; + uint8_t frame_field_info_present_flag; + uint8_t default_display_window_flag; + uint32_t def_disp_win_left_offset; + uint32_t def_disp_win_right_offset; + uint32_t def_disp_win_top_offset; + uint32_t def_disp_win_bottom_offset; + uint8_t vui_timing_info_present_flag; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + uint8_t vui_poc_proportional_to_timing_flag; + uint32_t vui_num_ticks_poc_diff_one_minus1; + uint8_t vui_hrd_parameters_present_flag; + HrdParameters hrd_parameters; + uint8_t bitstream_restriction_flag; + uint8_t tiles_fixed_structure_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint8_t restricted_ref_pic_lists_flag; + uint32_t min_spatial_segmentation_idc; + uint32_t max_bytes_per_pic_denom; + uint32_t max_bits_per_min_cu_denom; + uint32_t log2_max_mv_length_horizontal; + uint32_t log2_max_mv_length_vertical; + + void toDefault(); + + //bool operator == (const VuiParameters &) const; + + }; + + + + class NALUnit + { + public: + NALUnit(NALUnitType type); + virtual ~NALUnit(); + virtual NALUnitType getType() const; + + std::shared_ptr copy() const; + + bool m_processFailed; + + NALUnitType m_nalUnitType; + }; + + + + class VPS: public NALUnit + { + public: + VPS(); + uint8_t vps_video_parameter_set_id; + uint8_t vps_max_layers_minus1; + uint8_t vps_max_sub_layers_minus1; + uint8_t vps_temporal_id_nesting_flag; + ProfileTierLevel profile_tier_level; + uint8_t vps_sub_layer_ordering_info_present_flag; + std::vector vps_max_dec_pic_buffering_minus1; + std::vector vps_max_num_reorder_pics; + std::vector vps_max_latency_increase_plus1; + uint8_t vps_max_layer_id; + uint32_t vps_num_layer_sets_minus1; + std::vector > + layer_id_included_flag; + uint8_t vps_timing_info_present_flag; + uint32_t vps_num_units_in_tick; + uint32_t vps_time_scale; + uint8_t vps_poc_proportional_to_timing_flag; + uint32_t vps_num_ticks_poc_diff_one_minus1; + uint32_t vps_num_hrd_parameters; + std::vector hrd_layer_set_idx; + std::vector cprms_present_flag; + std::vector + hrd_parameters; + uint8_t vps_extension_flag; + + void toDefault(); + //bool operator == (const VPS &) const; + }; + + + class SPS: public NALUnit + { + public: + SPS(); + uint8_t sps_video_parameter_set_id; + uint8_t sps_max_sub_layers_minus1; + uint8_t sps_temporal_id_nesting_flag; + ProfileTierLevel profile_tier_level; + uint32_t sps_seq_parameter_set_id; + uint32_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + uint32_t pic_width_in_luma_samples; + uint32_t pic_height_in_luma_samples; + uint8_t conformance_window_flag; + uint32_t conf_win_left_offset; + uint32_t conf_win_right_offset; + uint32_t conf_win_top_offset; + uint32_t conf_win_bottom_offset; + uint32_t bit_depth_luma_minus8; + uint32_t bit_depth_chroma_minus8; + uint32_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t sps_sub_layer_ordering_info_present_flag; + std::vector sps_max_dec_pic_buffering_minus1; + std::vector sps_max_num_reorder_pics; + std::vector sps_max_latency_increase_plus1; + uint32_t log2_min_luma_coding_block_size_minus3; + uint32_t log2_diff_max_min_luma_coding_block_size; + uint32_t log2_min_transform_block_size_minus2; + uint32_t log2_diff_max_min_transform_block_size; + uint32_t max_transform_hierarchy_depth_inter; + uint32_t max_transform_hierarchy_depth_intra; + uint8_t scaling_list_enabled_flag; + uint8_t sps_scaling_list_data_present_flag; + ScalingListData scaling_list_data; + uint8_t amp_enabled_flag; + uint8_t sample_adaptive_offset_enabled_flag; + uint8_t pcm_enabled_flag; + uint8_t pcm_sample_bit_depth_luma_minus1; + uint8_t pcm_sample_bit_depth_chroma_minus1; + uint32_t log2_min_pcm_luma_coding_block_size_minus3; + uint32_t log2_diff_max_min_pcm_luma_coding_block_size; + uint8_t pcm_loop_filter_disabled_flag; + uint32_t num_short_term_ref_pic_sets; + std::vector + short_term_ref_pic_set; + uint8_t long_term_ref_pics_present_flag; + uint32_t num_long_term_ref_pics_sps; + std::vector lt_ref_pic_poc_lsb_sps; + std::vector used_by_curr_pic_lt_sps_flag; + uint8_t sps_temporal_mvp_enabled_flag; + uint8_t strong_intra_smoothing_enabled_flag; + uint8_t vui_parameters_present_flag; + VuiParameters vui_parameters; + uint8_t sps_extension_flag; + + void toDefault(); + + //bool operator == (const SPS &) const; + }; + + + class PPS: public NALUnit + { + public: + PPS(); + + uint32_t pps_pic_parameter_set_id; + uint32_t pps_seq_parameter_set_id; + uint8_t dependent_slice_segments_enabled_flag; + uint8_t output_flag_present_flag; + uint8_t num_extra_slice_header_bits; + uint8_t sign_data_hiding_flag; + uint8_t cabac_init_present_flag; + uint32_t num_ref_idx_l0_default_active_minus1; + uint32_t num_ref_idx_l1_default_active_minus1; + int32_t init_qp_minus26; + uint8_t constrained_intra_pred_flag; + uint8_t transform_skip_enabled_flag; + uint8_t cu_qp_delta_enabled_flag; + uint32_t diff_cu_qp_delta_depth; + int32_t pps_cb_qp_offset; + int32_t pps_cr_qp_offset; + uint8_t pps_slice_chroma_qp_offsets_present_flag; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_flag; + uint8_t transquant_bypass_enabled_flag; + uint8_t tiles_enabled_flag; + uint8_t entropy_coding_sync_enabled_flag; + uint32_t num_tile_columns_minus1; + uint32_t num_tile_rows_minus1; + uint8_t uniform_spacing_flag; + std::vector + column_width_minus1; + std::vector + row_height_minus1; + uint8_t loop_filter_across_tiles_enabled_flag; + uint8_t pps_loop_filter_across_slices_enabled_flag; + uint8_t deblocking_filter_control_present_flag; + uint8_t deblocking_filter_override_enabled_flag; + uint8_t pps_deblocking_filter_disabled_flag; + uint32_t pps_beta_offset_div2; + uint32_t pps_tc_offset_div2; + uint8_t pps_scaling_list_data_present_flag; + ScalingListData + scaling_list_data; + uint8_t lists_modification_present_flag; + int32_t log2_parallel_merge_level_minus2; + uint8_t slice_segment_header_extension_present_flag; + uint8_t pps_extension_flag; + + void toDefault(); + + //bool operator == (const PPS &) const; + }; + + + + + class AUD: public NALUnit + { + public: + AUD(); + + uint8_t pic_type; + void toDefault(); + }; + + +} + +#endif diff --git a/DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp b/DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp new file mode 100644 index 00000000000..d051178003e --- /dev/null +++ b/DirectShowFilters/BDReader/source/HEVC/HevcNalDecode.cpp @@ -0,0 +1,749 @@ +// Copyright (C) 2016 Team MediaPortal +// http://www.team-mediaportal.com +// +// MediaPortal is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// MediaPortal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with MediaPortal. If not, see . + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#include "HevcNalDecode.h" + +#include +#include +#include + +#include + +#include + +extern void LogDebug(const char *fmt, ...) ; + +using namespace HEVC; + +NALUnitType HevcNalDecode::processNALUnit(const uint8_t *pdata, std::size_t size, hevchdr& h) +{ + //Note: 'emulation_prevention_three_byte' removal is dealt with inside the BitstreamReader + BitstreamReader bs(pdata, size); + + NALUnitType type = NAL_FAIL; + + try + { + type = processNALUnitHeader(bs); + } + catch(...) + { + LogDebug("HevcNalDecode:processNALUnit exception ..."); + return NAL_FAIL; + } + + switch(type) + { + case NAL_SPS: + { + std::shared_ptr psps(new SPS); + try + { + processSPS(psps, bs); + } + catch(...) + { + LogDebug("HevcNalDecode:processSPS exception ..."); + return NAL_FAIL; + } + + //Assign values to hevchdr elements + h.chromaFormat = psps -> chroma_format_idc; + + h.width = psps -> pic_width_in_luma_samples; + h.height = psps -> pic_height_in_luma_samples; + if (h.height == 1088) h.height = 1080; // Prevent blur lines + + h.lumaDepth = psps -> bit_depth_luma_minus8 + 8; // bit_depth_luma_minus8 + h.chromaDepth = psps -> bit_depth_chroma_minus8 + 8; // bit_depth_chroma_minus8 + + h.progressive = (psps->profile_tier_level.general_progressive_source_flag > 0); + + h.profile = psps->profile_tier_level.general_profile_idc; + h.level = psps->profile_tier_level.general_level_idc; + + if(psps -> vui_parameters_present_flag) + { + if (psps->vui_parameters.aspect_ratio_info_present_flag) + { + h.ar = psps->vui_parameters.aspect_ratio_idc; + if(h.ar == 255) //EXTENDED_SAR + { + h.arx = psps->vui_parameters.sar_width; + h.ary = psps->vui_parameters.sar_height; + // make sure that both are 0 if one is 0 + if(h.arx == 0 || h.ary == 0) + { + h.arx = 0; + h.ary = 0; + } + } + else //Look up the aspect ratio from a table + { + struct {int x, y;} ar[] = {{0,0},{1,1},{12,11},{10,11},{16,11},{40,33},{24,11},{20,11},{32,11},{80,33},{18,11},{15,11},{64,33},{160,99},{4,3},{3,2},{2,1}}; + if(h.ar > 16) + { + // aspect ratio reserved + h.arx = 0; + h.ary = 0; + } + else + { + // use preset aspect ratio + h.arx = ar[h.ar].x; + h.ary = ar[h.ar].y; + } + } + + h.arx *= h.width; + h.ary *= h.height; + + uint32_t a = h.arx, b = h.ary; + while(a) {uint32_t tmp = a; a = b % tmp; b = tmp;} + if(b) h.arx /= b, h.ary /= b; + } + + if (psps->vui_parameters.vui_timing_info_present_flag) + { + if ((psps->vui_parameters.vui_time_scale > 0) && (psps->vui_parameters.vui_num_units_in_tick > 0)) + { + h.AvgTimePerFrame = (__int64)((10000000.0 * (double)psps->vui_parameters.vui_num_units_in_tick)/(double)psps->vui_parameters.vui_time_scale); + } + } + } + + if (h.arx == 0 && h.ary == 0) //Do something sensible if aspect ratio info not present + { + if (h.width > 0 && h.width > 0) + { + h.arx = h.width; + h.ary = h.height; + + uint32_t a = h.arx, b = h.ary; + while(a) {uint32_t tmp = a; a = b % tmp; b = tmp;} + if(b) h.arx /= b, h.ary /= b; + } + } + + break; + } + + default: {} //Do not decode any other NALs + }; + + return type; +} + +//Remove 'emulation_prevention_three_byte' characters and copy to new buffer +void HevcNalDecode::Remove3Byte(uint8_t* dst, const uint8_t* src, int length) +{ + int si=0; + int di=0; + while(si+23){ + dst[di++]= src[si++]; + dst[di++]= src[si++]; + } + else if(src[si]==0 && src[si+1]==0){ + if(src[si+2]==3){ //escape + dst[di++]= 0; + dst[di++]= 0; + si+=3; + continue; + } + else //next start code + return; + } + + dst[di++]= src[si++]; + } +} + + +NALUnitType HevcNalDecode::processNALUnitHeader(BitstreamReader &bs) +{ + //forbidden_zero_bit + bs.getBit(); + + NALUnitType type = (NALUnitType)bs.getBits(6); + + //nuh_layer_id + bs.getBits(6); + + //nuh_temporal_id_plus1 + bs.getBits(3); + return type; +} + +void HevcNalDecode::processSPS(std::shared_ptr psps, BitstreamReader &bs) +{ + psps -> sps_video_parameter_set_id = bs.getBits(4); + psps -> sps_max_sub_layers_minus1 = bs.getBits(3); + psps -> sps_temporal_id_nesting_flag = bs.getBits(1); + psps -> profile_tier_level = processProfileTierLevel(psps -> sps_max_sub_layers_minus1, bs); + + psps -> sps_seq_parameter_set_id = bs.getGolombU(); + psps -> chroma_format_idc = bs.getGolombU(); + + if(psps -> chroma_format_idc == 3) + psps -> separate_colour_plane_flag = bs.getBits(1); + else + psps -> separate_colour_plane_flag = 0; + + psps -> pic_width_in_luma_samples = bs.getGolombU(); + psps -> pic_height_in_luma_samples = bs.getGolombU(); + psps -> conformance_window_flag = bs.getBits(1); + + if(psps -> conformance_window_flag) + { + psps -> conf_win_left_offset = bs.getGolombU(); + psps -> conf_win_right_offset = bs.getGolombU(); + psps -> conf_win_top_offset = bs.getGolombU(); + psps -> conf_win_bottom_offset = bs.getGolombU(); + } + + psps -> bit_depth_luma_minus8 = bs.getGolombU(); + psps -> bit_depth_chroma_minus8 = bs.getGolombU(); + psps -> log2_max_pic_order_cnt_lsb_minus4 = bs.getGolombU(); + psps -> sps_sub_layer_ordering_info_present_flag = bs.getBits(1); + + psps -> sps_max_dec_pic_buffering_minus1.resize(psps -> sps_max_sub_layers_minus1 + 1, 0); + psps -> sps_max_num_reorder_pics.resize(psps -> sps_max_sub_layers_minus1 + 1, 0); + psps -> sps_max_latency_increase_plus1.resize(psps -> sps_max_sub_layers_minus1 + 1, 0); + + for(std::size_t i=(psps -> sps_sub_layer_ordering_info_present_flag ? 0 : psps -> sps_max_sub_layers_minus1); + i<=psps -> sps_max_sub_layers_minus1; + i++) + { + psps -> sps_max_dec_pic_buffering_minus1[i] = bs.getGolombU(); + psps -> sps_max_num_reorder_pics[i] = bs.getGolombU(); + psps -> sps_max_latency_increase_plus1[i] = bs.getGolombU(); + } + + psps -> log2_min_luma_coding_block_size_minus3 = bs.getGolombU(); + psps -> log2_diff_max_min_luma_coding_block_size = bs.getGolombU(); + psps -> log2_min_transform_block_size_minus2 = bs.getGolombU(); + psps -> log2_diff_max_min_transform_block_size = bs.getGolombU(); + psps -> max_transform_hierarchy_depth_inter = bs.getGolombU(); + psps -> max_transform_hierarchy_depth_intra = bs.getGolombU(); + + psps -> scaling_list_enabled_flag = bs.getBits(1); + if(psps -> scaling_list_enabled_flag) + { + psps -> sps_scaling_list_data_present_flag = bs.getBits(1); + if(psps -> sps_scaling_list_data_present_flag) + { + psps -> scaling_list_data = processScalingListData(bs); + } + } + + psps -> amp_enabled_flag = bs.getBits(1); + psps -> sample_adaptive_offset_enabled_flag = bs.getBits(1); + psps -> pcm_enabled_flag = bs.getBits(1); + + if(psps -> pcm_enabled_flag) + { + psps -> pcm_sample_bit_depth_luma_minus1 = bs.getBits(4); + psps -> pcm_sample_bit_depth_chroma_minus1 = bs.getBits(4); + psps -> log2_min_pcm_luma_coding_block_size_minus3 = bs.getGolombU(); + psps -> log2_diff_max_min_pcm_luma_coding_block_size = bs.getGolombU(); + psps -> pcm_loop_filter_disabled_flag = bs.getBits(1); + } + + psps -> num_short_term_ref_pic_sets = bs.getGolombU(); + + psps -> short_term_ref_pic_set.resize(psps -> num_short_term_ref_pic_sets); + for(std::size_t i=0; i num_short_term_ref_pic_sets; i++) + psps -> short_term_ref_pic_set[i] = processShortTermRefPicSet(i, psps -> num_short_term_ref_pic_sets, psps -> short_term_ref_pic_set, psps, bs); + + psps -> long_term_ref_pics_present_flag = bs.getBits(1); + if(psps -> long_term_ref_pics_present_flag) + { + psps -> num_long_term_ref_pics_sps = bs.getGolombU(); + psps -> lt_ref_pic_poc_lsb_sps.resize(psps -> num_long_term_ref_pics_sps); + psps -> used_by_curr_pic_lt_sps_flag.resize(psps -> num_long_term_ref_pics_sps); + + for(std::size_t i = 0; i num_long_term_ref_pics_sps; i++) + { + psps -> lt_ref_pic_poc_lsb_sps[i] = bs.getBits(psps -> log2_max_pic_order_cnt_lsb_minus4 + 4); + psps -> used_by_curr_pic_lt_sps_flag[i] = bs.getBits(1); + } + } + + psps -> sps_temporal_mvp_enabled_flag = bs.getBits(1); + psps -> strong_intra_smoothing_enabled_flag = bs.getBits(1); + psps -> vui_parameters_present_flag = bs.getBits(1); + + if(psps -> vui_parameters_present_flag) + { + psps -> vui_parameters = processVuiParameters(psps -> sps_max_sub_layers_minus1, bs); + } + + psps -> sps_extension_flag = bs.getBits(1); +} + + +//======================================================================= + +VuiParameters HevcNalDecode::processVuiParameters(std::size_t sps_max_sub_layers_minus1, BitstreamReader &bs) +{ + VuiParameters vui; + + vui.toDefault(); + + vui.aspect_ratio_idc = 0; + vui.sar_width = 0; + vui.sar_height = 0; + + + vui.aspect_ratio_info_present_flag = bs.getBits(1); + + if(vui.aspect_ratio_info_present_flag) + { + vui.aspect_ratio_idc = bs.getBits(8); + + if(vui.aspect_ratio_idc == 255) //EXTENDED_SAR + { + vui.sar_width = bs.getBits(16); + vui.sar_height = bs.getBits(16); + } + } + + + vui.overscan_info_present_flag = bs.getBits(1); + if(vui.overscan_info_present_flag) + vui.overscan_appropriate_flag = bs.getBits(1); + + vui.video_format = 5; + vui.video_full_range_flag = 0; + vui.colour_primaries = 2; + vui.transfer_characteristics = 2; + vui.matrix_coeffs = 2; + + vui.video_signal_type_present_flag = bs.getBits(1); + + if(vui.video_signal_type_present_flag) + { + vui.video_format = bs.getBits(3); + vui.video_full_range_flag = bs.getBits(1); + vui.colour_description_present_flag = bs.getBits(1); + + if(vui.colour_description_present_flag) + { + vui.colour_primaries = bs.getBits(8); + vui.transfer_characteristics = bs.getBits(8); + vui.matrix_coeffs = bs.getBits(8); + } + + } + + vui.chroma_sample_loc_type_top_field = 0; + vui.chroma_sample_loc_type_bottom_field = 0; + + vui.chroma_loc_info_present_flag = bs.getBits(1); + if(vui.chroma_loc_info_present_flag) + { + vui.chroma_sample_loc_type_top_field = bs.getGolombU(); + vui.chroma_sample_loc_type_bottom_field = bs.getGolombU(); + } + + + vui.neutral_chroma_indication_flag = bs.getBits(1); + vui.field_seq_flag = bs.getBits(1); + vui.frame_field_info_present_flag = bs.getBits(1); + vui.default_display_window_flag = bs.getBits(1); + + vui.def_disp_win_left_offset = 0; + vui.def_disp_win_right_offset = 0; + vui.def_disp_win_right_offset = 0; + vui.def_disp_win_bottom_offset = 0; + + if(vui.default_display_window_flag) + { + vui.def_disp_win_left_offset = bs.getGolombU(); + vui.def_disp_win_right_offset = bs.getGolombU(); + vui.def_disp_win_top_offset = bs.getGolombU(); + vui.def_disp_win_bottom_offset = bs.getGolombU(); + } + + vui.vui_timing_info_present_flag = bs.getBits(1); + + if(vui.vui_timing_info_present_flag) + { + vui.vui_num_units_in_tick = bs.getBits(32); + vui.vui_time_scale = bs.getBits(32); + vui.vui_poc_proportional_to_timing_flag = bs.getBits(1); + + if(vui.vui_poc_proportional_to_timing_flag) + vui.vui_num_ticks_poc_diff_one_minus1 = bs.getGolombU(); + + vui.vui_hrd_parameters_present_flag = bs.getBits(1); + + if(vui.vui_hrd_parameters_present_flag) + vui.hrd_parameters = processHrdParameters(1, sps_max_sub_layers_minus1, bs); + } + + vui.bitstream_restriction_flag = bs.getBits(1); + + if(vui.bitstream_restriction_flag) + { + vui.tiles_fixed_structure_flag = bs.getBits(1); + vui.motion_vectors_over_pic_boundaries_flag = bs.getBits(1); + vui.restricted_ref_pic_lists_flag = bs.getBits(1); + + vui.min_spatial_segmentation_idc = bs.getGolombU(); + vui.max_bytes_per_pic_denom = bs.getGolombU(); + vui.max_bits_per_min_cu_denom = bs.getGolombU(); + vui.log2_max_mv_length_horizontal = bs.getGolombU(); + vui.log2_max_mv_length_vertical = bs.getGolombU(); + } + + return vui; +} + +//======================================================================= + +ProfileTierLevel HevcNalDecode::processProfileTierLevel(std::size_t max_sub_layers_minus1, BitstreamReader &bs) +{ + ProfileTierLevel ptl; + + ptl.toDefault(); + + ptl.general_profile_space = bs.getBits(2); + ptl.general_tier_flag = bs.getBits(1); + ptl.general_profile_idc = bs.getBits(5); + + for(std::size_t i=0; i<32; i++) + ptl.general_profile_compatibility_flag[i] = bs.getBits(1); + + ptl.general_progressive_source_flag = bs.getBits(1); + ptl.general_interlaced_source_flag = bs.getBits(1); + ptl.general_non_packed_constraint_flag = bs.getBits(1); + ptl.general_frame_only_constraint_flag = bs.getBits(1); + bs.getBits(32); + bs.getBits(12); + ptl.general_level_idc = bs.getBits(8); + + ptl.sub_layer_profile_present_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_level_present_flag.resize(max_sub_layers_minus1); + + for(std::size_t i=0; i 0) + { + for(std::size_t i=max_sub_layers_minus1; i<8; i++) + bs.getBits(2); + } + + ptl.sub_layer_profile_space.resize(max_sub_layers_minus1); + ptl.sub_layer_tier_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_profile_idc.resize(max_sub_layers_minus1); + ptl.sub_layer_profile_compatibility_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_progressive_source_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_interlaced_source_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_non_packed_constraint_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_frame_only_constraint_flag.resize(max_sub_layers_minus1); + ptl.sub_layer_level_idc.resize(max_sub_layers_minus1); + + for(std::size_t i=0; i= 2) + sc.scaling_list_dc_coef_minus8[sizeId-2].resize(6); + } + + for(std::size_t matrixId = 0; matrixId<(size_t)((sizeId == 3)?2:6); matrixId++) + { + sc.scaling_list_pred_mode_flag[sizeId][matrixId] = bs.getBits(1); + if(!sc.scaling_list_pred_mode_flag[sizeId][matrixId]) + sc.scaling_list_pred_matrix_id_delta[sizeId][matrixId] = bs.getGolombU(); + else + { + std::size_t nextCoef = 8; + std::size_t coefNum = std::min(64, (1 << (4 + (sizeId << 1)))); + if(sizeId > 1) + sc.scaling_list_dc_coef_minus8[sizeId-2][matrixId] = bs.getGolombS(); + + sc.scaling_list_delta_coef[sizeId][matrixId].resize(coefNum); + for(std::size_t i = 0; i < coefNum; i++) + sc.scaling_list_delta_coef[sizeId][matrixId][i] = bs.getGolombS(); + } + } + } + + return sc; +} + +//======================================================================= + +ShortTermRefPicSet HevcNalDecode::processShortTermRefPicSet(std::size_t stRpsIdx, std::size_t num_short_term_ref_pic_sets, const std::vector &refPicSets, std::shared_ptr psps, BitstreamReader &bs) +{ + ShortTermRefPicSet rpset; + + rpset.toDefault(); + + rpset.inter_ref_pic_set_prediction_flag = 0; + rpset.delta_idx_minus1 = 0; + if(stRpsIdx) + { + rpset.inter_ref_pic_set_prediction_flag = bs.getBits(1); + } + + if(rpset.inter_ref_pic_set_prediction_flag) + { + if(stRpsIdx == num_short_term_ref_pic_sets) + rpset.delta_idx_minus1 = bs.getGolombU(); + + rpset.delta_rps_sign = bs.getBits(1); + rpset.abs_delta_rps_minus1 = bs.getGolombU(); + + std::size_t RefRpsIdx = stRpsIdx - (rpset.delta_idx_minus1 + 1); + std::size_t NumDeltaPocs = 0; + + if(refPicSets[RefRpsIdx].inter_ref_pic_set_prediction_flag) + { + for(std::size_t i=0; i psps -> sps_max_dec_pic_buffering_minus1[psps -> sps_max_sub_layers_minus1]) + { + LogDebug("HevcNalDecode:ShortTermRefPicSet: num_negative_pics > sps_max_dec_pic_buffering_minus1"); + return rpset; + } + + if(rpset.num_positive_pics > psps -> sps_max_dec_pic_buffering_minus1[psps -> sps_max_sub_layers_minus1]) + { + LogDebug("HevcNalDecode:ShortTermRefPicSet: num_positive_pics > sps_max_dec_pic_buffering_minus1"); + return rpset; + } + + rpset.delta_poc_s0_minus1.resize(rpset.num_negative_pics); + rpset.used_by_curr_pic_s0_flag.resize(rpset.num_negative_pics); + + for(std::size_t i=0; i. + +// ======================================================================== +// The code in this file is derived from the 'HEVCESBrowser' project, +// a tool for analyzing HEVC(h265) bitstreams authored by 'virinext'. +// See https://github.com/virinext/hevcesbrowser +// and http://www.codeproject.com/Tips/896030/The-Structure-of-HEVC-Video +// Licensed under the GNU General Public License and +// the Code Project Open License, http://www.codeproject.com/info/cpol10.aspx +// ======================================================================== + +#ifndef HEVC_NAL_DECODE +#define HEVC_NAL_DECODE + +#include "Hevc.h" +#include "BitstreamReader.h" + +#include +#include +#include + +namespace HEVC +{ + class HevcNalDecode + { + public: + NALUnitType processNALUnit(const uint8_t *pdata, std::size_t size, hevchdr& h); + + protected: + NALUnitType processNALUnitHeader(BitstreamReader &bs); + void Remove3Byte(uint8_t* dst, const uint8_t* src, int length); + void processSPS(std::shared_ptr psps, BitstreamReader &bs); + ProfileTierLevel processProfileTierLevel(std::size_t max_sub_layers_minus1, BitstreamReader &bs); + HrdParameters processHrdParameters(uint8_t commonInfPresentFlag, std::size_t maxNumSubLayersMinus1, BitstreamReader &bs); + ShortTermRefPicSet processShortTermRefPicSet(std::size_t stRpsIdx, size_t num_short_term_ref_pic_sets, const std::vector &refPicSets, std::shared_ptr psps, BitstreamReader &bs); + VuiParameters processVuiParameters(std::size_t sps_max_sub_layers_minus1, BitstreamReader &bs); + ScalingListData processScalingListData(BitstreamReader &bs); + SubLayerHrdParameters processSubLayerHrdParameters(uint8_t sub_pic_hrd_params_present_flag, std::size_t CpbCnt, BitstreamReader &bs); + }; +} + +#endif + diff --git a/DirectShowFilters/BDReader/source/StreamParser.cpp b/DirectShowFilters/BDReader/source/StreamParser.cpp index 0d554b41338..8ca5e607f16 100644 --- a/DirectShowFilters/BDReader/source/StreamParser.cpp +++ b/DirectShowFilters/BDReader/source/StreamParser.cpp @@ -28,10 +28,13 @@ #include "StreamParser.h" #include #include +#include "HEVC\Hevc.h" // For more details for memory leak detection see the alloctracing.h header #include "..\..\alloctracing.h" +using namespace HEVC; + extern void LogDebug(const char *fmt, ...) ; StreamParser::StreamParser() @@ -68,6 +71,20 @@ bool StreamParser::Parse(byte* tsPacket, int serviceType) parsed=true; } } + else if (serviceType == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + hevchdr hevc; + if (hdrParser.Read(hevc, framesize, &pmt)) + { + basicVideoInfo.width = hevc.width; + basicVideoInfo.height = hevc.height; + basicVideoInfo.fps = 1000 / (hevc.AvgTimePerFrame / 10000); + basicVideoInfo.isInterlaced = 0; + basicVideoInfo.streamType = 4; // HEVC + basicVideoInfo.isValid = true; + parsed = true; + } + } else if (serviceType == BLURAY_STREAM_TYPE_VIDEO_H264) { avchdr avc; diff --git a/DirectShowFilters/BDReader/source/VideoPin.cpp b/DirectShowFilters/BDReader/source/VideoPin.cpp index 8f9117f6568..e71b04604eb 100644 --- a/DirectShowFilters/BDReader/source/VideoPin.cpp +++ b/DirectShowFilters/BDReader/source/VideoPin.cpp @@ -105,6 +105,7 @@ CVideoPin::CVideoPin(LPUNKNOWN pUnk, CBDReaderFilter* pFilter, HRESULT* phr, CCr m_bDoFakeSeek(false), m_bResetToLibSeek(false), m_H264decoder(GUID_NULL), + m_HEVCdecoder(GUID_NULL), m_VC1decoder(GUID_NULL), m_MPEG2decoder(GUID_NULL), m_VC1Override(GUID_NULL), @@ -212,6 +213,12 @@ void CVideoPin::SetVideoDecoder(int format, GUID* decoder) LogDebug("vid: SetVideoDecoder for MPEG2"); LogMediaType(&tmp); } + else if (format == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + m_HEVCdecoder = tmp.subtype = *decoder; + LogDebug("vid: SetVideoDecoder for HEVC"); + LogMediaType(&tmp); + } else { LogDebug("vid: SetVideoDecoder - trying to set a decoder for invalid format %d", format); @@ -237,6 +244,8 @@ bool CVideoPin::CheckVideoFormat(GUID* pFormat, CLSID* pDecoder) decoder = &m_H264decoder; else if (IsEqualGUID(*pFormat, VC1_SubType)) decoder = &m_VC1decoder; + else if (IsEqualGUID(*pFormat, HEVC_SubType)) + decoder = &m_HEVCdecoder; else if (IsEqualGUID(*pFormat, MEDIASUBTYPE_MPEG2_VIDEO)) decoder = &m_MPEG2decoder; else @@ -741,6 +750,22 @@ HRESULT CVideoPin::FillBuffer(IMediaSample* pSample) pSample->GetPointer(&pSampleBuffer); memcpy(pSampleBuffer, buffer->GetData(), buffer->GetDataSize()); + //Switch to AnnexB for HEVC + if (m_demux.GetVideoServiceType() == BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + int i = buffer->GetDataSize(); + while (i > 0) + { + //size of nalu + int iSize = (*pSampleBuffer << 24) | (*(pSampleBuffer + 1) << 16) | (*(pSampleBuffer + 2) << 8) | (*(pSampleBuffer + 3)); + + *(DWORD*)pSampleBuffer = 0x01000000; //four byte start code + + i -= iSize + 4; + pSampleBuffer += iSize + 4; + } + } + m_nSampleCounter++; #ifdef LOG_VIDEO_PIN_SAMPLES diff --git a/DirectShowFilters/BDReader/source/VideoPin.h b/DirectShowFilters/BDReader/source/VideoPin.h index 1bf5672a56b..534c53f410f 100644 --- a/DirectShowFilters/BDReader/source/VideoPin.h +++ b/DirectShowFilters/BDReader/source/VideoPin.h @@ -96,6 +96,7 @@ class CVideoPin : public CSourceStream, public CSourceSeeking CLSID m_VC1decoder; CLSID m_H264decoder; CLSID m_MPEG2decoder; + CLSID m_HEVCdecoder; CLSID m_currentDecoder; diff --git a/DirectShowFilters/BDReader/source/mediaformats.h b/DirectShowFilters/BDReader/source/mediaformats.h index 66116dae771..3589fd6b8bd 100644 --- a/DirectShowFilters/BDReader/source/mediaformats.h +++ b/DirectShowFilters/BDReader/source/mediaformats.h @@ -90,6 +90,7 @@ static GUID MEDIASUBTYPE_CVD_SUBPICTURE = {0x7b57308f, 0x5154, 0x4c36, 0xb9, 0x3 static GUID MEDIATYPE_Subtitle = {0xe487eb08, 0x6b26, 0x4be9, 0x9d, 0xd3, 0x99, 0x34, 0x34, 0xd3, 0x13, 0xfd}; static GUID MEDIASUBTYPE_PS2_SUB = {0x4f3d3d21, 0x6d7c, 0x4f73, 0xaa, 0x5, 0xe3, 0x97, 0xb5, 0xea, 0xe0, 0xaa}; static GUID H264_SubType = {0x8D2D71CB, 0x243F, 0x45E3, {0xB2, 0xD8, 0x5F, 0xD7, 0x96, 0x7E, 0xC0, 0x9B}}; +static GUID HEVC_SubType = { 0x43564548, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }; static GUID MPG4_SubType = FOURCCMap(MAKEFOURCC('A','V','C','1')); static GUID VC1_SubType = FOURCCMap('1CVW'); static GUID AVC1_SubType = {0x31435641, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; diff --git a/mediaportal/Configuration/Sections/BDCodec.Designer.cs b/mediaportal/Configuration/Sections/BDCodec.Designer.cs index 2e97e27b60a..cf7b2e22009 100644 --- a/mediaportal/Configuration/Sections/BDCodec.Designer.cs +++ b/mediaportal/Configuration/Sections/BDCodec.Designer.cs @@ -23,229 +23,269 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.mpGroupBox1 = new MediaPortal.UserInterface.Controls.MPGroupBox(); - this.configAudioRenderer = new MediaPortal.UserInterface.Controls.MPButton(); - this.configAUDIO = new MediaPortal.UserInterface.Controls.MPButton(); - this.configVC1 = new MediaPortal.UserInterface.Controls.MPButton(); - this.configH264 = new MediaPortal.UserInterface.Controls.MPButton(); - this.configMPEG = new MediaPortal.UserInterface.Controls.MPButton(); - this.mpLabel2 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.vc1videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.mpLabel1 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.h264videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.audioRendererComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.label3 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.label6 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.audioCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); - this.label5 = new MediaPortal.UserInterface.Controls.MPLabel(); - this.mpGroupBox1.SuspendLayout(); - this.SuspendLayout(); - // - // mpGroupBox1 - // - this.mpGroupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.mpGroupBox1 = new MediaPortal.UserInterface.Controls.MPGroupBox(); + this.configAudioRenderer = new MediaPortal.UserInterface.Controls.MPButton(); + this.configAUDIO = new MediaPortal.UserInterface.Controls.MPButton(); + this.configVC1 = new MediaPortal.UserInterface.Controls.MPButton(); + this.configH264 = new MediaPortal.UserInterface.Controls.MPButton(); + this.configHEVC = new MediaPortal.UserInterface.Controls.MPButton(); + this.configMPEG = new MediaPortal.UserInterface.Controls.MPButton(); + this.mpLabel2 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.vc1videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.mpLabel1 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.h264videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.mpLabel3 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.hevcvideoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.audioRendererComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.label3 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.label6 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.audioCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.videoCodecComboBox = new MediaPortal.UserInterface.Controls.MPComboBox(); + this.label5 = new MediaPortal.UserInterface.Controls.MPLabel(); + this.mpGroupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // mpGroupBox1 + // + this.mpGroupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.mpGroupBox1.Controls.Add(this.configAudioRenderer); - this.mpGroupBox1.Controls.Add(this.configAUDIO); - this.mpGroupBox1.Controls.Add(this.configVC1); - this.mpGroupBox1.Controls.Add(this.configH264); - this.mpGroupBox1.Controls.Add(this.configMPEG); - this.mpGroupBox1.Controls.Add(this.mpLabel2); - this.mpGroupBox1.Controls.Add(this.vc1videoCodecComboBox); - this.mpGroupBox1.Controls.Add(this.mpLabel1); - this.mpGroupBox1.Controls.Add(this.h264videoCodecComboBox); - this.mpGroupBox1.Controls.Add(this.audioRendererComboBox); - this.mpGroupBox1.Controls.Add(this.label3); - this.mpGroupBox1.Controls.Add(this.label6); - this.mpGroupBox1.Controls.Add(this.audioCodecComboBox); - this.mpGroupBox1.Controls.Add(this.videoCodecComboBox); - this.mpGroupBox1.Controls.Add(this.label5); - this.mpGroupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.mpGroupBox1.Location = new System.Drawing.Point(6, 0); - this.mpGroupBox1.Name = "mpGroupBox1"; - this.mpGroupBox1.Size = new System.Drawing.Size(462, 313); - this.mpGroupBox1.TabIndex = 1; - this.mpGroupBox1.TabStop = false; - this.mpGroupBox1.Text = "Settings Decoder"; - // - // configAudioRenderer - // - this.configAudioRenderer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configAudioRenderer.BackColor = System.Drawing.Color.Transparent; - this.configAudioRenderer.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configAudioRenderer.Location = new System.Drawing.Point(422, 127); - this.configAudioRenderer.Name = "configAudioRenderer"; - this.configAudioRenderer.Size = new System.Drawing.Size(35, 21); - this.configAudioRenderer.TabIndex = 74; - this.configAudioRenderer.Text = "\r\n"; - this.configAudioRenderer.UseVisualStyleBackColor = false; - this.configAudioRenderer.Click += new System.EventHandler(this.configAudioRenderer_Click); - // - // configAUDIO - // - this.configAUDIO.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configAUDIO.BackColor = System.Drawing.Color.Transparent; - this.configAUDIO.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configAUDIO.Location = new System.Drawing.Point(422, 103); - this.configAUDIO.Name = "configAUDIO"; - this.configAUDIO.Size = new System.Drawing.Size(35, 21); - this.configAUDIO.TabIndex = 73; - this.configAUDIO.Text = "\r\n"; - this.configAUDIO.UseVisualStyleBackColor = false; - this.configAUDIO.Click += new System.EventHandler(this.configAUDIO_Click); - // - // configVC1 - // - this.configVC1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configVC1.BackColor = System.Drawing.Color.Transparent; - this.configVC1.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configVC1.Location = new System.Drawing.Point(422, 72); - this.configVC1.Name = "configVC1"; - this.configVC1.Size = new System.Drawing.Size(35, 21); - this.configVC1.TabIndex = 72; - this.configVC1.Text = "\r\n"; - this.configVC1.UseVisualStyleBackColor = false; - this.configVC1.Click += new System.EventHandler(this.configVC1_Click); - // - // configH264 - // - this.configH264.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configH264.BackColor = System.Drawing.Color.Transparent; - this.configH264.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configH264.Location = new System.Drawing.Point(422, 48); - this.configH264.Name = "configH264"; - this.configH264.Size = new System.Drawing.Size(35, 21); - this.configH264.TabIndex = 71; - this.configH264.Text = "\r\n"; - this.configH264.UseVisualStyleBackColor = false; - this.configH264.Click += new System.EventHandler(this.configH264_Click); - // - // configMPEG - // - this.configMPEG.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.configMPEG.BackColor = System.Drawing.Color.Transparent; - this.configMPEG.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; - this.configMPEG.Location = new System.Drawing.Point(422, 24); - this.configMPEG.Name = "configMPEG"; - this.configMPEG.Size = new System.Drawing.Size(35, 21); - this.configMPEG.TabIndex = 70; - this.configMPEG.Text = "\r\n"; - this.configMPEG.UseVisualStyleBackColor = false; - this.configMPEG.Click += new System.EventHandler(this.configMPEG_Click); - // - // mpLabel2 - // - this.mpLabel2.Location = new System.Drawing.Point(16, 76); - this.mpLabel2.Name = "mpLabel2"; - this.mpLabel2.Size = new System.Drawing.Size(88, 16); - this.mpLabel2.TabIndex = 10; - this.mpLabel2.Text = "VC-1 Video :"; - // - // vc1videoCodecComboBox - // - this.vc1videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.mpGroupBox1.Controls.Add(this.configAudioRenderer); + this.mpGroupBox1.Controls.Add(this.configAUDIO); + this.mpGroupBox1.Controls.Add(this.configVC1); + this.mpGroupBox1.Controls.Add(this.configH264); + this.mpGroupBox1.Controls.Add(this.configHEVC); + this.mpGroupBox1.Controls.Add(this.configMPEG); + this.mpGroupBox1.Controls.Add(this.mpLabel2); + this.mpGroupBox1.Controls.Add(this.vc1videoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.mpLabel1); + this.mpGroupBox1.Controls.Add(this.h264videoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.mpLabel3); + this.mpGroupBox1.Controls.Add(this.hevcvideoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.audioRendererComboBox); + this.mpGroupBox1.Controls.Add(this.label3); + this.mpGroupBox1.Controls.Add(this.label6); + this.mpGroupBox1.Controls.Add(this.audioCodecComboBox); + this.mpGroupBox1.Controls.Add(this.videoCodecComboBox); + this.mpGroupBox1.Controls.Add(this.label5); + this.mpGroupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Popup; + this.mpGroupBox1.Location = new System.Drawing.Point(6, 0); + this.mpGroupBox1.Name = "mpGroupBox1"; + this.mpGroupBox1.Size = new System.Drawing.Size(462, 313); + this.mpGroupBox1.TabIndex = 1; + this.mpGroupBox1.TabStop = false; + this.mpGroupBox1.Text = "Settings Decoder"; + // + // configAudioRenderer + // + this.configAudioRenderer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configAudioRenderer.BackColor = System.Drawing.Color.Transparent; + this.configAudioRenderer.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configAudioRenderer.Location = new System.Drawing.Point(422, 151); + this.configAudioRenderer.Name = "configAudioRenderer"; + this.configAudioRenderer.Size = new System.Drawing.Size(35, 21); + this.configAudioRenderer.TabIndex = 75; + this.configAudioRenderer.Text = "\r\n"; + this.configAudioRenderer.UseVisualStyleBackColor = false; + this.configAudioRenderer.Click += new System.EventHandler(this.configAudioRenderer_Click); + // + // configAUDIO + // + this.configAUDIO.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configAUDIO.BackColor = System.Drawing.Color.Transparent; + this.configAUDIO.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configAUDIO.Location = new System.Drawing.Point(422, 127); + this.configAUDIO.Name = "configAUDIO"; + this.configAUDIO.Size = new System.Drawing.Size(35, 21); + this.configAUDIO.TabIndex = 74; + this.configAUDIO.Text = "\r\n"; + this.configAUDIO.UseVisualStyleBackColor = false; + this.configAUDIO.Click += new System.EventHandler(this.configAUDIO_Click); + // + // configVC1 + // + this.configVC1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configVC1.BackColor = System.Drawing.Color.Transparent; + this.configVC1.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configVC1.Location = new System.Drawing.Point(422, 96); + this.configVC1.Name = "configVC1"; + this.configVC1.Size = new System.Drawing.Size(35, 21); + this.configVC1.TabIndex = 73; + this.configVC1.Text = "\r\n"; + this.configVC1.UseVisualStyleBackColor = false; + this.configVC1.Click += new System.EventHandler(this.configVC1_Click); + // + // configH264 + // + this.configH264.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configH264.BackColor = System.Drawing.Color.Transparent; + this.configH264.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configH264.Location = new System.Drawing.Point(422, 48); + this.configH264.Name = "configH264"; + this.configH264.Size = new System.Drawing.Size(35, 21); + this.configH264.TabIndex = 71; + this.configH264.Text = "\r\n"; + this.configH264.UseVisualStyleBackColor = false; + this.configH264.Click += new System.EventHandler(this.configH264_Click); + // + // configHEVC + // + this.configHEVC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configHEVC.BackColor = System.Drawing.Color.Transparent; + this.configHEVC.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configHEVC.Location = new System.Drawing.Point(422, 72); + this.configHEVC.Name = "configHEVC"; + this.configHEVC.Size = new System.Drawing.Size(35, 21); + this.configHEVC.TabIndex = 72; + this.configHEVC.Text = "\r\n"; + this.configHEVC.UseVisualStyleBackColor = false; + this.configHEVC.Click += new System.EventHandler(this.configHEVC_Click); + // + // configMPEG + // + this.configMPEG.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.configMPEG.BackColor = System.Drawing.Color.Transparent; + this.configMPEG.Image = global::MediaPortal.Configuration.Properties.Resources.codec_screwdriver; + this.configMPEG.Location = new System.Drawing.Point(422, 24); + this.configMPEG.Name = "configMPEG"; + this.configMPEG.Size = new System.Drawing.Size(35, 21); + this.configMPEG.TabIndex = 70; + this.configMPEG.Text = "\r\n"; + this.configMPEG.UseVisualStyleBackColor = false; + this.configMPEG.Click += new System.EventHandler(this.configMPEG_Click); + // + // mpLabel2 + // + this.mpLabel2.Location = new System.Drawing.Point(16, 100); + this.mpLabel2.Name = "mpLabel2"; + this.mpLabel2.Size = new System.Drawing.Size(88, 16); + this.mpLabel2.TabIndex = 93; + this.mpLabel2.Text = "VC-1 Video :"; + // + // vc1videoCodecComboBox + // + this.vc1videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.vc1videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.vc1videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.vc1videoCodecComboBox.Location = new System.Drawing.Point(122, 72); - this.vc1videoCodecComboBox.Name = "vc1videoCodecComboBox"; - this.vc1videoCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.vc1videoCodecComboBox.Sorted = true; - this.vc1videoCodecComboBox.TabIndex = 5; - // - // mpLabel1 - // - this.mpLabel1.Location = new System.Drawing.Point(16, 52); - this.mpLabel1.Name = "mpLabel1"; - this.mpLabel1.Size = new System.Drawing.Size(88, 16); - this.mpLabel1.TabIndex = 8; - this.mpLabel1.Text = "H.264 Video :"; - // - // h264videoCodecComboBox - // - this.h264videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.vc1videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.vc1videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.vc1videoCodecComboBox.Location = new System.Drawing.Point(122, 96); + this.vc1videoCodecComboBox.Name = "vc1videoCodecComboBox"; + this.vc1videoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.vc1videoCodecComboBox.Sorted = true; + this.vc1videoCodecComboBox.TabIndex = 4; + // + // mpLabel1 + // + this.mpLabel1.Location = new System.Drawing.Point(16, 52); + this.mpLabel1.Name = "mpLabel1"; + this.mpLabel1.Size = new System.Drawing.Size(88, 16); + this.mpLabel1.TabIndex = 91; + this.mpLabel1.Text = "H.264 Video :"; + // + // h264videoCodecComboBox + // + this.h264videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.h264videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.h264videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.h264videoCodecComboBox.Location = new System.Drawing.Point(122, 48); - this.h264videoCodecComboBox.Name = "h264videoCodecComboBox"; - this.h264videoCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.h264videoCodecComboBox.Sorted = true; - this.h264videoCodecComboBox.TabIndex = 3; - this.h264videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.h264videoCodecComboBox_SelectedIndexChanged); - // - // audioRendererComboBox - // - this.audioRendererComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.h264videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.h264videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.h264videoCodecComboBox.Location = new System.Drawing.Point(122, 48); + this.h264videoCodecComboBox.Name = "h264videoCodecComboBox"; + this.h264videoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.h264videoCodecComboBox.Sorted = true; + this.h264videoCodecComboBox.TabIndex = 2; + this.h264videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.h264videoCodecComboBox_SelectedIndexChanged); + // + // mpLabel3 + // + this.mpLabel3.Location = new System.Drawing.Point(16, 76); + this.mpLabel3.Name = "mpLabel3"; + this.mpLabel3.Size = new System.Drawing.Size(88, 16); + this.mpLabel3.TabIndex = 92; + this.mpLabel3.Text = "HEVC Video :"; + // + // hevcvideoCodecComboBox + // + this.hevcvideoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.audioRendererComboBox.BorderColor = System.Drawing.Color.Empty; - this.audioRendererComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.audioRendererComboBox.Location = new System.Drawing.Point(122, 128); - this.audioRendererComboBox.Name = "audioRendererComboBox"; - this.audioRendererComboBox.Size = new System.Drawing.Size(295, 21); - this.audioRendererComboBox.Sorted = true; - this.audioRendererComboBox.TabIndex = 9; - // - // label3 - // - this.label3.Location = new System.Drawing.Point(16, 132); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(88, 17); - this.label3.TabIndex = 6; - this.label3.Text = "Audio renderer:"; - // - // label6 - // - this.label6.Location = new System.Drawing.Point(16, 28); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(88, 16); - this.label6.TabIndex = 0; - this.label6.Text = "MPEG-2 Video :"; - // - // audioCodecComboBox - // - this.audioCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.hevcvideoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.hevcvideoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.hevcvideoCodecComboBox.Location = new System.Drawing.Point(122, 72); + this.hevcvideoCodecComboBox.Name = "hevcvideoCodecComboBox"; + this.hevcvideoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.hevcvideoCodecComboBox.Sorted = true; + this.hevcvideoCodecComboBox.TabIndex = 3; + this.hevcvideoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.hevcvideoCodecComboBox_SelectedIndexChanged); + // + // audioRendererComboBox + // + this.audioRendererComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.audioCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.audioCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.audioCodecComboBox.Location = new System.Drawing.Point(122, 104); - this.audioCodecComboBox.Name = "audioCodecComboBox"; - this.audioCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.audioCodecComboBox.Sorted = true; - this.audioCodecComboBox.TabIndex = 7; - // - // videoCodecComboBox - // - this.videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.audioRendererComboBox.BorderColor = System.Drawing.Color.Empty; + this.audioRendererComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.audioRendererComboBox.Location = new System.Drawing.Point(122, 152); + this.audioRendererComboBox.Name = "audioRendererComboBox"; + this.audioRendererComboBox.Size = new System.Drawing.Size(295, 21); + this.audioRendererComboBox.Sorted = true; + this.audioRendererComboBox.TabIndex = 6; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 156); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(88, 17); + this.label3.TabIndex = 95; + this.label3.Text = "Audio renderer:"; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(16, 28); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(88, 16); + this.label6.TabIndex = 90; + this.label6.Text = "MPEG-2 Video :"; + // + // audioCodecComboBox + // + this.audioCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; - this.videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.videoCodecComboBox.Location = new System.Drawing.Point(122, 24); - this.videoCodecComboBox.Name = "videoCodecComboBox"; - this.videoCodecComboBox.Size = new System.Drawing.Size(295, 21); - this.videoCodecComboBox.Sorted = true; - this.videoCodecComboBox.TabIndex = 1; - this.videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.videoCodecComboBox_SelectedIndexChanged); - // - // label5 - // - this.label5.Location = new System.Drawing.Point(16, 108); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(125, 21); - this.label5.TabIndex = 2; - this.label5.Text = "LPCM/AC3/DTS :"; - // - // BDCodec - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.SystemColors.Window; - this.Controls.Add(this.mpGroupBox1); - this.Name = "BDCodec"; - this.Size = new System.Drawing.Size(472, 391); - this.mpGroupBox1.ResumeLayout(false); - this.ResumeLayout(false); + this.audioCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.audioCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.audioCodecComboBox.Location = new System.Drawing.Point(122, 128); + this.audioCodecComboBox.Name = "audioCodecComboBox"; + this.audioCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.audioCodecComboBox.Sorted = true; + this.audioCodecComboBox.TabIndex = 5; + // + // videoCodecComboBox + // + this.videoCodecComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.videoCodecComboBox.BorderColor = System.Drawing.Color.Empty; + this.videoCodecComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.videoCodecComboBox.Location = new System.Drawing.Point(122, 21); + this.videoCodecComboBox.Name = "videoCodecComboBox"; + this.videoCodecComboBox.Size = new System.Drawing.Size(295, 21); + this.videoCodecComboBox.Sorted = true; + this.videoCodecComboBox.TabIndex = 1; + this.videoCodecComboBox.SelectedIndexChanged += new System.EventHandler(this.videoCodecComboBox_SelectedIndexChanged); + // + // label5 + // + this.label5.Location = new System.Drawing.Point(16, 132); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(125, 21); + this.label5.TabIndex = 94; + this.label5.Text = "LPCM/AC3/DTS :"; + // + // BDCodec + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Window; + this.Controls.Add(this.mpGroupBox1); + this.Name = "BDCodec"; + this.Size = new System.Drawing.Size(472, 391); + this.mpGroupBox1.ResumeLayout(false); + this.ResumeLayout(false); } @@ -254,6 +294,8 @@ private void InitializeComponent() private MediaPortal.UserInterface.Controls.MPGroupBox mpGroupBox1; private MediaPortal.UserInterface.Controls.MPLabel mpLabel1; private MediaPortal.UserInterface.Controls.MPComboBox h264videoCodecComboBox; + private MediaPortal.UserInterface.Controls.MPLabel mpLabel3; + private MediaPortal.UserInterface.Controls.MPComboBox hevcvideoCodecComboBox; private MediaPortal.UserInterface.Controls.MPComboBox audioRendererComboBox; private MediaPortal.UserInterface.Controls.MPLabel label3; private MediaPortal.UserInterface.Controls.MPLabel label6; @@ -267,5 +309,6 @@ private void InitializeComponent() private UserInterface.Controls.MPButton configAUDIO; private UserInterface.Controls.MPButton configVC1; private UserInterface.Controls.MPButton configH264; + private UserInterface.Controls.MPButton configHEVC; } } diff --git a/mediaportal/Configuration/Sections/BDCodec.cs b/mediaportal/Configuration/Sections/BDCodec.cs index ece5b551ff0..c27f507640a 100644 --- a/mediaportal/Configuration/Sections/BDCodec.cs +++ b/mediaportal/Configuration/Sections/BDCodec.cs @@ -62,6 +62,7 @@ public override sealed void OnSectionActivated() ArrayList availableVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubTypeEx.MPEG2); ArrayList availableAudioFilters = FilterHelper.GetFilters(MediaType.Audio, MediaSubType.Mpeg2Audio); ArrayList availableH264VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.H264); + ArrayList availableHEVCVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.HEVC); ArrayList availableVC1VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.VC1); ArrayList availableVC1CyberlinkVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.CyberlinkVC1); ArrayList availableFileSyncFilters = FilterHelper.GetFilters(MediaType.Stream, MediaSubType.Null); @@ -113,6 +114,7 @@ public override sealed void OnSectionActivated() audioCodecComboBox.Items.AddRange(availableAudioFilters.ToArray()); availableFileSyncFilters.Sort(); h264videoCodecComboBox.Items.AddRange(availableH264VideoFilters.ToArray()); + hevcvideoCodecComboBox.Items.AddRange(availableHEVCVideoFilters.ToArray()); vc1videoCodecComboBox.Items.AddRange(availableVC1VideoFilters.ToArray()); vc1videoCodecComboBox.Items.AddRange(availableVC1CyberlinkVideoFilters.ToArray()); audioRendererComboBox.Items.AddRange(availableAudioRenderers.ToArray()); @@ -137,6 +139,7 @@ public override void LoadSettings() // Set codecs string videoCodec = xmlreader.GetValueAsString("bdplayer", "mpeg2videocodec", ""); string h264videoCodec = xmlreader.GetValueAsString("bdplayer", "h264videocodec", ""); + string hevcvideoCodec = xmlreader.GetValueAsString("bdplayer", "hevcvideocodec", ""); string vc1videoCodec = xmlreader.GetValueAsString("bdplayer", "vc1videocodec", ""); string audioCodec = xmlreader.GetValueAsString("bdplayer", "mpeg2audiocodec", ""); //string aacaudioCodec = xmlreader.GetValueAsString("bdplayer", "aacaudiocodec", ""); @@ -151,6 +154,11 @@ public override void LoadSettings() ArrayList availableH264VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.H264); h264videoCodec = SetCodecBox(availableH264VideoFilters, "LAV Video Decoder", "CoreAVC Video Decoder", ""); } + if (hevcvideoCodec == string.Empty) + { + ArrayList availableHEVCVideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.HEVC); + hevcvideoCodec = SetCodecBox(availableHEVCVideoFilters, "LAV Video Decoder", "CoreAVC Video Decoder", ""); + } if (vc1videoCodec == string.Empty) { ArrayList availableVC1VideoFilters = FilterHelper.GetFilters(MediaType.Video, MediaSubType.VC1); @@ -165,10 +173,12 @@ public override void LoadSettings() audioCodecComboBox.Text = audioCodec; videoCodecComboBox.Text = videoCodec; h264videoCodecComboBox.Text = h264videoCodec; + hevcvideoCodecComboBox.Text = hevcvideoCodec; vc1videoCodecComboBox.Text = vc1videoCodec; CheckBoxValid(audioCodecComboBox); CheckBoxValid(videoCodecComboBox); CheckBoxValid(h264videoCodecComboBox); + CheckBoxValid(hevcvideoCodecComboBox); CheckBoxValid(vc1videoCodecComboBox); CheckBoxValid(audioRendererComboBox); } @@ -242,6 +252,7 @@ public override void SaveSettings() xmlwriter.SetValue("bdplayer", "mpeg2audiocodec", audioCodecComboBox.Text); xmlwriter.SetValue("bdplayer", "mpeg2videocodec", videoCodecComboBox.Text); xmlwriter.SetValue("bdplayer", "h264videocodec", h264videoCodecComboBox.Text); + xmlwriter.SetValue("bdplayer", "hevcvideocodec", hevcvideoCodecComboBox.Text); xmlwriter.SetValue("bdplayer", "vc1videocodec", vc1videoCodecComboBox.Text); } } @@ -296,6 +307,11 @@ private void h264videoCodecComboBox_SelectedIndexChanged(object sender, System.E */ } + private void hevcvideoCodecComboBox_SelectedIndexChanged(object sender, System.EventArgs e) + { + + } + private void RegMPtoConfig(string subkeysource) { using (RegistryKey subkey = Registry.CurrentUser.CreateSubKey(subkeysource)) @@ -397,6 +413,11 @@ private void configH264_Click(object sender, EventArgs e) ConfigCodecSection(sender, e, h264videoCodecComboBox.Text); } + private void configHEVC_Click(object sender, EventArgs e) + { + ConfigCodecSection(sender, e, hevcvideoCodecComboBox.Text); + } + private void configVC1_Click(object sender, EventArgs e) { ConfigCodecSection(sender, e, vc1videoCodecComboBox.Text); diff --git a/mediaportal/Core/Player/BDPlayer.cs b/mediaportal/Core/Player/BDPlayer.cs index 516148fdb93..d617cebd413 100644 --- a/mediaportal/Core/Player/BDPlayer.cs +++ b/mediaportal/Core/Player/BDPlayer.cs @@ -244,6 +244,7 @@ public BDFilterConfig() public string VideoMPEG { get; set; } public string VideoH264 { get; set; } public string VideoVC1 { get; set; } + public string VideoHEVC { get; set; } public string Audio { get; set; } //public string AudioAAC { get; set; } //public string AudioDDPlus { get; set; } @@ -1988,6 +1989,7 @@ protected virtual BDFilterConfig GetFilterConfiguration() //filterConfig.AudioDDPlus = xmlreader.GetValueAsString("bdplayer", "ddplusaudiocodec", ""); filterConfig.VideoH264 = xmlreader.GetValueAsString("bdplayer", "h264videocodec", ""); filterConfig.VideoVC1 = xmlreader.GetValueAsString("bdplayer", "vc1videocodec", ""); + filterConfig.VideoHEVC = xmlreader.GetValueAsString("bdplayer", "hevcvideocodec", ""); filterConfig.AudioRenderer = xmlreader.GetValueAsString("bdplayer", "audiorenderer", "Default DirectSound Device"); // get AR setting @@ -2714,6 +2716,10 @@ protected string MatchFilters(string format) { return filterConfig.VideoVC1; } + else if (_currentVideoFormat == BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC) + { + return filterConfig.VideoHEVC; + } else { return filterConfig.VideoH264; @@ -3234,7 +3240,16 @@ private void SetVideoDecoder() { ExportGuidFilterAndRelease(filterConfig.VideoH264, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_H264); - if (filterConfig.VideoMPEG != filterConfig.VideoH264) + if (filterConfig.VideoHEVC != filterConfig.VideoH264) + { + ExportGuidFilterAndRelease(filterConfig.VideoHEVC, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC); + } + else + { + _ireader.SetVideoDecoder((int)BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC, ref GuidFilter); + } + + if (filterConfig.VideoMPEG != filterConfig.VideoH264 || filterConfig.VideoMPEG != filterConfig.VideoHEVC) { ExportGuidFilterAndRelease(filterConfig.VideoMPEG, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_MPEG2); } @@ -3243,7 +3258,7 @@ private void SetVideoDecoder() _ireader.SetVideoDecoder((int)BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_MPEG2, ref GuidFilter); } - if (filterConfig.VideoVC1 != filterConfig.VideoH264 || filterConfig.VideoVC1 != filterConfig.VideoMPEG) + if (filterConfig.VideoVC1 != filterConfig.VideoH264 || filterConfig.VideoVC1 != filterConfig.VideoHEVC || filterConfig.VideoVC1 != filterConfig.VideoMPEG) { ExportGuidFilterAndRelease(filterConfig.VideoVC1, BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_VC1); } @@ -3495,6 +3510,8 @@ protected string VideoFormattoString(VideoFormat videoFormat) return "1080p"; case VideoFormat.BLURAY_VIDEO_FORMAT_576P: return "576p"; + case VideoFormat.BLURAY_VIDEO_FORMAT_2160P: + return "2160p"; default: return Strings.Unknown; } @@ -3528,6 +3545,8 @@ protected string StreamTypetoString(BluRayStreamFormats stream) return "H264"; case BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_VC1: return "VC1"; + case BluRayStreamFormats.BLURAY_STREAM_TYPE_VIDEO_HEVC: + return "HEVC"; } return Strings.Unknown; }