NTSTATUS NTAPI HookedNtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) { //checkStructAlignment(); if (SystemInformationClass == SystemKernelDebuggerInformation || SystemInformationClass == SystemProcessInformation) { NTSTATUS ntStat = DllExchange.dNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if (NT_SUCCESS(ntStat) && SystemInformation != 0 && SystemInformationLength != 0) { if (SystemInformationClass == SystemKernelDebuggerInformation) { ((PSYSTEM_KERNEL_DEBUGGER_INFORMATION)SystemInformation)->KernelDebuggerEnabled = FALSE; ((PSYSTEM_KERNEL_DEBUGGER_INFORMATION)SystemInformation)->KernelDebuggerNotPresent = TRUE; } else if (SystemInformationClass == SystemProcessInformation) { FilterProcess((PSYSTEM_PROCESS_INFORMATION)SystemInformation); FakeCurrentParentProcessId((PSYSTEM_PROCESS_INFORMATION)SystemInformation); } } return ntStat; } return DllExchange.dNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); }
int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double pts) { int iGotPicture = 0, len = 0; if (!m_pCodecContext) return VC_ERROR; if (pData) m_iLastKeyframe++; if (m_pHardware) { int result; if (pData || (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) { result = m_pHardware->Check(m_pCodecContext); result &= ~VC_NOBUFFER; } else { result = m_pHardware->Decode(m_pCodecContext, nullptr); } if (result) return result; } if (!m_pHardware && pData) SetFilters(); if (m_pFilterGraph && !m_filterEof) { int result = 0; if (pData == NULL) result = FilterProcess(nullptr); if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) { result &= VC_PICTURE; } if (result) return result; } m_dts = dts; m_pCodecContext->reordered_opaque = pts_dtoi(pts); AVPacket avpkt; av_init_packet(&avpkt); avpkt.data = pData; avpkt.size = iSize; avpkt.dts = (dts == DVD_NOPTS_VALUE) ? AV_NOPTS_VALUE : dts / DVD_TIME_BASE * AV_TIME_BASE; avpkt.pts = (pts == DVD_NOPTS_VALUE) ? AV_NOPTS_VALUE : pts / DVD_TIME_BASE * AV_TIME_BASE; /* We lie, but this flag is only used by pngdec.c. * Setting it correctly would allow CorePNG decoding. */ avpkt.flags = AV_PKT_FLAG_KEY; len = avcodec_decode_video2(m_pCodecContext, m_pDecodedFrame, &iGotPicture, &avpkt); if (m_decoderState == STATE_HW_FAILED && !m_pHardware) return VC_REOPEN; if(m_iLastKeyframe < m_pCodecContext->has_b_frames + 2) m_iLastKeyframe = m_pCodecContext->has_b_frames + 2; if (len < 0) { if(m_pHardware) { int result = m_pHardware->Check(m_pCodecContext); if (result & VC_NOBUFFER) { result = m_pHardware->Decode(m_pCodecContext, NULL); return result; } } CLog::Log(LOGERROR, "%s - avcodec_decode_video returned failure", __FUNCTION__); return VC_ERROR; } if (!iGotPicture) { if (pData && m_pCodecContext->skip_frame > AVDISCARD_DEFAULT) { m_droppedFrames++; if (m_interlaced) m_droppedFrames++; } if (m_pHardware && (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) { int result; result = m_pHardware->Decode(m_pCodecContext, NULL); return result; } else return VC_BUFFER; } if (m_pDecodedFrame->key_frame) { m_started = true; m_iLastKeyframe = m_pCodecContext->has_b_frames + 2; } if (m_pDecodedFrame->interlaced_frame) m_interlaced = true; else m_interlaced = false; /* put a limit on convergence count to avoid huge mem usage on streams without keyframes */ if (m_iLastKeyframe > 300) m_iLastKeyframe = 300; /* h264 doesn't always have keyframes + won't output before first keyframe anyway */ if(m_pCodecContext->codec_id == AV_CODEC_ID_H264 || m_pCodecContext->codec_id == AV_CODEC_ID_SVQ3) m_started = true; if (m_pHardware == nullptr) { bool need_scale = std::find( m_formats.begin() , m_formats.end() , m_pCodecContext->pix_fmt) == m_formats.end(); bool need_reopen = false; if (m_filters != m_filters_next) need_reopen = true; if (!m_filters_next.empty() && m_filterEof) need_reopen = true; if (m_pFilterIn) { if (m_pFilterIn->outputs[0]->format != m_pCodecContext->pix_fmt || m_pFilterIn->outputs[0]->w != m_pCodecContext->width || m_pFilterIn->outputs[0]->h != m_pCodecContext->height) need_reopen = true; } // try to setup new filters if (need_reopen || (need_scale && m_pFilterGraph == nullptr)) { m_filters = m_filters_next; if (FilterOpen(m_filters, need_scale) < 0) FilterClose(); } } int result; if (m_pHardware) { av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pDecodedFrame); result = m_pHardware->Decode(m_pCodecContext, m_pFrame); } else if (m_pFilterGraph && !m_filterEof) { result = FilterProcess(m_pDecodedFrame); } else { av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pDecodedFrame); result = VC_PICTURE | VC_BUFFER; } if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) result &= ~VC_BUFFER; if (result & VC_FLUSHED) Reset(); return result; }
CDVDVideoCodec::VCReturn CDVDVideoCodecFFmpeg::GetPicture(VideoPicture* pVideoPicture) { if (m_eof) { return VC_EOF; } // handle hw accelerators first, they may have frames ready if (m_pHardware) { int flags = m_codecControlFlags; flags &= ~DVD_CODEC_CTRL_DRAIN; m_pHardware->SetCodecControl(flags); CDVDVideoCodec::VCReturn ret = m_pHardware->Decode(m_pCodecContext, nullptr); if (ret == VC_PICTURE) { if (m_pHardware->GetPicture(m_pCodecContext, pVideoPicture)) return VC_PICTURE; else return VC_ERROR; } else if (ret == VC_BUFFER) ; else return ret; } else if (m_pFilterGraph && !m_filterEof) { CDVDVideoCodec::VCReturn ret = FilterProcess(nullptr); if (ret == VC_PICTURE) { if (!SetPictureParams(pVideoPicture)) return VC_ERROR; return VC_PICTURE; } else if (ret == VC_BUFFER) ; else return ret; } // process ffmpeg if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) { AVPacket avpkt; av_init_packet(&avpkt); avpkt.data = nullptr; avpkt.size = 0; avpkt.dts = AV_NOPTS_VALUE; avpkt.pts = AV_NOPTS_VALUE; avcodec_send_packet(m_pCodecContext, &avpkt); } int ret = avcodec_receive_frame(m_pCodecContext, m_pDecodedFrame); if (m_decoderState == STATE_HW_FAILED && !m_pHardware) return VC_REOPEN; if(m_iLastKeyframe < m_pCodecContext->has_b_frames + 2) m_iLastKeyframe = m_pCodecContext->has_b_frames + 2; if (ret == AVERROR_EOF) { // next drain hw accel or filter if (m_pHardware) { int flags = m_codecControlFlags; flags |= DVD_CODEC_CTRL_DRAIN; m_pHardware->SetCodecControl(flags); int ret = m_pHardware->Decode(m_pCodecContext, nullptr); if (ret == VC_PICTURE) { if (m_pHardware->GetPicture(m_pCodecContext, pVideoPicture)) return VC_PICTURE; else return VC_ERROR; } else { m_eof = true; CLog::Log(LOGDEBUG, "CDVDVideoCodecFFmpeg::GetPicture - eof hw accel"); return VC_EOF; } } else if (m_pFilterGraph && !m_filterEof) { int ret = FilterProcess(nullptr); if (ret == VC_PICTURE) { if (!SetPictureParams(pVideoPicture)) return VC_ERROR; else return VC_PICTURE; } else { m_eof = true; CLog::Log(LOGDEBUG, "CDVDVideoCodecFFmpeg::GetPicture - eof filter"); return VC_EOF; } } else { m_eof = true; CLog::Log(LOGDEBUG, "CDVDVideoCodecFFmpeg::GetPicture - eof"); return VC_EOF; } } else if (ret == AVERROR(EAGAIN)) { return VC_BUFFER; } else if (ret) { CLog::Log(LOGERROR, "%s - avcodec_receive_frame returned failure", __FUNCTION__); return VC_ERROR; } // here we got a frame int64_t framePTS = m_pDecodedFrame->best_effort_timestamp; if (m_pCodecContext->skip_frame > AVDISCARD_DEFAULT) { if (m_dropCtrl.m_state == CDropControl::VALID && m_dropCtrl.m_lastPTS != AV_NOPTS_VALUE && framePTS != AV_NOPTS_VALUE && framePTS > (m_dropCtrl.m_lastPTS + m_dropCtrl.m_diffPTS * 1.5)) { m_droppedFrames++; if (m_interlaced) m_droppedFrames++; } } m_dropCtrl.Process(framePTS, m_pCodecContext->skip_frame > AVDISCARD_DEFAULT); if (m_pDecodedFrame->key_frame) { m_started = true; m_iLastKeyframe = m_pCodecContext->has_b_frames + 2; } if (m_pDecodedFrame->interlaced_frame) m_interlaced = true; else m_interlaced = false; if (!m_started) { int frames = 300; if (m_dropCtrl.m_state == CDropControl::VALID) frames = static_cast<int>(6000000 / m_dropCtrl.m_diffPTS); if (m_iLastKeyframe >= frames && m_pDecodedFrame->pict_type == AV_PICTURE_TYPE_I) { m_started = true; } else { av_frame_unref(m_pDecodedFrame); return VC_BUFFER; } } // push the frame to hw decoder for further processing if (m_pHardware) { av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pDecodedFrame); CDVDVideoCodec::VCReturn ret = m_pHardware->Decode(m_pCodecContext, m_pFrame); if (ret == VC_FLUSHED) { Reset(); return ret; } else if (ret == VC_FATAL) { m_decoderState = STATE_HW_FAILED; return VC_REOPEN; } else if (ret == VC_PICTURE) { if (m_pHardware->GetPicture(m_pCodecContext, pVideoPicture)) return VC_PICTURE; else return VC_ERROR; } return ret; } // process filters for sw decoding else { SetFilters(); bool need_scale = std::find(m_formats.begin(), m_formats.end(), m_pCodecContext->pix_fmt) == m_formats.end(); bool need_reopen = false; if (m_filters != m_filters_next) need_reopen = true; if (!m_filters_next.empty() && m_filterEof) need_reopen = true; if (m_pFilterIn) { if (m_pFilterIn->outputs[0]->format != m_pCodecContext->pix_fmt || m_pFilterIn->outputs[0]->w != m_pCodecContext->width || m_pFilterIn->outputs[0]->h != m_pCodecContext->height) need_reopen = true; } // try to setup new filters if (need_reopen || (need_scale && m_pFilterGraph == nullptr)) { m_filters = m_filters_next; if (FilterOpen(m_filters, need_scale) < 0) FilterClose(); } if (m_pFilterGraph && !m_filterEof) { CDVDVideoCodec::VCReturn ret = FilterProcess(m_pDecodedFrame); if (ret != VC_PICTURE) return VC_NONE; } else { av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pDecodedFrame); } if (!SetPictureParams(pVideoPicture)) return VC_ERROR; else return VC_PICTURE; } return VC_NONE; }