@@ -5,6 +5,8 @@ CID3Converter::CID3Converter()
5
5
: m_enabled(false )
6
6
, m_treatUnknownPrivateDataAsSuperimpose(false )
7
7
, m_insertInappropriate5BytesIntoPesPayload(false )
8
+ , m_forceMonotonousPts(false )
9
+ , m_lastID3Pts(-1 )
8
10
, m_firstPmtPid(0 )
9
11
, m_captionPid(0 )
10
12
, m_superimposePid(0 )
@@ -24,6 +26,7 @@ void CID3Converter::SetOption(int flags)
24
26
m_enabled = !!(flags & 1 );
25
27
m_treatUnknownPrivateDataAsSuperimpose = !!(flags & 2 );
26
28
m_insertInappropriate5BytesIntoPesPayload = !!(flags & 4 );
29
+ m_forceMonotonousPts = !!(flags & 8 );
27
30
}
28
31
29
32
void CID3Converter::AddPacket (const uint8_t *packet)
@@ -242,30 +245,31 @@ void CID3Converter::CheckPrivateDataPes(const std::vector<uint8_t> &pes)
242
245
{
243
246
const uint8_t PRIVATE_STREAM_1 = 0xbd ;
244
247
const uint8_t PRIVATE_STREAM_2 = 0xbf ;
248
+ const int ACCEPTABLE_PTS_DIFF_SEC = 10 ;
245
249
246
250
size_t payloadPos = 0 ;
247
- uint8_t pts[ 5 ] = {} ;
251
+ int64_t pts = - 1 ;
248
252
if (pes[0 ] == 0 && pes[1 ] == 0 && pes[2 ] == 1 ) {
249
253
int streamID = pes[3 ];
250
254
if (streamID == PRIVATE_STREAM_1 && pes.size () >= 9 ) {
251
255
int ptsDtsFlags = pes[7 ] >> 6 ;
252
256
payloadPos = 9 + pes[8 ];
253
257
if (ptsDtsFlags >= 2 && pes.size () >= 14 ) {
254
- std::copy (pes.begin () + 9 , pes.begin () + 14 , pts);
258
+ pts = (pes[13 ] >> 1 ) |
259
+ (pes[12 ] << 7 ) |
260
+ ((pes[11 ] & 0xfe ) << 14 ) |
261
+ (pes[10 ] << 22 ) |
262
+ (static_cast <int64_t >(pes[9 ] & 0x0e ) << 29 );
255
263
}
256
264
}
257
265
else if (streamID == PRIVATE_STREAM_2) {
258
266
payloadPos = 6 ;
259
267
if (m_pcr >= 0 ) {
260
- pts[0 ] = static_cast <uint8_t >(m_pcr >> 29 ) | 0x21 ; // 3 bits
261
- pts[1 ] = static_cast <uint8_t >(m_pcr >> 22 ); // 8 bits
262
- pts[2 ] = static_cast <uint8_t >(m_pcr >> 14 ) | 1 ; // 7 bits
263
- pts[3 ] = static_cast <uint8_t >(m_pcr >> 7 ); // 8 bits
264
- pts[4 ] = static_cast <uint8_t >(m_pcr << 1 ) | 1 ; // 7 bits
268
+ pts = m_pcr;
265
269
}
266
270
}
267
271
}
268
- if (payloadPos == 0 || payloadPos + 1 >= pes.size () || pts[ 0 ] == 0 ) {
272
+ if (payloadPos == 0 || payloadPos + 1 >= pes.size () || pts < 0 ) {
269
273
return ;
270
274
}
271
275
int dataIdentifier = pes[payloadPos];
@@ -275,6 +279,14 @@ void CID3Converter::CheckPrivateDataPes(const std::vector<uint8_t> &pes)
275
279
// Not an ARIB Synchronized/Asynchronous PES data
276
280
return ;
277
281
}
282
+ if (m_forceMonotonousPts) {
283
+ if (m_lastID3Pts >= 0 &&
284
+ ((0x200000000 + m_lastID3Pts - pts) & 0x1ffffffff ) < 90000 * ACCEPTABLE_PTS_DIFF_SEC) {
285
+ // Prevent PTS goes back
286
+ pts = m_lastID3Pts;
287
+ }
288
+ m_lastID3Pts = pts;
289
+ }
278
290
279
291
// ID3 Timed Metadata
280
292
m_buf.clear ();
@@ -286,7 +298,11 @@ void CID3Converter::CheckPrivateDataPes(const std::vector<uint8_t> &pes)
286
298
m_buf.push_back (0x80 );
287
299
m_buf.push_back (0x80 );
288
300
m_buf.push_back (5 );
289
- m_buf.insert (m_buf.end (), pts, pts + 5 );
301
+ m_buf.push_back (static_cast <uint8_t >(pts >> 29 ) | 0x21 ); // 3 bits
302
+ m_buf.push_back (static_cast <uint8_t >(pts >> 22 )); // 8 bits
303
+ m_buf.push_back (static_cast <uint8_t >(pts >> 14 ) | 1 ); // 7 bits
304
+ m_buf.push_back (static_cast <uint8_t >(pts >> 7 )); // 8 bits
305
+ m_buf.push_back (static_cast <uint8_t >(pts << 1 ) | 1 ); // 7 bits
290
306
if (m_insertInappropriate5BytesIntoPesPayload) {
291
307
m_buf.insert (m_buf.end (), 5 , 0 );
292
308
}
0 commit comments