feat(avpipe): add SmearFrames
This commit is contained in:
@@ -15,7 +15,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
try {
|
||||
auto pipe = mosh_me::VideoMuxer::link(std::filesystem::path(argv[2]))
|
||||
<< mosh_me::DropIFrames::link()
|
||||
<< mosh_me::SmearFrames::link(3, 5)
|
||||
<< mosh_me::MoshableVideoEncoder::link()
|
||||
<< mosh_me::VideoDecoder::link()
|
||||
<< mosh_me::VideoPacketSource::link(argv[1]);
|
||||
|
||||
@@ -60,7 +60,30 @@ class DropIFrames
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>, FrameMeta>,
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>,
|
||||
FrameMeta>> {
|
||||
private:
|
||||
uint32_t remaining_ = 0;
|
||||
|
||||
public:
|
||||
DropIFrames(uint32_t keep_n = 0);
|
||||
mosh_me::PipeData<av::Packet> pull() noexcept override;
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>, FrameMeta>
|
||||
propagateMeta() noexcept override;
|
||||
};
|
||||
|
||||
class SmearFrames
|
||||
: public AsPipeLink<
|
||||
SmearFrames, av::Packet, av::Packet,
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>, FrameMeta>,
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>,
|
||||
FrameMeta>> {
|
||||
private:
|
||||
std::vector<av::Packet> back_buffer_;
|
||||
std::vector<av::Packet>::iterator read_head_;
|
||||
uint32_t n_repeat_ = 0;
|
||||
uint32_t current_ix_ = 0;
|
||||
|
||||
public:
|
||||
SmearFrames(uint32_t n_frames = 1, uint32_t n_repeat = 2);
|
||||
mosh_me::PipeData<av::Packet> pull() noexcept override;
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>, FrameMeta>
|
||||
propagateMeta() noexcept override;
|
||||
|
||||
@@ -117,6 +117,8 @@ mosh_me::MoshableVideoEncoder::propagateMeta() noexcept {
|
||||
return {ctx_, frame_meta};
|
||||
}
|
||||
|
||||
mosh_me::DropIFrames::DropIFrames(uint32_t keep_n) : remaining_(keep_n) {}
|
||||
|
||||
mosh_me::PipeData<av::Packet> mosh_me::DropIFrames::pull() noexcept {
|
||||
for (;;) {
|
||||
auto input = fetchInput();
|
||||
@@ -124,8 +126,10 @@ mosh_me::PipeData<av::Packet> mosh_me::DropIFrames::pull() noexcept {
|
||||
return std::unexpected(input.error());
|
||||
}
|
||||
|
||||
if (input->isKeyPacket()) {
|
||||
if (input->isKeyPacket() && remaining_ == 0) {
|
||||
continue;
|
||||
} else if (input->isKeyPacket()) {
|
||||
remaining_--;
|
||||
}
|
||||
|
||||
return input;
|
||||
@@ -144,6 +148,60 @@ mosh_me::VideoMuxer::VideoMuxer(const std::filesystem::path &path) {
|
||||
ctx_.openOutput(path);
|
||||
}
|
||||
|
||||
mosh_me::SmearFrames::SmearFrames(uint32_t n_frames, uint32_t n_repeat)
|
||||
: n_repeat_(n_repeat) {
|
||||
back_buffer_.reserve(n_frames);
|
||||
read_head_ = back_buffer_.begin();
|
||||
}
|
||||
|
||||
mosh_me::PipeData<av::Packet> mosh_me::SmearFrames::pull() noexcept {
|
||||
for (;;) {
|
||||
auto input = fetchInput();
|
||||
if (!input) {
|
||||
// TODO: dump back_buffer
|
||||
return std::unexpected(input.error());
|
||||
}
|
||||
|
||||
// Do not repeat iframes
|
||||
if (input->isKeyPacket()) {
|
||||
current_ix_ = 0;
|
||||
back_buffer_.clear();
|
||||
read_head_ = back_buffer_.begin();
|
||||
return input;
|
||||
}
|
||||
|
||||
if (back_buffer_.size() == back_buffer_.capacity()) {
|
||||
// Full, dump the back buffer
|
||||
if (read_head_ == back_buffer_.end() && current_ix_ == n_repeat_ - 1) {
|
||||
current_ix_ = 0;
|
||||
back_buffer_.clear();
|
||||
read_head_ = back_buffer_.begin();
|
||||
} else if (read_head_ == back_buffer_.end()) {
|
||||
current_ix_++;
|
||||
read_head_ = back_buffer_.begin();
|
||||
auto frame = *read_head_++;
|
||||
frame.setDts(input->dts());
|
||||
frame.setPts(input->pts());
|
||||
return frame;
|
||||
} else {
|
||||
auto frame = *read_head_++;
|
||||
frame.setDts(input->dts());
|
||||
frame.setPts(input->pts());
|
||||
return frame;
|
||||
}
|
||||
} else {
|
||||
// Fill back_buffer
|
||||
back_buffer_.push_back(*input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::reference_wrapper<av::VideoEncoderContext>, mosh_me::FrameMeta>
|
||||
|
||||
mosh_me::SmearFrames::propagateMeta() noexcept {
|
||||
return fetchMeta();
|
||||
}
|
||||
|
||||
mosh_me::PipeData<void> mosh_me::VideoMuxer::pull() noexcept {
|
||||
std::error_code ec;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user