mirror of
https://github.com/k4yt3x/video2x.git
synced 2026-05-06 07:27:29 +08:00
feat(encoder): add separate audio/subtitle copy and recalculate PTS option
Signed-off-by: k4yt3x <i@k4yt3x.com>
This commit is contained in:
@@ -6,10 +6,9 @@ extern "C" {
|
||||
#include <libavutil/opt.h>
|
||||
}
|
||||
|
||||
#include "logger_manager.h"
|
||||
|
||||
#include "avutils.h"
|
||||
#include "conversions.h"
|
||||
#include "logger_manager.h"
|
||||
|
||||
namespace video2x {
|
||||
namespace encoder {
|
||||
@@ -45,6 +44,9 @@ int Encoder::init(
|
||||
) {
|
||||
int ret;
|
||||
|
||||
// Copy the encoder configuration
|
||||
enc_cfg_ = enc_cfg;
|
||||
|
||||
// Allocate the output format context
|
||||
avformat_alloc_output_context2(&ofmt_ctx_, nullptr, nullptr, out_fpath.u8string().c_str());
|
||||
if (!ofmt_ctx_) {
|
||||
@@ -188,8 +190,8 @@ int Encoder::init(
|
||||
out_vstream->r_frame_rate = enc_ctx_->framerate;
|
||||
|
||||
// Copy other streams if necessary
|
||||
if (enc_cfg.copy_streams) {
|
||||
// Allocate the stream mape frame o
|
||||
if (enc_cfg.copy_audio_streams || enc_cfg.copy_subtitle_streams) {
|
||||
// Allocate the stream map
|
||||
stream_map_ =
|
||||
reinterpret_cast<int*>(av_malloc_array(ifmt_ctx->nb_streams, sizeof(*stream_map_)));
|
||||
if (!stream_map_) {
|
||||
@@ -198,22 +200,37 @@ int Encoder::init(
|
||||
}
|
||||
|
||||
// Map each input stream to an output stream
|
||||
for (int i = 0; i < static_cast<int>(ifmt_ctx->nb_streams); i++) {
|
||||
AVStream* in_stream = ifmt_ctx->streams[i];
|
||||
for (int stream_index = 0; stream_index < static_cast<int>(ifmt_ctx->nb_streams);
|
||||
stream_index++) {
|
||||
AVStream* in_stream = ifmt_ctx->streams[stream_index];
|
||||
AVCodecParameters* in_codecpar = in_stream->codecpar;
|
||||
|
||||
// Skip the input video stream as it's already processed
|
||||
if (i == in_vstream_idx) {
|
||||
stream_map_[i] = out_vstream_idx_;
|
||||
if (stream_index == in_vstream_idx) {
|
||||
stream_map_[stream_index] = out_vstream_idx_;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map only audio and subtitle streams (skip other types)
|
||||
if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
|
||||
in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
|
||||
stream_map_[i] = -1;
|
||||
logger()->warn("Skipping unsupported stream type at index: {}", i);
|
||||
continue;
|
||||
// Determine if the current stream should be skipped
|
||||
switch (in_codecpar->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
if (!enc_cfg.copy_audio_streams) {
|
||||
stream_map_[stream_index] = -1;
|
||||
continue;
|
||||
}
|
||||
logger()->debug("Copying audio stream at index: {}", stream_index);
|
||||
break;
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
if (!enc_cfg.copy_subtitle_streams) {
|
||||
stream_map_[stream_index] = -1;
|
||||
continue;
|
||||
}
|
||||
logger()->debug("Copying subtitle stream at index: {}", stream_index);
|
||||
break;
|
||||
default:
|
||||
stream_map_[stream_index] = -1;
|
||||
logger()->warn("Skipping unsupported stream type at index: {}", stream_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create corresponding output stream for audio and subtitle streams
|
||||
@@ -242,8 +259,8 @@ int Encoder::init(
|
||||
out_stream->time_base = in_stream->time_base;
|
||||
|
||||
// Map input stream index to output stream index
|
||||
logger()->debug("Stream mapping: {} (in) -> {} (out)", i, out_stream->index);
|
||||
stream_map_[i] = out_stream->index;
|
||||
logger()->debug("Stream mapping: {} (in) -> {} (out)", stream_index, out_stream->index);
|
||||
stream_map_[stream_index] = out_stream->index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +292,9 @@ int Encoder::write_frame(AVFrame* frame, int64_t frame_idx) {
|
||||
frame->pict_type = AV_PICTURE_TYPE_NONE;
|
||||
|
||||
// Calculate this frame's presentation timestamp (PTS)
|
||||
frame->pts = av_rescale_q(frame_idx, av_inv_q(enc_ctx_->framerate), enc_ctx_->time_base);
|
||||
if (enc_cfg_.recalculate_pts) {
|
||||
frame->pts = av_rescale_q(frame_idx, av_inv_q(enc_ctx_->framerate), enc_ctx_->time_base);
|
||||
}
|
||||
|
||||
// Convert the frame to the encoder's pixel format if needed
|
||||
if (frame->format != enc_ctx_->pix_fmt) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "filter_libplacebo.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "fsutils.h"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "libvideo2x.h"
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
@@ -238,8 +237,10 @@ int VideoProcessor::process_frames(
|
||||
}
|
||||
|
||||
// Calculate this frame's presentation timestamp (PTS)
|
||||
frame->pts =
|
||||
av_rescale_q(frame_idx_, av_inv_q(enc_ctx->framerate), enc_ctx->time_base);
|
||||
if (enc_cfg_.recalculate_pts) {
|
||||
frame->pts =
|
||||
av_rescale_q(frame_idx_, av_inv_q(enc_ctx->framerate), enc_ctx->time_base);
|
||||
}
|
||||
|
||||
// Process the frame based on the selected processing mode
|
||||
AVFrame* proc_frame = nullptr;
|
||||
@@ -265,7 +266,8 @@ int VideoProcessor::process_frames(
|
||||
frame_idx_.fetch_add(1);
|
||||
logger()->debug("Processed frame {}/{}", frame_idx_.load(), total_frames_.load());
|
||||
}
|
||||
} else if (enc_cfg_.copy_streams && stream_map[packet->stream_index] >= 0) {
|
||||
} else if ((enc_cfg_.copy_audio_streams || enc_cfg_.copy_subtitle_streams) &&
|
||||
stream_map[packet->stream_index] >= 0) {
|
||||
ret = write_raw_packet(packet.get(), ifmt_ctx, ofmt_ctx, stream_map);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user