save timelapse stream to file

This commit is contained in:
2019-11-02 18:05:24 +01:00
parent 7db1739df6
commit 83ba717d5b
9 changed files with 150 additions and 23 deletions

View File

@@ -12,6 +12,11 @@ static void encoder_trace_callback(void* context, int level, const char* message
LOG("ENCODER: %s", message);
}
MP4Encoder::~MP4Encoder()
{
destroy();
}
bool MP4Encoder::init(int width, int height, int fps, int bitrate) noexcept
{
if (WelsCreateSVCEncoder(&m_encoder) != 0)
@@ -75,6 +80,11 @@ bool MP4Encoder::init(int width, int height, int fps, int bitrate) noexcept
return true;
}
bool MP4Encoder::init() noexcept
{
return init(m_width, m_height, m_framerate, m_bitrate);
}
bool MP4Encoder::encode(const Image& rgba) noexcept
{
// lazy allocation of YUV buffer
@@ -167,7 +177,7 @@ bool MP4Encoder::write_mp4(const std::string& filename) const noexcept
MP4SetTimeScale(mp4, 90000);
MP4SetVideoProfileLevel(mp4, 1);
MP4TrackId mp4_track = MP4AddH264VideoTrack(mp4, 90000, 90000 / m_framerate, m_width, m_height,
m_header.avc_profile, m_header.avc_profile_compat, m_header.avc_level, 3);
m_header.avc_profile, m_header.avc_compat, m_header.avc_level, 3);
MP4AddH264SequenceParameterSet(mp4, mp4_track, m_header.SPS_data.data(), m_header.SPS_data.size());
MP4AddH264PictureParameterSet(mp4, mp4_track, m_header.PPS_data.data(), m_header.PPS_data.size());
for (const auto& f : m_frames)
@@ -196,3 +206,54 @@ void MP4Encoder::destroy() noexcept
m_header.PPS_data.clear();
m_header.SPS_data.clear();
}
bool MP4Encoder::read(BinaryStreamReader& r)
{
Serializer::Descriptor d;
r >> d;
d.value<Serializer::Integer>("width", m_width);
d.value<Serializer::Integer>("height", m_height);
d.value<Serializer::Integer>("bitrate", m_bitrate);
d.value<Serializer::Float>("framerate", m_framerate);
d.value<Serializer::RawData>("SPS", m_header.SPS_data);
d.value<Serializer::RawData>("PPS", m_header.PPS_data);
d.value<Serializer::Integer>("avc_profile", m_header.avc_profile);
d.value<Serializer::Integer>("avc_compat", m_header.avc_compat);
d.value<Serializer::Integer>("avc_level", m_header.avc_level);
auto frames = d.get<Serializer::List>("frames");
for (const auto& f : frames->items)
{
if (auto fd = std::dynamic_pointer_cast<Serializer::Descriptor>(f))
{
m_frames.emplace_back();
m_frames.back().type = (Frame::kType)fd->value<Serializer::Integer>("type");
m_frames.back().data = fd->value<Serializer::RawData>("data");
}
}
return true;
}
void MP4Encoder::write(BinaryStreamWriter& w) const
{
Serializer::Descriptor d;
d.class_id = "mp4enc";
d.name = L"MP4 Encoder class";
d.props["width"] = std::make_shared<Serializer::Integer>(m_width);
d.props["height"] = std::make_shared<Serializer::Integer>(m_height);
d.props["bitrate"] = std::make_shared<Serializer::Integer>(m_bitrate);
d.props["framerate"] = std::make_shared<Serializer::Float>(m_framerate);
d.props["SPS"] = std::make_shared<Serializer::RawData>(m_header.SPS_data);
d.props["PPS"] = std::make_shared<Serializer::RawData>(m_header.PPS_data);
d.props["avc_profile"] = std::make_shared<Serializer::Integer>(m_header.avc_profile);
d.props["avc_compat"] = std::make_shared<Serializer::Integer>(m_header.avc_compat);
d.props["avc_level"] = std::make_shared<Serializer::Integer>(m_header.avc_level);
auto frames = std::make_shared<Serializer::List>();
for (const auto& f : m_frames)
{
auto fd = frames->add<Serializer::Descriptor>();
fd->props["type"] = std::make_shared<Serializer::Integer>((int)f.type);
fd->props["data"] = std::make_shared<Serializer::RawData>(f.data);
}
d.props["frames"] = frames;
w << d;
}