| // 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 <VideoToolbox/VideoToolbox.h> |
| |
| #include <cstdint> |
| #include <string> |
| #include <vector> |
| |
| #include <stdio.h> |
| #include <string.h> |
| |
| #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder |
| #define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder") |
| #endif |
| |
| |
| #include <stddef.h> |
| |
| namespace android { |
| namespace emulation { |
| |
| class MediaH264DecoderVideoToolBox : public MediaH264DecoderPlugin { |
| public: |
| virtual void initH264Context(void* ptr) override; |
| virtual void reset(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; |
| |
| virtual void save(base::Stream* stream) const override; |
| virtual bool load(base::Stream* stream) override; |
| |
| virtual int type() const override { return PLUGIN_TYPE_VIDEO_TOOL_BOX; } |
| |
| |
| explicit MediaH264DecoderVideoToolBox(uint64_t id, |
| H264PingInfoParser parser); |
| virtual ~MediaH264DecoderVideoToolBox(); |
| |
| public: |
| enum class DecoderState { |
| BAD_STATE = 0, |
| GOOD_STATE = 1, |
| }; |
| |
| DecoderState getState() const {return mState;} |
| std::vector<uint8_t> getSPS() const { return mSPS; } |
| std::vector<uint8_t> getPPS() const { return mPPS; } |
| private: |
| void initH264ContextInternal(unsigned int width, |
| unsigned int height, |
| unsigned int outWidth, |
| unsigned int outHeight, |
| PixelFormat pixFmt); |
| uint64_t mId = 0; |
| H264PingInfoParser mParser; |
| MediaHostRenderer mRenderer; |
| DecoderState mState = DecoderState::GOOD_STATE; |
| |
| void decodeFrameInternal(size_t* pRetSzBytes, int32_t* pRetErr, const uint8_t* frame, size_t szBytes, uint64_t pts, size_t consumedSzBytes); |
| // Passes the Sequence Parameter Set (SPS) and Picture Parameter Set (PPS) to the |
| // videotoolbox decoder |
| CFDataRef createVTDecoderConfig(); |
| // Callback passed to the VTDecompressionSession |
| static void videoToolboxDecompressCallback(void* opaque, |
| void* sourceFrameRefCon, |
| OSStatus status, |
| VTDecodeInfoFlags flags, |
| CVImageBufferRef image_buffer, |
| CMTime pts, |
| CMTime duration); |
| static CFDictionaryRef createOutputBufferAttributes(int width, |
| int height, |
| OSType pix_fmt); |
| static CMSampleBufferRef createSampleBuffer(CMFormatDescriptionRef fmtDesc, |
| void* buffer, |
| size_t sz); |
| static OSType toNativePixelFormat(PixelFormat fmt); |
| |
| // 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); |
| |
| void handleIDRFrame(const uint8_t* ptr, size_t szBytes, uint64_t pts); |
| void handleNonIDRFrame(const uint8_t* ptr, size_t szBytes, uint64_t pts); |
| void handleSEIFrame(const uint8_t* ptr, size_t szBytes); |
| |
| void createCMFormatDescription(); |
| void recreateDecompressionSession(); |
| |
| // The VideoToolbox decoder session |
| VTDecompressionSessionRef mDecoderSession = nullptr; |
| // The decoded video buffer |
| uint64_t mOutputPts = 0; |
| CVImageBufferRef mDecodedFrame = nullptr; |
| CMFormatDescriptionRef mCmFmtDesc = nullptr; |
| bool mImageReady = false; |
| static constexpr int kBPP = 2; // YUV420 is 2 bytes per pixel |
| unsigned int mOutputHeight = 0; |
| unsigned int mOutputWidth = 0; |
| unsigned int mWidth = 0; |
| unsigned int mHeight = 0; |
| PixelFormat mOutPixFmt; |
| // The calculated size of the outHeader buffer size allocated in the guest. |
| // It should be sizeY + (sizeUV * 2), where: |
| // sizeY = outWidth * outHeight, |
| // sizeUV = sizeY / 4 |
| // It is equivalent to outWidth * outHeight * 3 / 2 |
| unsigned int mOutBufferSize = 0; |
| std::vector<uint8_t> mSPS; // sps NALU |
| std::vector<uint8_t> mPPS; // pps NALU |
| |
| bool mIsInFlush = false; |
| private: |
| |
| bool mIsLoadingFromSnapshot = false; |
| std::vector<uint8_t> mSavedDecodedFrame; |
| void copyFrame(); |
| void oneShotDecode(std::vector<uint8_t> & data, uint64_t pts); |
| |
| mutable SnapshotState mSnapshotState; |
| |
| }; // MediaH264DecoderVideoToolBox |
| |
| |
| } // namespace emulation |
| } // namespace android |