I tried to make a program, which merges two frames. I use LibAV (libav-win32-20140428) under Windows 7 64 and Visual Studio 2013. But the result is quite odd.
The filter which was used is Overlay. When I change the graph, to the one, that uses only one stream and add FADE effect, everything works like a charm. But OVERLAY and eg. DRAWBOX give me strange distortion (three frames on one and black and white effect). Here is the code:
static int init_filter_graph(AVFilterGraph **pGraph, AVFilterContext **pSrc1, AVFilterContext **pSink)
{
AVFilterGraph* tFilterGraph;
AVFilterContext* tBufferContext1;
AVFilter* tBuffer1;
AVFilterContext* tColorContext;
AVFilter* tColor;
AVFilterContext* tOverlayContext;
AVFilter* tOverlay;
AVFilterContext* tBufferSinkContext;
AVFilter* tBufferSink;
int tError;
/* Create a new filtergraph, which will contain all the filters. */
tFilterGraph = avfilter_graph_alloc();
if (!tFilterGraph) {
return -1;
}
{ // BUFFER FILTER 1
tBuffer1 = avfilter_get_by_name("buffer");
if (!tBuffer1) {
return -1;
}
tBufferContext1 = avfilter_graph_alloc_filter(tFilterGraph, tBuffer1, "src1");
if (!tBufferContext1) {
return -1;
}
av_dict_set(&tOptionsDict, "width", "320", 0);
av_dict_set(&tOptionsDict, "height", "240", 0);
av_dict_set(&tOptionsDict, "pix_fmt", "bgr24", 0);
av_dict_set(&tOptionsDict, "time_base", "1/25", 0);
av_dict_set(&tOptionsDict, "sar", "1", 0);
tError = avfilter_init_dict(tBufferContext1, &tOptionsDict);
av_dict_free(&tOptionsDict);
if (tError < 0) {
return tError;
}
}
{ // COLOR FILTER
tColor = avfilter_get_by_name("color");
if (!tColor) {
return -1;
}
tColorContext = avfilter_graph_alloc_filter(tFilterGraph, tColor, "color");
if (!tColorContext) {
return -1;
}
av_dict_set(&tOptionsDict, "color", "white", 0);
av_dict_set(&tOptionsDict, "size", "20x120", 0);
av_dict_set(&tOptionsDict, "framerate", "1/25", 0);
tError = avfilter_init_dict(tColorContext, &tOptionsDict);
av_dict_free(&tOptionsDict);
if (tError < 0) {
return tError;
}
}
{ // OVERLAY FILTER
tOverlay = avfilter_get_by_name("overlay");
if (!tOverlay) {
return -1;
}
tOverlayContext = avfilter_graph_alloc_filter(tFilterGraph, tOverlay, "overlay");
if (!tOverlayContext) {
return -1;
}
av_dict_set(&tOptionsDict, "x", "0", 0);
av_dict_set(&tOptionsDict, "y", "0", 0);
av_dict_set(&tOptionsDict, "main_w", "120", 0);
av_dict_set(&tOptionsDict, "main_h", "140", 0);
av_dict_set(&tOptionsDict, "overlay_w", "320", 0);
av_dict_set(&tOptionsDict, "overlay_h", "240", 0);
tError = avfilter_init_dict(tOverlayContext, &tOptionsDict);
av_dict_free(&tOptionsDict);
if (tError < 0) {
return tError;
}
}
{ // BUFFERSINK FILTER
tBufferSink = avfilter_get_by_name("buffersink");
if (!tBufferSink) {
return -1;
}
tBufferSinkContext = avfilter_graph_alloc_filter(tFilterGraph, tBufferSink, "sink");
if (!tBufferSinkContext) {
return -1;
}
tError = avfilter_init_str(tBufferSinkContext, NULL);
if (tError < 0) {
return tError;
}
}
// Linking graph
tError = avfilter_link(tBufferContext1, 0, tOverlayContext, 0);
if (tError >= 0) {
tError = avfilter_link(tColorContext, 0, tOverlayContext, 1);
}
if (tError >= 0) {
tError = avfilter_link(tOverlayContext, 0, tBufferSinkContext, 0);
}
if (tError < 0) {
return tError;
}
tError = avfilter_graph_config(tFilterGraph, NULL);
if (tError < 0) {
return tError;
}
*pGraph = tFilterGraph;
*pSrc1 = tBufferContext1;
*pSink = tBufferSinkContext;
return 0;
}
What do you think is the reason?
I got a hint from Luca Barbato at LibAV's mailing list:
Can you try to reproduce that with avconv? From the image looks like you are getting a pixel format you are not really expecting.
lu
And I discovered, that I need to use Format Filter, to keep the pixels' format the same. So I added:
{ // FORMAT FILTER
tFormat = avfilter_get_by_name("format");
if (!tFormat) {
// Could not find the tFormat filter.
return -1;
}
tFormatContext = avfilter_graph_alloc_filter(tFilterGraph, tFormat, "format");
if (!tFormatContext) {
// Could not allocate the tFormat instance.
return -1;
}
av_dict_set(&tOptionsDict, "pix_fmts", "bgr24", 0);
tError = avfilter_init_dict(tFormatContext, &tOptionsDict);
av_dict_free(&tOptionsDict);
if (tError < 0) {
// Could not initialize the tFormat filter.
return tError;
}
}
in init_filter_graph function.
And now my filter graph looks like this:
tError = avfilter_link(tBufferContext1, 0, tOverlayContext, 0);
if (tError >= 0)
{
tError = avfilter_link(tColorContext, 0, tOverlayContext, 1);
}
if (tError >= 0)
{
tError = avfilter_link(tOverlayContext, 0, tFormatContext, 0);
}
if (tError >= 0)
{
tError = avfilter_link(tFormatContext, 0, tBufferSinkContext, 0);
}
if (tError < 0) { // Error connecting filters.
return tError;
}
The distortion is gone and color is back!