1 // Copyright (C) 2019 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include "host-common/GoldfishMediaDefs.h" 18 #include "host-common/H264NaluParser.h" 19 #include "host-common/H264PingInfoParser.h" 20 #include "host-common/MediaCodec.h" 21 #include "host-common/MediaH264DecoderPlugin.h" 22 #include "host-common/MediaHostRenderer.h" 23 24 #include <cstdint> 25 #include <list> 26 #include <mutex> 27 #include <string> 28 #include <vector> 29 30 extern "C" { 31 #include "host-common/dynlink_cuda.h" 32 #include "host-common/dynlink_nvcuvid.h" 33 } 34 #include <stdio.h> 35 #include <string.h> 36 37 #include <stddef.h> 38 39 namespace android { 40 namespace emulation { 41 42 class MediaH264DecoderCuvid : public MediaH264DecoderPlugin { 43 public: 44 virtual void reset(void* ptr) override; 45 virtual void initH264Context(void* ptr) override; 46 virtual MediaH264DecoderPlugin* clone() override; 47 virtual void destroyH264Context() override; 48 virtual void decodeFrame(void* ptr) override; 49 virtual void flush(void* ptr) override; 50 virtual void getImage(void* ptr) override; 51 52 explicit MediaH264DecoderCuvid(uint64_t id, H264PingInfoParser parser); 53 virtual ~MediaH264DecoderCuvid(); 54 55 virtual void save(base::Stream* stream) const override; 56 virtual bool load(base::Stream* stream) override; 57 type()58 virtual int type() const override { return PLUGIN_TYPE_CUVID; } 59 60 private: 61 void initH264ContextInternal(unsigned int width, 62 unsigned int height, 63 unsigned int outWidth, 64 unsigned int outHeight, 65 PixelFormat pixFmt); 66 uint32_t mId = 0; 67 H264PingInfoParser mParser; 68 MediaHostRenderer mRenderer; 69 70 // void decodeFrameInternal(void* ptr, const uint8_t* frame, size_t szBytes, 71 // uint64_t pts, size_t consumedSzBytes); 72 // We should move these shared memory calls elsewhere, as vpx decoder is 73 // also using the same/similar functions 74 static void* getReturnAddress(void* ptr); 75 static uint8_t* getDst(void* ptr); 76 77 uint64_t mOutputPts = 0; 78 std::vector<uint8_t> mSPS; // sps NALU 79 std::vector<uint8_t> mPPS; // pps NALU 80 81 bool mIsInFlush = false; 82 83 public: 84 // cuda related methods 85 static bool initCudaDrivers(); 86 static bool s_isCudaInitialized; 87 88 private: 89 // cuda call back HandleVideoSequenceProc(void * pUserData,CUVIDEOFORMAT * pVideoFormat)90 static int CUDAAPI HandleVideoSequenceProc(void* pUserData, 91 CUVIDEOFORMAT* pVideoFormat) { 92 return ((MediaH264DecoderCuvid*)pUserData) 93 ->HandleVideoSequence(pVideoFormat); 94 } HandlePictureDecodeProc(void * pUserData,CUVIDPICPARAMS * pPicParams)95 static int CUDAAPI HandlePictureDecodeProc(void* pUserData, 96 CUVIDPICPARAMS* pPicParams) { 97 return ((MediaH264DecoderCuvid*)pUserData) 98 ->HandlePictureDecode(pPicParams); 99 } 100 static int CUDAAPI HandlePictureDisplayProc(void * pUserData,CUVIDPARSERDISPINFO * pDispInfo)101 HandlePictureDisplayProc(void* pUserData, CUVIDPARSERDISPINFO* pDispInfo) { 102 return ((MediaH264DecoderCuvid*)pUserData) 103 ->HandlePictureDisplay(pDispInfo); 104 } 105 106 int HandleVideoSequence(CUVIDEOFORMAT* pVideoFormat); 107 108 int HandlePictureDecode(CUVIDPICPARAMS* pPicParams); 109 110 int HandlePictureDisplay(CUVIDPARSERDISPINFO* pDispInfo); 111 112 void doFlush(); 113 114 private: 115 // image props 116 bool mUseGpuTexture = false; 117 bool mImageReady = false; 118 static constexpr int kBPP = 2; // YUV420 is 2 bytes per pixel 119 unsigned int mHeight = 0; 120 unsigned int mWidth = 0; 121 unsigned int mOutputHeight = 0; 122 unsigned int mOutputWidth = 0; 123 unsigned int mSurfaceHeight = 0; 124 unsigned int mBPP = 0; 125 unsigned int mSurfaceWidth = 0; 126 unsigned int mLumaWidth = 0; 127 unsigned int mLumaHeight = 0; 128 unsigned int mChromaHeight = 0; 129 PixelFormat mOutPixFmt; 130 unsigned int mOutBufferSize = 0; 131 132 unsigned int mColorPrimaries = 2; 133 unsigned int mColorRange = 0; 134 unsigned int mColorTransfer = 2; 135 unsigned int mColorSpace = 2; 136 137 // right now, decoding command only passes the input address; 138 // and output address is only available in getImage(). 139 // TODO: this should be set to the output address to avoid 140 // extra copying 141 mutable std::list<int> mSavedW; 142 mutable std::list<int> mSavedH; 143 mutable std::list<uint64_t> mSavedPts; 144 // mSavedFrames are byte frames saved on CPU 145 mutable std::list<std::vector<uint8_t>> mSavedFrames; 146 // mSavedTexFrames are texture frames saved on GPU 147 mutable std::list<MediaHostRenderer::TextureFrame> mSavedTexFrames; 148 std::mutex mFrameLock; 149 150 // cuda stuff 151 CUcontext mCudaContext = nullptr; 152 CUvideoctxlock mCtxLock; 153 CUvideoparser mCudaParser = nullptr; 154 CUvideodecoder mCudaDecoder = nullptr; 155 156 private: 157 bool mIsLoadingFromSnapshot = false; 158 mutable SnapshotState mSnapshotState; 159 void oneShotDecode(std::vector<uint8_t>& data, uint64_t pts); 160 161 void decodeFrameInternal(uint64_t* pRetSzBytes, 162 int32_t* pRetErr, 163 const uint8_t* frame, 164 size_t szBytes, 165 uint64_t inputPts); 166 }; // MediaH264DecoderCuvid 167 } // namespace emulation 168 } // namespace android 169