You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
6.7 KiB
208 lines
6.7 KiB
// 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 <stddef.h>
|
|
#include <vector>
|
|
|
|
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<uint8_t> data;
|
|
uint64_t pts;
|
|
};
|
|
|
|
struct FrameInfo {
|
|
std::vector<uint8_t> data;
|
|
int width;
|
|
int height;
|
|
ColorAspects color;
|
|
uint64_t pts;
|
|
};
|
|
|
|
struct SnapshotState {
|
|
std::vector<uint8_t> sps; // sps NALU
|
|
std::vector<uint8_t> pps; // pps NALU
|
|
std::vector<PacketInfo> savedPackets;
|
|
FrameInfo savedDecodedFrame; // only one or nothing
|
|
std::vector<FrameInfo> savedFrames;
|
|
|
|
void saveSps(std::vector<uint8_t> xsps) { sps = std::move(xsps); }
|
|
|
|
void savePps(std::vector<uint8_t> xpps) { pps = std::move(xpps); }
|
|
bool savePacket(std::vector<uint8_t> 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<uint8_t> vec;
|
|
vec.assign(frame, frame+size);
|
|
PacketInfo pkt{vec, pts};
|
|
savedPackets.push_back(std::move(pkt));
|
|
return true;
|
|
}
|
|
|
|
void saveDecodedFrame(std::vector<uint8_t> 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<uint8_t>& 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<uint8_t>& 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
|