1 /* ///////////////////////////////////////////////////////////////////////
2 * File: transport_packet.h
7 * Brief: the transport_packet class - TS packet
10 * Copyright (c) 2008-2020, Waruqi All rights reserved.
11 * //////////////////////////////////////////////////////////////////// */
13 #ifndef EXTL_MEDIA_TS_TRANSPORT_PACKET_H
14 #define EXTL_MEDIA_TS_TRANSPORT_PACKET_H
16 /*!\file transport_packet.h
17 * \brief the transport_packet class - TS packet
20 # error transport_packet.h need be supported by c++.
23 /* ///////////////////////////////////////////////////////////////////////
27 #include "../../memory/buffer.h"
28 #include "../../algorithm/algorithm.h"
29 #include "../../utility/bit_op.h"
30 #include "../../type/traits/is_unsigned.h"
32 /* ///////////////////////////////////////////////////////////////////////
33 * ::extl::media namespace
35 EXTL_MEDIA_BEGIN_WHOLE_NAMESPACE
38 /*!brief transport_packet
40 * \ingroup extl_group_media
43 * // transport packet format - TS
44 * struct transport_packet
48 transport_error_indicator : 1 ;
49 payload_unit_start_indicator : 1 ;
50 transport_priority : 1 ;
52 transport_scrambling_control : 2 ;
53 adaptation_field_control : 2 ;
54 continuity_counter : 4 ;
57 if (adaptation_field_control == 0x2
58 || adaptation_field_control == 0x3 )
60 struct adaptation_field
62 // adaptation field header
63 adaptation_field_length : 8 ;
64 discontinuity_indicator : 1 ;
65 random_access_indicator : 1 ;
66 elementary_stream_priority_indicator : 1 ;
69 splicing_point_flag : 1 ;
70 transport_private_data_flag : 1 ;
71 adaptation_field_extension_flag : 1 ;
73 // program clock reference
82 // original program clock reference
91 if (splicing_point_flag == 1)
93 splice_countdown : 8 ;
96 // transport private data
97 if (transport_private_data_flag == 1)
99 for (i = 0; i < transport_private_data_length; ++i)
100 private_data_byte : 8 ;
102 if (adaptation_field_extension_flag == 1)
104 adaptation_field_extension_length : 8 ;
106 piecewise_rate_flag : 1 ;
107 seamless_splice_flag : 1 ;
116 if (piecewise_rate_flag == 1)
119 piecewise_rate : 22 ;
122 if (seamless_splice_flag == 1)
125 dts_next_au[32..30] : 3 ;
127 dts_next_au[29..15] : 15 ;
129 dts_next_au[14..0] : 15 ;
133 for (i = 0; i < N; ++i)
138 for (i = 0; i < N; ++i)
144 if (adaptation_field_control == 0x1
145 || adaptation_field_control == 0x3 )
147 for (i = 0; i < N; ++i)
153 * \note member methods and attributes need using attach and detach, static methods need not
158 printf("%x\n", p1.sync_byte());
159 printf("%x\n", p1.transport_error_indicator());
160 printf("%x\n", p1.payload_unit_start_indicator());
161 printf("%x\n", p1.transport_priority());
162 printf("%x\n", p1.pid());
163 printf("%x\n", p1.transport_scrambling_control());
164 printf("%x\n", p1.adaptation_field_control());
165 printf("%x\n", p1.continuity_counter());
166 // modify payload ...
170 printf("%x\n", transport_packet::pid(buf));
174 class transport_packet
179 typedef transport_packet class_type
;
180 typedef e_byte_t byte_type
;
181 typedef e_uint16_t word_type
;
182 typedef e_uint32_t dword_type
;
183 typedef e_uint64_t qword_type
;
184 typedef byte_type
* pointer
;
185 typedef byte_type
const* const_pointer
;
186 typedef attached_buffer
<byte_type
, 188> buffer_type
;
187 typedef e_size_t size_type
;
188 typedef size_type index_type
;
189 typedef e_bool_t bool_type
;
192 // \note defined in reverse order by dword_type
193 dword_type continuity_counter
: 4 ; //< low bit
194 dword_type adaptation_field_control
: 2 ;
195 dword_type transport_scrambling_control
: 2 ;
196 dword_type pid
: 13 ;
197 dword_type transport_priority
: 1 ;
198 dword_type payload_unit_start_indicator
: 1 ;
199 dword_type transport_error_indicator
: 1 ;
200 dword_type sync_byte
: 8 ; //< high bit
203 struct adaptation_field_header_type
205 byte_type adaptation_field_length
;
207 // \note defined in reverse order by byte_type
208 byte_type adaptation_field_extension_flag
: 1 ; //< low bit
209 byte_type transport_private_data_flag
: 1 ;
210 byte_type splicing_point_flag
: 1 ;
211 byte_type opcr_flag
: 1 ;
212 byte_type pcr_flag
: 1 ;
213 byte_type elementary_stream_priority_indicator
: 1 ;
214 byte_type random_access_indicator
: 1 ;
215 byte_type discontinuity_indicator
: 1 ; //< high bit
218 // program_clock_reference
219 // pcr_base + base1 + reseved + pcr_extension
223 // 32(pcr_base) + 1(base1)
224 dword_type pcr_base
;
226 // \note defined in reverse order by word_type
227 word_type pcr_extension
: 9 ; //< low bit
228 word_type reseved
: 6 ;
229 word_type base1
: 1 ; //< high bit
232 // original_program_clock_reference
233 // opcr_base + base1 + reseved + pcr_extension
237 // 32(opcr_base) + 1(base1)
238 dword_type opcr_base
;
240 // \note defined in reverse order by word_type
241 word_type opcr_extension
: 9 ; //< low bit
242 word_type reseved
: 6 ;
243 word_type base1
: 1 ; //< high bit
246 // adaptation_field_extension_header
247 struct adaptation_field_extension_header_type
249 byte_type adaptation_field_extension_length
: 8 ;
251 // \note defined in reverse order by byte_type
252 byte_type reserved
: 5 ;
253 byte_type seamless_splice_flag
: 1 ;
254 byte_type piecewise_rate_flag
: 1 ;
255 byte_type ltw_flag
: 1 ;
261 // \note defined in reverse order by word_type
262 word_type ltw_offset
: 15 ;
263 word_type ltw_valid_flag
: 1 ;
267 /// \name Enumerators
270 // the packet header size
271 enum { en_header_size
= sizeof(header_type
) };
272 // the whole packet size
273 enum { en_packet_size
= 188 };
275 enum { en_adaptation_field_header_size
= sizeof(adaptation_field_header_type
) };
277 enum { en_pcr_size
= sizeof(pcr_type
) };
278 // the whole packet size
279 enum { en_opcr_size
= sizeof(opcr_type
) };
281 enum { en_splicing_size
= 1 };
282 // the adaptation field extension _header size
283 enum { en_adaptation_field_extension_header_size
= sizeof(adaptation_field_extension_header_type
) };
285 enum { en_ltw_size
= sizeof(ltw_type
) };
288 // for header_type::sync_byte
289 enum { en_sync_byte
= 0x47 };
291 // for header_type::pid
292 enum { en_pid_pat
= 0x0000 };
293 enum { en_pid_cat
= 0x0001 };
294 enum { en_pid_tsdt
= 0x0002 };
295 enum { en_pid_null
= 0x1FFF }; //!<? 0xFFFF or 0x 1FFF
301 buffer_type m_buffer
;
304 /// \name Constructors
307 explicit_k
transport_packet(const_pointer data
= NULL
)
313 EXTL_STATIC_ASSERT(sizeof(header_type
) == 4);
314 EXTL_STATIC_ASSERT(sizeof(byte_type
) == 1);
315 EXTL_STATIC_ASSERT(is_unsigned
<byte_type
>::value
);
316 EXTL_STATIC_ASSERT(is_unsigned
<dword_type
>::value
);
323 buffer_type
& buffer() { return m_buffer
; }
324 buffer_type
const& buffer() const { return m_buffer
; }
326 pointer
data() { return buffer().data(); }
327 const_pointer
data() const { return buffer().data(); }
329 pointer
adaptation_field_data() { return (data() + en_header_size
); }
330 const_pointer
adaptation_field_data() const { return (data() + en_header_size
); }
332 pointer
pcr_data() { return (exists_pcr()? (adaptation_field_data() + en_adaptation_field_header_size
) : adaptation_field_data()); }
333 const_pointer
pcr_data() const { return (exists_pcr()? (adaptation_field_data() + en_adaptation_field_header_size
) : adaptation_field_data()); }
335 pointer
opcr_data() { return (exists_opcr()? (pcr_data() + en_pcr_size
) : pcr_data()); }
336 const_pointer
opcr_data() const { return (exists_opcr()? (pcr_data() + en_pcr_size
) : pcr_data()); }
338 pointer
splicing_data() { return (exists_splicing()? (opcr_data() + en_opcr_size
) : opcr_data()); }
339 const_pointer
splicing_data() const { return (exists_splicing()? (opcr_data() + en_opcr_size
) : opcr_data()); }
341 pointer
transport_private_data() { return (exists_private_data()? (splicing_data() + en_splicing_size
) : splicing_data()); }
342 const_pointer
transport_private_data() const { return (exists_private_data()? (splicing_data() + en_splicing_size
) : splicing_data()); }
344 pointer
private_data() { return &(transport_private_data()[1]); }
345 const_pointer
private_data() const { return &(transport_private_data()[1]); }
347 pointer
adaptation_field_extension_data() { return (exists_adaptation_field_extension()? (private_data() + private_data_length()) : transport_private_data()); }
348 const_pointer
adaptation_field_extension_data() const { return (exists_adaptation_field_extension()? (private_data() + private_data_length()) : transport_private_data()); }
350 pointer
ltw_data() { return (exists_ltw()? (adaptation_field_extension_data() + en_adaptation_field_extension_header_size
) : adaptation_field_extension_data()); }
351 const_pointer
ltw_data() const { return (exists_ltw()? (adaptation_field_extension_data() + en_adaptation_field_extension_header_size
) : adaptation_field_extension_data()); }
354 /// \name Protected Accessors
357 header_type
& header() { return *reinterpret_cast<header_type
*>(data()); }
358 header_type
const& header() const { return *reinterpret_cast<header_type
const*>(data()); }
360 adaptation_field_header_type
& adaptation_field_header() { return *reinterpret_cast<adaptation_field_header_type
*>(adaptation_field_data()); }
361 adaptation_field_header_type
const& adaptation_field_header() const { return *reinterpret_cast<adaptation_field_header_type
const*>(adaptation_field_data()); }
363 pcr_type
& pcr_body() { return *reinterpret_cast<pcr_type
*>(pcr_data()); }
364 pcr_type
const& pcr_body() const { return *reinterpret_cast<pcr_type
const*>(pcr_data()); }
366 opcr_type
& opcr_body() { return *reinterpret_cast<opcr_type
*>(opcr_data()); }
367 opcr_type
const& opcr_body() const { return *reinterpret_cast<opcr_type
const*>(opcr_data()); }
369 adaptation_field_extension_header_type
& adaptation_field_extension() { return *reinterpret_cast<adaptation_field_extension_header_type
*>(adaptation_field_extension_data()); }
370 adaptation_field_extension_header_type
const& adaptation_field_extension() const { return *reinterpret_cast<adaptation_field_extension_header_type
const*>(adaptation_field_extension_data()); }
372 ltw_type
& ltw() { return *reinterpret_cast<ltw_type
*>(ltw_data()); }
373 ltw_type
const& ltw() const { return *reinterpret_cast<ltw_type
const*>(ltw_data()); }
380 /// attaches packet buffer - size: 188b
381 /// \note maybe modify the buffer for performance
382 void attach(const_pointer p
);
383 /// detaches packet buffer
384 /// \note maybe modify the buffer for performance
385 const_pointer
detach();
388 /// \name Header Attributes
391 size_type
sync_byte() const { return static_cast<size_type
>(header().sync_byte
); }
392 void sync_byte(size_type value
) { header().sync_byte
= static_cast<dword_type
>(value
); }
394 size_type
transport_error_indicator() const { return static_cast<size_type
>(header().transport_error_indicator
); }
395 void transport_error_indicator(size_type value
) { header().transport_error_indicator
= static_cast<dword_type
>(value
); }
397 size_type
payload_unit_start_indicator() const { return static_cast<size_type
>(header().payload_unit_start_indicator
); }
398 void payload_unit_start_indicator(size_type value
) { header().payload_unit_start_indicator
= static_cast<dword_type
>(value
); }
400 size_type
transport_priority() const { return static_cast<size_type
>(header().transport_priority
); }
401 void transport_priority(size_type value
) { header().transport_priority
= static_cast<dword_type
>(value
); }
403 size_type
pid() const { return static_cast<size_type
>(header().pid
); }
404 void pid(size_type value
) { header().pid
= static_cast<dword_type
>(value
); }
406 size_type
transport_scrambling_control() const { return static_cast<size_type
>(header().transport_scrambling_control
); }
407 void transport_scrambling_control(size_type value
) { header().transport_scrambling_control
= static_cast<dword_type
>(value
); }
409 size_type
adaptation_field_control() const { return static_cast<size_type
>(header().adaptation_field_control
); }
410 void adaptation_field_control(size_type value
) { header().adaptation_field_control
= static_cast<dword_type
>(value
); }
412 size_type
continuity_counter() const { return static_cast<size_type
>(header().continuity_counter
); }
413 void continuity_counter(size_type value
) { header().continuity_counter
= static_cast<dword_type
>(value
); }
416 /// \name Adaptation Field Header Attributes
419 size_type
adaptation_field_length() const { return static_cast<size_type
>(adaptation_field_header().adaptation_field_length
); }
420 void adaptation_field_length(size_type value
) { adaptation_field_header().adaptation_field_length
= static_cast<byte_type
>(value
); }
422 size_type
discontinuity_indicator() const { return static_cast<size_type
>(adaptation_field_header().discontinuity_indicator
); }
423 void discontinuity_indicator(size_type value
) { adaptation_field_header().discontinuity_indicator
= static_cast<byte_type
>(value
); }
425 size_type
random_access_indicator() const { return static_cast<size_type
>(adaptation_field_header().random_access_indicator
); }
426 void random_access_indicator(size_type value
) { adaptation_field_header().random_access_indicator
= static_cast<byte_type
>(value
); }
428 size_type
elementary_stream_priority_indicator() const { return static_cast<size_type
>(adaptation_field_header().elementary_stream_priority_indicator
); }
429 void elementary_stream_priority_indicator(size_type value
) { adaptation_field_header().elementary_stream_priority_indicator
= static_cast<byte_type
>(value
); }
431 size_type
pcr_flag() const { return static_cast<size_type
>(adaptation_field_header().pcr_flag
); }
432 void pcr_flag(size_type value
) { adaptation_field_header().pcr_flag
= static_cast<byte_type
>(value
); }
434 size_type
opcr_flag() const { return static_cast<size_type
>(adaptation_field_header().opcr_flag
); }
435 void opcr_flag(size_type value
) { adaptation_field_header().opcr_flag
= static_cast<byte_type
>(value
); }
437 size_type
splicing_point_flag() const { return static_cast<size_type
>(adaptation_field_header().splicing_point_flag
); }
438 void splicing_point_flag(size_type value
) { adaptation_field_header().splicing_point_flag
= static_cast<byte_type
>(value
); }
440 size_type
transport_private_data_flag() const { return static_cast<size_type
>(adaptation_field_header().transport_private_data_flag
); }
441 void transport_private_data_flag(size_type value
) { adaptation_field_header().transport_private_data_flag
= static_cast<byte_type
>(value
); }
443 size_type
adaptation_field_extension_flag() const { return static_cast<size_type
>(adaptation_field_header().adaptation_field_extension_flag
); }
444 void adaptation_field_extension_flag(size_type value
) { adaptation_field_header().adaptation_field_extension_flag
= static_cast<byte_type
>(value
); }
446 bool_type
exists_pcr() const { return (1 == pcr_flag()); }
447 bool_type
exists_opcr() const { return (1 == opcr_flag()); }
448 bool_type
exists_splicing() const { return (1 == splicing_point_flag()); }
449 bool_type
exists_private_data() const { return (1 == transport_private_data_flag()); }
450 bool_type
exists_adaptation_field_extension() const { return (1 == adaptation_field_extension_flag()); }
453 /// \name Adaptation Field PCR Attributes
456 qword_type
pcr() const { return (pcr_base() * 300 + pcr_extension()); }
457 qword_type
opcr() const { return (opcr_base() * 300 + opcr_extension()); }
459 qword_type
pcr_base() const { return ((static_cast<qword_type
>(pcr_body().pcr_base
) << 1) | pcr_body().base1
); }
460 void pcr_base(qword_type value
) { pcr_body().pcr_base
= static_cast<dword_type
>(value
>> 1); pcr_body().base1
= static_cast<word_type
>(value
& 0x1); }
462 size_type
pcr_extension() const { return static_cast<size_type
>(pcr_body().pcr_extension
); }
463 void pcr_extension(size_type value
) { pcr_body().pcr_extension
= static_cast<word_type
>(value
); }
465 qword_type
opcr_base() const { return ((static_cast<qword_type
>(opcr_body().opcr_base
) << 1) | opcr_body().base1
); }
466 void opcr_base(qword_type value
) { opcr_body().opcr_base
= static_cast<dword_type
>(value
>> 1); opcr_body().base1
= static_cast<word_type
>(value
& 0x1); }
468 size_type
opcr_extension() const { return static_cast<size_type
>(opcr_body().opcr_extension
); }
469 void opcr_extension(size_type value
) { opcr_body().opcr_extension
= static_cast<word_type
>(value
); }
472 /// \name Adaptation Field Other Attributes
475 size_type
splice_countdown() const { return splicing_data()[0]; }
476 void splice_countdown(size_type value
) { splicing_data()[0] = static_cast<byte_type
>(value
); }
478 size_type
private_data_length() const { return transport_private_data()[0]; }
479 void private_data_length(size_type value
){ transport_private_data()[0] = static_cast<byte_type
>(value
); }
481 // size_type adaptation_field_extension_length() const { return adaptation_field_extension().adaptation_field_extension_length; }
482 //void adaptation_field_extension_length(size_type value) { adaptation_field_extension().adaptation_field_extension_length = static_cast<byte_type>(adaptation_field_extension_length); }
484 size_type
ltw_flag() const { return adaptation_field_extension().ltw_flag
; }
485 void ltw_flag(size_type value
) { adaptation_field_extension().ltw_flag
= static_cast<byte_type
>(value
); }
487 size_type
piecewise_rate_flag() const { return adaptation_field_extension().piecewise_rate_flag
; }
488 void piecewise_rate_flag(size_type value
) { adaptation_field_extension().piecewise_rate_flag
= static_cast<byte_type
>(value
); }
490 size_type
seamless_splice_flag() const { return adaptation_field_extension().seamless_splice_flag
; }
491 void seamless_splice_flag(size_type value
) { adaptation_field_extension().seamless_splice_flag
= static_cast<byte_type
>(value
); }
493 bool_type
exists_ltw() const { return (1 == ltw_flag()); }
494 bool_type
exists_piecewise_rate() const { return (1 == piecewise_rate_flag()); }
495 bool_type
exists_seamless_splice() const { return (1 == seamless_splice_flag()); }
497 size_type
ltw_valid_flag() const { return ltw().ltw_valid_flag
; }
498 void ltw_valid_flag(size_type value
) { ltw().ltw_valid_flag
= static_cast<word_type
>(value
); }
500 size_type
ltw_offset() const { return ltw().ltw_offset
; }
501 void ltw_offset(size_type value
) { ltw().ltw_offset
= static_cast<word_type
>(value
); }
505 /// \name Packet Attributes
508 /// return \true if packet is pat(program association table)
509 bool_type
is_pat() const { return (pid() == en_pid_pat
); }
510 /// the packet is set to be pat
511 void set_pat() { pid(en_pid_pat
); }
513 /// return \true if packet is cat(conditional access table)
514 bool_type
is_cat() const { return (pid() == en_pid_cat
); }
515 /// the packet is set to be cat
516 void set_cat() { pid(en_pid_cat
); }
518 /// return \true if packet is tsdt(transport stream description table)
519 bool_type
is_tsdt() const { return (pid() == en_pid_tsdt
); }
520 /// the packet is set to be tsdt
521 void set_tsdt() { pid(en_pid_tsdt
); }
523 /// return \true if packet is null
524 bool_type
is_null() const { return (pid() == en_pid_null
); }
525 /// the packet is set to be null
526 void set_null() { pid(en_pid_null
); }
528 /// return \true if packet is scrambled
529 bool_type
is_scrambling() const { return (transport_scrambling_control() != 0); }
531 /// return \true if packet exists error
532 bool_type
exists_error() const { return (transport_error_indicator() != 0); }
534 /// return \true if the packet exists adaptation field
535 bool_type
exists_adaptation_field() const { return (adaptation_field_control() == 0x2 || adaptation_field_control() == 0x3); }
537 /// return \true if the adaptation field is valid
538 bool_type
adaptation_field_is_valid() const { return !((adaptation_field_control() == 0x2 && adaptation_field_length() != 183) || (adaptation_field_control() == 0x3 && adaptation_field_length() > 182)); }
541 /// \name Other Attributes
544 bool_type
is_valid() const { return (sync_byte() == en_sync_byte
); }
547 /// \name Static Methods
550 static size_type
pid(const_pointer data
) { return (((data
[1] & 0x1F) << 8) | data
[2]); }
553 /// \name Protected Helpers
556 /// reverse byte stream and \note size must be divided by 1, 2, 4
557 void reverse(pointer data
, size_type size
);
562 /* ///////////////////////////////////////////////////////////////////////
565 inline void transport_packet::reverse(pointer data
, size_type size
)
567 // \note size must be divided by 1, 2, 4
568 EXTL_ASSERT(size
== 1 || size
== 2 || (size
% 4) == 0);
571 pointer pe
= pb
+ size
- 1;
580 inline void transport_packet::attach(const_pointer p
)
584 // attach packet data
585 buffer().attach(p
, en_packet_size
);
587 // adjust header data
588 reverse(data(), en_header_size
);
593 reverse(pcr_data(), 4);
594 reverse(pcr_data() + 4, 2);
600 reverse(opcr_data(), 4);
601 reverse(opcr_data() + 4, 2);
607 reverse(ltw_data(), en_ltw_size
);
611 inline transport_packet::
612 const_pointer
transport_packet::detach()
619 reverse(ltw_data(), en_ltw_size
);
625 reverse(opcr_data() + 4, 2);
626 reverse(opcr_data(), 4);
632 reverse(pcr_data() + 4, 2);
633 reverse(pcr_data(), 4);
636 // resume header data
637 reverse(data(), en_header_size
);
643 /* ///////////////////////////////////////////////////////////////////////
644 * ::extl::media namespace
646 EXTL_MEDIA_END_WHOLE_NAMESPACE
648 /* //////////////////////////////////////////////////////////////////// */
649 #endif /* EXTL_MEDIA_TS_TRANSPORT_PACKET_H */
650 /* //////////////////////////////////////////////////////////////////// */