// Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include "host-common/GoldfishMediaDefs.h" #include "host-common/MediaH264Decoder.h" #include #include namespace android { namespace emulation { class MediaH264DecoderDefault; // this is an interface for platform specific implementations // such as VideoToolBox, CUVID, etc class MediaH264DecoderPlugin { public: using PixelFormat = MediaH264Decoder::PixelFormat; using Err = MediaH264Decoder::Err; virtual void initH264Context(void* ptr) = 0; virtual void reset(void* ptr) = 0; virtual MediaH264DecoderPlugin* clone() = 0; virtual void destroyH264Context() = 0; virtual void decodeFrame(void* ptr) = 0; virtual void flush(void* ptr) = 0; virtual void getImage(void* ptr) = 0; virtual void save(base::Stream* stream) const {}; virtual bool load(base::Stream* stream) {return true;}; MediaH264DecoderPlugin() = default; virtual ~MediaH264DecoderPlugin() = default; protected: // solely for snapshot save load purpose enum { PLUGIN_TYPE_NONE = 0, PLUGIN_TYPE_FFMPEG = 1, PLUGIN_TYPE_CUVID = 2, PLUGIN_TYPE_VIDEO_TOOL_BOX = 3, PLUGIN_TYPE_VIDEO_TOOL_BOX_PROXY = 4, PLUGIN_TYPE_GENERIC = 5, }; // this is required by save/load virtual int type() const { return PLUGIN_TYPE_NONE; } friend MediaH264DecoderDefault; public: struct ColorAspects { unsigned int primaries; unsigned int range; unsigned int transfer; unsigned int space; }; struct PacketInfo { std::vector data; uint64_t pts; }; struct FrameInfo { std::vector data; int width; int height; ColorAspects color; uint64_t pts; }; struct SnapshotState { std::vector sps; // sps NALU std::vector pps; // pps NALU std::vector savedPackets; FrameInfo savedDecodedFrame; // only one or nothing std::vector savedFrames; void saveSps(std::vector xsps) { sps = std::move(xsps); } void savePps(std::vector xpps) { pps = std::move(xpps); } bool savePacket(std::vector data, uint64_t pts = 0) { if (pts > 0 && savedPackets.size() > 0 && pts == savedPackets.back().pts) { return false; } PacketInfo pkt{data, pts}; savedPackets.push_back(std::move(pkt)); return true; } bool savePacket(const uint8_t* frame, size_t size, uint64_t pts = 0) { if (pts > 0 && savedPackets.size() > 0 && pts == savedPackets.back().pts) { return false; } std::vector vec; vec.assign(frame, frame+size); PacketInfo pkt{vec, pts}; savedPackets.push_back(std::move(pkt)); return true; } void saveDecodedFrame(std::vector data, int width = 0, int height = 0, ColorAspects xcolor = ColorAspects{}, uint64_t pts = 0) { FrameInfo frame{data, width, height, xcolor, pts}; savedDecodedFrame = std::move(frame); savedFrames.push_back(savedDecodedFrame); } void saveVec(base::Stream* stream, const std::vector& vec) const { stream->putBe32(vec.size()); if (!vec.empty()) { stream->write(vec.data(), vec.size()); } } void saveFrameInfo(base::Stream* stream, const FrameInfo& frame) const { saveVec(stream, frame.data); stream->putBe32(frame.width); stream->putBe32(frame.height); saveColor(stream, frame.color); stream->putBe64(frame.pts); } void loadFrameInfo(base::Stream* stream, FrameInfo& frame) { loadVec(stream, frame.data); frame.width = stream->getBe32(); frame.height = stream->getBe32(); loadColor(stream, frame.color); frame.pts = stream->getBe64(); } void savePacketInfo(base::Stream* stream, const PacketInfo& pkt) const { saveVec(stream, pkt.data); stream->putBe64(pkt.pts); } void loadPacketInfo(base::Stream* stream, PacketInfo& pkt) { loadVec(stream, pkt.data); pkt.pts = stream->getBe64(); } void saveColor(base::Stream* stream, const ColorAspects& color) const { stream->putBe32(color.primaries); stream->putBe32(color.range); stream->putBe32(color.transfer); stream->putBe32(color.space); } void loadColor(base::Stream* stream, ColorAspects& color) const { color.primaries = stream->getBe32(); color.range = stream->getBe32(); color.transfer = stream->getBe32(); color.space = stream->getBe32(); } void save(base::Stream* stream) const { saveVec(stream, sps); saveVec(stream, pps); stream->putBe32(savedPackets.size()); for (size_t i = 0; i < savedPackets.size(); ++i) { savePacketInfo(stream, savedPackets[i]); } saveFrameInfo(stream, savedDecodedFrame); } void loadVec(base::Stream* stream, std::vector& vec) { int size = stream->getBe32(); vec.resize(size); if (size > 0) { stream->read(vec.data(), size); } } void load(base::Stream* stream) { loadVec(stream, sps); loadVec(stream, pps); int count = stream->getBe32(); savedPackets.resize(count); for (int i = 0; i < count; ++i) { loadPacketInfo(stream, savedPackets[i]); } loadFrameInfo(stream, savedDecodedFrame); } }; }; } // namespace emulation } // namespace android