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/MediaH264Decoder.h" 19 20 #include <stddef.h> 21 #include <vector> 22 23 namespace android { 24 namespace emulation { 25 26 class MediaH264DecoderDefault; 27 28 // this is an interface for platform specific implementations 29 // such as VideoToolBox, CUVID, etc 30 class MediaH264DecoderPlugin { 31 public: 32 using PixelFormat = MediaH264Decoder::PixelFormat; 33 using Err = MediaH264Decoder::Err; 34 35 virtual void initH264Context(void* ptr) = 0; 36 virtual void reset(void* ptr) = 0; 37 virtual MediaH264DecoderPlugin* clone() = 0; 38 virtual void destroyH264Context() = 0; 39 virtual void decodeFrame(void* ptr) = 0; 40 virtual void flush(void* ptr) = 0; 41 virtual void getImage(void* ptr) = 0; 42 virtual void sendMetadata(void* ptr) = 0; 43 save(base::Stream * stream)44 virtual void save(base::Stream* stream) const {}; load(base::Stream * stream)45 virtual bool load(base::Stream* stream) {return true;}; 46 47 MediaH264DecoderPlugin() = default; 48 virtual ~MediaH264DecoderPlugin() = default; 49 50 protected: 51 // solely for snapshot save load purpose 52 enum { 53 PLUGIN_TYPE_NONE = 0, 54 PLUGIN_TYPE_FFMPEG = 1, 55 PLUGIN_TYPE_CUVID = 2, 56 PLUGIN_TYPE_VIDEO_TOOL_BOX = 3, 57 PLUGIN_TYPE_VIDEO_TOOL_BOX_PROXY = 4, 58 PLUGIN_TYPE_GENERIC = 5, 59 60 }; 61 62 // this is required by save/load type()63 virtual int type() const { return PLUGIN_TYPE_NONE; } 64 65 friend MediaH264DecoderDefault; 66 67 public: 68 struct ColorAspects { 69 unsigned int primaries; 70 unsigned int range; 71 unsigned int transfer; 72 unsigned int space; 73 }; 74 75 struct PacketInfo { 76 std::vector<uint8_t> data; 77 uint64_t pts; 78 }; 79 80 struct FrameInfo { 81 std::vector<uint8_t> data; 82 int width; 83 int height; 84 ColorAspects color; 85 uint64_t pts; 86 }; 87 88 struct SnapshotState { 89 std::vector<uint8_t> sps; // sps NALU 90 std::vector<uint8_t> pps; // pps NALU 91 std::vector<PacketInfo> savedPackets; 92 FrameInfo savedDecodedFrame; // only one or nothing 93 std::vector<FrameInfo> savedFrames; 94 saveSpsSnapshotState95 void saveSps(std::vector<uint8_t> xsps) { sps = std::move(xsps); } 96 savePpsSnapshotState97 void savePps(std::vector<uint8_t> xpps) { pps = std::move(xpps); } 98 bool savePacket(std::vector<uint8_t> data, uint64_t pts = 0) { 99 if (pts > 0 && savedPackets.size() > 0 && 100 pts == savedPackets.back().pts) { 101 return false; 102 } 103 PacketInfo pkt{data, pts}; 104 savedPackets.push_back(std::move(pkt)); 105 return true; 106 } 107 bool savePacket(const uint8_t* frame, size_t size, uint64_t pts = 0) { 108 if (pts > 0 && savedPackets.size() > 0 && 109 pts == savedPackets.back().pts) { 110 return false; 111 } 112 std::vector<uint8_t> vec; 113 vec.assign(frame, frame+size); 114 PacketInfo pkt{vec, pts}; 115 savedPackets.push_back(std::move(pkt)); 116 return true; 117 } 118 119 void saveDecodedFrame(std::vector<uint8_t> data, 120 int width = 0, 121 int height = 0, 122 ColorAspects xcolor = ColorAspects{}, 123 uint64_t pts = 0) { 124 FrameInfo frame{data, width, height, xcolor, pts}; 125 savedDecodedFrame = std::move(frame); 126 savedFrames.push_back(savedDecodedFrame); 127 } 128 saveVecSnapshotState129 void saveVec(base::Stream* stream, 130 const std::vector<uint8_t>& vec) const { 131 stream->putBe32(vec.size()); 132 if (!vec.empty()) { 133 stream->write(vec.data(), vec.size()); 134 } 135 } 136 saveFrameInfoSnapshotState137 void saveFrameInfo(base::Stream* stream, const FrameInfo& frame) const { 138 saveVec(stream, frame.data); 139 stream->putBe32(frame.width); 140 stream->putBe32(frame.height); 141 saveColor(stream, frame.color); 142 stream->putBe64(frame.pts); 143 } 144 loadFrameInfoSnapshotState145 void loadFrameInfo(base::Stream* stream, FrameInfo& frame) { 146 loadVec(stream, frame.data); 147 frame.width = stream->getBe32(); 148 frame.height = stream->getBe32(); 149 loadColor(stream, frame.color); 150 frame.pts = stream->getBe64(); 151 } 152 savePacketInfoSnapshotState153 void savePacketInfo(base::Stream* stream, const PacketInfo& pkt) const { 154 saveVec(stream, pkt.data); 155 stream->putBe64(pkt.pts); 156 } 157 loadPacketInfoSnapshotState158 void loadPacketInfo(base::Stream* stream, PacketInfo& pkt) { 159 loadVec(stream, pkt.data); 160 pkt.pts = stream->getBe64(); 161 } 162 saveColorSnapshotState163 void saveColor(base::Stream* stream, const ColorAspects& color) const { 164 stream->putBe32(color.primaries); 165 stream->putBe32(color.range); 166 stream->putBe32(color.transfer); 167 stream->putBe32(color.space); 168 } 169 loadColorSnapshotState170 void loadColor(base::Stream* stream, ColorAspects& color) const { 171 color.primaries = stream->getBe32(); 172 color.range = stream->getBe32(); 173 color.transfer = stream->getBe32(); 174 color.space = stream->getBe32(); 175 } 176 saveSnapshotState177 void save(base::Stream* stream) const { 178 saveVec(stream, sps); 179 saveVec(stream, pps); 180 stream->putBe32(savedPackets.size()); 181 for (size_t i = 0; i < savedPackets.size(); ++i) { 182 savePacketInfo(stream, savedPackets[i]); 183 } 184 saveFrameInfo(stream, savedDecodedFrame); 185 } 186 loadVecSnapshotState187 void loadVec(base::Stream* stream, std::vector<uint8_t>& vec) { 188 int size = stream->getBe32(); 189 vec.resize(size); 190 if (size > 0) { 191 stream->read(vec.data(), size); 192 } 193 } loadSnapshotState194 void load(base::Stream* stream) { 195 loadVec(stream, sps); 196 loadVec(stream, pps); 197 int count = stream->getBe32(); 198 savedPackets.resize(count); 199 for (int i = 0; i < count; ++i) { 200 loadPacketInfo(stream, savedPackets[i]); 201 } 202 loadFrameInfo(stream, savedDecodedFrame); 203 } 204 }; 205 }; 206 207 } // namespace emulation 208 } // namespace android 209