-
-
Save irieger/2eba5909c27b6cc195f6646a4cb12138 to your computer and use it in GitHub Desktop.
Blackmagic HDR metadata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
IDeckLinkMutableVideoFrame* new_frame = NULL; | |
VideoFrameWithMetadata* frame_with_meta = nullptr; | |
result = this->_dl_video_output->CreateVideoFrame((int32_t)this->_width, (int32_t)this->_height, (int32_t) line_bytes, bmdFormat10BitRGB,bmdFrameFlagDefault, &new_frame); | |
if (result == S_OK) | |
{ | |
new_frame->GetBytes((void**) &mem_ptr); | |
std::memset((void*) mem_ptr, 64, frame_bytes); | |
frame_with_meta = new VideoFrameWithMetadata(new_frame, false); | |
new_frame->Release(); | |
this->_videoFrameBlack = frame_with_meta; | |
new_frame = NULL; | |
frame_with_meta = nullptr; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cstdlib> | |
#include <cstring> | |
#include <stdexcept> | |
#include "videoframewithmetadata.h" | |
static inline bool CompareREFIID(const REFIID& ref1, const REFIID& ref2) | |
{ | |
return memcmp(&ref1, &ref2, sizeof(REFIID)) == 0; | |
} | |
VideoFrameWithMetadata::VideoFrameWithMetadata(IDeckLinkVideoFrame* video_frame, bool activate_metadata) | |
: _video_frame(video_frame), _activate_metadata(activate_metadata), m_refCount(1) | |
{ | |
this->_video_frame->AddRef(); | |
} | |
VideoFrameWithMetadata::~VideoFrameWithMetadata() | |
{ | |
this->_video_frame->Release(); | |
} | |
HRESULT STDMETHODCALLTYPE VideoFrameWithMetadata::QueryInterface(REFIID iid, LPVOID *ppv) | |
{ | |
if (CompareREFIID(iid, IID_IUnknown)) | |
{ | |
*ppv = static_cast<IDeckLinkVideoFrame*>(this); | |
} | |
else if (CompareREFIID(iid, IID_IDeckLinkVideoFrame)) | |
{ | |
*ppv = static_cast<IDeckLinkVideoFrame*>(this); | |
} | |
else if (CompareREFIID(iid, IID_IDeckLinkVideoFrameMetadataExtensions) && this->_activate_metadata) | |
{ | |
*ppv = static_cast<IDeckLinkVideoFrameMetadataExtensions*>(this); | |
} | |
else | |
{ | |
*ppv = NULL; | |
return E_NOINTERFACE; | |
} | |
AddRef(); | |
return S_OK; | |
} | |
ULONG STDMETHODCALLTYPE VideoFrameWithMetadata::AddRef(void) | |
{ | |
// gcc atomic operation builtin | |
return __sync_add_and_fetch(&m_refCount, 1); | |
} | |
ULONG STDMETHODCALLTYPE VideoFrameWithMetadata::Release(void) | |
{ | |
// gcc atomic operation builtin | |
ULONG newRefValue = __sync_sub_and_fetch(&m_refCount, 1); | |
if (!newRefValue) | |
delete this; | |
return newRefValue; | |
} | |
long VideoFrameWithMetadata::GetWidth(void) | |
{ | |
return this->_video_frame->GetWidth(); | |
} | |
long VideoFrameWithMetadata::GetHeight(void) | |
{ | |
return this->_video_frame->GetHeight(); | |
} | |
long VideoFrameWithMetadata::GetRowBytes(void) | |
{ | |
return this->_video_frame->GetRowBytes(); | |
} | |
BMDPixelFormat VideoFrameWithMetadata::GetPixelFormat(void) | |
{ | |
return this->_video_frame->GetPixelFormat(); | |
} | |
BMDFrameFlags VideoFrameWithMetadata::GetFlags(void) | |
{ | |
if (this->_activate_metadata) | |
{ | |
return bmdFrameContainsHDRMetadata; | |
} | |
else | |
{ | |
return this->_video_frame->GetFlags(); | |
} | |
} | |
HRESULT VideoFrameWithMetadata::GetBytes(/* out */ void** buffer) | |
{ | |
return this->_video_frame->GetBytes(buffer); | |
} | |
HRESULT VideoFrameWithMetadata::GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) | |
{ | |
return this->_video_frame->GetTimecode(format, timecode); | |
} | |
HRESULT VideoFrameWithMetadata::GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary** ancillary) | |
{ | |
return this->_video_frame->GetAncillaryData(ancillary); | |
} | |
HRESULT VideoFrameWithMetadata::GetInt (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ int64_t *value) | |
{ | |
switch (metadataID) | |
{ | |
case bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc: | |
*value = this->_hdr_eotf; | |
break; | |
default: | |
return E_INVALIDARG; | |
} | |
return S_OK; | |
} | |
HRESULT VideoFrameWithMetadata::GetFloat (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ double *value) | |
{ | |
switch (metadataID) | |
{ | |
case bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX: | |
*value = this->_hdr_primary_red_x; | |
break; | |
case bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY: | |
*value = this->_hdr_primary_red_y; | |
break; | |
case bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX: | |
*value = this->_hdr_primary_green_x; | |
break; | |
case bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY: | |
*value = this->_hdr_primary_green_y; | |
break; | |
case bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX: | |
*value = this->_hdr_primary_blue_x; | |
break; | |
case bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY: | |
*value = this->_hdr_primary_blue_y; | |
break; | |
case bmdDeckLinkFrameMetadataHDRWhitePointX: | |
*value = this->_hdr_primary_white_x; | |
break; | |
case bmdDeckLinkFrameMetadataHDRWhitePointY: | |
*value = this->_hdr_primary_white_y; | |
break; | |
case bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance: | |
*value = this->_hdr_max_master_disp_lum; | |
break; | |
case bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance: | |
*value = this->_hdr_min_master_disp_lum; | |
break; | |
case bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel: | |
*value = this->_hdr_maximum_content_light_level; | |
break; | |
case bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel: | |
*value = this->_hdr_maximum_average_frame_light_level; | |
break; | |
default: | |
return E_INVALIDARG; | |
} | |
return S_OK; | |
} | |
HRESULT VideoFrameWithMetadata::GetFlag (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ bool* value) | |
{ | |
switch (metadataID) | |
{ | |
default: | |
return E_INVALIDARG; | |
} | |
return S_OK; | |
} | |
HRESULT VideoFrameWithMetadata::GetString (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ const char **value) | |
{ | |
switch (metadataID) | |
{ | |
default: | |
return E_INVALIDARG; | |
} | |
return S_OK; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <DeckLinkAPI.h> | |
class VideoFrameWithMetadata : public IDeckLinkVideoFrame, public IDeckLinkVideoFrameMetadataExtensions | |
{ | |
public: | |
VideoFrameWithMetadata(IDeckLinkVideoFrame* video_frame, bool activate_metadata = false); | |
~VideoFrameWithMetadata(); | |
// IUnknown methods | |
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv); | |
virtual ULONG STDMETHODCALLTYPE AddRef(void); | |
virtual ULONG STDMETHODCALLTYPE Release(void); | |
// IDeckLinkVideoFrame methods | |
virtual long GetWidth(void); | |
virtual long GetHeight(void); | |
virtual long GetRowBytes(void); | |
virtual BMDPixelFormat GetPixelFormat(void); | |
virtual BMDFrameFlags GetFlags(void); | |
virtual HRESULT GetBytes(/* out */ void** buffer); | |
virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) ; | |
virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary** ancillary); | |
// IDeckLinkVideoFrameMetadataExtensions | |
virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ int64_t *value); | |
virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ double *value); | |
virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ bool* value); | |
virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ const char **value); | |
protected: | |
int32_t m_refCount; | |
IDeckLinkVideoFrame* _video_frame; | |
bool _activate_metadata = false; | |
int64_t _hdr_eotf = 2; | |
double _hdr_primary_red_x = 0.708; | |
double _hdr_primary_red_y = 0.292; | |
double _hdr_primary_green_x = 0.170; | |
double _hdr_primary_green_y = 0.797; | |
double _hdr_primary_blue_x = 0.131; | |
double _hdr_primary_blue_y = 0.046; | |
double _hdr_primary_white_x = 0.3127; | |
double _hdr_primary_white_y = 0.3290; | |
double _hdr_max_master_disp_lum = 4000.0; | |
double _hdr_min_master_disp_lum = 0.005; | |
double _hdr_maximum_content_light_level = 4000.0; | |
double _hdr_maximum_average_frame_light_level = 50.0; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Simple example based on TestPattern example from the blackmagic SDK (as suggested in their FAQ I used the VideoFrame3D sample code as a base. Not sure about correct cleanup implementation as I don't fully understand that part of their reference handling yet.