<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><style>body { line-height: 1.5; }blockquote { margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em; }p { margin-top: 0px; margin-bottom: 0px; }body { font-size: 10.5pt; font-family: 'Segoe UI'; color: rgb(0, 0, 0); line-height: 1.5; }</style></head><body>
<div><span></span>hi Ross,</div><div><br></div><div>Let me explain how I transfer data from our camera to live555 library.</div><div><br></div><div>I followed the second approach from instructions on the FAQ page, <span style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;"></span><a href="http://www.live555.com/liveMedia/faq.html#liveInput" segoe="" ui'";="" font-size:="" 14px;="" font-weight:="" normal;="" font-style:="" normal;'="" style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;">http://www.live555.com/liveMedia/faq.html#liveInput</a><span segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgb(255,="" 255,="" 255);="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'="" style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;"> </span></div><div>namely, to write my own "<span style="font-family: "" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'="">Gm813xSource</span>" as subclass of "FramedSource", and my own "<span style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;">GM813XServerMediaSubsession" as subclass of "</span><span style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;">OnDemandServerMediaSubsession".</span></div><div><span style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;"><br></span></div><div>The GM813XSource.cpp is modified out of DeviceSource.cpp. Here I copy the key part of the code to below.</div><div><br></div><div><span style="font-family: ''; background-color: rgb(192, 192, 192);" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'="">void Gm813xSource::doGetNextFrame()<br>{<br> if (gmPollFrame()) {<br> deliverFrame();<br> }<br>}<br></span></div><div><span style="font-family: ''; background-color: rgb(192, 192, 192);" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""><br></span></div><div><span style="font-family: ''; background-color: rgb(192, 192, 192);" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""><span style="font-family: "" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgb(192,="" 192,="" 192);="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'="">Boolean Gm813xSource::gmPollFrame(void)<br>{<br> int ret = gm_poll(&poll_fds, 1, 2000);<br> if(GM_TIMEOUT == ret) {<br> envir() << "gm_poll timeout\n";<br> return false;<br> }<br> if(GM_SUCCESS == ret) {<br> return true;<br> }<br> envir() << "gm_poll error, ret=" << ret << "\n";<br> return false;<br>}<br></span></span></div><div><span style="font-family: ''; background-color: rgb(192, 192, 192);" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""><span style="font-family: "" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgb(192,="" 192,="" 192);="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""><br></span></span></div><span style="background-color: rgb(192, 192, 192);"><span style="font-family: "" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgb(255,="" 255,="" 255);="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""></span>
</span><div><span style="font-family: "" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""><span style="background-color: rgb(192, 192, 192);">void Gm813xSource::deliverFrame(void)<br>{<br> int ret;<br> gm_enc_multi_bitstream_t bs;<br><br> if (!isCurrentlyAwaitingData())<br> return; // we're not ready for the data yet<br><br> memset(&bs, 0, sizeof(bs));<br><br> bs.bindfd = main_bindfd;//poll_fds[i].bindfd;<br> bs.bs.bs_buf = frameBuf; // set buffer point<br> bs.bs.bs_buf_len = FRAME_BUF_SIZE; // set buffer length<br> bs.bs.mv_buf = 0; // not to recevie MV data<br> bs.bs.mv_buf_len = 0; // not to recevie MV data<br><br> if (bytesInBuf > 0) { // send leftover data<br> if (bytesInBuf > fMaxSize) {<br> fFrameSize = fMaxSize;<br> fNumTruncatedBytes = bytesInBuf - fMaxSize;<br> bytesInBuf = fNumTruncatedBytes;<br> dataPtr += fFrameSize;<br> } else {<br> fFrameSize = bytesInBuf;<br> bytesInBuf = 0;<br> }<br> memmove(fTo, dataPtr, fFrameSize);<br> FramedSource::afterGetting(this);<br> } else { // get a new frame and send<br> if ((ret = gm_recv_multi_bitstreams(&bs, 1)) < 0) {<br> printf("Error, gm_recv_multi_bitstreams return value %d\n", ret);<br> } else {<br> if ((bs.retval < 0) && bs.bindfd) {<br> printf("Error to receive bitstream. ret=%d\n", bs.retval);<br> } else if (bs.retval == GM_SUCCESS) {<br> u_int8_t* newFrameDataStart = (u_int8_t*)bs.bs.bs_buf; //%%% TO BE WRITTEN %%%<br> unsigned newFrameSize = bs.bs.bs_len; //%%% TO BE WRITTEN %%%<br> bytesInBuf = newFrameSize;<br> dataPtr = bs.bs.bs_buf;<br><br> // Deliver the data here:<br> if (newFrameSize > fMaxSize) {<br> fFrameSize = fMaxSize;<br> fNumTruncatedBytes = newFrameSize - fMaxSize;<br> } else {<br> fFrameSize = newFrameSize;<br> }<br><br> bytesInBuf -= fFrameSize;<br> dataPtr += fFrameSize;<br><br> gettimeofday(&fPresentationTime, NULL); <br> memmove(fTo, newFrameDataStart, fFrameSize);<br><br> // After delivering the data, inform the reader that it is now available:<br> FramedSource::afterGetting(this);<br> }<br> }<br> }<br>}</span><br></span></div><div><span style="font-family: ''; background-color: rgb(255, 255, 255);" segoe="" ui'";="" font-size:="" 14px;="" color:="" rgb(0,="" 0,="" 0);="" background-color:="" rgba(0,="" font-weight:="" normal;="" font-style:="" normal;text-decoration:="" none;'=""><br></span></div><div>As you can see, I use "<span style="background-color: rgb(192, 192, 192); font-size: 10.5pt; line-height: 1.5;">frameBuf"</span><span style="font-size: 10.5pt; line-height: 1.5; background-color: rgb(255, 255, 255);"> to hold encoded bytes from the encoder, and then move the data to fTo as soon as possible, finally, after each copying I called </span><span style="background-color: rgb(192, 192, 192); font-size: 10.5pt; line-height: 1.5;">afterGetting</span><span style="font-size: 10.5pt; line-height: 1.5; background-color: rgb(255, 255, 255);"> callback.</span><span style="font-size: 10.5pt; line-height: 1.5; background-color: rgb(255, 255, 255);"> For the "frameBuf", I allocated 512K bytes, which is big enough to hold the largest I frame. If the afterGetting callback of sink-side object then deliver the frame data to network immediatly, the latency I've introduced by frameBuf should be only 1 frame, namely 33ms (of course there's capture buffer and buffers inside the hw encoder that's not counted here, but they shouldn't add too much, I'm currenly checking this with help from the chip FAE). </span></div><div><span style="font-size: 10.5pt; line-height: 1.5; background-color: rgb(255, 255, 255);"><br></span></div><div><span style="font-size: 10.5pt; line-height: 1.5; background-color: rgb(255, 255, 255);">Another confusion is raised when I observed the </span><span style="background-color: rgb(192, 192, 192); font-size: 10.5pt; line-height: 1.5;">fMaxSize</span><span style="font-size: 10.5pt; line-height: 1.5; background-color: rgb(255, 255, 255);">. The value of this variable goes down by the encoded frame size, each time after I copy the frame and call afterGetting. But it doesn't go back to the max value (seems to be 150KB, no matter how I try to override it in </span><span style="font-family: ''; font-size: 10.5pt; line-height: 1.5; background-color: window;">createNewRTPSink) next time. Only if the new frame size exceeds fMaxSize, then next time it goes back. My question is, does this mean that all those data copied to fTO is not consumed right away, thus introduced a frame buffer here?</span></div><div><br></div><div>It's a long post, thanks for your patience to read this far.</div><div><br></div><hr style="width: 210px; height: 1px;" color="#b5c4df" size="1" align="left">
<div><span><div style="MARGIN: 10px; FONT-FAMILY: verdana; FONT-SIZE: 10pt"><div style="font-family: 'Segoe UI', Tahoma; font-size: 14px; line-height: normal;"><div style="position: static !important; margin: 7.5pt;"><div style="font-family: 'Segoe UI';"><p class="MsoNormal" style="margin: 0cm 0cm 0.0001pt;"><font face="Verdana, sans-serif" size="2">Xin Liu</font></p><p class="MsoNormal" style="margin: 0cm 0cm 0.0001pt;"><font face="Verdana, sans-serif" size="2">VsceneVideo Co. Ltd.</font></p></div><div style="font-family: 'Segoe UI';"><p class="MsoNormal" style="margin: 0cm 0cm 0.0001pt;"><font face="Verdana, sans-serif" size="2"><span lang="EN-US">Mobile</span>:+86 </font><span lang="EN-US"><font face="Verdana, sans-serif" size="2">186 1245 1524<o:p></o:p></font></span></p></div><div><p class="MsoNormal" style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: 宋体;"><span lang="EN-US" style="font-size: 10pt; font-family: Verdana, sans-serif;">Email</span><span style="font-size: 10pt;">:</span><span lang="EN-US" style="font-size: 10pt; font-family: Verdana, sans-serif;"><a href="mailto:xliu@vscenevideo.com" style="text-decoration: none !important; color: purple;">xliu@vscenevideo.com</a></span></p></div></div></div></div></span></div><blockquote style="margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em;"><div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm"><div style="PADDING-RIGHT: 8px; PADDING-LEFT: 8px; FONT-SIZE: 12px;FONT-FAMILY:tahoma;COLOR:#000000; BACKGROUND: #efefef; PADDING-BOTTOM: 8px; PADDING-TOP: 8px"><div><b>From:</b> <a href="mailto:finlayson@live555.com">Ross Finlayson</a></div><div><b>Date:</b> 2017-01-11 20:04</div><div><b>To:</b> <a href="mailto:live-devel@ns.live555.com">LIVE555 Streaming Media - development & use</a></div><div><b>Subject:</b> Re: [Live-devel] how to make latency as low as possible</div></div></div><div><div>Our server software - by itself - contributes no significant latency. I suspect that most of your latency comes from the interface between your camera and our server. (You didn’t say how you are feeding your camera’s output to our server; but that’s where I would look first.)</div>
<div> </div>
<div>Ross Finlayson</div>
<div>Live Networks, Inc.</div>
<div>http://www.live555.com/</div>
<div> </div>
<div> </div>
<div>_______________________________________________</div>
<div>live-devel mailing list</div>
<div>live-devel@lists.live555.com</div>
<div>http://lists.live555.com/mailman/listinfo/live-devel</div>
</div></blockquote>
</body></html>