fixed the fps/bitrate issue unless the input is severely messed up

This commit is contained in:
rexy712 2019-03-09 07:18:55 -08:00
parent 051a694789
commit 8cc6272158
2 changed files with 26 additions and 26 deletions

1
TODO
View File

@ -1,7 +1,6 @@
use libmagic to determine file types?
add av_freep cleanup to raii interface for libav* (probably replacing unique_ptr in that case)
raii-ify the muxing function
fix muxing fps/bitrate issue
scale video thumbnails to same size as image thumbnails (500 in either dimension, same aspect ratio)
crosspost title
thread pool for workers. rehurn std::promise?

View File

@ -21,9 +21,19 @@
#include <utility> //move
#include <tuple>
#define DEBUG
#define DBG_LEVEL_NONE 0
#define DBG_LEVEL_NORMAL 2
#define DBG_LEVEL_VERBOSE 3
#ifdef DEBUG
#define DEBUG_LEVEL DBG_LEVEL_NORMAL
#if defined(DEBUG_LEVEL) && DEBUG_LEVEL >= DBG_LEVEL_VERBOSE
# define LIBAV_SET_LOG_LEVEL() av_log_set_level(AV_LOG_INFO)
#else
# define LIBAV_SET_LOG_LEVEL() av_log_set_level(AV_LOG_FATAL)
#endif
#if defined(DEBUG_LEVEL) && DEBUG_LEVEL >= DBG_LEVEL_NORMAL
# define DEBUG_PRINT(...) do{printf(__VA_ARGS__);}while(0)
#else
# define DEBUG_PRINT(...) do{}while(0)
@ -38,6 +48,8 @@
#include "reddit.hpp"
#include "matrix.hpp"
#include <limits> //numeric_limits
extern "C"{
# include <libavcodec/avcodec.h> //AVCodecContext, AVCodec
# include <libavformat/avformat.h> //AVFormatContext
@ -58,7 +70,7 @@ extern "C"{
//with the new code that fixes invalid input pts/dts, now the output framerate/bitrate is off
bool mux_audio_video(const raii::string_base& audio_file, const raii::string_base& video_file, const raii::string_base& output_file){
REGISTER_LIBAV();
av_log_set_level(AV_LOG_FATAL);
LIBAV_SET_LOG_LEVEL();
AVOutputFormat* out_format = NULL;
AVFormatContext* audio_context = NULL, *video_context = NULL, *output_context = NULL;
@ -94,17 +106,10 @@ bool mux_audio_video(const raii::string_base& audio_file, const raii::string_bas
audio_index_in = i;
AVStream* in_stream = audio_context->streams[i];
AVCodec* codec = avcodec_find_encoder(in_stream->codecpar->codec_id);
AVCodecContext* tmp = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(tmp, in_stream->codecpar);
AVStream* out_stream = avformat_new_stream(output_context, codec);
AVStream* out_stream = avformat_new_stream(output_context, NULL);
audio_index_out = out_stream->index;
if(output_context->oformat->flags & AVFMT_GLOBALHEADER){
tmp->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
tmp->codec_tag = 0;
avcodec_parameters_from_context(out_stream->codecpar, tmp);
avcodec_free_context(&tmp);
avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
out_stream->codecpar->codec_tag = 0;
break;
}
@ -114,17 +119,10 @@ bool mux_audio_video(const raii::string_base& audio_file, const raii::string_bas
video_index_in = i;
AVStream* in_stream = video_context->streams[i];
AVCodec* codec = avcodec_find_encoder(in_stream->codecpar->codec_id);
AVCodecContext* tmp = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(tmp, in_stream->codecpar);
AVStream* out_stream = avformat_new_stream(output_context, codec);
AVStream* out_stream = avformat_new_stream(output_context, NULL);
video_index_out = out_stream->index;
if(output_context->oformat->flags & AVFMT_GLOBALHEADER){
tmp->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
tmp->codec_tag = 0;
avcodec_parameters_from_context(out_stream->codecpar, tmp);
avcodec_free_context(&tmp);
avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
out_stream->codecpar->codec_tag = 0;
break;
}
@ -150,7 +148,10 @@ bool mux_audio_video(const raii::string_base& audio_file, const raii::string_bas
}
int64_t video_pts = 0, audio_pts = 0;
int64_t last_video_dts = 0, last_audio_dts = 0;
//took me 2 days to realize I had to initialize these to the smallest possible int64 value instead of just 0
int64_t last_video_dts, last_audio_dts;
last_video_dts = last_audio_dts = std::numeric_limits<int64_t>::min();
while(true){
AVPacket packet;
@ -208,7 +209,7 @@ bool mux_audio_video(const raii::string_base& audio_file, const raii::string_bas
//if dts is out of order, ffmpeg throws an error. So manually fix. Similar to what ffmpeg does in ffmpeg.c
if(packet.dts < (*last_dts + !(output_context->oformat->flags & AVFMT_TS_NONSTRICT)) && packet.dts != AV_NOPTS_VALUE && (*last_dts) != AV_NOPTS_VALUE){
int64_t next_dts = (*last_dts)+1;
if(packet.pts >= packet.dts && packet.pts != AV_NOPTS_VALUE){
if(packet.pts >= packet.dts){
packet.pts = FFMAX(packet.pts, next_dts);
}
if(packet.pts == AV_NOPTS_VALUE){