// Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include "host-common/GoldfishMediaDefs.h" #include "host-common/H264NaluParser.h" #include "host-common/H264PingInfoParser.h" #include "host-common/MediaCodec.h" #include "host-common/MediaH264DecoderPlugin.h" #include "host-common/MediaHostRenderer.h" #include #include #include #include #include extern "C" { #include "host-common/dynlink_cuda.h" #include "host-common/dynlink_nvcuvid.h" } #include #include #include namespace android { namespace emulation { class MediaH264DecoderCuvid : public MediaH264DecoderPlugin { public: virtual void reset(void* ptr) override; virtual void initH264Context(void* ptr) override; virtual MediaH264DecoderPlugin* clone() override; virtual void destroyH264Context() override; virtual void decodeFrame(void* ptr) override; virtual void flush(void* ptr) override; virtual void getImage(void* ptr) override; explicit MediaH264DecoderCuvid(uint64_t id, H264PingInfoParser parser); virtual ~MediaH264DecoderCuvid(); virtual void save(base::Stream* stream) const override; virtual bool load(base::Stream* stream) override; virtual int type() const override { return PLUGIN_TYPE_CUVID; } private: void initH264ContextInternal(unsigned int width, unsigned int height, unsigned int outWidth, unsigned int outHeight, PixelFormat pixFmt); uint32_t mId = 0; H264PingInfoParser mParser; MediaHostRenderer mRenderer; // void decodeFrameInternal(void* ptr, const uint8_t* frame, size_t szBytes, // uint64_t pts, size_t consumedSzBytes); // We should move these shared memory calls elsewhere, as vpx decoder is // also using the same/similar functions static void* getReturnAddress(void* ptr); static uint8_t* getDst(void* ptr); uint64_t mOutputPts = 0; std::vector mSPS; // sps NALU std::vector mPPS; // pps NALU bool mIsInFlush = false; public: // cuda related methods static bool initCudaDrivers(); static bool s_isCudaInitialized; private: // cuda call back static int CUDAAPI HandleVideoSequenceProc(void* pUserData, CUVIDEOFORMAT* pVideoFormat) { return ((MediaH264DecoderCuvid*)pUserData) ->HandleVideoSequence(pVideoFormat); } static int CUDAAPI HandlePictureDecodeProc(void* pUserData, CUVIDPICPARAMS* pPicParams) { return ((MediaH264DecoderCuvid*)pUserData) ->HandlePictureDecode(pPicParams); } static int CUDAAPI HandlePictureDisplayProc(void* pUserData, CUVIDPARSERDISPINFO* pDispInfo) { return ((MediaH264DecoderCuvid*)pUserData) ->HandlePictureDisplay(pDispInfo); } int HandleVideoSequence(CUVIDEOFORMAT* pVideoFormat); int HandlePictureDecode(CUVIDPICPARAMS* pPicParams); int HandlePictureDisplay(CUVIDPARSERDISPINFO* pDispInfo); void doFlush(); private: // image props bool mUseGpuTexture = false; bool mImageReady = false; static constexpr int kBPP = 2; // YUV420 is 2 bytes per pixel unsigned int mHeight = 0; unsigned int mWidth = 0; unsigned int mOutputHeight = 0; unsigned int mOutputWidth = 0; unsigned int mSurfaceHeight = 0; unsigned int mBPP = 0; unsigned int mSurfaceWidth = 0; unsigned int mLumaWidth = 0; unsigned int mLumaHeight = 0; unsigned int mChromaHeight = 0; PixelFormat mOutPixFmt; unsigned int mOutBufferSize = 0; unsigned int mColorPrimaries = 2; unsigned int mColorRange = 0; unsigned int mColorTransfer = 2; unsigned int mColorSpace = 2; // right now, decoding command only passes the input address; // and output address is only available in getImage(). // TODO: this should be set to the output address to avoid // extra copying mutable std::list mSavedW; mutable std::list mSavedH; mutable std::list mSavedPts; // mSavedFrames are byte frames saved on CPU mutable std::list> mSavedFrames; // mSavedTexFrames are texture frames saved on GPU mutable std::list mSavedTexFrames; std::mutex mFrameLock; // cuda stuff CUcontext mCudaContext = nullptr; CUvideoctxlock mCtxLock; CUvideoparser mCudaParser = nullptr; CUvideodecoder mCudaDecoder = nullptr; private: bool mIsLoadingFromSnapshot = false; mutable SnapshotState mSnapshotState; void oneShotDecode(std::vector& data, uint64_t pts); void decodeFrameInternal(uint64_t* pRetSzBytes, int32_t* pRetErr, const uint8_t* frame, size_t szBytes, uint64_t inputPts); }; // MediaH264DecoderCuvid } // namespace emulation } // namespace android