如何计算 mpegts 文件的长度
Background
ts文件为传输流文件, 视频编码主要格式 h264/mpeg4, 音频为 acc/mp3。
ts文件分为三层:
1) ts 层Transport Stream、
- ts 层就是在pes层加入数据流的识别和传输必须的信息
- ts 流: 由定长的TS包组成 (188字节) , 而TS包是对PES包的一个重新封装 (到这里, ES经过了两层的封装) 。应用于相对有错环境下的传输与存储 (如DVB中) , 其基本单位是TS包, 长度固定188字节。日本的DVB-S广播系统采用192个字节的TS包, 美国采用204个字节的TS包, 多加了16个字节的前向纠错校验码 (FEC) 。
2) pes 层 Packet Elemental Stream、
- pes 层是在音视频数据上加了时间戳等对数据帧的说明信息,
- pes 流: PES流是ES流经过PES打包器处理后形成的数据流, 在这个过程中完成了将ES流分组、打包、加入包头信息等操作 (对ES流的第一次打包) 。PES流的基本单位是PES包。
3) es 层 Elementary Stream.
- es 层就是音视频数据,
- es 流: 有三种, 图像数据流, 音频数据流, 以及其他编码数据流。
mpegts 文件结构如下
mpegts 文件头字段如下
-
The Sync Byte (0x47) marks the beginning of each MPEG-2 transport stream (TS) packet, serving as a synchronization indicator for packet boundaries.
-
The PID (Packet Identifier) field within each TS packet identifies the type of payload contained in the packet. Different PID values correspond to various components of the transport stream:
- PID 0x0000 points to the Program Association Table (PAT), which lists all programs and their corresponding Program Map Table (PMT) PIDs.
- PID 0x0010 points to the Network Information Table (NIT), providing network-related information and descriptors.
- PIDs obtained from the PAT point to the PMT, which lists all elementary streams (audio, video, etc.) for a specific program.
- PIDs obtained from the PMT point to the actual elementary streams carrying audio, video, or other data.
-
The Program Association Table (PAT) is a vital component of the MPEG-2 transport stream. It lists all programs available in the stream along with the PID of their respective Program Map Tables (PMTs).
-
The Program Map Table (PMT) contains detailed information about the elementary streams associated with a specific program. It lists all elementary streams, such as audio and video streams, along with their corresponding PIDs.
-
The Network Information Table (NIT) provides network-related information and descriptors within the MPEG-2 transport stream. It includes details about the network structure, service providers, and other relevant information.
-
Elementary Streams within the MPEG-2 transport stream contain the actual audio, video, or other data transmitted over the network. These streams are identified by their PIDs and are crucial for decoding and playback of multimedia content.
1. Understand the MPEG-TS Structure:
- MPEG-TS (MPEG Transport Stream) files consist of packets, typically 188 bytes in size.
- Each packet starts with a 4-byte header, which includes a sync byte (0x47).
- The packets contain various streams, such as audio, video, and metadata.
2. Extract Relevant Packets:
- PCR (Program Clock Reference): This is used to calculate the timing information. The PCR values are typically found in the adaptation field of the packet header.
- PTS (Presentation Timestamp) and DTS (Decoding Timestamp): These are used to synchronize the decoding and presentation of the audio/video.
3. Calculate Duration:
- Find the first and last PCR values in the file.
- The duration can be calculated using the difference between the first and last PCR values:
[
\text{Duration} = \frac{\text{PCR}{\text{last}} - \text{PCR}{\text{first}}}{\text{PCR_frequency}}
]
wherePCR_frequency
is typically 27 MHz (27,000,000 ticks per second).
4. Calculate Bitrate:
- File Size: Determine the total file size in bits.
- Duration: Use the duration calculated from the PCR.
- Bitrate can then be calculated as:
[
\text{Bitrate} = \frac{\text{Total File Size in bits}}{\text{Duration in seconds}}
]
5. Manual Parsing:
- You would need to manually parse the binary data to extract the first and last PCR values.
- This involves reading the file byte-by-byte, identifying the sync byte (0x47), and then locating the PCR values within the adaptation field.
例如我有一个 mpegts 文件, 通过 ffprobe 得知它的长度为 86.9 秒: duration=86.999989
% ffprobe -show_format -show_streams record_20240814185406_00092.ts
ffprobe version 7.0 Copyright (c) 2007-2024 the FFmpeg developers
built with Apple clang version 15.0.0 (clang-1500.1.0.2.5)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.0_1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopenvino --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
libavutil 59. 8.100 / 59. 8.100
libavcodec 61. 3.100 / 61. 3.100
libavformat 61. 1.100 / 61. 1.100
libavdevice 61. 1.100 / 61. 1.100
libavfilter 10. 1.100 / 10. 1.100
libswscale 8. 1.100 / 8. 1.100
libswresample 5. 1.100 / 5. 1.100
libpostproc 58. 1.100 / 58. 1.100
[mpegts @ 0x12e605e80] DTS discontinuity in stream 0: packet 11 with DTS 406832999, packet 12 with DTS 414623999
Input #0, mpegts, from 'record_20240814185406_00092.ts':
Duration: 00:01:27.00, start: 4520.000000, bitrate: 10 kb/s
Program 1
Stream #0:0[0x41]: Video: h264 (Constrained Baseline) (HDMV / 0x564D4448), yuv420p(progressive), 1920x1080, 30 tbr, 90k tbn
[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=Constrained Baseline
codec_type=video
codec_tag_string=HDMV
codec_tag=0x564d4448
width=1920
height=1080
coded_width=1920
coded_height=1080
closed_captions=0
film_grain=0
has_b_frames=0
sample_aspect_ratio=N/A
display_aspect_ratio=N/A
pix_fmt=yuv420p
level=40
color_range=unknown
color_space=unknown
color_transfer=unknown
color_primaries=unknown
chroma_location=unspecified
field_order=progressive
refs=1
is_avc=false
nal_length_size=0
ts_id=1
ts_packetsize=188
id=0x41
r_frame_rate=30/1
avg_frame_rate=0/0
time_base=1/90000
start_pts=406800000
start_time=4520.000000
duration_ts=7829999
duration=86.999989
bit_rate=N/A
max_bit_rate=N/A
bits_per_raw_sample=8
nb_frames=N/A
nb_read_frames=N/A
nb_read_packets=N/A
extradata_size=23
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
DISPOSITION:non_diegetic=0
DISPOSITION:captions=0
DISPOSITION:descriptions=0
DISPOSITION:metadata=0
DISPOSITION:dependent=0
DISPOSITION:still_image=0
[/STREAM]
[FORMAT]
filename=record_20240814185406_00092.ts
nb_streams=1
nb_programs=1
nb_stream_groups=0
format_name=mpegts
format_long_name=MPEG-TS (MPEG-2 Transport Stream)
start_time=4520.000000
duration=86.999989
size=119004
bit_rate=10942
probe_score=50
[/FORMAT]
那它是怎么算出来的呢?
通过这个 TS 文件的最后一个有 Adaptation fields 包中的 PCR 字段(PCR_n), 减去第一个有 Adaptation fields 包中的 PCR 字段(PCR_1)
例如发现 package 626 中有 Adaptation fields 字段, PCR: 124383824700
Adaptation fields
Adaptation_field_length: 7
discontinuity_indicator: False
random_access_indicator: False
ES_priority_indicator: False
PCR_flag: True
OPCR_flag: False
splicing_point_flag: False
transport_private_data_flag: False
adaptation_field_extension_flag: False
PCR: 124383824700
PES header
stream_id: E0 (video stream 224)
PES_packet_length: 662
PES_scrambling: 0
PES_priority: False
data_alignment: False
copyright: False
original_or_copy: True
PTS_flag: True
DTS_flag: False
ESCR_flag: False
ES_rate_flag: False
DSM_trick_mode_flag: False
additional_copy_info_flag: False
PES_CRC_flag: False
PES_extension_flag: False
PES_header_data_length: 5
PTS: 414623999
Video sequence
Sequence header code not found in this packet
AFD not found in this packet
- package 3 中也有 Adaptation fields, 其中 PCR: 122036625000
Adaptation fields
Adaptation_field_length: 7
discontinuity_indicator: False
random_access_indicator: True
ES_priority_indicator: False
PCR_flag: True
OPCR_flag: False
splicing_point_flag: False
transport_private_data_flag: False
adaptation_field_extension_flag: False
PCR: 122036625000
PES header
stream_id: E0 (video stream 224)
PES_packet_length: 0 (undefined)
PES_scrambling: 0
PES_priority: False
data_alignment: False
copyright: False
original_or_copy: True
PTS_flag: True
DTS_flag: False
ESCR_flag: False
ES_rate_flag: False
DSM_trick_mode_flag: False
additional_copy_info_flag: False
PES_CRC_flag: False
PES_extension_flag: False
PES_header_data_length: 5
PTS: 406800000
Video sequence
Sequence header code not found in this packet
AFD not found in this packet
而 PCR 的含义如下
The Program Clock Reference (PCR) is a timestamp used in MPEG Transport Streams (MPEG-TS) to synchronize the decoding of audio and video data. PCR helps the decoder to reconstruct the timing of the original media streams. Here’s a detailed explanation of the PCR format:
1. PCR Structure:
The PCR is a 42-bit value that consists of two parts:
- PCR Base (33 bits): Represents the most significant part of the PCR and has a 27 MHz clock frequency.
- PCR Extension (9 bits): Represents the least significant part and extends the precision of the PCR with a 90 kHz clock frequency.
2. Bit Allocation:
- PCR Base (33 bits): Occupies bits 0 to 32.
- Reserved (6 bits): Follows the PCR base, and these bits are reserved for future use (usually set to 0).
- PCR Extension (9 bits): Occupies bits 42 to 50.
3. Detailed Breakdown:
-
PCR Base: The PCR base is a counter that increments at a rate of 27 MHz. It rolls over every 2^33 ticks, which means the value wraps around to 0 after approximately 26.5 hours.
- Range: 0 to (2^{33} - 1) (0 to 8,589,934,591)
- Clock Rate: 27 MHz (27,000,000 ticks per second)
-
PCR Extension: The PCR extension provides additional precision by adding a fractional component to the PCR base. It increments at a rate of 90 kHz.
- Range: 0 to (2^{9} - 1) (0 to 511)
- Clock Rate: 90 kHz (90,000 ticks per second)
4. PCR Calculation:
-
PCR Value: The full PCR value is calculated as:
[
\text{PCR} = \text{PCR Base} \times 300 + \text{PCR Extension}
]
This formula considers the 27 MHz clock and the additional precision from the 90 kHz clock. -
Interpretation: The PCR gives the time at which the packet carrying the PCR was transmitted. The decoder uses this information to synchronize playback by comparing the PCR value with the system clock reference (SCR) of the decoder.
5. Location in MPEG-TS Packet:
- PCR is found in the adaptation field of an MPEG-TS packet, which is present if the
adaptation_field_control
bits in the packet header are set accordingly. - If the adaptation field is present, the PCR is located at a specific offset within that field.
6. Example:
If the PCR base is 0x123456789
(hexadecimal) and the PCR extension is 0x1FF
:
- PCR Base: ( \text{PCR Base} = 781,874,935,29 )
- PCR Extension: ( \text{PCR Extension} = 511 )
- PCR Value: ( \text{PCR} = 781,874,935,29 \times 300 + 511 = 234,562,480,028,511 ) ticks
7. Use in Synchronization:
PCR values are periodically inserted into the MPEG-TS stream (usually every 100 ms or so) to maintain synchronization. The decoder uses these values to correct any drift in its clock, ensuring that audio and video remain in sync during playback.
Summary:
- PCR is a 42-bit timestamp used for synchronization in MPEG-TS.
- PCR Base: 33 bits, increments at 27 MHz.
- PCR Extension: 9 bits, increments at 90 kHz.
- Location: Found in the adaptation field of MPEG-TS packets.
结论
(124383824700 - 122036625000)/27000000 = 86.93
末尾的 TS package 的 PCR 减去开头的 TS package 的 PCR 值, 再除以 27,000,000, 就得出了这个 TS 的长度是 86 秒多
为什么要除以 27000000, 因为 " PCR base is a counter that increments at a rate of 27 MHz"