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