Я пишу приложение для декодирования MP3
кадров. У меня возникли трудности с поиском заголовков.
Заголовок MP3
состоит из 32 бит и начинается с подписи: 11111111 111
.
Во внутреннем цикле ниже я ищу эту подпись. Когда эта подпись найдена, я извлекаю следующие два байта, а затем передаю последние три байта заголовка в пользовательский класс MpegFrame()
. Класс проверяет целостность заголовка и анализирует информацию из него. MpegFrame.isValid()
возвращает логическое значение, указывающее достоверность/целостность заголовка кадра. Если заголовок недействителен, внешний цикл выполняется снова, и подпись ищется снова.
При выполнении моей программы с CBR
MP3
найдены только некоторые кадры. Приложение сообщает о множестве недопустимых кадров.
Я считаю, что недопустимые кадры могут быть результатом пропуска битов. Заголовок имеет длину 4 байта. Когда заголовок определяется как недействительный, я пропускаю все 4 байта и начинаю искать подпись со следующих четырех байтов. В следующем случае: 11111111 11101101 11111111 11101001
подпись заголовка находится в первых двух байтах, однако третий байт содержит ошибку, которая делает заголовок недействительным. Если я пропущу все байты, потому что я определил, что заголовок, начинающийся с первого байта, недействителен, я пропущу потенциальный заголовок, начинающийся с третьего байта (поскольку третий и четвертый байты содержат подпись).
Я не могу искать в InputStream
назад, поэтому у меня следующий вопрос: Когда я определяю заголовок, начинающийся с байтов 1 и 2, как недопустимый, как мне запустить цикл поиска подписи, начинающийся с байта 2, а не с байта 5? ?
В приведенном ниже коде b
— это первый байт рассматриваемого возможного заголовка, b1
— второй байт, b2
— третий байт и b3
— четвертый байт.
int bytesRead = 0;
//10 bytes of Tagv2
int j = 0;
byte[] tagv2h = new byte[10];
j = fis.read(tagv2h);
bytesRead += j;
ByteBuffer bb = ByteBuffer.wrap(new byte[]{tagv2h[6], tagv2h[7],tagv2h[8], tagv2h[9]});
bb.order(ByteOrder.BIG_ENDIAN);
int tagSize = bb.getInt();
byte[] tagv2 = new byte[tagSize];
j = fis.read(tagv2);
bytesRead += j;
while (bytesRead < MPEG_FILE.length()) {
boolean foundHeader = false;
// Seek frame
int b = 0;
int b1 = 0;
while ((b = fis.read()) > -1) {
bytesRead++;
if (b == 255) {
b1 = fis.read();
if (b1 > -1) {
bytesRead++;
if (((b1 >> 5) & 0x7) == 0x7) {
System.out.println("Found header.");
foundHeader = true;
break;
}
}
}
}
if (!foundHeader) {
continue;
}
int b2 = fis.read();
int b3 = fis.read();
MpegFrame frame = new MpegFrame(b1, b2, b3, false);
if (!frame.isValid()) {
System.out.println("Invalid header @ " + (bytesRead-4));
continue;
}
}