fixed urgent bug that irreparably deleted sequences
This commit is contained in:
+16
-15
@@ -203,26 +203,26 @@ void PreviewGenerator::generate_waveform() {
|
||||
}
|
||||
}
|
||||
}
|
||||
AVPacket packet;
|
||||
AVPacket* packet = av_packet_alloc();
|
||||
bool done = true;
|
||||
|
||||
bool end_of_file = false;
|
||||
|
||||
// get the ball rolling
|
||||
av_read_frame(fmt_ctx, &packet);
|
||||
avcodec_send_packet(codec_ctx[packet.stream_index], &packet);
|
||||
av_read_frame(fmt_ctx, packet);
|
||||
avcodec_send_packet(codec_ctx[packet->stream_index], packet);
|
||||
|
||||
while (!end_of_file) {
|
||||
while (codec_ctx[packet.stream_index] == NULL || 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);
|
||||
while (codec_ctx[packet->stream_index] == NULL || 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) dout << "[ERROR] Failed to read packet for preview generation" << read_ret;
|
||||
break;
|
||||
}
|
||||
if (codec_ctx[packet.stream_index] != NULL) {
|
||||
int send_ret = avcodec_send_packet(codec_ctx[packet.stream_index], &packet);
|
||||
if (codec_ctx[packet->stream_index] != NULL) {
|
||||
int send_ret = avcodec_send_packet(codec_ctx[packet->stream_index], packet);
|
||||
if (send_ret < 0 && send_ret != AVERROR(EAGAIN)) {
|
||||
dout << "[ERROR] Failed to send packet for preview generation - aborting" << send_ret;
|
||||
end_of_file = true;
|
||||
@@ -231,9 +231,9 @@ void PreviewGenerator::generate_waveform() {
|
||||
}
|
||||
}
|
||||
if (!end_of_file) {
|
||||
MediaStream* s = media->get_stream_from_file_index(fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO, packet.stream_index);
|
||||
MediaStream* s = media->get_stream_from_file_index(fmt_ctx->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO, packet->stream_index);
|
||||
if (s != NULL) {
|
||||
if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (fmt_ctx->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (!s->preview_done) {
|
||||
int dstH = 120;
|
||||
int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height);
|
||||
@@ -267,12 +267,12 @@ void PreviewGenerator::generate_waveform() {
|
||||
sws_freeContext(sws_ctx);
|
||||
|
||||
if (!retrieve_duration) {
|
||||
avcodec_close(codec_ctx[packet.stream_index]);
|
||||
codec_ctx[packet.stream_index] = NULL;
|
||||
avcodec_close(codec_ctx[packet->stream_index]);
|
||||
codec_ctx[packet->stream_index] = NULL;
|
||||
}
|
||||
}
|
||||
media_lengths[packet.stream_index]++;
|
||||
} else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
media_lengths[packet->stream_index]++;
|
||||
} 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();
|
||||
@@ -349,13 +349,14 @@ void PreviewGenerator::generate_waveform() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
av_packet_unref(&packet);
|
||||
av_packet_unref(packet);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<media->audio_tracks.size();i++) {
|
||||
media->audio_tracks.at(i)->preview_done = true;
|
||||
}
|
||||
av_frame_free(&temp_frame);
|
||||
av_packet_free(&packet);
|
||||
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
|
||||
if (codec_ctx[i] != NULL) {
|
||||
avcodec_close(codec_ctx[i]);
|
||||
|
||||
+11
-4
@@ -729,13 +729,12 @@ void MainWindow::on_actionLink_Unlink_triggered()
|
||||
if (panel_timeline->focused()) panel_timeline->toggle_links();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRipple_To_In_Point_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) panel_timeline->ripple_to_in_point(true);
|
||||
void MainWindow::on_actionRipple_To_In_Point_triggered() {
|
||||
if (panel_timeline->focused()) panel_timeline->ripple_to_in_point(true, true);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRipple_to_Out_Point_triggered() {
|
||||
if (panel_timeline->focused()) panel_timeline->ripple_to_in_point(false);
|
||||
if (panel_timeline->focused()) panel_timeline->ripple_to_in_point(false, true);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSet_In_Point_triggered() {
|
||||
@@ -880,3 +879,11 @@ void MainWindow::on_actionAudio_Scrubbing_triggered() {
|
||||
void MainWindow::on_actionTransition_Tool_triggered() {
|
||||
if (panel_timeline->focused()) panel_timeline->ui->toolTransitionButton->click();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEdit_to_In_Point_triggered() {
|
||||
if (panel_timeline->focused()) panel_timeline->ripple_to_in_point(true, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEdit_to_Out_Point_triggered() {
|
||||
if (panel_timeline->focused()) panel_timeline->ripple_to_in_point(false, false);
|
||||
}
|
||||
|
||||
@@ -193,6 +193,10 @@ private slots:
|
||||
|
||||
void on_actionTransition_Tool_triggered();
|
||||
|
||||
void on_actionEdit_to_In_Point_triggered();
|
||||
|
||||
void on_actionEdit_to_Out_Point_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
void setup_layout();
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
<addaction name="actionLink_Unlink"/>
|
||||
<addaction name="actionRipple_To_In_Point"/>
|
||||
<addaction name="actionRipple_to_Out_Point"/>
|
||||
<addaction name="actionEdit_to_In_Point"/>
|
||||
<addaction name="actionEdit_to_Out_Point"/>
|
||||
<addaction name="actionSplit_at_Playhead"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSet_In_Point"/>
|
||||
@@ -824,6 +826,22 @@
|
||||
<string>T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_to_In_Point">
|
||||
<property name="text">
|
||||
<string>Edit to In Point</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Alt+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_to_Out_Point">
|
||||
<property name="text">
|
||||
<string>Edit to Out Point</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Alt+W</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
||||
+3
-1
@@ -416,14 +416,16 @@ void Project::process_file_list(bool recursive, QStringList& files, QTreeWidgetI
|
||||
}
|
||||
|
||||
imported = true;
|
||||
} else {
|
||||
} else if (!files.at(i).isEmpty()) {
|
||||
QString file(files.at(i));
|
||||
bool skip = false;
|
||||
|
||||
/* Heuristic to determine whether file is part of an image sequence */
|
||||
|
||||
// check file extension (assume it's not a
|
||||
|
||||
int lastcharindex = file.lastIndexOf(".");
|
||||
dout << "INFO:" << file << lastcharindex;
|
||||
bool found = true;
|
||||
if (lastcharindex != -1 && lastcharindex > file.lastIndexOf('/')) {
|
||||
// image_sequence_formats
|
||||
|
||||
+33
-14
@@ -702,7 +702,7 @@ void Timeline::paste() {
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::ripple_to_in_point(bool in) {
|
||||
void Timeline::ripple_to_in_point(bool in, bool ripple) {
|
||||
if (sequence != NULL) {
|
||||
// get track count
|
||||
int track_min = 0;
|
||||
@@ -736,29 +736,48 @@ void Timeline::ripple_to_in_point(bool in) {
|
||||
}
|
||||
}
|
||||
|
||||
if (one_frame_mode) {
|
||||
QVector<Selection> areas;
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
if (one_frame_mode) {
|
||||
// set up deletion areas based on track count
|
||||
if (in) {
|
||||
in_point = sequence->playhead;
|
||||
} else {
|
||||
in_point = sequence->playhead - 1;
|
||||
}
|
||||
|
||||
for (int i=track_min;i<=track_max;i++) {
|
||||
Selection s;
|
||||
s.in = in_point;
|
||||
s.out = in_point + 1;
|
||||
s.track = i;
|
||||
areas.append(s);
|
||||
}
|
||||
|
||||
// trim and move clips around the in point
|
||||
delete_areas_and_relink(ca, areas);
|
||||
if (ripple) ca->append(new RippleCommand(sequence, in_point, -1));
|
||||
} else {
|
||||
// set up deletion areas based on track count
|
||||
QVector<Selection> areas;
|
||||
// set up deletion areas based on track count
|
||||
for (int i=track_min;i<=track_max;i++) {
|
||||
Selection s;
|
||||
s.in = qMin(in_point, sequence->playhead);
|
||||
s.out = qMax(in_point, sequence->playhead);
|
||||
s.track = i;
|
||||
areas.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
// trim and move clips around the in point
|
||||
ComboAction* ca = new ComboAction();
|
||||
delete_areas_and_relink(ca, areas);
|
||||
ca->append(new RippleCommand(sequence, in_point, (in) ? (in_point - sequence->playhead) : (sequence->playhead - in_point)));
|
||||
undo_stack.push(ca);
|
||||
|
||||
update_ui(true);
|
||||
|
||||
if (in) panel_sequence_viewer->seek(in_point);
|
||||
// trim and move clips around the in point
|
||||
delete_areas_and_relink(ca, areas);
|
||||
if (ripple) ca->append(new RippleCommand(sequence, in_point, (in) ? (in_point - sequence->playhead) : (sequence->playhead - in_point)));
|
||||
}
|
||||
|
||||
undo_stack.push(ca);
|
||||
|
||||
update_ui(true);
|
||||
|
||||
if (in_point < sequence->playhead && ripple) panel_sequence_viewer->seek(in_point);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ public:
|
||||
QVector<int> get_tracks_of_linked_clips(int i);
|
||||
bool has_clip_been_split(int c);
|
||||
void toggle_links();
|
||||
void ripple_to_in_point(bool in);
|
||||
void ripple_to_in_point(bool in, bool ripple);
|
||||
void delete_in_out(bool ripple);
|
||||
void previous_cut();
|
||||
void next_cut();
|
||||
|
||||
+6
-1
@@ -311,11 +311,14 @@ void Viewer::pause() {
|
||||
// add it to the sequence
|
||||
Clip* c = new Clip(seq);
|
||||
Media* m = panel_project->last_imported_media.at(0);
|
||||
|
||||
m->ready_lock.lock();
|
||||
|
||||
c->media = m; // latest media
|
||||
c->media_type = MEDIA_TYPE_FOOTAGE;
|
||||
c->media_stream = 0;
|
||||
c->timeline_in = recording_start;
|
||||
c->timeline_out = seq->playhead;
|
||||
c->timeline_out = m->get_length_in_frames(seq->frame_rate);
|
||||
c->clip_in = 0;
|
||||
c->track = recording_track;
|
||||
c->color_r = 128;
|
||||
@@ -323,6 +326,8 @@ void Viewer::pause() {
|
||||
c->color_b = 128;
|
||||
c->name = m->name;
|
||||
|
||||
m->ready_lock.unlock();
|
||||
|
||||
QVector<Clip*> add_clips;
|
||||
add_clips.append(c);
|
||||
undo_stack.push(new AddClipCommand(seq, add_clips)); // add clip
|
||||
|
||||
+6
-10
@@ -70,6 +70,8 @@ void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_
|
||||
}
|
||||
}
|
||||
|
||||
#define AUDIO_BUFFER_PADDING 2048
|
||||
|
||||
void cache_audio_worker(Clip* c, bool scrubbing, Clip* nest) {
|
||||
long timeline_in = c->timeline_in;
|
||||
long timeline_out = c->timeline_out;
|
||||
@@ -270,7 +272,7 @@ void cache_audio_worker(Clip* c, bool scrubbing, Clip* nest) {
|
||||
#endif
|
||||
if (c->audio_buffer_write == 0) c->audio_buffer_write = get_buffer_offset_from_frame(c->sequence, qMax(timeline_in, c->audio_target_frame));
|
||||
|
||||
int offset = (audio_ibuffer_read + 512) - c->audio_buffer_write;
|
||||
int offset = (audio_ibuffer_read + AUDIO_BUFFER_PADDING) - c->audio_buffer_write;
|
||||
if (offset > 0) {
|
||||
c->audio_buffer_write += offset;
|
||||
c->frame_sample_index += offset;
|
||||
@@ -325,16 +327,8 @@ void cache_audio_worker(Clip* c, bool scrubbing, Clip* nest) {
|
||||
long buffer_timeline_out = get_buffer_offset_from_frame(c->sequence, timeline_out);
|
||||
audio_write_lock.lock();
|
||||
while (c->frame_sample_index < nb_bytes
|
||||
&& c->audio_buffer_write < audio_ibuffer_read+audio_ibuffer_size-512
|
||||
&& c->audio_buffer_write < audio_ibuffer_read+audio_ibuffer_size-AUDIO_BUFFER_PADDING
|
||||
&& c->audio_buffer_write < buffer_timeline_out) {
|
||||
|
||||
/*dout << "F (" <<
|
||||
c->frame_sample_index << "/" << nb_bytes
|
||||
<< ") (" <<
|
||||
c->audio_buffer_write << "/" << (audio_ibuffer_read+audio_ibuffer_size-512)
|
||||
<< ") (" <<
|
||||
c->audio_buffer_write << "/" << buffer_timeline_out << ")";*/
|
||||
|
||||
int upper_byte_index = (c->audio_buffer_write+1)%audio_ibuffer_size;
|
||||
int lower_byte_index = (c->audio_buffer_write)%audio_ibuffer_size;
|
||||
qint16 old_sample = static_cast<qint16>((audio_ibuffer[upper_byte_index] & 0xFF) << 8 | (audio_ibuffer[lower_byte_index] & 0xFF));
|
||||
@@ -590,6 +584,7 @@ void open_clip_worker(Clip* clip) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
dout << "[ERROR] Could not open" << filename << "-" << err;
|
||||
return;
|
||||
}
|
||||
|
||||
errCode = avformat_find_stream_info(clip->formatCtx, NULL);
|
||||
@@ -597,6 +592,7 @@ void open_clip_worker(Clip* clip) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
dout << "[ERROR] Could not open" << filename << "-" << err;
|
||||
return;
|
||||
}
|
||||
|
||||
av_dump_format(clip->formatCtx, 0, filename, 0);
|
||||
|
||||
+3
-4
@@ -26,8 +26,7 @@ Clip::Clip(Sequence* s) :
|
||||
speed(1.0),
|
||||
media(NULL),
|
||||
opening_transition(NULL),
|
||||
closing_transition(NULL),
|
||||
pkt(new AVPacket()),
|
||||
closing_transition(NULL),
|
||||
replaced(false),
|
||||
filter_graph(NULL),
|
||||
texture(NULL),
|
||||
@@ -38,6 +37,7 @@ Clip::Clip(Sequence* s) :
|
||||
use_existing_frame(false),
|
||||
ignore_reverse(false)
|
||||
{
|
||||
pkt = av_packet_alloc();
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -160,8 +160,7 @@ Clip::~Clip() {
|
||||
for (int i=0;i<effects.size();i++) {
|
||||
delete effects.at(i);
|
||||
}
|
||||
av_packet_unref(pkt);
|
||||
delete pkt;
|
||||
av_packet_free(&pkt);
|
||||
}
|
||||
|
||||
long Clip::get_timeline_in_with_transition() {
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ AddMediaCommand::~AddMediaCommand() {
|
||||
}
|
||||
|
||||
void AddMediaCommand::undo() {
|
||||
if (parent == NULL) {
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
|
||||
} else {
|
||||
parent->removeChild(item);
|
||||
|
||||
@@ -493,10 +493,7 @@ void TimelineWidget::wheelEvent(QWheelEvent *event) {
|
||||
void TimelineWidget::dragLeaveEvent(QDragLeaveEvent*) {
|
||||
if (sequence != NULL && panel_timeline->importing) {
|
||||
if (panel_timeline->importing_files) {
|
||||
for (int i=0;i<panel_project->last_imported_media.size();i++) {
|
||||
// hack? but seems to work
|
||||
undo_stack.undo();
|
||||
}
|
||||
undo_stack.undo();
|
||||
}
|
||||
panel_timeline->ghosts.clear();
|
||||
panel_timeline->importing = false;
|
||||
@@ -2391,7 +2388,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
if (clip_rect.bottom() >= 0 && clip_rect.bottom() < height()) p.drawLine(QPoint(qMax(0, clip_rect.left()), clip_rect.bottom()), QPoint(qMin(width(), clip_rect.right()), clip_rect.bottom()));
|
||||
|
||||
// draw transition tool
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION && panel_timeline->transition_tool_clip > -1) {
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION && panel_timeline->transition_tool_clip == i) {
|
||||
QRect transition_tool_rect = clip_rect;
|
||||
if (panel_timeline->transition_tool_type == TA_CLOSING_TRANSITION) {
|
||||
transition_tool_rect.setLeft(transition_tool_rect.left() + (3*(transition_tool_rect.width()>>2)));
|
||||
|
||||
Reference in New Issue
Block a user