Skip to content

Commit

Permalink
Dynlib load fixes and VP9 fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
MikuAuahDark committed Jun 8, 2024
1 parent e631229 commit 33ac78c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 45 deletions.
94 changes: 52 additions & 42 deletions src/nav_backend_mediafoundation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,16 @@ struct MediaTypeCombination
{MFVideoFormat_IYUV, NAV_PIXELFORMAT_YUV420},
{MFVideoFormat_NV12, NAV_PIXELFORMAT_NV12},
{MFVideoFormat_RGB24, NAV_PIXELFORMAT_RGB8},
{NULL_GUID, NAV_PIXELFORMAT_UNKNOWN}
};

struct KnownBestCombination
{
GUID codec;
GUID rawformat;
nav_pixelformat pixfmt;
} knownBestCombination[] = {
{MFVideoFormat_H264, MFVideoFormat_I420, NAV_PIXELFORMAT_YUV420},
{MFVideoFormat_VP90, MFVideoFormat_NV12, NAV_PIXELFORMAT_NV12},
};

inline void unixTimestampToFILETIME(FILETIME &ft, uint64_t t = 0LL)
Expand Down Expand Up @@ -452,21 +461,42 @@ MediaFoundationState::MediaFoundationState(MediaFoundationBackend *backend, nav_
// }
// else
// failed = true;
bool gotCodec = false;
GUID codec = NULL_GUID;

mfMediaType->GetGUID(MF_MT_SUBTYPE, &codec);
mfMediaType->CopyAllItems(partialType.get());
mfMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);

for (const MediaTypeCombination &comb: mediaTypeCombination)
// Try best known combination first
for (const KnownBestCombination &comb: knownBestCombination)
{
if (comb.pixfmt == NAV_PIXELFORMAT_UNKNOWN)
continue;

partialType->SetGUID(MF_MT_SUBTYPE, comb.guid);
if (SUCCEEDED(mfsr->SetCurrentMediaType(i, nullptr, partialType.get())))
if (comb.codec != NULL_GUID && comb.codec == codec)
{
pixfmt = comb.pixfmt;
partialType->SetGUID(MF_MT_SUBTYPE, comb.rawformat);

if (SUCCEEDED(mfsr->SetCurrentMediaType(i, nullptr, partialType.get())))
{
gotCodec = true;
pixfmt = comb.pixfmt;
}

break;
}
}

if (!gotCodec)
{
for (const MediaTypeCombination &comb: mediaTypeCombination)
{
partialType->SetGUID(MF_MT_SUBTYPE, comb.guid);
if (SUCCEEDED(mfsr->SetCurrentMediaType(i, nullptr, partialType.get())))
{
pixfmt = comb.pixfmt;
break;
}
}
}
}

failed = failed || pixfmt == NAV_PIXELFORMAT_UNKNOWN;
Expand All @@ -485,12 +515,11 @@ MediaFoundationState::MediaFoundationState(MediaFoundationBackend *backend, nav_

if (!failed)
{
// FIXME: Assume YUV420P for now
streamInfo.type = NAV_STREAMTYPE_VIDEO;
streamInfo.video.fps = fps.LowPart == 0 ? 0.0 : ((double) fps.HighPart / (double) fps.LowPart);
streamInfo.video.width = dimensions.HighPart;
streamInfo.video.height = dimensions.LowPart;
streamInfo.video.format = NAV_PIXELFORMAT_YUV420;
streamInfo.video.format = pixfmt;
}
}
}
Expand Down Expand Up @@ -605,11 +634,12 @@ nav_packet_t *MediaFoundationState::read()
return nullptr;
if (mfSample)
{
DWORD totalbufsize;
ComPtr<IMFMediaBuffer> testbuf;
DWORD bufcount;

if (FAILED(mfSample->GetTotalLength(&totalbufsize)))
if (FAILED(mfSample->GetBufferCount(&bufcount)))
throw std::runtime_error("MediaFoundation assertion failed");
if (totalbufsize > 0)
if (bufcount > 0)
return new MediaFoundationPacket(this, mfSample, streamIndex, timestamp);
}
}
Expand Down Expand Up @@ -643,45 +673,26 @@ double MediaFoundationPacket::tell() const noexcept

nav_frame_t *MediaFoundationPacket::decode()
{
DWORD bufsize, bufcount;

if (FAILED(mfSample->GetTotalLength(&bufsize)))
DWORD bufsize, tempbufsize;
ComPtr<IMFMediaBuffer> mfMediaBuffer;
if (FAILED(mfSample->ConvertToContiguousBuffer(mfMediaBuffer.dptr())))
throw std::runtime_error("MediaFoundation assertion failed");

if (FAILED(mfSample->GetBufferCount(&bufcount)))
BYTE *source;
if (FAILED(mfMediaBuffer->Lock(&source, &bufsize, &tempbufsize)))
throw std::runtime_error("MediaFoundation assertion failed");

std::unique_ptr<nav::FrameVector> frame = std::make_unique<nav::FrameVector>(nullptr, bufsize);
uint8_t *buf = (uint8_t*) frame->data();
size_t bufpos = 0;

for (DWORD i = 0; i < bufcount; i++)
{
ComPtr<IMFMediaBuffer> mfMediaBuffer;
BYTE *mediaBuffer = nullptr;
DWORD mediaBufferSize = 0;

if (FAILED(mfSample->GetBufferByIndex(i, mfMediaBuffer.dptr())))
throw std::runtime_error("IMFSample::GetBufferByIndex failed");

if (FAILED(mfMediaBuffer->Lock(&mediaBuffer, nullptr, &mediaBufferSize)))
throw std::runtime_error("IMFMediaBuffer::Lock failed");

std::copy(mediaBuffer, mediaBuffer + mediaBufferSize, buf + bufpos);
bufpos += mediaBufferSize;

if (FAILED(mfMediaBuffer->Unlock()))
throw std::runtime_error("IMFMediaBuffer::Unlock failed (inconsistent state)");
}

return frame.release();
nav::FrameVector *frame = new nav::FrameVector(source, bufsize);
mfMediaBuffer->Unlock();
return frame;
}

MediaFoundationBackend::MediaFoundationBackend()
: mfplat("mfplat.dll")
, mfreadwrite("mfreadwrite.dll")
, MFStartup(nullptr)
, MFShutdown(nullptr)
, MFCreateMediaType(nullptr)
, MFCreateMFByteStreamOnStream(nullptr)
, MFCreateSourceReaderFromByteStream(nullptr)
{
Expand All @@ -690,7 +701,6 @@ MediaFoundationBackend::MediaFoundationBackend()
!mfplat.get("MFShutdown", &MFShutdown) ||
!mfplat.get("MFCreateMediaType", &MFCreateMediaType) ||
!mfplat.get("MFCreateMFByteStreamOnStream", &MFCreateMFByteStreamOnStream) ||
!mfplat.get("MFTEnumEx", &MFTEnumEx) ||
!mfreadwrite.get("MFCreateSourceReaderFromByteStream", &MFCreateSourceReaderFromByteStream)
)
throw std::runtime_error("cannot load MediaFoundation function pointer");
Expand Down
3 changes: 1 addition & 2 deletions src/nav_backend_mediafoundation_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ComPtr
return *this;
}

T *operator->()
T *operator->() const
{
return ptr;
}
Expand Down Expand Up @@ -199,7 +199,6 @@ class MediaFoundationBackend: public Backend
_NAV_PROXY_FUNCTION_POINTER(MFShutdown);
_NAV_PROXY_FUNCTION_POINTER(MFCreateMediaType);
_NAV_PROXY_FUNCTION_POINTER(MFCreateMFByteStreamOnStream);
_NAV_PROXY_FUNCTION_POINTER(MFTEnumEx);
_NAV_PROXY_FUNCTION_POINTER(MFCreateSourceReaderFromByteStream);
#undef _NAV_PROXY_FUNCTION_POINTER
};
Expand Down
3 changes: 2 additions & 1 deletion src/nav_dynlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ void *DynLib::_get(const std::string &name, bool &err)
void *result = nullptr;

#ifdef _WIN32
SetLastError(0);
result = GetProcAddress((HMODULE) mod, name.c_str());
err = GetLastError() != 0;
err = GetLastError() == 0;
#else
dlerror();
result = dlsym(mod, name.c_str());
Expand Down

0 comments on commit 33ac78c

Please sign in to comment.