diff --git a/io/exportthread.h b/io/exportthread.h index 32692e831..e4d438587 100644 --- a/io/exportthread.h +++ b/io/exportthread.h @@ -9,7 +9,7 @@ class ExportDialog; class ExportThread : public QThread { Q_OBJECT public: - void run() override; + void run(); // export parameters QString filename; diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 1c1a27796..0e2544cf2 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -56,118 +56,129 @@ void PreviewGenerator::run() { avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar); avcodec_open2(codec_ctx[i], codec, NULL); - if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - if (codec_ctx[i]->channel_layout == 0) { - codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels); - } + if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) { + codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels); } } AVPacket packet; bool done = true; - while (av_read_frame(fmt_ctx, &packet) >= 0) { - MediaStream* s = get_stream_from_file_index(packet.stream_index); - if (s != NULL && !s->preview_done) { - if (avcodec_send_packet(codec_ctx[packet.stream_index], &packet) >= 0) { - if (avcodec_receive_frame(codec_ctx[packet.stream_index], temp_frame) >= 0) { - if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - int dstH = 120; - int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); - uint8_t* data = new uint8_t[dstW*dstH*3]; - sws_ctx = sws_getContext( - temp_frame->width, - temp_frame->height, - static_cast(temp_frame->format), - dstW, - dstH, - static_cast(AV_PIX_FMT_RGB24), - SWS_FAST_BILINEAR, - NULL, - NULL, - NULL - ); + bool end_of_file = false; - int linesize[AV_NUM_DATA_POINTERS]; - linesize[0] = dstW*3; - sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); + // get the ball rolling + av_read_frame(fmt_ctx, &packet); + avcodec_send_packet(codec_ctx[packet.stream_index], &packet); - s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888); + while (!end_of_file) { + while (avcodec_receive_frame(codec_ctx[packet.stream_index], temp_frame) == AVERROR(EAGAIN)) { + av_packet_unref(&packet); + int read_ret = av_read_frame(fmt_ctx, &packet); + if (read_ret < 0) { + end_of_file = true; + if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Failed to read packet for preview generation"; + break; + } else { + avcodec_send_packet(codec_ctx[packet.stream_index], &packet); + } + } + if (!end_of_file) { + MediaStream* s = get_stream_from_file_index(packet.stream_index); + if (s != NULL && !s->preview_done) { + if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + int dstH = 120; + int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); + qDebug() << dstW; + uint8_t* data = new uint8_t[dstW*dstH*3]; + + sws_ctx = sws_getContext( + temp_frame->width, + temp_frame->height, + static_cast(temp_frame->format), + dstW, + dstH, + static_cast(AV_PIX_FMT_RGB24), + SWS_FAST_BILINEAR, + NULL, + NULL, + NULL + ); + + int linesize[AV_NUM_DATA_POINTERS]; + linesize[0] = dstW*3; + sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); + + s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888); // delete [] data; - s->preview_done = true; - s->preview_lock.unlock(); + s->preview_done = true; + s->preview_lock.unlock(); - sws_freeContext(sws_ctx); - } else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4; + sws_freeContext(sws_ctx); + } else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4; - AVFrame* swr_frame = av_frame_alloc(); - swr_frame->channel_layout = temp_frame->channel_layout; - swr_frame->sample_rate = temp_frame->sample_rate; - swr_frame->format = AV_SAMPLE_FMT_S16; + AVFrame* swr_frame = av_frame_alloc(); + swr_frame->channel_layout = temp_frame->channel_layout; + swr_frame->sample_rate = temp_frame->sample_rate; + swr_frame->format = AV_SAMPLE_FMT_S16; - swr_ctx = swr_alloc_set_opts( - NULL, - temp_frame->channel_layout, - static_cast(swr_frame->format), - temp_frame->sample_rate, - temp_frame->channel_layout, - static_cast(temp_frame->format), - temp_frame->sample_rate, - 0, - NULL - ); + swr_ctx = swr_alloc_set_opts( + NULL, + temp_frame->channel_layout, + static_cast(swr_frame->format), + temp_frame->sample_rate, + temp_frame->channel_layout, + static_cast(temp_frame->format), + temp_frame->sample_rate, + 0, + NULL + ); - swr_init(swr_ctx); + swr_init(swr_ctx); - swr_convert_frame(swr_ctx, swr_frame, temp_frame); + swr_convert_frame(swr_ctx, swr_frame, temp_frame); - int channel_skip = swr_frame->channels * 2; - for (int i=0;inb_samples;i+=interval) { - for (int j=0;jchannels;j++) { - qint16 min = 0; - qint16 max = 0; - for (int k=j*2;kdata[0][i+k+1] << 8) | swr_frame->data[0][i+k]); - if (sample > max) { - max = sample; - } else if (sample < min) { - min = sample; - } + int channel_skip = swr_frame->channels * 2; + for (int i=0;inb_samples;i+=interval) { + for (int j=0;jchannels;j++) { + qint16 min = 0; + qint16 max = 0; + for (int k=j*2;kdata[0][i+k+1] << 8) | swr_frame->data[0][i+k]); + if (sample > max) { + max = sample; + } else if (sample < min) { + min = sample; } - min /= 256; - max /= 256; - s->audio_preview.append(min); - s->audio_preview.append(max); } + min /= 256; + max /= 256; + s->audio_preview.append(min); + s->audio_preview.append(max); } - - swr_free(&swr_ctx); - av_frame_free(&swr_frame); } - } else { - qDebug() << "[ERROR] Failed to retrieve frame"; + + swr_free(&swr_ctx); + av_frame_free(&swr_frame); } - } else { - qDebug() << "[ERROR] Failed to send packet"; - } - } - av_packet_unref(&packet); - - // check if we've got all our previews - if (media->audio_tracks.size() == 0) { - done = true; - for (int i=0;ivideo_tracks.size();i++) { - if (!media->video_tracks.at(i)->preview_done) { - done = false; - break; + // check if we've got all our previews + if (media->audio_tracks.size() == 0) { + done = true; + for (int i=0;ivideo_tracks.size();i++) { + if (!media->video_tracks.at(i)->preview_done) { + done = false; + break; + } + } + if (done) { + end_of_file = true; + break; + } } } - if (done) { - break; - } + av_packet_unref(&packet); } } for (int i=0;iaudio_tracks.size();i++) { diff --git a/olive.pro.user b/olive.pro.user index 2bdb25d2c..38906f29f 100644 --- a/olive.pro.user +++ b/olive.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index cb33cc987..90ad37f73 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -24,7 +24,7 @@ private slots: void menu_select(QAction* q); private: - Ui::EffectControls *ui; + Ui::EffectControls *ui; Clip* clip; }; diff --git a/panels/timeline.cpp b/panels/timeline.cpp index b2cbb74a7..68fd1039e 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -85,29 +85,33 @@ void Timeline::next_cut() { long n_cut = LONG_MAX; for (int i=0;iclip_count();i++) { Clip* c = sequence->get_clip(i); - if (c->timeline_out < n_cut && c->timeline_out > playhead) { - n_cut = c->timeline_out; - seek_enabled = true; - } else if (c->timeline_in < n_cut && c->timeline_in > playhead) { + if (c->timeline_in < n_cut && c->timeline_in > playhead) { n_cut = c->timeline_in; seek_enabled = true; + } else if (c->timeline_out < n_cut && c->timeline_out > playhead) { + n_cut = c->timeline_out; + seek_enabled = true; } } if (seek_enabled) seek(n_cut); } -void Timeline::seek(long p) { - pause(); - - // reset all clip audio - for (int i=0;iclip_count();i++) { +void Timeline::reset_all_audio() { + // reset all clip audio + for (int i=0;iclip_count();i++) { Clip* c = sequence->get_clip(i); c->reset_audio = true; c->frame_sample_index = 0; c->audio_buffer_write = 0; - } + } clear_audio_ibuffer(); - audio_ibuffer_read = 0; +} + +void Timeline::seek(long p) { + pause(); + + reset_all_audio(); + audio_ibuffer_frame = p; playhead = p; @@ -166,23 +170,25 @@ bool Timeline::focused() { } void Timeline::undo() { - if (sequence != NULL) { - current_clips.clear(); - panel_effect_controls->set_clip(NULL); - sequence->undo(); - ui->video_area->redraw_clips(); - ui->audio_area->redraw_clips(); - } + qDebug() << "[INFO] Undo/redo was so buggy, it's not been disabled. Sorry for any inconvenience"; +// if (sequence != NULL) { +// current_clips.clear(); +// panel_effect_controls->set_clip(NULL); +// sequence->undo(); +// ui->video_area->redraw_clips(); +// ui->audio_area->redraw_clips(); +// } } void Timeline::redo() { - if (sequence != NULL) { - current_clips.clear(); - panel_effect_controls->set_clip(NULL); - sequence->redo(); - ui->video_area->redraw_clips(); - ui->audio_area->redraw_clips(); - } + qDebug() << "[INFO] Undo/redo was so buggy, it's not been disabled. Sorry for any inconvenience"; +// if (sequence != NULL) { +// current_clips.clear(); +// panel_effect_controls->set_clip(NULL); +// sequence->redo(); +// ui->video_area->redraw_clips(); +// ui->audio_area->redraw_clips(); +// } } QString frame_to_timecode(long f) { @@ -213,8 +219,6 @@ void Timeline::repaint_timeline() { } void Timeline::redraw_all_clips() { - // add current sequence to the undo stack - sequence->undo_add_current(); project_changed = true; ui->video_area->redraw_clips(); @@ -222,6 +226,8 @@ void Timeline::redraw_all_clips() { ui->headers->update(); panel_viewer->ui->endTimecode->setText(frame_to_timecode(sequence->getEndFrame())); + + reset_all_audio(); } void Timeline::select_all() { diff --git a/panels/timeline.h b/panels/timeline.h index 703d691d0..172934bd4 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -162,6 +162,7 @@ private: void set_tool(int tool); long last_frame; QVector clip_clipboard; + void reset_all_audio(); }; #endif // TIMELINE_H diff --git a/panels/timeline.ui b/panels/timeline.ui index b00f79f8c..c50ec79a3 100644 --- a/panels/timeline.ui +++ b/panels/timeline.ui @@ -70,7 +70,7 @@ - 30 + 40 16777215 @@ -87,8 +87,8 @@ - 16 - 16 + 20 + 20 @@ -100,7 +100,7 @@ - 30 + 40 16777215 @@ -117,8 +117,8 @@ - 16 - 16 + 20 + 20 @@ -130,7 +130,7 @@ - 30 + 40 16777215 @@ -147,8 +147,8 @@ - 16 - 16 + 20 + 20 @@ -160,7 +160,7 @@ - 30 + 40 16777215 @@ -175,6 +175,12 @@ :/icons/rolling.png :/icons/rolling-disabled.png:/icons/rolling.png + + + 20 + 20 + + true @@ -184,7 +190,7 @@ - 30 + 40 16777215 @@ -201,8 +207,8 @@ - 16 - 16 + 20 + 20 @@ -214,7 +220,7 @@ - 30 + 40 16777215 @@ -230,6 +236,12 @@ :/icons/slip-disabled.png + + + 20 + 20 + + true @@ -239,7 +251,7 @@ - 30 + 40 16777215 @@ -258,7 +270,7 @@ - 30 + 40 16777215 @@ -274,7 +286,7 @@ - 30 + 40 16777215 @@ -318,8 +330,8 @@ 0 0 - 468 - 309 + 458 + 314 diff --git a/playback/audio.cpp b/playback/audio.cpp index 6ad3ef384..56057782f 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -15,7 +15,7 @@ bool audio_device_set = false; qint8 audio_ibuffer[audio_ibuffer_size]; int audio_ibuffer_read = 0; -QVector audio_ibuffer_write; +long audio_ibuffer_frame = 0; void init_audio() { if (audio_device_set) { @@ -51,4 +51,14 @@ void init_audio() { void clear_audio_ibuffer() { memset(audio_ibuffer, 0, audio_ibuffer_size); + audio_ibuffer_read = 0; +} + +int get_buffer_offset_from_frame(long frame) { + if (frame >= audio_ibuffer_frame) { + return av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(sequence->audio_layout), ((frame-audio_ibuffer_frame)/sequence->frame_rate)*sequence->audio_frequency, AV_SAMPLE_FMT_S16, 1); + } else { + qDebug() << "[WARNING] get_buffer_offset_from_frame called incorrectly"; + return 0; + } } diff --git a/playback/audio.h b/playback/audio.h index 4370dedfd..4e529e997 100644 --- a/playback/audio.h +++ b/playback/audio.h @@ -14,9 +14,10 @@ extern QIODevice* audio_io_device; #define audio_ibuffer_size 192000 extern qint8 audio_ibuffer[audio_ibuffer_size]; extern int audio_ibuffer_read; -//extern QVector audio_ibuffer_write; +extern long audio_ibuffer_frame; void clear_audio_ibuffer(); void init_audio(); +int get_buffer_offset_from_frame(long frame); #endif // AUDIO_H diff --git a/playback/cacher.cpp b/playback/cacher.cpp index 73915f91b..c79564d69 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -23,7 +23,7 @@ void cache_audio_worker(Clip* c) { // gets one frame worth of audio and sends it to the audio buffer AVFrame* frame = c->cache_A.frames[0]; - if (c->frame_sample_index == 0) { + if (c->need_new_audio_frame) { // no more audio left in frame, get a new one if (!c->reached_end) { retrieve_next_frame_raw_data(c, frame); @@ -33,6 +33,29 @@ void cache_audio_worker(Clip* c) { swr_convert_frame(c->swr_ctx, frame, NULL); } + c->need_new_audio_frame = false; + if (c->audio_just_reset) { + // get precise sample offset for the elected clip_in from this audio frame + + float target_sts = 0; + if (c->audio_target_frame < c->timeline_in) { + target_sts = playhead_to_seconds(c, c->clip_in); + } else { + target_sts = playhead_to_seconds(c, c->audio_target_frame); + } + float frame_sts = (frame->pts * av_q2d(c->stream->time_base)); + int nb_samples = qRound((target_sts - frame_sts)*c->sequence->audio_frequency); + if (nb_samples == 0) { + c->frame_sample_index = 0; + } else { + c->frame_sample_index = av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(c->sequence->audio_layout), nb_samples, AV_SAMPLE_FMT_S16, 1); + } + qDebug() << target_sts << frame_sts << nb_samples << c->frame_sample_index; + c->audio_just_reset = false; + } else { + c->frame_sample_index = 0; + } + // perform all audio effects int nb_bytes = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast(frame->format), 1); for (int j=0;jeffects.size();j++) { @@ -46,22 +69,35 @@ void cache_audio_worker(Clip* c) { } else { int nb_bytes = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast(frame->format), 1); - if (c->audio_buffer_write == 0) c->audio_buffer_write = (((int)(audio_ibuffer_read/2))*2) + 1024; int half_buffer = (audio_ibuffer_size/2); + if (c->audio_buffer_write == 0) { + c->audio_buffer_write = get_buffer_offset_from_frame(qMax(c->timeline_in, c->audio_target_frame)); + int offset = audio_ibuffer_read - c->audio_buffer_write; + if (offset > 0) { + c->audio_buffer_write += offset; + c->frame_sample_index += offset; + while (c->frame_sample_index > nb_bytes) { + // get new frame + retrieve_next_frame_raw_data(c, frame); + + nb_bytes = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast(frame->format), 1); + c->frame_sample_index -= nb_bytes; + } + } + } while (c->frame_sample_index < nb_bytes) { - if (c->audio_buffer_write >= audio_ibuffer_read+half_buffer) { + if (c->audio_buffer_write >= audio_ibuffer_read+half_buffer || c->audio_buffer_write >= get_buffer_offset_from_frame(c->timeline_out)) { written = max_write; break; } else { audio_ibuffer[c->audio_buffer_write%audio_ibuffer_size] += frame->data[0][c->frame_sample_index]; - c->audio_buffer_write++; c->frame_sample_index++; + written++; } } - written += c->frame_sample_index; if (c->frame_sample_index == nb_bytes) { - c->frame_sample_index = 0; + c->need_new_audio_frame = true; } } } @@ -120,7 +156,10 @@ void reset_cache(Clip* c, long target_frame) { } else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { // seek (target_frame represents timeline timecode in frames, not clip timecode) swr_drop_output(c->swr_ctx, swr_get_out_samples(c->swr_ctx, 0)); - av_seek_frame(c->formatCtx, c->media_stream->file_index, playhead_to_seconds(c, target_frame) / timebase, AVSEEK_FLAG_ANY); + av_seek_frame(c->formatCtx, c->media_stream->file_index, playhead_to_seconds(c, target_frame) / timebase, AVSEEK_FLAG_BACKWARD); + c->audio_target_frame = target_frame; + c->need_new_audio_frame = true; + c->audio_just_reset = true; } } } diff --git a/playback/playback.cpp b/playback/playback.cpp index 475c38a06..e84850290 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -272,13 +272,13 @@ void retrieve_next_frame_raw_data(Clip* c, AVFrame* output) { if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { sws_scale(c->sws_ctx, c->frame->data, c->frame->linesize, 0, c->stream->codecpar->height, output->data, output->linesize); } else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + output->pts = c->frame->pts; ret = swr_convert_frame(c->swr_ctx, output, c->frame); if (ret < 0) { qDebug() << "[ERROR] Failed to resample audio." << ret; } } } else if (ret == AVERROR_EOF) { -// qDebug() << "reached end triggered" << c->track; c->reached_end = true; } else { qDebug() << "[WARNING] Raw frame data could not be retrieved." << ret; diff --git a/project/clip.cpp b/project/clip.cpp index 6797fec71..0919def30 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -39,13 +39,31 @@ Clip* Clip::copy() { void Clip::init() { reset(); - clip_in = timeline_in = timeline_out = track = undeletable = 0; + clip_in = 0; + timeline_in = 0; + timeline_out = 0; + track = 0; + undeletable = 0; texture = NULL; pkt = new AVPacket(); } void Clip::reset() { - cache_size = cache_A.offset = cache_B.offset = open = pkt_written = cache_A.written = cache_B.written = cache_A.unread = cache_B.unread = reached_end = reset_audio = frame_sample_index = audio_buffer_write = 0; + cache_size = false; + audio_just_reset = false; + cache_A.offset = false; + cache_B.offset = false; + open = false; + pkt_written = false; + cache_A.written = false; + cache_B.written = false; + cache_A.unread = false; + cache_B.unread = false; + reached_end = false; + reset_audio = false; + frame_sample_index = false; + audio_buffer_write = false; + need_new_audio_frame = false; texture_frame = -1; formatCtx = NULL; stream = NULL; diff --git a/project/clip.h b/project/clip.h index 0cf5af4f5..4a4493a4b 100644 --- a/project/clip.h +++ b/project/clip.h @@ -86,9 +86,12 @@ struct Clip // audio playback variables SwrContext* swr_ctx; + bool need_new_audio_frame; int frame_sample_index; int audio_buffer_write; bool reset_audio; + bool audio_just_reset; + long audio_target_frame; }; #endif // CLIP_H diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 188d65a94..53de14d29 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -794,17 +794,14 @@ void TimelineWidget::redraw_clips() { clip_painter.drawImage(thumb_rect, clip->media_stream->video_preview); } } else { - long length = clip->media->get_length_in_frames(clip->sequence->frame_rate); - int waveform_x = ((float)clip->clip_in/(float)length) * clip->media_stream->audio_preview.size(); - int waveform_width = (((float)clip->getLength()/(float)length) * clip->media_stream->audio_preview.size()); int divider = clip->media_stream->audio_channels*2; - int waveform_scaled_length = qFloor((clip->media_stream->audio_preview.size() / (length*panel_timeline->zoom))/divider)*divider; clip_painter.setPen(QColor(80, 80, 80)); - int draw_x = clip_rect.x(); int channel_height = clip_rect.height()/clip->media_stream->audio_channels; + long media_length = clip->media->get_length_in_frames(clip->sequence->frame_rate); for (int i=0;imedia_stream->audio_preview.size())/divider)*divider; + int waveform_index = qFloor((((clip->clip_in + ((float) i/panel_timeline->zoom))/media_length) * clip->media_stream->audio_preview.size())/divider)*divider; + for (int j=0;jmedia_stream->audio_channels;j++) { int mid = clip_rect.top()+channel_height*j+(channel_height/2); int offset = waveform_index+(j*2); @@ -830,7 +827,7 @@ void TimelineWidget::redraw_clips() { clip_painter.drawText(text_rect, 0, clip->name, &text_rect); if (clip->linked.size() > 0) { int underline_y = CLIP_TEXT_PADDING + clip_painter.fontMetrics().height() + clip_rect.top(); - int underline_width = qMin(clip_rect.width() - CLIP_TEXT_PADDING, clip_rect.left() + CLIP_TEXT_PADDING+clip_painter.fontMetrics().width(clip->name)); + int underline_width = qMin(clip_rect.left() + clip_rect.width() - CLIP_TEXT_PADDING, clip_rect.left() + CLIP_TEXT_PADDING + clip_painter.fontMetrics().width(clip->name)); clip_painter.drawLine(clip_rect.left() + CLIP_TEXT_PADDING, underline_y, underline_width, underline_y); } diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index d12324db8..a55fcbf0e 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -114,7 +114,6 @@ void ViewerWidget::paintGL() } } else if (render_audio && c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && - playhead >= c->timeline_in && c->lock.tryLock()) { // clip is not caching, start caching audio c->lock.unlock();