fixed various audio exporting bugs
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
#include "panels/panels.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "io/exportthread.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
@@ -341,6 +342,7 @@ void ExportDialog::render_thread_finished() {
|
||||
QMessageBox::Ok
|
||||
);
|
||||
}
|
||||
clear_audio_ibuffer();
|
||||
prep_ui_for_render(false);
|
||||
panel_sequence_viewer->viewer_widget->makeCurrent();
|
||||
panel_sequence_viewer->viewer_widget->initializeGL();
|
||||
|
||||
+24
-6
@@ -242,6 +242,9 @@ bool ExportThread::setupAudio() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set sample rate to use for project
|
||||
audio_rendering_rate = params.audio_sampling_rate;
|
||||
|
||||
// setup context
|
||||
acodec_ctx->codec_id = static_cast<AVCodecID>(params.audio_codec);
|
||||
acodec_ctx->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
@@ -283,7 +286,7 @@ bool ExportThread::setupAudio() {
|
||||
acodec_ctx->sample_rate,
|
||||
olive::ActiveSequence->audio_layout,
|
||||
AV_SAMPLE_FMT_S16,
|
||||
olive::ActiveSequence->audio_frequency,
|
||||
acodec_ctx->sample_rate,
|
||||
0,
|
||||
nullptr
|
||||
);
|
||||
@@ -291,9 +294,14 @@ bool ExportThread::setupAudio() {
|
||||
|
||||
// initialize raw audio frame
|
||||
audio_frame = av_frame_alloc();
|
||||
audio_frame->sample_rate = olive::ActiveSequence->audio_frequency;
|
||||
audio_frame->sample_rate = acodec_ctx->sample_rate;
|
||||
audio_frame->nb_samples = acodec_ctx->frame_size;
|
||||
if (audio_frame->nb_samples == 0) audio_frame->nb_samples = 256; // should possibly be smaller?
|
||||
|
||||
if (audio_frame->nb_samples == 0) {
|
||||
// FIXME: Magic number. I don't know what to put here and truthfully I don't even know if it matters.
|
||||
audio_frame->nb_samples = 256;
|
||||
}
|
||||
|
||||
audio_frame->format = AV_SAMPLE_FMT_S16;
|
||||
audio_frame->channel_layout = AV_CH_LAYOUT_STEREO; // change this to support surround/mono sound in the future (this is whatever format they're held in the internal buffer)
|
||||
audio_frame->channels = av_get_channel_layout_nb_channels(audio_frame->channel_layout);
|
||||
@@ -306,15 +314,18 @@ bool ExportThread::setupAudio() {
|
||||
}
|
||||
aframe_bytes = av_samples_get_buffer_size(nullptr, audio_frame->channels, audio_frame->nb_samples, static_cast<AVSampleFormat>(audio_frame->format), 0);
|
||||
|
||||
av_init_packet(&audio_pkt);
|
||||
|
||||
// init converted audio frame
|
||||
swr_frame = av_frame_alloc();
|
||||
swr_frame->channel_layout = acodec_ctx->channel_layout;
|
||||
swr_frame->channels = acodec_ctx->channels;
|
||||
swr_frame->sample_rate = acodec_ctx->sample_rate;
|
||||
swr_frame->format = acodec_ctx->sample_fmt;
|
||||
av_frame_make_writable(swr_frame);
|
||||
swr_frame->nb_samples = acodec_ctx->frame_size;
|
||||
av_frame_get_buffer(swr_frame, 0);
|
||||
|
||||
av_init_packet(&audio_pkt);
|
||||
av_frame_make_writable(swr_frame);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -439,8 +450,11 @@ void ExportThread::run() {
|
||||
|
||||
// convert to export sample format
|
||||
swr_convert_frame(swr_ctx, swr_frame, audio_frame);
|
||||
|
||||
swr_frame->pts = file_audio_samples;
|
||||
|
||||
qDebug() << swr_frame->nb_samples << acodec_ctx->frame_size;
|
||||
|
||||
// send to encoder
|
||||
if (!encode(fmt_ctx, acodec_ctx, swr_frame, &audio_pkt, audio_stream, true)) continueEncode = false;
|
||||
|
||||
@@ -473,14 +487,18 @@ void ExportThread::run() {
|
||||
olive::Global->set_rendering_state(false);
|
||||
|
||||
if (params.audio_enabled && continueEncode) {
|
||||
|
||||
// flush swresample
|
||||
do {
|
||||
|
||||
swr_convert_frame(swr_ctx, swr_frame, nullptr);
|
||||
if (swr_frame->nb_samples == 0) break;
|
||||
swr_frame->pts = file_audio_samples;
|
||||
if (!encode(fmt_ctx, acodec_ctx, swr_frame, &audio_pkt, audio_stream, true)) continueEncode = false;
|
||||
file_audio_samples += swr_frame->nb_samples;
|
||||
|
||||
} while (swr_frame->nb_samples > 0);
|
||||
|
||||
}
|
||||
|
||||
bool continueVideo = true;
|
||||
@@ -526,8 +544,8 @@ void ExportThread::run() {
|
||||
sws_freeContext(sws_ctx);
|
||||
}
|
||||
if (swr_ctx != nullptr) {
|
||||
swr_free(&swr_ctx);
|
||||
av_frame_free(&swr_frame);
|
||||
swr_free(&swr_ctx);
|
||||
}
|
||||
|
||||
delete [] c_filename;
|
||||
|
||||
+4
-2
@@ -50,9 +50,11 @@ bool audio_scrub = false;
|
||||
QMutex audio_write_lock;
|
||||
QAudioInput* audio_input = nullptr;
|
||||
QFile output_recording;
|
||||
bool audio_rendering = false;
|
||||
bool recording = false;
|
||||
|
||||
bool audio_rendering = false;
|
||||
int audio_rendering_rate = 0;
|
||||
|
||||
qint8 audio_ibuffer[audio_ibuffer_size];
|
||||
qint64 audio_ibuffer_read = 0;
|
||||
long audio_ibuffer_frame = 0;
|
||||
@@ -152,7 +154,7 @@ void clear_audio_ibuffer() {
|
||||
}
|
||||
|
||||
int current_audio_freq() {
|
||||
return audio_rendering ? olive::ActiveSequence->audio_frequency : audio_output->format().sampleRate();
|
||||
return audio_rendering ? audio_rendering_rate : audio_output->format().sampleRate();
|
||||
}
|
||||
|
||||
qint64 get_buffer_offset_from_frame(double framerate, long frame) {
|
||||
|
||||
+11
-10
@@ -32,19 +32,19 @@
|
||||
#include "project/sequence.h"
|
||||
|
||||
class AudioSenderThread : public QThread {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioSenderThread();
|
||||
void run();
|
||||
void stop();
|
||||
QWaitCondition cond;
|
||||
bool close;
|
||||
QMutex lock;
|
||||
AudioSenderThread();
|
||||
void run();
|
||||
void stop();
|
||||
QWaitCondition cond;
|
||||
bool close;
|
||||
QMutex lock;
|
||||
public slots:
|
||||
void notifyReceiver();
|
||||
void notifyReceiver();
|
||||
private:
|
||||
QVector<qint16> samples;
|
||||
int send_audio_to_output(qint64 offset, int max);
|
||||
QVector<qint16> samples;
|
||||
int send_audio_to_output(qint64 offset, int max);
|
||||
};
|
||||
|
||||
double log_volume(double linear);
|
||||
@@ -62,6 +62,7 @@ extern double audio_ibuffer_timecode;
|
||||
extern bool audio_scrub;
|
||||
extern bool recording;
|
||||
extern bool audio_rendering;
|
||||
extern int audio_rendering_rate;
|
||||
void clear_audio_ibuffer();
|
||||
|
||||
int current_audio_freq();
|
||||
|
||||
@@ -180,6 +180,7 @@ void Cacher::CacheAudioWorker() {
|
||||
// retrieve frame
|
||||
bool new_frame = false;
|
||||
while ((frame_sample_index_ == -1 || frame_sample_index_ >= nb_bytes) && nb_bytes > 0) {
|
||||
|
||||
// no more audio left in frame, get a new one
|
||||
if (!reached_end) {
|
||||
int loop = 0;
|
||||
@@ -187,7 +188,8 @@ void Cacher::CacheAudioWorker() {
|
||||
if (reverse_audio && !audio_just_reset) {
|
||||
avcodec_flush_buffers(codecCtx);
|
||||
reached_end = false;
|
||||
int64_t backtrack_seek = qMax(reverse_target_ - static_cast<int64_t>(av_q2d(av_inv_q(stream->time_base))), static_cast<int64_t>(0));
|
||||
int64_t backtrack_seek = qMax(reverse_target_ - static_cast<int64_t>(av_q2d(av_inv_q(stream->time_base))),
|
||||
static_cast<int64_t>(0));
|
||||
av_seek_frame(formatCtx, stream->index, backtrack_seek, AVSEEK_FLAG_BACKWARD);
|
||||
#ifdef AUDIOWARNINGS
|
||||
if (backtrack_seek == 0) {
|
||||
@@ -339,7 +341,10 @@ void Cacher::CacheAudioWorker() {
|
||||
if (audio_just_reset) {
|
||||
// get precise sample offset for the elected clip_in from this audio frame
|
||||
double target_sts = playhead_to_clip_seconds(clip, audio_target_frame);
|
||||
double frame_sts = ((frame->pts - stream->start_time) * timebase);
|
||||
|
||||
int64_t stream_start = qMax(static_cast<int64_t>(0), stream->start_time);
|
||||
double frame_sts = ((frame->pts - stream_start) * timebase);
|
||||
|
||||
int nb_samples = qRound64((target_sts - frame_sts)*current_audio_freq());
|
||||
frame_sample_index_ = nb_samples * 4;
|
||||
#ifdef AUDIOWARNINGS
|
||||
@@ -387,10 +392,6 @@ void Cacher::CacheAudioWorker() {
|
||||
if (new_frame) {
|
||||
apply_audio_effects(clip, bytes_to_seconds(audio_buffer_write, 2, current_audio_freq()) + audio_ibuffer_timecode + ((double)clip->clip_in(true)/clip->sequence->frame_rate) - ((double)timeline_in/last_fr), frame, nb_bytes, nests_);
|
||||
}
|
||||
} else {
|
||||
// shouldn't ever get here
|
||||
qCritical() << "Tried to cache a non-footage/tone clip";
|
||||
return;
|
||||
}
|
||||
|
||||
// mix audio into internal buffer
|
||||
@@ -957,7 +958,7 @@ void Cacher::OpenWorker() {
|
||||
|
||||
// set up cache
|
||||
queue_.append(av_frame_alloc());
|
||||
// if (clip->reverse) {
|
||||
|
||||
if (true) {
|
||||
AVFrame* reverse_frame = av_frame_alloc();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user