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