Jump to content

One small step for ffmpeg... one giant leap for Emby! (Looking for C developer(s) to help with transcode throttling)


jluce50

Recommended Posts

jluce50

Can I just say that getting ffmpeg to build on Windows is a NIGHTMARE! I've been at it all day and it's just one error after another. If I had any hair I'd have pulled it all out by now. GAAAHHH!!!

 

I'm this close -->  <-- to loading up linux on a flash drive and running that...

 

Sorry, just had to vent.

Link to comment
Share on other sites

well i put in a windows-based throttle via process suspension and can confirm that it works. this really should only be a temporary solution until the ffmpeg changes are complete. I know others have been able to pause ffmpeg processes with success, but it's generally not a recommended practice for multi-threaded apps because this only pauses the main thread i believe. So if ffmpeg hasn't been designed for this, it's child threads may continue to operate which could create unexpected results.

Link to comment
Share on other sites

On windows if you suspend the process it should suspend all threads belonging to that process.  I've never heard of it only suspending the main or first thread as that would be kind of dumb IMHO.  But if this is the way it presently works, we can easily create a function that will suspend all threads for the program.  Would not be much harder to do if needed.

 

Glad to hear you're making good progress on this!

Link to comment
Share on other sites

well that is what i know based on Msdn documentation. it seems to be fine so we might as well just test it out for a while. since the ffmpeg change is considerably better i think that's where more time should be spent. also i've asked one developer to test a linux port of it. from there i'll check with our Bsd guys to see if the linux version will work. Osx will take some research though. 

Link to comment
Share on other sites

actually it might be fairly comprehensive

            foreach (ProcessThread thread in process.Threads)
            {
                var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
                if (pOpenThread == IntPtr.Zero)
                {
                    break;
                }
                SuspendThread(pOpenThread);
            }

Link to comment
Share on other sites

denethor

well i put in a windows-based throttle via process suspension and can confirm that it works. this really should only be a temporary solution until the ffmpeg changes are complete. I know others have been able to pause ffmpeg processes with success, but it's generally not a recommended practice for multi-threaded apps because this only pauses the main thread i believe. So if ffmpeg hasn't been designed for this, it's child threads may continue to operate which could create unexpected results.

I think this is implemented in 5537 Alpha. Although it dramatically improved the CPU usage it has broke the multi stream transcoding stability. If I start second stream on another device first one got hangs. Sometimes it completely stops, sometimes hangs for a long time etc. It is practically impossible to stream multiple files to multiple device. But one stream works stable.

Link to comment
Share on other sites

jabbera

While the thread schedulers are an unknown, instead of suspending why don't we just lower the priority of ffmpeg processes to idle that has more then 120 seconds of content buffered. It's easy to implement on all platforms and should accomplish the goal of giving "starving" ffmpeg processes priority. It will also allow idle time to be used to continue to transcode.

Link to comment
Share on other sites

I think this is implemented in 5537 Alpha. Although it dramatically improved the CPU usage it has broke the multi stream transcoding stability. If I start second stream on another device first one got hangs. Sometimes it completely stops, sometimes hangs for a long time etc. It is practically impossible to stream multiple files to multiple device. But one stream works stable.

 

can someone else confirm that? if that's the case then we'll have to just wait for ffmpeg.

Link to comment
Share on other sites

jluce50

I think this is implemented in 5537 Alpha. Although it dramatically improved the CPU usage it has broke the multi stream transcoding stability. If I start second stream on another device first one got hangs. Sometimes it completely stops, sometimes hangs for a long time etc. It is practically impossible to stream multiple files to multiple device. But one stream works stable.

 

can someone else confirm that? if that's the case then we'll have to just wait for ffmpeg.

 

 

Wouldn't this just be a matter of how it's implemented? I would be surprised if was impossible to suspend one process without affecting the others. When an ffmpeg process is kicked off, doesn't the code retain a handle of some sort? If not, perhaps we can create some sort of process pool to keep track...

Edited by jluce50
Link to comment
Share on other sites

Nologic

hmm going back to command line...there are two ways of seeking, fast & accuarate. When you use -ss prior to the input file it's fast...when it's used after the input its accuarate...and well you can use them both.

 

[Linky]

[Linky]

Edited by Nologic
Link to comment
Share on other sites

FredipusRex

Glancing over the ffmpeg code, it seems to me that you can implement a pause step pretty easily with about 4-5 lines of code. You just need to tap into the pre-existing output availability checking. If output is (temporarily) unavailable, it already pauses to give it a chance to recover. Tap into that existing system and you don't have to understand the ramifications of every change.

 

1. Create a new "global" int variable named "paused" in ffmpeg.c. It only needs to be file-scope. Default it to zero.

 

2. In check_keyboard_interaction(), add:

 

if (key == 'p') paused ^= 1; // Toggle pause

 

3. In transcode_step(), the first bit of code checks for a problem with the output streams, attempts to reset them, does an internal pause and returns 0 (success), which allows the outer code loop (including key press detection) some cycles. Hijack this by adding some code to the beginning of the procedure:

 

if (paused)

{

av_usleep(1000); // Shorter sleep duration to be more responsive to unpause

return 0;

}

 

That should be it. This won't start/stop things on a dime, but it should allow fairly responsive throttling without making wholesale changes to ffmpeg. Which should make it easier to get a pull request approved.

  • Like 1
Link to comment
Share on other sites

FredipusRex

You might need to let any keystroke unpause to avoid side-effects. So 'p' could be used by MB3 to both pause and unpause while any non-'p' key would clear the pause flag and do what it already does. Keeps everything backward compatible.

Link to comment
Share on other sites

Glancing over the ffmpeg code, it seems to me that you can implement a pause step pretty easily with about 4-5 lines of code. You just need to tap into the pre-existing output availability checking. If output is (temporarily) unavailable, it already pauses to give it a chance to recover. Tap into that existing system and you don't have to understand the ramifications of every change.

 

1. Create a new "global" int variable named "paused" in ffmpeg.c. It only needs to be file-scope. Default it to zero.

 

2. In check_keyboard_interaction(), add:

 

if (key == 'p') paused ^= 1; // Toggle pause

 

3. In transcode_step(), the first bit of code checks for a problem with the output streams, attempts to reset them, does an internal pause and returns 0 (success), which allows the outer code loop (including key press detection) some cycles. Hijack this by adding some code to the beginning of the procedure:

 

if (paused)

{

av_usleep(1000); // Shorter sleep duration to be more responsive to unpause

return 0;

}

 

That should be it. This won't start/stop things on a dime, but it should allow fairly responsive throttling without making wholesale changes to ffmpeg. Which should make it easier to get a pull request approved.

 

Would you mind helping but doing a little differently? I would forget about the "check for output stream problem" and just allow the pause value to be set via accepting an stdin key.

Link to comment
Share on other sites

You might need to let any keystroke unpause to avoid side-effects. So 'p' could be used by MB3 to both pause and unpause while any non-'p' key would clear the pause flag and do what it already does. Keeps everything backward compatible.

 

Well when we send commands it doesn't have to be a single key. we can easily send a string, so we could actually send the word pause and unpause. it just would be inconsistent with the naming of what they currently accept.

Link to comment
Share on other sites

FredipusRex

ffmpeg's stdin processing is largely single keystroke based (there is a 'command' variant, but that's complicated), so 'p' is easy while 'pause' is hard(er).

 

I was just thinking that if we limited the modification to a single character and preserved backward compatibility by not compromising other keystrokes, you'd be more likely to get accepted into the main trunk.

 

Oh, and the output stream problem was just an example. Really, what I'm suggesting is setting/unsettling the pause flag via the preexisting stdin processing ('s' already acts as a flag toggle, so it's consistent with how they do things). Then checking that flag at the top of transcode_step(), which currently has an "output stream problem" check at the top. If we do something very similar to what's done for output stream problems (wait a while and then hand back to the outer loop), again it's a very minimalist change that mimics their code style.

 

I'd love to help, but I'm currently without a development computer (mine died a few months ago and I don't have the funds to replace it now). But I'm happy to look at code and help out that way.

Link to comment
Share on other sites

hmm going back to command line...there are two ways of seeking, fast & accuarate. When you use -ss prior to the input file it's fast...when it's used after the input its accuarate...and well you can use them both.

 

[Linky]

[Linky]

The biggest problem with the command lines is that you can't "copy" the video and seek accurately YET.  So for example: -c:v copy is a no go.

Link to comment
Share on other sites

jluce50

I'd love to help, but I'm currently without a development computer (mine died a few months ago and I don't have the funds to replace it now). But I'm happy to look at code and help out that way.

 

That is much appreciated and I'll definitely take you up on that. I like the approach you've outlined, but I'll need to get ffmpeg building on my Windows machine first. After that headache, making and testing the changes should be a breeze by comparison...

Link to comment
Share on other sites

I would suggest specific pause and unpause commands.  Using a toggle opens the door for something to get out of sync.

Link to comment
Share on other sites

jluce50

can someone else confirm that? if that's the case then we'll have to just wait for ffmpeg.

 

I haven't started messing with the code yet, but I thought I'd provide a little more detail. It looks like what's happening is that the first process started works fine. When starting a second process, it will transcode until it reaches the threshold and then then suspends but never resumes. Meanwhile the first process continues suspending/resuming appropriately.

 

Also, when closing the respective video players the ffmpeg process continue to hang around in a suspended state. If I start up another stream a third ffmpeg is created.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...