fixed blurs causing black frames and added backend for stabilizer
This commit is contained in:
@@ -8,7 +8,7 @@ uniform bool horiz_blur;
|
||||
uniform bool vert_blur;
|
||||
|
||||
void main(void) {
|
||||
float rad = floor(radius);
|
||||
float rad = ceil(radius);
|
||||
float x_rad = (horiz_blur) ? rad : 0.5;
|
||||
float y_rad = (vert_blur) ? rad : 0.5;
|
||||
vec2 texCoord = gl_FragCoord.xy/resolution;
|
||||
|
||||
@@ -11,12 +11,13 @@ uniform vec2 resolution;
|
||||
|
||||
void main(void) {
|
||||
if (length > 0.0) {
|
||||
float ceillen = ceil(length);
|
||||
float radians = (angle*M_PI)/180.0;
|
||||
float divider = 1.0 / length;
|
||||
float divider = 1.0 / ceillen;
|
||||
float sin_angle = sin(radians);
|
||||
float cos_angle = cos(radians);
|
||||
|
||||
for (float i=-length+0.5;i<=length;i+=2.0) {
|
||||
for (float i=-ceillen+0.5;i<=ceillen;i+=2.0) {
|
||||
float y = sin_angle * i;
|
||||
float x = cos_angle * i;
|
||||
gl_FragColor += texture2D(image, vec2(gl_FragCoord.x+x, gl_FragCoord.y+y)/resolution)*(divider);
|
||||
|
||||
@@ -24,7 +24,7 @@ void main(void) {
|
||||
if (radius == 0.0 || sigma == 0.0 || (!horiz_blur && !vert_blur)) {
|
||||
gl_FragColor = texture2D(image, gl_FragCoord.xy/resolution);
|
||||
} else {
|
||||
float rad = floor(radius);
|
||||
float rad = ceil(radius);
|
||||
float x_rad = horiz_blur ? rad : 0.5;
|
||||
float y_rad = vert_blur ? rad : 0.5;
|
||||
|
||||
|
||||
+19
-38
@@ -456,9 +456,7 @@ void cache_video_worker(Clip* c, long playhead) {
|
||||
MediaStream* ms = media->get_stream_from_file_index(true, c->media_stream);
|
||||
|
||||
while ((retr_ret = av_buffersink_get_frame(c->buffersink_ctx, frame)) == AVERROR(EAGAIN)) {
|
||||
if (c->multithreaded && c->cacher->interrupt) { // abort
|
||||
return;
|
||||
}
|
||||
if (c->multithreaded && c->cacher->interrupt) return; // abort
|
||||
|
||||
AVFrame* send_frame = c->frame;
|
||||
read_ret = (c->use_existing_frame) ? 0 : retrieve_next_frame(c, send_frame);
|
||||
@@ -476,11 +474,11 @@ void cache_video_worker(Clip* c, long playhead) {
|
||||
dout << "skipped adding a frame to the queue - fpts:" << send_frame->pts << "target:" << target_pts;
|
||||
}*/
|
||||
|
||||
if (send_it) {
|
||||
if (send_it) {
|
||||
if ((send_ret = av_buffersrc_add_frame_flags(c->buffersrc_ctx, send_frame, AV_BUFFERSRC_FLAG_KEEP_REF)) < 0) {
|
||||
dout << "[ERROR] Failed to add frame to buffer source." << send_ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
av_frame_unref(c->frame);
|
||||
@@ -693,27 +691,7 @@ void open_clip_worker(Clip* clip) {
|
||||
}
|
||||
char filter_args[512];
|
||||
|
||||
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
/* SKIP_TYPE_SEEK is used if a video is playing at a speed so fast
|
||||
* that it is quicker to seek to the next frame than to just play
|
||||
* up to it (e.g. 2000% speed would require playing and skipping
|
||||
* 20 frames per frame and it many cases it would be quicker to
|
||||
* seek to it and cache in memory instead.
|
||||
*
|
||||
* TODO there could probably be a better heuristic than
|
||||
* (speed >= 5) for using seek mode. Experiment with the value
|
||||
* but also in the future perhaps we could implement a system
|
||||
* of testing how long it takes to seek vs how long it takes to
|
||||
* decode a frame and compare them to choose with method.
|
||||
*/
|
||||
clip->skip_type = (clip->speed < 5) ? SKIP_TYPE_DISCARD : SKIP_TYPE_SEEK;
|
||||
|
||||
// create memory cache for video (deprecated)
|
||||
// clip->cache_size = (ms->infinite_length) ? 1 : ceil(av_q2d(clip->stream->avg_frame_rate)/4); // cache is half a second in total
|
||||
|
||||
// if (clip->skip_type == SKIP_TYPE_SEEK) clip->cache_size *= 2;
|
||||
// if (ms->video_interlacing != VIDEO_PROGRESSIVE) clip->cache_size *= 2;
|
||||
|
||||
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
snprintf(filter_args, sizeof(filter_args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
|
||||
clip->stream->codecpar->width,
|
||||
clip->stream->codecpar->height,
|
||||
@@ -727,39 +705,42 @@ void open_clip_worker(Clip* clip) {
|
||||
avfilter_graph_create_filter(&clip->buffersrc_ctx, avfilter_get_by_name("buffer"), "in", filter_args, NULL, clip->filter_graph);
|
||||
avfilter_graph_create_filter(&clip->buffersink_ctx, avfilter_get_by_name("buffersink"), "out", NULL, NULL, clip->filter_graph);
|
||||
|
||||
enum AVPixelFormat pix_fmts[] = { static_cast<AVPixelFormat>(dest_format), AV_PIX_FMT_NONE };
|
||||
if (av_opt_set_int_list(clip->buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0) {
|
||||
dout << "[ERROR] Could not set output pixel format";
|
||||
}
|
||||
/*enum AVPixelFormat sinkpix_fmts[] = { static_cast<AVPixelFormat>(dest_format), AV_PIX_FMT_NONE };
|
||||
if (av_opt_set_int_list(clip->buffersink_ctx, "pix_fmts", sinkpix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0) {
|
||||
dout << "[ERROR] Could not set output pixel format";
|
||||
}*/
|
||||
|
||||
AVFilterContext* last_filter = clip->buffersrc_ctx;
|
||||
|
||||
if (ms->video_interlacing != VIDEO_PROGRESSIVE) {
|
||||
AVFilterContext* yadif_filter;
|
||||
char yadif_args[100];
|
||||
snprintf(yadif_args, sizeof(yadif_args), "mode=3:parity=%d", ((ms->video_interlacing == VIDEO_TOP_FIELD_FIRST) ? 0 : 1)); // try mode 1
|
||||
snprintf(yadif_args, sizeof(yadif_args), "mode=3:parity=%d", ((ms->video_interlacing == VIDEO_TOP_FIELD_FIRST) ? 0 : 1)); // there's a CUDA version if we start using nvdec/nvenc
|
||||
avfilter_graph_create_filter(&yadif_filter, avfilter_get_by_name("yadif"), "yadif", yadif_args, NULL, clip->filter_graph);
|
||||
|
||||
avfilter_link(last_filter, 0, yadif_filter, 0);
|
||||
last_filter = yadif_filter;
|
||||
}
|
||||
|
||||
/* stabilization code one day
|
||||
if (false) {
|
||||
/* stabilization code one day */
|
||||
bool stabilize = false;
|
||||
if (stabilize) {
|
||||
AVFilterContext* stab_filter;
|
||||
int stab_ret = avfilter_graph_create_filter(&stab_filter, avfilter_get_by_name("vidstabtransform"), "vidstab", "input=C\\:/Users/Matt/Desktop/samples/transforms.trf", NULL, clip->filter_graph);
|
||||
int stab_ret = avfilter_graph_create_filter(&stab_filter, avfilter_get_by_name("vidstabtransform"), "vidstab", "input=/media/matt/Home/samples/transforms.trf", NULL, clip->filter_graph);
|
||||
if (stab_ret < 0) {
|
||||
char err[100];
|
||||
av_strerror(stab_ret, err, sizeof(err));
|
||||
dout << "stab ret:" << stab_ret << err;
|
||||
} else {
|
||||
dout << "link 1:" << avfilter_link(last_filter, 0, stab_filter, 0);
|
||||
avfilter_link(last_filter, 0, stab_filter, 0);
|
||||
last_filter = stab_filter;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
avfilter_link(last_filter, 0, clip->buffersink_ctx, 0);
|
||||
AVFilterContext* format_conv;
|
||||
avfilter_graph_create_filter(&format_conv, avfilter_get_by_name("format"), "fmt", "pix_fmts=rgba", NULL, clip->filter_graph);
|
||||
avfilter_link(last_filter, 0, format_conv, 0);
|
||||
|
||||
avfilter_link(format_conv, 0, clip->buffersink_ctx, 0);
|
||||
|
||||
avfilter_graph_config(clip->filter_graph, NULL);
|
||||
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
|
||||
+1
-2
@@ -96,8 +96,7 @@ struct Clip
|
||||
bool pkt_written;
|
||||
bool open;
|
||||
bool finished_opening;
|
||||
bool replaced;
|
||||
int skip_type;
|
||||
bool replaced;
|
||||
bool ignore_reverse;
|
||||
|
||||
// caching functions
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
format.setDepthBufferSize(24);
|
||||
setFormat(format);
|
||||
|
||||
// error handler - retries after 500ms if we couldn't get the entire image
|
||||
// error handler - retries after 50ms if we couldn't get the entire image
|
||||
retry_timer.setInterval(50);
|
||||
connect(&retry_timer, SIGNAL(timeout()), this, SLOT(retry()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user