private MP4Parser(final String path) throws IOException, FileNotFoundException { mFile = new RandomAccessFile(new File(path), "r"); try { parse("", mFile.length()); } catch (Exception e) { e.printStackTrace(); throw new IOException("Parse error: malformed mp4 file"); } }
private void parse(String path, long len) throws IOException { ByteBuffer byteBuffer; long sum = 0, newlen = 0; byte[] buffer = new byte[8]; String name = ""; if (!path.equals("")) mBoxes.put(path, mPos - 8); while (sum < len) { mFile.read(buffer, 0, 8); mPos += 8; sum += 8; if (validBoxName(buffer)) { name = new String(buffer, 4, 4); if (buffer[3] == 1) { // 64 bits atom size mFile.read(buffer, 0, 8); mPos += 8; sum += 8; byteBuffer = ByteBuffer.wrap(buffer, 0, 8); newlen = byteBuffer.getLong() - 16; } else { // 32 bits atom size byteBuffer = ByteBuffer.wrap(buffer, 0, 4); newlen = byteBuffer.getInt() - 8; } // 1061109559+8 correspond to "????" in ASCII the HTC Desire S seems to write that // sometimes, maybe other phones do // "wide" atom would produce a newlen == 0, and we shouldn't throw an exception because of // that if (newlen < 0 || newlen == 1061109559) throw new IOException(); Log.d(TAG, "Atom -> name: " + name + " position: " + mPos + ", length: " + newlen); sum += newlen; parse(path + '/' + name, newlen); } else { if (len < 8) { mFile.seek(mFile.getFilePointer() - 8 + len); sum += len - 8; } else { int skipped = mFile.skipBytes((int) (len - 8)); if (skipped < ((int) (len - 8))) { throw new IOException(); } mPos += len - 8; sum += len - 8; } } } }
/** * Finds sps & pps parameters inside a .mp4. * * @param path Path to the file to analyze * @throws IOException * @throws FileNotFoundException */ public MP4Config(String path) throws IOException, FileNotFoundException { StsdBox stsdBox; // We open the mp4 file mp4Parser = new MP4Parser(path); // We parse it try { mp4Parser.parse(); } catch (IOException ignore) { // Maybe enough of the file has been parsed and we can get the stsd box } // We find the stsdBox stsdBox = mp4Parser.getStsdBox(); mPPS = stsdBox.getB64PPS(); mSPS = stsdBox.getB64SPS(); mProfilLevel = stsdBox.getProfileLevel(); // We're done ! mp4Parser.close(); }