<div>In main.cpp </div><div>š</div><div>pthread_cond_t cond = PTHREAD_COND_INITIALIZER;<br />pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;<br /><br />void *liveMedia(void *arg)<br />{<br />ššš pthread_mutex_lock(&mutex);<br /><br />ššš H264VideoCamSource **videoSource = (H264VideoCamSource **) arg;<br /><br />ššš TaskScheduler* scheduler = BasicTaskScheduler::createNew();<br />ššš UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);<br /><br />ššš // Create the RTSP server:<br />ššš //RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);<br />ššš RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);<br />ššš if (rtspServer == NULL) {<br />ššššššš *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";<br />ššššššš exit(1);<br />ššš }<br /><br />ššš char const* descriptionString = "Session streamed by \"testOnDemandRTSPServer\"";<br />ššš {<br />ššššššš char const* streamName = "h264ESVideoTest";<br />ššššššš ServerMediaSession* sms = ServerMediaSession::createNew(*env, streamName, streamName, descriptionString);<br />ššššššš sms->addSubsession(H264VideoCamServerMediaSubsession::createNew(*env, reuseFirstSource, videoSource));<br />ššššššš rtspServer->addServerMediaSession(sms);<br /><br />ššššššš announceStream(rtspServer, sms, streamName);<br />ššš }<br /><br />ššš if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {<br />ššššššš *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";<br />ššš }<br />ššš else {<br />ššššššš *env << "\n(RTSP-over-HTTP tunneling is not available.)\n";<br />ššš }<br /><br />ššš /* Tell main thread that Live555 is ready to stream */<br />ššš if (pthread_cond_broadcast(&cond))<br />ššššššš *env << "Broadcast went wrong!\n";<br />ššš pthread_mutex_unlock(&mutex);<br /><br />ššš env->taskScheduler().doEventLoop(); // does not return<br /><br />ššš *env << "Fell off end of live555!\n";<br /><br />ššš return NULL;<br />} </div><div>š</div><div>void signalNewFrameData(H264VideoCamSource* ourDevice)<br />{<br />ššš TaskScheduler* ourScheduler = NULL; //%%% TO BE WRITTEN %%%<br />ššš ourScheduler = &(ourDevice->envir().taskScheduler());<br /><br />ššš if (ourScheduler != NULL && (ourDevice->getReferenceCount() != 0)) { // sanity check<br />ššššššš ourScheduler->triggerEvent(H264VideoCamSource::eventTriggerId, ourDevice);<br />ššš }<br />} </div><div>š</div><div>int main(int argc, char *argv[])<br />{<br />ššš H264VideoCamSource *videoSource = NULL;<br /><br />ššš pthread_t thread;<br />ššš pthread_create(&thread, NULL, liveMedia, (void *) &videoSource);<br />ššš /* Wait for Live555 to be ready to stream */<br />ššš pthread_mutex_lock(&mutex);<br />ššš pthread_cond_wait(&cond, &mutex);<br />ššš pthread_mutex_unlock(&mutex);<br /><br />ššš VideoCam videoCam(-1);<br />ššš h264encoder *encoder = new h264encoder(videoCam.get(CV_CAP_PROP_FRAME_WIDTH),<br />šššššššššššššššššššššššššššššššššššššššššš videoCam.get(CV_CAP_PROP_FRAME_HEIGHT));<br /><br />ššš int i_nals;<br />ššš x264_nal_t *nals;<br />ššš cv::Mat current_frame;<br />ššš while (1) {<br />ššššššš videoCam.read(current_frame);<br />ššššššš printf("reference = %i\n", videoSource->getReferenceCount());<br />ššššššš if (videoSource->getReferenceCount() != 0) {<br />ššššššššššš encoder->encode_frame(&current_frame, &i_nals, &nals);<br />ššššššššššš printf("encode frame\n");<br />ššššššššššš for (int i = 0; i < i_nals; i++) {<br />ššššššššššššššš printf("updateNAL[%i]\n", i);<br />ššššššššššššššš videoSource->updateNAL(&(nals[i]));<br />ššššššššššššššš printf("nals[i].i_type = %i\n", nals[i].i_type);<br />ššššššššššššššš signalNewFrameData(videoSource);</div><div>ššššššššššš }</div><div>ššššššš }<br />ššš }<br />ššš delete encoder;<br /><br />ššš return 0;<br />}</div><div>š</div><div>In my H264VideoCamSource.cpp (DeviceSource.cpp)</div><div>š</div><div>void H264VideoCamSource::updateNAL(x264_nal_t *nal)<br />{<br />ššš nalUnit = nal; //nalUnit is x264_nal_t *nalUnit pointer, member of H264VideoCamSource<br />ššš printf("nalUnit updated\n");<br />}</div><div>š</div><div>void H264VideoCamSource::deliverFrame()<br />{<br />ššš if (!isCurrentlyAwaitingData()) return; // we're not ready for the data yet<br /><br />ššš printf("deliver data\n");<br /><br />ššš u_int8_t* newFrameDataStart = (u_int8_t*)(nalUnit->p_payload + 4);<br />ššš unsigned newFrameSize = (nalUnit->i_payload - 4);<br /><br />ššš // Deliver the data here:</div><div>ššš ...<br />}</div><div>š</div><div>Output:</div><div>encode frame<br />updateNAL[0]<br />nalUnit updated<br />nals[i].i_type = 7<br />updateNAL[1]<br />nalUnit updated<br />nals[i].i_type = 8<br />updateNAL[2]<br />nalUnit updated<br />nals[i].i_type = 6<br />updateNAL[3]<br />nalUnit updated<br />nals[i].i_type = 5<br />deliver data<br />encode frame<br />updateNAL[0]</div><div>...</div><div>Gettind data is the main thread. The data is then transmitted to the object H264VideoCamSource and calling signalNewFrameData.</div><div>Apparently, in my case no thread syncronization is necessary. </div><div>06.02.2012, 02:18, "Ross Finlayson" <finlayson@live555.com>:</div><blockquote type="cite"><div><blockquote type="cite"><div>I'm creating a RTSP Server in a separate thread. My encoder (libx264) produces arrays x264 nal units. When the encoder processes the first frame it produces an array of 4 nal units. Then I pass by one unit in my DeviceSource and call signalNewFrameData every time. But it seems this separate thread does not have time to process, and rewrites them to the main thread.</div></blockquote>That last sentence makes no sense.</div><div><br /><blockquote type="cite"><div>If I need to synchronize threads, then please tell me where I need to do it.</div></blockquote></div>No, you don't need to do any 'thread synchronization'. šNote that only one of your threads - the one that contains the RTSP server - is running LIVE555 code. šThe only exception to this is that other thread(s) may call "TaskScheduler::triggerEvent()", to signal an event that the first thread (the LIVE555 thread) will then handle, within the LIVE555 event loop.<div>If this is what you are doing, then your code should work, provided, of course, that the LIVE555 thread is processing its event loop - i.e., has already called "doEventLoop()".</div><br /><br /><div><span style="border-collapse:separate;font-family:Helvetica;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-transform:none;font-size:medium;"><span style="border-collapse:separate;font-family:Helvetica;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;text-transform:none;font-size:medium;">Ross Finlayson<br />Live Networks, Inc.<br /><a href="http://www.live555.com/">http://www.live555.com/</a></span></span></div><br /><p>_______________________________________________<br />live-devel mailing list<br /><a href="mailto:live-devel@lists.live555.com">live-devel@lists.live555.com</a><br /><a href="http://lists.live555.com/mailman/listinfo/live-devel">http://lists.live555.com/mailman/listinfo/live-devel</a></p></blockquote>