- Removal Specific SEI Message from H264/AVC Elementary Stream
- Get H264/AVC Video Statistics from Transport Stream
- Get Picture Statistics From HEVC/H.264 Elementary Stream
- Extract a Selected GOP starting at CRA in HEVC/H.265 Elementary Stream
- Print High-Level Syntax Elements (SPS/PPS) in HEVC/H.265 Elementary Stream
- Modify Aspect Ratio Parameters in HEVC/H.265 Elementary Stream
- Detect Discontinuities in frame_num cadence in AVC/H.264 elementary stream
- Removal of Non-Reference Frames from H.264/AVC Elementary Stream in order to Reduce Bitrate
- Enhancement of Random Access Ability of H.264/AVC Stream by Insertion of SPS/PPS at IDR frames
- Remove Frames Until First Key Frame in H.264/AVC File
- Get DTS Statistics of both Video and Audio in MPEG2 System (Transport) Stream
- Get H265/HEVC Video Statistics from Transport Stream
- Remove AUDs (Access Unit Delimiters) from H.264/AVC and H.265/HEVC Elementary Stream
- Print pic_parameter_set_id of each frame in H.264/AVC stream, relevant if multiple PPS are present
15. Print weighted prediction parameters per frame/slice (for H.264/AVC) streams, adapted for Python 3.x
16. Parse SPS and Print Resolution (H.264/AVC), adapted for Python 3.x
17. Get Number Slices in H.264/HEVC Streams, adapted for Python 3.x
18. Parse SPS and Print Custom Scaling Matrices (if present) in H.264/AVC, adapted for Python 3.x
19. Compare SPS in H264/AVC stream, adapted for Python 3.x
20. Get Instant Bitrates from H264 File, adapted for Python 3.x
21. Get Instant Bitrates from HEVC File, adapted for Python 3.x
22. Remove Specific SEI Messages from HEVC File, Python 3.x
23. Get Meta Data of HEVC Stream in MP4-file, Python 3.x
24. Detect Large Frames in H264/AVC Elementary Stream, Python 3.x
25. Detect Large Frames in HEVC Elementary Stream, Python 3.x
26. Find Video Track Number in mp4-file, Python 3.x
27. Print Mpegts Packets Payload Sizes, Python 3.x
28. Cut H264/AVC Elementary Stream at Specified IDR, Python 3.x
29. Count Short Start-Codes, Python 3.x
30. Parse PNG Image Format, Python 3.x
31. Parse Slice Header and Print Weighted Prediction Parameters H264, Python 3.x
32. Get PSNR, SSIM and VIFP with sewar package, Python 3.x
33. Print NAL Headers of HEVC Elementary Stream, Python 3.x
34. Remove NALU with Given nal_unit_type from H264 Elementary Stream, Python 3.x
*Additional python scripts to analyze MPEG-System stream (Transport Stream) are housed at the following page “Python Scripts to Analyze and Process Transport Stream“
Part of scripts written in Python 2.x
Removal Specific SEI Message from H264/AVC Elementary Stream
The script RemoveSeiInH264Stream.py tailored to remove SEI messages specified by sei_type (e.g. sei_type=0 is buffering period SEI message).
Note: with ffmpeg you can remove all SEI NALUs regardless to sei_type:
The removal process of the python script is not in-place therefore the output stream must be different from the input one.
If the input stream does not contain a specified sei_type then no output stream is generated. Notice that most of SEI messages carry auxiliary information and can be removed from the stream (although the appearence of video might be affected in some cases).
Example [ removal of SEI messages with sei_type=0 ]
- The input stream does not contain SEI message with sei_type=5
python RemoveSeiInH264Stream.py out.h264 5 out1.h264
Analyzing …
||==============================================================================> |||
- The input stream contains SEI message with sei_type=0
python RemoveSeiInH264Stream.py test.h264 0 out.h264
||==============================================================================> |||
Copying without SEI 0….
This script can be useful to adapt a video stream to be playable by Microsoft Media Player (since SEI bueffering period prior to SPS makes the stream not playable.
Get H264/AVC Video Statistics from Transport Stream
The script GetAVCVideoStatsFromTS.py (adapted for python 2.x) and
GetAVCVideoStatsFromTSVer3.py (adapted for python 3.x)
is tailored to pick statistics (frame size, dts/pts. frame duration etc.) from video AVC/H.264 stream comprised in Mpeg System container ( Transport format files usually ending with ‘.ts’). It’s worth mentioning that the frame start is detected if a video ts-packet contains the PES header with the timestamp DTS (to avoid counting of frame slices).
Usage:
-i input ts-file, a section of ts-stream can be provided (even without SPS/PPS, unlike to ‘ffmpeg’)
-v print pts, dts and sizes of each video frame (default false)
-a ignore AUD (Access Unit Delimiter) violations (AUD is mandatory in Transport Stream but sometimes AUDs are absent and most of players copes with that violation), default false
-p print progress bar (the length is 80), default false. If verbose is ON then the progress bar disappears.
Examples:
[Print Number of detected frames, if AUD is absent a corresponding error reported ]
Video Size in bytes 17415224
0 Size 50711, dts 126000, pts 126000
1 Size 4517, dts 129600, pts 129600, frame duration 40.00
2 Size 8079, dts 132600, pts 132600, frame duration 33.33
3 Size 3801, dts 135600, pts 135600, frame duration 33.33
4 Size 7159, dts 138600, pts 138600, frame duration 33.33
5 Size 10218, dts 141600, pts 141600, frame duration 33.33
6 Size 13865, dts 144600, pts 144600, frame duration 33.33
7 Size 18646, dts 147600, pts 147600, frame duration 33.33
8 Size 8108, dts 150600, pts 150600, frame duration 33.33
9 Size 25734, dts 153600, pts 153600, frame duration 33.33
10 Size 20030, dts 156600, pts 156600, frame duration 33.33
897 Size 23225, dts 2817573, pts 2817573, frame duration 33.33
898 Size 1622, dts 2820573, pts 2820573, frame duration 33.33
899 Size 28580, dts 2823573, pts 2823573, frame duration 33.33
Minimal PTS diff (in ms) 33.32, attained at frame 17
Maximal DTS diff (in ms) 40.00, attained at frame 0
Video Size in bytes 17415224
Get Picture Statistics From HEVC/H.264 Elementary Stream
HEVC Case:
The scripts GetPictureStatsHevc.py (adapted to python 2.x) and GetPictureStatsHevcVer3.py (adapted to Python 3.x)
gathers and prints frame starts and offsets (in hex) as well as frame types.
Usage:
-n maximal number of frames to process, if 0 then the whole file processed, (default 0)
pb f8 3f
pb 137 38
pb 16f 38
pb 1a7 4b0
pb 657 28d
pb 8e4 18c
pb a70 201
pb c71 dd2
pb 1a43 0
H264 Case:
The script GetPictureStatsH264.py
gathers and prints frame starts and offsets (in hex) as well as frame types of h264 elementary stream.
Usage:
-n maximal number of frames to process, if 0 then the whole file processed, (default 0)
python GetPictureStatsH264.py -i crowd_qsv.h264 -n 10
pb 8e1ad 53618
pb e17c5 1a2d4
pb fba99 eb02
pb 10a59b e82d
pb 118dc8 2e4bd
pb 147285 d33e
pb 1545c3 69b3
pb 15af76 7015
pb 161f8b // if ‘-n’ is applied then the last frame size is omitted
Extract a Selected GOP starting at CRA in HEVC/H.265 Elementary Stream
The script CutOpenGopAtCRA.py
looks for CRA-frame started GOP and extracts it to a specified file by discarding RASL frames.
Usage:
-o output hevc gop file
-g number (counted from zero) of GOP started with CRA to extract (RASL removed) to a specified file
rasl 156e3e 2eb discarded
rasl 157129 273 discarded
rasl 15739c 22e discarded
rasl 1575ca 164 discarded
pb 15772e 187c
pb 158faa 1b4
pb 15915e 10d
pb 15926b 155
pb 1593c0 130
pb 1594f0 24fc
pb 15b9ec 1a0
pb 15bb8c f8
pb 15bc84 d3
pb 15bd57 1f7b
pb 15dcd2 129
pb 15ddfb d6
pb 15ded1 1eb6
pb 15fd87 de
pb 15fe65 b0
pb 15ff15 2152
pb 162067 d5
pb 16213c b1
pb 1621ed 20b3
pb 1642a0 114
pb 1643b4 c7
pb 16447b d3
pb 16454e b7
pb 164605 139c
pb 1659a1 135
pb 165ad6 d2
pb 165ba8 a7
pb 165c4f f49
pb 166b98 18a
pb 166d22 174
pb 166e96 146
pb 166fdc f8
pb 1670d4 155
pb 167229 7b
Print High-Level Syntax Elements (SPS/PPS) in HEVC/H.265 Elementary Stream
The script ParseHevcHL.py
processes HEVC/H.265 stream on GOP-basis (where SPS is an indication of GOP start, i.e. IDR without SPS is not recognized as the new GOP bebinning).
SPS and PPS (VPS is not processed) are parsed and most of syntax elements are printed.
Usage:
-n number gops to process, if 0 then the whole stream (default 0)
sps_video_parameter_set_id 0
sps_max_sub_layers 1
sps_temporal_id_nesting_flag 1
general_profile_space 0
general_tier_flag 0
general_profile_idc 1
general_progressive_source_flag 1
general_interlaced_source_flag 0
general_non_packed_constraint_flag 0
general_frame_only_constraint_flag 1
general_level_idc 123
sps_seq_parameter_set_id 0
chroma_format_idc 1
pic_width_in_luma_samples 1920
pic_height_in_luma_samples 1080
conformance_window_flag 0
bit_depth_luma 8
bit_depth_chroma 8
log2_max_pic_order_cnt_lsb 8
sps_sub_layer_ordering_info 1
sps_max_dec_pic_buffering 5
sps_num_reorder_pics 2
sps_max_latency_increase_plus1 5
log2_min_coding_block_size 3
log2_diff_max_min_coding_block_size 3
log2_min_transform_block_size 2
log2_diff_max_min_transform_block_size 3
max_transform_hierarchy_depth_inter 0
max_transform_hierarchy_depth_intra 0
scaling_list_enabled_flag 0
amp_enabled_flag 0
sample_adaptive_offset_enabled_flag 1
pcm_enabled_flag 0
num_short_term_ref_pic_sets 0
long_term_ref_pics_present_flag 0
sps_temporal_mvp_enable_flag 1
sps_strong_intra_smoothing_enable_flag 1
vui_parameters_present_flag 1
VUI
aspect_ratio_info_present_flag 1
aspect_ratio_idc 1
overscan_info_present_flag 0
video_signal_type_present_flag 0
chroma_loc_info_present_flag 0
neutral_chroma_indication_flag 0
field_seq_flag 0
frame_field_info_present_flag 0
default_display_window_flag 0
vui_timing_info_present_flag 1
vui_num_units_in_tick 1001
vui_time_scale 60000
vui_poc_proportional_to_timing_flag 0
hrd_parameters_present_flag 0
bitstream_restriction_flag 0
pps_seq_parameter_set_id 0
dependent_slice_segments_enabled_flag 0
output_flag_present_flag 0
num_extra_slice_header_bits 0
sign_data_hiding_flag 1
cabac_init_present_flag 0
num_ref_idx_l0_default_active 1
num_ref_idx_l1_default_active 1
init_qp 26
constrained_intra_pred_flag 0
transform_skip_enabled_flag 0
cu_qp_delta_enabled_flag 1
diff_cu_qp_delta_depth 1
pps_cb_qp_offset 0
pps_cr_qp_offset 0
pps_slice_chroma_qp_offsets_present_flag 0
weighted_pred_flag 1
weighted_bipred_flag 0
transquant_bypass_enable_flag 0
tiles_enabled_flag 0
entropy_coding_sync_enabled_flag 1
loop_filter_across_slices_enabled_flag 1
deblocking_filter_control_present_flag 0
pps_scaling_list_data_present_flag 0
lists_modification_present_flag 0
log2_parallel_merge_level 2
slice_segment_header_extension_present_flag 0
pps_extension_flag 0
number of PPS 1
number of frames 30
It’s not uncommon when aspect ratio is absent in a hevc elementary stream and a decoder applies a default aspect ratio which does not match. The following python script ModifyHevcAspectRatio.py(python 2.x)
gets sample aspect ratio width and height and update aspect ratio parameters in SPS-VUI.
Usage:
-i input hevc stream
-o output hevc stream with modified aspect ratio signaled
–aspectw sample aspect ratio width, default 1
–aspecth sample aspect ratio height, default 1
-n number gops to process, if 0 then the whole stream
Example [setting 16:9]:
python ModifyHevcAspectRatio.py -i test.h265 --aspectw 16 --aspecth 9 -o test_aspect.h265
Note: ffmpeg also supports modification of aspect ratio without re-encoding, only changing SPS (by using ‘hevc_metadata‘:
ffmpeg -i swbf.h265 -c:v copy -bsf:v "hevc_metadata=sample_aspect_ ratio=1/1" -y swbf_ar.h265
ffmpeg -i swbf.h264 -c:v copy -bsf:v "h264_metadata=sample_aspect_ ratio=4/3" -y swbf_ar.h264
Detect Discontinuities in frame_num cadence in AVC/H.264 elementary stream
The syntax element ‘frame_num’ (signaled in the slice header) is not a sort of ‘frame counter’ since frame_num is incremented only if the previous frame is used for reference.
Moreover frame_num is incremented modulo 1<<log2_frame_num ( the syntax element ‘log2_frame_num’ is signaled in SPS).
In case of a network congestion the method usually called as ‘stream thinning’ is applied – to discard frames which not used for reference in order to reduce bitrate (in such case some jitter or short freezes can be observed). Sometimes the whole frame can disappear due to packet losses or it can arrive to a decoder too late to be displayed (relevant for low-latency applications). Loss of used for reference frame causes serious visual distortions since Encoder and Decoder uses different references (they are out-sync), these distortions are cleaned by IDR-frame or by “intra-refresh brush”.
the python script DetectFrameNumGaps.py (version 2.x) is tailored to detect gaps in frame_num cadence, python version 3.x – DetectFrameNumGaps3x.py
Usage (identical for bothDetectFrameNumGaps.pyandDetectFrameNumGaps3x.py):
-n number frames to process, if 0 then the whole stream processed, default 0.
-v verbose mode (default false)
naltype 6, offset 0x9
naltype 6, offset 0x1f
naltype 6, offset 0x30
naltype 7, offset 0x39
profile_idc 100
constraint_flags 0 0 0 0
level 40
sps_id 0
chroma_format_idc 1
depth_luma 8, depth_chroma 8
qpprime_y_zero_transform_bypass_flag 0
Scaling Matrices:
IntraY4x4 not present
IntraCb4x4 not present
IntraCr4x4 not present
InterY4x4 not present
InterCb4x4 not present
InterCr4x4 not present
IntraY8x8 not present
InterY8x8 not present
log2_frame_num 4
naltype 5, offset 0x77
idr (frame number 0)
slice type I
frame 0, frameNum 0
naltype 6, offset 0x3ed
naltype 1, offset 0x3fe
slice type P
frame 1, frameNum 1
naltype 6, offset 0x6c0
naltype 1, offset 0x6d1
slice type B
frame 2, frameNum 2
naltype 6, offset 0x956
naltype 1, offset 0x967
slice type P
frame 3, frameNum 2
naltype 6, offset 0x1da8
naltype 1, offset 0x1db9
slice type B
frame 4, frameNum 3
naltype 6, offset 0x24b0
naltype 1, offset 0x24c1
slice type P
frame 5, frameNum 3
naltype 6, offset 0x4102
naltype 1, offset 0x4113
slice type B
frame 6, frameNum 4
naltype 6, offset 0x4514
naltype 1, offset 0x4525
slice type P
frame 7, frameNum 4
naltype 6, offset 0x6927
naltype 1, offset 0x6938
slice type B
frame 8, frameNum 5
naltype 6, offset 0x6b07
naltype 1, offset 0x6b18
slice type P
frame 9, frameNum 5
Number of IDRs 1
Number of gaps in frame_num 0
Number of IDRs 86
Number of gaps in frame_num 1
Removal of Non-Reference Frames from H.264/AVC Elementary Stream in order to Reduce Bitrate
One of adaptive bitrate methods is to remove non-reference frames (usually B-frames) from a stream. Consequently, the stream bitrate is reduced. In case of network jams removal of non-reference frames is an alternative approach tinstead of switching to lower bitrate stream. Moreover, such stream “thinning” can be easily executed by Middle Boxes without overloading of server.
Removal of non-reference frame might make only jitter visible. Because the frame is not used for reference no drift in reference data between encoder and decoder happens.
I share the python script ThinningH264Stream.py which performs “thinning” of h264/avc elementary stream.
Usage:
-o output h264-file without non-reference frames
-n number frames to process, if 0 then the whole stream processed
-v verbose mode – nal types and other info is printed (default false)
naltype 9 ( aud), ref-idc 0, offset (hex) 0
naltype 7 ( sps), ref-idc 3, offset (hex) 6
naltype 8 ( pps), ref-idc 3, offset (hex) 20
naltype 6 ( sei), ref-idc 0, offset (hex) 29
naltype 5 ( idr), sliceType i, ref-idc 3, offset (hex) 2a4
naltype 5 ( idr), ref-idc 3, offset (hex) f82 non-first slice
naltype 5 ( idr), ref-idc 3, offset (hex) 1d02 non-first slice
frame size 11420
naltype 9 ( aud), ref-idc 0, offset (hex) 2c9c
naltype 1 ( ipb), sliceType p, ref-idc 2, offset (hex) 2ca2
naltype 1 ( ipb), ref-idc 2, offset (hex) 2ce1 non-first slice
naltype 1 ( ipb), ref-idc 2, offset (hex) 2d96 non-first slice
frame size 286
naltype 9 ( aud), ref-idc 0, offset (hex) 2dba
naltype 1 ( ipb), sliceType b, ref-idc 1, offset (hex) 2dc0
naltype 1 ( ipb), ref-idc 1, offset (hex) 2dd5 non-first slice
naltype 1 ( ipb), ref-idc 1, offset (hex) 2e04 non-first slice
frame size 102
naltype 9 ( aud), ref-idc 0, offset (hex) 2e20
naltype 1 ( ipb), sliceType b, ref-idc 0, offset (hex) 2e26
naltype 1 ( ipb), ref-idc 0, offset (hex) 2e3a non-first slice
naltype 1 ( ipb), ref-idc 0, offset (hex) 2e4d non-first slice
frame size 73
naltype 9 ( aud), ref-idc 0, offset (hex) 2e69
naltype 1 ( ipb), sliceType b, ref-idc 0, offset (hex) 2e6f
naltype 1 ( ipb), ref-idc 0, offset (hex) 2e7e non-first slice
naltype 1 ( ipb), ref-idc 0, offset (hex) 2eaa non-first slice
frame size 92
naltype 9 ( aud), ref-idc 0, offset (hex) 2ec5
naltype 1 ( ipb), sliceType p, ref-idc 2, offset (hex) 2ecb
naltype 1 ( ipb), ref-idc 2, offset (hex) 2ef8 non-first slice
naltype 1 ( ipb), ref-idc 2, offset (hex) 2fc0 non-first slice
frame size 318
naltype 9 ( aud), ref-idc 0, offset (hex) 3003
naltype 1 ( ipb), sliceType b, ref-idc 1, offset (hex) 3009
naltype 1 ( ipb), ref-idc 1, offset (hex) 3021 non-first slice
naltype 1 ( ipb), ref-idc 1, offset (hex) 30cb non-first slice
frame size 245
naltype 9 ( aud), ref-idc 0, offset (hex) 30f8
naltype 1 ( ipb), sliceType b, ref-idc 0, offset (hex) 30fe
naltype 1 ( ipb), ref-idc 0, offset (hex) 3110 non-first slice
naltype 1 ( ipb), ref-idc 0, offset (hex) 3139 non-first slice
frame size 97
naltype 9 ( aud), ref-idc 0, offset (hex) 3159
naltype 1 ( ipb), sliceType b, ref-idc 0, offset (hex) 315f
naltype 1 ( ipb), ref-idc 0, offset (hex) 3174 non-first slice
naltype 1 ( ipb), ref-idc 0, offset (hex) 31e2 non-first slice
frame size 173
naltype 9 ( aud), ref-idc 0, offset (hex) 3206
naltype 1 ( ipb), sliceType p, ref-idc 2, offset (hex) 320c
naltype 1 ( ipb), ref-idc 2, offset (hex) 3259 non-first slice
naltype 1 ( ipb), ref-idc 2, offset (hex) 34b4 non-first slice
frame size 801
Enhancement of Random Access Ability of H.264/AVC Stream by Insertion of SPS/PPS at IDR frames
SPS:
00 00 00 01 67 42 00 1e 8d 68 1e 08 e9 a8 08 08 08
10
PPS:
00 00 00 01 68 ce 09 c8
3 HL headers added
Remove Frames Until First Key Frame in H.264/AVC File
Sometimes h264 files start with non-key frame (e.g. if segmentation done at frame boundary and not at key frame boundary, in such case a segment might start from non-key frame). Most of players can’t play such files (e.g. Pot player)
The script CutLeadFramesH264.py seeks the fist key frame.
All frames prior to the key frame are discarded, the rest of frames are stored in the output file.
Usage:
beginning.
Example:
python CutLeadFramesH264.py -i test_no_sps.h264 -o test1.h264 -v –idr
…
Frame 103, naltype 1, frameStart 0xd1bb9
Frame 104, naltype 1, frameStart 0xd2e55
Frame 105, naltype 1, frameStart 0xd465b
Frame 106, naltype 1, frameStart 0xd5a9d
Frame 107, naltype 1, frameStart 0xd77d1
Frame 108, naltype 1, frameStart 0xd9031
Frame 109, naltype 1, frameStart 0xdae98
Frame 110, naltype 1, frameStart 0xdcb33
Frame 111, naltype 1, frameStart 0xdede7
Frame 112, naltype 1, frameStart 0xe0dce
Frame 113, naltype 1, frameStart 0xe2b96
Frame 114, naltype 1, frameStart 0xeaf0b
Frame 115, naltype 1, frameStart 0xed80f
Frame 116, naltype 1, frameStart 0xee851
Frame 117, naltype 1, frameStart 0xefab2
Frame 118, naltype 1, frameStart 0xf0cc4
Frame 119, naltype 1, frameStart 0xf1f4b
Frame 120, naltype 1, frameStart 0xf36f3
Frame 121, naltype 1, frameStart 0xf4f7e
Frame 122, naltype 1, frameStart 0xf6869
Frame 123, naltype 1, frameStart 0xf8b5a
Frame 124, naltype 1, frameStart 0xfa090
Frame 125, naltype 1, frameStart 0xfbf8c
Frame 126, naltype 1, frameStart 0xfdb06
Frame 127, naltype 1, frameStart 0xff56b
write output file
Get DTS Statistics of both Video and Audio in MPEG2 System (Transport) Stream
In Cloud Gaming timestamps (DTS) of video and audio frames are determined at rendering stage by reading current clock and converting it to 90kHz. Intervals between video/audio timestamps are not necessarily fixed (the rendering rate can drop). In applications where video is captured from cameras interval between frames can fluctuate too.
The script GetDtsAnalysis.py collects DTS values of both video (H.264/AVC or H.265/HEVC) and audio frames and computes the following statistics:
- The number of total ts-packets, video ts-packets, audio ts-packets, video frames and audio frames.
- For both video and audio:
Minimal interval between two successive DTS values
Maximal interval between two successive DTS values
Average interval between two successive DTS values
Standard deviation (std) of DTS intervals
- In addition alignment (the maximum and the average) between video and audio DTS is computed: for each video frame DTS the script looks for the audio DTS which is most close to it (this is an useful feature to detect potential li-syncs).
-i input ts-file
-v whether to print all DTS values
Example:
video_pid 100, audio_pid 101
Collect PTS …
Number of video packets 116460
Number of audio packets 1896
Number of video frames 355
Number of audio frames 474
Max Video DTS differences in ms 46.5
Average Video DTS differences in ms 33.4
Std of Video DTS differences in ms 1.6
Max Audio DTS differences in ms 28.1
Average Audio DTS differences in ms 26.1
Std of Audio DTS differences in ms 0.4
Average DTS Diff between video and audio in ms 6.5
Get H265/HEVC Video Statistics from Transport Stream
The script GetHEVCVideoStatsFromTS.py
is tailored to collect statistics – total number oframes, total number of key frames (IDR frame accompanied with VPS, SPS and PPS). The script prints also per frame statistics: NALU type and current frame offset. It’s worth mentioning that access unit delimiter (AUD) is expected at the start of each frame (requested by Mpeg2 System).
Usage:
-i input transport file (ts) containing hevc elementary stream
-n number frames to process, if 0 then the whole stream (default 0)
Examples:
[Process 5 frames only ]
python GetHEVCVideoStatsFromTS.py -i test.ts -n 5
video pid 1024
Key Frame 0, nalType 20, offset 0x24e, pkt 14
Frame 1, nalType 1, offset 0x85ba, pkt 182
Frame 2, nalType 1, offset 0x969e, pkt 205
Frame 3, nalType 1, offset 0xbc12, pkt 256
Frame 4, nalType 1, offset 0xd44e, pkt 289
Frame Count 5, key frames 1
VPS Cnt 1
SPS Cnt 1
PPS Cnt 1
[Process the whole steam ]
python GetHEVCVideoStatsFromTS.py -i test.ts
….
Frame 374, nalType 1, offset 0x2c8da6, pkt 15531
Frame 375, nalType 1, offset 0x2c9676, pkt 15543
Key Frame 375, nalType 20, offset 0x2ca00a, pkt 15567
Frame 376, nalType 1, offset 0x2d0616, pkt 15695
Frame 377, nalType 1, offset 0x2d0b3a, pkt 15702
Frame 378, nalType 1, offset 0x2d1292, pkt 15712
Frame 379, nalType 1, offset 0x2d1c1e, pkt 15725
Frame 380, nalType 1, offset 0x2d2376, pkt 15735
Frame 380, nalType 1, offset 0x2d2ad6, pkt 15745
Frame 381, nalType 1, offset 0x2d3226, pkt 15755
Frame 382, nalType 1, offset 0x2d38c2, pkt 15764
Frame 383, nalType 1, offset 0x2d40d6, pkt 15775
Frame 384, nalType 1, offset 0x2d4772, pkt 15784
Frame 385, nalType 1, offset 0x2d4e0e, pkt 15793
Frame 385, nalType 1, offset 0x2d556e, pkt 15803
Frame 386, nalType 1, offset 0x2d5d7a, pkt 15814
Frame 387, nalType 1, offset 0x2d658e, pkt 15825
Frame 388, nalType 1, offset 0x2d6da2, pkt 15836
Frame 389, nalType 1, offset 0x2d7672, pkt 15848
Frame 390, nalType 1, offset 0x2d7ffe, pkt 15861
Frame 390, nalType 1, offset 0x2d88d6, pkt 15873
Frame 391, nalType 1, offset 0x2d9026, pkt 15883
Frame 392, nalType 1, offset 0x2d9a6e, pkt 15897
Frame 393, nalType 1, offset 0x2da282, pkt 15908
Frame 394, nalType 1, offset 0x2daa96, pkt 15919
Frame 395, nalType 1, offset 0x2db1ee, pkt 15929
Frame 395, nalType 1, offset 0x2dbac6, pkt 15941
Frame 396, nalType 1, offset 0x2dc2d2, pkt 15952
Frame 397, nalType 1, offset 0x2dcae6, pkt 15963
Frame 398, nalType 1, offset 0x2dd23e, pkt 15973
Frame 399, nalType 1, offset 0x2ddc86, pkt 15987
Frame 400, nalType 1, offset 0x2de3de, pkt 15997
Key Frame 400, nalType 20, offset 0x2decb6, pkt 16020
Frame 401, nalType 1, offset 0x2e52c2, pkt 16148
Frame 402, nalType 1, offset 0x2e5ad6, pkt 16159
Frame 403, nalType 1, offset 0x2e6172, pkt 16168
Frame 404, nalType 1, offset 0x2e6bba, pkt 16182
Frame 405, nalType 1, offset 0x2e7546, pkt 16195
Frame 405, nalType 1, offset 0x2e7e1e, pkt 16207
Frame 406, nalType 1, offset 0x2e8a92, pkt 16224
Frame 407, nalType 1, offset 0x2e94da, pkt 16238
Frame 408, nalType 1, offset 0x2e9e66, pkt 16251
Frame 409, nalType 1, offset 0x2eaae2, pkt 16268
Frame 410, nalType 1, offset 0x2eb46e, pkt 16281
Frame 410, nalType 1, offset 0x2ebf7a, pkt 16296
Frame 411, nalType 1, offset 0x2ece22, pkt 16316
Frame 412, nalType 1, offset 0x2edcd2, pkt 16336
Frame 413, nalType 1, offset 0x2eedb6, pkt 16359
Frame 414, nalType 1, offset 0x2efe9a, pkt 16382
Frame 415, nalType 1, offset 0x2f11b2, pkt 16408
Frame 415, nalType 1, offset 0x2f264a, pkt 16436
Frame 416, nalType 1, offset 0x2f395a, pkt 16462
Frame Count 416, key frames 17
VPS Cnt 17
SPS Cnt 17
PPS Cnt 17
Remove AUDs (Access Unit Delimiters) from H.264/AVC and H.265/HEVC Elementary Streams
The scripts RemoveAudsInH264Stream.py and RemoveAudsInHEVCStream.py
Remove AUDs (access unit delimiters) from AVC/H.264 and HEVC/H.265 elementary streams. Number of removed AUDs is reported at the end.
If no AUD is present then output file is not generated and corressponding print issued.
Usage:
Example:
python RemoveAudsInHEVCStream.py test.h265 test_no_auds.h265
Analyzing …
||===========================================================> |||
AUDs to remove 59
Print pic_parameter_set_id of each frame in H.264/AVC stream, relevant if multiple PPS are present
Motivation: Some NVIDIA encoders (e.g. T4) supports Weighted Prediction mode (specified by the parameter enableWeightedPrediction in NV_ENC_INITIALIZE_PARAMS structure). If enableWeightedPrediction is on then the encoder generates two PPS – the first PPS (with pic_parameter_set_id=0) enables Weighted Prediction (weighted_pred_flag=1), the second PPS (with pic_parameter_set_id=1) disables Weighted Prediction.
In the slice header of each frame the first PPS is chosen if the weighted prediction is activated in this frame, otherwise the second PPS is assigned. It’s desirable to know how many frames in the stream utilize the weighted prediction. In other words how many frames carry pic_parameter_set_id=0 in theirs slice headers.
The script GetFramePpsIdH264.py traverses H.264/AVC elementary stream and prints: the following info per frame:
- Frame number
- Frame offset in bytes
- Slice Nal type (5 – for IDR and 1 for others)
- pic_parameter_set_id
Usage:
-i input h264-file
-n number frames to process, if 0 then the whole stream processed
Example:
python GetFramePpsIdH264.py -i test_wp.h264
…..
Frame 679, Offset 1d4847, NalType 1, ppsid 1
Frame 680, Offset 1d4dbb, NalType 1, ppsid 1
Frame 681, Offset 1d53c1, NalType 1, ppsid 1
Frame 682, Offset 1d5836, NalType 1, ppsid 1
Frame 683, Offset 1d5d7e, NalType 1, ppsid 1
Frame 684, Offset 1d63ba, NalType 1, ppsid 1
Frame 685, Offset 1d6931, NalType 1, ppsid 1
Frame 686, Offset 1d6de7, NalType 1, ppsid 1
number frames with pps_id=0 0
number frames with pps_id=1 687
Print weighted prediction parameters per frame/slice (for H.264/AVC) streams, adapted for Python 3.x
Sometimes it’s worth to know whether your encoder chooses non-trivial weighted prediction (and on what frames).
The following python 3.x script PrintWPStatisticsH264.py parses all P-slice headers and print weighted prediction parameters (if present). Multiple PPS supported.
Multiple slices supported. Notice that only P-slices are analyzed for weighted prediction.
Usage:
-i input h264-file
-n number frames to process, if 0 then the whole stream processed
Example [weighted prediction is off, four slices per frame]
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
….
Example [weighted prediction is activates on some frames, switching the weighted prediction on frame level is allowed by multiple PPS, the first PPS with weighted_pred_flag=off and another on ]
python PrintWPStatisticsH264.py -i test1.h264
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
Reference Picture 0
luma_weight_l0 33
luma_offset_l0 0
chroma_weight_cb 33
chroma_offset_cb -4
chroma_weight_cr 33
chroma_offset_cr -3
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
Reference Picture 0
luma_weight_l0 33
luma_offset_l0 0
chroma_weight_cb 33
chroma_offset_cb -4
chroma_weight_cr 33
chroma_offset_cr -3
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
Reference Picture 0
luma_weight_l0 33
luma_offset_l0 0
chroma_weight_cb 33
chroma_offset_cb -4
chroma_weight_cr 33
chroma_offset_cr -3
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
Reference Picture 0
luma_weight_l0 33
luma_offset_l0 0
chroma_weight_cb 33
chroma_offset_cb -4
chroma_weight_cr 33
chroma_offset_cr -3
weighted prediction off
weighted prediction off
weighted prediction off
weighted prediction off
Parse SPS and Print Resolution (H.264/AVC)
Sometimes encoders change resolution at the middle of video stream to cope with instabilities in transmission mediums. By the way Nvidia SDK has even a special routine
NvEncReconfigureEncoder to reconfigure video resolution on the fly without resetting of the encoder.
The script PrintResolutionsInH264ES.py is tailored to traverse input H264/AVC elementary stream and print resolutions signaled in SPS.
Usage:
-i input h264-file
-n number frames to process, if 0 then the whole stream processed
-v print other SPS parameters in addition to resolution (default false)
-q print resolution signaled in SPS only if it is changed (default false), if it is on then verbose set to false
Example [ print resolutions signaled in all SPS (regardless whether the resolution changed or not), plus printing other SPS parameters
python PrintResolutionsInH264ES.py -i test.h264 -v
profile_idc 100
level 40
sps_id 0
pic_order_cnt_type 0
max_pic_order_cnt 32768
max_num_ref_frames 1
Frame 0 (offset 0x0), width 704, height 576
profile_idc 100
level 40
sps_id 0
pic_order_cnt_type 0
max_pic_order_cnt 32768
max_num_ref_frames 1
Frame 25 (offset 0x285e0), width 704, height 576
profile_idc 100
level 40
sps_id 0
pic_order_cnt_type 0
max_pic_order_cnt 32768
max_num_ref_frames 1
Frame 50 (offset 0x4e4f3), width 704, height 576
profile_idc 100
level 40
sps_id 0
pic_order_cnt_type 0
max_pic_order_cnt 32768
max_num_ref_frames 1
Frame 75 (offset 0x76297), width 704, height 576
profile_idc 100
level 40
sps_id 0
pic_order_cnt_type 0
max_pic_order_cnt 32768
max_num_ref_frames 1
Frame 100 (offset 0x9de9a), width 704, height 576
Example [ print resolutions (signaled in all SPS) only if they are changed]
python PrintResolutionsInH264ES.py -i test.h264 -q
Frame 0 (offset 0x0), width 1920, height 1088
Frame 300 (offset 0x59608c), width 1888, height 1088
Frame 600 (offset 0xe6da04), width 1872, height 1088
Frame 900 (offset 0x170bb55), width 1856, height 1088
Frame 1200 (offset 0x212048b), width 1840, height 1088
Frame 1500 (offset 0x2b0a028), width 1824, height 1088
Frame 1800 (offset 0x351791c), width 1808, height 1088
Frame 2100 (offset 0x3efced9), width 1792, height 1088
Frame 2400 (offset 0x48f557f), width 1776, height 1088
Frame 2700 (offset 0x534dde0), width 1760, height 1088
Frame 3000 (offset 0x5db3029), width 1744, height 1088
Frame 3300 (offset 0x681b400), width 1728, height 1088
Frame 3600 (offset 0x722507e), width 1712, height 1088
Frame 3900 (offset 0x7c509eb), width 1696, height 1088
Frame 4200 (offset 0x86d3afd), width 1680, height 1088
Frame 4500 (offset 0x91687f0), width 1664, height 1088
Frame 4800 (offset 0x9be119c), width 1648, height 1088
Get Number Slices in H.264/HEVC Streams
The script GetNumberSlicesPerFrameInH264 (adapted for Python 3.x) is tailored to count and print the number of slices per frame for input h264/avc file. This script is relevant in analysis of dynamic slicing mode. In addition the script GetNumberSlicesPerFrameInHEVC count number of slices per frame for hevc elementary stream
Usage:
-i input h264-file (elementary stream)
-n number of frames to process, if 0 (default) then the whole stream processed
Example [ h264 case, print slices per frame for first 10 frames]
python GetNumberSlicesPerFrameInH264.py -i crowdrun1080p_slices.h264 -n 10
slices 4
slices 4
slices 4
slices 4
slices 4
slices 4
slices 4
slices 4
slices 4
slices 4
python GetNumberSlicesPerFrameInHEVC.py -i test_slices5.h265 -n 10
frame start 0, position 0x0
slices 5
frame start 1, position 0x25d5d
slices 5
frame start 2, position 0x465de
slices 5
frame start 3, position 0x52cce
slices 5
frame start 4, position 0x5bfc5
slices 5
frame start 5, position 0x658de
slices 5
frame start 6, position 0x6f844
slices 5
frame start 7, position 0xa0df5
slices 5
frame start 8, position 0xb1786
slices 5
frame start 9, position 0xbd830
————————————————————————————————————————————————-
Parse SPS and Print Custom Scaling Matrices in H.264/AVC
The script PrintScalingMatricesH264.py parses SPS of H.264/AVC elementary stream and prints custom scaling matrices (if present), the script is adapted for Python 3.x
Usage:
-i input h264-file (elementary stream)
-n number of frames to process, if 0 (default) then the whole stream processed
Example [ process 20 first frames and parse all SPS]
profile_idc 100
level 40
sps_id 0
scaling_list_present_flag[0] 1
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (8×8):
16 18 20 22 24 26 28 30 18 18 22 24 26 28 30 32 20 22 24 26 28 30 32 34 22 24 26 28 30 32 34 36 24 26 28 30 32 34 36 39 26 28 30 32 34 36 39 42 28 30 32 34 36 39 42 45 30 32 34 36 39 42 45 48
scales (8×8):
16 18 20 22 24 26 28 30 18 18 22 24 26 28 30 32 20 22 24 26 28 30 32 34 22 24 26 28 30 32 34 36 24 26 28 30 32 34 36 39 26 28 30 32 34 36 39 42 28 30 32 34 36 39 42 45 30 32 34 36 39 42 45 48
profile_idc 100
level 40
sps_id 0
scaling_list_present_flag[0] 1
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (4×4):
16 21 26 31 21 26 31 36 26 31 36 41 31 36 41 48
scales (8×8):
16 18 20 22 24 26 28 30 18 18 22 24 26 28 30 32 20 22 24 26 28 30 32 34 22 24 26 28 30 32 34 36 24 26 28 30 32 34 36 39 26 28 30 32 34 36 39 42 28 30 32 34 36 39 42 45 30 32 34 36 39 42 45 48
scales (8×8):
16 18 20 22 24 26 28 30 18 18 22 24 26 28 30 32 20 22 24 26 28 30 32 34 22 24 26 28 30 32 34 36 24 26 28 30 32 34 36 39 26 28 30 32 34 36 39 42 28 30 32 34 36 39 42 45 30 32 34 36 39 42 45 48
————————————————————————————————————————————————-
Compare SPS in H264/AVC stream
Sometimes h264/avc stream is spliced from several segments and each segment carries its own SPS.
The script CompareSPSinH264Ver3.py (adapted for Python version 3.x) compare SPS along the whole h264/avc stream and prints differences (if present), actually the very first SPS is compared with all other SPS
Usage:
-i input h264-file
-v verbose mode (default false)
Example:
SPS at address 104fac differ in size with first sps (first len 119, current len 118)
SPS at address 1a870b differ in size with first sps (first len 119, current len 118)
SPS at address 24b810 differ in size with first sps (first len 119, current len 118)
————————————————————————————————————————————————-
Get Instant Bitrates from H264 File
-n number frames to process, if 0 then the whole stream processed
-v verbose mode (default false)
-p print progress (default false), set fault if verbose is ON
-f frame rate either 30 or 60, default 60
–overlap overlaping window with hop of frame duration (default false)
–winsize window size in seconds for calculation instant bitrate (default 1)
Example:
python GetBitrate.py -i crowdrun1080p.h264 -f 60
number of frames 1000
non-overlap windowing, window size 1s, average bitrate (Mbps) 21.2264, maxbitrate (Mbps) 23.6517
Note:
ffprobe is declared as supporting computation of the average bitrate, but for elementary streams ffprobe provides nothing
ffprobe -v quiet -show_entries stream=bit_rate -of default=noprint_wrappers=1 test.h264
bit_rate=N/A
Moreover, i found that for mpegts streams results of ffprobe bitrate computation are wrong, for test.ts with video bitrate ~5Mbps, ffprobe shows incorrect result:
ffprobe -v quiet -show_entries stream=bit_rate -of default=noprint_wrappers=1 test.ts
bit_rate=192141
bit_rate=N/A
bit_rate=192141
bit_rate=N/A
In addition there are two free bitrate viewers:
- Bitrate viewer based on ffprobe (actually GUI version of ffprobe) – ffmpeg bitrate viewer:
————————————————————————————————————————————————-
Usage:
-i input hevc-file
-n number frames to process, if 0 then the whole stream processed
-v verbose mode (default false)
-p print progress (default false), set fault if verbose is ON
-f frame rate (integer), default 60
–overlap overlaping window with hop of frame duration (default false)
–winsize window size in seconds for calculation instant bitrate (default 1)
Example:
python GetHevcBitrate.py -i crowd_2Mbps_deadzone_50_ver2.hevc -f 50
number of frames 500
non-overlap windowing, window size 1s, average bitrate (Mbps) 2.1179, maxbitrate (Mbps) 3.7076
————————————————————————————————————————————————-
Remove Specific SEI Messages from HEVC File
Sometimes SEI messages in HEVC/H.265 streams get redundant (or even can mislead decoders). Therefore i provide the script RemoveSeiFromHevcStream.py to remove all SEI messages from the input HEVC/H.265 elementary stream (“SEI thinning”)
The script works at GOP level (to be easy in future to parallel it), the script reads the whole GOP, analyzes it, removes SEIs and writes SEI-free GOP to output file.
Usage:
-i input hevc fifo or file
-o output hevc tiled stream
-v whether to print naltypes and offsets (default false)
Example:
python RemoveSeiFromHevcStream.py -i test.h265 -o qwert.h265
gop 0, address 0x0
gop 1, address 0xd2535
gop 2, address 0x146657
removed seis 31
———————————————————————————————————————————————————————————————————
Get Meta Data of HEVC Stream in MP4-file
The script GetMetaHevcHdr searches video track in mp4-file and checks whether the track contains hevc-stream (‘hev1’ or ‘hvc1’ are present). If hevc-stream is presnt then hvcC-box is parsed and the stream’s information printed:
Usage:
-i input mp4-file containing hevc stream
-d dump headers vps, sps and pps as vps.bin, sps.bin and pps.bin (default false), note – strat code ’00 00 00 01′ added.
Example:
python GetMetaHevcHdr.py -i strange.mp4
C:\Tools>python GetMetaHevcHdr.py -i strange.mp4
video trak number 0
resolution 1920×1080
Configuration Version 0x1
profile Main
compatibility_flags 60000000
progressive_source_flag 0
interlaced_source_flag 0
non_packed_constraint_flag 0
frame_only_constraint_flag 0
level_idc 0x78 (120)
min_spatial_segmentation_idc 0x0
parallelismType 0
chromaFormat 1
luma_bit_depth 8
chroma_bit_depth 8
avgFrameRate 0
constantFrameRate 0
numTemporalLayers 3
temporalIdNested 0
nal_unit_size 4
high level headers 3
Hexstr 0x20
array_completeness 0
header type VPS
nal_count 1
hdr_len 30
Hexstr 0x21
array_completeness 0
header type SPS
nal_count 1
hdr_len 66
Hexstr 0x22
array_completeness 0
header type PPS
nal_count 1
hdr_len 9
Detect Large Frames in H264/AVC Elementary Stream
We determine large frames as frames with sizes exceeding much the expected size for a given bitrate. Such spike frames can impact on latency and cause network congestions. I-frames or P-frames at a scene cut or a flaw in Rate Control can generate large frames.
It’s obvious that the stream should be generated by an encoder configured with CBR mode or in VBR mode. If the encoder is configured with CRF or constant QP mode then frame size fluctuations are caused by the complexity of scenes.
The script DetectLargeFramesInH264 is tailored to detect large frames in h264/avc elementary stream. This script works in dual-pass mode, in the first pass it gathers statisitics and in the second pass the script processes collected data. In addition to number of large frames the scripts compute average and peak bitrates (taken over the window of 1s).
This script is dedicated to check Rate Control in CBR/VBR modes.
Usage:
-i input h264-file
-n number frames to process, if 0 then the whole stream processed
-s skip first frames due to ubstability Rate Control at the start, default 0
-t target bitrate in Mbps, default 10Mbps
-v verbose mode, print numbers of large frames (default false)
-f frame rate, default 60
-a large frame scale factor, when the size of a frame in bytes exceeds ‘factor’ x ‘expected_size’ it is called Large Frame, default 1.5x above the expected
Example [ find large frames exceeding the expectd size by 1.5x or more, the traget bitrate is 10Mbps, the frame rate 60fps, skip first 10 frames due to instability of Rate Control at the start]
python DetectLargeFramesInH264.py -i test_vbr_10Mbps.h264 -s 10 -t 10 -v -f 60 -a 1.5
Expected frame size 20833 bytes
number of frames 765
62 frame type pb frame size 31432 (expected 20833)
387 frame type pb frame size 33387 (expected 20833)
480 frame type idr frame size 31412 (expected 20833)
540 frame type idr frame size 32222 (expected 20833)
660 frame type idr frame size 32998 (expected 20833)
720 frame type idr frame size 34312 (expected 20833)
average bitrate (Mbps) 9.5568, peak bitrate (Mbps) 9.9682
number Large Frames (scale threshold 1.500000) 6
Note: frame type is either ‘idr’ or ‘pb’ including P,B or non-IDR I-frame
Detect Large Frames in HEVC Elementary Stream
Description is similar to that of h264 case – Detect Large Frames in H264/AVC Elementary Stream
The script DetectLargeFramesInHEVC is tailored to detect large frames in hevc elementary stream. This script works in dual-pass mode, in the first pass it gathers statisitics and in the second pass the script processes collected data. In addition to number of large frames the scripts compute average and peak bitrates (taken over the window of 1s).
This script is dedicated to check Rate Control in CBR/VBR modes.
Usage:
-i input hevc-file
-n number frames to process, if 0 then the whole stream processed
-s skip first frames due to ubstability Rate Control at the start, default 0
-t target bitrate in Mbps, default 10Mbps
-v verbose mode, print numbers of large frames (default false)
-f frame rate, default 60
-a large frame scale factor, when the size of a frame in bytes exceeds ‘factor’ x ‘expected_size’ it is called Large Frame, default 1.5x above the expected
Example [ find large frames exceeding the expectd size by 1.4x or more, the traget bitrate is 15Mbps, the frame rate 60fps]
python DetectLargeFramesInHEVC.py -i test_vbr_15M.h265 -s 0 -t 15 -v -f 60 -a 1.4
Expected frame size 31250 bytes
number of frames 557
0 frame type idr frame size 43967 (expected 31250)
148 frame type pb frame size 45329 (expected 31250)
478 frame type pb frame size 44949 (expected 31250)
549 frame type pb frame size 44957 (expected 31250)
average bitrate (Mbps) 13.4108, peak bitrate (Mbps) 14.9510
number Large Frames (scale threshold 1.400000) 4
Note: frame type is either ‘idr’ or ‘pb’ including P,B, I, CRA
Find Video Track Number in mp4-file
The script GetVideoTrakNo.py (adapted for Python 3.x) , looks for the video track (actually for the first video track) in mp4-file’s metadata and prints the track number (counted from one, not from zero, the reason MP4Box tool uses track numbers counted from 1).
Example:
python GetVideoTrakNo.py test.mp4
Video Track 1
Note:
video track can have number 2 or even higher.
Example:
python GetVideoTrakNo.py box.mp4
Video Track 2
mp4box -info box.mp4
* Movie Info *
Timescale 90000 – Duration 00:00:15.184
Fragmented File no – 2 track(s)
File Brand isom – version 0
Created: GMT Mon Jun 09 15:54:39 2014
File has no MPEG4 IOD/OD
Track # 1 Info – TrackID 1 – TimeScale 44100 – Duration 00:00:15.123
Media Info: Language “Undetermined” – Type “soun:mp4a” – 579 samples
MPEG-4 Config: Audio Stream – ObjectTypeIndication 0x6b
MPEG-1 Audio – 1 Channel(s) – SampleRate 44100 – Layer 2
Self-synchronized
Track # 2 Info – TrackID 2 – TimeScale 1000000 – Duration 00:00:15.217
Media Info: Language “Undetermined” – Type “vide:avc1” – 456 samples
Visual Track layout: x=0 y=0 width=640 height=480
MPEG-4 Config: Visual Stream – ObjectTypeIndication 0x21
AVC/H264 Video – Visual Size 640 x 480
AVC Info: 1 SPS – 1 PPS – Profile High @ Level 3
NAL Unit length bits: 32
Pixel Aspect Ratio 1:1 – Indicated track size 640 x 480
Synchronized on stream 1
Print Mpegts Packets Payload Sizes
The script PrintPayloadSize.py (adapted for Python 3.x) , traverses mpegts file until PAT/PMT found, then the script parses PAT/PMT to figire out video PID (h264 or hevc).
Then the scripts parses video mpegts packets and prints payload sizes (incl. PES headers).
Usage:
-i input mpegts-file (must contain video – h264 or hevc)
-n number of mpegts video packets to parse, if 0 then all, (default 0)
Note: For each packet three magnitudes are printed out:
packet number video packet number payload size in bytes
its commonly mpegts contains not only video packets, therefore packet number differs from video packet number.
Example [ process first 200 video packets]:
python PrintPayloadSize.py -i test_real_clock.ts -n 200
Pkt 1588, vpkt 0, mpegts-payload 182 // first video packet is 1588 packet from the beginning of the file and has payload 182 (due to adaptation field, since it’s a frame start)
Pkt 1589, vpkt 1, mpegts-payload 184
Pkt 1590, vpkt 2, mpegts-payload 184
Pkt 1591, vpkt 3, mpegts-payload 184
…
Pkt 1773, vpkt 180, mpegts-payload 184
Pkt 1774, vpkt 181, mpegts-payload 184
Pkt 1775, vpkt 182, mpegts-payload 184
Pkt 1776, vpkt 183, mpegts-payload 184
Pkt 1777, vpkt 184, mpegts-payload 184
Pkt 1778, vpkt 185, mpegts-payload 81 // the last packet in a frame, the payload size is not 184
Pkt 1779, vpkt 186, mpegts-payload 182 // the first packet in the next frame
Pkt 1780, vpkt 187, mpegts-payload 184
Pkt 1781, vpkt 188, mpegts-payload 184
Pkt 1782, vpkt 189, mpegts-payload 184
Pkt 1783, vpkt 190, mpegts-payload 184
Pkt 1784, vpkt 191, mpegts-payload 184
Pkt 1785, vpkt 192, mpegts-payload 184
Pkt 1786, vpkt 193, mpegts-payload 184
Pkt 1787, vpkt 194, mpegts-payload 184
Pkt 1788, vpkt 195, mpegts-payload 184
Pkt 1789, vpkt 196, mpegts-payload 184
Pkt 1790, vpkt 197, mpegts-payload 184
Pkt 1791, vpkt 198, mpegts-payload 184
Pkt 1792, vpkt 199, mpegts-payload 184
Cut H264/AVC Elementary Stream at Specified IDR
The python script CutH264AtIDR.py traverses the input stream until it detects k-th IDR (specified in the command line), then the script cuts the input stream at this IDR and the tail is saved as output h264 stream.
Usage:
-i input h264-file
-o output h264-file, cut at the specified k-th IDR
-n IDR number to cut (k-th IDR), must be greater 1, default 2 (i.e. at the second IDR to cut)
Examples:
python CutH264.py -i test.h264 -o test_tail.h264 -n 2
2-th idr found at offset 0x2c303a8, frame 3342
If k-th IDR not found then the output file is empty and a corresponding print is issued, e.g
python CutH264.py -i test.h264 -o test_tail.h264 -n 20
20-th idr not found, empty output file
The H264/AVC spec. contains two types of start-codes: long (32 bits, 00 00 00 01) and short (24 bits, 00 00 01)
During my career, once I was faced with a peculiar h264 decoder which ignored short start-codes (and respected long start codes). This decoder could not find the slice start if the start code was short.
I share the python script CountShortStartCodesInH264.py which detects and count short start codes in h264 file. In addtion this script counts the number of frames.
Usage:
-i input h264 file
-v verbose mode, print offset of short start code (default false)
-n number frames to process, if 0 then the whole stream processed
Example:
python CountShortStartCodesInH264.py -i battlefield_hp_cbr16_10M.h264
number of detected frames 557
number of short start codes 1672
Note: why number of start codes is greater than the number of frames? In the given stream each frame is divided into four slices. Thus each frame contains four start codes.
Example (process two frames in verbose mode)
python CountShortStartCodesInH264.py -i battlefield_hp_cbr16_10M.h264 -n 2 -v
short start code at offset 4467 (0x1173)
short start code at offset 8600 (0x2198)
short start code at offset 15524 (0x3ca4)
short start code at offset 20005 (0x4e25)
number of detected frames 2
number of short start codes 4
PNG is still-popular lossless format, despite it was developed at the middle of 90x. PNG file consists of chunks (control and data), each chunk ends with 4-bytes CRC code. Thus, the png-format is highly error resilient.
The python script ParsePNSG , adapted for 3.x version, is tailored to parse PNG file.
Example:
python ParsePNG.py -i intra-modes.png
chunk name: IHDR
chunk size: 13, offset 0x8
width 632
height 677
bit-depth 8
palette used 0
color image 1
chunk name: sRGB
chunk size: 1, offset 0x21
chunk name: gAMA
chunk size: 4, offset 0x2e
chunk name: pHYs
chunk size: 9, offset 0x3e
chunk name: IDAT
chunk size: 65445, offset 0x53
chunk name: IDAT
chunk size: 65524, offset 0x10004
chunk name: IDAT
chunk size: 65524, offset 0x20004
chunk name: IDAT
chunk size: 65524, offset 0x30004
chunk name: IDAT
chunk size: 65524, offset 0x40004
chunk name: IDAT
chunk size: 51084, offset 0x50004
number of chunks 10
————————————————————————————————————————————————————-
Parse Slice Header and Print Weighted Prediction Parameters, H.264
The weighted prediction was adopted by H.264/AVC. In some video sequences, in particular those containg fading between scenes, the current picture is more strongly correlated to a reference picture scaled by a weighting factor.
The python script PrintWeightsH264 gets as input H.264/AVC stream and parses SPS, PPS and slice headers. The script prints the weghted prediction information if it’s present in the slice header.
Usage:
-i input h264-file
-n number frames to process, if 0 then the whole stream processed, default 0
-v verbose mode, print SPS and PPS info (default false)
Example [encode 4 frames in verbose mode (i.e. printing SPS and PPS)]:
python PrintWeightsH264.py -i test.h264 -n 3 -v
SPS
profile_idc 100
level_idc 50
sps_id 0
log2_max_frame_num 4
log2_max_pic_order_cnt 10
max_num_ref_frames 1
gaps_in_frame_num_value_allowed_flag 0
pic_width_in_mbs 120
pic_width_in_mbs 68
frame_mbs_only_flag 1
direct_8x8_inference_flag 1
PPS
pps_id 0
sps_id 0
bottom_field_pic_order_in_frame_present_flag 0
num_ref_idx_l0 1
num_ref_idx_l1 1
weighted_pred_flag 1
weighted_bipred_idc 0
pic_init_qp 26
chroma_qp_index_offset 0
deblocking_filter_control_present_flag 0
constrained_intra_pred_flag 0
Frame 0
Slice
first_mb 0
slice type I
pps_id 0
frame_num 0
idr_idx 0
POC 0
Frame 1
Slice
first_mb 0
slice type P
pps_id 0
frame_num 1
POC 2
override flag 0
ref_pic_list_modification_flag_l0 0
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
luma_weight_l0_flag 1
luma_weight_l0 33
luma_offset_l0 -2
chroma_weight_l0_flag 0
Frame 2
Slice
first_mb 0
slice type P
pps_id 0
frame_num 2
POC 4
override flag 0
ref_pic_list_modification_flag_l0 0
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
luma_weight_l0_flag 0
chroma_weight_l0_flag 0
Frame 3
Slice
first_mb 0
slice type P
pps_id 0
frame_num 3
POC 6
override flag 0
ref_pic_list_modification_flag_l0 0
luma_log2_weight_denom 5
chroma_log2_weight_denom 5
luma_weight_l0_flag 0
chroma_weight_l0_flag 0
————————————————————————————————————————————————————-
Get PSNR, SSIM and VIFP (Visual Information Fidelity) with sewar package
The ‘sewar’ package contains different image and video quality metrics (PSNR,SSIM,MS-SSIM,VIFP etc.).
To install ‘sewar’ type: pip install sewar
The scripts GetPsnr.py , GetSSIM.py and GetVifp.py take as input reference and deformed yuv420p@8bpp video sequences and computes PSNR, SSIM and VIFP (Visual Information Fidelity) score per picture.
Usage:
-f reference yuv-sequence (yuv420p@8bpp)
-d deformed yuv-sequence (yuv420p@8bpp)
-n number of frames to process, if 0 then all frames, default 0
--width
width in pixels, must be even
--height
height in pixels, must be even
Example [ compute psnr values of first 10 frames]
python GetPsnr.py --width 1920 --height 1080 -f Fifa17_1920x1080.yuv -d fifa_hp_cbr16_10M.yuv -n 10
frame 0, psnr 30.53
frame 1, psnr 32.48
frame 2, psnr 33.20
frame 3, psnr 34.46
frame 4, psnr 33.86
frame 5, psnr 33.63
frame 6, psnr 33.35
frame 7, psnr 33.09
frame 8, psnr 32.88
frame 9, psnr 32.60
average psnr 33.01
Example [ compute SSIM values of first 10 frames]
python GetSsim.py --width 1920 --height 1080 -f Fifa17_1920x1080.yuv -d fifa_hp_cbr16_10M.yuv -n 10
frame 0, ssim 0.84
frame 1, ssim 0.87
frame 2, ssim 0.89
frame 3, ssim 0.91
frame 4, ssim 0.90
frame 5, ssim 0.90
frame 6, ssim 0.90
frame 7, ssim 0.90
frame 8, ssim 0.89
frame 9, ssim 0.89
average ssim 0.89
Example [ compute VIFP scores of first 10 frames]
python GetVifp.py --width 1920 --height 1080 -f Fifa17_1920x1080.yuv -d fifa_hp_cbr16_10M.yuv -n 10
frame 0, vifp 0.29
frame 1, vifp 0.36
frame 2, vifp 0.40
frame 3, vifp 0.44
frame 4, vifp 0.43
frame 5, vifp 0.43
frame 6, vifp 0.43
frame 7, vifp 0.42
frame 8, vifp 0.42
frame 9, vifp 0.41
average vifp 0.40
Note: to get (or to extract) yuv-sequence from encoded stream i use ffmpeg tool:
ffmpeg -i fifa_hp_cbr16_15M.h264 -pixel_format yuv420p -frames 100 -y fifa_hp_cbr16_15M.yuv
————————————————————————————————————————————————————-
Print NAL Headers of HEVC Elementary Stream
The python script GetHevcNalTypes.py takes input HEVC elementary stream and print NAL unit types and layer IDs (relevant for scalable streams).
If layerID (nuh_layer_id) is non-zero then NAL data belong to enchancement layer, if layerID=0 then the current NAL unit belongs to base layer.
Usage:
-i input hevc file
-n number of frames to process, if 0 then all, (default 0)
Example: dual SNR scalable stream
python GetHevcNalTypes.py -i dual_layer.h265
nal-type 32 VPS, layerId 0
nal-type 33 SPS, layerId 0
nal-type 33 SPS, layerId 1
nal-type 34 PPS, layerId 0
nal-type 19 IDR, layerId 0
nal-type 34 PPS, layerId 1
nal-type 19 IDR, layerId 1
nal-type 1 PB, layerId 0
nal-type 5 STSA, layerId 1
nal-type 1 PB, layerId 0
nal-type 5 STSA, layerId 1
nal-type 1 PB, layerId 0
nal-type 5 STSA, layerId 1
nal-type 1 PB, layerId 0
...
nal-type 5 STSA, layerId 1
nal-type 1 PB, layerId 0
nal-type 5 STSA, layerId 1
nal-type 1 PB, layerId 0
nal-type 5 STSA, layerId 1
nal-type 1 PB, layerId 0
nal-type 5 STSA, layerId 1
————————————————————————————————————————————————————-
Remove NALU with Given nal_unit_type from H264 Elementary Stream
There are situations when it’s required to remove NALU with a specific nal_unit_type (e.g. NALUs belonging to an enhanced layer in scalable h264).
The script RemoveNalTypeInH264Stream.py is tailored to remove NALUs with given nal_unit_type.
Usage:
RemoveNalTypeInH264Stream.py input.h264 nal_unit_type output.h264
Example [remove NALUs with user-defined nal_unit_type=0x1F (31 in decimal)]:
python RemoveNalTypeInH264Stream.py tomoishicheck.h264 31 out.h264
Nal units to remove 2223
23+ years’ programming and theoretical experience in the computer science fields such as video compression, media streaming and artificial intelligence (co-author of several papers and patents).
the author is looking for new job, my resume
certainly like your web site however you need to check the spelling on several of your posts. A number of them are rife with spelling issues and I find it very troublesome to inform the truth nevertheless I will certainly come again again.
Its like you read my mind! You appear to know so much about this, like you wrote the book in it or something. I think that you can do with some pics to drive the message home a little bit, but other than that, this is magnificent blog. An excellent read. I’ll definitely be back.
I have to express appreciation to this writer for rescuing me from this problem. Just after researching through the world-wide-web and obtaining recommendations that were not helpful, I thought my entire life was well over. Being alive devoid of the solutions to the problems you have fixed as a result of your entire report is a crucial case, as well as ones which might have adversely damaged my career if I had not encountered your blog. Your know-how and kindness in handling every item was very helpful. I’m not sure what I would have done if I had not discovered such a solution like this. I’m able to at this moment look ahead to my future. Thanks so much for your skilled and amazing guide. I will not think twice to propose your site to anyone who needs to have guide about this area.
It is really a nice and helpful piece of info. I am glad that you shared this helpful information with us. Please keep us up to date like this. Thank you for sharing.
Fantastic beat ! I wish to apprentice while you amend your site, how can i subscribe for a blog site? The account aided me a acceptable deal. I had been a little bit acquainted of this your broadcast provided bright clear idea
Hello.This article was really fascinating, especially since I was looking for thoughts on this topic last Tuesday.
It’s arduous to find educated individuals on this topic, however you sound like you recognize what you’re speaking about! Thanks
Good write-up, I am normal visitor of one?¦s website, maintain up the excellent operate, and It is going to be a regular visitor for a long time.
Great write-up, I¦m regular visitor of one¦s site, maintain up the nice operate, and It is going to be a regular visitor for a lengthy time.
I like this web blog very much, Its a very nice place to read and receive info .
Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.
I will right away grab your rss as I can’t find your email subscription link or e-newsletter service. Do you’ve any? Please let me know in order that I may just subscribe. Thanks.
I have been surfing online more than 3 hours today, yet I never found any interesting article like yours. It’s pretty worth enough for me. Personally, if all webmasters and bloggers made good content as you did, the net will be a lot more useful than ever before.
I like what you guys are up too. Such clever work and reporting! Carry on the excellent works guys I have incorporated you guys to my blogroll. I think it’ll improve the value of my site 🙂
hello!,I really like your writing very so much! share we keep up a correspondence more approximately your article on AOL? I require an expert in this space to resolve my problem. Maybe that is you! Having a look forward to look you.
obviously like your web site but you need to test the spelling on quite a few of your posts. A number of them are rife with spelling problems and I in finding it very troublesome to tell the reality nevertheless I will surely come again again.
Hi, i believe that i noticed you visited my website so i came to ?go back the choose?.I am attempting to to find things to improve my site!I assume its ok to use a few of your concepts!!
I am not sure where you’re getting your information, but great topic. I needs to spend some time learning much more or understanding more. Thanks for magnificent information I was looking for this information for my mission.
My brother recommended I might like this blog. He was entirely right. This post truly made my day. You cann’t imagine simply how much time I had spent for this info! Thanks!
I think other site proprietors should take this site as an model, very clean and fantastic user friendly style and design, as well as the content. You are an expert in this topic!
Great work! That is the kind of information that are supposed to be shared around the web. Disgrace on Google for now not positioning this publish upper! Come on over and talk over with my website . Thanks =)
Keep up the fantastic piece of work, I read few blog posts on this site and I conceive that your website is very interesting and has sets of good information.
Dear videonerd.website admin, Your posts are always well-referenced and credible.