c++ FFMPEG错误:解码H.265流时“帧中的第一片缺失”

i34xakig  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(185)

我在使用ffmpeg库解码IP摄像头流(h.265)时遇到问题。
我使用Live 555接收RTP负载。

mMediaSession->readSource()->getNextFrame(mVideoBuffer.data(),
mVideoBuffer.size(), Stream::Static_PayloadRead, this, Stream::Static_StreamClose, this);

前两个字节(在开始代码0001之后)具有nal_unit_header。我正在从1-6位((NALU[0] >> 1)& 0x 3F)中检索类型。然后我根据NALU类型处理数据:

enum NalUnitType  
{  
  NAL_UNIT_CODED_SLICE_TRAIL_N = 0,   // 0  
  NAL_UNIT_CODED_SLICE_TRAIL_R,   // 1    
  NAL_UNIT_CODED_SLICE_TSA_N,     // 2  
  NAL_UNIT_CODED_SLICE_TLA,       // 3    
  NAL_UNIT_CODED_SLICE_STSA_N,    // 4  
  NAL_UNIT_CODED_SLICE_STSA_R,    // 5    
  NAL_UNIT_CODED_SLICE_RADL_N,    // 6  
  NAL_UNIT_CODED_SLICE_DLP,       // 7     
  NAL_UNIT_CODED_SLICE_RASL_N,    // 8  
  NAL_UNIT_CODED_SLICE_TFD,       // 9   
  NAL_UNIT_RESERVED_10,  
...
  NAL_UNIT_CODED_SLICE_BLA,       // 16 
  NAL_UNIT_CODED_SLICE_BLANT,     // 17    
  NAL_UNIT_CODED_SLICE_BLA_N_LP,  // 18  
  NAL_UNIT_CODED_SLICE_IDR,       // 19  // Current name in the spec: IDR_W_DLP  
  NAL_UNIT_CODED_SLICE_IDR_N_LP,  // 20  
  NAL_UNIT_CODED_SLICE_CRA,       // 21  
  NAL_UNIT_RESERVED_22,  
 ...
  NAL_UNIT_VPS,                   // 32  
  NAL_UNIT_SPS,                   // 33  
  NAL_UNIT_PPS,                   // 34  
  NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35  
  NAL_UNIT_EOS,                   // 36  
  NAL_UNIT_EOB,                   // 37  
  NAL_UNIT_FILLER_DATA,           // 38  
  NAL_UNIT_SEI,                   // 39 Prefix SEI  
  NAL_UNIT_SEI_SUFFIX,            // 40 Suffix SEI  
...
  NAL_UNIT_INVALID,  
};

如果buffer没有开始代码,我会在发送到FFmpeg之前,在有效载荷数据的开始处添加0x 00000001。相机正在发送这些NALU(以相同的顺序):

  1. HEVC_NAL_VPS,
  2. HEVC_NAL_SPS,
  3. HEVC_NAL_PPS,
  4. HEVC_NAL_IDR_W_RADL,
  5. HEVC_NAL_IDR_W_RADL,
  6. HEVC_NAL_IDR_W_RADL,
  7. HEVC_NAL_TRAIL_R,
  8. HEVC_NAL_TRAIL_R.
    我的解决方案部分工作,因为我有1/3的图像解码。其他2个HEVC_NAL_IDR_W_RADL切片得到FFmpeg错误:“帧中的第一个切片丢失”。如果我降低流分辨率,则我具有1/2图像和一个附加HEVC_NAL_IDR_W_RADL切片。
    类似的代码与H.264流一起工作,所以我知道(我希望)Live 555和FFmpeg代码应该没问题。
    Live 555不会重新组装I帧(http://lists.live555.com/pipermail/live-devel/2016-September/020244.html
    是否有一种特定的方法来重新组装多个切片中发送的帧。我甚至尝试组装帧,因为它将是分段单元NAL类型49(How to depacketize the fragmented frames in RTP data (over UDP) for H265/HEVC?
    非常感谢
b09cbbtk

b09cbbtk1#

它的确定只是缝合在一起。下面描述的解决方案适用于我与FFmpeg + Live555。
对于I切片,我执行以下操作:

0x00 0x00 0x00 0x01 
VPS
0x00 0x00 0x01
SPS
0x00 0x00 0x01
PPS
0x00 0x00 0x01
I-Slice #0
0x00 0x00 0x01
I-Slice #1
....
0x00 0x00 0x01
I-Slice #last

对于非I切片:

0x00 0x00 0x00 0x01 
non-I-Slice #0
0x00 0x00 0x01
non-I-Slice #1
....
0x00 0x00 0x01
non-I-Slice #last

要知道切片是否是其帧的第一个切片,您可以检查NALU[2] & 0x80,它应该仅在初始切片中为非零。Live555保证给予切片正确的顺序。因此,当你遇到一个开始新帧的切片时,只需将之前拼接的切片馈送到FFmpeg HEVC解码器并开始拼接一个新帧。

  • PS:* 它也适用于其他视频处理API,如英特尔的MediaSDK。尽管说大多数编解码器应该能够消耗单独的NAL单元,而不是整个帧,我没有设法使它运行的方式既不FFmpeg也不英特尔。但所描述的解决方案对他们两个都很有效。尽管如此,我认为可能有一个标志的地方或一种方法,使他们与不同的NALU工作。这将是伟大的,如果有人可以提供信息,如果这是可能的,以及如何使它的工作,如果是的。
  • PPS:* 它的工作方式与H264相同,但我们应该检查NALU[1] & 0x80

相关问题