Container & Codec
Container는 여러 미디어 스트림(비디오, 오디오, 자막 등)과 메타데이터를 하나의 파일 안에 담을 수 있도록 정의한 파일 포맷을 일컫는 용어이다. Container의 종류로는 QuickTime File Format (QTFF)와 ISO BMFF (ISO/IEC 14496-12)가 있다.
QuickTime File Format (QTFF)는 Apple이 1991년에 만든 시간 기반 멀티미디어 컨테이너 포맷으로, 예시로는 MOV 컨테이너가 해당된다.
ISO BMFF (ISO/IEC 14496-12)는 QuickTime의 구조를 기반으로 국제 표준화된 일반적이고 확장 가능한 멀티미디어 컨테이너 포맷으로, 예시로는 mp4 컨테이너가 해당된다.
Codec는 Coder-Decoder의 약자로, 컨테이너 내부 미디어 데이터를 압축(인코딩)하거나 압축을 풀어(디코딩) 재생할 수 있도록 하는 알고리즘이다. 이때, Encoding은 원본 비디오/오디오 신호를 압축된 스트림으로 변환하는 과정이고, Decoding은 파일에 저장된 압축 스트림을 풀어 다시 재생 가능한 신호로 변환하는 과정이다. 예시로는 H.264, AAC가 해당된다.
Presentation는 컨테이너 내부에 들어 있는 트랙(비디오/오디오 등)의 샘플들을 적절한 시간적 순서에 따라 재생하여 하나의 통합된 미디어 경험으로 사용자에게 보여 주는 행위를 의미한다. 간단하게 '재생'이라고 칭하기도 한다.
MP4
MP4는 ISO BMFF 컨테이너 포맷으로 한 영상 파일 형식이다. mp4 파일의 구조는 크게 ftyp (File Type Box), moov (Movie Box), mdat (Media Data Box)의 세가지 영역으로 구성되어있다.

첫 번째 영역
ftyp (File Type Box)는 컨테이너의 브랜드 및 확장 규칙 정보를 저장하는 박스이다. major_brand, compatible_brands 등의 정보를 기반으로 파서가 파일 규격을 해석한다.
두 번째 영역
moov (Movie Box)는 전체 프레젠테이션의 메타데이터와 트랙 정보를 저장하는 박스이다. moov 박스는 mvhd와 여러 Track Box를 저장한다.

mvhd (Movie Header Box)는 컨테이너 내부 전체 프레젠테이션 수준의 메타데이터 정보를 저장하는 박스이다. 해당 박스가 저장하는 주요 정보는 아래와 같다.
| 이름 | 의미 |
| timescale | 1초를 몇 개의 tick으로 나눌지에 대한 정보 |
| tick | 시간을 표현하는 가장 작은 시간 단위 timescale에 의해 정의된 불연속 시간 단위 |
| timebase | tick 하나가 실제 시간으로 환산될 때의 초 단위 값 |
| duration | 미디어의 전체 재생 시간 |
| creation_time | 미디어 생성 시간 |
| modification_time | 미디어 수정 시간 |
| rate | 기본 재생 속도 |
| volume | 기본 재생 볼륨 |
| matrix (display transform) | 영상 출력 시 공간적 변환(orientation / scale / rotation / position)을 나타내는 3×3 행렬 |
영상 트랙을 실제로 화면에 표시할 때 회전, 위치 이동, 확대, 축소 등의 공간 변환을 적용하면 다음과 같다.

세 번째 영역
mdat (Media Data Box)는 실제 인코딩된 비디오 및 오디오 정보를 저장하는 박스로 MP4 컨테이너 대부분의 용량 차지한다.
추가 용어
Box는 ISO BMFF 컨테이너에서 정보를 담는 가장 작은 구조적 단위이다. 이때, Container Box는 하위 Box를 포함하는 Box를 의미하고, Leaf Box는 하위 Box를 포함하지 않는 Box를 의미한다.
Atom은 QuickTime File Format 컨테이너에서 정보를 담는 가장 작은 구조적 단위이다.
바이트 단위의 구조체는 다음과 같다.

Track & Stream
Track은 컨테이너 내부에서 하나의 시간 기반 미디어 스트림을 의미한다.
Track Box는 Track(하나의 개별 스트림) 정보를 저장하는 박스를 의미한다. 일반적으로 MP4 파일은 Video Track과 Audio Track을 갖는다.
Stream은 시간 흐름에 따른 연속적 데이터 흐름을 의미한다.
moov 는 여러 Track을 포함하기 때문에, moov 관점 Track Box 구조는 아래와 같다.

Track Box 내부 Box 구조는 다음과 같다. 이때, 주요 Box는 밑줄로 강조하였다.

아래는 실제 mp4를 대상으로 특정 Track 영역의 정보를 파싱한 모습이다. (해당 파싱 도구와 옵션은 이후 목차인 도구 사용에서 다루었다.)

Sample & Block & Chunk
Sample은 컨테이너 내부 미디어 데이터를 재생할 수 있는 최소 논리적 단위를 의미한다. (여러 블록이 포함된 구조) 때문에, Video Track Sample은 하나의 비디오 프레임을 의미하게된다.
Block은 컨테이너 내부 미디어 데이터를 저장하는 최소 물리적 단위를 의미한다.
Chunk는 mdat 내부 연속적으로 저장된 sample들의 집합을 의미한다.
stbl (Sample Table Box)는 컨테이너 내부 Sample 들을 저장하는 컨테이너 박스이다.
Sample Table Box 내부 Sample의 종류는 다음과 같고, 주요 Sample은 밑줄로 강조하였다. 아래는 주요 Sample에 대한 특징과 해석이다.
stts (Decoding Time to Sample Box)는 샘플별 디코딩/재생 간격(타임스탬프 델타) 정보를 가진 박스이다. stts 내부 Entry 1개가 여러 Sample을 포함할 수 있다. 이는 데이터 압축 효과를 갖기 때문이다.
stsz (Sample Size Box)는 각 샘플의 바이트 크기를 저장하는 박스이다.
stsc (Sample to Chunk Box)는 샘플이 어떤 청크(chunk)에 속하는지 매핑 테이블을 가진 박스이다. stsc 내부 sample_desc_index는 sample이 stsd(Sample Description Box)의 몇 번째 엔트리를 사용하는지 가리키는 인덱스 정보로, stsd가 없는 경우 sample_desc_index는 항상 1 값을 갖게된다. 아래는 stsc의 실제 정보에 대한 해석을 서술한 내용이다.
- (0) first_chunk = 1, first_sample = 1, chunk_count = 1, samples_per_chunk = 23, sample_desc_index = 1
- 해석 : 1번 청크 (청크 1개 = 샘플 23개)
- `(1) first_chunk = 2, first_sample = 24, chunk_count = 3, samples_per_chunk = 22, sample_desc_index = 1` - 해석 : 2~4번 청크 (청크 1개 = 샘플 22개)
- `(2) first_chunk = 5, first_sample = 90, chunk_count = 1, samples_per_chunk = 21, sample_desc_index = 1` - 해석 : 5번 청크 (청크 1개 = 샘플 21개)
stco/co64 (Chunk Offset Box)는 mdat 내부 각 청크의 오프셋(파일 위치)을 저장하는 박스로, stco의 entry 갯수는 stsc의 청크 갯수와 정확하게 일치한다.

아래는 실제 mp4를 대상으로 특정 stbl 영역의 정보를 파싱한 모습이다. (해당 파싱 도구와 옵션은 이후 목차인 도구 사용에서 다루었다.)

MP4 Analysis Tools
mp4dump.exe 도구 주요 옵션
--track N : N 번째 트랙 정보만을 출력하는 옵션. 선택된 트랙의 mdat 정보를 포함한 파일이 생성됨. 이때, 파일은 input 파일명 뒤에 ‘.n’이 추가된 파일명으로 생성됨.
--verbosity N : 얼마나 깊이 있게 box 내부를 추출할지 결정하는 옵션
- 0 : 요약 정보 중심 (Default)
- 1 : 주요 필드 추가 출력
- 2 : 대부분의 box 필드 출력
- 3 : 모든 내부 필드 상세 출력
mp4info.exe 도구 주요 옵션
--show-sample-data : 실제 미디어 데이터를 출력하는 옵션. 원시 데이터를 전부 보여주지 못해서 결국 수동으로 매핑해보았습니다.....(PE 파일을 까서 데이터 제한 길이를 패치할까 해보았지만... 그것보다는 수동 매핑이 더 명확하게 이해하는데에 좋은 방향인 것 같아서 수동 매핑의 방법을 선택했습니다....)
수동 분석
1. stsc 분석 : 첫 번째 Chunk : 첫 번째 부터 스물세 번째 Sample 포함

2. stts 분석 : 첫 번째 부터 스물세 번째 Sample의 Duration 정보 (21번째 엔트리가 2개의 Sample을 포함)

3. stsz 분석 : 첫 번째 부터 스물세 번째 Sample의 데이터 크기 정보 (여섯 번째 Entry의 데이터 유독 크기가 큼. 이유는 MP4 파일이 블랙박스 영상 파일이고, 여섯 번째 Entry에서 GPS 정보를 추가로 저장함.)

4. stco 분석 : 첫 번째 Chunk의 실제 데이터 시작 주소 정보

5. 결론
- 첫 번째 Chunk는 첫 번째 부터 스물세 번째 Sample을 포함
- 첫 번째 Chunk의 Duration은 1,222로 1.222초의 재생 시간을 가짐
- 첫 번째 Chunk의 데이터 크기는 767 Byte를 가짐. (일곱 번째 Sample (여섯 번째 Entry)만 107 바이트의 데이터 크기를 가지고 나머지 Sample은 전부 30 바이트의 데이터 크기를 가짐)
- 첫 번째 Chunk의 mdat 데이터 시작 주소는 1,260,461(0x133BAD) Byte임
∴ Chunk #1 mdat 내부 실제 데이터 주소 : [0x133BAD, 0x133BAD + 0x2FF) (실제로 따라가본 결과 일치함!)
