0

I'm evaluating using the MLT framework to process and concatenate some videos. I would need to integrate it with a 32 bit C# application, and also apply some dynamic, custom overlay to the data based on C# data structures, so I was planning on building the C API and using it in C# through P/Invoke.

I have managed to build a minimalistic config of the library with SDL, libavcodec, and dlfcn-win32, all other modules disabled, following https://www.mltframework.org/docs/windowsbuild/. However, my 32 bit build is not working correctly when using the C API, or the C++ API. I get segfaults, dummy output videos created, or hangs when using SDL. The created melt.exe and example project play.cpp have the same problem too.

Now this made me think maybe there is a problem with 32 bit builds, so I have tried a 64 bit build as well, with similar results. After that, I have tried the following configurations and compilers:

The fact that the last one did not work is surprising, makes me think there must be something wrong with my environment or something I'm doing. I followed those instructions to the letter. Also the built Shotcut.exe crashes on startup. In all these cases, the build did succeed but the built binaries did not work as expected.

Has anyone gotten MLT's C API to work correctly for video encoding on Windows 32 bit?

Here's my small test project, adapted from https://www.mltframework.org/docs/framework/.

(I have edited this code sample to reflect some of the concerns from Sergey's answer, but no change in the final result).

#include <windows.h>
#include <stdio.h>
#include "include/mlt/framework/mlt.h"

int main()
{
    mlt_repository repo = mlt_factory_init(NULL);

    fprintf(stderr, "start\n");

    if (repo != NULL)
    {
        mlt_consumer consumer = mlt_factory_consumer(NULL, "sdl", NULL);
        fprintf(stderr, "Creating consumer %p\n", consumer);

        if (consumer == NULL)
        {
            fprintf(stderr, "Consumer NULL. Aborting");
            return 1;
        }

        mlt_producer producer = mlt_factory_producer(NULL, "color", "red");
        fprintf(stderr, "Creating producer %p\n", producer);

        if (producer == NULL)
        {
            fprintf(stderr, "Producer NULL. Aborting");
            return 1;
        }

        fprintf(stderr, "Connecting %p to %p\n", producer, consumer);
        mlt_consumer_connect(consumer, mlt_producer_service(producer));

        fprintf(stderr, "Starting consumer %p\n", consumer);
        mlt_consumer_start(consumer);

        fprintf(stderr, "Wait for consumer\n");
        while (!mlt_consumer_is_stopped(consumer))
        {
            Sleep(1000);
            fprintf(stderr, "Wait more for consumer...\n");
        }


        fprintf(stderr, "Close consumer\n");
        // Close the consumer
        mlt_consumer_close(consumer);

        fprintf(stderr, "Close producer\n");
        // Close the producer
        mlt_producer_close(producer);

        fprintf(stderr, "Close factory\n");
        // Close the factory
        mlt_factory_close();
    }
    else
    {
        // Report an error during initialisation
        fprintf(stderr, "Unable to locate factory modules\n");
    }

    return 0;
}
james2048
  • 121
  • 1
  • 6

2 Answers2

0

From MLT Documentation:

mlt_consumer mlt_factory_consumer (mlt_profile, const char *, const void *)
Fetch a consumer from the repository

You are not checking the value returned by mlt_factory_consumer and it is NULL.

mlt_consumer hello = mlt_factory_consumer(NULL, "color", "red");
printf("Created consumer %p\n", hello);

mlt_producer world = mlt_factory_producer(NULL, NULL, NULL);
printf("Created producer %p\n", world);

mlt_service service = mlt_producer_service (world);
printf("Created service %p\n", service);
> gcc test.c -lmlt -g && ./a.out
Created consumer (nil)
Created producer (nil)
Created service (nil)
Segmentation fault (core dumped)

Whereas when given the default arguments it returns a valid pointer:

mlt_consumer hello = mlt_factory_consumer(NULL, NULL, NULL);
printf("Created consumer %p\n", hello);
printf("Loop over parent %p\n", hello -> parent . child);
. . .
> gcc test.c -lmlt -g && ./a.out
Created consumer 0x561978461cf0
Loop over parent 0x561978461cf0
Created producer (nil)
Created service (nil)
Connected 0
Starting consumer 0
Wait for consumer
Wait more for consumer...
Wait more for consumer...

  CTRL-C

Close consumer
Close producer
Close factory

screenshot

From the link you provided:

The default consumer is sdl. Also note, you can override the defaults as follows:

MLT_CONSUMER=xml ./hello file.avi will create a XML document on stdout.

MLT_CONSUMER=xml MLT_PRODUCER=avformat ./hello file.avi will play the video using the avformat producer directly, thus it will bypass the normalising functions.

MLT_CONSUMER=libdv ./hello file.avi > /dev/dv1394 might, if you’re lucky, do on the fly, realtime conversions of file.avi to DV and broadcast it to your DV device.

It is clear that you have to provide mlt_factory_consumer with a valid argument or NULL (and override the default consumer if you wish):

mlt_consumer hello = mlt_factory_consumer(NULL, "xml", NULL); 
printf("Created consumer %p\n", hello);
. . .
> gcc test.c -lmlt -g && ./a.out
Created consumer 0x55ab3ceb7660
Loop over parent 0x55ab3ceb7660
Created producer (nil)
Created service (nil)
Connected 0
Starting consumer 0
Wait for consumer
Close consumer
Close producer
Close factory
  • Hey Sergey, thanks for the answer. I made a copy and paste error, which I have corrected (swapped producer and consumer variables). Also I wasn't checking for null pointers in the code as I was running this inside gdb to check the pointers were valid. I've made some edits to the original question to add some checks though. I am still having the issue. – james2048 Jul 24 '17 at 09:31
  • @james2048 you are having a different issue now, as it is not in your code anymore. I'm running [the default package of MLT on Arch](https://www.archlinux.org/packages/extra/x86_64/mlt/) and your edited example runs fine, showing a red window. Are you having the same issue when compiled in Windows and Ubuntu? Are you sure you've installed all dependencies? It would be easier to locate the issue if you'd give any output. So far I'm unable to reproduce this problem. Also you probably should make a note in the question that code is edited, as this answer now makes no sense. –  Jul 24 '17 at 10:27
  • Hey Sergey, I have made a note that I have edited the question. Sorry about that. Also sorry if it wasn't obvious, but yes, the code compiles and runs fine on Linux (Ubuntu), the problems occur on Windows. – james2048 Jul 24 '17 at 11:31
  • Here is a pastebin with some output using different consumers/producers. https://pastebin.com/ByUfFPE8 I have not "installed" the dependencies, I have built the library from source using MinGW and then I am building and running my example in the prefix of the "make install" directory. I have copied all runtime libs like libavcodec to this directory as well. – james2048 Jul 24 '17 at 11:38
0

I have solved the issue. There is a bug where on Windows a default mlt_profile is not created when none is passed in.

So create one explicitly and pass it in to the factory calls:

mlt_profile profile = mlt_profile_init(NULL);

This fixed my issues with the C API on Windows. And no, SDL for some reason still doesn't work. But it's not that important.

james2048
  • 121
  • 1
  • 6