[Mediaserver]mini_Mediaserver_1-코드설명/code description-amf0.cpp(1-7)

👉🏻 아래는 amf0.cpp 파일이 함수에 대한 설명입니다.
Below is a description of the functions in the amf0.cpp file.

👉🏻 코드 설명 / Code Explanation

✔️1. std::string Amf0::parse_string(const std::vector& buf, size_t& pos) { … }

— 이 함수는 버퍼의 데이터를 문자열로 변환하는 함수 입니다.
This function converts data in a buffer into a string.

— 버퍼에 아래의 예시 데이터가 있다고 가정합니다.
Assume the buffer contains the example data shown below.

buf = {0x02, 0x00, 0x05, 'h', 'e', 'l', 'l', 'o', 0x00}, pos = 0

— pos기본값이 0보다 크거나,버퍼0번 배열 값이 0x02가 아니라면 리턴(로직 중단)합니다.
Return (halt the logic) if the pos default value is greater than 0 or the value at index 0 of the buffer array is not 0x02.

    if (pos >= buf.size() || buf[pos]!= 0x02) return "";
    // buf[0] -> buf[1],포인터 이동
    pos++;

— pos+1 = 2 < buf.size(9)면 통과합니다.
Return (halt the logic) if the pos default value is greater than 0 or the value at index 0 of the buffer array is not 0x02.

if (pos + 1 >= buf.size()) return "";

— buf[pos]를 상위바이트로 이동(8)하고 뒤에 00 붙입니다.(예:0xAB -> 0xAB00)
Shift buf[pos] to the upper byte (by 8 bits) and append 00 (e.g., 0xAB -> 0xAB00).

— len = 0x00 << 8 | 0x05 = 5, pos+=2 → pos=3

uint16_t len = (buf[pos] << 8) | buf[pos+1];

— 3 + len(5)이 버퍼사이즈보다 크면 리턴(로직중단)
If 3 + len(5) is greater than the buffer size, return (terminate logic).

— pos(3)+len(5) = 8 <= 9 이면 통과합니다.
It passes if pos(3) + len(5) = 8 <= 9.

// pos = 3
pos += 2;
if (pos + len > buf.size()) return "";

— 실제 문자열로 변환해서 리턴합니다.
Converts it to an actual string and returns it.

— buf[3]~buf[7] = “hello” 잘라서 리턴하고, pos=8로 업데이트합니다.
Extract and return “hello” from buf[3] to buf[7], and update pos to 8.

    std::string str(buf.begin() + pos, buf.begin() + pos + len);
    pos += len;
    return str;

✔️ RTMP에서 null 값을 읽고 pos만 한 칸 넘겨주는 역할.(0x05에서 다음칸으로pos 이동)
It reads a null value from the RTMP stream and advances the pos by one position (moving pos from 0x05 to the next position).

void Amf0::parse_null(const std::vector<uint8_t>& buf, size_t& pos) {
    if (pos < buf.size() && buf[pos]==0x05) pos++;
}

✔️ 2.double Amf0::parse_number(const std::vector& buf, size_t& pos) {…}

— 이 함수는 버퍼의 데이터를 숫자로 변환하는 함수 입니다.
This function converts data in the buffer into a number.

— 버퍼에 아래의 예시 데이터가 있다고 가정합니다.
Assume the buffer contains the example data shown below.

buf = { 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
  마커/Marker | ------------- 8바이트/byte double ------------- |
pos = 0

— RTMP에서 숫자 1.0을 보내면 AMF0로 이렇게 인코딩 됩니다.
When sending the number 1.0 in RTMP, it is encoded in AMF0 like this.

— 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 은 IEEE754에서 1.0을 의미합니다.
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 represents 1.0 in IEEE 754.

— IEEE754는 컴퓨터가 실수를 메모리에 저장하는 국제 표준 규칙입니다.
IEEE 754 is an international standard for how computers store real numbers in memory.

— number 마커인지 확인하기
Check if it is a number marker.

    if (pos >= buf.size() || buf[pos]!= 0x00) return 0;
    pos++; // 1
    uint64_t val = 0;

— val을 상위 비트로 8비트이동하고 뒤에 00붙입니다.
Shift val 8 bits to the left (to the upper bits) and append 00 at the end.

— 8번 반복문을 실행하면 buf[1]~buf[8]까지 총 8바이트가 조립됩니다.(빅엔디언 과정)
Executing the loop eight times assembles a total of 8 bytes, from buf[1] to buf[8] (big-endian process).

— 실제로 진행되는 과정은 아래의 표와 같습니다.
The actual process is as shown in the table below.

 for (int i = 0; i < 8; i++) val = (val << 8) | buf[pos++];
iposbufval << 8OR 후 val /
Value after OR
010x3F0x000x000000000000003F
120xF00x0000000000003F000x0000000000003FF0
230x000x00000000003FF0000x00000000003FF000
340x000x000000003FF000000x000000003FF00000
450x000x0000003FF00000000x0000003FF0000000
560x000x00003FF0000000000x00003FF000000000
670x000x003FF000000000000x003FF00000000000
780x000x3FF00000000000000x3FF0000000000000

— double형으로 형변환해서 리턴합니다.
It casts the value to a double and returns it.

return *reinterpret_cast<double*>(&val);

 ⭐️IEEE754 double

✔️ 0x3F : 0011 1111 (2진수/Binary number)

✔️ 0xF0 : 1111 0000 (2진수/Binary number)

✔️ 64비트 실수는 이렇게 사용하자라고 약속된것입니다.
This is the agreed-upon way to use 64-bit floating-point numbers.

✔️ 구조 : 구조: 부호 + 지수 + 가수
Structure: Sign + Exponent + Mantissa

   63bit                62~52bit           51~0bit
[부호1비트]             [지수부 11비트]       [가수부 52비트]
[Sign bit: 1 bit] [Exponent: 11 bits] [Mantissa: 52 bits]
  S            E             M
값/Value = (-1)^S * 1.M * 2^(E-1023)
[0x3F]    [0xF0]
00111111  11110000 ... (이후 00은 모두 0 / After that, all 00s are 0)
│└────┬─────┘└─┬─┘
│     │        └─ 가수부(M)의 시작점 (모두 0) / Starting point of the vocal section (M) (all zeros)
│     └─ 지수부(E): 11비트 / Exponent part (E): 11 bits
└─ 부호(S): 1비트 (0 = 양수) / Sign (S): 1 bit (0 = positive)

1.0 = (-1)^0 * 1.0 * 2^0 
— S=0, E-1023=0 → E=1023 = 0x3FF, M=0

— 지수 부분은 11비트 →  2^11 = 2048개 표현 가능합니다.
The exponent part consists of 11 bits, allowing for 2^11 (2,048) possible values.

— 52비트 가수 → 정밀도 15∼17자리 십진수입니다.
A 52-bit significand corresponds to a precision of 15 to 17 decimal digits.

— S값은 0이면 양수 -1이면 음수입니다.
An S-value of 0 indicates a positive number, while -1 indicates a negative number.

— E값은 1023이 기본 할당되어 있습니다.(상수) 이것을 bias라고 합니다.
The E-value is assigned a default value of 1023 (a constant); this is referred to as the bias.

— 처음에 저장할떄 1023을 저장하고 나중에 값이 설정될때 이 값을 빼줍니다.
Initially, you store 1023, and later, when the value is set, you subtract this value.

bias = 2^(11-1) - 1 = 1023

— 밑이 2인 거듭제곱 연산 부분이 \(2^{0}\)이 되며, 모든 수의 0제곱은 1이됩니다. 즉
The part involving the power of 2 becomes (2^{0}), and any number raised to the power of 0 equals 1. In other words,

지수부/Index Section : 2^{1023 – 1023} = 2^0 = 1

최종값 / Final value = 1 ✕ 1.0 ✕ 1 = 1.0

Leave a Reply