You need to replace the function call(s) ffmpeg
uses to read the file with ones that will retry until the file is done being written.
First, you can write your own processor and provide a callback to ffio_init_context()
that will retry reads until the file is completely written (you'd have to determine a method for your function to be able to tell that the file is done).
Second, you can determine what function calls ffmpeg
uses to read the file (probably read()
or fread()
) and use LD_PRELOAD to interpose a replacement that will retry until the file is finished being written. It's a bit hackish but it can be made to work. Something like this (this is just off-the-cuff code to demonstrate how you could do it. If you're lucky this might even work...):
read.c:
// most libc implementations also provide another symbol
// for library functions that starts with "_"
extern ssize_t _read( int, void *, size-t );
ssize_t read( int fd, void *buffer, size_t bytes )
{
ssize_t bytesRead;
for ( ;; )
{
bytesRead = _read( fd, buffer, bytes );
if ( bytesRead != 0 || fileIsComplete( fd ) )
{
break;
}
}
return ( bytesRead );
}
You'd need to implement fileIsComplete()
to check if the file has been completely written or not - and if the file isn't done, make it sleep
for a short bit or you'll just spin like crazy. And if ffmpeg
isn't using read()
, you'll have to figure out what it is using, for example fread()
.
If libc doesn't have an alternate underscore-prefixed symbol for the function(s) ffmpeg
uses to read the file, you'll have to do something like this (example is for fread()
:
fread.c:
// function pointer to the real fread() function
static size_t (*real_fread)( void *, size_t, size_t, FILE *) = NULL;
size_t fread( void *buffer, size_t size, size_t n, FILE *stream )
{
// might need to mutex this for multithreaded apps
if ( real_fread == NULL )
{
real_fread = dlsym( RTLD_NEXT, "fread" );
}
size_t result;
for ( ;; )
{
result = real_fread( buffer, size, n, stream );
if ( ( result != 0 ) || fileIsComplete( stream ) )
{
break;
}
}
return( result );
}
Just compile your interposing C code into a shared object and use LD_PRELOAD to have ffmpeg
use your interposed read()
function. Note that in both cases you'll have to add the proper header files (or maybe skip them because you might get redeclaration errors - in which case you might have to provide proper definitions for values like RTLD_NEXT
yourself).
Doing so can be tricky to get working right, as all calls to your interposing function(s) will go through your library for any process running with your LD_PRELOAD set. You'd probably do best with a wrapper script to set LD_PRELOAD and then run ffmpeg
so only you only have to deal with making ffmpeg
work with your interposing library.
And ffmpeg
might not handle partial reads very well - you may have to modify your code to keep reading until the file is done or a certain number of bytes has been read, such as the requested number of bytes.