anchor.diff:  (defmethod stream-playback-stop ((rec stream-record))
     (bt:release-lock (vacancy-lock (car (rcursor rec)))))
   
  -(defclass mjpeg-stream-record (stream-record)
  -  ((jpeg-descriptor :accessor jpeg-descriptor :initform (cl-jpeg::make-descriptor))))
  +(defclass video-stream-record (stream-record)
  +  ())
   
  -(defmethod shared-initialize :after ((rec mjpeg-stream-record) slots &key &allow-other-keys)
  -  (declare (ignorable slots))
  -  (flexi-streams:with-input-from-sequence (is +avi-dht+)
  -    (setf (jpeg::descriptor-byte-reader (jpeg-descriptor rec)) #'(lambda () (read-byte is)))
  -    (jpeg:read-dht (jpeg-descriptor rec)))
  -  (setf (buffer rec) (make-array (suggested-buffer-size rec) :element-type '(unsigned-byte 8))
  -	(jpeg:descriptor-source-cache (jpeg-descriptor rec)) (buffer rec))
  -  (initialize-ring rec (max 5 (* 1 (floor (rate rec) (scale rec)))) ;at least 5 chunks to prevent cursor deadlocks
  -		   (* (height (avi rec)) (width (avi rec)) 3) 'cl-jpeg::uint8))
  -
  -(defclass audio-stream-record (stream-record)
  -  ((compression-code :accessor compression-code)
  -   (number-of-channels :accessor number-of-channels)
  -   (sample-rate :accessor sample-rate)
  -   (average-bytes-per-second :accessor average-bytes-per-second)
  -   (block-align :accessor block-align)
  -   (significant-bits-per-sample :accessor significant-bits-per-sample)
  -   (extra-format-bytes :accessor extra-format-bytes)
  -   (extra-bytes :accessor extra-bytes)))
  -
  -(defmethod shared-initialize :after ((rec audio-stream-record) slots &key &allow-other-keys)
  -  (declare (ignorable slots))
  -  (setf  (buffer rec) (make-array (suggested-buffer-size rec) :element-type '(unsigned-byte 8))))
  -
  -(defmethod read-audio-stream-header ((rec audio-stream-record) stream)
  -  (loop for chunk = (riff:read-riff-chunk stream)
  -     when (string-equal (riff:riff-chunk-id chunk) "strf") do
  -       (flexi-streams:with-input-from-sequence (is (riff:riff-chunk-data chunk))
  -	(setf (compression-code rec) (riff:read-u2 is)
  -	     (number-of-channels rec) (riff:read-u2 is)
  -	     (sample-rate rec) (riff:read-u4 is)
  -	     (average-bytes-per-second rec) (riff:read-u4 is)
  -	     (block-align rec) (riff:read-u2 is)
  -	     (significant-bits-per-sample rec) (riff:read-u2 is))
  -	(debug-log (format nil "Audio stream with sample rate ~D at ~D bits per sample" (sample-rate rec) (significant-bits-per-sample rec)))
  -       (unless (eql (compression-code rec) +pcmi-uncompressed+)
  -	 (setf (extra-format-bytes rec) (riff:read-u2 is)
  -	       (extra-bytes rec) (make-array (extra-format-bytes rec) :element-type (stream-element-type is)))
  -	 (read-sequence (extra-bytes rec) is)))
  -       (return)))
  -
  -(defclass video-stream ()
  -  ((filename :accessor filename :initarg :filename :initform nil)))
  -
  -(defclass avi-mjpeg-stream (video-stream)
  -  ((chunk-decoder :accessor chunk-decoder)
  +(defclass av-container ()
  +  ((filename :accessor filename :initarg :filename :initform nil)
  +   (player-callback :accessor player-callback :initarg :player-callback :initform nil) ;;called once all headers are processed
      (width :accessor width :initarg :width :initform 640)
      (height :accessor height :initarg :height :initform 480)
  -   (padding :accessor padding :initform 0)
  -   (flags :accessor flags)
  -   (nstreams :accessor nstreams)
  -   (player-callback :accessor player-callback :initarg :player-callback :initform nil) ;;called once all headers are processed
      (stream-records :accessor stream-records)
      (finish :accessor finish :initform nil)
      (pause :accessor pause :initform nil)
  
positive.code: (defgeneric decode-media-stream (record fsize input-stream))
  
  (defmethod decode-media-stream ((rec stream-record) fsize input-stream)
    (read-sequence (frame (car (wcursor rec))) input-stream :end fsize))
  
  (defmethod decode-media-stream ((rec audio-stream-record) fsize input-stream)
    (let* ((chunk (pop (wcursor rec)))
  	 (cur-lock (vacancy-lock chunk))
  	 (new-chunk (car (wcursor rec))))
      (bt:acquire-lock (vacancy-lock new-chunk))
      (read-sequence (frame chunk) input-stream :end fsize)
      (bt:release-lock cur-lock)))
  
  (defmethod decode-media-stream ((rec mjpeg-stream-record) fsize input-stream)
    (let* ((chunk (pop (wcursor rec)))
  	 (cur-lock (vacancy-lock chunk))
  	 (new-chunk (car (wcursor rec))))
      (bt:acquire-lock (vacancy-lock new-chunk))
      (read-sequence (jpeg:descriptor-source-cache (jpeg-descriptor rec)) input-stream :end fsize)
      (jpeg:decode-stream nil :buffer (frame chunk)
  			:descriptor (jpeg-descriptor rec)
  			:cached-source-p t)
      (bt:release-lock cur-lock)))
  
  (defmethod initialize-instance :after ((s avi-mjpeg-stream) &key &allow-other-keys)
    (setf (chunk-decoder s) #'(lambda (stream id size)
  			      (if (member (subseq id 2) '("dc" "wb") :test #'string-equal)
  				  (progn (decode-media-stream (elt (stream-records s) (parse-integer (subseq id 0 2))) size stream)
  					 (when (plusp (padding s)) (loop repeat (rem size (padding s)) do (read-byte s))))
  				  (read-sequence (make-array size :element-type '(unsigned-byte 8)) stream)))))
  
  (defgeneric decode (stream)
    (:documentation "Decodes the video stream"))
  
  (defmethod read-avi-stream-info ((avi avi-mjpeg-stream) stream)
    (loop for chunk = (riff:read-riff-chunk stream)
       with rec = (make-instance 'stream-record :avi avi)
       when (string-equal (riff:riff-chunk-id chunk) "strh") do
         (flexi-streams:with-input-from-sequence (is (riff:riff-chunk-data chunk))
  	 (setf (fcc-type rec) (riff::read-fourcc is)
  	       (fcc-handler rec) (riff::read-fourcc is)
  	       (flags rec) (riff:read-u4 is)
  	       (priority rec) (riff:read-u2 is)
  	       (language rec) (riff:read-u2 is)
  	       (initial-frames rec) (riff:read-u4 is)
  	       (scale rec) (riff:read-u4 is)
  	       (rate rec) (riff:read-u4 is)
  	       (start rec) (riff:read-u4 is)
  	       (stream-length rec) (riff:read-u4 is)
  	       (suggested-buffer-size rec) (riff:read-u4 is)
  	       (quality rec) (riff:read-u4 is)
  	       (sample-size rec) (riff:read-u4 is)
  	       (frame rec) (list (riff:read-u2 is) (riff:read-u2 is) (riff:read-u2 is) (riff:read-u2 is))))
         (when (and (string-equal (fcc-type rec) "vids") (not (member (fcc-handler rec) '("mjpg") :test #'string-equal)))
  	 (error 'unsupported-avi-file-format))
         (cond ((and (string-equal (fcc-type rec) "vids") (string-equal (fcc-handler rec) "mjpg"))
  	      (change-class rec 'mjpeg-stream-record))
  	     ((string-equal (fcc-type rec) "auds") (change-class rec 'audio-stream-record) (read-audio-stream-header rec stream)))
         (return-from read-avi-stream-info rec))
    (error 'malformed-avi-file-format))
  
  (defmethod read-avi-header ((avi avi-mjpeg-stream) stream)
    (loop for chunk = (riff:read-riff-chunk stream)
       when (string-equal (riff:riff-chunk-id chunk) "avih") do
         (flexi-streams:with-input-from-sequence (is (riff:riff-chunk-data chunk))
  	 (riff:read-u4 is)   ;;dwMicroSecPerFrame
  	 (riff:read-u4 is)   ;;dwMaxBytesPerSec
  	 (setf (padding avi) (riff:read-u4 is)
  	       (flags avi) (riff:read-u4 is))
  	 (unless (zerop (logand (flags avi) +avif-must-use-index+))
  	   (debug-log (format nil "CL-VIDEO WARNING: must use index flag is set, frame order is possibly incorrect~%")))
  	 (riff:read-u4 is)   ;;dwTotalFrames
  	 (riff:read-u4 is)   ;;dwInitialFrames
  	 (setf (nstreams avi) (riff:read-u4 is))
  	 (riff:read-u4 is) ;;dwSuggestedBufferSize
  	 (setf (width avi) (riff:read-u4 is)
  	       (height avi) (riff:read-u4 is))
  	 (riff:read-u4 is) (riff:read-u4 is) (riff:read-u4 is) (riff:read-u4 is))
         (setf (stream-records avi)
  	     (loop repeat (nstreams avi) collecting (read-avi-stream-info avi stream)))
         (return)))
  
  (defmethod find-mjpeg-stream-record ((avi avi-mjpeg-stream))
    (find-if #'(lambda (x) (eql (type-of x) 'mjpeg-stream-record)) (stream-records avi)))
  
  (defmethod find-pcm-stream-record ((avi avi-mjpeg-stream))
    (find-if #'(lambda (x) (and (eql (type-of x) 'audio-stream-record)
  			      (eql (compression-code x) +pcmi-uncompressed+))) (stream-records avi)))
  
  (defmethod prime-all-streams ((avi avi-mjpeg-stream))
    ;; the playback shouldn't start before 1st frame is decoded
    (loop for rec in (stream-records avi) do
         (bt:acquire-lock (vacancy-lock (car (wcursor rec))))))
  
  
  (defmethod decode ((avi avi-mjpeg-stream))
    (with-open-file (stream (filename avi) :direction :input :element-type '(unsigned-byte 8))
      ;; read AVI header first
      (let* ((chunk (riff:read-riff-chunk stream))
  	   (id (getf chunk :chunk-id))
  	   (fourcc (getf chunk :file-type)))
        (unless (string-equal id "riff")
  	(error 'unrecognized-file-format))
        (cond ((string-equal fourcc "avi ") (read-avi-header avi stream))
  	    (t (error 'unsupported-avi-file-format))))
      (when (player-callback avi)
        (funcall (player-callback avi) avi))
      (loop for chunk = (riff:read-riff-chunk stream :chunk-data-reader (chunk-decoder avi))
         while (and chunk (not (finish avi))))
      (loop for rec in (stream-records avi) do 
  	 (setf (final rec) (car (wcursor rec)))
  	 (bt:release-lock (vacancy-lock (car (wcursor rec)))))))
  
  (defun decode-file (pathname &key player-callback)
    (let ((avi-stream (make-instance 'avi-mjpeg-stream :filename pathname :player-callback player-callback)))
      (decode avi-stream)))
  
  (defun show-file-chunks (pathname)
    (with-open-file (stream pathname :direction :input :element-type '(unsigned-byte 8))
      (loop for chunk = (riff:read-riff-chunk stream)
  	 while chunk do (format t "~A size ~D~%" (riff:riff-chunk-id chunk) (riff:riff-chunk-data-size chunk)))))
  
negative.code:   ()
    (:report (lambda (condition stream)
  	     (declare (ignorable condition))
  	     (format stream "Unrecognized file format"))))
  
  (defclass chunk ()
    ((lock :reader vacancy-lock :initform (bt:make-lock "vacancy"))
     (frame :accessor frame :initarg :frame)))
  
  (defclass stream-record ()
    ((chunk-queue :accessor chunk-queue)
     (rcursor :accessor rcursor)
     (wcursor :accessor wcursor)
     (final :accessor final :initform nil)
     (buffer :accessor buffer :type '(unsigned-byte 8))
     (container :accessor container :initarg :container)))
  
  (defmethod initialize-ring ((rec stream-record) ring-length frame-size element-type)
    (setf (chunk-queue rec) (make-list ring-length))
  