samirkumardas / jmuxer

jMuxer - a simple javascript mp4 muxer that works in both browser and node environment.
Other
555 stars 112 forks source link

Calling jmuxer.destroy after providing no frames can cause "DEMUXER_ERROR_COULD_NOT_OPEN" #10

Closed bp2008 closed 6 years ago

bp2008 commented 6 years ago

I've been using jmuxer to great effect in https://github.com/bp2008/ui3 but kept experiencing this intermittent error in Chrome. Once in a while when transitioning from one video stream to another, the HTML5 video element would throw a MediaError (via the video element's "error" event). The MediaError was always code 4 (MEDIA_ERR_SRC_NOT_SUPPORTED) with message "DEMUXER_ERROR_COULD_NOT_OPEN".

Today I tracked down the cause. It happens when I destroy the jmuxer instance before feeding the first frame to it. It is a little tricky to reproduce, because for the error to occur, a little time must pass between creating the jmuxer instance and destroying it. Possibly the Media Source needs to be ready first (it loads asynchronously). I noticed if I comment out this.mediaSource.endOfStream(); in jmuxer's destroy method, the MediaError won't be thrown.

I'm not sure what the ideal solution is for this. I am working around the problem by not destroying jmuxer instances which haven't been fed any frames yet.

samirkumardas commented 6 years ago

I have tried several ways but not able to generate the issue.

I think I have pin pointed the issue. I have pushed a probable solution. I believe it will fix the issue. thanks

bp2008 commented 6 years ago

Here, this will let you reproduce the error.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Demuxer Bug Test</title>
    <style type="text/css">
        input[type="button"]
        {
            margin-bottom: 10px;
        }

        #player
        {
            width: 160px;
            height: 90px;
            border: 1px solid #AA0000;
        }

        #output
        {
            border: 1px solid black;
            padding: 10px;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div>
        <input id="btnPush1" type="button" value="This button produces the error" />
    </div>
    <div>
        <input id="btnPush2" type="button" value="This button does not produce the error" />
    </div>
    <div>
        Video element: <video id="player" muted></video>
    </div>
    <div id="output"></div>

    <script src="dist/jmuxer.min.js"></script>
    <script type="text/javascript">
        var jmuxer;
        var player = document.getElementById("player");
        var output = document.getElementById("output");

        player.addEventListener('error', function (e)
        {
            msg(player.error.message + " (code " + player.error.code + ")", "#FF0000");
        });

        document.getElementById("btnPush1").addEventListener("click", function ()
        {
            if (jmuxer)
            {
                jmuxer.destroy();
                jmuxer = null;
                msg("jmuxer destroyed");
            }
            else
            {
                jmuxer = new JMuxer({
                    node: 'player',
                    mode: 'video'
                });
                msg("jmuxer created");
            }
        });
        document.getElementById("btnPush2").addEventListener("click", function ()
        {
            if (jmuxer)
            {
                jmuxer.destroy();
                jmuxer = null;
            }
            jmuxer = new JMuxer({
                node: 'player',
                mode: 'video'
            });
            msg("jmuxer destroyed + created");
        });
        function msg(text, color)
        {
            var el = document.createElement("div");
            if (color)
                el.style.color = color;
            el.innerText = text;
            output.appendChild(el);
        }
    </script>
</body>
</html>
samirkumardas commented 6 years ago

Have you tried with latest pull?

bp2008 commented 6 years ago

Not yet.

bp2008 commented 6 years ago

Yeah, it still happens with the latest.

You can simply drop the html file into your root directory and open it in Chrome (no web server required) and push the buttons to test. test_demuxer_chrome.zip

samirkumardas commented 6 years ago

Thanks for test file.

I have added the patch. thanks