mosh-me/app/mk-moshable.cpp

90 lines
2.1 KiB
C++

#include <avcpp/av.h>
#include <avcpp/codeccontext.h>
#include <avcpp/formatcontext.h>
#include <avcpp/stream.h>
#include <spdlog/spdlog.h>
int main(int argc, char *argv[]) {
if (argc < 3) {
spdlog::error("Please invoke with {} <ifile> <ofile>", argv[0]);
}
av::init();
try {
av::FormatContext ictx;
ictx.openInput(argv[1]);
ictx.findStreamInfo();
off_t v_istream_ix = -1;
for (off_t i = 0; i < ictx.streamsCount(); i++) {
auto stream = ictx.stream(i);
if (stream.isVideo() && stream.isValid()) {
v_istream_ix = i;
}
}
if (v_istream_ix == -1) {
spdlog::error("No video stream found in {}", argv[1]);
return 1;
}
av::VideoDecoderContext decoder(ictx.stream(v_istream_ix));
decoder.open();
av::FormatContext octx;
av::OutputFormat ofmt;
ofmt.setFormat("", argv[2]);
octx.setFormat(ofmt);
auto ocodec = av::findEncodingCodec("libxvid");
av::VideoEncoderContext encoder(ocodec);
encoder.setPixelFormat(decoder.pixelFormat());
encoder.setWidth(decoder.width());
encoder.setHeight(decoder.height());
encoder.setGopSize(1000);
encoder.setMaxBFrames(0);
encoder.setGlobalQuality(1);
encoder.raw()->qmin = 1;
encoder.raw()->qmax = 1;
encoder.setFlags(AV_CODEC_FLAG_QPEL | AV_CODEC_FLAG_4MV);
encoder.setTimeBase({1, 1000});
encoder.open();
auto ostream = octx.addStream(encoder);
ostream.setFrameRate(ictx.stream(v_istream_ix).frameRate());
octx.openOutput(argv[2]);
octx.writeHeader();
for (;;) {
auto pkt = ictx.readPacket();
if (pkt.isNull()) {
break;
}
if (pkt.streamIndex() != v_istream_ix) {
continue;
}
auto frame = decoder.decode(pkt);
if (frame) {
frame.setTimeBase(encoder.timeBase());
frame.setStreamIndex(0);
frame.setPictureType();
auto opkt = encoder.encode(frame);
if (opkt) {
opkt.setStreamIndex(0);
octx.writePacket(opkt);
}
}
}
octx.writeTrailer();
octx.flush();
} catch (const av::Exception &e) {
spdlog::error("{}", e.what());
}
}