90 lines
2.1 KiB
C++
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());
|
|
}
|
|
}
|