|
24 | 24 |
|
25 | 25 | public class AvcCsdUtils { |
26 | 26 | // Refer: https://android.googlesource.com/platform/frameworks/av/+/lollipop-release/media/libstagefright/MediaCodec.cpp#2198 |
27 | | - private static final byte[] AVC_CSD_PREFIX = {0x00, 0x00, 0x00, 0x01}; |
| 27 | + // Refer: http://stackoverflow.com/a/2861340 |
| 28 | + private static final byte[] AVC_START_CODE_3 = {0x00, 0x00, 0x01}; |
| 29 | + private static final byte[] AVC_START_CODE_4 = {0x00, 0x00, 0x00, 0x01}; |
28 | 30 | // Refer: http://www.cardinalpeak.com/blog/the-h-264-sequence-parameter-set/ |
29 | 31 | private static final byte AVC_SPS_NAL = 103; // 0<<7 + 3<<5 + 7<<0 |
30 | 32 |
|
31 | 33 | public static ByteBuffer getSpsBuffer(MediaFormat format) { |
32 | 34 | ByteBuffer prefixedSpsBuffer = format.getByteBuffer(MediaFormatExtraConstants.KEY_AVC_SPS).asReadOnlyBuffer(); |
33 | | - byte[] csdPrefix = new byte[4]; |
34 | | - prefixedSpsBuffer.get(csdPrefix); |
35 | | - if (!Arrays.equals(csdPrefix, AVC_CSD_PREFIX)) { |
36 | | - throw new IllegalStateException("Wrong csd-0 prefix."); |
37 | | - } |
| 35 | + skipStartCode(prefixedSpsBuffer); |
38 | 36 | if (prefixedSpsBuffer.get() != AVC_SPS_NAL) { |
39 | 37 | throw new IllegalStateException("Got non SPS NAL data."); |
40 | 38 | } |
41 | 39 | return prefixedSpsBuffer.slice(); |
42 | 40 | } |
43 | 41 |
|
| 42 | + private static void skipStartCode(ByteBuffer prefixedSpsBuffer) { |
| 43 | + byte[] prefix3 = new byte[3]; |
| 44 | + prefixedSpsBuffer.get(prefix3); |
| 45 | + if (Arrays.equals(prefix3, AVC_START_CODE_3)) return; |
| 46 | + |
| 47 | + byte[] prefix4 = Arrays.copyOf(prefix3, 4); |
| 48 | + prefix4[3] = prefixedSpsBuffer.get(); |
| 49 | + if (Arrays.equals(prefix4, AVC_START_CODE_4)) return; |
| 50 | + throw new IllegalStateException("AVC NAL start code does not found in csd."); |
| 51 | + } |
| 52 | + |
44 | 53 | private AvcCsdUtils() { |
45 | 54 | throw new RuntimeException(); |
46 | 55 | } |
|
0 commit comments