正在显示
5 个修改的文件
包含
394 行增加
和
9 行删除
| @@ -486,6 +486,8 @@ Supported operating systems and hardware: | @@ -486,6 +486,8 @@ Supported operating systems and hardware: | ||
| 486 | ). | 486 | ). |
| 487 | 1. Support HLS(h.264+mp3) streaming, read | 487 | 1. Support HLS(h.264+mp3) streaming, read |
| 488 | [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301). | 488 | [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301). |
| 489 | +1. [dev] Support push MPEG-TS over UDP to SRS, read | ||
| 490 | +[#250](https://github.com/winlinvip/simple-rtmp-server/issues/250). | ||
| 489 | 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). | 491 | 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). |
| 490 | 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). | 492 | 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). |
| 491 | 1. [no-plan] Support multiple processes, for both origin and edge | 493 | 1. [no-plan] Support multiple processes, for both origin and edge |
| @@ -35,19 +35,20 @@ using namespace std; | @@ -35,19 +35,20 @@ using namespace std; | ||
| 35 | #include <srs_kernel_ts.hpp> | 35 | #include <srs_kernel_ts.hpp> |
| 36 | #include <srs_kernel_stream.hpp> | 36 | #include <srs_kernel_stream.hpp> |
| 37 | #include <srs_kernel_ts.hpp> | 37 | #include <srs_kernel_ts.hpp> |
| 38 | -#include <srs_core_autofree.hpp> | ||
| 39 | 38 | ||
| 40 | #ifdef SRS_AUTO_STREAM_CASTER | 39 | #ifdef SRS_AUTO_STREAM_CASTER |
| 41 | 40 | ||
| 42 | SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c) | 41 | SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c) |
| 43 | { | 42 | { |
| 44 | stream = new SrsStream(); | 43 | stream = new SrsStream(); |
| 44 | + context = new SrsTsContext(); | ||
| 45 | output = _srs_config->get_stream_caster_output(c); | 45 | output = _srs_config->get_stream_caster_output(c); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | SrsMpegtsOverUdp::~SrsMpegtsOverUdp() | 48 | SrsMpegtsOverUdp::~SrsMpegtsOverUdp() |
| 49 | { | 49 | { |
| 50 | srs_freep(stream); | 50 | srs_freep(stream); |
| 51 | + srs_freep(context); | ||
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) | 54 | int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) |
| @@ -85,10 +86,7 @@ int SrsMpegtsOverUdp::on_ts_packet(SrsStream* stream) | @@ -85,10 +86,7 @@ int SrsMpegtsOverUdp::on_ts_packet(SrsStream* stream) | ||
| 85 | { | 86 | { |
| 86 | int ret = ERROR_SUCCESS; | 87 | int ret = ERROR_SUCCESS; |
| 87 | 88 | ||
| 88 | - SrsTsPacket* packet = new SrsTsPacket(); | ||
| 89 | - SrsAutoFree(SrsTsPacket, packet); | ||
| 90 | - | ||
| 91 | - if ((ret = packet->decode(stream)) != ERROR_SUCCESS) { | 89 | + if ((ret = context->decode(stream)) != ERROR_SUCCESS) { |
| 92 | srs_error("mpegts: decode ts packet failed. ret=%d", ret); | 90 | srs_error("mpegts: decode ts packet failed. ret=%d", ret); |
| 93 | return ret; | 91 | return ret; |
| 94 | } | 92 | } |
| @@ -34,6 +34,7 @@ class sockaddr_in; | @@ -34,6 +34,7 @@ class sockaddr_in; | ||
| 34 | #include <string> | 34 | #include <string> |
| 35 | 35 | ||
| 36 | class SrsStream; | 36 | class SrsStream; |
| 37 | +class SrsTsContext; | ||
| 37 | class SrsConfDirective; | 38 | class SrsConfDirective; |
| 38 | 39 | ||
| 39 | #ifdef SRS_AUTO_STREAM_CASTER | 40 | #ifdef SRS_AUTO_STREAM_CASTER |
| @@ -45,6 +46,7 @@ class SrsMpegtsOverUdp | @@ -45,6 +46,7 @@ class SrsMpegtsOverUdp | ||
| 45 | { | 46 | { |
| 46 | private: | 47 | private: |
| 47 | SrsStream* stream; | 48 | SrsStream* stream; |
| 49 | + SrsTsContext* context; | ||
| 48 | std::string output; | 50 | std::string output; |
| 49 | public: | 51 | public: |
| 50 | SrsMpegtsOverUdp(SrsConfDirective* c); | 52 | SrsMpegtsOverUdp(SrsConfDirective* c); |
| @@ -39,6 +39,7 @@ using namespace std; | @@ -39,6 +39,7 @@ using namespace std; | ||
| 39 | #include <srs_kernel_buffer.hpp> | 39 | #include <srs_kernel_buffer.hpp> |
| 40 | #include <srs_kernel_utility.hpp> | 40 | #include <srs_kernel_utility.hpp> |
| 41 | #include <srs_kernel_stream.hpp> | 41 | #include <srs_kernel_stream.hpp> |
| 42 | +#include <srs_core_autofree.hpp> | ||
| 42 | 43 | ||
| 43 | // in ms, for HLS aac sync time. | 44 | // in ms, for HLS aac sync time. |
| 44 | #define SRS_CONF_DEFAULT_AAC_SYNC 100 | 45 | #define SRS_CONF_DEFAULT_AAC_SYNC 100 |
| @@ -401,6 +402,33 @@ SrsMpegtsFrame::SrsMpegtsFrame() | @@ -401,6 +402,33 @@ SrsMpegtsFrame::SrsMpegtsFrame() | ||
| 401 | key = false; | 402 | key = false; |
| 402 | } | 403 | } |
| 403 | 404 | ||
| 405 | +SrsTsContext::SrsTsContext() | ||
| 406 | +{ | ||
| 407 | +} | ||
| 408 | + | ||
| 409 | +SrsTsContext::~SrsTsContext() | ||
| 410 | +{ | ||
| 411 | +} | ||
| 412 | + | ||
| 413 | +int SrsTsContext::decode(SrsStream* stream) | ||
| 414 | +{ | ||
| 415 | + int ret = ERROR_SUCCESS; | ||
| 416 | + | ||
| 417 | + // parse util EOF of stream. | ||
| 418 | + // for example, parse multiple times for the PES_packet_length(0) packet. | ||
| 419 | + while (!stream->empty()) { | ||
| 420 | + SrsTsPacket* packet = new SrsTsPacket(); | ||
| 421 | + SrsAutoFree(SrsTsPacket, packet); | ||
| 422 | + | ||
| 423 | + if ((ret = packet->decode(stream)) != ERROR_SUCCESS) { | ||
| 424 | + srs_error("mpegts: decode ts packet failed. ret=%d", ret); | ||
| 425 | + return ret; | ||
| 426 | + } | ||
| 427 | + } | ||
| 428 | + | ||
| 429 | + return ret; | ||
| 430 | +} | ||
| 431 | + | ||
| 404 | SrsTsPacket::SrsTsPacket() | 432 | SrsTsPacket::SrsTsPacket() |
| 405 | { | 433 | { |
| 406 | sync_byte = 0; | 434 | sync_byte = 0; |
| @@ -412,11 +440,13 @@ SrsTsPacket::SrsTsPacket() | @@ -412,11 +440,13 @@ SrsTsPacket::SrsTsPacket() | ||
| 412 | adaption_field_control = SrsTsAdaptationFieldTypeReserved; | 440 | adaption_field_control = SrsTsAdaptationFieldTypeReserved; |
| 413 | continuity_counter = 0; | 441 | continuity_counter = 0; |
| 414 | adaptation_field = NULL; | 442 | adaptation_field = NULL; |
| 443 | + payload = NULL; | ||
| 415 | } | 444 | } |
| 416 | 445 | ||
| 417 | SrsTsPacket::~SrsTsPacket() | 446 | SrsTsPacket::~SrsTsPacket() |
| 418 | { | 447 | { |
| 419 | srs_freep(adaptation_field); | 448 | srs_freep(adaptation_field); |
| 449 | + srs_freep(payload); | ||
| 420 | } | 450 | } |
| 421 | 451 | ||
| 422 | int SrsTsPacket::decode(SrsStream* stream) | 452 | int SrsTsPacket::decode(SrsStream* stream) |
| @@ -471,6 +501,23 @@ int SrsTsPacket::decode(SrsStream* stream) | @@ -471,6 +501,23 @@ int SrsTsPacket::decode(SrsStream* stream) | ||
| 471 | // calc the user defined data size for payload. | 501 | // calc the user defined data size for payload. |
| 472 | int nb_payload = SRS_TS_PACKET_SIZE - (stream->pos() - pos); | 502 | int nb_payload = SRS_TS_PACKET_SIZE - (stream->pos() - pos); |
| 473 | 503 | ||
| 504 | + // optional: payload. | ||
| 505 | + if (adaption_field_control == SrsTsAdaptationFieldTypePayloadOnly || adaption_field_control == SrsTsAdaptationFieldTypeBoth) { | ||
| 506 | + if (pid == SrsTsPidPAT) { | ||
| 507 | + // 2.4.4.3 Program association Table | ||
| 508 | + srs_freep(payload); | ||
| 509 | + payload = new SrsTsPayloadPAT(this); | ||
| 510 | + } else { | ||
| 511 | + // left bytes as reserved. | ||
| 512 | + stream->skip(nb_payload); | ||
| 513 | + } | ||
| 514 | + | ||
| 515 | + if (payload && (ret = payload->decode(stream)) != ERROR_SUCCESS) { | ||
| 516 | + srs_error("ts: demux payload failed. ret=%d", ret); | ||
| 517 | + return ret; | ||
| 518 | + } | ||
| 519 | + } | ||
| 520 | + | ||
| 474 | return ret; | 521 | return ret; |
| 475 | } | 522 | } |
| 476 | 523 | ||
| @@ -713,6 +760,145 @@ int SrsTsAdaptationField::decode(SrsStream* stream) | @@ -713,6 +760,145 @@ int SrsTsAdaptationField::decode(SrsStream* stream) | ||
| 713 | return ret; | 760 | return ret; |
| 714 | } | 761 | } |
| 715 | 762 | ||
| 763 | +SrsTsPayloadPATProgram::SrsTsPayloadPATProgram() | ||
| 764 | +{ | ||
| 765 | + number = 0; | ||
| 766 | + pid = 0; | ||
| 767 | +} | ||
| 768 | + | ||
| 769 | +SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram() | ||
| 770 | +{ | ||
| 771 | +} | ||
| 772 | + | ||
| 773 | +SrsTsPayload::SrsTsPayload(SrsTsPacket* p) | ||
| 774 | +{ | ||
| 775 | + packet = p; | ||
| 776 | +} | ||
| 777 | + | ||
| 778 | +SrsTsPayload::~SrsTsPayload() | ||
| 779 | +{ | ||
| 780 | +} | ||
| 781 | + | ||
| 782 | +SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p) | ||
| 783 | +{ | ||
| 784 | + pointer_field = 0; | ||
| 785 | +} | ||
| 786 | + | ||
| 787 | +SrsTsPayloadPSI::~SrsTsPayloadPSI() | ||
| 788 | +{ | ||
| 789 | +} | ||
| 790 | + | ||
| 791 | +int SrsTsPayloadPSI::decode(SrsStream* stream) | ||
| 792 | +{ | ||
| 793 | + int ret = ERROR_SUCCESS; | ||
| 794 | + | ||
| 795 | + /** | ||
| 796 | + * When the payload of the Transport Stream packet contains PSI data, the payload_unit_start_indicator has the following | ||
| 797 | + * significance: if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value | ||
| 798 | + * shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field. If the | ||
| 799 | + * Transport Stream packet does not carry the first byte of a PSI section, the payload_unit_start_indicator value shall be '0', | ||
| 800 | + * indicating that there is no pointer_field in the payload. Refer to 2.4.4.1 and 2.4.4.2. This also applies to private streams of | ||
| 801 | + * stream_type 5 (refer to Table 2-29). | ||
| 802 | + */ | ||
| 803 | + if (packet->payload_unit_start_indicator) { | ||
| 804 | + if (!stream->require(1)) { | ||
| 805 | + ret = ERROR_STREAM_CASTER_TS_AF; | ||
| 806 | + srs_error("ts: demux PSI failed. ret=%d", ret); | ||
| 807 | + return ret; | ||
| 808 | + } | ||
| 809 | + pointer_field = stream->read_1bytes(); | ||
| 810 | + } | ||
| 811 | + | ||
| 812 | + return ret; | ||
| 813 | +} | ||
| 814 | + | ||
| 815 | +SrsTsPayloadPAT::SrsTsPayloadPAT(SrsTsPacket* p) : SrsTsPayloadPSI(p) | ||
| 816 | +{ | ||
| 817 | + nb_programs = 0; | ||
| 818 | + programs = NULL; | ||
| 819 | +} | ||
| 820 | + | ||
| 821 | +SrsTsPayloadPAT::~SrsTsPayloadPAT() | ||
| 822 | +{ | ||
| 823 | + srs_freep(programs); | ||
| 824 | +} | ||
| 825 | + | ||
| 826 | +int SrsTsPayloadPAT::decode(SrsStream* stream) | ||
| 827 | +{ | ||
| 828 | + int ret = ERROR_SUCCESS; | ||
| 829 | + | ||
| 830 | + if ((ret = SrsTsPayloadPSI::decode(stream)) != ERROR_SUCCESS) { | ||
| 831 | + return ret; | ||
| 832 | + } | ||
| 833 | + | ||
| 834 | + // atleast 8B without programs and crc32 | ||
| 835 | + if (!stream->require(8)) { | ||
| 836 | + ret = ERROR_STREAM_CASTER_TS_AF; | ||
| 837 | + srs_error("ts: demux PAT failed. ret=%d", ret); | ||
| 838 | + return ret; | ||
| 839 | + } | ||
| 840 | + // 1B | ||
| 841 | + table_id = (SrsTsPsiId)stream->read_1bytes(); | ||
| 842 | + | ||
| 843 | + // 2B | ||
| 844 | + section_length = stream->read_2bytes(); | ||
| 845 | + | ||
| 846 | + section_syntax_indicator = (section_length >> 15) & 0x01; | ||
| 847 | + const0_value = (section_length >> 14) & 0x01; | ||
| 848 | + section_length &= 0x0FFF; | ||
| 849 | + | ||
| 850 | + if (!stream->require(section_length)) { | ||
| 851 | + ret = ERROR_STREAM_CASTER_TS_AF; | ||
| 852 | + srs_error("ts: demux PAT section failed. ret=%d", ret); | ||
| 853 | + return ret; | ||
| 854 | + } | ||
| 855 | + int pos = stream->pos(); | ||
| 856 | + | ||
| 857 | + // 2B | ||
| 858 | + transport_stream_id = stream->read_2bytes(); | ||
| 859 | + | ||
| 860 | + // 1B | ||
| 861 | + current_next_indicator = stream->read_1bytes(); | ||
| 862 | + | ||
| 863 | + version_number = (current_next_indicator >> 1) & 0x1F; | ||
| 864 | + current_next_indicator &= 0x01; | ||
| 865 | + | ||
| 866 | + // TODO: FIXME: check the indicator. | ||
| 867 | + | ||
| 868 | + // 1B | ||
| 869 | + section_number = stream->read_1bytes(); | ||
| 870 | + // 1B | ||
| 871 | + last_section_number = stream->read_1bytes(); | ||
| 872 | + | ||
| 873 | + // multiple 4B program data. | ||
| 874 | + int program_bytes = section_length - 4 - (stream->pos() - pos); | ||
| 875 | + nb_programs = program_bytes / 4; | ||
| 876 | + if (nb_programs > 0) { | ||
| 877 | + srs_freep(programs); | ||
| 878 | + programs = new SrsTsPayloadPATProgram[nb_programs]; | ||
| 879 | + | ||
| 880 | + for (int i = 0; i < nb_programs; i++) { | ||
| 881 | + SrsTsPayloadPATProgram* program = programs + i; | ||
| 882 | + | ||
| 883 | + int tmpv = stream->read_4bytes(); | ||
| 884 | + program->number = (int16_t)((tmpv >> 16) & 0xFFFF); | ||
| 885 | + program->pid = (int16_t)(tmpv & 0x1FFF); | ||
| 886 | + } | ||
| 887 | + } | ||
| 888 | + | ||
| 889 | + // 4B | ||
| 890 | + if (!stream->require(4)) { | ||
| 891 | + ret = ERROR_STREAM_CASTER_TS_AF; | ||
| 892 | + srs_error("ts: demux PAT crc32 failed. ret=%d", ret); | ||
| 893 | + return ret; | ||
| 894 | + } | ||
| 895 | + CRC_32 = stream->read_4bytes(); | ||
| 896 | + | ||
| 897 | + // TODO: FIXME: verfy crc32. | ||
| 898 | + | ||
| 899 | + return ret; | ||
| 900 | +} | ||
| 901 | + | ||
| 716 | SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w) | 902 | SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w) |
| 717 | { | 903 | { |
| 718 | writer = w; | 904 | writer = w; |
| @@ -42,6 +42,7 @@ class SrsAvcAacCodec; | @@ -42,6 +42,7 @@ class SrsAvcAacCodec; | ||
| 42 | class SrsCodecSample; | 42 | class SrsCodecSample; |
| 43 | class SrsSimpleBuffer; | 43 | class SrsSimpleBuffer; |
| 44 | class SrsTsAdaptationField; | 44 | class SrsTsAdaptationField; |
| 45 | +class SrsTsPayload; | ||
| 45 | 46 | ||
| 46 | // Transport Stream packets are 188 bytes in length. | 47 | // Transport Stream packets are 188 bytes in length. |
| 47 | #define SRS_TS_PACKET_SIZE 188 | 48 | #define SRS_TS_PACKET_SIZE 188 |
| @@ -109,6 +110,22 @@ enum SrsTsAdaptationFieldType | @@ -109,6 +110,22 @@ enum SrsTsAdaptationFieldType | ||
| 109 | }; | 110 | }; |
| 110 | 111 | ||
| 111 | /** | 112 | /** |
| 113 | +* the context of ts, to decode the ts stream. | ||
| 114 | +*/ | ||
| 115 | +class SrsTsContext | ||
| 116 | +{ | ||
| 117 | +public: | ||
| 118 | + SrsTsContext(); | ||
| 119 | + virtual ~SrsTsContext(); | ||
| 120 | +public: | ||
| 121 | + /** | ||
| 122 | + * the stream contains only one ts packet. | ||
| 123 | + * @remark we will consume all bytes in stream. | ||
| 124 | + */ | ||
| 125 | + virtual int decode(SrsStream* stream); | ||
| 126 | +}; | ||
| 127 | + | ||
| 128 | +/** | ||
| 112 | * the packet in ts stream, | 129 | * the packet in ts stream, |
| 113 | * 2.4.3.2 Transport Stream packet layer, hls-mpeg-ts-iso13818-1.pdf, page 36 | 130 | * 2.4.3.2 Transport Stream packet layer, hls-mpeg-ts-iso13818-1.pdf, page 36 |
| 114 | * Transport Stream packets shall be 188 bytes long. | 131 | * Transport Stream packets shall be 188 bytes long. |
| @@ -203,14 +220,11 @@ public: | @@ -203,14 +220,11 @@ public: | ||
| 203 | u_int8_t continuity_counter; //4bits | 220 | u_int8_t continuity_counter; //4bits |
| 204 | private: | 221 | private: |
| 205 | SrsTsAdaptationField* adaptation_field; | 222 | SrsTsAdaptationField* adaptation_field; |
| 223 | + SrsTsPayload* payload; | ||
| 206 | public: | 224 | public: |
| 207 | SrsTsPacket(); | 225 | SrsTsPacket(); |
| 208 | virtual ~SrsTsPacket(); | 226 | virtual ~SrsTsPacket(); |
| 209 | public: | 227 | public: |
| 210 | - /** | ||
| 211 | - * the stream contains only one ts packet. | ||
| 212 | - * @remark we will consume all bytes in stream. | ||
| 213 | - */ | ||
| 214 | virtual int decode(SrsStream* stream); | 228 | virtual int decode(SrsStream* stream); |
| 215 | }; | 229 | }; |
| 216 | 230 | ||
| @@ -516,6 +530,189 @@ public: | @@ -516,6 +530,189 @@ public: | ||
| 516 | }; | 530 | }; |
| 517 | 531 | ||
| 518 | /** | 532 | /** |
| 533 | +* 2.4.4.4 Table_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 62 | ||
| 534 | +* The table_id field identifies the contents of a Transport Stream PSI section as shown in Table 2-26. | ||
| 535 | +*/ | ||
| 536 | +enum SrsTsPsiId | ||
| 537 | +{ | ||
| 538 | + // program_association_section | ||
| 539 | + SrsTsPsiIdPas = 0x00, | ||
| 540 | + // conditional_access_section (CA_section) | ||
| 541 | + SrsTsPsiIdCas = 0x01, | ||
| 542 | + // TS_program_map_section | ||
| 543 | + SrsTsPsiIdPms = 0x02, | ||
| 544 | + // TS_description_section | ||
| 545 | + SrsTsPsiIdDs = 0x03, | ||
| 546 | + // ISO_IEC_14496_scene_description_section | ||
| 547 | + SrsTsPsiIdSds = 0x04, | ||
| 548 | + // ISO_IEC_14496_object_descriptor_section | ||
| 549 | + SrsTsPsiIdOds = 0x05, | ||
| 550 | + // ITU-T Rec. H.222.0 | ISO/IEC 13818-1 reserved | ||
| 551 | + SrsTsPsiIdIso138181Start = 0x06, | ||
| 552 | + SrsTsPsiIdIso138181End = 0x37, | ||
| 553 | + // Defined in ISO/IEC 13818-6 | ||
| 554 | + SrsTsPsiIdIso138186Start = 0x38, | ||
| 555 | + SrsTsPsiIdIso138186End = 0x3F, | ||
| 556 | + // User private | ||
| 557 | + SrsTsPsiIdUserStart = 0x40, | ||
| 558 | + SrsTsPsiIdUserEnd = 0xFE, | ||
| 559 | + // forbidden | ||
| 560 | + SrsTsPsiIdForbidden = 0xFF, | ||
| 561 | +}; | ||
| 562 | + | ||
| 563 | +/** | ||
| 564 | +* the program of PAT of PSI ts packet. | ||
| 565 | +*/ | ||
| 566 | +class SrsTsPayloadPATProgram | ||
| 567 | +{ | ||
| 568 | +public: | ||
| 569 | + // 4B | ||
| 570 | + /** | ||
| 571 | + * Program_number is a 16-bit field. It specifies the program to which the program_map_PID is | ||
| 572 | + * applicable. When set to 0x0000, then the following PID reference shall be the network PID. For all other cases the value | ||
| 573 | + * of this field is user defined. This field shall not take any single value more than once within one version of the Program | ||
| 574 | + * Association Table. | ||
| 575 | + */ | ||
| 576 | + int16_t number; // 16bits | ||
| 577 | + // reserved 3bits | ||
| 578 | + /** | ||
| 579 | + * program_map_PID/network_PID 13bits | ||
| 580 | + * network_PID ¨C The network_PID is a 13-bit field, which is used only in conjunction with the value of the | ||
| 581 | + * program_number set to 0x0000, specifies the PID of the Transport Stream packets which shall contain the Network | ||
| 582 | + * Information Table. The value of the network_PID field is defined by the user, but shall only take values as specified in | ||
| 583 | + * Table 2-3. The presence of the network_PID is optional. | ||
| 584 | + */ | ||
| 585 | + int16_t pid; | ||
| 586 | +public: | ||
| 587 | + SrsTsPayloadPATProgram(); | ||
| 588 | + virtual ~SrsTsPayloadPATProgram(); | ||
| 589 | +}; | ||
| 590 | + | ||
| 591 | +/** | ||
| 592 | +* the payload of ts packet, can be PES or PSI payload. | ||
| 593 | +*/ | ||
| 594 | +class SrsTsPayload | ||
| 595 | +{ | ||
| 596 | +protected: | ||
| 597 | + SrsTsPacket* packet; | ||
| 598 | +public: | ||
| 599 | + SrsTsPayload(SrsTsPacket* p); | ||
| 600 | + virtual ~SrsTsPayload(); | ||
| 601 | +public: | ||
| 602 | + virtual int decode(SrsStream* stream) = 0; | ||
| 603 | +}; | ||
| 604 | + | ||
| 605 | +/** | ||
| 606 | +* the PSI payload of ts packet. | ||
| 607 | +* 2.4.4 Program specific information, hls-mpeg-ts-iso13818-1.pdf, page 59 | ||
| 608 | +*/ | ||
| 609 | +class SrsTsPayloadPSI : public SrsTsPayload | ||
| 610 | +{ | ||
| 611 | +public: | ||
| 612 | + // 1B | ||
| 613 | + /** | ||
| 614 | + * This is an 8-bit field whose value shall be the number of bytes, immediately following the pointer_field | ||
| 615 | + * until the first byte of the first section that is present in the payload of the Transport Stream packet (so a value of 0x00 in | ||
| 616 | + * the pointer_field indicates that the section starts immediately after the pointer_field). When at least one section begins in | ||
| 617 | + * a given Transport Stream packet, then the payload_unit_start_indicator (refer to 2.4.3.2) shall be set to 1 and the first | ||
| 618 | + * byte of the payload of that Transport Stream packet shall contain the pointer. When no section begins in a given | ||
| 619 | + * Transport Stream packet, then the payload_unit_start_indicator shall be set to 0 and no pointer shall be sent in the | ||
| 620 | + * payload of that packet. | ||
| 621 | + */ | ||
| 622 | + int8_t pointer_field; | ||
| 623 | +public: | ||
| 624 | + SrsTsPayloadPSI(SrsTsPacket* p); | ||
| 625 | + virtual ~SrsTsPayloadPSI(); | ||
| 626 | +public: | ||
| 627 | + virtual int decode(SrsStream* stream); | ||
| 628 | +}; | ||
| 629 | + | ||
| 630 | +/** | ||
| 631 | +* the PAT payload of PSI ts packet. | ||
| 632 | +* 2.4.4.3 Program association Table, hls-mpeg-ts-iso13818-1.pdf, page 61 | ||
| 633 | +* The Program Association Table provides the correspondence between a program_number and the PID value of the | ||
| 634 | +* Transport Stream packets which carry the program definition. The program_number is the numeric label associated with | ||
| 635 | +* a program. | ||
| 636 | +*/ | ||
| 637 | +class SrsTsPayloadPAT : public SrsTsPayloadPSI | ||
| 638 | +{ | ||
| 639 | +public: | ||
| 640 | + // 1B | ||
| 641 | + /** | ||
| 642 | + * This is an 8-bit field, which shall be set to 0x00 as shown in Table 2-26. | ||
| 643 | + */ | ||
| 644 | + SrsTsPsiId table_id; //8bits | ||
| 645 | + | ||
| 646 | + // 2B | ||
| 647 | + /** | ||
| 648 | + * The section_syntax_indicator is a 1-bit field which shall be set to '1'. | ||
| 649 | + */ | ||
| 650 | + int8_t section_syntax_indicator; //1bit | ||
| 651 | + /** | ||
| 652 | + * const value, must be '0' | ||
| 653 | + */ | ||
| 654 | + int8_t const0_value; //1bit | ||
| 655 | + // 2bits reserved. | ||
| 656 | + /** | ||
| 657 | + * This is a 12-bit field, the first two bits of which shall be '00'. The remaining 10 bits specify the number | ||
| 658 | + * of bytes of the section, starting immediately following the section_length field, and including the CRC. The value in this | ||
| 659 | + * field shall not exceed 1021 (0x3FD). | ||
| 660 | + */ | ||
| 661 | + u_int16_t section_length; //12bits | ||
| 662 | + | ||
| 663 | + // 2B | ||
| 664 | + /** | ||
| 665 | + * This is a 16-bit field which serves as a label to identify this Transport Stream from any other | ||
| 666 | + * multiplex within a network. Its value is defined by the user. | ||
| 667 | + */ | ||
| 668 | + u_int16_t transport_stream_id; //16bits | ||
| 669 | + | ||
| 670 | + // 1B | ||
| 671 | + // 2bits reerverd. | ||
| 672 | + /** | ||
| 673 | + * This 5-bit field is the version number of the whole Program Association Table. The version number | ||
| 674 | + * shall be incremented by 1 modulo 32 whenever the definition of the Program Association Table changes. When the | ||
| 675 | + * current_next_indicator is set to '1', then the version_number shall be that of the currently applicable Program Association | ||
| 676 | + * Table. When the current_next_indicator is set to '0', then the version_number shall be that of the next applicable Program | ||
| 677 | + * Association Table. | ||
| 678 | + */ | ||
| 679 | + int8_t version_number; //5bits | ||
| 680 | + /** | ||
| 681 | + * A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is | ||
| 682 | + * currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next | ||
| 683 | + * table to become valid. | ||
| 684 | + */ | ||
| 685 | + int8_t current_next_indicator; //1bit | ||
| 686 | + | ||
| 687 | + // 1B | ||
| 688 | + /** | ||
| 689 | + * This 8-bit field gives the number of this section. The section_number of the first section in the | ||
| 690 | + * Program Association Table shall be 0x00. It shall be incremented by 1 with each additional section in the Program | ||
| 691 | + * Association Table. | ||
| 692 | + */ | ||
| 693 | + u_int8_t section_number; //8bits | ||
| 694 | + | ||
| 695 | + // 1B | ||
| 696 | + /** | ||
| 697 | + * This 8-bit field specifies the number of the last section (that is, the section with the highest | ||
| 698 | + * section_number) of the complete Program Association Table. | ||
| 699 | + */ | ||
| 700 | + u_int8_t last_section_number; //8bits | ||
| 701 | + | ||
| 702 | + // multiple 4B program data. | ||
| 703 | + int nb_programs; | ||
| 704 | + SrsTsPayloadPATProgram* programs; | ||
| 705 | + | ||
| 706 | + // 4B | ||
| 707 | + int32_t CRC_32; //32bits | ||
| 708 | +public: | ||
| 709 | + SrsTsPayloadPAT(SrsTsPacket* p); | ||
| 710 | + virtual ~SrsTsPayloadPAT(); | ||
| 711 | +public: | ||
| 712 | + virtual int decode(SrsStream* stream); | ||
| 713 | +}; | ||
| 714 | + | ||
| 715 | +/** | ||
| 519 | * write data from frame(header info) and buffer(data) to ts file. | 716 | * write data from frame(header info) and buffer(data) to ts file. |
| 520 | * it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter | 717 | * it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter |
| 521 | */ | 718 | */ |
-
请 注册 或 登录 后发表评论