【问题标题】:Parsing hevc bitstream解析 hevc 比特流
【发布时间】:2014-07-18 14:05:17
【问题描述】:

有没有办法解析 HEVC 比特流文件?

我希望能够创建一个新的比特流文件,其中包含从原始比特流文件中选择的最终单元数据包。

编辑:我插入了我的代码。请找到我的比特流文件here

#library for searching in a string
import re

#library to keep dictionary order
import collections
import bitstring
from bitstring import BitStream, BitArray, ConstBitStream, pack
from bitstring import ByteStore, offsetcopy

#read bitstream file
s = BitStream(filename='11LTCCA_560x416_50Hz_8b_P420_GOP8_IP48_200frms_QP28.HEVC.str')

#find no of packets
pcks = list(s.findall('0x000001', bytealigned=True))

print len(pcks)

#set the current position, in the beginning of the nal unit.
s.pos =pcks[0]-8
print s.pos

#find the number of bits of first nal packet
no_p = pcks[1]-pcks[0]


forbidden_zero_bit = s.read(1)
nal_unit_type = s.read('uint:6')

# go to the beginning of the second nal unit
s.read(no_p)
# print nal unit type of the 1st packet
print nal_unit_type

no_p = pcks[2]-pcks[1]
s.pos = pcks[1]-8
print s.pos
forbidden_zero_bit = s.read(1)
nal_unit_type = s.read('uint:6')
s.read(no_p)
print nal_unit_type

【问题讨论】:

    标签: hevc bitstream h.265


    【解决方案1】:

    如果你只想取一些最终的单元数据包(例如,取决于层 id 和时间 id),并且你不需要修改 VPS、SPS、PPS、Slice Header 等,那么你也可以自己轻松实现:

    HEVC standard的附件B“字节流格式”中说明了相应的语法。

    简而言之:

    1. 在比特流文件中搜索模式 0x000001,它将所有最终单元分开。此外,如果下一个最终单元是访问单元的第一个最终单元(访问单元 = 用于解码整个帧的所有最终单元),则此模式之前可以有一个 0x00 字节。

    2. 根据HEVC standard 的第 7.3.1.2 节读取最终单元标题,并根据您想要的任何标准保留/删除最终单元。确保保留参数集(根据HEVC standard 的表 7-1 的最终单元类型 32、33 和 34)。

    3. 将所有最终单元组装到一个新文件中,并确保中间始终包含 0x000001 序列。

    我曾经使用 Python 做过类似的事情,效果很好。如果您想更轻松地阅读最终单元标题,请使用bitstring module。如果您想这样做并有更详细的问题,可以私信我寻求帮助。

    编辑: 关于您发布的代码: 为什么在BitStream对象(s.pos =pcks[0]-8s.pos = pcks[1]-8)中分配位置时要加上“-8”?这应该是 +24(24 位 = 3 字节 = 最终单元分隔符的长度 0x000001),以便在分隔符之后开始读取以获取最终单元。但是,在读取数据时必须考虑到这一点:no_p = pcks[1]-pcks[0] 应该是 no_p = pcks[1]-pcks[0]-24,因为您在 nal 单位分隔符之后开始读取。

    如果您对找到的第一个位置 (pcks[0]) 是 8 而不是 0 感到困惑:根据HEVC standard 的附件 B,在每个最终单元分隔符之前,可以有任意数量的零字节.通常,每个访问单元之前总是有一个零字节。

    【讨论】:

    • 非常感谢!我也将使用 Python 开发它。我会尽快尝试,如果有任何问题,我会私信你!
    • 你能帮我解析一下吗?我需要更多帮助来阅读标题。 find() 方法在比特流中并没有真正起作用...本站不支持 pm...
    • 我假设你打开了字节流,它位于一个名为“data”的变量中,并且你有一个最终单元开头的位置“pos”。那么“data[pos]”将是最终单元标头的第一个字节,“data[pos+1]”将是最终单元标头的第二个字节。然后,您可以使用“ord(data[pos]) & int(0b01111110)”获取最终单元类型,并使用“ord(data[pos+1]) & int(0b00000111)”获取时间 id。 layer id 会有点困难,因为它在两个字节中都有位。
    • 谢谢!使用 & 你的意思是 '+' 字符?有没有办法遍历字节流并读取顺序的最终类型单元?
    • 使用 & 我的意思是 '&' 字符 ;) 这是一个位运算符。让我更详细地解释一下:NAL 单元标头的第一位必须始终为零,并且不携带任何信息。接下来的 6 位以无符号整数的形式构成最终单元类型,因此如果最终单元标头的第一个字节是例如0b01000011,你的最终单位类型是 0b100001 = 33 (2^5+2^0),你可以使用上面描述的按位运算得到这个数字。我忘记了一件事:你必须对整个事情进行位移才能获得正确的结果。所以只需执行 "(ord(data[pos]) & int(0b01111110))>>1"。
    【解决方案2】:

    你可以试试 GStreamer。他们有一个用于解析 H.265/HEVC 的插件。只是该插件还是相当新的,所以我不确定它现在有多稳定。

    您可以获取更多详情here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多