Skip to content

Commit 1586795

Browse files
committed
HEVC 10bitのHWデコード時の問題を回避。( #70 )
デコードに失敗して同じフレームがしばらく帰ってきてしまい、フリーズしてしまったいた。 理由は不明だが、hevc_mp4toannexbの代わりに独自実装とすると回避できる。
1 parent 7a1f4e9 commit 1586795

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

NVEncCore/rgy_input_avcodec.cpp

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,51 @@ void RGYInputAvcodec::vc1AddFrameHeader(AVPacket *pkt) {
288288
}
289289
}
290290

291+
void RGYInputAvcodec::hevcMp42Annexb(AVPacket *pkt) {
292+
static const uint8_t SC[] = { 0, 0, 0, 1 };
293+
const uint8_t *ptr, *ptr_fin;
294+
if (pkt == NULL) {
295+
m_hevcMp42AnnexbBuffer.reserve(m_Demux.video.nExtradataSize + 128);
296+
ptr = m_Demux.video.pExtradata;
297+
ptr_fin = ptr + m_Demux.video.nExtradataSize;
298+
ptr += 0x16;
299+
} else {
300+
m_hevcMp42AnnexbBuffer.reserve(pkt->size + 128);
301+
ptr = pkt->data;
302+
ptr_fin = ptr + pkt->size;
303+
}
304+
const int numOfArrays = *ptr;
305+
ptr += !!numOfArrays;
306+
307+
while (ptr + 6 < ptr_fin) {
308+
ptr += !!numOfArrays;
309+
const int count = readUB16(ptr); ptr += 2;
310+
int units = (numOfArrays) ? count : 1;
311+
for (int i = (std::max)(1, units); i; i--) {
312+
uint32_t size = readUB16(ptr); ptr += 2;
313+
uint32_t uppper = count << 16;
314+
size += (numOfArrays) ? 0 : uppper;
315+
m_hevcMp42AnnexbBuffer.insert(m_hevcMp42AnnexbBuffer.end(), SC, SC+4);
316+
m_hevcMp42AnnexbBuffer.insert(m_hevcMp42AnnexbBuffer.end(), ptr, ptr+size); ptr += size;
317+
}
318+
}
319+
if (pkt) {
320+
if (pkt->buf->size < (int)m_hevcMp42AnnexbBuffer.size()) {
321+
av_grow_packet(pkt, (int)m_hevcMp42AnnexbBuffer.size());
322+
}
323+
memcpy(pkt->data, m_hevcMp42AnnexbBuffer.data(), m_hevcMp42AnnexbBuffer.size());
324+
pkt->size = (int)m_hevcMp42AnnexbBuffer.size();
325+
} else {
326+
if (m_Demux.video.pExtradata) {
327+
av_free(m_Demux.video.pExtradata);
328+
}
329+
m_Demux.video.pExtradata = (uint8_t *)av_malloc(m_hevcMp42AnnexbBuffer.size());
330+
m_Demux.video.nExtradataSize = (int)m_hevcMp42AnnexbBuffer.size();
331+
memcpy(m_Demux.video.pExtradata, m_hevcMp42AnnexbBuffer.data(), m_hevcMp42AnnexbBuffer.size());
332+
}
333+
m_hevcMp42AnnexbBuffer.clear();
334+
}
335+
291336
RGY_ERR RGYInputAvcodec::getFirstFramePosAndFrameRate(const sTrim *pTrimList, int nTrimCount, bool bDetectpulldown) {
292337
AVRational fpsDecoder = m_Demux.video.pStream->avg_frame_rate;
293338
const bool fpsDecoderInvalid = (fpsDecoder.den == 0 || fpsDecoder.num == 0);
@@ -942,7 +987,9 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *pInputInfo, c
942987

943988
//必要ならbitstream filterを初期化
944989
if (m_Demux.video.nHWDecodeDeviceId >= 0 && m_Demux.video.pStream->codecpar->extradata && m_Demux.video.pStream->codecpar->extradata[0] == 1) {
945-
if (m_Demux.video.pStream->codecpar->codec_id == AV_CODEC_ID_H264 ||
990+
if (m_Demux.video.pStream->codecpar->codec_id == AV_CODEC_ID_HEVC) {
991+
m_Demux.video.bUseHEVCmp42AnnexB = true;
992+
} else if (m_Demux.video.pStream->codecpar->codec_id == AV_CODEC_ID_H264 ||
946993
m_Demux.video.pStream->codecpar->codec_id == AV_CODEC_ID_HEVC) {
947994
const char *filtername = nullptr;
948995
switch (m_Demux.video.pStream->codecpar->codec_id) {
@@ -1035,7 +1082,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *pInputInfo, c
10351082
AddMessage(RGY_LOG_ERROR, _T("failed to copy codec param to context for parser: %s.\n"), qsv_av_err2str(ret).c_str());
10361083
return RGY_ERR_UNKNOWN;
10371084
}
1038-
if (m_Demux.video.pBsfcCtx) {
1085+
if (m_Demux.video.pBsfcCtx || m_Demux.video.bUseHEVCmp42AnnexB) {
10391086
SetExtraData(codecParamCopy.get(), m_Demux.video.pExtradata, m_Demux.video.nExtradataSize);
10401087
}
10411088
if (0 > (ret = avcodec_parameters_to_context(m_Demux.video.pCodecCtxParser, codecParamCopy.get()))) {
@@ -1157,7 +1204,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *pInputInfo, c
11571204
AddMessage(RGY_LOG_ERROR, _T("failed to copy codec param to context for parser: %s.\n"), qsv_av_err2str(ret).c_str());
11581205
return RGY_ERR_UNKNOWN;
11591206
}
1160-
if (m_Demux.video.pBsfcCtx) {
1207+
if (m_Demux.video.pBsfcCtx || m_Demux.video.bUseHEVCmp42AnnexB) {
11611208
SetExtraData(codecParamCopy.get(), m_Demux.video.pExtradata, m_Demux.video.nExtradataSize);
11621209
}
11631210
if (0 > (ret = avcodec_parameters_to_context(m_Demux.video.pCodecCtxDecode, codecParamCopy.get()))) {
@@ -1452,6 +1499,9 @@ int RGYInputAvcodec::getSample(AVPacket *pkt, bool bTreatFirstPacketAsKeyframe)
14521499
if (m_Demux.video.pStream->codecpar->codec_id == AV_CODEC_ID_VC1) {
14531500
vc1AddFrameHeader(pkt);
14541501
}
1502+
if (m_Demux.video.bUseHEVCmp42AnnexB) {
1503+
hevcMp42Annexb(pkt);
1504+
}
14551505
//最初のキーフレームを取得するまではスキップする
14561506
//スキップした枚数はi_samplesでカウントし、trim時に同期を適切にとるため、m_sTrimParam.offsetに格納する
14571507
// ただし、bTreatFirstPacketAsKeyframeが指定されている場合には、キーフレームでなくてもframePosListへの追加を許可する
@@ -1749,7 +1799,9 @@ RGY_ERR RGYInputAvcodec::GetHeader(RGYBitstream *pBitstream) {
17491799
memcpy(m_Demux.video.pExtradata, m_Demux.video.pStream->codecpar->extradata, m_Demux.video.nExtradataSize);
17501800
memset(m_Demux.video.pExtradata + m_Demux.video.nExtradataSize, 0, AV_INPUT_BUFFER_PADDING_SIZE);
17511801

1752-
if (m_Demux.video.pBsfcCtx && m_Demux.video.pExtradata[0] == 1) {
1802+
if (m_Demux.video.bUseHEVCmp42AnnexB) {
1803+
hevcMp42Annexb(nullptr);
1804+
} else if (m_Demux.video.pBsfcCtx && m_Demux.video.pExtradata[0] == 1) {
17531805
if (m_Demux.video.nExtradataSize < m_Demux.video.pBsfcCtx->par_out->extradata_size) {
17541806
m_Demux.video.pExtradata = (uint8_t *)av_realloc(m_Demux.video.pExtradata, m_Demux.video.pBsfcCtx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
17551807
}

NVEncCore/rgy_input_avcodec.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ typedef struct AVDemuxVideo {
690690
AVCodecContext *pCodecCtxParser; //動画ストリームのParser用
691691

692692
int nHWDecodeDeviceId; //HWデコードする場合に選択したデバイス
693+
694+
bool bUseHEVCmp42AnnexB;
693695
} AVDemuxVideo;
694696

695697
typedef struct AVDemuxStream {
@@ -857,6 +859,8 @@ class RGYInputAvcodec : public RGYInput
857859
//ptsを動画のtimebaseから音声のtimebaseに変換する
858860
int64_t convertTimebaseVidToStream(int64_t pts, const AVDemuxStream *pStream);
859861

862+
void hevcMp42Annexb(AVPacket *pkt);
863+
860864
//VC-1のヘッダの修正を行う
861865
void vc1FixHeader(int nLengthFix = -1);
862866

NVEncCore/rgy_version.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
#ifndef __RGY_CONFIG_H__
3030
#define __RGY_CONFIG_H__
3131

32-
#define VER_FILEVERSION 0,4,15,0
33-
#define VER_STR_FILEVERSION "4.15"
34-
#define VER_STR_FILEVERSION_TCHAR _T("4.15")
32+
#define VER_FILEVERSION 0,4,16,0
33+
#define VER_STR_FILEVERSION "4.16"
34+
#define VER_STR_FILEVERSION_TCHAR _T("4.16")
3535

3636
#ifdef _M_IX86
3737
#define BUILD_ARCH_STR _T("x86")

0 commit comments

Comments
 (0)