• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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