mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-10-25 02:10:51 +00:00
Fixed Metal video decode presenting stale pictures, and added AV1 decode on Metal. (#4047)
This commit is contained in:
committed by
GitHub
parent
ec6e934a2d
commit
cd84669abc
69
src/video.h
69
src/video.h
@@ -258,11 +258,6 @@ namespace bgfx
|
||||
return poc;
|
||||
}
|
||||
|
||||
inline bool isInRange(int32_t _value, int32_t _min, int32_t _max)
|
||||
{
|
||||
return _min <= _value && _value <= _max;
|
||||
}
|
||||
|
||||
static constexpr int32_t kVideoMaxH264SizeInMbsMinus1 = 1023;
|
||||
|
||||
inline bool isDecodableProfile(int32_t _profileIdc)
|
||||
@@ -278,17 +273,17 @@ namespace bgfx
|
||||
{
|
||||
return true
|
||||
&& isDecodableProfile(_sps.profile_idc)
|
||||
&& isInRange(_sps.seq_parameter_set_id, 0, h264::MAX_SPS_ID)
|
||||
&& isInRange(_sps.chroma_format_idc, 0, h264::MAX_CHROMA_FORMAT_IDC)
|
||||
&& isInRange(_sps.bit_depth_luma_minus8, 0, h264::MAX_BIT_DEPTH_MINUS8)
|
||||
&& isInRange(_sps.bit_depth_chroma_minus8, 0, h264::MAX_BIT_DEPTH_MINUS8)
|
||||
&& isInRange(_sps.log2_max_frame_num_minus4, 0, h264::MAX_LOG2_MINUS4)
|
||||
&& isInRange(_sps.pic_order_cnt_type, 0, h264::MAX_PIC_ORDER_CNT_TYPE)
|
||||
&& isInRange(_sps.log2_max_pic_order_cnt_lsb_minus4, 0, h264::MAX_LOG2_MINUS4)
|
||||
&& isInRange(_sps.num_ref_frames_in_pic_order_cnt_cycle, 0, h264::MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE)
|
||||
&& isInRange(_sps.num_ref_frames, 0, h264::MAX_NUM_REF_FRAMES)
|
||||
&& isInRange(_sps.pic_width_in_mbs_minus1, 0, kVideoMaxH264SizeInMbsMinus1)
|
||||
&& isInRange(_sps.pic_height_in_map_units_minus1, 0, kVideoMaxH264SizeInMbsMinus1)
|
||||
&& bx::isInRange(_sps.seq_parameter_set_id, 0, h264::MAX_SPS_ID)
|
||||
&& bx::isInRange(_sps.chroma_format_idc, 0, h264::MAX_CHROMA_FORMAT_IDC)
|
||||
&& bx::isInRange(_sps.bit_depth_luma_minus8, 0, h264::MAX_BIT_DEPTH_MINUS8)
|
||||
&& bx::isInRange(_sps.bit_depth_chroma_minus8, 0, h264::MAX_BIT_DEPTH_MINUS8)
|
||||
&& bx::isInRange(_sps.log2_max_frame_num_minus4, 0, h264::MAX_LOG2_MINUS4)
|
||||
&& bx::isInRange(_sps.pic_order_cnt_type, 0, h264::MAX_PIC_ORDER_CNT_TYPE)
|
||||
&& bx::isInRange(_sps.log2_max_pic_order_cnt_lsb_minus4, 0, h264::MAX_LOG2_MINUS4)
|
||||
&& bx::isInRange(_sps.num_ref_frames_in_pic_order_cnt_cycle, 0, h264::MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE)
|
||||
&& bx::isInRange(_sps.num_ref_frames, 0, h264::MAX_NUM_REF_FRAMES)
|
||||
&& bx::isInRange(_sps.pic_width_in_mbs_minus1, 0, kVideoMaxH264SizeInMbsMinus1)
|
||||
&& bx::isInRange(_sps.pic_height_in_map_units_minus1, 0, kVideoMaxH264SizeInMbsMinus1)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -298,16 +293,16 @@ namespace bgfx
|
||||
const int32_t maxQpInit = h264::MAX_QP - h264::PIC_INIT_QP;
|
||||
|
||||
return true
|
||||
&& isInRange(_pps.pic_parameter_set_id, 0, h264::MAX_PPS_ID)
|
||||
&& isInRange(_pps.seq_parameter_set_id, 0, h264::MAX_SPS_ID)
|
||||
&& bx::isInRange(_pps.pic_parameter_set_id, 0, h264::MAX_PPS_ID)
|
||||
&& bx::isInRange(_pps.seq_parameter_set_id, 0, h264::MAX_SPS_ID)
|
||||
&& 0 == _pps.num_slice_groups_minus1
|
||||
&& isInRange(_pps.num_ref_idx_l0_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& isInRange(_pps.num_ref_idx_l1_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& isInRange(_pps.weighted_bipred_idc, 0, h264::MAX_WEIGHTED_BIPRED_IDC)
|
||||
&& isInRange(_pps.pic_init_qp_minus26, -h264::PIC_INIT_QP - qpBdOffset, maxQpInit)
|
||||
&& isInRange(_pps.pic_init_qs_minus26, -h264::PIC_INIT_QP, maxQpInit)
|
||||
&& isInRange(_pps.chroma_qp_index_offset, -h264::MAX_CHROMA_QP_INDEX_OFFSET, h264::MAX_CHROMA_QP_INDEX_OFFSET)
|
||||
&& isInRange(_pps.second_chroma_qp_index_offset, -h264::MAX_CHROMA_QP_INDEX_OFFSET, h264::MAX_CHROMA_QP_INDEX_OFFSET)
|
||||
&& bx::isInRange(_pps.num_ref_idx_l0_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& bx::isInRange(_pps.num_ref_idx_l1_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& bx::isInRange(_pps.weighted_bipred_idc, 0, h264::MAX_WEIGHTED_BIPRED_IDC)
|
||||
&& bx::isInRange(_pps.pic_init_qp_minus26, -h264::PIC_INIT_QP - qpBdOffset, maxQpInit)
|
||||
&& bx::isInRange(_pps.pic_init_qs_minus26, -h264::PIC_INIT_QP, maxQpInit)
|
||||
&& bx::isInRange(_pps.chroma_qp_index_offset, -h264::MAX_CHROMA_QP_INDEX_OFFSET, h264::MAX_CHROMA_QP_INDEX_OFFSET)
|
||||
&& bx::isInRange(_pps.second_chroma_qp_index_offset, -h264::MAX_CHROMA_QP_INDEX_OFFSET, h264::MAX_CHROMA_QP_INDEX_OFFSET)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -320,17 +315,17 @@ namespace bgfx
|
||||
const int32_t mbaff = 0 != _sps.mb_adaptive_frame_field_flag && 0 == _sh.field_pic_flag ? 1 : 0;
|
||||
|
||||
return true
|
||||
&& isInRange(_sh.first_mb_in_slice * (1 + mbaff), 0, picSizeInMbs - 1)
|
||||
&& isInRange(_sh.slice_type, 0, h264::MAX_SLICE_TYPE)
|
||||
&& isInRange(sliceQp, -qpBdOffset, h264::MAX_QP)
|
||||
&& isInRange(_sh.num_ref_idx_l0_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& isInRange(_sh.num_ref_idx_l1_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& isInRange(_sh.cabac_init_idc, 0, h264::MAX_CABAC_INIT_IDC)
|
||||
&& isInRange(_sh.disable_deblocking_filter_idc, 0, h264::MAX_DISABLE_DEBLOCKING_FILTER_IDC)
|
||||
&& isInRange(_sh.slice_alpha_c0_offset_div2, -h264::MAX_DEBLOCKING_OFFSET_DIV2, h264::MAX_DEBLOCKING_OFFSET_DIV2)
|
||||
&& isInRange(_sh.slice_beta_offset_div2, -h264::MAX_DEBLOCKING_OFFSET_DIV2, h264::MAX_DEBLOCKING_OFFSET_DIV2)
|
||||
&& isInRange(_sh.idr_pic_id, 0, h264::MAX_IDR_PIC_ID)
|
||||
&& isInRange(_sh.redundant_pic_cnt, 0, h264::MAX_REDUNDANT_PIC_CNT)
|
||||
&& bx::isInRange(_sh.first_mb_in_slice * (1 + mbaff), 0, picSizeInMbs - 1)
|
||||
&& bx::isInRange(_sh.slice_type, 0, h264::MAX_SLICE_TYPE)
|
||||
&& bx::isInRange(sliceQp, -qpBdOffset, h264::MAX_QP)
|
||||
&& bx::isInRange(_sh.num_ref_idx_l0_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& bx::isInRange(_sh.num_ref_idx_l1_active_minus1, 0, h264::MAX_NUM_REF_IDX_ACTIVE_MINUS1)
|
||||
&& bx::isInRange(_sh.cabac_init_idc, 0, h264::MAX_CABAC_INIT_IDC)
|
||||
&& bx::isInRange(_sh.disable_deblocking_filter_idc, 0, h264::MAX_DISABLE_DEBLOCKING_FILTER_IDC)
|
||||
&& bx::isInRange(_sh.slice_alpha_c0_offset_div2, -h264::MAX_DEBLOCKING_OFFSET_DIV2, h264::MAX_DEBLOCKING_OFFSET_DIV2)
|
||||
&& bx::isInRange(_sh.slice_beta_offset_div2, -h264::MAX_DEBLOCKING_OFFSET_DIV2, h264::MAX_DEBLOCKING_OFFSET_DIV2)
|
||||
&& bx::isInRange(_sh.idr_pic_id, 0, h264::MAX_IDR_PIC_ID)
|
||||
&& bx::isInRange(_sh.redundant_pic_cnt, 0, h264::MAX_REDUNDANT_PIC_CNT)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -434,7 +429,7 @@ namespace bgfx
|
||||
h264::PPS pps = {};
|
||||
h264::read_pps(&pps, &nalBs);
|
||||
|
||||
if (isInRange(pps.seq_parameter_set_id, 0, int32_t(_spsArrayLen) - 1)
|
||||
if (bx::isInRange(pps.seq_parameter_set_id, 0, int32_t(_spsArrayLen) - 1)
|
||||
&& isPpsInRange(pps, _spsArray[pps.seq_parameter_set_id])
|
||||
&& pps.pic_parameter_set_id < (int)_ppsArrayLen)
|
||||
{
|
||||
|
||||
1525
src/video_mtl.cpp
1525
src/video_mtl.cpp
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@ static const bgfx::EmbeddedShader s_embeddedShaders[] =
|
||||
BGFX_EMBEDDED_SHADER_END()
|
||||
};
|
||||
|
||||
static bx::StringView s_supportedExt[32];
|
||||
static bx::StringView s_supportedExt[64];
|
||||
static uint32_t s_numSupportedExt = 0;
|
||||
|
||||
static int32_t compareExt(const void* _lhs, const void* _rhs)
|
||||
@@ -850,29 +850,55 @@ struct View
|
||||
&& bx::FileType::File == fi.type)
|
||||
{
|
||||
bx::StringView ext = fi.filePath.getExt();
|
||||
bool supported = false;
|
||||
|
||||
if (!ext.isEmpty() )
|
||||
{
|
||||
ext.set(ext.getPtr()+1, ext.getTerm() );
|
||||
supported = isExtSupported(ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
bx::FilePath fullPath = m_path;
|
||||
fullPath.join(fi.filePath.getFileName() );
|
||||
supported = VideoPlayer::isVideoFile(fullPath);
|
||||
}
|
||||
|
||||
if (isExtSupported(ext) )
|
||||
{
|
||||
const bx::StringView fileName = fi.filePath.getFileName();
|
||||
m_fileList.push_back(std::string(fileName.getPtr(), fileName.getTerm() ) );
|
||||
}
|
||||
if (supported)
|
||||
{
|
||||
const bx::StringView fileName = fi.filePath.getFileName();
|
||||
m_fileList.push_back(std::string(fileName.getPtr(), fileName.getTerm() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bx::close(&dr);
|
||||
|
||||
const bx::StringView fileName = _filePath.getFileName();
|
||||
|
||||
{
|
||||
bx::FileInfo fi;
|
||||
bool listed = false;
|
||||
|
||||
for (FileList::const_iterator it = m_fileList.begin(); it != m_fileList.end(); ++it)
|
||||
{
|
||||
listed |= 0 == bx::strCmp(it->c_str(), fileName);
|
||||
}
|
||||
|
||||
if (!listed
|
||||
&& !fileName.isEmpty()
|
||||
&& bx::stat(fi, _filePath)
|
||||
&& bx::FileType::File == fi.type)
|
||||
{
|
||||
m_fileList.push_back(std::string(fileName.getPtr(), fileName.getTerm() ) );
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(m_fileList.begin(), m_fileList.end(), sortNameAscending);
|
||||
|
||||
m_fileIndex = 0;
|
||||
uint32_t idx = 0;
|
||||
|
||||
const bx::StringView fileName = _filePath.getFileName();
|
||||
|
||||
for (FileList::const_iterator it = m_fileList.begin(); it != m_fileList.end(); ++it, ++idx)
|
||||
{
|
||||
if (0 == bx::strCmpI(it->c_str(), fileName) )
|
||||
@@ -1564,7 +1590,41 @@ int _main_(int _argc, char** _argv)
|
||||
|
||||
if (0 != (caps->supported & BGFX_CAPS_VIDEO_DECODE) )
|
||||
{
|
||||
s_supportedExt[s_numSupportedExt++] = "mp4";
|
||||
struct CodecExt
|
||||
{
|
||||
bgfx::VideoCodec::Enum codec;
|
||||
const char* const* ext;
|
||||
};
|
||||
|
||||
static const char* const s_containerExt[] = { "mp4", "m4v", "mov", NULL };
|
||||
static const char* const s_h264Ext[] = { "264", "h264", NULL };
|
||||
static const char* const s_h265Ext[] = { "265", "h265", "hevc", NULL };
|
||||
static const char* const s_av1Ext[] = { "av1", "obu", "ivf", NULL };
|
||||
|
||||
static const CodecExt s_codecExt[] =
|
||||
{
|
||||
{ bgfx::VideoCodec::Count, s_containerExt },
|
||||
{ bgfx::VideoCodec::H264, s_h264Ext },
|
||||
{ bgfx::VideoCodec::H265, s_h265Ext },
|
||||
{ bgfx::VideoCodec::AV1, s_av1Ext },
|
||||
};
|
||||
|
||||
for (uint32_t ii = 0; ii < BX_COUNTOF(s_codecExt); ++ii)
|
||||
{
|
||||
const CodecExt& codecExt = s_codecExt[ii];
|
||||
|
||||
if (bgfx::VideoCodec::Count != codecExt.codec
|
||||
&& 0 == caps->codecs[codecExt.codec])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const char* const* ext = codecExt.ext; NULL != *ext && s_numSupportedExt < BX_COUNTOF(s_supportedExt); ++ext)
|
||||
{
|
||||
s_supportedExt[s_numSupportedExt++] = *ext;
|
||||
}
|
||||
}
|
||||
|
||||
bx::quickSort(s_supportedExt, s_numSupportedExt, sizeof(s_supportedExt[0]), compareExt);
|
||||
}
|
||||
|
||||
@@ -2453,18 +2513,7 @@ int _main_(int _argc, char** _argv)
|
||||
bx::FilePath fp = view.m_path;
|
||||
fp.join(view.m_fileList[view.m_fileIndex].c_str() );
|
||||
|
||||
bx::StringView fileName(view.m_fileList[view.m_fileIndex].c_str() );
|
||||
|
||||
bx::StringView ext;
|
||||
if (fileName.getLength() >= 4)
|
||||
{
|
||||
ext.set(fileName.getTerm() - 4, fileName.getTerm() );
|
||||
}
|
||||
|
||||
const bool nextIsVideo = false
|
||||
|| 0 == bx::strCmpI(ext, ".mp4")
|
||||
|| 0 == bx::strCmpI(ext, ".m4v")
|
||||
;
|
||||
const bool nextIsVideo = VideoPlayer::isVideoFile(fp);
|
||||
|
||||
if (videoOwnsTexture)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
#define TEXTUREV_VIDEO_PLAYER_H_HEADER_GUARD
|
||||
|
||||
#include <bgfx/bgfx.h>
|
||||
#include <bx/string.h>
|
||||
#include <bx/filepath.h>
|
||||
|
||||
class VideoPlayer
|
||||
{
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
VideoPlayer();
|
||||
~VideoPlayer();
|
||||
|
||||
static bool isVideoExt(const bx::StringView& _ext);
|
||||
static bool isVideoFile(const bx::FilePath& _filePath);
|
||||
|
||||
bool open(const char* _filePath);
|
||||
void close();
|
||||
|
||||
Reference in New Issue
Block a user