H264编解码使用Videotoolbox
H264 encoding and decoding using Videotoolbox
我正在使用 videotoolbox 测试编码和解码,将捕获的帧转换为 H264 并使用该数据在 AVSampleBufferdisplayLayer 中显示它。
解压缩 CMVideoFormatDescriptionCreateFromH264ParameterSets 时出现错误,错误代码为 -12712
我关注this code from mobisoftinfotech.com
status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
kCFAlloc atorDefault, 2,
(const uint8_t const)parameterSetPointers,
parameterSetSizes, 4, &_formatDesc);
视频压缩测试;谁能解决问题?
我不确定你是否找到了问题所在。但是,我在您的代码中发现了 2 个导致错误的地方。在修复它们并 运行 在本地测试应用程序后,它似乎工作正常。 (使用 Xcode 9.4.1、MacOS 10.13 测试)
第一个在-(void)CompressAndConvertToData:(CMSampleBufferRef)sampleBuffer
方法中while循环应该是这样的
while (bufferOffset < blockBufferLength - AVCCHeaderLength) {
// Read the NAL unit length
uint32_t NALUnitLength = 0;
memcpy(&NALUnitLength, bufferDataPointer + bufferOffset, AVCCHeaderLength);
// Convert the length value from Big-endian to Little-endian
NALUnitLength = CFSwapInt32BigToHost(NALUnitLength);
// Write start code to the elementary stream
[elementaryStream appendBytes:startCode length:startCodeLength];
// Write the NAL unit without the AVCC length header to the elementary stream
[elementaryStream appendBytes:bufferDataPointer + bufferOffset + AVCCHeaderLength
length:NALUnitLength];
// Move to the next NAL unit in the block buffer
bufferOffset += AVCCHeaderLength + NALUnitLength;
}
uint8_t *bytes = (uint8_t*)[elementaryStream bytes];
int size = (int)[elementaryStream length];
[self receivedRawVideoFrame:bytes withSize:size];
第二位是你处理NALU type 8的解压代码,if(nalu_type == 8)
语句中的代码块。这是一个棘手的问题。
要修复它,请更新
for (int i = _spsSize + 12; i < _spsSize + 50; i++)
至
for (int i = _spsSize + 12; i < _spsSize + 12 + 50; i++)
并且您可以自由删除此 hack
//was crashing here
if(_ppsSize == 0)
_ppsSize = 4;
为什么?让我们打印出帧数据包格式。
po frame
▿ 4282 elements
- 0 : 0
- 1 : 0
- 2 : 0
- 3 : 1
- 4 : 39
- 5 : 100
- 6 : 0
- 7 : 30
- 8 : 172
- 9 : 86
- 10 : 193
- 11 : 112
- 12 : 247
- 13 : 151
- 14 : 64
- 15 : 0
- 16 : 0
- 17 : 0
- 18 : 1
- 19 : 40
- 20 : 238
- 21 : 60
- 22 : 176
- 23 : 0
- 24 : 0
- 25 : 0
- 26 : 1
- 27 : 6
- 28 : 5
- 29 : 35
- 30 : 71
- 31 : 86
- 32 : 74
- 33 : 220
- 34 : 92
- 35 : 76
- 36 : 67
- 37 : 63
- 38 : 148
- 39 : 239
- 40 : 197
- 41 : 17
- 42 : 60
- 43 : 209
- 44 : 67
- 45 : 168
- 46 : 0
- 47 : 0
- 48 : 3
- 49 : 0
- 50 : 0
- 51 : 3
- 52 : 0
- 53 : 2
- 54 : 143
- 55 : 92
- 56 : 40
- 57 : 1
- 58 : 221
- 59 : 204
- 60 : 204
- 61 : 221
- 62 : 2
- 63 : 0
- 64 : 76
- 65 : 75
- 66 : 64
- 67 : 128
- 68 : 0
- 69 : 0
- 70 : 0
- 71 : 1
- 72 : 37
- 73 : 184
- 74 : 32
- 75 : 1
- 76 : 223
- 77 : 205
- 78 : 248
- 79 : 30
- 80 : 231
… more
第一个NALU起始码if (nalu_type == 7)
是从索引15到18的0,0,0,1。接下来的0,0,0,1(从23到26)是类型6,类型8 NALU 起始代码是从 68 到 71。这就是为什么我稍微修改 for 循环以从起始索引 (_spsSize + 12) 开始扫描,范围为 50.
我尚未完全测试您的代码以确保编码和解码按预期正常工作。但是,我希望这个发现对您有所帮助。
顺便说一句,如果有什么误会,希望大家多多指教。
我正在使用 videotoolbox 测试编码和解码,将捕获的帧转换为 H264 并使用该数据在 AVSampleBufferdisplayLayer 中显示它。
解压缩 CMVideoFormatDescriptionCreateFromH264ParameterSets 时出现错误,错误代码为 -12712
我关注this code from mobisoftinfotech.com
status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
kCFAlloc atorDefault, 2,
(const uint8_t const)parameterSetPointers,
parameterSetSizes, 4, &_formatDesc);
视频压缩测试;谁能解决问题?
我不确定你是否找到了问题所在。但是,我在您的代码中发现了 2 个导致错误的地方。在修复它们并 运行 在本地测试应用程序后,它似乎工作正常。 (使用 Xcode 9.4.1、MacOS 10.13 测试)
第一个在-(void)CompressAndConvertToData:(CMSampleBufferRef)sampleBuffer
方法中while循环应该是这样的
while (bufferOffset < blockBufferLength - AVCCHeaderLength) {
// Read the NAL unit length
uint32_t NALUnitLength = 0;
memcpy(&NALUnitLength, bufferDataPointer + bufferOffset, AVCCHeaderLength);
// Convert the length value from Big-endian to Little-endian
NALUnitLength = CFSwapInt32BigToHost(NALUnitLength);
// Write start code to the elementary stream
[elementaryStream appendBytes:startCode length:startCodeLength];
// Write the NAL unit without the AVCC length header to the elementary stream
[elementaryStream appendBytes:bufferDataPointer + bufferOffset + AVCCHeaderLength
length:NALUnitLength];
// Move to the next NAL unit in the block buffer
bufferOffset += AVCCHeaderLength + NALUnitLength;
}
uint8_t *bytes = (uint8_t*)[elementaryStream bytes];
int size = (int)[elementaryStream length];
[self receivedRawVideoFrame:bytes withSize:size];
第二位是你处理NALU type 8的解压代码,if(nalu_type == 8)
语句中的代码块。这是一个棘手的问题。
要修复它,请更新
for (int i = _spsSize + 12; i < _spsSize + 50; i++)
至
for (int i = _spsSize + 12; i < _spsSize + 12 + 50; i++)
并且您可以自由删除此 hack
//was crashing here
if(_ppsSize == 0)
_ppsSize = 4;
为什么?让我们打印出帧数据包格式。
po frame
▿ 4282 elements
- 0 : 0
- 1 : 0
- 2 : 0
- 3 : 1
- 4 : 39
- 5 : 100
- 6 : 0
- 7 : 30
- 8 : 172
- 9 : 86
- 10 : 193
- 11 : 112
- 12 : 247
- 13 : 151
- 14 : 64
- 15 : 0
- 16 : 0
- 17 : 0
- 18 : 1
- 19 : 40
- 20 : 238
- 21 : 60
- 22 : 176
- 23 : 0
- 24 : 0
- 25 : 0
- 26 : 1
- 27 : 6
- 28 : 5
- 29 : 35
- 30 : 71
- 31 : 86
- 32 : 74
- 33 : 220
- 34 : 92
- 35 : 76
- 36 : 67
- 37 : 63
- 38 : 148
- 39 : 239
- 40 : 197
- 41 : 17
- 42 : 60
- 43 : 209
- 44 : 67
- 45 : 168
- 46 : 0
- 47 : 0
- 48 : 3
- 49 : 0
- 50 : 0
- 51 : 3
- 52 : 0
- 53 : 2
- 54 : 143
- 55 : 92
- 56 : 40
- 57 : 1
- 58 : 221
- 59 : 204
- 60 : 204
- 61 : 221
- 62 : 2
- 63 : 0
- 64 : 76
- 65 : 75
- 66 : 64
- 67 : 128
- 68 : 0
- 69 : 0
- 70 : 0
- 71 : 1
- 72 : 37
- 73 : 184
- 74 : 32
- 75 : 1
- 76 : 223
- 77 : 205
- 78 : 248
- 79 : 30
- 80 : 231
… more
第一个NALU起始码if (nalu_type == 7)
是从索引15到18的0,0,0,1。接下来的0,0,0,1(从23到26)是类型6,类型8 NALU 起始代码是从 68 到 71。这就是为什么我稍微修改 for 循环以从起始索引 (_spsSize + 12) 开始扫描,范围为 50.
我尚未完全测试您的代码以确保编码和解码按预期正常工作。但是,我希望这个发现对您有所帮助。 顺便说一句,如果有什么误会,希望大家多多指教。