Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: pixels from component



Hi,

I recently wrote a small sample sample program which takes a Quicktime movie
and uses OpenGL to render it. The code is based on examples that have
been posted in this forum, and else where. You can find the project
here:


http://www.geocities.com/ajmas/MovieinOpenGL.zip

or just the essential class here attached.

André-John Mas


/* *********************************************************** */ import java.awt.*; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.Buffer; import java.nio.IntBuffer;

import quicktime.QTSession;
import quicktime.io.OpenMovieFile;
import quicktime.io.QTFile;
import quicktime.qd.QDGraphics;
import quicktime.std.StdQTConstants;
import quicktime.std.image.CodecComponent;
import quicktime.std.image.DSequence;
import quicktime.std.image.ImageDescription;
import quicktime.std.movies.Movie;
import quicktime.std.movies.TimeInfo;
import quicktime.std.movies.Track;
import quicktime.std.movies.media.Media;
import quicktime.std.movies.media.MediaSample;
import quicktime.util.RawEncodedImage;

/**
* Class to play a Quicktime movie and to allow to get each frame.
*
* Heavily based on th QTSnapper source code, from the "Playing Movies
* in a Java 3D World, Part 2" article at O'Reilly:
*
* http://www.onjava.com/pub/a/onjava/2005/06/01/kgpjava_part2.html
*
* @author Andre-John Mas
*
*/
public class QTMoviePlayer {

  private boolean isSessionOpen = false;

  private OpenMovieFile movieFile;

  private Movie movie;

  private Track videoTrack;

  private Media vidMedia;

  private MediaSample mediaSample; // current sample/frame

  private int rowInts; // no. of ints in each row of a frame

  private int numSamples; // number of samples in the movie

  private int sampIdx; // current sample index

  private QDGraphics qdGraphics; // off-screen drawing surface

  private DSequence dSeq; // decompressed image sequence

  private int width; // frame width

  private int height; // frame height

  private int[]      pixelData;
  private IntBuffer  pixelBuffer;

  private long numFramesMade;

  public QTMoviePlayer(String fileName) throws IOException {
    File file = new File(fileName);
    if (!file.exists()) {
      throw new FileNotFoundException("could not find " + fileName);
    }
    try {
      // open a QuickTime session
      QTSession.open();
      isSessionOpen = true;

      // open the movie
      movieFile = OpenMovieFile.asRead(new QTFile(fileName));
      movie = Movie.fromFile(movieFile);

// extrack the video track from the movie
videoTrack = movie.getIndTrackType(1, StdQTConstants.videoMediaType,
StdQTConstants.movieTrackMediaType);
if (videoTrack == null) {
System.out.println("Sorry, not a video");
System.exit(0);
}


      // get the media data struct. used by the video track
      vidMedia = videoTrack.getMedia();
      numSamples = vidMedia.getSampleCount();

      sampIdx = 1; // get the first sample in the track
      mediaSample = vidMedia.getSample(0, vidMedia
          .sampleNumToMediaTime(sampIdx).time, 1);

// store the width and height of the image in the media sample
ImageDescription imgDesc = (ImageDescription) mediaSample.description;
width = imgDesc.getWidth();
height = imgDesc.getHeight();


// set up a drawing environment for coverting future frame images
qdGraphics = new QDGraphics(imgDesc.getBounds());
dSeq = new DSequence(imgDesc, qdGraphics, imgDesc.getBounds(), null,
null, StdQTConstants.codecFlagUseImageBuffer,
StdQTConstants.codecLosslessQuality, CodecComponent.bestFidelityCodec);
// the sample will be decompressed into qdGraphics


      // divide by four to get number of 32-bit ints.
      rowInts = qdGraphics.getPixMap().getRowBytes()/4;

      width = rowInts;

      int bufferSize = rowInts*height;
      pixelData = new int[bufferSize];
      pixelBuffer = IntBuffer.wrap(pixelData);

      numFramesMade = 0;
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }

  }

  public void start() {
    //Not implemented - does nothing
  }

/**
* stopMovie() and getFrame() are synchronized so that it's not possible to
* terminate the QuickTime session while a frame is being copied from the
* movie.
*/
synchronized public void stop() {
if (isSessionOpen) {
QTSession.close();
isSessionOpen = false;
}
}



public int getWidth() { return width; }


public int getHeight() { return height; }


/** Not implemented */ public Image getNextFrameImage() { throw new RuntimeException("Not Implemented"); }


/**
* Return a single sample (a frame) from the movie as a BufferedImage object.
*
* The frame is the next one in the movie, which is counted off using sampIdx
* (which goes 1 to numSamples, then repeats).
*
* This coding differs from getFrame() in JMFSnapper in that JMFSnapper gets
* the current frame from a running movie, while this method always gets the
* next frame from the movie.
*
* The current time is written on top of the image when it's converted to a
* BufferedImage.
*/
public Buffer getNextFrame() {
if (!isSessionOpen)
return null;


    if (sampIdx > numSamples) // start back with the first sample
      sampIdx = 1;

    try {
      // get the sample starting at the specified index time

      TimeInfo ti = vidMedia.sampleNumToMediaTime(sampIdx);
      mediaSample = vidMedia.getSample(0, ti.time, 1);

      sampIdx++;

      writeToBufferedImage(mediaSample);
      numFramesMade++; // count another frame generated
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return pixelBuffer;
  }


/**
* Write the contents of the sample into the BufferedImage
*
* The data passes through many stages. The basic steps are to get a 'raw'
* image from the current media sample (frame), then write it as a pixel array
* into the DataBuffer part of the BufferedImage.
*/
private void writeToBufferedImage(MediaSample mediaSample)
throws Exception
{
// extract the raw image from the sample
RawEncodedImage rawIm = RawEncodedImage.fromQTHandle (mediaSample.data);
dSeq.decompressFrameS(rawIm, 0);
rawIm.disposeQTObject();


// pull a raw image from qdGraphics (this one will be decompressed)
RawEncodedImage rawIm2 = qdGraphics.getPixMap().getPixelData();
rawIm2.copyToArray(0, pixelData, 0, pixelData.length);
pixelBuffer.rewind();


    rawIm2.disposeQTObject();
  }

}

_______________________________________________
Do not post admin requests to the list. They will be ignored.
QuickTime-java mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quicktime-java/email@hidden

This email sent to email@hidden
References: 
 >pixels from component (From: robert huber <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.