"No, you don’t ‘set’ “fTo” to point to the data; you *copy* the data to the address pointed to by “fTo”"
Yes, you are correct. I was using "loosey goosey" terminology here. Specifically, I do something like this: memmove(fTo, nal.p_payload ...... A bit more details on the crash I'm encountering. First, it's not really a "crash" in that the server dies. It appears to be a C++ exception that is being fired and handled somewhere (I get a notification of it in my development environment). But since my streaming server isn't streaming the file (according to VLC, no bytes are being received), I assume there's something wrong somewhere. This makes me suspicious of the fact I am NOT prepending the NAL units with 0x0 0x0 0x0 0x1 as you described. However, I'm a bit confused as to why my live streaming code is working, then, as I'm not explicitly doing that from within it. Here is the code that's popping a NAL unit off a queue I'm building and writing it onto fTo. This is for my LIVE streaming server and it's working just fine and is in production. I found the code for doing the "truncation" business online and it's worked great for us; admittedly I didn't understand it too well. ...... x264_nal_t nal = this->_nalQueue.front(); this->_nalQueue.pop(); assert(nal.p_payload != NULL); // You need to remove the start code which is there in front of every nal unit. // the start code might be 0x00000001 or 0x000001. so detect it and remove it. pass remaining data to live555 int trancate = 0; if (nal.i_payload >= 4 && nal.p_payload[0] == 0 && nal.p_payload[1] == 0 && nal.p_payload[2] == 0 && nal.p_payload[3] == 1) { trancate = 4; } else { if (nal.i_payload >= 3 && nal.p_payload[0] == 0 && nal.p_payload[1] == 0 && nal.p_payload[2] == 1) { trancate = 3; } } if (nal.i_payload - trancate > fMaxSize) { fFrameSize = fMaxSize; fNumTruncatedBytes = nal.i_payload - trancate - fMaxSize; } else { fFrameSize = nal.i_payload - trancate; } //http://comments.gmane.org/gmane.comp.multimedia.live555.devel/4930 // http://stackoverflow.com/questions/13863673/how-to-write-a-live555-framedsource-to-allow-me-to-stream-h-264-live timeval lastPresentationTime = fPresentationTime; fPresentationTime = this->_time; if (newData) { fDurationInMicroseconds = 1000000 / m_fps; // 66000; } else { fDurationInMicroseconds = 0; } memmove(fTo, nal.p_payload + trancate, fFrameSize); ..... And this is the stack for the exception that does occur (again, this exception DOES NOT happen in the live streaming code, only when trying to stream a static file). As you can see, it's within the call to getAuxSDPLine. I notice "test4Bytes" which makes me think it's related to this prepending of 0x0 0x0 0x0 0x1? ManagedStreamingServerLibrary.dll!StreamParser::ensureValidBytes1(unsigned int) C++ ManagedStreamingServerLibrary.dll!StreamParser::ensureValidBytes(unsigned int) C++ ManagedStreamingServerLibrary.dll!StreamParser::test4Bytes(void) C++ ManagedStreamingServerLibrary.dll!H264or5VideoStreamParser::parse(void) C++ ManagedStreamingServerLibrary.dll!MPEGVideoStreamFramer::continueReadProcessing(void) C++ ManagedStreamingServerLibrary.dll!MPEGVideoStreamFramer::doGetNextFrame(void) C++ ManagedStreamingServerLibrary.dll!FramedSource::getNextFrame(unsigned char *,unsigned int,void (*)(void *,unsigned int,unsigned int,struct timeval,unsigned int),void *,void (*)(void *),void *) C++ ManagedStreamingServerLibrary.dll!H264or5Fragmenter::doGetNextFrame(void) C++ ManagedStreamingServerLibrary.dll!FramedSource::getNextFrame(unsigned char *,unsigned int,void (*)(void *,unsigned int,unsigned int,struct timeval,unsigned int),void *,void (*)(void *),void *) C++ ManagedStreamingServerLibrary.dll!MultiFramedRTPSink::packFrame(void) C++ ManagedStreamingServerLibrary.dll!MultiFramedRTPSink::buildAndSendPacket(bool) C++ ManagedStreamingServerLibrary.dll!MultiFramedRTPSink::continuePlaying(void) C++ ManagedStreamingServerLibrary.dll!H264or5VideoRTPSink::continuePlaying(void) C++ ManagedStreamingServerLibrary.dll!MediaSink::startPlaying(class MediaSource &,void (*)(void *),void *) C++ > ManagedStreamingServerLibrary.dll!OCVFileServerMediaSubsession::getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource) Line 99 C++ At any rate, I tried modifying the code that moves the data to fTo to include 0x0 0x0 0x0 0x1 and I'm still seeing these exceptions. fFrameSize += 4; fTo[0] = 0x0; fTo[1] = 0x0; fTo[2] = 0x0; fTo[3] = 0x1; memmove(fTo + 4, nal.p_payload + trancate, fFrameSize); Any thoughts? Something is wonky, but I'm having a helluva time tracking it down. On Thu, Apr 6, 2017 at 3:02 PM Ross Finlayson <finlay...@live555.com> wrote: > > FramedSource* > OCVFileServerMediaSubsession::createNewStreamSource(unsigned > /*clientSessionId*/, unsigned& estBitrate) { > > estBitrate = 90000; // kbps, estimate > > > > // Create the video source: > > { > > std::ifstream in(fFileName, std::ifstream::ate | > std::ifstream::binary); > > fFileSize = in.tellg(); > > } > > > > OCVFileSource* fileSource = OCVFileSource::createNew(envir(), > fFileName); > > if (fileSource == NULL) return NULL; > > > > // Create a framer for the Video Elementary Stream: > > return H264VideoStreamFramer::createNew(envir(), fileSource); > > } > > This is correct, *provided that* your “OCVFileSource” delivers a stream of > H.264 NAL units, each prepended with a 4-byte ‘start code’ (0x00 0x00 0x00 > 0x01). (That’s because the downstream ‘framer’ object - > “H264VideoStreamFramer” - expects a stream of NAL units in this format.) > > > > Then within OCVFileSource::doGetNextFrame() I use our own special file > reader to get a frame from the OCV file and I use lib x264 to encode it > into a group of NAL units (much like I do with our live camera solution). > > Again, each NAL unit in this ‘group of NAL units’ needs to be prepended > with a (0x00 0x00 0x00 0x01) ‘start code’. > > > I then set "fTo" with the encoded data > > No, you don’t ‘set’ “fTo” to point to the data; you *copy* the data to the > address pointed to by “fTo”. You should also check the size of the data > against “fMaxSize” (and then set “fFrameSize” and “fNumTruncatedBytes” as > appropriate). > > I.e., you do something like this: > if (myDataSize > fMaxSize) { > fFrameSize = fMaxSize; > fNumTruncatedBytes = newFrameSize - fMaxSize; > } else { > fFrameSize = myDataSize; > } > memmove(fTo, myDataPointer, fFrameSize); > > Note that, in your case, you don’t need to set “fPresentationTime” or > “fDurationInMicroseconds”; those will be computed by the downstream > “H264VideoStreamFramer” object instead. > > > > and call > > > > nextTask() = envir().taskScheduler().scheduleDelayedTask(0, > > (TaskFunc*)FramedSource::afterGetting, this); > > > > to reschedule another call to doGetNextFrame(). > > This will work. However, in your case you could replace this with: > FramedSource::afterGetting(this); > which is more efficient. (You can do this because you’re streaming to a > network, rather than to a file. The downstream ‘RTPSink’ object will - > after transmitting a RTP packet - return to the event loop, so you won’t > get infinite recursion.) > > > Ross Finlayson > Live Networks, Inc. > http://www.live555.com/ > > > _______________________________________________ > live-devel mailing list > live-devel@lists.live555.com > http://lists.live555.com/mailman/listinfo/live-devel >
_______________________________________________ live-devel mailing list live-devel@lists.live555.com http://lists.live555.com/mailman/listinfo/live-devel