forked from mirror/libbpg
libbpg-0.9.6
This commit is contained in:
parent
3035b41edf
commit
35a8402710
248 changed files with 232891 additions and 100 deletions
232
x265/source/encoder/nal.cpp
Normal file
232
x265/source/encoder/nal.cpp
Normal file
|
@ -0,0 +1,232 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (C) 2013 x265 project
|
||||
*
|
||||
* Authors: Steve Borho <steve@borho.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
|
||||
*
|
||||
* This program is also available under a commercial proprietary license.
|
||||
* For more information, contact us at license @ x265.com.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "bitstream.h"
|
||||
#include "nal.h"
|
||||
|
||||
using namespace X265_NS;
|
||||
|
||||
NALList::NALList()
|
||||
: m_numNal(0)
|
||||
, m_buffer(NULL)
|
||||
, m_occupancy(0)
|
||||
, m_allocSize(0)
|
||||
, m_extraBuffer(NULL)
|
||||
, m_extraOccupancy(0)
|
||||
, m_extraAllocSize(0)
|
||||
, m_annexB(true)
|
||||
{}
|
||||
|
||||
void NALList::takeContents(NALList& other)
|
||||
{
|
||||
/* take other NAL buffer, discard our old one */
|
||||
X265_FREE(m_buffer);
|
||||
m_buffer = other.m_buffer;
|
||||
m_allocSize = other.m_allocSize;
|
||||
m_occupancy = other.m_occupancy;
|
||||
|
||||
/* copy packet data */
|
||||
m_numNal = other.m_numNal;
|
||||
memcpy(m_nal, other.m_nal, sizeof(x265_nal) * m_numNal);
|
||||
|
||||
/* reset other list, re-allocate their buffer with same size */
|
||||
other.m_numNal = 0;
|
||||
other.m_occupancy = 0;
|
||||
other.m_buffer = X265_MALLOC(uint8_t, m_allocSize);
|
||||
}
|
||||
|
||||
void NALList::serialize(NalUnitType nalUnitType, const Bitstream& bs)
|
||||
{
|
||||
static const char startCodePrefix[] = { 0, 0, 0, 1 };
|
||||
|
||||
uint32_t payloadSize = bs.getNumberOfWrittenBytes();
|
||||
const uint8_t* bpayload = bs.getFIFO();
|
||||
if (!bpayload)
|
||||
return;
|
||||
|
||||
uint32_t nextSize = m_occupancy + sizeof(startCodePrefix) + 2 + payloadSize + (payloadSize >> 1) + m_extraOccupancy;
|
||||
if (nextSize > m_allocSize)
|
||||
{
|
||||
uint8_t *temp = X265_MALLOC(uint8_t, nextSize);
|
||||
if (temp)
|
||||
{
|
||||
memcpy(temp, m_buffer, m_occupancy);
|
||||
|
||||
/* fixup existing payload pointers */
|
||||
for (uint32_t i = 0; i < m_numNal; i++)
|
||||
m_nal[i].payload = temp + (m_nal[i].payload - m_buffer);
|
||||
|
||||
X265_FREE(m_buffer);
|
||||
m_buffer = temp;
|
||||
m_allocSize = nextSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
x265_log(NULL, X265_LOG_ERROR, "Unable to realloc access unit buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *out = m_buffer + m_occupancy;
|
||||
uint32_t bytes = 0;
|
||||
|
||||
if (!m_annexB)
|
||||
{
|
||||
/* Will write size later */
|
||||
bytes += 4;
|
||||
}
|
||||
else if (!m_numNal || nalUnitType == NAL_UNIT_VPS || nalUnitType == NAL_UNIT_SPS || nalUnitType == NAL_UNIT_PPS)
|
||||
{
|
||||
memcpy(out, startCodePrefix, 4);
|
||||
bytes += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(out, startCodePrefix + 1, 3);
|
||||
bytes += 3;
|
||||
}
|
||||
|
||||
/* 16 bit NAL header:
|
||||
* forbidden_zero_bit 1-bit
|
||||
* nal_unit_type 6-bits
|
||||
* nuh_reserved_zero_6bits 6-bits
|
||||
* nuh_temporal_id_plus1 3-bits */
|
||||
out[bytes++] = (uint8_t)nalUnitType << 1;
|
||||
out[bytes++] = 1 + (nalUnitType == NAL_UNIT_CODED_SLICE_TSA_N);
|
||||
|
||||
/* 7.4.1 ...
|
||||
* Within the NAL unit, the following three-byte sequences shall not occur at
|
||||
* any byte-aligned position:
|
||||
* - 0x000000
|
||||
* - 0x000001
|
||||
* - 0x000002 */
|
||||
for (uint32_t i = 0; i < payloadSize; i++)
|
||||
{
|
||||
if (i > 2 && !out[bytes - 2] && !out[bytes - 3] && out[bytes - 1] <= 0x03)
|
||||
{
|
||||
/* inject 0x03 to prevent emulating a start code */
|
||||
out[bytes] = out[bytes - 1];
|
||||
out[bytes - 1] = 0x03;
|
||||
bytes++;
|
||||
}
|
||||
|
||||
out[bytes++] = bpayload[i];
|
||||
}
|
||||
|
||||
X265_CHECK(bytes <= 4 + 2 + payloadSize + (payloadSize >> 1), "NAL buffer overflow\n");
|
||||
|
||||
if (m_extraOccupancy)
|
||||
{
|
||||
/* these bytes were escaped by serializeSubstreams */
|
||||
memcpy(out + bytes, m_extraBuffer, m_extraOccupancy);
|
||||
bytes += m_extraOccupancy;
|
||||
m_extraOccupancy = 0;
|
||||
}
|
||||
|
||||
/* 7.4.1.1
|
||||
* ... when the last byte of the RBSP data is equal to 0x00 (which can
|
||||
* only occur when the RBSP ends in a cabac_zero_word), a final byte equal
|
||||
* to 0x03 is appended to the end of the data. */
|
||||
if (!out[bytes - 1])
|
||||
out[bytes++] = 0x03;
|
||||
|
||||
if (!m_annexB)
|
||||
{
|
||||
uint32_t dataSize = bytes - 4;
|
||||
out[0] = (uint8_t)(dataSize >> 24);
|
||||
out[1] = (uint8_t)(dataSize >> 16);
|
||||
out[2] = (uint8_t)(dataSize >> 8);
|
||||
out[3] = (uint8_t)dataSize;
|
||||
}
|
||||
|
||||
m_occupancy += bytes;
|
||||
|
||||
X265_CHECK(m_numNal < (uint32_t)MAX_NAL_UNITS, "NAL count overflow\n");
|
||||
|
||||
x265_nal& nal = m_nal[m_numNal++];
|
||||
nal.type = nalUnitType;
|
||||
nal.sizeBytes = bytes;
|
||||
nal.payload = out;
|
||||
}
|
||||
|
||||
/* concatenate and escape WPP sub-streams, return escaped row lengths.
|
||||
* These streams will be appended to the next serialized NAL */
|
||||
uint32_t NALList::serializeSubstreams(uint32_t* streamSizeBytes, uint32_t streamCount, const Bitstream* streams)
|
||||
{
|
||||
uint32_t maxStreamSize = 0;
|
||||
uint32_t estSize = 0;
|
||||
for (uint32_t s = 0; s < streamCount; s++)
|
||||
estSize += streams[s].getNumberOfWrittenBytes();
|
||||
estSize += estSize >> 1;
|
||||
|
||||
if (estSize > m_extraAllocSize)
|
||||
{
|
||||
uint8_t *temp = X265_MALLOC(uint8_t, estSize);
|
||||
if (temp)
|
||||
{
|
||||
X265_FREE(m_extraBuffer);
|
||||
m_extraBuffer = temp;
|
||||
m_extraAllocSize = estSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
x265_log(NULL, X265_LOG_ERROR, "Unable to realloc WPP substream concatenation buffer\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bytes = 0;
|
||||
uint8_t *out = m_extraBuffer;
|
||||
for (uint32_t s = 0; s < streamCount; s++)
|
||||
{
|
||||
const Bitstream& stream = streams[s];
|
||||
uint32_t inSize = stream.getNumberOfWrittenBytes();
|
||||
const uint8_t *inBytes = stream.getFIFO();
|
||||
uint32_t prevBufSize = bytes;
|
||||
|
||||
if (inBytes)
|
||||
{
|
||||
for (uint32_t i = 0; i < inSize; i++)
|
||||
{
|
||||
if (bytes >= 2 && !out[bytes - 2] && !out[bytes - 1] && inBytes[i] <= 0x03)
|
||||
{
|
||||
/* inject 0x03 to prevent emulating a start code */
|
||||
out[bytes++] = 3;
|
||||
}
|
||||
|
||||
out[bytes++] = inBytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (s < streamCount - 1)
|
||||
{
|
||||
streamSizeBytes[s] = bytes - prevBufSize;
|
||||
if (streamSizeBytes[s] > maxStreamSize)
|
||||
maxStreamSize = streamSizeBytes[s];
|
||||
}
|
||||
}
|
||||
|
||||
m_extraOccupancy = bytes;
|
||||
return maxStreamSize;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue