PS流封装

概述

背景

由于工作需要,研究国标28181有半年多啦,里面涉及的媒体封装为不太常用的PS。通过研究协议文档及网上相关优秀的文章,结合自己的理解,整理记录如下。如理解有偏差,请指正。

封装请添加图片描述
定义
缩写全称描述
PSProgram Stream节目流
ESElementary Stream原始流:如H264 / G711
PESPacketized Elementary Stream分组的原始流
PES packetPES packetPES包。用于携带基本流数据。组成:包头 + 连续的基本流数据。
PES StreamPES streamPES流,由相同流ID的PES包组成。
STDSystem Target Decoder系统目标解码器
PTSPresentation Timestamps显示时间戳
DTSDecoding Timestamps解码时间戳
SCRSystem Clock Reference系统时钟参考
PCRProgram Clock Reference节目时钟参考

格式

节目流

PS 打包流程:

MPEG2_program_stream() {
    do {
        pack()
    } while (nextbits() == pack_start_code)
    MPEG_program_end_code // 0x000001B9
}

pack() {
    pack_header()
    while (nextbits() == packet_start_code_prefix) {
        PES_packet()
    }
}
节目流头

PS Header 打包流程:

pack_header() {
    pack_start_code                        // 32 bslbf
    '01'                                   // 2  bslbf
    system_clock_reference_base[32..30]    // 3  bslbf
    marker_bit                             // 1  bslbf
    system_clock_reference_base[29..15]    // 15 bslbf
    marker_bit                             // 1  bslbf
    system_clock_reference_base[14..0]     // 15 bslbf
    marker_bit                             // 1  bslbf
    system_clock_reference_extension       // 9  uimsbf
    marker_bit                             // 1  bslbf
    program_mux_rate                       // 22 uimsbf
    marker_bit                             // 1  bslbf
    marker_bit                             // 1  bslbf
    reserved                               // 5  bslbf
    pack_stuffing_length                   // 3  uimsbf
    for (i = 0; i < pack_stuffing_length; i++) {
        stuffing_byte                      // 8  bslbf
    }
    if (nextbits() == system_header_start_code) {
        system_header()
    }
}

字段描述

字段描述
pack_start_code起始码:0x000001BA
system_clock_reference_base; system_clock_reference_extension系统时钟参考(SCR)分为两部分:系统时钟参考基础部分和扩张部分,分别占33bits和9bits。
SCR(i) = SCR_base(i) × 300 + SCR_ext(i)
SCR_base:一般设置为PTS
SCR_ext:0
300存在的原因:PTS以90MHz为单位,SCR以27MHz为单位。
参考代码:
scr_base = dts >= 3600 ? (dts - 3600) : 0;
scr_ext = 0;
marker_bit标记位:固定为1
program_mux_rate节目复合率:22位表示;单位50字节/秒;不允许取0值。
应该就是码率的一种表示方式,如:码率1M,则该值为20971。
即:20971 * 50 = 1 * 1024 *1024
参考代码:program_mux_rate = bit_rate / 50;
reserved保留位,无特殊说明,默认为1。
pack_stuffing_length3位,规定该字段后填充字节的个数。
stuffing_byte填充字节,8位,固定为0xFF。
参考代码:
data[13] = 0xFA;
data[14] = 0xFF;
data[15] = 0xFF;
系统头

PS System Header 打包流程:

system_header() {
    system_header_start_code        // 32 bslbf
    header_length                   // 16 uimsbf
    marker_bit                      // 1  bslbf
    rate_bound                      // 22 uimsbf
    marker_bit                      // 1  bslbf
    audio_bound                     // 6  uimsbf
    fixed_flag                      // 1  bslbf
    CSPS_flag                       // 1  bslbf
    system_audio_lock_flag          // 1  bslbf
    system_video_lock_flag          // 1  bslbf
    marker_bit                      // 1  bslbf
    video_bound                     // 5  uimsbf
    packet_rate_restriction_flag    // 1  bslbf
    reserved_bits                   // 7  bslbf
    while (nextbits() == '1') {
        stream_id                   // 8  uimsbf
        '11'                        // 2  bslbf
        P-STD_buffer_bound_scale    // 1  bslbf
        P-STD_buffer_size_bound     // 13 uimsbf
    }
}

字段描述

字段描述
system_header_start_code起始码:0x000001BB
header_length头长度,16位,不包括起始码和该长度自身。
rate_bound速率界限,22位,取值不小于编码在节目流的任何包中的program_mux_rate字段的最大值。可以理解为,最大码率。
audio_bound音频界限,6位,取值是在从0到32的闭区间中的整数。最大活跃音频流的数目。默认可以设置为1个。
fixed_flag固定标志,1位,1:固定码率;0:可变码率。
CSPS_flag不清楚,默认设置为0。
system_audio_lock_flag不清楚,默认设置为0。
system_video_lock_flag不清楚,默认设置为0。
video_bound视频界限,5位,取值是在从0到16的闭区间中的整数。表示最大活跃视频流的数目。默认可以设置为1个。
packet_rate_restriction_flag不清楚,默认设置为0。
stream_id流ID。
视频流:基数:0xE0; 增量:video_bound
音频流:基数:0xC0; 增量:audio_bound
例如:
第一个视频流为:0xE0
第二个视频流为:0xE1
STD_buffer_bound_scale1位,缓冲区界限比例。被下面的字段使用。
视频流:1
音频流:0
STD_buffer_size_bound13位,缓冲区大小:根据上面比例字段来区分计算。
if (P-STD_buffer_bound_scale == 0) {
Buffer_Size = P-STD_buffer_size_bound x 128;
} else {
Buffer_Size = P-STD_buffer_size_bound x 1024;
}
例如:
P-STD_buffer_size_bound的值为40。缓冲区大小的计算方式为:
视频流: 40 x 1024 = 40960;
音频流: 40 x 128 = 5120;
映射

PS Map 打包流程:

program_stream_map() {
    packet_start_code_prefix             // 24 bslbf
    map_stream_id                        // 8  uimsbf
    program_stream_map_length            // 16 uimsbf
    current_next_indicator               // 1  bslbf
    reserved                             // 2  bslbf
    program_stream_map_version           // 5  uimsbf 
    reserved                             // 7  bslbf
    marker_bit                           // 1  bslbf
    program_stream_info_length           // 16 uimsbf
    for (i = 0; i < N; i++) {
        descriptor()
    }
    elementary_stream_map_length         // 16 uimsbf
    for (i = 0; i < N1; i++) {
        stream_type                      // 8  uimsbf
        elementary_stream_id             // 8  uimsbf
        elementary_stream_info_length    // 16 uimsbf
        for (i = 0; i < N2; i++) {
            descriptor()
        }
    }
    CRC_32                               // 32 rpchof
}

字段描述

字段描述
packet_start_code_prefix起始码前缀:0x000001
map_stream_id固定为:0xBC
program_stream_map_length头长度,16位,不包括起始码和该长度自身。
current_next_indicator设置为1,表示该PSM当前有效。为0时表示该PSM尚未有效并且下一个节目流映射表将生效。一般设置为1。
program_stream_map_versionPSM版本号。理论上,PSM变化时需要自增1,对32取模。
program_stream_info_length16位,用于表示流描述信息的长度。一般为0。
elementary_stream_map_length16位,用于表示下面所有元素流信息的总长度。
stream_type流类型,如:
H264: 0x1B
H265: 0x24
G711A: 0x90
elementary_stream_id见PS System Header中stream_id。
elementary_stream_info_length16位,用于表示接下来流描述信息的长度。一般为0。
CRC_32见13818-1附录A。
PES包
PES_packet() {
    packet_start_code_prefix            // 24 bslbf
    stream_id                           // 8  uimsbf
    PES_packet_length                   // 16 uimsbf
    if (stream_id != program_stream_map
        && stream_id != padding_stream
        && stream_id != private_stream_2
        && stream_id != ECM
        && stream_id != EMM
        && stream_id != program_stream_directory
        && stream_id != DSMCC_stream
        && stream_id != ITU-T Rec.H.222.1 type E stream) {
            '10'                        // 2 bslbf
            PES_scrambling_control      // 2 bslbf
            PES_priority                // 1 bslbf
            data_alignment_indicator    // 1 bslbf
            copyright                   // 1 bslbf
            original_or_copy            // 1 bslbf
            PTS_DTS_flags               // 2 bslbf
            ESCR_flag                   // 1 bslbf
            ES_rate_flag                // 1 bslbf
            DSM_trick_mode_flag         // 1 bslbf   
            additional_copy_info_flag   // 1 bslbf
            PES_CRC_flag                // 1 bslbf
            PES_extension_flag          // 1 bslbf
            PES_header_data_length      // 8 bslbf
            if (PTS_DTS_flags == '10') {
                '0010'                  // 4  bslbf
                PTS[32..30]             // 3  bslbf
                marker_bit              // 1  bslbf
                PTS[29..15]             // 15 bslbf
                marker_bit              // 1  bslbf
                PTS[14..0]              // 15 bslbf
                marker_bit              // 1  bslbf
            }
            if (PTS_DTS_flags == '11') {
                '0011'                  // 4  bslbf
                PTS[32..30]             // 3  bslbf
                marker_bit              // 1  bslbf
                PTS[29..15]             // 15 bslbf
                marker_bit              // 1  bslbf
                PTS[14..0]              // 15 bslbf
                marker_bit              // 1  bslbf
                '0001'                  // 4  bslbf
                DTS[32..30]             // 3  bslbf
                marker_bit              // 1  bslbf
                DTS[29..15]             // 15 bslbf
                marker_bit              // 1  bslbf
                DTS[14..0]              // 15 bslbf
                marker_bit              // 1  bslbf
            }
            if (ESCR_flag == '1') {
                reserved                // 2  bslbf
                ESCR_base[32..30]       // 3  bslbf
                marker_bit              // 1  bslbf
                ESCR_base[29..15]       // 15 bslbf
                marker_bit              // 1  bslbf
                ESCR_base[14..0]        // 15 bslbf
                marker_bit              // 1  bslbf
                ESCR_extension          // 9  bslbf
                marker_bit              // 1  bslbf
            }
            if (ES_rate_flag == '1') {
                marker_bit              // 1  bslbf
                ES_rate                 // 22 bslbf
                marker_bit              // 1  bslbf
            }
            if (DSM_trick_mode_flag == '1') {
                trick_mode_control      // 3  bslbf
                if (trick_mode_control == fast_forward) {
                    field_id            // 2  bslbf
                    intra_slice_refresh // 1  bslbf
                    frequency_truncation// 2  bslbf
                } else if (trick_mode_control == slow_motion) {
                    rep_cntrl           // 5  bslbf
                } else if (trick_mode_control == freeze_frame) {
                    field_id            // 2  bslbf
                    reserved            // 3  bslbf
                } else if (trick_mode_control == fast_reverse) {
                    field_id            // 2  bslbf
                    intra_slice_refresh // 1  bslbf
                    frequency_truncation// 2  bslbf
                } else if (trick_mode_control == slow_reverse) {
                    rep_cntrl           // 5  bslbf
                } else {
                    reserved            // 5  bslbf
                }
            }
            if (additional_copy_info_flag == '1') {
                marker_bit              // 1  bslbf
                additional_copy_info    // 7  bslbf
            }
            if (PES_CRC_flag == '1') {
                previous_PES_packet_CRC // 16 bslbf
            }
            if (PES_extension_flag == '1') {
                PES_private_data_flag   // 1  bslbf
                pack_header_field_flag  // 1  bslbf
                program_packet_sequence_counter_flag // 1  bslbf
                P-STD_buffer_flag       // 1  bslbf
                reserved                // 3  bslbf
                PES_extension_flag_2    // 1  bslbf
                if (PES_private_data_flag == '1') {
                    PES_private_data    // 128 bslbf
                }
                if (pack_header_field_flag == '1') {
                    pack_field_length   // 8  bslbf
                    pack_header()
                }
                if (program_packet_sequence_counter_flag == '1') {
                    marker_bit             // 1  bslbf
                    program_packet_sequence_counter // 7  bslbf
                    marker_bit             // 1  bslbf
                    MPEG1_MPEG2_identifier // 1  bslbf
                    original_stuff_length  // 6  bslbf
                }
                if (P-STD_buffer_flag == '1') {
                    '01'                // 2  bslbf
                    P-STD_buffer_scale  // 1  bslbf
                    P-STD_buffer_size   // 13 bslbf
                }
                if (PES_extension_flag_2 == '1') {
                    marker_bit          // 1  bslbf
                    PES_extension_field_length // 7  bslbf
                    for (i=0; i < PES_extension_field_length; i++) {
                        reserved        // 8  bslbf
                    }
                }                
            }
            for (i=0; i < N1; i++) {
                stuffing_byte           // 8  bslbf
            }
            for (i=0; i < N2; i++) {
                PES_packet_data_byte    // 8  bslbf
            }
        } else if (stream_id != program_stream_map
        || stream_id != private_stream_2
        || stream_id != ECM
        || stream_id != EMM
        || stream_id != program_stream_directory
        || stream_id != DSMCC_stream
        || stream_id != ITU-T Rec.H.222.1 type E stream) {
            for (i=0; i < PES_packet_length; i++) {
                PES_packet_data_byte    // 8  bslbf
            }
        } else if (stream_id == padding_stream) {
            for (i=0; i < PES_packet_length; i++) {
                padding_byte            // 8  bslbf
            }
        }
}

示例

海康摄像头包

0000   04 f9 38 a3 18 0e ec c8 9c 02 ec 91 08 00 45 00   ..8...........E.
0010   05 ba 73 a2 40 00 40 06 cd ad ac 10 12 8c c0 a8   ..s.@.@.........
0020   74 a9 3a d4 8d 76 00 8e 04 46 be 63 d8 04 80 18   t.:..v...F.c....
0030   01 c9 e2 3a 00 00 01 01 08 0a 00 06 77 e9 cd 48   ...:........w..H
0040   1c 11 
             05 84 
                   80 60 00 00 00 00 00 00 03 92 19 f1   .....`..........
0050   00 00 01 ba 45 82 f6 63 64 01 05 45 0f fe ff ff   ....E..cd..E....
0060   00 01 b7 8e 
                   00 00 01 bb 00 12 82 a2 87 04 e1 7f   ................
0070   e0 e0 80 c0 c0 08 bd e0 80 bf e0 80 
                                           00 00 01 bc   ................
0080   00 5e ec ff 00 24 40 0e 48 4b 01 00 16 45 ae f0   .^...$@.HK...E..
0090   35 37 00 ff ff ff 41 12 48 4b 00 01 02 03 04 05   57....A.HK......
00a0   06 07 08 09 0a 0b 0c 0d 0e 0f 00 30 1b e0 00 1c   ...........0....
00b0   42 0e 07 10 10 ea 0a 00 05 a0 11 30 00 00 1c 21   B..........0...!
00c0   2a 0a 7f ff 00 00 07 08 1f fe 40 b4 90 c0 00 0c   *.........@.....
00d0   43 0a 01 40 fe 00 7d 03 03 e8 03 ff fe 95 28 7d   C..@..}.......(}

00e0   00 00 01 e0 00 3a 8c 80 09 21 60 bd 98 d9 ff ff   .....:...!`.....
00f0   ff fc 00 00 00 01 67 64 00 32 ad 84 01 0c 20 08   ......gd.2.... .
0100   61 00 43 08 02 18 40 10 c2 00 84 3b 50 14 00 5a   a.C...@....;P..Z
0110   d3 70 10 10 14 00 00 03 00 04 00 00 03 00 ca 10   .p..............

0120   00 00 01 e0 00 0e 8c 00 03 ff ff fc 00 00 00 01   ................
0130   68 ee 3c b0 
                   
                   00 00 01 e0 00 0e 8c 00 02 ff fc 00   h.<.............
0140   00 00 01 06 e5 01 7b 80 
                               
                               00 00 01 e0 ff c6 8c 00   ......{.........
0150   05 ff ff ff ff fd 00 00 00 01 65 b8 00 00 03 02   ..........e.....
0160   0d 0c 13 ff 7c 83 58 2c fe 06 fd 07 ff 26 d4 c2   ....|.X,.....&..
0170   51 bf 27 93 c5 95 1b 0e 3b 68 be d6 af 24 b4 31   Q.'.....;h...$.1
0180   88 b8 e8 45 c4 94 ba 56 53 97 99 ff 62 60 92 23   ...E...VS...b`.#
0190   8d 6f be 11 35 ec 5a a9 cc 4b e3 18 aa bb 3c 4e   .o..5.Z..K....<N
01a0   09 1a 14 4b cc 95 f1 5c 3c ba f7 8a 81 7c 77 ce   ...K...\<....|w.
01b0   fc 25 e0 cc 31 ad cc fa 2e 16 e2 99 51 09 b6 9c   .%..1.......Q...
01c0   1e e5 16 a3 3b 11 00 8f bb 87 aa b5 0e 66 4c 44   ....;........fLD
01d0   f2 1a 4a e4 28 04 a0 e9 c9 ea 37 11 6b 49 37 51   ..J.(.....7.kI7Q

附录

流类型
// ISO/IEC 13818-1:2015 (E)
// 2.4.4.9 Semantic definition of fields in transport stream program map section
// Table 2-34 - Stream type assignments(p69)
enum EPSI_STREAM_TYPE
{
	PSI_STREAM_RESERVED			= 0x00, // ITU-T | ISO/IEC Reserved
	PSI_STREAM_MPEG1			= 0x01, // ISO/IEC 11172-2 Video
	PSI_STREAM_MPEG2			= 0x02, // Rec. ITU-T H.262 | ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrained parameter video stream(see Note 2)
	PSI_STREAM_AUDIO_MPEG1		= 0x03, // ISO/IEC 11172-3 Audio
	PSI_STREAM_MP3				= 0x04, // ISO/IEC 13818-3 Audio
	PSI_STREAM_PRIVATE_SECTION	= 0x05, // Rec. ITU-T H.222.0 | ISO/IEC 13818-1 private_sections
	PSI_STREAM_PRIVATE_DATA		= 0x06, // Rec. ITU-T H.222.0 | ISO/IEC 13818-1 PES packets containing private data
	PSI_STREAM_MHEG				= 0x07, // ISO/IEC 13522 MHEG
	PSI_STREAM_DSMCC			= 0x08, // Rec. ITU-T H.222.0 | ISO/IEC 13818-1 Annex A DSM-CC
	PSI_STREAM_H222_ATM			= 0x09, // Rec. ITU-T H.222.1
	PSI_STREAM_DSMCC_A			= 0x0a, // ISO/IEC 13818-6(Extensions for DSM-CC) type A
	PSI_STREAM_DSMCC_B			= 0x0b, // ISO/IEC 13818-6(Extensions for DSM-CC) type B
	PSI_STREAM_DSMCC_C			= 0x0c, // ISO/IEC 13818-6(Extensions for DSM-CC) type C
	PSI_STREAM_DSMCC_D			= 0x0d, // ISO/IEC 13818-6(Extensions for DSM-CC) type D
	PSI_STREAM_H222_Aux			= 0x0e, // Rec. ITU-T H.222.0 | ISO/IEC 13818-1 auxiliary
	PSI_STREAM_AAC				= 0x0f, // ISO/IEC 13818-7 Audio with ADTS transport syntax
	PSI_STREAM_MPEG4			= 0x10, // ISO/IEC 14496-2 Visual
	PSI_STREAM_MPEG4_AAC_LATM	= 0x11, // ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3
	PSI_STREAM_MPEG4_PES		= 0x12, // ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets
	PSI_STREAM_MPEG4_SECTIONS	= 0x13, // ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC 14496_sections
	PSI_STREAM_MPEG2_SDP		= 0x14, // ISO/IEC 13818-6 Synchronized Download Protocol
	PSI_STREAM_PES_META			= 0x15, // Metadata carried in PES packets
	PSI_STREAM_SECTION_META		= 0x16, // Metadata carried in metadata_sections
	PSI_STREAM_DSMCC_DATA		= 0x17, // Metadata carried in ISO/IEC 13818-6 Data Carousel
	PSI_STREAM_DSMCC_OBJECT		= 0x18, // Metadata carried in ISO/IEC 13818-6 Object Carousel
	PSI_STREAM_DSMCC_SDP		= 0x19, // Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol
	PSI_STREAM_MPEG2_IPMP		= 0x1a, // IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)
	PSI_STREAM_H264				= 0x1b, // H.264
	PSI_STREAM_MPEG4_AAC		= 0x1c, // ISO/IEC 14496-3 Audio, without using any additional transport syntax, such as DST, ALS and SLS
	PSI_STREAM_MPEG4_TEXT		= 0x1d, // ISO/IEC 14496-17 Text
	PSI_STREAM_AUX_VIDEO		= 0x1e, // Auxiliary video stream as defined in ISO/IEC 23002-3
	PSI_STREAM_H264_SVC			= 0x1f, // SVC video sub-bitstream of an AVC video stream conforming to one or more profiles defined in Annex G of Rec. ITU-T H.264 | ISO/IEC 14496-10
	PSI_STREAM_H264_MVC			= 0x20, // MVC video sub-bitstream of an AVC video stream conforming to one or more profiles defined in Annex H of Rec. ITU-T H.264 | ISO/IEC 14496-10
	PSI_STREAM_JPEG_2000		= 0x21, // Video stream conforming to one or more profiles as defined in Rec. ITU-T T.800 | ISO/IEC 15444-1
	PSI_STREAM_MPEG2_3D			= 0x22, // Additional view Rec. ITU-T H.262 | ISO/IEC 13818-2 video stream for service-compatible stereoscopic 3D services
	PSI_STREAM_MPEG4_3D			= 0x23, // Additional view Rec. ITU-T H.264 | ISO/IEC 14496-10 video stream conforming to one or more profiles defined in Annex A for service-compatible stereoscopic 3D services
	PSI_STREAM_H265				= 0x24, // Rec. ITU-T H.265 | ISO/IEC 23008-2 video stream or an HEVC temporal video sub-bitstream
	PSI_STREAM_H265_subset		= 0x25, // HEVC temporal video subset of an HEVC video stream conforming to one or more profiles defined in Annex A of Rec. ITU-T H.265 | ISO/IEC 23008-2
	PSI_STREAM_H264_MVCD		= 0x26, // MVCD video sub-bitstream of an AVC video stream conforming to one or more profiles defined in Annex I of Rec. ITU-T H.264 | ISO/IEC 14496-10
	PSI_STREAM_VP8				= 0x9d,
	PSI_STREAM_VP9				= 0x9e,
	PSI_STREAM_AV1				= 0x9f,
	// 0x27-0x7E Rec. ITU-T H.222.0 | ISO/IEC 13818-1 Reserved
	PSI_STREAM_IPMP				= 0x7F, // IPMP stream
	// 0x80-0xFF User Private
	PSI_STREAM_VIDEO_CAVS		= 0x42, // ffmpeg/libavformat/mpegts.h
	PSI_STREAM_AUDIO_AC3		= 0x81, // ffmpeg/libavformat/mpegts.h
    PSI_STREAM_AUDIO_EAC3       = 0x87, // ffmpeg/libavformat/mpegts.h
	PSI_STREAM_AUDIO_DTS		= 0x8a, // ffmpeg/libavformat/mpegts.h
	PSI_STREAM_VIDEO_DIRAC		= 0xd1, // ffmpeg/libavformat/mpegts.h
	PSI_STREAM_VIDEO_VC1		= 0xea, // ffmpeg/libavformat/mpegts.h
	PSI_STREAM_VIDEO_SVAC		= 0x80, // GBT 25724-2010 SVAC(2014)
	PSI_STREAM_AUDIO_SVAC		= 0x9B, // GBT 25724-2010 SVAC(2014)
	PSI_STREAM_AUDIO_G711A		= 0x90,	// GBT 25724-2010 SVAC(2014)
    PSI_STREAM_AUDIO_G711U      = 0x91,
	PSI_STREAM_AUDIO_G722		= 0x92,
	PSI_STREAM_AUDIO_G723		= 0x93,
	PSI_STREAM_AUDIO_G729		= 0x99,
	PSI_STREAM_AUDIO_OPUS		= 0x9c,
};

参考

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值