Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround for file://con use of stdin on Windows #651

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

dnastrain
Copy link

Workaround of issue found on Windows when using "file://con" for input to srt-live-transmit.exe -- only 1st 13160 bytes of data was being read from stdin.

Proposed fix for issue #646

@maxsharabayko maxsharabayko added this to the v.1.3.3 milestone Apr 18, 2019
@maxsharabayko maxsharabayko added the [apps] Area: Test applications related improvements label Apr 18, 2019
@maxsharabayko
Copy link
Collaborator

@dnastrain Cool! This works!

Funny thing is that srt_epoll_wait(...) does not change fds values, srtrfdslen ramains equal to the initial 2, making it possible for the reading loop to work.

if (src.get() && (srtrfdslen || sysrfdslen))

This is a kind of a fragile part for further maintenance.

This thing is probably not related to this PR, but found it while testing your fix. Like as you wrote:

detecting changes to the srt-target connection.

This set up:

srt-live-transmit file://con srt://:4200 -v

Detects connection (prints Accepted SRT target connection). But does not detect disconnection, and does not initialize new listening for incomming connections, so you can not connect again. But this seems to be true for the current master version.

srt-live-transmit.exe "srt://127.0.0.1:4200" file://con -v

Prints neither Source SRT connected, nor Source SRT disconnected.

@dnastrain
Copy link
Author

@maxlovic, ok, great!

Btw, I agree with you re: that one code part is kind of fragile, and is also what allowed the change to be small+targeted, since as you said it was:

making it possible for the reading loop to work

I had also noticed that current master has the same behavior, re:

detecting changes to the srt-target connection.

That said, when I use cmd-lines listed in #646 , srt-live-transmit does successfully detect disconnections & reconnections, at least while ffmpeg is 'pumping in data' to be read from stdin.

Copy link
Collaborator

@maxsharabayko maxsharabayko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue detecting target caller loosing SRT connection.

Interrupt receiver-listener with Ctrl+C.
Listener (Ctrl + C)

srt-live-transmit.exe srt://:4200 file://con -v
Media path: 'srt://:4200' --> 'file://con'
Opening SRT source listener on :4200
Binding a server on :4200 ...
 listen...
 accept...
 connected.
Accepted SRT source connection

-------- REQUESTED INTERRUPT!

Check the output of the caller-sender (current master). It detects disconnection: SRT target disconnected.
Caller (master version)

srt-live-transmit.exe file://con srt://127.0.0.1:4200 -v
Media path: 'file://con' --> 'srt://127.0.0.1:4200'
Opening SRT target caller on 127.0.0.1:4200
Connecting to 127.0.0.1:4200
SRT target connected
SRT target disconnected
SrtCommon: DESTROYING CONNECTION, closing sockets (rt%64882620 ls%-1)...
SrtCommon: ... done.
Opening SRT target
-------- REQUESTED INTERRUPT!

Check the output of the caller-sender (current PR). It does not detect disconnection.
Caller (PR 651)

srt-live-transmit.exe file://con srt://127.0.0.1:4200 -v
Media path: 'file://con' --> 'srt://127.0.0.1:4200'
Opening SRT target caller on 127.0.0.1:4200
Connecting to 127.0.0.1:4200
SRT target connected

@dnastrain
Copy link
Author

There is an issue detecting target caller loosing SRT connection.

Thank you @maxlovic for those details!
Was there an action item on me to re-merge, or is this just to be aware that current master is fixed?

@maxsharabayko
Copy link
Collaborator

Thank you @maxlovic for those details!
Was there an action item on me to re-merge, or is this just to be aware that current master is fixed?

I just quickly checked it yesterday to check if this PR is ready to be merged. But it appered to introduce this issue with detecting target disconnection. I believe there were no fixes in SRT master branch since. But maybe worth updating.

@maxsharabayko maxsharabayko modified the milestones: v.1.3.3, v.1.3.4 May 29, 2019
@dnastrain
Copy link
Author

Hi @maxlovic, I agree the current code does have that side affect -- if I comment out the lines

            if (srcUriType == UriParser::Type::FILE && tarConnected && ::WaitForSingleObject(hStdIn, 0) == WAIT_OBJECT_0)
            {
                srcReadMore = true;
            }

The behavior goes away (or better, matches Master).
More testing is needed I guess.
Thanks!

@maxsharabayko
Copy link
Collaborator

@dnastrain For some reason ::WaitForSingleObject(hStdIn, 0) signals the stdin has some data to read, while it does not. And the loop is blocked on reading from stdin.
Beside that, I think polling should be done anyway, to receive e.g. a disconnect event. Like this:

const int epoll_read = srt_epoll_wait(pollid,
	&srtrwfds[0], &srtrfdslen, &srtrwfds[2], &srtwfdslen,
	(srcReadMore ? 0 : 100),
	&sysrfds[0], &sysrfdslen, 0, 0);
if (epoll_read >= 0 || srcReadMore)

@dnastrain
Copy link
Author

dnastrain commented Jun 12, 2019

Hi @maxlovic , thank you for that info!
I also see the ::WaitForSingleObject(hStdIn, 0) returns as signaled even though stdin doesn't have 'real' data to be read.
Online forums point to there can be mouse (or other) events that can also trigger it -- so am looking at this further.

(I think this also explains why when I tested with ffmpeg piping data into stdin, it seemed to work ok)

@maxsharabayko
Copy link
Collaborator

@dnastrain I've updated your code like this to check what is happening:

#ifdef _WIN32
            // Workaround Issue #646:
            // On unix (POSIX), stdin is a valid FD with value 0. But not on Windows. This means that the first time epoll
            // hits on Windows is when the connection is done for SRT target. After that you will not receive any other events
            // from the poll. Furthermore, if you have connected and there is nothing in the stdin buffer waiting to be read, you 
            // will not read anything at all, because the polling event will never happen
            srcReadMore = false;
            cerr << "WaitForSingleObject ";
            // https://docs.microsoft.com/en-us/windows/console/reading-input-buffer-events
            if (srcUriType == UriParser::Type::FILE && tarConnected && ::WaitForSingleObject(hStdIn, 0) == WAIT_OBJECT_0)
            {
                srcReadMore = true;
                cerr << " has data ";
                INPUT_RECORD irInBuf[128];
                DWORD cNumRead;
                ReadConsoleInput(hStdIn, irInBuf, 128, &cNumRead);
                for (int i = 0; i < cNumRead; i++)
                {
                    switch (irInBuf[i].EventType)
                    {
                    case KEY_EVENT: // keyboard input 
                        cerr << "KEY_EVENT\n";
                        break;

                    case MOUSE_EVENT: // mouse input 
                        cerr << "MOUSE_EVENT\n";
                        break;

                    case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing 
                        cerr << "BUFFER_SIZE_EVENT\n";
                        break;

                    case FOCUS_EVENT:  // disregard focus events 
                        cerr << "FOCUS_EVENT\n";

                    case MENU_EVENT:   // disregard menu events 
                        cerr << "MENU_EVENT\n";
                        break;

                    default:
                        cerr << "UNKNOWN EVENT\n";
                        break;
                    }
                }
            }
            cerr << " - done " << endl;
#endif

Funny thing is that when I stick the terminal window to the left side of the window, with Win + Left, or any other key press, I get the event. And the event has to be read with ReadConsoleInput.

Also this condition is bad without checking srcReadMore.
if (src.get() && false && (srtrfdslen || sysrfdslen))

@dnastrain
Copy link
Author

It does now seem that one of your original suggestions for issue #646 , finding a 'non-blocking' version std::cin.peek() is what's really needed -- using the Windows Console functions seems to have added unnecessary complexity.

@dnastrain
Copy link
Author

Hi @maxlovic, so I agree the version in my PR is not 'issue free', since it can fail to detect a disconnect event if the cin.read() call is active and blocking.

At this point I would suggest this is as a 'lesser-issue' than the original problem in #646 , where srt-live-transmit stops sending any data past 10x1316 bytes on Windows, when an active stream from ffmpeg is piped to stdin.

Thoughts?

@dnastrain
Copy link
Author

dnastrain commented Jun 13, 2019

btw, I did some experiments with using std::cin.rdbuf()->in_avail() >= 0 rather than ::WaitForSingleObject, and the results were similar -- there appears to be data in the cin buffer right away, that causes the code to get to the cin.read code and then block.

some forums on stackoverflow suggest calling ::FlushConsoleInputBuffer at the beginning of one's console app (on Windows), but that also seems like a 'hack'...

I would still contend that this PR works correctly when data is streaming into stdin, and has the lesser-bug of blocking on cin.read if data isn't streaming-in (on Windows).

@maxsharabayko
Copy link
Collaborator

@dnastrain

At this point I would suggest this is as a 'lesser-issue' than the original problem in #646 , where srt-live-transmit stops sending any data past 10x1316 bytes on Windows, when an active stream from ffmpeg is piped to stdin.

Thoughts?

This is not a critical issue, and it is a sample application issue, so better to come up with a proper fix.
I think PeekConsoleInput and ReadConsoleInput might do the job on Windows.

@maxsharabayko maxsharabayko modified the milestones: v1.3.4, v1.4.1 Aug 9, 2019
@maxsharabayko maxsharabayko modified the milestones: v1.4.1, v1.4.2 Nov 4, 2019
@ethouris ethouris added Priority: Low Status: In Progress Type: Bug Indicates an unexpected problem or unintended behavior labels Nov 7, 2019
@maxsharabayko maxsharabayko modified the milestones: v1.5.0, v1.5.1 Jul 27, 2020
@mbakholdina mbakholdina modified the milestones: v1.5.1, Backlog May 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[apps] Area: Test applications related improvements Priority: Low Type: Bug Indicates an unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants