Re: GStreamer playback of MP4 files with and without audio

Terry Barnaby via gstreamer-devel <[email protected]> Mon, 7 Oct 2024 06:57:47 +0100
Newsgroups gmane.comp.video.gstreamer.devel
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------mPLVWHgWKiu1t0xyd0eGch3X
Content-Type: multipart/alternative;
 boundary="------------wL5vQEdCm7820FEs9b8H70Fi"

--------------wL5vQEdCm7820FEs9b8H70Fi
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit

Many thanks Gareth.

Looks like your code was about the same as mine.

I have managed to get my test code to work however I don't know the 
reason it didn't work before. Enclosed is my code that works for anyone 
else in the same boat.

In my attached code only the function gstAudioAddPadCallback3() works as 
the "pad-added" callback for adding an MP3 audio processing sub pipeline.

It seems:
1. If you use decodebin in the attached sub pipeline, the pipeline will 
not go to the PLAYING state for some reason (no errors/warnings).

2. If you use gst_parse_bin_from_description(), gst_bin_add() and 
gst_element_sync_state_with_parent() the pipeline will not go to the 
PLAYING state for some reason (no errors/warnings).

No idea on why these issue occur. Using decodebin would have been more 
useful to handle different audio formats automatically (I assume it 
would have done that).

Terry
On 03/10/2024 09:24, Gareth Alldread via gstreamer-devel wrote:
> I haven't got experience with filesrc - but I attached my example 
> doing something similar with uridecodebin (which will work with an 
> video file btw).  I have stripped this out of my app - so it is 
> encapsulated inside a class - but I'm sure you get the idea.
>
>
>
> On Wed, 2 Oct 2024 at 17:46, Terry Barnaby via gstreamer-devel 
> <[email protected]> wrote:
>
>     I have tried using g_signal_connect(m_sourceElement, "pad-added",
>     ...) and within that adding a sub pipeline to the main pipeline,
>     but I am getting something wrong when I add the sub pipeline.
>
>     My simple program attached, sees the signal callback, but when I
>     add the sub pipeline and link it to the new pad, the displayed
>     video just freezes.
>     I've looked at the "Basic tutorial 3: Dynamic pipelines" and it
>     looks like I am doing the right thing and no errors are seen.
>
>     Any ideas on what I am ding wrong ?
>
>
>     On 02/10/2024 08:26, Gareth Alldread via gstreamer-devel wrote:
>>     I would add a handler for the "pad-added" event on the filesrc
>>     element and only create/add the audio part of the pipeline if you
>>     get an audio pad created.  That is what I have done to handle
>>     rtspsrc streams that may or may not have audio.  Reply if you
>>     want more details.
>>
>>     g_signal_connect(m_sourceElement, "pad-added",
>>     G_CALLBACK(&SynxRTSPPipeline::onPadAdded), this);
>>
>>     On Wed, 2 Oct 2024 at 07:30, Terry Barnaby via gstreamer-devel
>>     <[email protected]> wrote:
>>
>>         I am developing a C++ video inspection program that creates
>>         MP4/H264/MP3 files and needs to play them back with the video
>>         stream processed by various gstreamer elements and audio
>>         separately.
>>
>>         In general this has been working fine when just video was
>>         being recorded/played back, but I am just adding audio to the
>>         mix. Some MP4 files will contain only a video stream and some
>>         will contain both video and audio streams.
>>
>>         I need some way to handle the playback of these MP4 files
>>         that may or may not have MP3 audio streams.
>>
>>         As a simple idea if I use something like (The real C++ code
>>         constructs the gstreamer piple line and tees the video stream
>>         to various gstreamer sub pipelines):
>>
>>         gst-launch-1.0 -v filesrc location=temp.mp4 ! qtdemux name=demux
>>
>>           demux.video_0 ! queue ! h264parse ! openh264dec ! glimagesink
>>
>>           demux.audio_0 ! queue ! decodebin ! audioconvert ! pulsesink
>>
>>         This plays back the video and audio streams fine (not sure
>>         how well synchronised?) from an MP4 with video and audio
>>         streams, but hangs if the MP4 only has a video stream.
>>
>>         So I think I need to:
>>
>>         1. Maybe there is some gstreamer element or attribute that
>>         can ignore the audio stream if not present somehow ?
>>
>>         2. Check if the MP4 file has an audio stream before creating
>>         the gstreamer pipeline in C++.
>>
>>         3. Create the basic C++ pipleline in C++ and interrogate pads
>>         or something somehow and add the "demux.audio_0 ! queue !
>>         decodebin ! audioconvert ! pulsesink" sub pipeline if it is
>>         seen an audio stream is present.
>>
>>         Any ideas on the simplest/most CPU efficient way of doing
>>         this with gstreamer ?
>>
>>
>

--------------wL5vQEdCm7820FEs9b8H70Fi
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">Many thanks Gareth.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Looks like your code was about the same
      as mine.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">I have managed to get my test code to
      work however I don't know the reason it didn't work before.
      Enclosed is my code that works for anyone else in the same boat.<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">In my attached code only the function
      gstAudioAddPadCallback3() works as the "pad-added" callback for
      adding an MP3 audio processing sub pipeline.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">It seems:</div>
    <div class="moz-cite-prefix">1. If you use decodebin in the attached
      sub pipeline, the pipeline will not go to the PLAYING state for
      some reason (no errors/warnings).</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">2. If you use
      gst_parse_bin_from_description(), gst_bin_add() and
      gst_element_sync_state_with_parent() the pipeline will not go to
      the PLAYING state for some reason (no errors/warnings).</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">No idea on why these issue occur. Using
      decodebin would have been more useful to handle different audio
      formats automatically (I assume it would have done that).<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Terry<br>
    </div>
    <div class="moz-cite-prefix">On 03/10/2024 09:24, Gareth Alldread
      via gstreamer-devel wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAENg58osT5ChaTZQSkym3Ubxxwsjdc5Jiug_7Rj8-ME+6Em6pA@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div>I haven't got experience with filesrc - but I attached my
          example doing something similar with uridecodebin (which will
          work with an video file btw).  I have stripped this out of my
          app - so it is encapsulated inside a class - but I'm sure you
          get the idea.<br>
        </div>
        <div><br>
        </div>
        <div><br>
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Wed, 2 Oct 2024 at 17:46,
          Terry Barnaby via gstreamer-devel &lt;<a
            href="mailto:[email protected]"
            moz-do-not-send="true" class="moz-txt-link-freetext">[email protected]</a>&gt;
          wrote:<br>
        </div>
        <blockquote class="gmail_quote"
style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <div>
            <div>I have tried using g_signal_connect(m_sourceElement,
              "pad-added", ...) and within that adding a sub pipeline to
              the main pipeline, but I am getting something wrong when I
              add the sub pipeline.</div>
            <div><br>
            </div>
            <div>My simple program attached, sees the signal callback,
              but when I add the sub pipeline and link it to the new
              pad, the displayed video just freezes.</div>
            <div>I've looked at the "Basic tutorial 3: Dynamic
              pipelines" and it looks like I am doing the right thing
              and no errors are seen.</div>
            <div><br>
            </div>
            <div>Any ideas on what I am ding wrong ?<br>
            </div>
            <div><br>
            </div>
            <div><br>
            </div>
            <div>On 02/10/2024 08:26, Gareth Alldread via
              gstreamer-devel wrote:<br>
            </div>
            <blockquote type="cite">
              <div dir="ltr">
                <div>I would add a handler for the "pad-added" event on
                  the filesrc element and only create/add the audio part
                  of the pipeline if you get an audio pad created.  That
                  is what I have done to handle rtspsrc streams that may
                  or may not have audio.  Reply if you want more
                  details.</div>
                <div><br>
                </div>
                <div> g_signal_connect(m_sourceElement, "pad-added",
                  G_CALLBACK(&amp;SynxRTSPPipeline::onPadAdded), this);<br>
                </div>
              </div>
              <br>
              <div class="gmail_quote">
                <div dir="ltr" class="gmail_attr">On Wed, 2 Oct 2024 at
                  07:30, Terry Barnaby via gstreamer-devel &lt;<a
                    href="mailto:[email protected]"
                    target="_blank" moz-do-not-send="true"
                    class="moz-txt-link-freetext">[email protected]</a>&gt;
                  wrote:<br>
                </div>
                <blockquote class="gmail_quote"
style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                  <div>
                    <p>I am developing a C++ video inspection program
                      that creates MP4/H264/MP3 files and needs to play
                      them back with the video stream processed by
                      various gstreamer elements and audio separately.</p>
                    <p>In general this has been working fine when just
                      video was being recorded/played back, but I am
                      just adding audio to the mix. Some MP4 files will
                      contain only a video stream and some will contain
                      both video and audio streams.</p>
                    <p>I need some way to handle the playback of these
                      MP4 files that may or may not have MP3 audio
                      streams.<br>
                    </p>
                    <p>As a simple idea if I use something like (The
                      real C++ code constructs the gstreamer piple line
                      and tees the video stream to various gstreamer sub
                      pipelines):<br>
                    </p>
                    <pre>gst-launch-1.0 -v filesrc location=temp.mp4 ! qtdemux name=demux</pre>
                    <pre> demux.video_0 ! queue ! h264parse ! openh264dec ! glimagesink</pre>
                    <pre> demux.audio_0 ! queue ! decodebin ! audioconvert ! pulsesink</pre>
                    <p>This plays back the video and audio streams fine
                      (not sure how well synchronised?) from an MP4 with
                      video and audio streams, but hangs if the MP4 only
                      has a video stream.</p>
                    <p>So I think I need to:</p>
                    <p>1. Maybe there is some gstreamer element or
                      attribute that can ignore the audio stream if not
                      present somehow ?</p>
                    <p>2. Check if the MP4 file has an audio stream
                      before creating the gstreamer pipeline in C++.</p>
                    <p>3. Create the basic C++ pipleline in C++ and
                      interrogate pads or something somehow and add the
                      "demux.audio_0 ! queue ! decodebin ! audioconvert
                      ! pulsesink" sub pipeline if it is seen an audio
                      stream is present.<br>
                    </p>
                    Any ideas on the simplest/most CPU efficient way of
                    doing this with gstreamer ?<br>
                    <p><br>
                    </p>
                  </div>
                </blockquote>
              </div>
            </blockquote>
            <p><br>
            </p>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <p><br>
    </p>
  </body>
</html>

--------------wL5vQEdCm7820FEs9b8H70Fi--

--------------mPLVWHgWKiu1t0xyd0eGch3X
Content-Type: text/x-c++src; charset=UTF-8; name="test1.cpp"
Content-Disposition: attachment; filename="test1.cpp"
Content-Transfer-Encoding: base64

LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKgl0ZXN0MS5jcHAJU2ltcGxlIEMrKyBn
c3RyZWFtZXIgZXhhbXBsZQogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqCiAqIGh0
dHBzOi8vZ3N0cmVhbWVyLmZyZWVkZXNrdG9wLm9yZy9kb2N1bWVudGF0aW9uL3R1dG9yaWFs
cwogKgogKi8KI2luY2x1ZGUgPGdzdC9nc3QuaD4KI2luY2x1ZGUgPGdzdC9hcHAvZ3N0YXBw
c3JjLmg+CiNpbmNsdWRlIDxnc3QvcGJ1dGlscy9nc3RkaXNjb3ZlcmVyLmg+CiNpbmNsdWRl
IDxnbGliLmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8dW5pc3RkLmg+CiNpbmNs
dWRlIDxzaWduYWwuaD4KI2luY2x1ZGUgPHN0ZGludC5oPgoKR3N0RWxlbWVudCoJcGlwZWxp
bmU7CkdzdENsb2NrVGltZQljYW1lcmFUaW1lOwpHc3RDbG9ja1RpbWUJb3ZlcmxheVRpbWU7
Cgp2b2lkIHByaW50U3RhdHVzKCl7CglHc3RTdGF0ZSBzdGF0ZTsgR3N0U3RhdGUgcGVuZGlu
ZzsKCglnc3RfZWxlbWVudF9nZXRfc3RhdGUocGlwZWxpbmUsICZzdGF0ZSwgJnBlbmRpbmcs
IDApOwoJcHJpbnRmKCJQaXBlbGluZSBTdGF0dXM6ICVkICVkXG4iLCBzdGF0ZSwgcGVuZGlu
Zyk7Cn0KCnN0YXRpYyBnYm9vbGVhbiBidXNfY2FsbChHc3RCdXMqIGJ1cywgR3N0TWVzc2Fn
ZSogbXNnLCBncG9pbnRlciBkYXRhKXsKCUdNYWluTG9vcCoJbG9vcCA9IChHTWFpbkxvb3Aq
KWRhdGE7CgoJLy9wcmludGYoImJ1c19jYWxsOiAlZFxuIiwgR1NUX01FU1NBR0VfVFlQRSht
c2cpKTsKCQoJc3dpdGNoKEdTVF9NRVNTQUdFX1RZUEUobXNnKSl7CgoJY2FzZSBHU1RfTUVT
U0FHRV9FT1M6CgkJcHJpbnRmKCJFbmQgb2Ygc3RyZWFtXG4iKTsKCQkvL2dfbWFpbl9sb29w
X3F1aXQobG9vcCk7CgkJYnJlYWs7CgoJY2FzZSBHU1RfTUVTU0FHRV9FUlJPUjp7CgkJZ2No
YXIgICpkZWJ1ZzsKCQlHRXJyb3IgKmVycm9yOwoKCQlnc3RfbWVzc2FnZV9wYXJzZV9lcnJv
ciAobXNnLCAmZXJyb3IsICZkZWJ1Zyk7CgkJZ19mcmVlIChkZWJ1Zyk7CgoJCXByaW50Zigi
RXJyb3I6ICVzXG4iLCBlcnJvci0+bWVzc2FnZSk7CgkJZ19lcnJvcl9mcmVlKGVycm9yKTsK
CgkJZ19tYWluX2xvb3BfcXVpdChsb29wKTsKCQlicmVhazsKCQl9CgoJZGVmYXVsdDoKCQkv
L3ByaW50ZigiYnVzX2NhbGw6IG1lc3NhZ2U6ICVkXG4iLCBHU1RfTUVTU0FHRV9UWVBFKG1z
ZykpOwoJCWJyZWFrOwoJfQoKCXJldHVybiBHU1RfQlVTX1BBU1M7Cn0KCnZvaWQgIGdzdEF1
ZGlvQWRkUGFkQ2FsbGJhY2sxKEdzdEVsZW1lbnQqIGVsZW1lbnQsIEdzdFBhZCogcGFkLCBn
cG9pbnRlciB1c2VyX2RhdGEpewoJR3N0RWxlbWVudCoJcGlwZWxpbmUgPSAoR3N0RWxlbWVu
dCopdXNlcl9kYXRhOwoJR0Vycm9yKgkJZXJyb3IgPSBOVUxMOwoJZ2NoYXIqCQluYW1lOwoJ
R3N0RWxlbWVudCoJZTE7CglHc3RFbGVtZW50KgllMjsKCUdzdFBhZCoJCXBhZDI7CgoJcHJp
bnRmKCJnc3RBdWRpb0FkZFBhZENhbGxiYWNrMTogZG9lcyBub3Qgd29ya1xuIik7CgoJbmFt
ZSA9IGdzdF9wYWRfZ2V0X25hbWUocGFkKTsKCWdfcHJpbnQgKCJBIG5ldyBwYWQgJXMgd2Fz
IGNyZWF0ZWRcbiIsIG5hbWUpOwoJaWYoIXN0cmNtcChuYW1lLCAiYXVkaW9fMCIpKXsKCQlH
c3RFbGVtZW50KgllMTsKCQlHc3RFbGVtZW50KgllMjsKCQlHc3RQYWQqCQlwYWQyOwoKCQll
MSA9IGdzdF9wYXJzZV9iaW5fZnJvbV9kZXNjcmlwdGlvbigicXVldWUgbmFtZT1hdWRpb1F1
ZXVlICEgZGVjb2RlYmluICEgYXVkaW9jb252ZXJ0ICEgcHVsc2VzaW5rIiwgdHJ1ZSwgJmVy
cm9yKTsKCQlnc3RfYmluX2FkZChHU1RfQklOKHBpcGVsaW5lKSwgZTEpOwoJCWdzdF9lbGVt
ZW50X3N5bmNfc3RhdGVfd2l0aF9wYXJlbnQoZTEpOwoKCQllMiA9IGdzdF9iaW5fZ2V0X2J5
X25hbWUoR1NUX0JJTihlMSksICJhdWRpb1F1ZXVlIik7CgkJcGFkMiA9IGdzdF9lbGVtZW50
X2dldF9zdGF0aWNfcGFkKGUyLCAic2luayIpOwoJCXByaW50ZigiTGlua1BhZHM6ICVwICVw
XG4iLCBwYWQsIHBhZDIpOwoJCWdzdF9wYWRfbGluayhwYWQsIHBhZDIpOwoJCWdzdF9vYmpl
Y3RfdW5yZWYocGFkMik7Cgl9CglnX2ZyZWUgKG5hbWUpOwp9Cgp2b2lkICBnc3RBdWRpb0Fk
ZFBhZENhbGxiYWNrMihHc3RFbGVtZW50KiBlbGVtZW50LCBHc3RQYWQqIHBhZCwgZ3BvaW50
ZXIgdXNlcl9kYXRhKXsKCUdzdEVsZW1lbnQqCXBpcGVsaW5lID0gKEdzdEVsZW1lbnQqKXVz
ZXJfZGF0YTsKCUdFcnJvcioJCWVycm9yID0gTlVMTDsKCWdjaGFyKgkJbmFtZTsKCUdzdEVs
ZW1lbnQqCWUxOwoJR3N0RWxlbWVudCoJZTI7CglHc3RFbGVtZW50KgllMzsKCUdzdEVsZW1l
bnQqCWU0OwoJR3N0UGFkKgkJcGFkMjsKCglwcmludGYoImdzdEF1ZGlvQWRkUGFkQ2FsbGJh
Y2syOiBkb2VzIG5vdCB3b3JrXG4iKTsKCQoJbmFtZSA9IGdzdF9wYWRfZ2V0X25hbWUocGFk
KTsKCWdfcHJpbnQgKCJBIG5ldyBwYWQgJXMgd2FzIGNyZWF0ZWRcbiIsIG5hbWUpOwoJaWYo
IXN0cmNtcChuYW1lLCAiYXVkaW9fMCIpKXsKCQlHc3RFbGVtZW50KgllMTsKCQlHc3RFbGVt
ZW50KgllMjsKCQlHc3RFbGVtZW50KgllMzsKCQlHc3RFbGVtZW50KgllNDsKCQlHc3RQYWQq
CQlwYWQyOwoJCQoJCWUxID0gZ3N0X2VsZW1lbnRfZmFjdG9yeV9tYWtlKCJxdWV1ZSIsIE5V
TEwpOwoJCWUyID0gZ3N0X2VsZW1lbnRfZmFjdG9yeV9tYWtlKCJkZWNvZGViaW4iLCBOVUxM
KTsKCQllMyA9IGdzdF9lbGVtZW50X2ZhY3RvcnlfbWFrZSgiYXVkaW9jb252ZXJ0IiwgTlVM
TCk7CgkJZTQgPSBnc3RfZWxlbWVudF9mYWN0b3J5X21ha2UoInB1bHNlc2luayIsIE5VTEwp
OwoJCWdzdF9iaW5fYWRkX21hbnkoR1NUX0JJTihwaXBlbGluZSksIGUxLCBlMiwgZTMsIGU0
LCAwKTsKCQlnc3RfZWxlbWVudF9saW5rX21hbnkoZTEsIGUyLCBlMywgZTQsIDApOwoKCQln
c3RfZWxlbWVudF9zeW5jX3N0YXRlX3dpdGhfcGFyZW50KGUxKTsKCQlnc3RfZWxlbWVudF9z
eW5jX3N0YXRlX3dpdGhfcGFyZW50KGUyKTsKCQlnc3RfZWxlbWVudF9zeW5jX3N0YXRlX3dp
dGhfcGFyZW50KGUzKTsKCQlnc3RfZWxlbWVudF9zeW5jX3N0YXRlX3dpdGhfcGFyZW50KGU0
KTsKCQkKCQlwYWQyID0gZ3N0X2VsZW1lbnRfZ2V0X3N0YXRpY19wYWQoZTEsICJzaW5rIik7
CgkJcHJpbnRmKCJMaW5rUGFkczogJXAgJXBcbiIsIHBhZCwgcGFkMik7CgkJZ3N0X3BhZF9s
aW5rKHBhZCwgcGFkMik7CgkJZ3N0X29iamVjdF91bnJlZihwYWQyKTsKCX0KCWdfZnJlZSAo
bmFtZSk7Cgp9Cgp2b2lkICBnc3RBdWRpb0FkZFBhZENhbGxiYWNrMyhHc3RFbGVtZW50KiBl
bGVtZW50LCBHc3RQYWQqIHBhZCwgZ3BvaW50ZXIgdXNlcl9kYXRhKXsKCUdzdEVsZW1lbnQq
CXBpcGVsaW5lID0gKEdzdEVsZW1lbnQqKXVzZXJfZGF0YTsKCUdFcnJvcioJCWVycm9yID0g
TlVMTDsKCWdjaGFyKgkJbmFtZTsKCUdzdEVsZW1lbnQqCWUxOwoJR3N0RWxlbWVudCoJZTI7
CglHc3RFbGVtZW50KgllMzsKCUdzdEVsZW1lbnQqCWU0OwoJR3N0UGFkKgkJcGFkMjsKCglw
cmludGYoImdzdEF1ZGlvQWRkUGFkQ2FsbGJhY2szOiB3b3JrcyFcbiIpOwoJCgluYW1lID0g
Z3N0X3BhZF9nZXRfbmFtZShwYWQpOwoJZ19wcmludCAoIkEgbmV3IHBhZCAlcyB3YXMgY3Jl
YXRlZFxuIiwgbmFtZSk7CglpZighc3RyY21wKG5hbWUsICJhdWRpb18wIikpewoJCUdzdEVs
ZW1lbnQqCWUxOwoJCUdzdEVsZW1lbnQqCWUyOwoJCUdzdEVsZW1lbnQqCWUzOwoJCUdzdEVs
ZW1lbnQqCWU0OwoJCUdzdEVsZW1lbnQqCWU1OwoJCUdzdFBhZCoJCXBhZDI7CgkJCgkJZTEg
PSBnc3RfZWxlbWVudF9mYWN0b3J5X21ha2UoInF1ZXVlIiwgTlVMTCk7CgkJZTIgPSBnc3Rf
ZWxlbWVudF9mYWN0b3J5X21ha2UoIm1wZWdhdWRpb3BhcnNlIiwgTlVMTCk7CgkJZTMgPSBn
c3RfZWxlbWVudF9mYWN0b3J5X21ha2UoIm1wZzEyM2F1ZGlvZGVjIiwgTlVMTCk7CgkJZTQg
PSBnc3RfZWxlbWVudF9mYWN0b3J5X21ha2UoImF1ZGlvY29udmVydCIsIE5VTEwpOwoJCWU1
ID0gZ3N0X2VsZW1lbnRfZmFjdG9yeV9tYWtlKCJwdWxzZXNpbmsiLCBOVUxMKTsKCQlnc3Rf
YmluX2FkZF9tYW55KEdTVF9CSU4ocGlwZWxpbmUpLCBlMSwgZTIsIGUzLCBlNCwgZTUsIDAp
OwoJCWdzdF9lbGVtZW50X2xpbmtfbWFueShlMSwgZTIsIGUzLCBlNCwgZTUsIDApOwoKCQln
c3RfZWxlbWVudF9zeW5jX3N0YXRlX3dpdGhfcGFyZW50KGUxKTsKCQlnc3RfZWxlbWVudF9z
eW5jX3N0YXRlX3dpdGhfcGFyZW50KGUyKTsKCQlnc3RfZWxlbWVudF9zeW5jX3N0YXRlX3dp
dGhfcGFyZW50KGUzKTsKCQlnc3RfZWxlbWVudF9zeW5jX3N0YXRlX3dpdGhfcGFyZW50KGU0
KTsKCQlnc3RfZWxlbWVudF9zeW5jX3N0YXRlX3dpdGhfcGFyZW50KGU1KTsKCgkJcGFkMiA9
IGdzdF9lbGVtZW50X2dldF9zdGF0aWNfcGFkKGUxLCAic2luayIpOwoJCXByaW50ZigiTGlu
a1BhZHM6ICVwICVwXG4iLCBwYWQsIHBhZDIpOwoJCWdzdF9wYWRfbGluayhwYWQsIHBhZDIp
OwoJCWdzdF9vYmplY3RfdW5yZWYocGFkMik7Cgl9CglnX2ZyZWUgKG5hbWUpOwoKfQoKdm9p
ZCAgZ3N0QXVkaW9BZGRQYWRDYWxsYmFjazQoR3N0RWxlbWVudCogZWxlbWVudCwgR3N0UGFk
KiBwYWQsIGdwb2ludGVyIHVzZXJfZGF0YSl7CglHc3RFbGVtZW50KglwaXBlbGluZSA9IChH
c3RFbGVtZW50Kil1c2VyX2RhdGE7CglHRXJyb3IqCQllcnJvciA9IE5VTEw7CglnY2hhcioJ
CW5hbWU7CglHc3RFbGVtZW50KgllMTsKCUdzdEVsZW1lbnQqCWUyOwoJR3N0UGFkKgkJcGFk
MjsKCglwcmludGYoImdzdEF1ZGlvQWRkUGFkQ2FsbGJhY2s0OiBkb2VzIG5vdCB3b3JrXG4i
KTsKCgluYW1lID0gZ3N0X3BhZF9nZXRfbmFtZShwYWQpOwoJZ19wcmludCAoIkEgbmV3IHBh
ZCAlcyB3YXMgY3JlYXRlZFxuIiwgbmFtZSk7CgoJaWYoIXN0cmNtcChuYW1lLCAiYXVkaW9f
MCIpKXsKCQlHc3RFbGVtZW50KgllMTsKCQlHc3RFbGVtZW50KgllMjsKCQlHc3RQYWQqCQlw
YWQyOwoKCQllMSA9IGdzdF9wYXJzZV9iaW5fZnJvbV9kZXNjcmlwdGlvbigicXVldWUgbmFt
ZT1hdWRpb1F1ZXVlICEgbXBlZ2F1ZGlvcGFyc2UgISBtcGcxMjNhdWRpb2RlYyAhIGF1ZGlv
Y29udmVydCAhIHB1bHNlc2luayIsIHRydWUsICZlcnJvcik7CgkJZ3N0X2Jpbl9hZGQoR1NU
X0JJTihwaXBlbGluZSksIGUxKTsKCQkKCQlnc3RfZWxlbWVudF9zeW5jX3N0YXRlX3dpdGhf
cGFyZW50KGUxKTsKCgkJZTIgPSBnc3RfYmluX2dldF9ieV9uYW1lKEdTVF9CSU4oZTEpLCAi
YXVkaW9RdWV1ZSIpOwoJCXBhZDIgPSBnc3RfZWxlbWVudF9nZXRfc3RhdGljX3BhZChlMiwg
InNpbmsiKTsKCQlwcmludGYoIkxpbmtQYWRzOiAlcCAlcFxuIiwgcGFkLCBwYWQyKTsKCQln
c3RfcGFkX2xpbmsocGFkLCBwYWQyKTsKCQlnc3Rfb2JqZWN0X3VucmVmKHBhZDIpOwoJfQoJ
Z19mcmVlIChuYW1lKTsKfQoKCmludCBtYWluIChpbnQgYXJnYywgY2hhcioqIGFyZ3YpewoJ
R01haW5Mb29wKglsb29wOwoJR0Vycm9yKgkJZXJyb3IgPSBOVUxMOwoJR3N0QnVzKgkJYnVz
OwoJZ3VpbnQJCWJ1c193YXRjaF9pZDsKCXB0aHJlYWRfdAl0aHJlYWQxOwoJcHRocmVhZF90
CXRocmVhZDI7CgljaGFyCQljbWRbNDA5Nl07CglHc3RFbGVtZW50KglkZW11eDsKCUdzdFBh
ZCoJCXBhZDsKCgkvLyBJbml0aWFsaXNhdGlvbgoJZ3N0X2luaXQoJmFyZ2MsICZhcmd2KTsK
Cglsb29wID0gZ19tYWluX2xvb3BfbmV3KE5VTEwsIEZBTFNFKTsKCgljbWRbMF0gPSAwOwoK
CS8vc3RyY2F0KGNtZCwgImZpbGVzcmMgbG9jYXRpb249dGVtcDEubXA0ICEgcXRkZW11eCBu
YW1lPWRlbXV4ICBkZW11eC52aWRlb18wICEgcXVldWUgISBoMjY0cGFyc2UgISBvcGVuaDI2
NGRlYyAhIGdsaW1hZ2VzaW5rIik7CglzdHJjYXQoY21kLCAiZmlsZXNyYyBsb2NhdGlvbj10
ZW1wMi5tcDQgISBxdGRlbXV4IG5hbWU9ZGVtdXggIGRlbXV4LnZpZGVvXzAgISBxdWV1ZSAh
IGgyNjRwYXJzZSAhIG9wZW5oMjY0ZGVjICEgZ2xpbWFnZXNpbmsiKTsKCgkvL3N0cmNhdChj
bWQsICIgZGVtdXguYXVkaW9fMCAhIHF1ZXVlIG5hbWU9YXVkaW9RdWV1ZSAhIGRlY29kZWJp
biAhIGF1ZGlvY29udmVydCAhIHB1bHNlc2luayIpOwoJLy9zdHJjYXQoY21kLCAiIHF1ZXVl
IG5hbWU9YXVkaW9RdWV1ZSAhIGRlY29kZWJpbiAhIGF1ZGlvY29udmVydCAhIHB1bHNlc2lu
ayIpOwoKCQkKCXByaW50ZigiUnVuOiAlc1xuIiwgY21kKTsKCXBpcGVsaW5lID0gZ3N0X3Bh
cnNlX2xhdW5jaChjbWQsICZlcnJvcik7CgoJZGVtdXggPSBnc3RfYmluX2dldF9ieV9uYW1l
KEdTVF9CSU4ocGlwZWxpbmUpLCAiZGVtdXgiKTsKCS8vZ19zaWduYWxfY29ubmVjdChkZW11
eCwgInBhZC1hZGRlZCIsIEdfQ0FMTEJBQ0soZ3N0QXVkaW9BZGRQYWRDYWxsYmFjazEpLCBw
aXBlbGluZSk7CgkvL2dfc2lnbmFsX2Nvbm5lY3QoZGVtdXgsICJwYWQtYWRkZWQiLCBHX0NB
TExCQUNLKGdzdEF1ZGlvQWRkUGFkQ2FsbGJhY2syKSwgcGlwZWxpbmUpOwoJZ19zaWduYWxf
Y29ubmVjdChkZW11eCwgInBhZC1hZGRlZCIsIEdfQ0FMTEJBQ0soZ3N0QXVkaW9BZGRQYWRD
YWxsYmFjazMpLCBwaXBlbGluZSk7CgkvL2dfc2lnbmFsX2Nvbm5lY3QoZGVtdXgsICJwYWQt
YWRkZWQiLCBHX0NBTExCQUNLKGdzdEF1ZGlvQWRkUGFkQ2FsbGJhY2s0KSwgcGlwZWxpbmUp
OwoKCS8vIFdlIGFkZCBhIG1lc3NhZ2UgaGFuZGxlcgoJYnVzID0gZ3N0X3BpcGVsaW5lX2dl
dF9idXMoR1NUX1BJUEVMSU5FIChwaXBlbGluZSkpOwoJYnVzX3dhdGNoX2lkID0gZ3N0X2J1
c19hZGRfd2F0Y2goYnVzLCBidXNfY2FsbCwgbG9vcCk7Cglnc3Rfb2JqZWN0X3VucmVmKGJ1
cyk7CgoJcHJpbnRmKCJOb3cgc2V0IHBpcGVsaW5lIGluIHN0YXRlIHBsYXlpbmdcbiIpOwoJ
Z3N0X2VsZW1lbnRfc2V0X3N0YXRlKHBpcGVsaW5lLCBHU1RfU1RBVEVfUEFVU0VEKTsKCglz
bGVlcCgyKTsgcHJpbnRTdGF0dXMoKTsKCWdzdF9lbGVtZW50X3NldF9zdGF0ZShwaXBlbGlu
ZSwgR1NUX1NUQVRFX1BMQVlJTkcpOwoJc2xlZXAoMik7IHByaW50U3RhdHVzKCk7CgoJLy8g
SXRlcmF0ZQoJcHJpbnRmKCJSdW5uaW5nLi4uXG4iKTsKCWdfbWFpbl9sb29wX3J1bihsb29w
KTsKCgkvLyBPdXQgb2YgdGhlIG1haW4gbG9vcCwgY2xlYW4gdXAgbmljZWx5CglwcmludGYo
IlJldHVybmVkLCBzdG9wcGluZyBwbGF5YmFja1xuIik7Cglnc3RfZWxlbWVudF9zZXRfc3Rh
dGUocGlwZWxpbmUsIEdTVF9TVEFURV9OVUxMKTsKCglwcmludGYoIkRlbGV0aW5nIHBpcGVs
aW5lXG4iKTsKCWdzdF9vYmplY3RfdW5yZWYoR1NUX09CSkVDVCAocGlwZWxpbmUpKTsKCWdf
c291cmNlX3JlbW92ZShidXNfd2F0Y2hfaWQpOwoJZ19tYWluX2xvb3BfdW5yZWYobG9vcCk7
CgoJcmV0dXJuIDA7Cn0K

--------------mPLVWHgWKiu1t0xyd0eGch3X--