// Copyright 2020 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. #include "host-common/MediaSnapshotState.h" #include #include #define MEDIA_SNAPSTATE_DEBUG 0 #if MEDIA_SNAPSTATE_DEBUG #define SNAPSTATE_DPRINT(fmt, ...) \ fprintf(stderr, "media-snapshot-state: %s:%d " fmt "\n", __func__, \ __LINE__, ##__VA_ARGS__); #else #define SNAPSTATE_DPRINT(fmt, ...) #endif #include namespace android { namespace emulation { bool MediaSnapshotState::savePacket(std::vector data, uint64_t pts) { 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 MediaSnapshotState::savePacket(const uint8_t* frame, size_t size, uint64_t pts) { 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 MediaSnapshotState::saveDecodedFrame(std::vector data, int width, int height, uint64_t pts, ColorAspects xcolor) { SNAPSTATE_DPRINT("save decoded byte data"); FrameInfo frame{ std::move(data), std::vector{}, width, height, pts, xcolor}; savedFrames.push_back(std::move(frame)); } void MediaSnapshotState::saveDecodedFrame(std::vector texture, int width, int height, uint64_t pts, ColorAspects xcolor) { SNAPSTATE_DPRINT("save decoded texture"); FrameInfo frame{std::vector{}, std::move(texture), width, height, pts, xcolor}; savedFrames.push_back(std::move(frame)); } namespace { template void saveVec(base::Stream* stream, const std::vector& vec) { stream->putBe32(vec.size()); if (!vec.empty()) { stream->write(vec.data(), vec.size() * sizeof(vec[0])); } } template void loadVec(base::Stream* stream, std::vector& vec) { int size = stream->getBe32(); vec.resize(size); if (size > 0) { stream->read(vec.data(), size * sizeof(vec[0])); } } } // namespace void MediaSnapshotState::saveFrameInfo(base::Stream* stream, const FrameInfo& frame) const { SNAPSTATE_DPRINT("save bytedata"); saveVec(stream, frame.data); SNAPSTATE_DPRINT("save texture"); saveVec(stream, frame.texture); stream->putBe32(frame.width); stream->putBe32(frame.height); saveColor(stream, frame.color); stream->putBe64(frame.pts); } void MediaSnapshotState::loadFrameInfo(base::Stream* stream, FrameInfo& frame) { SNAPSTATE_DPRINT("load bytedata"); loadVec(stream, frame.data); SNAPSTATE_DPRINT("load texture"); loadVec(stream, frame.texture); // set all to zero, as we dont really save texture std::fill(frame.texture.begin(), frame.texture.end(), 0); frame.width = stream->getBe32(); frame.height = stream->getBe32(); loadColor(stream, frame.color); frame.pts = stream->getBe64(); } void MediaSnapshotState::savePacketInfo(base::Stream* stream, const PacketInfo& pkt) const { saveVec(stream, pkt.data); stream->putBe64(pkt.pts); } void MediaSnapshotState::loadPacketInfo(base::Stream* stream, PacketInfo& pkt) { loadVec(stream, pkt.data); pkt.pts = stream->getBe64(); } void MediaSnapshotState::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 MediaSnapshotState::loadColor(base::Stream* stream, ColorAspects& color) const { color.primaries = stream->getBe32(); color.range = stream->getBe32(); color.transfer = stream->getBe32(); color.space = stream->getBe32(); } void MediaSnapshotState::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]); } stream->putBe32(savedFrames.size()); SNAPSTATE_DPRINT("save now "); for (auto iter = savedFrames.begin(); iter != savedFrames.end(); ++iter) { SNAPSTATE_DPRINT("save now "); saveFrameInfo(stream, *iter); } // saveFrameInfo(stream, savedDecodedFrame); } void MediaSnapshotState::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]); } int fcount = stream->getBe32(); SNAPSTATE_DPRINT("load now "); for (int i = 0; i < fcount; ++i) { SNAPSTATE_DPRINT("load now "); loadFrameInfo(stream, savedDecodedFrame); savedFrames.push_back(std::move(savedDecodedFrame)); } } } // namespace emulation } // namespace android