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 <VideoToolbox/VideoToolbox.h> 25 26 #include <cstdint> 27 #include <string> 28 #include <vector> 29 30 #include <stdio.h> 31 #include <string.h> 32 33 #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder 34 #define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder") 35 #endif 36 37 38 #include <stddef.h> 39 40 namespace android { 41 namespace emulation { 42 43 class MediaH264DecoderVideoToolBox : public MediaH264DecoderPlugin { 44 public: 45 virtual void initH264Context(void* ptr) override; 46 virtual void reset(void* ptr) override; 47 virtual MediaH264DecoderPlugin* clone() override; 48 virtual void destroyH264Context() override; 49 virtual void decodeFrame(void* ptr) override; 50 virtual void flush(void* ptr) override; 51 virtual void getImage(void* ptr) override; 52 53 virtual void save(base::Stream* stream) const override; 54 virtual bool load(base::Stream* stream) override; 55 type()56 virtual int type() const override { return PLUGIN_TYPE_VIDEO_TOOL_BOX; } 57 58 59 explicit MediaH264DecoderVideoToolBox(uint64_t id, 60 H264PingInfoParser parser); 61 virtual ~MediaH264DecoderVideoToolBox(); 62 63 public: 64 enum class DecoderState { 65 BAD_STATE = 0, 66 GOOD_STATE = 1, 67 }; 68 getState()69 DecoderState getState() const {return mState;} getSPS()70 std::vector<uint8_t> getSPS() const { return mSPS; } getPPS()71 std::vector<uint8_t> getPPS() const { return mPPS; } 72 private: 73 void initH264ContextInternal(unsigned int width, 74 unsigned int height, 75 unsigned int outWidth, 76 unsigned int outHeight, 77 PixelFormat pixFmt); 78 uint64_t mId = 0; 79 H264PingInfoParser mParser; 80 MediaHostRenderer mRenderer; 81 DecoderState mState = DecoderState::GOOD_STATE; 82 83 void decodeFrameInternal(size_t* pRetSzBytes, int32_t* pRetErr, const uint8_t* frame, size_t szBytes, uint64_t pts, size_t consumedSzBytes); 84 // Passes the Sequence Parameter Set (SPS) and Picture Parameter Set (PPS) to the 85 // videotoolbox decoder 86 CFDataRef createVTDecoderConfig(); 87 // Callback passed to the VTDecompressionSession 88 static void videoToolboxDecompressCallback(void* opaque, 89 void* sourceFrameRefCon, 90 OSStatus status, 91 VTDecodeInfoFlags flags, 92 CVImageBufferRef image_buffer, 93 CMTime pts, 94 CMTime duration); 95 static CFDictionaryRef createOutputBufferAttributes(int width, 96 int height, 97 OSType pix_fmt); 98 static CMSampleBufferRef createSampleBuffer(CMFormatDescriptionRef fmtDesc, 99 void* buffer, 100 size_t sz); 101 static OSType toNativePixelFormat(PixelFormat fmt); 102 103 // We should move these shared memory calls elsewhere, as vpx decoder is also using the same/similar 104 // functions 105 static void* getReturnAddress(void* ptr); 106 static uint8_t* getDst(void* ptr); 107 108 void handleIDRFrame(const uint8_t* ptr, size_t szBytes, uint64_t pts); 109 void handleNonIDRFrame(const uint8_t* ptr, size_t szBytes, uint64_t pts); 110 void handleSEIFrame(const uint8_t* ptr, size_t szBytes); 111 112 void createCMFormatDescription(); 113 void recreateDecompressionSession(); 114 115 // The VideoToolbox decoder session 116 VTDecompressionSessionRef mDecoderSession = nullptr; 117 // The decoded video buffer 118 uint64_t mOutputPts = 0; 119 CVImageBufferRef mDecodedFrame = nullptr; 120 CMFormatDescriptionRef mCmFmtDesc = nullptr; 121 bool mImageReady = false; 122 static constexpr int kBPP = 2; // YUV420 is 2 bytes per pixel 123 unsigned int mOutputHeight = 0; 124 unsigned int mOutputWidth = 0; 125 unsigned int mWidth = 0; 126 unsigned int mHeight = 0; 127 PixelFormat mOutPixFmt; 128 // The calculated size of the outHeader buffer size allocated in the guest. 129 // It should be sizeY + (sizeUV * 2), where: 130 // sizeY = outWidth * outHeight, 131 // sizeUV = sizeY / 4 132 // It is equivalent to outWidth * outHeight * 3 / 2 133 unsigned int mOutBufferSize = 0; 134 std::vector<uint8_t> mSPS; // sps NALU 135 std::vector<uint8_t> mPPS; // pps NALU 136 137 bool mIsInFlush = false; 138 private: 139 140 bool mIsLoadingFromSnapshot = false; 141 std::vector<uint8_t> mSavedDecodedFrame; 142 void copyFrame(); 143 void oneShotDecode(std::vector<uint8_t> & data, uint64_t pts); 144 145 mutable SnapshotState mSnapshotState; 146 147 }; // MediaH264DecoderVideoToolBox 148 149 150 } // namespace emulation 151 } // namespace android 152