Merge branch 'master' into otio

This commit is contained in:
itsmattkc
2020-10-22 20:26:16 +11:00
149 changed files with 4350 additions and 2079 deletions
+8
View File
@@ -20,6 +20,8 @@
#include "encoder.h"
#include <QFile>
#include "ffmpeg/ffmpegencoder.h"
OLIVE_NAMESPACE_ENTER
@@ -34,6 +36,12 @@ const EncodingParams &Encoder::params() const
return params_;
}
void Encoder::WriteAudio(AudioParams pcm_info, const QString &pcm_filename)
{
QFile f(pcm_filename);
WriteAudio(pcm_info, &f);
}
EncodingParams::EncodingParams() :
video_enabled_(false),
video_bit_rate_(0),
+3 -1
View File
@@ -116,7 +116,9 @@ public:
virtual bool WriteFrame(OLIVE_NAMESPACE::FramePtr frame, OLIVE_NAMESPACE::rational time) = 0;
virtual void WriteAudio(OLIVE_NAMESPACE::AudioParams pcm_info,
const QString& pcm_filename) = 0;
QIODevice *file) = 0;
void WriteAudio(OLIVE_NAMESPACE::AudioParams pcm_info,
const QString& pcm_filename);
virtual void Close() = 0;
+41 -12
View File
@@ -107,9 +107,11 @@ bool FFmpegDecoder::Open()
FFmpegFramePoolValue& frame_pool = frame_pool_map_[key];
if (!frame_pool.pool) {
// FIXME: Hardcoded value. It seems to work fine, but is there a possibility we should make
// this a dynamic value somehow or a configurable value?
frame_pool.pool = new FFmpegFramePool(32);
// Frames are allocated as threads * threads, to scale from each thread sharing one set
// to all of them working individually
int thread_count = QThread::idealThreadCount();
int max_memory_frame_count = thread_count * thread_count;
frame_pool.pool = new FFmpegFramePool(max_memory_frame_count);
}
frame_pool.handles++;
@@ -574,6 +576,25 @@ ItemPtr FFmpegDecoder::Probe(const QString& filename, const QAtomicInt* cancelle
audio_stream->set_channels(avstream->codecpar->channels);
audio_stream->set_sample_rate(avstream->codecpar->sample_rate);
if (avstream->duration == AV_NOPTS_VALUE) {
// Loop through stream until we get the whole duration
FFmpegDecoderInstance instance(filename, i);
AVPacket* pkt = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
int64_t new_dur;
do {
new_dur = frame->pts;
} while (instance.GetFrame(pkt, frame) >= 0);
avstream->duration = new_dur;
av_frame_free(&frame);
av_packet_free(&pkt);
}
str = audio_stream;
} else {
@@ -1087,6 +1108,9 @@ FFmpegFramePool::ElementPtr FFmpegDecoderInstance::RetrieveFrame(const int64_t&
break;
}
// Cut down to thread count - 1 before we acquire a new frame
TruncateCacheRangeToFrames(QThread::idealThreadCount() -1);
FFmpegFramePool::ElementPtr cached = frame_pool_->Get();
if (!cached) {
@@ -1127,14 +1151,6 @@ FFmpegFramePool::ElementPtr FFmpegDecoderInstance::RetrieveFrame(const int64_t&
previous = cached_frames_.last();
}
// Clear early frames
int removed = TruncateCacheRangeTo(second_ts_);
if (removed == 0 && MemoryPoolLimitReached()) {
// Relinquish a frame if we have to conserve memory
RemoveFirstFrame();
}
// Append this frame and signal to other threads that a new frame has arrived
cached_frames_.append(cached);
@@ -1322,7 +1338,7 @@ void FFmpegDecoderInstance::RemoveFramesBefore(const qint64 &t)
}
}
int FFmpegDecoderInstance::TruncateCacheRangeTo(const qint64 &t)
int FFmpegDecoderInstance::TruncateCacheRangeToTime(const qint64 &t)
{
int counter = 0;
@@ -1335,6 +1351,19 @@ int FFmpegDecoderInstance::TruncateCacheRangeTo(const qint64 &t)
return counter;
}
int FFmpegDecoderInstance::TruncateCacheRangeToFrames(int nb_frames)
{
int counter = 0;
// We keep one frame in memory as an identifier for what pts the decoder is up to
while (cached_frames_.size() > nb_frames) {
RemoveFirstFrame();
counter++;
}
return counter;
}
void FFmpegDecoderInstance::RemoveFirstFrame()
{
cached_frames_.removeFirst();
+2 -1
View File
@@ -62,7 +62,8 @@ public:
FFmpegFramePool::ElementPtr GetFrameFromCache(const int64_t& t) const;
void RemoveFramesBefore(const qint64& t);
int TruncateCacheRangeTo(const qint64& t);
int TruncateCacheRangeToTime(const qint64& t);
int TruncateCacheRangeToFrames(int nb_frames);
void RemoveFirstFrame();
AVFormatContext* fmt_ctx() const
+7 -6
View File
@@ -185,10 +185,9 @@ fail:
return success;
}
void FFmpegEncoder::WriteAudio(AudioParams pcm_info, const QString &pcm_filename)
void FFmpegEncoder::WriteAudio(AudioParams pcm_info, QIODevice* file)
{
QFile pcm(pcm_filename);
if (pcm.open(QFile::ReadOnly)) {
if (file->open(QFile::ReadOnly)) {
// Divide PCM stream into AVFrames
// See if the codec defines a number of samples per frame
@@ -239,7 +238,7 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, const QString &pcm_filename
int max_read = pcm_info.samples_to_bytes(samples_needed);
// Read bytes from PCM
QByteArray input_data = pcm.read(max_read);
QByteArray input_data = file->read(max_read);
// Use swresample to convert the data into the correct format
const char* input_data_array = input_data.constData();
@@ -273,7 +272,7 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, const QString &pcm_filename
}
// Break if we've reached the end point
if (pcm.atEnd()) {
if (file->atEnd()) {
break;
}
}
@@ -282,7 +281,9 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, const QString &pcm_filename
swr_free(&swr_ctx);
pcm.close();
file->close();
} else {
qWarning() << "Failed to open audio IO device for encoding";
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ public:
virtual bool WriteFrame(OLIVE_NAMESPACE::FramePtr frame, OLIVE_NAMESPACE::rational time) override;
virtual void WriteAudio(OLIVE_NAMESPACE::AudioParams pcm_info,
const QString& pcm_filename) override;
QIODevice *file) override;
virtual void Close() override;