[x265] [PATCH] Encoder: do not use std::list for the class AccessUnit
Steve Borho
steve at borho.org
Tue Sep 24 18:26:50 CEST 2013
On Tue, Sep 24, 2013 at 6:56 AM, Gopu Govindaswamy <
gopu at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Gopu Govindaswamy <gopu at multicorewareinc.com>
> # Date 1380019510 -19800
> # Node ID 70ba2b3b7bc972ed04f5fd135d940e4759315fa8
> # Parent a8f6f62217d5e519f99a004c420e5906ac900f2f
> Encoder: do not use std::list for the class AccessUnit
>
I've queued this for default after making a number of fixes
>
> diff -r a8f6f62217d5 -r 70ba2b3b7bc9 source/Lib/TLibEncoder/TEncTop.cpp
> --- a/source/Lib/TLibEncoder/TEncTop.cpp Tue Sep 24 14:22:02 2013
> +0530
> +++ b/source/Lib/TLibEncoder/TEncTop.cpp Tue Sep 24 16:15:10 2013
> +0530
> @@ -114,14 +114,16 @@
> for (int i = 0; i < param.frameNumThreads; i++)
> {
> // Ensure frame encoder is idle before destroying it
> - AccessUnit tmp;
> - m_frameEncoder[i].getEncodedPicture(tmp);
> - for (AccessUnit::const_iterator it = tmp.begin(); it !=
> tmp.end(); it++)
> + NALUnitEBSP **nalunits = NULL;
> + m_frameEncoder[i].getEncodedPicture(nalunits);
>
This will crash; getEncodedPicture() does not expect nalunits to be NULL
> + if (nalunits)
> {
> - const NALUnitEBSP& nalu = **it;
> - free(nalu.m_nalUnitData);
> + for (int nalcount = 0; nalunits[nalcount] != NULL;
> nalcount++)
> + {
> + const NALUnitEBSP& nalu = *nalunits[nalcount];
> + free(nalu.m_nalUnitData);
>
wouldn't this leak nalu itself?
> + }
> }
> -
> m_frameEncoder[i].destroy();
> }
>
> @@ -161,9 +163,9 @@
> }
> }
>
> -int TEncTop::getStreamHeaders(AccessUnit& accessUnit)
> +int TEncTop::getStreamHeaders(NALUnitEBSP **nalunits)
> {
> - return m_frameEncoder->getStreamHeaders(accessUnit);
> + return m_frameEncoder->getStreamHeaders(nalunits);
> }
>
> /**
> @@ -173,7 +175,7 @@
> \param accessUnitsOut output bitstream
> \retval number of encoded pictures
> */
> -int TEncTop::encode(bool flush, const x265_picture_t* pic_in,
> x265_picture_t *pic_out, AccessUnit& accessUnitOut)
> +int TEncTop::encode(bool flush, const x265_picture_t* pic_in,
> x265_picture_t *pic_out, NALUnitEBSP **nalunits)
> {
> if (pic_in)
> {
> @@ -213,7 +215,7 @@
> // getEncodedPicture() should block until the FrameEncoder has
> completed
> // encoding the frame. This is how back-pressure through the API is
> // accomplished when the encoder is full.
> - TComPic *out = curEncoder->getEncodedPicture(accessUnitOut);
> + TComPic *out = curEncoder->getEncodedPicture(nalunits);
>
> if (!out && flush)
> {
> @@ -227,7 +229,7 @@
> {
> curEncoder = &m_frameEncoder[m_curEncoder];
> m_curEncoder = (m_curEncoder + 1) % param.frameNumThreads;
> - out = curEncoder->getEncodedPicture(accessUnitOut);
> + out = curEncoder->getEncodedPicture(nalunits);
> }
> while (!out && flushed != m_curEncoder);
> }
> @@ -259,7 +261,7 @@
> pic_out->stride[2] = recpic->getCStride();
> }
>
> - double bits = calculateHashAndPSNR(out, accessUnitOut);
> + double bits = calculateHashAndPSNR(out, nalunits);
> // Allow this frame to be recycled if no frame encoders are using
> it for reference
> ATOMIC_DEC(&out->m_countRefEncoders);
>
> @@ -487,7 +489,7 @@
>
> /* Returns Number of bits in current encoded pic */
>
> -double TEncTop::calculateHashAndPSNR(TComPic* pic, AccessUnit& accessUnit)
> +double TEncTop::calculateHashAndPSNR(TComPic* pic, NALUnitEBSP **nalunits)
> {
> TComPicYuv* recon = pic->getPicYuvRec();
> TComPicYuv* orig = pic->getPicYuvOrg();
> @@ -544,7 +546,10 @@
> m_frameEncoder->m_seiWriter.writeSEImessage(onalu.m_Bitstream,
> sei_recon_picture_digest, pic->getSlice()->getSPS());
> writeRBSPTrailingBits(onalu.m_Bitstream);
>
> - accessUnit.insert(accessUnit.end(), new NALUnitEBSP(onalu));
> + int count = 0;
> + while(nalunits[count] != NULL)
> + count++;
>
this is missing a malloc, nalunits[count] is NULL (as Aarthi also
discovered)
> + nalunits[count]->init(onalu);
> }
>
> /* calculate the size of the access unit, excluding:
> @@ -552,13 +557,14 @@
> * - SEI NAL units
> */
> UInt numRBSPBytes = 0;
> - for (AccessUnit::const_iterator it = accessUnit.begin(); it !=
> accessUnit.end(); it++)
> + int count = 0;
> + for (;nalunits[count] != NULL; count++)
> {
> - UInt numRBSPBytes_nal = (*it)->m_packetSize;
> + UInt numRBSPBytes_nal = nalunits[count]->m_packetSize;
> #if VERBOSE_RATE
> printf("*** %6s numBytesInNALunit: %u\n",
> nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal);
> #endif
> - if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI &&
> (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI)
> + if (nalunits[count]->m_nalUnitType != NAL_UNIT_PREFIX_SEI &&
> nalunits[count]->m_nalUnitType != NAL_UNIT_SUFFIX_SEI)
> {
> numRBSPBytes += numRBSPBytes_nal;
> }
> diff -r a8f6f62217d5 -r 70ba2b3b7bc9 source/Lib/TLibEncoder/TEncTop.h
> --- a/source/Lib/TLibEncoder/TEncTop.h Tue Sep 24 14:22:02 2013 +0530
> +++ b/source/Lib/TLibEncoder/TEncTop.h Tue Sep 24 16:15:10 2013 +0530
> @@ -101,9 +101,9 @@
> void xInitSPS(TComSPS *sps);
> void xInitPPS(TComPPS *pps);
>
> - int encode(bool bEos, const x265_picture_t* pic, x265_picture_t
> *pic_out, AccessUnit& accessUnit);
> + int encode(bool bEos, const x265_picture_t* pic, x265_picture_t
> *pic_out, NALUnitEBSP **nalunits);
>
> - int getStreamHeaders(AccessUnit& accessUnit);
> + int getStreamHeaders(NALUnitEBSP **nalunits);
>
> double printSummary();
>
> @@ -113,7 +113,7 @@
>
> protected:
>
> - double calculateHashAndPSNR(TComPic* pic, AccessUnit&); // Returns
> total number of bits for encoded pic
> + double calculateHashAndPSNR(TComPic* pic, NALUnitEBSP **nalunits); //
> Returns total number of bits for encoded pic
> };
> }
> //! \}
> diff -r a8f6f62217d5 -r 70ba2b3b7bc9 source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp Tue Sep 24 14:22:02 2013 +0530
> +++ b/source/encoder/encoder.cpp Tue Sep 24 16:15:10 2013 +0530
> @@ -47,7 +47,7 @@
>
> void configure(x265_param_t *param);
> void determineLevelAndProfile(x265_param_t *param);
> - int extract_naldata(AccessUnit &au, size_t &nalcount);
> + int extract_naldata(NALUnitEBSP **nalunits, size_t &nalcount);
> };
>
> x265_t::x265_t()
> @@ -364,19 +364,18 @@
> if (!pp_nal)
> return 0;
>
> - AccessUnit au;
> - if (!encoder->getStreamHeaders(au))
> + NALUnitEBSP *nalunits[5] = {0, 0, 0, 0, 0};
>
this should use MAX_NAL_UNITS
> + if (!encoder->getStreamHeaders(nalunits))
> {
> size_t nalcount;
> - if (!encoder->extract_naldata(au, nalcount))
> + if (!encoder->extract_naldata(nalunits, nalcount))
> {
> *pp_nal = &encoder->m_nals[0];
> if (pi_nal) *pi_nal = (int)nalcount;
> - for (AccessUnit::const_iterator t = au.begin(); t !=
> au.end(); t++)
> + for (nalcount = 0; nalcount < MAX_NAL_UNITS; nalcount++)
> {
> - X265_FREE(*t);
> + X265_FREE(nalunits[nalcount]);
>
isn't this leaking nalunits[nalcount].m_nalUnitData?
> }
> - au.clear();
> return 0;
> }
> return -1;
> @@ -388,17 +387,21 @@
> extern "C"
> int x265_encoder_encode(x265_t *encoder, x265_nal_t **pp_nal, int
> *pi_nal, x265_picture_t *pic_in, x265_picture_t *pic_out)
> {
> - AccessUnit au;
> -
> - int numEncoded = encoder->encode(!pic_in, pic_in, pic_out, au);
> + NALUnitEBSP *nalunits[5] = {0, 0, 0, 0, 0};
>
should use MAX_NAL_UNITS
> + int numEncoded = encoder->encode(!pic_in, pic_in, pic_out, nalunits);
>
> if (pp_nal && numEncoded)
> {
> size_t nalcount;
> - encoder->extract_naldata(au, nalcount);
> + encoder->extract_naldata(nalunits, nalcount);
>
> *pp_nal = &encoder->m_nals[0];
> if (pi_nal) *pi_nal =(int) nalcount;
> +
> + for (nalcount = 0; nalcount < MAX_NAL_UNITS; nalcount++)
> + {
> + X265_FREE(nalunits[nalcount]);
> + }
>
this could leak memory if a malloc failed after some of them succeeded.
> }
> else if (pi_nal)
> *pi_nal = 0;
> @@ -428,19 +431,18 @@
> BitCost::destroy();
> }
>
> -int x265_t::extract_naldata(AccessUnit &au, size_t &nalcount)
> +int x265_t::extract_naldata(NALUnitEBSP **nalunits, size_t &nalcount)
> {
> uint32_t memsize = 0;
> uint32_t offset = 0;
>
> nalcount = 0;
> - for (AccessUnit::const_iterator t = au.begin(); t != au.end(); t++)
> + for (; nalunits[nalcount] != NULL; nalcount++)
> {
> - const NALUnitEBSP& temp = **t;
> + const NALUnitEBSP& temp = *nalunits[nalcount];
> memsize += temp.m_packetSize + 4;
> - nalcount++;
> }
> -
> +
> X265_FREE(m_packetData);
> X265_FREE(m_nals);
> CHECKED_MALLOC(m_packetData, char, memsize);
> @@ -450,13 +452,13 @@
> memsize = 0;
>
> /* Copy NAL output packets into x265_nal_t structures */
> - for (AccessUnit::const_iterator it = au.begin(); it != au.end(); it++)
> + for (; nalunits[nalcount] != NULL; nalcount++)
> {
> - const NALUnitEBSP& nalu = **it;
> + const NALUnitEBSP& nalu = *nalunits[nalcount];
> uint32_t size = 0; /* size of annexB unit in bytes */
>
> static const char start_code_prefix[] = { 0, 0, 0, 1 };
> - if (it == au.begin() || nalu.m_nalUnitType == NAL_UNIT_SPS ||
> nalu.m_nalUnitType == NAL_UNIT_PPS)
> + if (nalcount == 0 || nalu.m_nalUnitType == NAL_UNIT_SPS ||
> nalu.m_nalUnitType == NAL_UNIT_PPS)
> {
> /* From AVC, When any of the following conditions are
> fulfilled, the
> * zero_byte syntax element shall be present:
> @@ -482,7 +484,6 @@
>
> m_nals[nalcount].i_type = nalu.m_nalUnitType;
> m_nals[nalcount].i_payload = size;
> - nalcount++;
> free(nalu.m_nalUnitData);
> }
>
> diff -r a8f6f62217d5 -r 70ba2b3b7bc9 source/encoder/frameencoder.cpp
> --- a/source/encoder/frameencoder.cpp Tue Sep 24 14:22:02 2013 +0530
> +++ b/source/encoder/frameencoder.cpp Tue Sep 24 16:15:10 2013 +0530
> @@ -55,7 +55,11 @@
> , m_cfg(NULL)
> , m_pic(NULL)
> , m_rows(NULL)
> -{}
> +{
> + for (int i = 0; i < 5; i++)
> + m_accessUnit[i] = NULL;
> + m_nalcount = 0;
> +}
>
> void FrameEncoder::setThreadPool(ThreadPool *p)
> {
> @@ -158,12 +162,11 @@
> start();
> }
>
> -int FrameEncoder::getStreamHeaders(AccessUnit& accessUnit)
> +int FrameEncoder::getStreamHeaders(NALUnitEBSP **nalunits)
> {
> TEncEntropy* entropyCoder = getEntropyCoder(0);
>
> entropyCoder->setEntropyCoder(&m_cavlcCoder, NULL);
> - NALUnitEBSP *tmp[MAX_NAL_UNITS] = {0, 0, 0, 0, 0};
> int count = 0;
>
> /* headers for start of bitstream */
> @@ -171,27 +174,24 @@
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> entropyCoder->encodeVPS(m_cfg->getVPS());
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - CHECKED_MALLOC(tmp[count], NALUnitEBSP, 1);
> - tmp[count]->init(nalu);
> - accessUnit.push_back(tmp[count]);
> + CHECKED_MALLOC(nalunits[count], NALUnitEBSP, 1);
> + nalunits[count]->init(nalu);
> count++;
>
> nalu = NALUnit(NAL_UNIT_SPS);
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> entropyCoder->encodeSPS(&m_sps);
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - CHECKED_MALLOC(tmp[count], NALUnitEBSP, 1);
> - tmp[count]->init(nalu);
> - accessUnit.push_back(tmp[count]);
> + CHECKED_MALLOC(nalunits[count], NALUnitEBSP, 1);
> + nalunits[count]->init(nalu);
> count++;
>
> nalu = NALUnit(NAL_UNIT_PPS);
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> entropyCoder->encodePPS(&m_pps);
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - CHECKED_MALLOC(tmp[count], NALUnitEBSP, 1);
> - tmp[count]->init(nalu);
> - accessUnit.push_back(tmp[count]);
> + CHECKED_MALLOC(nalunits[count], NALUnitEBSP, 1);
> + nalunits[count]->init(nalu);
> count++;
>
> if (m_cfg->getActiveParameterSetsSEIEnabled())
> @@ -206,9 +206,8 @@
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei, &m_sps);
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - CHECKED_MALLOC(tmp[count], NALUnitEBSP, 1);
> - tmp[count]->init(nalu);
> - accessUnit.push_back(tmp[count]);
> + CHECKED_MALLOC(nalunits[count], NALUnitEBSP, 1);
> + nalunits[count]->init(nalu);
> count++;
> }
>
> @@ -224,9 +223,8 @@
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei, &m_sps);
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - CHECKED_MALLOC(tmp[count], NALUnitEBSP, 1);
> - tmp[count]->init(nalu);
> - accessUnit.push_back(tmp[count]);
> + CHECKED_MALLOC(nalunits[count], NALUnitEBSP, 1);
> + nalunits[count]->init(nalu);
> }
> return 0;
>
> @@ -294,7 +292,7 @@
> void FrameEncoder::compressFrame()
> {
> PPAScopeEvent(FrameEncoder_compressFrame);
> -
> + m_nalcount = 0;
> TEncEntropy* entropyCoder = getEntropyCoder(0);
> TComSlice* slice = m_pic->getSlice();
>
> @@ -476,7 +474,7 @@
> }
>
> m_wp.xRestoreWPparam(slice);
> -
> + OutputNALUnit nalu(slice->getNalUnitType(), 0);
> if ((m_cfg->getRecoveryPointSEIEnabled()) && (slice->getSliceType()
> == I_SLICE))
> {
> if (m_cfg->getGradualDecodingRefreshInfoEnabled() &&
> !slice->getRapPicFlag())
> @@ -489,7 +487,9 @@
>
> m_seiWriter.writeSEImessage(nalu.m_Bitstream,
> seiGradualDecodingRefreshInfo, slice->getSPS());
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - m_accessUnit.push_back(new NALUnitEBSP(nalu));
> + CHECKED_MALLOC(m_accessUnit[m_nalcount], NALUnitEBSP, 1);
> + m_accessUnit[m_nalcount]->init(nalu);
> + m_nalcount++;
> }
> // Recovery point SEI
> OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI);
> @@ -501,7 +501,9 @@
>
> m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_recovery_point,
> slice->getSPS());
> writeRBSPTrailingBits(nalu.m_Bitstream);
> - m_accessUnit.push_back(new NALUnitEBSP(nalu));
> + CHECKED_MALLOC(m_accessUnit[m_nalcount], NALUnitEBSP, 1);
> + m_accessUnit[m_nalcount]->init(nalu);
> + m_nalcount++;
> }
>
> /* use the main bitstream buffer for storing the marshaled picture */
> @@ -535,7 +537,6 @@
> entropyCoder->resetEntropy();
>
> /* start slice NALunit */
> - OutputNALUnit nalu(slice->getNalUnitType(), 0);
> bool sliceSegment = !slice->isNextSlice();
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> entropyCoder->encodeSliceHeader(slice);
> @@ -635,8 +636,9 @@
> }
> entropyCoder->setBitstream(&nalu.m_Bitstream);
> bitstreamRedirect->clear();
> -
> - m_accessUnit.push_back(new NALUnitEBSP(nalu));
> + CHECKED_MALLOC(m_accessUnit[m_nalcount], NALUnitEBSP, 1);
> + m_accessUnit[m_nalcount]->init(nalu);
> + m_nalcount++;
>
> if (m_sps.getUseSAO())
> {
> @@ -658,6 +660,8 @@
> }
> }
>
> +fail:
> +
> delete[] outStreams;
> delete bitstreamRedirect;
> }
> @@ -1001,7 +1005,7 @@
> }
> }
>
> -TComPic *FrameEncoder::getEncodedPicture(AccessUnit& accessUnit)
> +TComPic *FrameEncoder::getEncodedPicture(NALUnitEBSP **nalunits)
> {
> if (m_pic)
> {
> @@ -1011,8 +1015,8 @@
> TComPic *ret = m_pic;
> m_pic = NULL;
>
> - // move NALs from member variable list to end of user's container
> - accessUnit.splice(accessUnit.end(), m_accessUnit);
> + // move NALs from member variable to end of user's container
> + ::memcpy(nalunits, m_accessUnit, sizeof(NALUnitEBSP) *
> m_nalcount);
>
the length of the memcpy should be: sizeof(NALUnitEBSP*) * m_nalcount
> return ret;
> }
>
> diff -r a8f6f62217d5 -r 70ba2b3b7bc9 source/encoder/frameencoder.h
> --- a/source/encoder/frameencoder.h Tue Sep 24 14:22:02 2013 +0530
> +++ b/source/encoder/frameencoder.h Tue Sep 24 16:15:10 2013 +0530
> @@ -135,7 +135,7 @@
> }
> }
>
> - int getStreamHeaders(AccessUnit& accessUnitOut);
> + int getStreamHeaders(NALUnitEBSP **nalunits);
>
> void initSlice(TComPic* pic);
>
> @@ -148,7 +148,7 @@
> void encodeSlice(TComOutputBitstream* substreams);
>
> /* blocks until worker thread is done, returns encoded picture and
> bitstream */
> - TComPic *getEncodedPicture(AccessUnit& accessUnit);
> + TComPic *getEncodedPicture(NALUnitEBSP **nalunits);
>
> // worker thread
> void threadMain();
> @@ -178,7 +178,8 @@
>
> /* Picture being encoded, and its output NAL list */
> TComPic* m_pic;
> - AccessUnit m_accessUnit;
> + NALUnitEBSP *m_accessUnit[5];
> + int m_nalcount;
>
> int m_numRows;
> int m_filterRowDelay;
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
--
Steve Borho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20130924/b75a37b5/attachment-0001.html>
More information about the x265-devel
mailing list