|
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