[Live-devel] H264 Live Input Issue

Marcin marcin at speed666.info
Tue Dec 23 15:11:44 PST 2014


Hi,
Do you have SPS and PPS being passed from Live Input and are they okay?
Marcin

W dniu 2014-12-23 o 11:23, Shubham Goyal pisze:
> Hi all
>
> Based on the FAQ for live input, I wrote my own subclasses for 
> FramedSource and OnDemandServerMediaSubsession to implement a unicast 
> server that can stream a live input. My live input source is a H264 
> encoded frame grab of my desktop using the Nvidia GRID SDK (which 
> internally uses Nvenc.)
>
> Before passing the frames to live555 I also removed the start codes in 
> every frame and created a queue of NAL units. The first frame of every 
> stream contains 3 NALs. And a single NAL in every subsequent frame. An 
> example of the output:
>
> Start code found in frame 1
> NAL size: 24
> 67 42 C0 0D 95 A0 D3 F9 67 C0 52 83 02 03 20 00 00 7D 00 00 1D 4C 10 80
>
> Start code found in frame 1
> NAL size: 4
> 68 CE 3C 80
>
> Start code found in frame 1
> NAL size: 3228
> 65 B8 04 7F C4 44 D4 08 00 0C 07 8A 00 02 01 D3 58 0E 93 93 00 2D 11 
> F3 D9 04 BA
>  48 99 6A 65 D3 81 79 07 92 B2 95 81 1D BD CF E4 70 86 7E F1 41 B9 35 
> 76 9C 28 2
> A E6 3D 30 6A 2E C0 99 91 99 2F 22 3E FF 19 54 3B 13 4C C0 38 15 7F F2 
> 7E FB CD
> … //a lot of data, removed for readability
> 5B 5B 5B 5B 5F 6B FF FF C1 54 20 04 E7 38 40 25 29 41 C0 04 00 43 3C 
> 1C 00 40 08
>  67
>
> Start code found in frame 2 // Note: second frame here
> NAL size: 1820
> 61 E0 20 BF C6 C1 23 80 78 54 98 07 2C C0 09 50 7A A4 C0 72 CA 91 8F 
> 2D E5 00 4E
>  82 01 04 03 A1 8B 24 A2 9C B5 F1 98 E0 3E 08 0C 0A 85 00 CF 12 05 E3 
> B1 36 82 F0
>  … //a lot of data, removed for readability
>  CC 65 72 DF FF D8 83 F3 A6 53 3F C4 2E 21 71 0B 88 5C 42 E2 17 10 BF 
> 70 1C 43 2
> A 4B 03 88 65 49 6F
>
> //Third frame.. and so forth
>
> Upon playing the RTSP stream using VLC my output is blank. VLC is 
> receiving data because the seconds clock in VLC starts ticking as soon 
> as the stream is played but the output is completely blank. I tried a 
> lot of combinations in sending the data including the start codes, 
> sending individual/multiple NALs per frame, but nothing is working. I 
> was not sure if my data was correct, so I wrote it to a file (with 
> start codes) and the file played back successfully. I even streamed 
> the file using the “testOnDemandRTSPServer” test program and that 
> worked too. There is definitely something that isn’t right and I’m not 
> able to figure it out. Would appreciate if somebody could point me in 
> the right direction. I am including some of my source code below for 
> reference.
>
> Thanks,
> Shubham
>
> *——testOnDemandRTSPServer.cpp—— *
> //Live h264 based GRID stream
> //Note: This is only a part of the file, not the entire file
>   {
> char const* streamName = "grid";
>     ServerMediaSession* sms
>       = ServerMediaSession::createNew(*env, streamName, streamName,
>       descriptionString);
> sms->addSubsession(GridServerMediaSubsession::createNew(*env, 
> reuseFirstSource));
> rtspServer->addServerMediaSession(sms);
>
>     announceStream(rtspServer, sms, streamName, "no file");
>   }
> *——testOnDemandRTSPServer.cpp—— *
>
> *——GridServerMediaSubsession.cpp——*
> #include"GridServerMediaSubsession.hh"
> #include"H264VideoRTPSink.hh"
> #include"GridSource.hh"
> #include"H264VideoStreamDiscreteFramer.hh"
>
> GridServerMediaSubsession*
> GridServerMediaSubsession::createNew(UsageEnvironment& env,
>       Boolean reuseFirstSource) {
> return new GridServerMediaSubsession(env, reuseFirstSource);
> }
>
> GridServerMediaSubsession::GridServerMediaSubsession(UsageEnvironment& 
> env, Boolean reuseFirstSource)
>   : OnDemandServerMediaSubsession(env, reuseFirstSource) {
> }
>
> GridServerMediaSubsession::~GridServerMediaSubsession() {
> }
>
> FramedSource* 
> GridServerMediaSubsession::createNewStreamSource(unsigned 
> /*clientSessionId*/, unsigned& estBitrate) {
>   estBitrate = 700; // kbps, estimate
>
> // Create the video source:
>   GridSource* liveSource = GridSource::createNew(envir());
>
> // Create a framer for the Video Elementary Stream:
> return H264VideoStreamDiscreteFramer::createNew(envir(), liveSource);
> }
>
> RTPSink* GridServerMediaSubsession
> ::createNewRTPSink(Groupsock* rtpGroupsock,
> unsigned char rtpPayloadTypeIfDynamic,
>   FramedSource* /*inputSource*/) {
> return H264VideoRTPSink::createNew(envir(), rtpGroupsock, 
> rtpPayloadTypeIfDynamic);
> *——GridServerMediaSubsession.cpp——*
>
> *—— GridSource.cpp ——*
>
> GridSource*
> GridSource::createNew(UsageEnvironment& env) {
> AppArguments args; //for input configuration
> //some code removed for readability
> return new GridSource(env, args);
> }
>
> EventTriggerId GridSource::eventTriggerId = 0;
>
> unsigned GridSource::referenceCount = 0;
> unsigned GridSource::frameCount = 0;
>
> GridSource::GridSource(UsageEnvironment& env,
>   AppArguments args)
>   : FramedSource(env), fargs(args) {
> if (referenceCount == 0) {
> //encoder is initialised here. Some code removed for readability
> }
>   ++referenceCount;
>
> if (eventTriggerId == 0) {
>     eventTriggerId = 
> envir().taskScheduler().createEventTrigger(deliverFrame0);
>   }
> }
>
> GridSource::~GridSource() {
>   --referenceCount;
> if (referenceCount == 0) {
> if (encoder)
>     {
>         encoder->NvFBCH264Release();
>     }
>
> // Reclaim our 'event trigger'
> envir().taskScheduler().deleteEventTrigger(eventTriggerId);
>     eventTriggerId = 0;
>   }
> }
>
> void GridSource::doGetNextFrame() {
>
> //Note: next frame is read only after previous frame’s NALs have been 
> delivered.
> if(nalQ.isEmpty()){
>    frameCount++;
>  populateQ(); //load the NALs for each frame. NALs stored in nalQ
> }
> deliverFrame();
> }
>
> void GridSource::deliverFrame0(void* clientData) {
> ((GridSource*)clientData)->deliverFrame();
> }
>
> void GridSource::populateQ(){
> //frame is grabbed by the GRID SDK
> //NALs for every frame are pushed to nalQ
> //Some code removed for readability
>
> while(/*frame data is available in frame buffer*/){
>     if(/*star code found in frame buffer*/)
> nalQ.pushNAL(outputPtr,byteSize); //data until next start code or 
> until end of buffer - Note: data excludes start codes
>    }
>
> }
>
> void GridSource::deliverFrame() {
>
> if(!isCurrentlyAwaitingData()) return; // we're not ready for the data yet
>
>   NAL* nal = nalQ.popNAL();
>   nal->print();
>
> // Deliver the data here:
> if (nal->getSize() > fMaxSize) {
>     fFrameSize = fMaxSize;
>     fNumTruncatedBytes = nal->getSize() - fMaxSize;
>   } else {
>     fFrameSize = nal->getSize();
>   }
>   gettimeofday(&fPresentationTime, NULL);
>
>   fDurationInMicroseconds = 1000000/30; //30 fps
>   memmove(fTo, nal->getPayload(), fFrameSize);
>
> // After delivering the data, inform the reader that it is now available:
>   FramedSource::afterGetting(this);
> }
>
> *——GridSource.cpp—— *
>
>
>
> _______________________________________________
> live-devel mailing list
> live-devel at lists.live555.com
> http://lists.live555.com/mailman/listinfo/live-devel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20141224/79e8fbb1/attachment-0001.html>


More information about the live-devel mailing list