improved render channel count system
This commit is contained in:
@@ -24,11 +24,11 @@
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "codec/ffmpeg/ffmpegcommon.h"
|
||||
#include "codec/ffmpeg/ffmpegdecoder.h"
|
||||
#include "codec/oiio/oiiodecoder.h"
|
||||
#include "codec/waveinput.h"
|
||||
#include "codec/waveoutput.h"
|
||||
#include "common/ffmpegutils.h"
|
||||
#include "common/filefunctions.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#ifdef USE_OTIO
|
||||
|
||||
+2
-2
@@ -122,9 +122,9 @@ public:
|
||||
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual PixelFormat::Format GetDesiredPixelFormat() const
|
||||
virtual VideoParams::Format GetDesiredPixelFormat() const
|
||||
{
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
return VideoParams::kFormatInvalid;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
codec/ffmpeg/avframeptr.h
|
||||
codec/ffmpeg/ffmpegcommon.h
|
||||
codec/ffmpeg/ffmpegcommon.cpp
|
||||
codec/ffmpeg/ffmpegdecoder.h
|
||||
codec/ffmpeg/ffmpegdecoder.cpp
|
||||
codec/ffmpeg/ffmpegencoder.h
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "ffmpegcommon.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
AVPixelFormat FFmpegCommon::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt)
|
||||
{
|
||||
AVPixelFormat possible_pix_fmts[] = {
|
||||
AV_PIX_FMT_RGBA,
|
||||
AV_PIX_FMT_RGBA64,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
|
||||
return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts,
|
||||
pix_fmt,
|
||||
1,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
SampleFormat::Format FFmpegCommon::GetNativeSampleFormat(const AVSampleFormat &smp_fmt)
|
||||
{
|
||||
switch (smp_fmt) {
|
||||
case AV_SAMPLE_FMT_U8:
|
||||
return SampleFormat::SAMPLE_FMT_U8;
|
||||
case AV_SAMPLE_FMT_S16:
|
||||
return SampleFormat::SAMPLE_FMT_S16;
|
||||
case AV_SAMPLE_FMT_S32:
|
||||
return SampleFormat::SAMPLE_FMT_S32;
|
||||
case AV_SAMPLE_FMT_S64:
|
||||
return SampleFormat::SAMPLE_FMT_S64;
|
||||
case AV_SAMPLE_FMT_FLT:
|
||||
return SampleFormat::SAMPLE_FMT_FLT;
|
||||
case AV_SAMPLE_FMT_DBL:
|
||||
return SampleFormat::SAMPLE_FMT_DBL;
|
||||
case AV_SAMPLE_FMT_U8P :
|
||||
case AV_SAMPLE_FMT_S16P:
|
||||
case AV_SAMPLE_FMT_S32P:
|
||||
case AV_SAMPLE_FMT_S64P:
|
||||
case AV_SAMPLE_FMT_FLTP:
|
||||
case AV_SAMPLE_FMT_DBLP:
|
||||
case AV_SAMPLE_FMT_NONE:
|
||||
case AV_SAMPLE_FMT_NB:
|
||||
break;
|
||||
}
|
||||
|
||||
return SampleFormat::SAMPLE_FMT_INVALID;
|
||||
}
|
||||
|
||||
AVSampleFormat FFmpegCommon::GetFFmpegSampleFormat(const SampleFormat::Format &smp_fmt)
|
||||
{
|
||||
switch (smp_fmt) {
|
||||
case SampleFormat::SAMPLE_FMT_U8:
|
||||
return AV_SAMPLE_FMT_U8;
|
||||
case SampleFormat::SAMPLE_FMT_S16:
|
||||
return AV_SAMPLE_FMT_S16;
|
||||
case SampleFormat::SAMPLE_FMT_S32:
|
||||
return AV_SAMPLE_FMT_S32;
|
||||
case SampleFormat::SAMPLE_FMT_S64:
|
||||
return AV_SAMPLE_FMT_S64;
|
||||
case SampleFormat::SAMPLE_FMT_FLT:
|
||||
return AV_SAMPLE_FMT_FLT;
|
||||
case SampleFormat::SAMPLE_FMT_DBL:
|
||||
return AV_SAMPLE_FMT_DBL;
|
||||
case SampleFormat::SAMPLE_FMT_INVALID:
|
||||
case SampleFormat::SAMPLE_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
}
|
||||
|
||||
AVPixelFormat FFmpegCommon::GetFFmpegPixelFormat(const PixelFormat::Format &pix_fmt)
|
||||
{
|
||||
switch (pix_fmt) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return AV_PIX_FMT_RGBA;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return AV_PIX_FMT_RGBA64;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
PixelFormat::Format FFmpegCommon::GetCompatiblePixelFormat(const PixelFormat::Format &pix_fmt)
|
||||
{
|
||||
switch (pix_fmt) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return PixelFormat::PIX_FMT_RGBA8;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return PixelFormat::PIX_FMT_RGBA16U;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -1,63 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef FFMPEGABSTRACTION_H
|
||||
#define FFMPEGABSTRACTION_H
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
#include "audio/sampleformat.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class FFmpegCommon {
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Returns a native pixel format that can be used to convert from a native frame to an AVFrame with minimal data loss
|
||||
*/
|
||||
static PixelFormat::Format GetCompatiblePixelFormat(const PixelFormat::Format& pix_fmt);
|
||||
|
||||
/**
|
||||
* @brief Returns an FFmpeg pixel format for a given native pixel format
|
||||
*/
|
||||
static AVPixelFormat GetFFmpegPixelFormat(const PixelFormat::Format& pix_fmt);
|
||||
|
||||
/**
|
||||
* @brief Returns a native sample format type for a given AVSampleFormat
|
||||
*/
|
||||
static SampleFormat::Format GetNativeSampleFormat(const AVSampleFormat& smp_fmt);
|
||||
|
||||
/**
|
||||
* @brief Returns an FFmpeg sample format type for a given native type
|
||||
*/
|
||||
static AVSampleFormat GetFFmpegSampleFormat(const SampleFormat::Format &smp_fmt);
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // FFMPEGABSTRACTION_H
|
||||
@@ -38,13 +38,12 @@ extern "C" {
|
||||
|
||||
#include "codec/waveinput.h"
|
||||
#include "common/define.h"
|
||||
#include "common/ffmpegutils.h"
|
||||
#include "common/filefunctions.h"
|
||||
#include "common/functiontimer.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "ffmpegcommon.h"
|
||||
#include "render/framehashcache.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -73,13 +72,17 @@ bool FFmpegDecoder::OpenInternal()
|
||||
|
||||
if (stream()->type() == Stream::kVideo) {
|
||||
// Get an Olive compatible AVPixelFormat
|
||||
ideal_pix_fmt_ = FFmpegCommon::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(s->codecpar->format));
|
||||
ideal_pix_fmt_ = FFmpegUtils::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(s->codecpar->format));
|
||||
|
||||
// Determine which Olive native pixel format we retrieved
|
||||
// Note that FFmpeg doesn't support float formats
|
||||
native_pix_fmt_ = GetNativePixelFormat(ideal_pix_fmt_);
|
||||
native_channel_count_ = GetNativeChannelCount(ideal_pix_fmt_);
|
||||
|
||||
if (native_pix_fmt_ == PixelFormat::PIX_FMT_INVALID) {
|
||||
qDebug() << "Set channel count to:" << native_channel_count_;
|
||||
|
||||
if (native_pix_fmt_ == VideoParams::kFormatInvalid
|
||||
|| native_channel_count_ == 0) {
|
||||
qDebug() << "Failed to find valid native pixel format for" << ideal_pix_fmt_;
|
||||
return false;
|
||||
}
|
||||
@@ -124,6 +127,7 @@ FramePtr FFmpegDecoder::RetrieveStillImage(const rational &timecode, const int &
|
||||
output_frame->set_video_params(VideoParams(frame->width,
|
||||
frame->height,
|
||||
native_pix_fmt_,
|
||||
native_channel_count_,
|
||||
std::static_pointer_cast<VideoStream>(stream())->pixel_aspect_ratio(),
|
||||
std::static_pointer_cast<VideoStream>(stream())->interlacing(),
|
||||
divider));
|
||||
@@ -172,7 +176,7 @@ FramePtr FFmpegDecoder::RetrieveVideoInternal(const rational &timecode, const in
|
||||
ClearFrameCache();
|
||||
|
||||
// Set new frame pool parameters
|
||||
pool_.SetParameters(divided_width, divided_height, native_pix_fmt_);
|
||||
pool_.SetParameters(divided_width, divided_height, native_pix_fmt_, native_channel_count_);
|
||||
}
|
||||
|
||||
// Retrieve frame
|
||||
@@ -184,6 +188,7 @@ FramePtr FFmpegDecoder::RetrieveVideoInternal(const rational &timecode, const in
|
||||
copy->set_video_params(VideoParams(vs->width(),
|
||||
vs->height(),
|
||||
native_pix_fmt_,
|
||||
native_channel_count_,
|
||||
std::static_pointer_cast<VideoStream>(stream())->pixel_aspect_ratio(),
|
||||
std::static_pointer_cast<VideoStream>(stream())->interlacing(),
|
||||
divider));
|
||||
@@ -328,10 +333,13 @@ FootagePtr FFmpegDecoder::Probe(const QString& filename, const QAtomicInt* cance
|
||||
|
||||
video_stream->set_width(avstream->codecpar->width);
|
||||
video_stream->set_height(avstream->codecpar->height);
|
||||
video_stream->set_format(GetNativePixelFormat(FFmpegCommon::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(avstream->codecpar->format))));
|
||||
video_stream->set_interlacing(interlacing);
|
||||
video_stream->set_pixel_aspect_ratio(pixel_aspect_ratio);
|
||||
|
||||
AVPixelFormat compatible_pix_fmt = FFmpegUtils::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(avstream->codecpar->format));
|
||||
video_stream->set_format(GetNativePixelFormat(compatible_pix_fmt));
|
||||
video_stream->set_channel_count(GetNativeChannelCount(compatible_pix_fmt));
|
||||
|
||||
str = video_stream;
|
||||
|
||||
} else {
|
||||
@@ -460,7 +468,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QString &filename, const AudioPar
|
||||
// Create resampling context
|
||||
SwrContext* resampler = swr_alloc_set_opts(nullptr,
|
||||
params.channel_layout(),
|
||||
FFmpegCommon::GetFFmpegSampleFormat(params.format()),
|
||||
FFmpegUtils::GetFFmpegSampleFormat(params.format()),
|
||||
params.sample_rate(),
|
||||
channel_layout,
|
||||
static_cast<AVSampleFormat>(instance_.avstream()->codecpar->format),
|
||||
@@ -542,15 +550,31 @@ bool FFmpegDecoder::ConformAudioInternal(const QString &filename, const AudioPar
|
||||
return success;
|
||||
}
|
||||
|
||||
PixelFormat::Format FFmpegDecoder::GetNativePixelFormat(AVPixelFormat pix_fmt)
|
||||
VideoParams::Format FFmpegDecoder::GetNativePixelFormat(AVPixelFormat pix_fmt)
|
||||
{
|
||||
switch (pix_fmt) {
|
||||
case AV_PIX_FMT_RGB24:
|
||||
case AV_PIX_FMT_RGBA:
|
||||
return PixelFormat::PIX_FMT_RGBA8;
|
||||
return VideoParams::kFormatUnsigned8;
|
||||
case AV_PIX_FMT_RGB48:
|
||||
case AV_PIX_FMT_RGBA64:
|
||||
return PixelFormat::PIX_FMT_RGBA16U;
|
||||
return VideoParams::kFormatUnsigned16;
|
||||
default:
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
return VideoParams::kFormatInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
int FFmpegDecoder::GetNativeChannelCount(AVPixelFormat pix_fmt)
|
||||
{
|
||||
switch (pix_fmt) {
|
||||
case AV_PIX_FMT_RGB24:
|
||||
case AV_PIX_FMT_RGB48:
|
||||
return VideoParams::kRGBChannelCount;
|
||||
case AV_PIX_FMT_RGBA:
|
||||
case AV_PIX_FMT_RGBA64:
|
||||
return VideoParams::kRGBAChannelCount;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,7 +753,7 @@ FFmpegFramePool::ElementPtr FFmpegDecoder::RetrieveFrame(const int64_t& target_t
|
||||
|
||||
// Store in queue, converting to native format
|
||||
uint8_t* destination_data = cached->data();
|
||||
int destination_linesize = Frame::generate_linesize_bytes(VideoParams::GetScaledDimension(instance_.avstream()->codecpar->width, divider), native_pix_fmt_);
|
||||
int destination_linesize = Frame::generate_linesize_bytes(VideoParams::GetScaledDimension(instance_.avstream()->codecpar->width, divider), native_pix_fmt_, native_channel_count_);
|
||||
FFmpegBufferToNativeBuffer(working_frame->data, working_frame->linesize, &destination_data, &destination_linesize);
|
||||
|
||||
// Set timestamp so this frame can be identified later
|
||||
|
||||
@@ -32,7 +32,6 @@ extern "C" {
|
||||
#include <QVector>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "audio/sampleformat.h"
|
||||
#include "avframeptr.h"
|
||||
#include "codec/decoder.h"
|
||||
#include "codec/waveoutput.h"
|
||||
@@ -126,7 +125,8 @@ private:
|
||||
|
||||
FramePtr RetrieveStillImage(const rational& timecode, const int& divider);
|
||||
|
||||
static PixelFormat::Format GetNativePixelFormat(AVPixelFormat pix_fmt);
|
||||
static VideoParams::Format GetNativePixelFormat(AVPixelFormat pix_fmt);
|
||||
static int GetNativeChannelCount(AVPixelFormat pix_fmt);
|
||||
|
||||
static uint64_t ValidateChannelLayout(AVStream *stream);
|
||||
|
||||
@@ -143,7 +143,8 @@ private:
|
||||
SwsContext* scale_ctx_;
|
||||
int scale_divider_;
|
||||
AVPixelFormat ideal_pix_fmt_;
|
||||
PixelFormat::Format native_pix_fmt_;
|
||||
VideoParams::Format native_pix_fmt_;
|
||||
int native_channel_count_;
|
||||
|
||||
FFmpegFramePool pool_;
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@ extern "C" {
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "ffmpegcommon.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "common/ffmpegutils.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -36,7 +35,8 @@ FFmpegEncoder::FFmpegEncoder(const EncodingParams ¶ms) :
|
||||
fmt_ctx_(nullptr),
|
||||
video_stream_(nullptr),
|
||||
video_codec_ctx_(nullptr),
|
||||
video_scale_ctx_(nullptr),
|
||||
video_alpha_scale_ctx_(nullptr),
|
||||
video_noalpha_scale_ctx_(nullptr),
|
||||
audio_stream_(nullptr),
|
||||
audio_codec_ctx_(nullptr),
|
||||
audio_resample_ctx_(nullptr),
|
||||
@@ -72,29 +72,49 @@ bool FFmpegEncoder::Open()
|
||||
}
|
||||
|
||||
// This is the format we will expect frames received in Write() to be in
|
||||
PixelFormat::Format native_pixel_fmt = params().video_params().format();
|
||||
VideoParams::Format native_pixel_fmt = params().video_params().format();
|
||||
|
||||
// This is the format we will need to convert the frame to for swscale to understand it
|
||||
video_conversion_fmt_ = FFmpegCommon::GetCompatiblePixelFormat(native_pixel_fmt);
|
||||
video_conversion_fmt_ = FFmpegUtils::GetCompatiblePixelFormat(native_pixel_fmt);
|
||||
|
||||
// This is the equivalent pixel format above as an AVPixelFormat that swscale can understand
|
||||
AVPixelFormat src_pix_fmt = FFmpegCommon::GetFFmpegPixelFormat(video_conversion_fmt_);
|
||||
AVPixelFormat src_alpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat(video_conversion_fmt_,
|
||||
VideoParams::kRGBAChannelCount);
|
||||
|
||||
AVPixelFormat src_noalpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat(video_conversion_fmt_,
|
||||
VideoParams::kRGBChannelCount);
|
||||
|
||||
if (src_alpha_pix_fmt == AV_PIX_FMT_NONE || src_noalpha_pix_fmt == AV_PIX_FMT_NONE) {
|
||||
Error(QStringLiteral("Failed to find suitable pixel format for this buffer"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is the pixel format the encoder wants to encode to
|
||||
AVPixelFormat encoder_pix_fmt = video_codec_ctx_->pix_fmt;
|
||||
|
||||
// Set up a scaling context - if the native pixel format is not equal to the encoder's, we'll need to convert it
|
||||
// before encoding. Even if we don't, this may be useful for converting between linesizes, etc.
|
||||
video_scale_ctx_ = sws_getContext(params().video_params().width(),
|
||||
params().video_params().height(),
|
||||
src_pix_fmt,
|
||||
params().video_params().width(),
|
||||
params().video_params().height(),
|
||||
encoder_pix_fmt,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
video_alpha_scale_ctx_ = sws_getContext(params().video_params().width(),
|
||||
params().video_params().height(),
|
||||
src_alpha_pix_fmt,
|
||||
params().video_params().width(),
|
||||
params().video_params().height(),
|
||||
encoder_pix_fmt,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
video_noalpha_scale_ctx_ = sws_getContext(params().video_params().width(),
|
||||
params().video_params().height(),
|
||||
src_noalpha_pix_fmt,
|
||||
params().video_params().width(),
|
||||
params().video_params().height(),
|
||||
encoder_pix_fmt,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
// Initialize an audio stream if it's enabled
|
||||
@@ -157,19 +177,22 @@ bool FFmpegEncoder::WriteFrame(FramePtr frame, rational time)
|
||||
|
||||
// We may need to convert this frame to a frame that swscale will understand
|
||||
if (frame->format() != video_conversion_fmt_) {
|
||||
frame = PixelFormat::ConvertPixelFormat(frame, video_conversion_fmt_);
|
||||
frame = frame->convert(video_conversion_fmt_);
|
||||
}
|
||||
|
||||
// Use swscale context to convert formats/linesizes
|
||||
input_data = frame->const_data();
|
||||
input_linesize = frame->linesize_bytes();
|
||||
error_code = sws_scale(video_scale_ctx_,
|
||||
|
||||
error_code = sws_scale((frame->channel_count() == VideoParams::kRGBAChannelCount) ? video_alpha_scale_ctx_ : video_noalpha_scale_ctx_,
|
||||
reinterpret_cast<const uint8_t**>(&input_data),
|
||||
&input_linesize,
|
||||
0,
|
||||
frame->height(),
|
||||
encoded_frame->data,
|
||||
encoded_frame->linesize);
|
||||
|
||||
|
||||
if (error_code < 0) {
|
||||
FFmpegError("Failed to scale frame", error_code);
|
||||
goto fail;
|
||||
@@ -208,7 +231,7 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, QIODevice* file)
|
||||
audio_codec_ctx_->sample_fmt,
|
||||
audio_codec_ctx_->sample_rate,
|
||||
static_cast<int64_t>(pcm_info.channel_layout()),
|
||||
FFmpegCommon::GetFFmpegSampleFormat(pcm_info.format()),
|
||||
FFmpegUtils::GetFFmpegSampleFormat(pcm_info.format()),
|
||||
pcm_info.sample_rate(),
|
||||
0,
|
||||
nullptr);
|
||||
@@ -300,9 +323,14 @@ void FFmpegEncoder::Close()
|
||||
open_ = false;
|
||||
}
|
||||
|
||||
if (video_scale_ctx_) {
|
||||
sws_freeContext(video_scale_ctx_);
|
||||
video_scale_ctx_ = nullptr;
|
||||
if (video_alpha_scale_ctx_) {
|
||||
sws_freeContext(video_alpha_scale_ctx_);
|
||||
video_alpha_scale_ctx_ = nullptr;
|
||||
}
|
||||
|
||||
if (video_noalpha_scale_ctx_) {
|
||||
sws_freeContext(video_noalpha_scale_ctx_);
|
||||
video_noalpha_scale_ctx_ = nullptr;
|
||||
}
|
||||
|
||||
if (video_codec_ctx_) {
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
virtual void Close() override;
|
||||
|
||||
virtual PixelFormat::Format GetDesiredPixelFormat() const override
|
||||
virtual VideoParams::Format GetDesiredPixelFormat() const override
|
||||
{
|
||||
return video_conversion_fmt_;
|
||||
}
|
||||
@@ -85,8 +85,9 @@ private:
|
||||
|
||||
AVStream* video_stream_;
|
||||
AVCodecContext* video_codec_ctx_;
|
||||
SwsContext* video_scale_ctx_;
|
||||
PixelFormat::Format video_conversion_fmt_;
|
||||
SwsContext* video_alpha_scale_ctx_;
|
||||
SwsContext* video_noalpha_scale_ctx_;
|
||||
VideoParams::Format video_conversion_fmt_;
|
||||
|
||||
AVStream* audio_stream_;
|
||||
AVCodecContext* audio_codec_ctx_;
|
||||
|
||||
@@ -28,22 +28,24 @@ FFmpegFramePool::FFmpegFramePool(int element_count) :
|
||||
MemoryPool(element_count),
|
||||
width_(0),
|
||||
height_(0),
|
||||
format_(PixelFormat::PIX_FMT_INVALID)
|
||||
format_(VideoParams::kFormatInvalid),
|
||||
channel_count_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void FFmpegFramePool::SetParameters(int width, int height, PixelFormat::Format format)
|
||||
void FFmpegFramePool::SetParameters(int width, int height, VideoParams::Format format, int channel_count)
|
||||
{
|
||||
Clear();
|
||||
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
format_ = format;
|
||||
channel_count_ = channel_count;
|
||||
}
|
||||
|
||||
size_t FFmpegFramePool::GetElementSize()
|
||||
{
|
||||
return Frame::generate_linesize_bytes(width_, format_) * height_;
|
||||
return Frame::generate_linesize_bytes(width_, format_, channel_count_) * height_;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#define FFMPEGFRAMEPOOL_H
|
||||
|
||||
#include "common/memorypool.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
@@ -32,7 +31,7 @@ class FFmpegFramePool : public MemoryPool<uint8_t>
|
||||
public:
|
||||
FFmpegFramePool(int element_count);
|
||||
|
||||
void SetParameters(int width, int height, PixelFormat::Format format);
|
||||
void SetParameters(int width, int height, VideoParams::Format format, int channel_count);
|
||||
|
||||
const int& width() const
|
||||
{
|
||||
@@ -52,7 +51,9 @@ private:
|
||||
|
||||
int height_;
|
||||
|
||||
PixelFormat::Format format_;
|
||||
VideoParams::Format format_;
|
||||
|
||||
int channel_count_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+43
-9
@@ -20,10 +20,13 @@
|
||||
|
||||
#include "frame.h"
|
||||
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
#include <QDebug>
|
||||
#include <QtGlobal>
|
||||
#include <QtMath>
|
||||
|
||||
#include "common/oiioutils.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
Frame::Frame() :
|
||||
@@ -45,14 +48,14 @@ void Frame::set_video_params(const VideoParams ¶ms)
|
||||
{
|
||||
params_ = params;
|
||||
|
||||
linesize_ = generate_linesize_bytes(width(), params_.format());
|
||||
linesize_pixels_ = linesize_ / PixelFormat::BytesPerPixel(params_.format());
|
||||
linesize_ = generate_linesize_bytes(width(), params_.format(), params_.channel_count());
|
||||
linesize_pixels_ = linesize_ / params_.GetBytesPerPixel();
|
||||
}
|
||||
|
||||
int Frame::generate_linesize_bytes(int width, PixelFormat::Format format)
|
||||
int Frame::generate_linesize_bytes(int width, VideoParams::Format format, int channel_count)
|
||||
{
|
||||
// Align to 32 bytes (not sure if this is necessary?)
|
||||
return PixelFormat::BytesPerPixel(format) * ((width + 31) & ~31);
|
||||
return VideoParams::GetBytesPerPixel(format, channel_count) * ((width + 31) & ~31);
|
||||
}
|
||||
|
||||
Color Frame::get_pixel(int x, int y) const
|
||||
@@ -61,9 +64,9 @@ Color Frame::get_pixel(int x, int y) const
|
||||
return Color();
|
||||
}
|
||||
|
||||
int byte_offset = y * linesize_bytes() + x * PixelFormat::BytesPerPixel(video_params().format());
|
||||
int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel();
|
||||
|
||||
return Color(data_.data() + byte_offset, video_params().format());
|
||||
return Color(data_.data() + byte_offset, video_params().format(), video_params().channel_count());
|
||||
}
|
||||
|
||||
bool Frame::contains_pixel(int x, int y) const
|
||||
@@ -77,9 +80,9 @@ void Frame::set_pixel(int x, int y, const Color &c)
|
||||
return;
|
||||
}
|
||||
|
||||
int byte_offset = y * linesize_bytes() + x * PixelFormat::BytesPerPixel(video_params().format());
|
||||
int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel();
|
||||
|
||||
c.toData(data_.data() + byte_offset, video_params().format());
|
||||
c.toData(data_.data() + byte_offset, video_params().format(), video_params().channel_count());
|
||||
}
|
||||
|
||||
bool Frame::allocate()
|
||||
@@ -90,9 +93,40 @@ bool Frame::allocate()
|
||||
return false;
|
||||
}
|
||||
|
||||
data_.resize(PixelFormat::GetBufferSize(params_.format(), linesize_, height()));
|
||||
data_.resize(VideoParams::GetBufferSize(linesize_, height(), params_.format(), params_.channel_count()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FramePtr Frame::convert(VideoParams::Format format) const
|
||||
{
|
||||
// Create new params with destination format
|
||||
VideoParams params = params_;
|
||||
params.set_format(format);
|
||||
|
||||
// Create new frame
|
||||
FramePtr converted = Frame::Create();
|
||||
converted->set_video_params(params);
|
||||
converted->set_timestamp(timestamp_);
|
||||
converted->allocate();
|
||||
|
||||
// Do the conversion through OIIO for convenience
|
||||
OIIO::ImageBuf src(OIIO::ImageSpec(width(), height(),
|
||||
channel_count(),
|
||||
OIIOUtils::GetOIIOBaseTypeFromFormat(this->format())));
|
||||
|
||||
OIIOUtils::FrameToBuffer(this, &src);
|
||||
|
||||
OIIO::ImageBuf dst(OIIO::ImageSpec(converted->width(), converted->height(),
|
||||
channel_count(),
|
||||
OIIOUtils::GetOIIOBaseTypeFromFormat(format)));
|
||||
|
||||
if (dst.copy_pixels(src)) {
|
||||
OIIOUtils::BufferToFrame(&dst, converted.get());
|
||||
return converted;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
+9
-3
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "render/color.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
@@ -47,7 +46,7 @@ public:
|
||||
const VideoParams& video_params() const;
|
||||
void set_video_params(const VideoParams& params);
|
||||
|
||||
static int generate_linesize_bytes(int width, PixelFormat::Format format);
|
||||
static int generate_linesize_bytes(int width, VideoParams::Format format, int channel_count);
|
||||
|
||||
int linesize_pixels() const
|
||||
{
|
||||
@@ -69,11 +68,16 @@ public:
|
||||
return params_.effective_height();
|
||||
}
|
||||
|
||||
PixelFormat::Format format() const
|
||||
VideoParams::Format format() const
|
||||
{
|
||||
return params_.format();
|
||||
}
|
||||
|
||||
int channel_count() const
|
||||
{
|
||||
return params_.channel_count();
|
||||
}
|
||||
|
||||
Color get_pixel(int x, int y) const;
|
||||
bool contains_pixel(int x, int y) const;
|
||||
void set_pixel(int x, int y, const Color& c);
|
||||
@@ -144,6 +148,8 @@ public:
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
FramePtr convert(VideoParams::Format format) const;
|
||||
|
||||
private:
|
||||
VideoParams params_;
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
codec/oiio/oiiocommon.cpp
|
||||
codec/oiio/oiiocommon.h
|
||||
codec/oiio/oiiodecoder.cpp
|
||||
codec/oiio/oiiodecoder.h
|
||||
PARENT_SCOPE
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "oiiocommon.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
void OIIOCommon::FrameToBuffer(FramePtr frame, OIIO::ImageBuf *buf)
|
||||
{
|
||||
#if OIIO_VERSION < 20112
|
||||
//
|
||||
// Workaround for OIIO bug that ignores destination stride in versions OLDER than 2.1.12
|
||||
//
|
||||
// See more: https://github.com/OpenImageIO/oiio/pull/2487
|
||||
//
|
||||
int width_in_bytes = frame->width() * PixelFormat::BytesPerPixel(frame->format());
|
||||
|
||||
for (int i=0;i<buf->spec().height;i++) {
|
||||
memcpy(
|
||||
#if OIIO_VERSION < 10903
|
||||
reinterpret_cast<char*>(buf->localpixels()) + i * width_in_bytes,
|
||||
#else
|
||||
reinterpret_cast<char*>(buf->localpixels()) + i * buf->scanline_stride(),
|
||||
#endif
|
||||
frame->data() + i * frame->linesize_bytes(),
|
||||
width_in_bytes);
|
||||
}
|
||||
#else
|
||||
buf->set_pixels(OIIO::ROI(),
|
||||
buf->spec().format,
|
||||
frame->data(),
|
||||
OIIO::AutoStride,
|
||||
frame->linesize_bytes());
|
||||
#endif
|
||||
}
|
||||
|
||||
void OIIOCommon::BufferToFrame(OIIO::ImageBuf *buf, FramePtr frame)
|
||||
{
|
||||
#if OIIO_VERSION < 20112
|
||||
//
|
||||
// Workaround for OIIO bug that ignores destination stride in versions OLDER than 2.1.12
|
||||
//
|
||||
// See more: https://github.com/OpenImageIO/oiio/pull/2487
|
||||
//
|
||||
int width_in_bytes = frame->width() * PixelFormat::BytesPerPixel(frame->format());
|
||||
|
||||
for (int i=0;i<buf->spec().height;i++) {
|
||||
memcpy(frame->data() + i * frame->linesize_bytes(),
|
||||
#if OIIO_VERSION < 10903
|
||||
reinterpret_cast<const char*>(buf->localpixels()) + i * width_in_bytes,
|
||||
#else
|
||||
reinterpret_cast<const char*>(buf->localpixels()) + i * buf->scanline_stride(),
|
||||
#endif
|
||||
width_in_bytes);
|
||||
}
|
||||
#else
|
||||
buf->get_pixels(OIIO::ROI(),
|
||||
buf->spec().format,
|
||||
frame->data(),
|
||||
OIIO::AutoStride,
|
||||
frame->linesize_bytes());
|
||||
#endif
|
||||
}
|
||||
|
||||
PixelFormat::Format OIIOCommon::GetFormatFromOIIOBasetype(const OIIO::ImageSpec& spec)
|
||||
{
|
||||
if (spec.format == OIIO::TypeDesc::UINT8) {
|
||||
return PixelFormat::PIX_FMT_RGBA8;
|
||||
} else if (spec.format == OIIO::TypeDesc::UINT16) {
|
||||
return PixelFormat::PIX_FMT_RGBA16U;
|
||||
} else if (spec.format == OIIO::TypeDesc::HALF) {
|
||||
return PixelFormat::PIX_FMT_RGBA16F;
|
||||
} else if (spec.format == OIIO::TypeDesc::FLOAT) {
|
||||
return PixelFormat::PIX_FMT_RGBA32F;
|
||||
} else {
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
rational OIIOCommon::GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec &spec)
|
||||
{
|
||||
return rational::fromDouble(spec.get_float_attribute("PixelAspectRatio", 1));
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -1,47 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OIIOCOMMON_H
|
||||
#define OIIOCOMMON_H
|
||||
|
||||
#include <OpenImageIO/imageio.h>
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class OIIOCommon
|
||||
{
|
||||
public:
|
||||
static void FrameToBuffer(FramePtr frame, OIIO::ImageBuf* buf);
|
||||
|
||||
static void BufferToFrame(OIIO::ImageBuf* buf, FramePtr frame);
|
||||
|
||||
static PixelFormat::Format GetFormatFromOIIOBasetype(const OIIO::ImageSpec& spec);
|
||||
|
||||
static rational GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec& spec);
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // OIIOCOMMON_H
|
||||
@@ -27,9 +27,9 @@
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "common/oiioutils.h"
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "oiiocommon.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -81,8 +81,9 @@ FootagePtr OIIODecoder::Probe(const QString& filename, const QAtomicInt* cancell
|
||||
|
||||
image_stream->set_width(in->spec().width);
|
||||
image_stream->set_height(in->spec().height);
|
||||
image_stream->set_format(OIIOCommon::GetFormatFromOIIOBasetype(in->spec()));
|
||||
image_stream->set_pixel_aspect_ratio(OIIOCommon::GetPixelAspectRatioFromOIIO(in->spec()));
|
||||
image_stream->set_format(OIIOUtils::GetFormatFromOIIOBasetype(static_cast<OIIO::TypeDesc::BASETYPE>(in->spec().format.basetype)));
|
||||
image_stream->set_channel_count(in->spec().nchannels);
|
||||
image_stream->set_pixel_aspect_ratio(OIIOUtils::GetPixelAspectRatioFromOIIO(in->spec()));
|
||||
image_stream->set_video_type(VideoStream::kVideoTypeStill);
|
||||
|
||||
// Images will always have just one stream
|
||||
@@ -149,14 +150,15 @@ FramePtr OIIODecoder::RetrieveVideoInternal(const rational &timecode, const int&
|
||||
frame->set_video_params(VideoParams(buffer_->spec().width,
|
||||
buffer_->spec().height,
|
||||
pix_fmt_,
|
||||
OIIOCommon::GetPixelAspectRatioFromOIIO(buffer_->spec()),
|
||||
channel_count_,
|
||||
OIIOUtils::GetPixelAspectRatioFromOIIO(buffer_->spec()),
|
||||
VideoParams::kInterlaceNone, // FIXME: Does OIIO deinterlace for us?
|
||||
divider));
|
||||
frame->allocate();
|
||||
|
||||
if (divider == 1) {
|
||||
|
||||
OIIOCommon::BufferToFrame(buffer_, frame);
|
||||
OIIOUtils::BufferToFrame(buffer_, frame.get());
|
||||
|
||||
} else {
|
||||
|
||||
@@ -167,7 +169,7 @@ FramePtr OIIODecoder::RetrieveVideoInternal(const rational &timecode, const int&
|
||||
qWarning() << "OIIO resize failed";
|
||||
}
|
||||
|
||||
OIIOCommon::BufferToFrame(&dst, frame);
|
||||
OIIOUtils::BufferToFrame(&dst, frame.get());
|
||||
|
||||
}
|
||||
|
||||
@@ -215,18 +217,23 @@ bool OIIODecoder::OpenImageHandler(const QString &fn)
|
||||
// Check if we can work with this pixel format
|
||||
const OIIO::ImageSpec& spec = image_->spec();
|
||||
|
||||
//is_rgba_ = (spec.nchannels == kRGBAChannels);
|
||||
// Store channel count
|
||||
channel_count_ = spec.nchannels;
|
||||
|
||||
// We use RGBA frames because that tends to be the native format of GPUs
|
||||
pix_fmt_ = OIIOCommon::GetFormatFromOIIOBasetype(spec);
|
||||
pix_fmt_ = OIIOUtils::GetFormatFromOIIOBasetype(static_cast<OIIO::TypeDesc::BASETYPE>(spec.format.basetype));
|
||||
|
||||
if (pix_fmt_ == PixelFormat::PIX_FMT_INVALID) {
|
||||
if (pix_fmt_ == VideoParams::kFormatInvalid) {
|
||||
qWarning() << "Failed to convert OIIO::ImageDesc to native pixel format";
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Many OIIO pixel formats are not handled here
|
||||
OIIO::TypeDesc type = PixelFormat::GetOIIOTypeDesc(pix_fmt_);
|
||||
OIIO::TypeDesc::BASETYPE type = OIIOUtils::GetOIIOBaseTypeFromFormat(pix_fmt_);
|
||||
|
||||
if (type == OIIO::TypeDesc::UNKNOWN) {
|
||||
qCritical() << "Failed to determine appropriate OIIO basetype from native format";
|
||||
return false;
|
||||
}
|
||||
|
||||
#if OIIO_VERSION < 20100
|
||||
buffer_ = new OIIO::ImageBuf(OIIO::ImageSpec(spec.width, spec.height, spec.nchannels, type));
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
|
||||
#include "codec/decoder.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -63,9 +62,9 @@ private:
|
||||
|
||||
int64_t last_sequence_index_;
|
||||
|
||||
PixelFormat::Format pix_fmt_;
|
||||
VideoParams::Format pix_fmt_;
|
||||
|
||||
//bool is_rgba_;
|
||||
int channel_count_;
|
||||
|
||||
OIIO::ImageBuf* buffer_;
|
||||
|
||||
|
||||
@@ -108,27 +108,27 @@ bool WaveInput::open()
|
||||
uint16_t bits_per_sample;
|
||||
data_stream >> bits_per_sample;
|
||||
|
||||
SampleFormat::Format format;
|
||||
AudioParams::Format format;
|
||||
|
||||
switch (bits_per_sample) {
|
||||
case 8:
|
||||
format = SampleFormat::SAMPLE_FMT_U8;
|
||||
format = AudioParams::kFormatUnsigned8;
|
||||
break;
|
||||
case 16:
|
||||
format = SampleFormat::SAMPLE_FMT_S16;
|
||||
format = AudioParams::kFormatSigned16;
|
||||
break;
|
||||
case 32:
|
||||
if (data_is_float) {
|
||||
format = SampleFormat::SAMPLE_FMT_FLT;
|
||||
format = AudioParams::kFormatFloat32;
|
||||
} else {
|
||||
format = SampleFormat::SAMPLE_FMT_S32;
|
||||
format = AudioParams::kFormatSigned32;
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
if (data_is_float) {
|
||||
format = SampleFormat::SAMPLE_FMT_DBL;
|
||||
format = AudioParams::kFormatFloat64;
|
||||
} else {
|
||||
format = SampleFormat::SAMPLE_FMT_S64;
|
||||
format = AudioParams::kFormatSigned64;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "waveoutput.h"
|
||||
|
||||
#include "render/audioparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
const int16_t kWAVIntegerFormat = 1;
|
||||
@@ -60,18 +62,18 @@ bool WaveOutput::open()
|
||||
|
||||
// Type of format
|
||||
switch (params_.format()) {
|
||||
case SampleFormat::SAMPLE_FMT_U8:
|
||||
case SampleFormat::SAMPLE_FMT_S16:
|
||||
case SampleFormat::SAMPLE_FMT_S32:
|
||||
case SampleFormat::SAMPLE_FMT_S64:
|
||||
case AudioParams::kFormatUnsigned8:
|
||||
case AudioParams::kFormatSigned16:
|
||||
case AudioParams::kFormatSigned32:
|
||||
case AudioParams::kFormatSigned64:
|
||||
write_int<int16_t>(&file_, kWAVIntegerFormat);
|
||||
break;
|
||||
case SampleFormat::SAMPLE_FMT_FLT:
|
||||
case SampleFormat::SAMPLE_FMT_DBL:
|
||||
case AudioParams::kFormatFloat32:
|
||||
case AudioParams::kFormatFloat64:
|
||||
write_int<int16_t>(&file_, kWAVFloatFormat);
|
||||
break;
|
||||
case SampleFormat::SAMPLE_FMT_INVALID:
|
||||
case SampleFormat::SAMPLE_FMT_COUNT:
|
||||
case AudioParams::kFormatInvalid:
|
||||
case AudioParams::kFormatCount:
|
||||
qWarning() << "Invalid sample format for WAVE audio";
|
||||
file_.close();
|
||||
return false;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
|
||||
#include "audio/sampleformat.h"
|
||||
#include "render/audioparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
Reference in New Issue
Block a user