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