aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java')
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java97
1 files changed, 75 insertions, 22 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java b/app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java
index d0b31671..0383c68a 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/tags/OggFile.java
@@ -23,10 +23,11 @@ import java.io.RandomAccessFile;
import java.util.HashMap;
-public class OggFile extends Common {
+public class OggFile extends Common implements PageInfo.PageParser {
- private static final int OGG_PAGE_SIZE = 27; // Static size of an OGG Page
- private static final int OGG_TYPE_COMMENT = 3; // ID of 'VorbisComment's
+ private static final int OGG_PAGE_SIZE = 27; // Static size of an OGG Page
+ private static final int OGG_TYPE_IDENTIFICATION = 1; // Identification header
+ private static final int OGG_TYPE_COMMENT = 3; // ID of 'VorbisComment's
public OggFile() {
}
@@ -34,24 +35,46 @@ public class OggFile extends Common {
public HashMap getTags(RandomAccessFile s) throws IOException {
long offset = 0;
int retry = 64;
+ boolean need_tags = true;
+ boolean need_id = true;
+
HashMap tags = new HashMap();
+ HashMap identification = new HashMap();
for( ; retry > 0 ; retry-- ) {
- long res[] = parse_ogg_page(s, offset);
- if(res[2] == OGG_TYPE_COMMENT) {
- tags = parse_ogg_vorbis_comment(s, offset+res[0], res[1]);
+ PageInfo pi = parse_stream_page(s, offset);
+ if(pi.type == OGG_TYPE_IDENTIFICATION) {
+ identification = parse_ogg_vorbis_identification(s, offset+pi.header_len, pi.payload_len);
+ need_id = false;
+ } else if(pi.type == OGG_TYPE_COMMENT) {
+ tags = parse_ogg_vorbis_comment(s, offset+pi.header_len, pi.payload_len);
+ need_tags = false;
+ }
+ offset += pi.header_len + pi.payload_len;
+ if (need_tags == false && need_id == false) {
break;
}
- offset += res[0] + res[1];
}
+
+ // Calculate duration in seconds
+ // Note that this calculation is WRONG: We would have to get the last
+ // packet to calculate the real length - but this is goot enough.
+ if (identification.containsKey("bitrate_nominal")) {
+ int br_nom = (Integer)identification.get("bitrate_nominal") / 8;
+ long file_length = s.length();
+ if (file_length > 0 && br_nom > 0) {
+ tags.put("duration", (int)(file_length/br_nom));
+ }
+ }
+
return tags;
}
- /* Parses the ogg page at offset 'offset' and returns
- ** [header_size, payload_size, type]
- */
- private long[] parse_ogg_page(RandomAccessFile s, long offset) throws IOException {
+ /**
+ * Parses the ogg page at offset 'offset'
+ */
+ public PageInfo parse_stream_page(RandomAccessFile s, long offset) throws IOException {
long[] result = new long[3]; // [header_size, payload_size]
byte[] p_header = new byte[OGG_PAGE_SIZE]; // buffer for the page header
byte[] scratch;
@@ -78,18 +101,18 @@ public class OggFile extends Common {
psize += b2u(scratch[i]);
}
}
-
- // populate result array
- result[0] = (s.getFilePointer() - offset);
- result[1] = psize;
- result[2] = -1;
-
+
+ PageInfo pi = new PageInfo();
+ pi.header_len = (s.getFilePointer() - offset);
+ pi.payload_len = psize;
+ pi.type = -1;
+
/* next byte is most likely the type -> pre-read */
if(psize >= 1 && s.read(p_header, 0, 1) == 1) {
- result[2] = b2u(p_header[0]);
+ pi.type = b2u(p_header[0]);
}
-
- return result;
+
+ return pi;
}
/* In 'vorbiscomment' field is prefixed with \3vorbis in OGG files
@@ -108,7 +131,37 @@ public class OggFile extends Common {
if( (new String(pfx, 0, pfx_len)).equals("\3vorbis") == false )
xdie("Damaged packet found!");
- return parse_vorbis_comment(s, offset+pfx_len, pl_len-pfx_len);
+ return parse_vorbis_comment(s, this, offset+pfx_len, pl_len-pfx_len);
}
-
+
+ /*
+ ** Returns a hashma with parsed vorbis identification header data
+ **/
+ private HashMap parse_ogg_vorbis_identification(RandomAccessFile s, long offset, long pl_len) throws IOException {
+ /* Structure:
+ * 7 bytes of \1vorbis
+ * 4 bytes version
+ * 1 byte channels
+ * 4 bytes sampling rate
+ * 4 bytes bitrate max
+ * 4 bytes bitrate nominal
+ * 4 bytes bitrate min
+ **/
+ HashMap id_hash = new HashMap();
+ byte[] buff = new byte[28];
+
+ if(pl_len >= buff.length) {
+ s.seek(offset);
+ s.read(buff);
+ id_hash.put("version" , b2le32(buff, 7));
+ id_hash.put("channels" , b2u(buff[11]));
+ id_hash.put("sampling_rate" , b2le32(buff, 12));
+ id_hash.put("bitrate_minimal" , b2le32(buff, 16));
+ id_hash.put("bitrate_nominal" , b2le32(buff, 20));
+ id_hash.put("bitrate_maximal" , b2le32(buff, 24));
+ }
+
+ return id_hash;
+ }
+
};