decoder: make texture inside decoder
This commit is contained in:
@@ -86,7 +86,7 @@ bool Decoder::Open(const CodecStream &stream)
|
||||
}
|
||||
}
|
||||
|
||||
bool Decoder::RetrieveVideo(TexturePtr destination, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled)
|
||||
TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
@@ -94,19 +94,19 @@ bool Decoder::RetrieveVideo(TexturePtr destination, const rational &timecode, co
|
||||
|
||||
if (!stream_.IsValid()) {
|
||||
qCritical() << "Can't retrieve video on a closed decoder";
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!SupportsVideo()) {
|
||||
qCritical() << "Decoder doesn't support video";
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cancelled && *cancelled) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return RetrieveVideoInternal(destination, timecode, divider, cancelled);
|
||||
return RetrieveVideoInternal(renderer, timecode, divider, cancelled);
|
||||
}
|
||||
|
||||
Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range, const AudioParams ¶ms, const QString& cache_path, Footage::LoopMode loop_mode, RenderMode::Mode mode)
|
||||
@@ -264,12 +264,12 @@ int64_t Decoder::GetImageSequenceIndex(const QString &filename)
|
||||
return number_only.toLongLong();
|
||||
}
|
||||
|
||||
bool Decoder::RetrieveVideoInternal(TexturePtr destination, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled)
|
||||
TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled)
|
||||
{
|
||||
Q_UNUSED(timecode)
|
||||
Q_UNUSED(divider)
|
||||
Q_UNUSED(cancelled)
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Decoder::ConformAudioInternal(const QVector<QString> &filenames, const AudioParams ¶ms, const QAtomicInt* cancelled)
|
||||
|
||||
+5
-3
@@ -150,9 +150,11 @@ public:
|
||||
RetrieveVideoParams()
|
||||
{
|
||||
divider = 1;
|
||||
maximum_format = VideoParams::kFormatInvalid;
|
||||
}
|
||||
|
||||
int divider;
|
||||
VideoParams::Format maximum_format;
|
||||
|
||||
void reset()
|
||||
{
|
||||
@@ -161,7 +163,7 @@ public:
|
||||
|
||||
bool operator==(const RetrieveVideoParams& rhs) const
|
||||
{
|
||||
return divider == rhs.divider;
|
||||
return divider == rhs.divider && maximum_format == rhs.maximum_format;
|
||||
}
|
||||
|
||||
bool operator!=(const RetrieveVideoParams& rhs) const
|
||||
@@ -180,7 +182,7 @@ public:
|
||||
*
|
||||
* This function is thread safe and can only run while the decoder is open. \see Open()
|
||||
*/
|
||||
bool RetrieveVideo(TexturePtr destination, const rational& timecode, const RetrieveVideoParams& divider, const QAtomicInt *cancelled = nullptr);
|
||||
TexturePtr RetrieveVideo(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled = nullptr);
|
||||
|
||||
enum RetrieveAudioStatus {
|
||||
kInvalid = -1,
|
||||
@@ -275,7 +277,7 @@ protected:
|
||||
* Sub-classes must override this function IF they support video. Function is already mutexed
|
||||
* so sub-classes don't need to worry about thread safety.
|
||||
*/
|
||||
virtual bool RetrieveVideoInternal(TexturePtr destination, const rational& timecode, const RetrieveVideoParams& divider, const QAtomicInt *cancelled);
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled);
|
||||
|
||||
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams ¶ms, const QAtomicInt* cancelled);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ extern "C" {
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "render/framehashcache.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/renderer.h"
|
||||
#include "render/subtitleparams.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -138,18 +139,18 @@ bool FFmpegDecoder::OpenInternal()
|
||||
return output_frame;
|
||||
}*/
|
||||
|
||||
bool FFmpegDecoder::RetrieveVideoInternal(TexturePtr destination, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled)
|
||||
TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled)
|
||||
{
|
||||
if (AVFramePtr f = RetrieveFrame(timecode, cancelled)) {
|
||||
if (InitScaler(f.get(), params)) {
|
||||
int r;
|
||||
r = av_buffersrc_add_frame_flags(buffersrc_ctx_, f.get(), AV_BUFFERSRC_FLAG_KEEP_REF);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
r = av_buffersink_get_frame(buffersink_ctx_, working_frame_);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VideoParams vp(instance_.avstream()->codecpar->width,
|
||||
@@ -160,14 +161,15 @@ bool FFmpegDecoder::RetrieveVideoInternal(TexturePtr destination, const rational
|
||||
VideoParams::kInterlaceNone,
|
||||
params.divider);
|
||||
|
||||
destination->Upload(working_frame_->data[0], working_frame_->linesize[0] / vp.GetBytesPerPixel());
|
||||
TexturePtr tex = renderer->CreateTexture(vp, working_frame_->data[0], working_frame_->linesize[0] / vp.GetBytesPerPixel());
|
||||
|
||||
av_frame_unref(working_frame_);
|
||||
return true;
|
||||
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FFmpegDecoder::CloseInternal()
|
||||
@@ -798,7 +800,7 @@ bool FFmpegDecoder::InitScaler(AVFrame *input, const RetrieveVideoParams& params
|
||||
}
|
||||
|
||||
// Get an Olive compatible AVPixelFormat
|
||||
AVPixelFormat ideal_pix_fmt = FFmpegUtils::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(input_fmt_));
|
||||
AVPixelFormat ideal_pix_fmt = FFmpegUtils::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(input_fmt_), params.maximum_format);
|
||||
|
||||
// Determine which Olive native pixel format we retrieved
|
||||
// Note that FFmpeg doesn't support float formats
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual bool OpenInternal() override;
|
||||
virtual bool RetrieveVideoInternal(TexturePtr destination, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override;
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override;
|
||||
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams ¶ms, const QAtomicInt* cancelled) override;
|
||||
virtual void CloseInternal() override;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "common/oiioutils.h"
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "render/renderer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -115,7 +116,7 @@ bool OIIODecoder::OpenInternal()
|
||||
return OpenImageHandler(stream().filename(), stream().stream());
|
||||
}
|
||||
|
||||
bool OIIODecoder::RetrieveVideoInternal(TexturePtr destination, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled)
|
||||
TexturePtr OIIODecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled)
|
||||
{
|
||||
Q_UNUSED(timecode)
|
||||
Q_UNUSED(cancelled)
|
||||
@@ -152,9 +153,7 @@ bool OIIODecoder::RetrieveVideoInternal(TexturePtr destination, const rational &
|
||||
}
|
||||
}
|
||||
|
||||
destination->Upload(buffer_.data(), buffer_.linesize_pixels());
|
||||
|
||||
return true;
|
||||
return renderer->CreateTexture(vp, buffer_.data(), buffer_.linesize_pixels());
|
||||
}
|
||||
|
||||
void OIIODecoder::CloseInternal()
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual bool OpenInternal() override;
|
||||
virtual bool RetrieveVideoInternal(TexturePtr destination, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override;
|
||||
virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override;
|
||||
virtual void CloseInternal() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -22,17 +22,20 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
AVPixelFormat FFmpegUtils::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt)
|
||||
AVPixelFormat FFmpegUtils::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt, VideoParams::Format maximum)
|
||||
{
|
||||
AVPixelFormat possible_pix_fmts[] = {
|
||||
// RGBA formats only because GPUs always upconvert to RGBA, so if it's RGB, that adds extra
|
||||
// conversion overhead
|
||||
AV_PIX_FMT_RGBA,
|
||||
AV_PIX_FMT_RGBA64,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
std::vector<AVPixelFormat> possible_pix_fmts(3);
|
||||
|
||||
return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts,
|
||||
possible_pix_fmts[0] = AV_PIX_FMT_RGBA;
|
||||
|
||||
if (maximum == VideoParams::kFormatUnsigned8) {
|
||||
possible_pix_fmts[1] = AV_PIX_FMT_NONE;
|
||||
} else {
|
||||
possible_pix_fmts[1] = AV_PIX_FMT_RGBA64;
|
||||
possible_pix_fmts[2] = AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts.data(),
|
||||
pix_fmt,
|
||||
1,
|
||||
nullptr);
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
/**
|
||||
* @brief Returns an AVPixelFormat that can be used to convert a frame to a data type Olive supports with minimal data loss
|
||||
*/
|
||||
static AVPixelFormat GetCompatiblePixelFormat(const AVPixelFormat& pix_fmt);
|
||||
static AVPixelFormat GetCompatiblePixelFormat(const AVPixelFormat& pix_fmt, VideoParams::Format maximum = VideoParams::kFormatInvalid);
|
||||
|
||||
/**
|
||||
* @brief Returns a native pixel format that can be used to convert from a native frame to an AVFrame with minimal data loss
|
||||
|
||||
@@ -452,17 +452,15 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
|
||||
if (decoder) {
|
||||
Decoder::RetrieveVideoParams p;
|
||||
p.divider = stream.video_params().divider();
|
||||
p.maximum_format = destination->format();
|
||||
|
||||
if (!IsCancelled()) {
|
||||
|
||||
VideoParams tex_params = stream.video_params();
|
||||
|
||||
if (tex_params.is_valid()) {
|
||||
TexturePtr unmanaged_texture = render_ctx_->CreateTexture(tex_params);
|
||||
TexturePtr unmanaged_texture = decoder->RetrieveVideo(render_ctx_, (stream_data.video_type() == VideoParams::kVideoTypeVideo) ? input_time : Decoder::kAnyTimecode, p, GetCancelPointer());
|
||||
|
||||
bool frame = decoder->RetrieveVideo(unmanaged_texture, (stream_data.video_type() == VideoParams::kVideoTypeVideo) ? input_time : Decoder::kAnyTimecode, p, GetCancelPointer());
|
||||
|
||||
if (frame) {
|
||||
if (unmanaged_texture) {
|
||||
// We convert to our rendering pixel format, since that will always be float-based which
|
||||
// is necessary for correct color conversion
|
||||
ColorProcessorPtr processor = ColorProcessor::Create(color_manager,
|
||||
|
||||
Reference in New Issue
Block a user