chore(app): keep only avcpp variant
This commit is contained in:
parent
2c045d4c73
commit
6e07b36f02
@ -7,32 +7,19 @@ project(
|
|||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|
||||||
find_package(spdlog REQUIRED)
|
find_package(spdlog REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
|
|
||||||
libavcodec
|
|
||||||
libavformat
|
|
||||||
libavutil
|
|
||||||
)
|
|
||||||
|
|
||||||
find_package(avcpp REQUIRED)
|
find_package(avcpp REQUIRED)
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
add_executable(mosh-me-2
|
add_executable(mosh-me
|
||||||
${PROJECT_SOURCE_DIR}/app/mosh-me-2.cpp
|
${PROJECT_SOURCE_DIR}/app/mosh-me.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(mosh-me-2 avcpp::avcpp spdlog::spdlog)
|
target_link_libraries(mosh-me avcpp::avcpp spdlog::spdlog)
|
||||||
target_compile_features(mosh-me-2 PUBLIC cxx_std_23)
|
|
||||||
target_include_directories(mosh-me-2 PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
|
||||||
|
|
||||||
add_executable(mosh-me ${PROJECT_SOURCE_DIR}/app/mosh-me.cpp)
|
|
||||||
|
|
||||||
target_link_libraries(mosh-me PkgConfig::FFMPEG spdlog::spdlog)
|
|
||||||
target_compile_features(mosh-me PUBLIC cxx_std_23)
|
target_compile_features(mosh-me PUBLIC cxx_std_23)
|
||||||
target_include_directories(mosh-me PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(mosh-me PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
|
||||||
install(TARGETS mosh-me mosh-me-2)
|
install(TARGETS mosh-me mosh-me)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
#include <avcpp/av.h>
|
|
||||||
#include <avcpp/avtime.h>
|
|
||||||
#include <avcpp/format.h>
|
|
||||||
#include <avcpp/formatcontext.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
|
|
||||||
if (argc < 4) {
|
|
||||||
spdlog::error("Usage: {} <input-file> <output-file> <smear-frames>",
|
|
||||||
argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *input_file = argv[1];
|
|
||||||
const char *output_file = argv[2];
|
|
||||||
int smear_frames = atoi(argv[3]);
|
|
||||||
|
|
||||||
av::init();
|
|
||||||
|
|
||||||
av::FormatContext ictx;
|
|
||||||
av::FormatContext octx;
|
|
||||||
ictx.openInput(input_file);
|
|
||||||
ictx.findStreamInfo();
|
|
||||||
|
|
||||||
std::vector<off_t> stream_map(ictx.streamsCount());
|
|
||||||
|
|
||||||
off_t oix = 0;
|
|
||||||
for (size_t i = 0; i < stream_map.size(); i++) {
|
|
||||||
auto istream = ictx.stream(i);
|
|
||||||
|
|
||||||
if (istream.codecParameters().codecType() != AVMEDIA_TYPE_AUDIO ||
|
|
||||||
istream.codecParameters().codecType() != AVMEDIA_TYPE_VIDEO ||
|
|
||||||
istream.codecParameters().codecType() != AVMEDIA_TYPE_SUBTITLE) {
|
|
||||||
stream_map[i] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ostream = octx.addStream();
|
|
||||||
ostream.setCodecParameters(istream.codecParameters());
|
|
||||||
ostream.codecParameters().codecTag(0);
|
|
||||||
stream_map[i] = oix++;
|
|
||||||
}
|
|
||||||
|
|
||||||
octx.openOutput(output_file);
|
|
||||||
octx.writeHeader();
|
|
||||||
|
|
||||||
av::Packet packet_buffer;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
auto pkt = ictx.readPacket();
|
|
||||||
|
|
||||||
if (pkt.isNull()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto istream = ictx.stream(pkt.streamIndex());
|
|
||||||
|
|
||||||
if (pkt.streamIndex() >= stream_map.size() ||
|
|
||||||
stream_map[pkt.streamIndex()] < 0 || pkt.isKeyPacket()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pkt.setStreamIndex(stream_map[pkt.streamIndex()]);
|
|
||||||
|
|
||||||
if (auto ts = pkt.pts().timestamp(); ts % smear_frames == 0) {
|
|
||||||
packet_buffer = pkt;
|
|
||||||
} else {
|
|
||||||
auto dts = pkt.dts();
|
|
||||||
auto pts = pkt.pts();
|
|
||||||
auto dur = pkt.duration();
|
|
||||||
pkt = packet_buffer;
|
|
||||||
pkt.setDts(dts);
|
|
||||||
pkt.setPts(pts);
|
|
||||||
pkt.setDuration(dur);
|
|
||||||
}
|
|
||||||
|
|
||||||
octx.writePacket(pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
octx.writeTrailer();
|
|
||||||
}
|
|
||||||
198
app/mosh-me.cpp
198
app/mosh-me.cpp
@ -1,152 +1,82 @@
|
|||||||
extern "C" {
|
#include <avcpp/av.h>
|
||||||
#include <libavformat/avformat.h>
|
#include <avcpp/avtime.h>
|
||||||
#include <libavutil/error.h>
|
#include <avcpp/format.h>
|
||||||
}
|
#include <avcpp/formatcontext.h>
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
static void log_err(int err) {
|
int main(int argc, char *argv[]) {
|
||||||
char buf[256];
|
|
||||||
av_strerror(err, buf, sizeof(buf));
|
|
||||||
spdlog::error("FFMPEG error: {}", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void smearStreams(const std::vector<off_t> &stream_list,
|
if (argc < 4) {
|
||||||
AVFormatContext *input_format,
|
spdlog::error("Usage: {} <input-file> <output-file> <smear-frames>",
|
||||||
AVFormatContext *output_format) {
|
argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool remove_iframes = false;
|
const char *input_file = argv[1];
|
||||||
|
const char *output_file = argv[2];
|
||||||
|
int smear_frames = atoi(argv[3]);
|
||||||
|
|
||||||
|
av::init();
|
||||||
|
|
||||||
|
av::FormatContext ictx;
|
||||||
|
av::FormatContext octx;
|
||||||
|
ictx.openInput(input_file);
|
||||||
|
ictx.findStreamInfo();
|
||||||
|
|
||||||
|
std::vector<off_t> stream_map(ictx.streamsCount());
|
||||||
|
|
||||||
|
off_t oix = 0;
|
||||||
|
for (size_t i = 0; i < stream_map.size(); i++) {
|
||||||
|
auto istream = ictx.stream(i);
|
||||||
|
|
||||||
|
if (istream.codecParameters().codecType() != AVMEDIA_TYPE_AUDIO ||
|
||||||
|
istream.codecParameters().codecType() != AVMEDIA_TYPE_VIDEO ||
|
||||||
|
istream.codecParameters().codecType() != AVMEDIA_TYPE_SUBTITLE) {
|
||||||
|
stream_map[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ostream = octx.addStream();
|
||||||
|
ostream.setCodecParameters(istream.codecParameters());
|
||||||
|
ostream.codecParameters().codecTag(0);
|
||||||
|
stream_map[i] = oix++;
|
||||||
|
}
|
||||||
|
|
||||||
|
octx.openOutput(output_file);
|
||||||
|
octx.writeHeader();
|
||||||
|
|
||||||
|
av::Packet packet_buffer;
|
||||||
|
|
||||||
AVPacket prev;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
AVPacket packet;
|
auto pkt = ictx.readPacket();
|
||||||
if (auto ret = av_read_frame(input_format, &packet); ret < 0) {
|
|
||||||
|
if (pkt.isNull()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVStream *istream = input_format->streams[packet.stream_index];
|
auto istream = ictx.stream(pkt.streamIndex());
|
||||||
if (packet.stream_index >= input_format->nb_streams ||
|
|
||||||
stream_list[packet.stream_index] < 0 ||
|
if (pkt.streamIndex() >= stream_map.size() ||
|
||||||
(istream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
|
stream_map[pkt.streamIndex()] < 0 || pkt.isKeyPacket()) {
|
||||||
packet.flags & AV_PKT_FLAG_KEY && remove_iframes)) {
|
|
||||||
av_packet_unref(&packet);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map to output stream index
|
pkt.setStreamIndex(stream_map[pkt.streamIndex()]);
|
||||||
packet.stream_index = stream_list[packet.stream_index];
|
|
||||||
AVStream *ostream = output_format->streams[packet.stream_index];
|
|
||||||
|
|
||||||
if (packet.pts > 0 && packet.pts % 25 < 10 && packet.pts % 2 == 0) {
|
if (auto ts = pkt.pts().timestamp(); ts % smear_frames == 0) {
|
||||||
prev.pts = packet.pts;
|
packet_buffer = pkt;
|
||||||
prev.dts = packet.dts;
|
} else {
|
||||||
prev.duration = packet.duration;
|
auto dts = pkt.dts();
|
||||||
packet = prev;
|
auto pts = pkt.pts();
|
||||||
|
auto dur = pkt.duration();
|
||||||
|
pkt = packet_buffer;
|
||||||
|
pkt.setDts(dts);
|
||||||
|
pkt.setPts(pts);
|
||||||
|
pkt.setDuration(dur);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust time data for output timebase
|
octx.writePacket(pkt);
|
||||||
packet.pts =
|
|
||||||
av_rescale_q_rnd(packet.pts, istream->time_base, ostream->time_base,
|
|
||||||
AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
|
|
||||||
packet.dts =
|
|
||||||
av_rescale_q_rnd(packet.dts, istream->time_base, ostream->time_base,
|
|
||||||
AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
|
|
||||||
packet.duration =
|
|
||||||
av_rescale_q(packet.duration, istream->time_base, ostream->time_base);
|
|
||||||
packet.pos = -1; // unknown position
|
|
||||||
|
|
||||||
if (auto ret = av_interleaved_write_frame(output_format, &packet);
|
|
||||||
ret < 0) {
|
|
||||||
spdlog::error("Could not mux packet");
|
|
||||||
log_err(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = packet;
|
octx.writeTrailer();
|
||||||
|
|
||||||
av_packet_unref(&packet);
|
|
||||||
}
|
|
||||||
av_packet_unref(&prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<off_t>
|
|
||||||
prepareOutputStreams(const AVFormatContext *input_format,
|
|
||||||
AVFormatContext *output_format) {
|
|
||||||
|
|
||||||
std::vector<off_t> streams_list(input_format->nb_streams);
|
|
||||||
off_t stream_ix = 0;
|
|
||||||
|
|
||||||
for (off_t i = 0; i < input_format->nb_streams; i++) {
|
|
||||||
AVStream *istream = input_format->streams[i];
|
|
||||||
AVCodecParameters *icpar = istream->codecpar;
|
|
||||||
if (icpar->codec_type != AVMEDIA_TYPE_AUDIO &&
|
|
||||||
icpar->codec_type != AVMEDIA_TYPE_VIDEO &&
|
|
||||||
icpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
|
|
||||||
streams_list[i] = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
streams_list[i] = stream_ix++;
|
|
||||||
AVStream *ostream = avformat_new_stream(output_format, nullptr);
|
|
||||||
if (auto ret = avcodec_parameters_copy(ostream->codecpar, icpar); ret < 0) {
|
|
||||||
spdlog::error("Could not prepare output stream");
|
|
||||||
log_err(ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return streams_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
|
||||||
if (argc < 3) {
|
|
||||||
spdlog::error("Please invoke with {} <input file> <output file>", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
spdlog::info("Opening File {}", argv[1]);
|
|
||||||
|
|
||||||
AVFormatContext *input_format = nullptr;
|
|
||||||
AVFormatContext *output_format = nullptr;
|
|
||||||
if (auto ret = avformat_open_input(&input_format, argv[1], nullptr, nullptr);
|
|
||||||
ret < 0) {
|
|
||||||
log_err(ret);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto ret = avformat_find_stream_info(input_format, nullptr); ret < 0) {
|
|
||||||
log_err(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
spdlog::info("Format: {}, frames: {}, bitrate: {}",
|
|
||||||
input_format->iformat->name, input_format->duration,
|
|
||||||
input_format->bit_rate);
|
|
||||||
|
|
||||||
if (auto ret = avformat_alloc_output_context2(&output_format, nullptr,
|
|
||||||
nullptr, argv[2]);
|
|
||||||
ret < 0) {
|
|
||||||
log_err(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto streams = prepareOutputStreams(input_format, output_format);
|
|
||||||
|
|
||||||
if (!(output_format->oformat->flags & AVFMT_NOFILE)) {
|
|
||||||
if (auto ret = avio_open(&output_format->pb, argv[2], AVIO_FLAG_WRITE);
|
|
||||||
ret < 0) {
|
|
||||||
spdlog::error("Could not open output file {}", argv[2]);
|
|
||||||
log_err(ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto ret = avformat_write_header(output_format, nullptr); ret < 0) {
|
|
||||||
spdlog::error("Could not write header");
|
|
||||||
log_err(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
smearStreams(streams, input_format, output_format);
|
|
||||||
|
|
||||||
av_write_trailer(output_format);
|
|
||||||
|
|
||||||
avformat_close_input(&input_format);
|
|
||||||
if (output_format && !(output_format->oformat->flags & AVFMT_NOFILE)) {
|
|
||||||
avio_closep(&output_format->pb);
|
|
||||||
}
|
|
||||||
avformat_free_context(output_format);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,14 +5,13 @@
|
|||||||
spdlog,
|
spdlog,
|
||||||
stdenv,
|
stdenv,
|
||||||
pkg-config,
|
pkg-config,
|
||||||
ffmpeg_7,
|
|
||||||
avcpp,
|
avcpp,
|
||||||
}:
|
}:
|
||||||
stdenv.mkDerivation (finalAttrs: {
|
stdenv.mkDerivation (finalAttrs: {
|
||||||
name = "mosh-me";
|
name = "mosh-me";
|
||||||
src = ../.;
|
src = ../.;
|
||||||
nativeBuildInputs = [cmake ninja pkg-config];
|
nativeBuildInputs = [cmake ninja pkg-config];
|
||||||
buildInputs = [ffmpeg_7 spdlog avcpp];
|
buildInputs = [spdlog avcpp];
|
||||||
cmakeFlags = [
|
cmakeFlags = [
|
||||||
(lib.cmakeBool "BUILD_TESTING" finalAttrs.doCheck)
|
(lib.cmakeBool "BUILD_TESTING" finalAttrs.doCheck)
|
||||||
];
|
];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user