[Live-devel] H264VideoStreamFramer

malc av1474 at comtv.ru
Sat Sep 15 11:14:02 PDT 2012


On Thu, 13 Sep 2012, malc wrote:

> On Wed, 12 Sep 2012, Ross Finlayson wrote:
> 
> > >            framer = H264VideoStreamFramer::createNew
> > >                (*env, subsession->readSource (), True/*includeStartCodeInOutput*/);
> > > 
> > >            MPEG2TransportStreamFromESSource* tsFrames =
> > >                MPEG2TransportStreamFromESSource::createNew (*env);
> > >            tsFrames->addNewVideoSource(framer, 5/*mpegVersion: H.264*/);
> > 

[..snip..]

> > 
> > Instead, *in principle*, you could just feed
> > "subsession->readSource()" directly into your
> > "MPEG2TransportStreamFromESSource" (via the "addNewVideoSource()"
> > call).  Unfortunately, however, there's a problem with this: The
> > H.264 NAL units that come from the RTP source (i.e., from
> > "subsession->readSource()") do not have a 4-byte 'start code' (i.e.,
> > 0x00 0x00 0x00 0x01) at the front, but that data that you feed into
> > a "MPEG2TransportStreamFromESSource" needs to have these start
> > codes.
> > 
> > Therefore, you will need to write your own subclass of
> > "FramedFilter" that adds a 4-byte 'start code' to each input frame,
> > and use an instance of this class - instead of
> > "H264VideoStreamFramer" - in front of "subsession->readSource()".
> > 

"Did" that:

struct AddStartCodes : FramedFilter {
    Boolean fHaveWrittenFirstFrame;
    const char *fSPropParameterSetsStr;
    unsigned char *mbuf;
    unsigned mlen;

    AddStartCodes (UsageEnvironment *env, FramedSource *source,
                   const char *sPropParameterSetsStr)
        : FramedFilter (*env, source)
        , fHaveWrittenFirstFrame (False)
        , fSPropParameterSetsStr (sPropParameterSetsStr)
        , mbuf (NULL)
        , mlen (0)
    {
    }

    void addData (const void *buf, size_t size)
    {
        mbuf = (unsigned char *) realloc (mbuf, mlen + size);
        if (!mbuf) die ("realloc %u", mlen);

        memcpy (mbuf + mlen, buf, size);
        mlen += size;
    }

    void flush (unsigned frameSize)
    {
        memmove (fTo + mlen, fTo, frameSize);
        memcpy (fTo, mbuf, mlen);
        fFrameSize = frameSize + mlen;
        mlen = 0;
    }

    void afterGettingFrame1 (unsigned frameSize,
                             unsigned numTruncatedBytes,
                             struct timeval presentationTime,
                             unsigned durationInMicroseconds)
    {
        const unsigned char start_code[4] = {0,0,0,1};
        if (!fHaveWrittenFirstFrame) {
            unsigned numSPropRecords;
            SPropRecord* sPropRecords = parseSPropParameterSets(fSPropParameterSetsStr,
                                                                numSPropRecords);
            for (unsigned i = 0; i < numSPropRecords; ++i) {
                addData (start_code, 4);
                addData (sPropRecords[i].sPropBytes, sPropRecords[i].sPropLength);
            }
            delete[] sPropRecords;
            fHaveWrittenFirstFrame = True; // for next time
        }

        addData (start_code, 4);
        flush (frameSize);
    }

    static void afterGettingFrame (void* clientData, unsigned frameSize,
                                   unsigned numTruncatedBytes,
                                   struct timeval presentationTime,
                                   unsigned durationInMicroseconds)
    {
        AddStartCodes *asc = (AddStartCodes *) clientData;
        asc->afterGettingFrame1 (frameSize, numTruncatedBytes,
                                 presentationTime, durationInMicroseconds);
        asc->fNumTruncatedBytes = numTruncatedBytes;
        asc->fPresentationTime = presentationTime;
        asc->fDurationInMicroseconds = durationInMicroseconds;
        FramedSource::afterGetting (asc);
    }

    virtual void doGetNextFrame ()
    {
        fInputSource->getNextFrame (fTo, fMaxSize,
                                    afterGettingFrame, this,
                                    FramedSource::handleClosure, this);
    }
};

However most players[1] are not able to successfully munch the output,
those that can't even barf on the out.ts output of
testH264VideoToTransportStream (atleast) when in.264 is just a copy of
src13_hrc7_525_420_2.264 url to which was given in the original post)

[1] mplayer with "native" demuxer (-demuxer lavf works)
    PlayStation3

-- 
mailto:av1474 at comtv.ru


More information about the live-devel mailing list