1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
4 * Authors: Steve Borho <steve@borho.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
25 #include "bitstream.h"
40 void NALList::takeContents(NALList
& other
)
42 /* take other NAL buffer, discard our old one */
44 m_buffer
= other
.m_buffer
;
45 m_allocSize
= other
.m_allocSize
;
46 m_occupancy
= other
.m_occupancy
;
48 /* copy packet data */
49 m_numNal
= other
.m_numNal
;
50 memcpy(m_nal
, other
.m_nal
, sizeof(x265_nal
) * m_numNal
);
52 /* reset other list, re-allocate their buffer with same size */
54 other
.m_occupancy
= 0;
55 other
.m_buffer
= X265_MALLOC(uint8_t, m_allocSize
);
58 void NALList::serialize(NalUnitType nalUnitType
, const Bitstream
& bs
)
60 static const char startCodePrefix
[] = { 0, 0, 0, 1 };
62 uint32_t payloadSize
= bs
.getNumberOfWrittenBytes();
63 const uint8_t* bpayload
= bs
.getFIFO();
67 uint32_t nextSize
= m_occupancy
+ sizeof(startCodePrefix
) + 2 + payloadSize
+ (payloadSize
>> 1) + m_extraOccupancy
;
68 if (nextSize
> m_allocSize
)
70 uint8_t *temp
= X265_MALLOC(uint8_t, nextSize
);
73 memcpy(temp
, m_buffer
, m_occupancy
);
75 /* fixup existing payload pointers */
76 for (uint32_t i
= 0; i
< m_numNal
; i
++)
77 m_nal
[i
].payload
= temp
+ (m_nal
[i
].payload
- m_buffer
);
81 m_allocSize
= nextSize
;
85 x265_log(NULL
, X265_LOG_ERROR
, "Unable to realloc access unit buffer\n");
90 uint8_t *out
= m_buffer
+ m_occupancy
;
93 if (!m_numNal
|| nalUnitType
== NAL_UNIT_SPS
|| nalUnitType
== NAL_UNIT_PPS
)
95 memcpy(out
, startCodePrefix
, 4);
100 memcpy(out
, startCodePrefix
+ 1, 3);
104 /* 16 bit NAL header:
105 * forbidden_zero_bit 1-bit
106 * nal_unit_type 6-bits
107 * nuh_reserved_zero_6bits 6-bits
108 * nuh_temporal_id_plus1 3-bits */
109 out
[bytes
++] = (uint8_t)nalUnitType
<< 1;
113 * Within the NAL unit, the following three-byte sequences shall not occur at
114 * any byte-aligned position:
118 for (uint32_t i
= 0; i
< payloadSize
; i
++)
120 if (i
> 2 && !out
[bytes
- 2] && !out
[bytes
- 3] && out
[bytes
- 1] <= 0x03)
122 /* inject 0x03 to prevent emulating a start code */
123 out
[bytes
] = out
[bytes
- 1];
124 out
[bytes
- 1] = 0x03;
128 out
[bytes
++] = bpayload
[i
];
131 X265_CHECK(bytes
<= 4 + 2 + payloadSize
+ (payloadSize
>> 1), "NAL buffer overflow\n");
133 if (m_extraOccupancy
)
135 /* these bytes were escaped by serializeSubstreams */
136 memcpy(out
+ bytes
, m_extraBuffer
, m_extraOccupancy
);
137 bytes
+= m_extraOccupancy
;
138 m_extraOccupancy
= 0;
142 * ... when the last byte of the RBSP data is equal to 0x00 (which can
143 * only occur when the RBSP ends in a cabac_zero_word), a final byte equal
144 * to 0x03 is appended to the end of the data. */
147 m_occupancy
+= bytes
;
149 X265_CHECK(m_numNal
< (uint32_t)MAX_NAL_UNITS
, "NAL count overflow\n");
151 x265_nal
& nal
= m_nal
[m_numNal
++];
152 nal
.type
= nalUnitType
;
153 nal
.sizeBytes
= bytes
;
157 /* concatenate and escape WPP sub-streams, return escaped row lengths.
158 * These streams will be appended to the next serialized NAL */
159 uint32_t NALList::serializeSubstreams(uint32_t* streamSizeBytes
, uint32_t streamCount
, const Bitstream
* streams
)
161 uint32_t maxStreamSize
= 0;
162 uint32_t estSize
= 0;
163 for (uint32_t s
= 0; s
< streamCount
; s
++)
164 estSize
+= streams
[s
].getNumberOfWrittenBytes();
165 estSize
+= estSize
>> 1;
167 if (estSize
> m_extraAllocSize
)
169 uint8_t *temp
= X265_MALLOC(uint8_t, estSize
);
172 X265_FREE(m_extraBuffer
);
173 m_extraBuffer
= temp
;
174 m_extraAllocSize
= estSize
;
178 x265_log(NULL
, X265_LOG_ERROR
, "Unable to realloc WPP substream concatenation buffer\n");
184 uint8_t *out
= m_extraBuffer
;
185 for (uint32_t s
= 0; s
< streamCount
; s
++)
187 const Bitstream
& stream
= streams
[s
];
188 uint32_t inSize
= stream
.getNumberOfWrittenBytes();
189 const uint8_t *inBytes
= stream
.getFIFO();
190 uint32_t prevBufSize
= bytes
;
194 for (uint32_t i
= 0; i
< inSize
; i
++)
196 if (bytes
>= 2 && !out
[bytes
- 2] && !out
[bytes
- 1] && inBytes
[i
] <= 0x03)
198 /* inject 0x03 to prevent emulating a start code */
202 out
[bytes
++] = inBytes
[i
];
206 if (s
< streamCount
- 1)
208 streamSizeBytes
[s
] = bytes
- prevBufSize
;
209 if (streamSizeBytes
[s
] > maxStreamSize
)
210 maxStreamSize
= streamSizeBytes
[s
];
214 m_extraOccupancy
= bytes
;
215 return maxStreamSize
;