You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
5.6 KiB

// 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 <cstdint>
#include <list>
#include <mutex>
#include <string>
#include <vector>
extern "C" {
#include "host-common/dynlink_cuda.h"
#include "host-common/dynlink_nvcuvid.h"
}
#include <stdio.h>
#include <string.h>
#include <stddef.h>
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<uint8_t> mSPS; // sps NALU
std::vector<uint8_t> 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<int> mSavedW;
mutable std::list<int> mSavedH;
mutable std::list<uint64_t> mSavedPts;
// mSavedFrames are byte frames saved on CPU
mutable std::list<std::vector<uint8_t>> mSavedFrames;
// mSavedTexFrames are texture frames saved on GPU
mutable std::list<MediaHostRenderer::TextureFrame> 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<uint8_t>& 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