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