1010#include " bitstream.h"
1111#include " debug.h"
1212
13- #include < cstring> // for memset memcpy
13+ #include < cstring> // for memset memcpy memcmp
1414
1515using namespace TSDemux ;
1616
@@ -43,7 +43,9 @@ void ES_hevc::Parse(STREAM_PKT* pkt)
4343 uint32_t startcode = m_StartCode;
4444 bool frameComplete = false ;
4545
46- if (m_NeedSPS)
46+ // Reset extra data only on a fresh capture, so a VPS from a previous PES
47+ // payload isn't discarded while waiting for its SPS/PPS.
48+ if (m_NeedVPS && m_NeedSPS && m_NeedPPS)
4749 stream_info.extra_data_size = 0 ;
4850
4951 while (p < es_len)
@@ -167,20 +169,9 @@ void ES_hevc::Parse_HEVC(int buf_ptr, unsigned int NumBytesInNalUnit, bool &comp
167169 switch (hdr.nal_unit_type )
168170 {
169171 case NAL_VPS_NUT :
170- if (m_NeedVPS)
171- {
172- if (stream_info.extra_data_size + NumBytesInNalUnit <= sizeof (stream_info.extra_data ))
173- {
174- memcpy (stream_info.extra_data + stream_info.extra_data_size , es_buf + (buf_ptr - 4 ), NumBytesInNalUnit);
175- stream_info.extra_data_size += NumBytesInNalUnit;
176- m_NeedVPS = false ;
177- }
178- else
179- {
180- DBG (DEMUX_DBG_INFO , " HEVC fixme: stream_info.extra_data too small! %i\n " , stream_info.extra_data_size + NumBytesInNalUnit);
181- }
182- }
183- break ;
172+ if (m_NeedVPS && AppendExtraData (buf_ptr, NumBytesInNalUnit))
173+ m_NeedVPS = false ;
174+ break ;
184175
185176 case NAL_SPS_NUT :
186177 {
@@ -191,19 +182,8 @@ void ES_hevc::Parse_HEVC(int buf_ptr, unsigned int NumBytesInNalUnit, bool &comp
191182 return ;
192183 }
193184 Parse_SPS (buf, NumBytesInNalUnit, hdr);
194- if (m_NeedSPS)
195- {
196- if (stream_info.extra_data_size + NumBytesInNalUnit <= sizeof (stream_info.extra_data ))
197- {
198- memcpy (stream_info.extra_data + stream_info.extra_data_size , es_buf + (buf_ptr - 4 ), NumBytesInNalUnit);
199- stream_info.extra_data_size += NumBytesInNalUnit;
200- m_NeedSPS = false ;
201- }
202- else
203- {
204- DBG (DEMUX_DBG_INFO , " HEVC fixme: stream_info.extra_data too small! %i\n " , stream_info.extra_data_size + NumBytesInNalUnit);
205- }
206- }
185+ if (m_NeedSPS && AppendExtraData (buf_ptr, NumBytesInNalUnit))
186+ m_NeedSPS = false ;
207187 break ;
208188 }
209189
@@ -216,19 +196,8 @@ void ES_hevc::Parse_HEVC(int buf_ptr, unsigned int NumBytesInNalUnit, bool &comp
216196 return ;
217197 }
218198 Parse_PPS (buf, NumBytesInNalUnit);
219- if (m_NeedPPS)
220- {
221- if (stream_info.extra_data_size + NumBytesInNalUnit <= sizeof (stream_info.extra_data ))
222- {
223- memcpy (stream_info.extra_data + stream_info.extra_data_size , es_buf + (buf_ptr - 4 ), NumBytesInNalUnit);
224- stream_info.extra_data_size += NumBytesInNalUnit;
225- m_NeedPPS = false ;
226- }
227- else
228- {
229- DBG (DEMUX_DBG_INFO , " HEVC fixme: stream_info.extra_data too small! %i\n " , stream_info.extra_data_size + NumBytesInNalUnit);
230- }
231- }
199+ if (m_NeedPPS && AppendExtraData (buf_ptr, NumBytesInNalUnit))
200+ m_NeedPPS = false ;
232201 break ;
233202 }
234203
@@ -269,6 +238,41 @@ void ES_hevc::Parse_HEVC(int buf_ptr, unsigned int NumBytesInNalUnit, bool &comp
269238 }
270239}
271240
241+ // Append a parameter set NAL (VPS/SPS/PPS) to the extra data as Annex B.
242+ // numBytes spans to the end of the next start code (3 or 4 bytes), stripped here if present.
243+ bool ES_hevc::AppendExtraData (int buf_ptr, unsigned int numBytes)
244+ {
245+ if (numBytes < 3 )
246+ return false ;
247+
248+ unsigned int nalSize = numBytes;
249+ const unsigned char * tail = es_buf + buf_ptr + numBytes;
250+ if (numBytes >= 4 && std::memcmp (tail - 4 , " \0\0\0\x01 " , 4 ) == 0 )
251+ nalSize = numBytes - 4 ;
252+ else if (std::memcmp (tail - 3 , " \0\0\x01 " , 3 ) == 0 )
253+ nalSize = numBytes - 3 ;
254+
255+ if (nalSize == 0 )
256+ return false ;
257+
258+ if (static_cast <size_t >(stream_info.extra_data_size ) + 4 + nalSize >
259+ sizeof (stream_info.extra_data ))
260+ {
261+ DBG (DEMUX_DBG_INFO , " HEVC fixme: stream_info.extra_data too small! %u\n " ,
262+ static_cast <unsigned int >(stream_info.extra_data_size ) + 4 + nalSize);
263+ return false ;
264+ }
265+
266+ uint8_t * ed = stream_info.extra_data + stream_info.extra_data_size ;
267+ ed[0 ] = 0 ;
268+ ed[1 ] = 0 ;
269+ ed[2 ] = 0 ;
270+ ed[3 ] = 1 ;
271+ std::memcpy (ed + 4 , es_buf + buf_ptr, nalSize);
272+ stream_info.extra_data_size += 4 + nalSize;
273+ return true ;
274+ }
275+
272276void ES_hevc::Parse_PPS (uint8_t *buf, int len)
273277{
274278 CBitstream bs (buf, len*8 , true );
0 commit comments