[Mediaserver]mini_Mediaserver_1-코드설명/code description-fmt,cs_id(1-3)

👉🏻 void RtmpSession::read_chunk_header() {} 함수에 대한 설명입니다.
This is a description of the void RtmpSession::read_chunk_header() {} function.

✔️ 여기서는 소켓에서 1바이트(8비트)를 읽어와서 fmt와 cs_id를 추출합니다.
Here, we read 1 byte (8 bits) from the socket to extract fmt and cs_id.

fmt 값/valueMessageHeader 크기의미 / meaning
011Byte풀 헤더/Full Header
17Bytestream_id 생략 / Stream_id omitted
23Byteonly timestamp
30Byte헤더 없음
no header

✔️ 소켓에서1 바이트 읽기
Read 1 byte from socket

— 1바이트는 8비트입니다.(7,6,5,4,3,2,1,0)
1 byte is 8 bits. (7,6,5,4,3,2,1,0)

— 8비트의 값은 설명을 위해 0x43 = 01000011 = 67 이 값으로 합니다.
For the purpose of explanation, the 8-bit value is set to 0x43 = 01000011 = 67.

socket_.async_read_some(asio::buffer(&chunk_basic_header_, 1)

✔️ 변수 생략 / Variable omitted

— C++문법상 사용되지 않는 변수명 생략 가능해서 생략되었습니다.
Variable names not used in C++ syntax can be omitted, so they have been omitted.

# 변수 생략된 코드
# Code with omitted variables
[this, self](std::error_code ec, std::size_t) {...}

# 변수 생략 이전
# Before variable omission
[this, self](std::error_code ec, std::size_t bytes_transferred) { ... }

✔️ fmt값 추출,오른쪽으로 6비트 밀기
Extract fmt value, shift right by 6 bits

— fmt값은 0,1,2,3밖에 없기 때문에 0,1비트위치의 값만 사용합니다.
Since fmt values ​​are only 0, 1, 2, and 3, only the values ​​at bit positions 0 and 1 are used.

— 그래서 6비트 밀어서 7번비트가 1번비트에 오도록 비트를 내립니다.
So, we shift by 6 bits to lower the bit so that the 7th bit becomes the 1st bit.

— 비트 이동후에
After moving the beat

uint8_t fmt = (chunk_basic_header_ >> 6) & 0x03;

— 오른쪽으로 6비트 밀기란?(예:)
What is shifting 6 bits to the right? (e.g.)

비트번호/bit bumber: 
         [7 6][ 5 4 3 2 1 0]
         [fmt][   cs_id   ]
          2-bit   6-bit
0x43 = 01000011 = 67

원본/original value: 
0 1 0 0 0 0 1 1

>> 6 적용/apply
1. 오른쪽으로 1칸/1 spaces to the right: 00100001
2. 오른쪽으로 2칸/2 spaces to the right: 00010000
3. 오른쪽으로 3칸/3 spaces to the right: 00001000
4. 오른쪽으로 4칸/4 spaces to the right: 00000100
5. 오른쪽으로 5칸/5 spaces to the right: 00000010
6. 오른쪽으로 6칸/6 spaces to the right: 00000001

& 0x03 이 6비트 0으로 덮어 씌우기
& Overwrite 0x03 with 6-bit 0

–AND연산은 둘다 1인 경우만 1이됨(&)
The AND operation returns 1 only when both are 1 (&)

  01000001 ← >> 6 비트이동한 결과 / 6 Bit shift result
& 00000011 ← 0x03 마스크 / 0x03 mask

  00000001 ← 하위 2비트만 살아남음 / Only the lower 2 bits survive

✔️ cs_id 추출 / Extract cs_id

& 0x3F는 하위 6비트만 뽑아서 cs_id 만드는 입니다.
& 0x3F is used to create cs_id by extracting only the lower 6 bits.

— fmt가 7,6번 비트로 만들었고 나머지 0~5비트로 AND 연산하면 10진수로 3만 남습니다.
fmt is created using bits 7 and 6, and performing an AND operation with the remaining bits 0 through 5 leaves only 3 in decimal.

— 그래서 따로 비트이동은 하지 않습니다.
Therefore, we do not perform separate bit shifting.

–AND연산은 둘다 1인 경우만 1이 됩니다.(&)
The AND operation returns 1 only when both are 1. (&)

  01000011 ← chunk_basic_header_ = 0x43 = 67
& 00111111 ← 0x3F 마스크 / 0x3F mask

  00000011 ← 결과 / result = 3

✔️ 그래서 fmt = 1 = “헤더 7바이트”,cs_id = 3 = “3번 채널” 이 됩니다.
So, fmt = 1 = “7 bytes of header”, cs_id = 3 = “channel 3”.

✔️ cs_id는 26 = 64 (0~63)개의 채널을 사용할 수 있습니다.(cs_id = 0~63)
cs_id is 26 = 64 (0~63) channels can be used. (cs_id = 0~63)

✔️ 만약 cs_id == 0이면 1바이트를 더 읽어서 채널을 (64+255=)319개 더 확장합니다.
If cs_id == 0, read 1 more byte to expand the channel to (64+255=)319 more.

— 1byte = 8bit = 255까지 사용가능
1 byte = 8 bits = up to 255 can be used

            if (cs_id == 0) {
                uint8_t ext;
                asio::async_read(socket_, asio::buffer(&ext, 1),
                    [this, self, fmt, ext](std::error_code ec, std::size_t) {
                        if (ec) return;
                        read_message_header(fmt, 64 + ext);
                    });
            } 

✔️ cs_id == 1이면 2바이트를 읽어서 buf[2]배열에 각각 저장합니다.
If cs_id == 1, read 2 bytes and store them in the buf[2] array.

✔️ 최대: 64 + 255 + (255<<8) = 64 + 255 + 65280 = 65599 개 까지의 채널을 사용할 수 있습니다.
Max: 64 + 255 + (255<<8) = 64 + 255 + 65280 = 65599 channels can be used.

            else if (cs_id == 1) {
                uint8_t buf[2];
                asio::async_read(socket_, asio::buffer(buf, 2),
                    [this, self, fmt, buf](std::error_code ec, std::size_t) {
                        if (ec) return;
                        read_message_header(fmt, 64 + buf[0] + (buf[1] << 8));
                    });
            } 

✔️ 64 + buf[0] + (buf[1] << 8) 계산

— 소켓으로 0x10 0x01 2바이트 값이 날아오면
If a 2-byte value 0x10 0x01 is sent through the socket

— buf[0] = 0x10 = 00000001 = 1 ,buf[1] = 0x01 = 00010000 = 16

— 리틀엔디안인경우 상위 바이트를 왼쪽으로 8비트 밀어서 256(=100000000 )을 만듦
In the case of Little Endian, the upper byte is shifted left by 8 bits to create 256 (= 100000000).

— 예시 / example:

buf[1]=0x01: 0x01 << 8 = 0x0100 = 256 ,
buf[0]=0x10: 0x10 = 16
합계/total: 256 + 16 = 272
최종/final cs_id = 64 + 272 = 336

— 최소값/minimum value :

buf[0] = 0x00 = 0, 
buf[1] = 0x00 = 0 ,
cs_id = 64 + 0 + (0 << 8) = 64 + 0 + 0 = 64

— 최대값/maximum value:

buf[0] = 0xFF = 255, 
buf[1] = 0xFF = 255, 
buf[1] << 8 = 0xFF << 8 = 0xFF00 = 65280,
cs_id = 64 + 255 + 65280 = 65599

✔️ 함수 전체 코드 / full function code

void RtmpSession::read_chunk_header() {
    auto self(shared_from_this());
    // 1바이트만 읽기 / Read only 1 byte
    socket_.async_read_some(asio::buffer(&chunk_basic_header_, 1),
        [this, self](std::error_code ec, std::size_t) {
            if (ec) {
                std::cout << "[Info] Connection closed: " << ec.message() << "\n";
                return;
            }
            uint8_t fmt = (chunk_basic_header_ >> 6) & 0x03;
            uint32_t cs_id = chunk_basic_header_ & 0x3F;
            if (cs_id == 0) {
                uint8_t ext;
                asio::async_read(socket_, asio::buffer(&ext, 1),
                    [this, self, fmt, ext](std::error_code ec, std::size_t) {
                        if (ec) return;
                        read_message_header(fmt, 64 + ext);
                    });
            } else if (cs_id == 1) {
                uint8_t buf[2];
                asio::async_read(socket_, asio::buffer(buf, 2),
                    [this, self, fmt, buf](std::error_code ec, std::size_t) {
                        if (ec) return;
                        read_message_header(fmt, 64 + buf[0] + (buf[1] << 8));
                    });
            } else {
                read_message_header(fmt, cs_id);
            }
        });
}

Leave a Reply