[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