1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ogg; 17 18 import org.mozilla.thirdparty.com.google.android.exoplayer2.C; 19 import org.mozilla.thirdparty.com.google.android.exoplayer2.Format; 20 import org.mozilla.thirdparty.com.google.android.exoplayer2.util.MimeTypes; 21 import org.mozilla.thirdparty.com.google.android.exoplayer2.util.ParsableByteArray; 22 import java.nio.ByteBuffer; 23 import java.nio.ByteOrder; 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.List; 27 28 /** 29 * {@link StreamReader} to extract Opus data out of Ogg byte stream. 30 */ 31 /* package */ final class OpusReader extends StreamReader { 32 33 private static final int DEFAULT_SEEK_PRE_ROLL_SAMPLES = 3840; 34 35 /** 36 * Opus streams are always decoded at 48000 Hz. 37 */ 38 private static final int SAMPLE_RATE = 48000; 39 40 private static final int OPUS_CODE = 0x4f707573; 41 private static final byte[] OPUS_SIGNATURE = {'O', 'p', 'u', 's', 'H', 'e', 'a', 'd'}; 42 43 private boolean headerRead; 44 verifyBitstreamType(ParsableByteArray data)45 public static boolean verifyBitstreamType(ParsableByteArray data) { 46 if (data.bytesLeft() < OPUS_SIGNATURE.length) { 47 return false; 48 } 49 byte[] header = new byte[OPUS_SIGNATURE.length]; 50 data.readBytes(header, 0, OPUS_SIGNATURE.length); 51 return Arrays.equals(header, OPUS_SIGNATURE); 52 } 53 54 @Override reset(boolean headerData)55 protected void reset(boolean headerData) { 56 super.reset(headerData); 57 if (headerData) { 58 headerRead = false; 59 } 60 } 61 62 @Override preparePayload(ParsableByteArray packet)63 protected long preparePayload(ParsableByteArray packet) { 64 return convertTimeToGranule(getPacketDurationUs(packet.data)); 65 } 66 67 @Override readHeaders(ParsableByteArray packet, long position, SetupData setupData)68 protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) { 69 if (!headerRead) { 70 byte[] metadata = Arrays.copyOf(packet.data, packet.limit()); 71 int channelCount = metadata[9] & 0xFF; 72 int preskip = ((metadata[11] & 0xFF) << 8) | (metadata[10] & 0xFF); 73 74 List<byte[]> initializationData = new ArrayList<>(3); 75 initializationData.add(metadata); 76 putNativeOrderLong(initializationData, preskip); 77 putNativeOrderLong(initializationData, DEFAULT_SEEK_PRE_ROLL_SAMPLES); 78 79 setupData.format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_OPUS, null, 80 Format.NO_VALUE, Format.NO_VALUE, channelCount, SAMPLE_RATE, initializationData, null, 0, 81 null); 82 headerRead = true; 83 } else { 84 boolean headerPacket = packet.readInt() == OPUS_CODE; 85 packet.setPosition(0); 86 return headerPacket; 87 } 88 return true; 89 } 90 putNativeOrderLong(List<byte[]> initializationData, int samples)91 private void putNativeOrderLong(List<byte[]> initializationData, int samples) { 92 long ns = (samples * C.NANOS_PER_SECOND) / SAMPLE_RATE; 93 byte[] array = ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putLong(ns).array(); 94 initializationData.add(array); 95 } 96 97 /** 98 * Returns the duration of the given audio packet. 99 * 100 * @param packet Contains audio data. 101 * @return Returns the duration of the given audio packet. 102 */ getPacketDurationUs(byte[] packet)103 private long getPacketDurationUs(byte[] packet) { 104 int toc = packet[0] & 0xFF; 105 int frames; 106 switch (toc & 0x3) { 107 case 0: 108 frames = 1; 109 break; 110 case 1: 111 case 2: 112 frames = 2; 113 break; 114 default: 115 frames = packet[1] & 0x3F; 116 break; 117 } 118 119 int config = toc >> 3; 120 int length = config & 0x3; 121 if (config >= 16) { 122 length = 2500 << length; 123 } else if (config >= 12) { 124 length = 10000 << (length & 0x1); 125 } else if (length == 3) { 126 length = 60000; 127 } else { 128 length = 10000 << length; 129 } 130 return (long) frames * length; 131 } 132 } 133