Skip to content

Commit

Permalink
add yuv file
Browse files Browse the repository at this point in the history
  • Loading branch information
penndev committed Dec 15, 2024
1 parent 68f087e commit 3a6e7b5
Show file tree
Hide file tree
Showing 9 changed files with 370 additions and 80 deletions.
25 changes: 11 additions & 14 deletions Media/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,23 @@
- MPEG-TS 分析工具 https://www.easyice.cn/


**文档**
**编解码文档**

- https://www.itu.int/itu-t/recommendations/rec.aspx?rec=H.264
- https://www.itu.int/itu-t/recommendations/rec.aspx?rec=H.265
- **H264** https://www.itu.int/itu-t/recommendations/rec.aspx?rec=H.264
- **H265** https://www.itu.int/itu-t/recommendations/rec.aspx?rec=H.265


**名词说明**

- 时间冗余(帧间编码):物体存在运动规律,同一个场景存在大量的重复背景元素。
- 空间冗余(帧内编码):物体在图片上存在大量重复的元素。
- GOP(I->P->B-I):Gropu of Pictures 动起来的图片就是视频。
- 时间冗余(帧间编码)
- 运动预测 物体在影像展示中普遍符合物理运动规律,比如一个球在 $X_1$,$Y_1$ 运动到 $X_1$,$Y_5$ 的位置,我们可以只编码这个物体的运动距离即可。
- 当前帧与上一帧除了球的运动其他都没有变动,存在背景冗余。

- 空间冗余(帧内编码):物体在图片上存在大量重复的元素,比如一个黑色的正方形,大部分区域在颜色表达上基本一致。

- GOP (I->P->B-I):Group of Pictures 动起来的图片就是视频。
- Intra-coded picture 帧内编码图片。
- Predictive-coded Picture 预测编码图片。
- Bidirectionally predicted picture 双向预测图片。
- YCrCb: (Y-Luminance 亮度)(C Chrominance 色度)


- 色度采样率 4:2:0(j:a:b) 形容一个以J个像素宽及两个像素高的概念上区域
> 4:2:0 对数据压缩率为 8*(8*3) / 8*(8+4) 所以压缩率为一半。
- J:水平抽样引用(概念上区域的宽度)。通常为4。
- a:在J个像素第一行中的色度抽样数目(Cr, Cb)。
- b:在J个像素第二行中的额外色度抽样数目(Cr, Cb)。

176 144
288 changes: 288 additions & 0 deletions Media/docs/yuv.drawio

Large diffs are not rendered by default.

Binary file added Media/docs/yuv411.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Media/docs/yuv420.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Media/docs/yuv422.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Media/docs/yuv440.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Media/docs/yuv444.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 18 additions & 16 deletions Media/yuv.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,39 @@
- a:在J个像素第一行中的色度抽样数目(Cr, Cb)。
- b:在J个像素第二行中的额外色度抽样数目(Cr, Cb)。

##
## 色度采样

> 人的眼睛对色彩敏感度低于亮度敏感度
- 4:4:4
![yuv444](./docs/yuv444.jpg)

压缩字节流`24`个字节
字节流为`24`个字节`8`个像素各自展示自己颜色无压缩

- 4:4:0
![yuv444](./docs/yuv440.jpg)

YUV文件存储格式
```
Y0,U0,V0 Y1,U1,V1 Y2,U2,V2 Y3,U3,V3
Y4,U4,V4 Y5,U5,V5 Y6,U6,V6 Y7,U7,V7
```
字节流为`16`个字节

- 4:2:2
![yuv422](./docs/yuv422.jpg)

图像字节数为`12`个字节
YUV文件存储格式
```
Y0,U0 Y1,V0 Y2,U1 Y3 V1
```
字节流为`16`个字节

- 4:2:0
![yuv422](./docs/yuv420.jpg)

图像字节数为`10`个字节
图像字节数为`12`个字节

- 4:1:1
![yuv422](./docs/yuv411.jpg)

图像字节数为`10`个字节
图像字节数为`12`个字节

## 存储为文件

## YUV 文件格式
```
YUV文件=全部的Y数据+全部的U数据+全部的V数据
```
一帧图片存储为YUV分为三部分Y+U+V,根据采样率来自动进行匹配到固定的位置。
不知道是谁规定的YUV数据这样存储,还挺有意思的。
103 changes: 53 additions & 50 deletions _code/h26x/h264_slice_mb.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,53 +24,7 @@ def residual_block_cabac(self, coeffLevel, startIdx, endIdx, maxNumCoeff):

raise ("residual_block_cabac")

def residual_luma(self, i16x16DClevel, i16x16AClevel, level4x4, level8x8, startIdx, endIdx):
if startIdx == 0 and self.mb_type.MbPartPredMode == "Intra_16x16":
self.residual_block(i16x16DClevel, 0, 15, 16)
for i8x8 in range(4):
if not self.transform_size_8x8_flag or not pps.entropy_coding_mode_flag:
for i4x4 in range(4):
if self.CodedBlockPatternLuma & (1 << i8x8):
if self.mb_type.MbPartPredMode == "Intra_16x16":
self.residual_block(
i16x16AClevel[i8x8 * 4 + i4x4], max(0, startIdx - 1), endIdx - 1, 15)
else:
self.residual_block(
level4x4[i8x8 * 4 + i4x4], startIdx, endIdx, 16)
elif self.mb_type.MbPartPredMode == "Intra_16x16":
for i in range(15):
level4x4[i8x8 * 4 + i4x4][i] = 0
else:
for i in range(16):
level4x4[i8x8 * 4 + i4x4][i] = 0
if not pps.entropy_coding_mode_flag and self.transform_size_8x8_flag:
for i in range(16):
level8x8[i8x8][4 * i +
i4x4] = level4x4[i8x8 * 4 + i4x4][i]
elif self.CodedBlockPatternLuma & (1 << i8x8):
self.residual_block(
level8x8.get(i8x8), 4 * startIdx, 4 * endIdx + 3, 64)
else:
for i in range(64):
level8x8[i8x8][i] = 0
return i16x16DClevel, i16x16AClevel, level4x4, level8x8

def residual(self, startIdx, endIdx):
if pps.entropy_coding_mode_flag != 1:
raise ("residual_block_cavlc")
else:
self.residual_block = self.residual_block_cabac

Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel4x4, LumaLevel8x8 = self.residual_luma(
i16x16DClevel={},
i16x16AClevel={},
level4x4={},
level8x8={},
startIdx=startIdx,
endIdx=endIdx
)
print(Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel4x4, LumaLevel8x8)
exit("i am here ready finish")


def __init__(self, bs: BitStream, slice: SliceData):
'''
Expand Down Expand Up @@ -106,9 +60,7 @@ def __init__(self, bs: BitStream, slice: SliceData):
self.transform_size_8x8_flag = bs.transform_size_8x8_flag()
if self.CodedBlockPatternLuma > 0 or self.CodedBlockPatternChroma > 0 or self.mb_type.MbPartPredMode == "Intra_16x16":
self.mb_qp_delta = bs.mb_qp_delta(slice)
# self.residual(0, 15)
print("I am here..")
exit('1')
self.residual(0, 15)

def mb_pred(self, bs: BitStream, slice: SliceData):
if self.mb_type.MbPartPredMode in ("Intra_4x4", "Intra_8x8", "Intra_16x16"):
Expand All @@ -135,3 +87,54 @@ def mb_pred(self, bs: BitStream, slice: SliceData):
elif self.mb_type.MbPartPredMode != "Direct":
raise ("self.mb_type.MbPartPredMode != Direct")

def residual_block_cavlc(self, coeffLevel, startIdx, endIdx, maxNumCoeff, bs:BitStream, slice:SliceData):


def residual(self, startIdx, endIdx, bs:BitStream, slice:SliceData):
if bs.pps.entropy_coding_mode_flag != 1:
self.residual_block = self.residual_block_cavlc
else:
self.residual_block = self.residual_block_cabac

Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel4x4, LumaLevel8x8 = self.residual_luma(
i16x16DClevel={},
i16x16AClevel={},
level4x4={},
level8x8={},
startIdx=startIdx,
endIdx=endIdx
)
print(Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel4x4, LumaLevel8x8)
exit("i am here ready finish")

def residual_luma(self, i16x16DClevel, i16x16AClevel, level4x4, level8x8, startIdx, endIdx, bs:BitStream, slice:SliceData):
if startIdx == 0 and self.mb_type.MbPartPredMode == "Intra_16x16":
self.residual_block(i16x16DClevel, 0, 15, 16)
for i8x8 in range(4):
if not self.transform_size_8x8_flag or not bs.pps.entropy_coding_mode_flag:
for i4x4 in range(4):
if self.CodedBlockPatternLuma & (1 << i8x8):
if self.mb_type.MbPartPredMode == "Intra_16x16":
self.residual_block(
i16x16AClevel[i8x8 * 4 + i4x4], max(0, startIdx - 1), endIdx - 1, 15)
else:
self.residual_block(
level4x4[i8x8 * 4 + i4x4], startIdx, endIdx, 16)
elif self.mb_type.MbPartPredMode == "Intra_16x16":
for i in range(15):
level4x4[i8x8 * 4 + i4x4][i] = 0
else:
for i in range(16):
level4x4[i8x8 * 4 + i4x4][i] = 0
if not bs.pps.entropy_coding_mode_flag and self.transform_size_8x8_flag:
for i in range(16):
level8x8[i8x8][4 * i +
i4x4] = level4x4[i8x8 * 4 + i4x4][i]
elif self.CodedBlockPatternLuma & (1 << i8x8):
self.residual_block(
level8x8.get(i8x8), 4 * startIdx, 4 * endIdx + 3, 64)
else:
for i in range(64):
level8x8[i8x8][i] = 0
return i16x16DClevel, i16x16AClevel, level4x4, level8x8

0 comments on commit 3a6e7b5

Please sign in to comment.