Forráskód Böngészése

added audio properties parsing

Mark VandenBrink 12 éve
szülő
commit
452ea9a0b8
2 módosított fájl, 65 hozzáadás és 12 törlés
  1. 62 11
      mp4-atom.lisp
  2. 3 1
      taglib-tests.lisp

+ 62 - 11
mp4-atom.lisp

@@ -324,8 +324,63 @@ Loop through this container and construct constituent atoms"
 	(setf lang     (stream-read-u16 mp4-file))
 	(setf quality  (stream-read-u16 mp4-file))))
 
+(defclass atom-esds (mp4-atom)
+  ((version      :accessor version)      ; 1 byte
+   (flags        :accessor flags)		 ; 3 bytes
+   (esid         :accessor esid)		 ; 2 bytes
+   (s-priority   :accessor s-priority) 	 ; 1 byte
+   (obj-id		 :accessor obj-id)		 ; 1 byte
+   (s-type       :accessor s-type)       ; 1 byte (1 bit up-stream, 1-but reservered, 6-bits stream type
+   (buf-size     :accessor buf-size)     ; 3 bytes
+   (max-bit-rate :accessor max-bit-rate) ; 4 bytes
+   (avg-bit-rate :accessor avg-bit-rate) ; 4 bytes
+   (dc-len       :accessor dc-len)       ; 2 bytes
+   (dc           :accessor dc)           ; 1 byte
+   (slc-len      :accessor slc-len)      ; 1 byte
+   (slc          :accessor slc))         ; 1 byte
+  (:documentation "XXX-partial definition for Elementary Stream DescriptorS"))
+
+
+(defmacro while (test &body body)
+  `(do ()
+       ((not ,test))
+     ,@body))
+
+(defun read-descriptor-len (instream)
+  "Get the ES descriptor's length."
+  (let* ((tmp (stream-read-u8 instream))
+		 (len (logand tmp #x7f)))
+	(declare (type (unsigned-byte 8) tmp))
+	(while (not (zerop (logand #x80 tmp)))
+	  (setf tmp (stream-read-u8 instream))
+	  (setf len (logior (ash len 7) (logand tmp #x7f))))
+	len))
+
+(defmethod initialize-instance :after ((me atom-esds) &key (mp4-file nil) &allow-other-keys)
+  (with-slots (version flags esid s-priority obj-id s-type buf-size max-bit-rate avg-bit-rate) me
+	(setf version  (stream-read-u8 mp4-file))
+	(setf flags    (stream-read-u24 mp4-file))
+	(assert (= 3 (stream-read-u8 mp4-file)) () "Expected a description tag of 3")
+	(let* ((len1 (read-descriptor-len mp4-file))
+		   (end-of-atom (+ (stream-seek mp4-file 0 :current) len1))
+		   (len2 0))
+	  (declare (ignore len2)) ; XXX for now...
+	  (setf esid (stream-read-u16 mp4-file))
+	  (setf s-priority (stream-read-u8 mp4-file))
+	  ;; XXX should do some range checking here against LEN1...
+	  (assert (= 4 (stream-read-u8 mp4-file)) () "Expected tag type of 4")
+	  (setf len2 (read-descriptor-len mp4-file))
+	  (setf obj-id (stream-read-u8 mp4-file))
+	  (setf s-type (stream-read-u8 mp4-file))
+	  (setf buf-size (stream-read-u24 mp4-file))
+	  (setf max-bit-rate (stream-read-u32 mp4-file))
+	  (setf avg-bit-rate (stream-read-u32 mp4-file))
+	  ;; XXX should do checking here on LEN2 and/or read rest of atom,
+	  ;; but for now, we have what we want, so just seek to end of atom
+	  (stream-seek mp4-file end-of-atom :start))))
+
 (defclass atom-stsd (mp4-atom)
-  ((flags       :accessor flags)
+  ((flags        :accessor flags)
    (version     :accessor version)
    (num-entries :accessor num-entries)))
 
@@ -547,20 +602,16 @@ return trak.mdia.mdhd and trak.mdia.minf.stbl.stsd"
 (defun get-audio-properties (mp4-file)
   (let ((time))
 	(multiple-value-bind (mdhd mp4a esds) (get-audio-properties-atoms mp4-file)
-	  (progn
-		(format t "mdhd: ~a~%" (vpprint mdhd nil))
-		(format t "mp4a: ~a~%" (vpprint mp4a nil))
-		(format t "esds: ~a~%" (vpprint esds nil))
-		(when mdhd
-		  (setf time (/ (float (duration mdhd)) (float (scale mdhd))))
-		  (format t "~a seconds~%" time))
+	  (when mdhd
+		(setf time (/ (float (duration mdhd)) (float (scale mdhd))))
+		(format t "~a seconds~%" time))
 		(when mp4a
-		  (inspect mp4a)
 		  (format t "channels: ~d~%" (num-chans mp4a))
-		  (format t "bite/sample: ~:d~%" (samp-size mp4a))
+		  (format t "bits/sample: ~:d~%" (samp-size mp4a))
 		  (let* ((upper (ash (samp-rate mp4a) -16))
 				 (lower (logand (samp-rate mp4a) #xffff))
 				 (rate (+ (float upper) (/ (float lower) 1000))))
 		  (format t "sample rate: ~:d~%" rate)))
 		(when esds
-		  (format t "XXX~%"))))))
+		  (format t "average bit-rate = ~:d, max bit-rate = ~:d~%"
+				  (avg-bit-rate esds) (max-bit-rate esds))))))

+ 3 - 1
taglib-tests.lisp

@@ -51,7 +51,9 @@
   (osicat:walk-directory dir (lambda (f)
 							   (when (has-extension f "m4a")
 								 (let ((file (mp4-test0 f)))
-								   (when file (mp4-tag:show-tags file :raw raw)))))))
+								   (when file 
+									 (mp4-tag:show-tags file :raw raw)
+									 (mp4-atom::get-audio-properties file)))))))
 
 ;;;;;;;;;;;;;;;;;;;; MP3 Tests ;;;;;;;;;;;;;;;;;;;;
 (defun mp3-test0 (file)