Package com.xuggle.xuggler

Source Code of com.xuggle.xuggler.Utils

/*******************************************************************************
* Copyright (c) 2008, 2010 Xuggle Inc.  All rights reserved.
* This file is part of Xuggle-Xuggler-Main.
*
* Xuggle-Xuggler-Main is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Xuggle-Xuggler-Main is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Xuggle-Xuggler-Main.  If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/

package com.xuggle.xuggler;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import com.xuggle.ferry.IBuffer;
import com.xuggle.ferry.JNIReference;
import com.xuggle.xuggler.Global;
import com.xuggle.xuggler.IAudioSamples;
import com.xuggle.xuggler.IVideoPicture;
import com.xuggle.xuggler.IPixelFormat;
import com.xuggle.xuggler.ITimeValue;
import com.xuggle.xuggler.video.IConverter;
import com.xuggle.xuggler.video.ConverterFactory;

import java.awt.image.BufferedImage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A collection of useful utilities for creating blank {@link IVideoPicture} objects
* and managing audio time stamp to sample conversions.
*
* @author aclarke
*
*/
public class Utils
{
  static private final Logger log = LoggerFactory.getLogger(Utils.class);
  static {
    log.trace("Utils loaded");
  }

  /**
   * Get a new blank frame object encoded in {@link IPixelFormat.Type#YUV420P} format.
   *
   * If crossHatchW and crossHatchH are greater than zero, then we'll draw a cross-hatch
   * pattern with boxes of those sizes alternating on the screen.  This can be useful to
   * spot coding and translation errors.  Word of warning though -- due to how the YUV420P
   * colorspace works, you'll need to make sure crossHatchW and crossHatchH are even numbers
   * to avoid unslightly u/v lines at box edges.
   *
   * @param w width of object
   * @param h height of object
   * @param yColor Y component of background color.
   * @param uColor U component of background color.
   * @param vColor V component of background color.
   * @param pts The time stamp, in microseconds, you want this frame to have, or {@link Global#NO_PTS} for none.
   * @param crossHatchW width of cross hatch on image, or <=0 for none
   * @param crossHatchH height of cross hatch on image, or <= 0 for none
   * @param crossHatchYColor Y component of cross-hatch color.
   * @param crossHatchUColor U component of cross-hatch color.
   * @param crossHatchVColor V component of cross-hatch color.
   * @return A new frame, or null if we can't create it.
   */
  public static IVideoPicture getBlankFrame(
      int w,
      int h,
      int yColor,
      int uColor,
      int vColor,
      long pts,
      int crossHatchW,
      int crossHatchH,
      int crossHatchYColor,
      int crossHatchUColor,
      int crossHatchVColor)
  {
    IVideoPicture frame = IVideoPicture.make(IPixelFormat.Type.YUV420P, w, h);
    if (frame == null)
      throw new OutOfMemoryError("could not allocate frame");
   
    if (frame != null)
    {
      AtomicReference<JNIReference> ref = new AtomicReference<JNIReference>(
          null);
      IBuffer data = null;
      try
      {
        data = frame.getData();
        int bufSize = frame.getSize();
        java.nio.ByteBuffer buffer = data.getByteBuffer(0, bufSize, ref);
        if (buffer != null)
        {
          // we have the raw data; now we set it to the specified YUV value.
          int lineLength = 0;
          int offset = 0;

          // first let's check the L
          offset = 0;
          lineLength = frame.getDataLineSize(0);
          int sliceLen = lineLength * h;
          for (int i = offset; i < offset + sliceLen; i++)
          {
            int x = (i - offset) % lineLength;
            int y = (i - offset) / lineLength;
            if (crossHatchH > 0
                && crossHatchW > 0
                && (((x / crossHatchW) % 2 == 1 && (y / crossHatchH) % 2 == 0) || ((x / crossHatchW) % 2 == 0 && (y / crossHatchH) % 2 == 1)))
              buffer.put(i, (byte) crossHatchYColor);
            else
              buffer.put(i, (byte) yColor);
          }

          // now, check the U value
          offset = (frame.getDataLineSize(0) * h);
          lineLength = frame.getDataLineSize(1);
          sliceLen = lineLength * ((h + 1) / 2);
          for (int i = offset; i < offset + sliceLen; i++)
          {
            if (crossHatchH > 0 && crossHatchW > 0)
            {
              // put x and y in bottom right of pixel range
              int x = ((i - offset) % lineLength) * 2;
              int y = ((i - offset) / lineLength) * 2;

              int[] xCoords = new int[]
              {
                  x, x + 1, x, x + 1
              };
              int[] yCoords = new int[]
              {
                  y, y, y + 1, y + 1
              };
              int finalColor = 0;
              for (int j = 0; j < xCoords.length; j++)
              {
                int color = uColor;
                x = xCoords[j];
                y = yCoords[j];
                if (((x / crossHatchW) % 2 == 1 && (y / crossHatchH) % 2 == 0)
                    || ((x / crossHatchW) % 2 == 0 && (y / crossHatchH) % 2 == 1))
                {
                  color = crossHatchUColor;
                }
                finalColor += color;
              }
              finalColor /= xCoords.length;
              buffer.put(i, (byte) finalColor);
            }
            else
              buffer.put(i, (byte) uColor);
          }

          // and finally the V
          offset = (frame.getDataLineSize(0) * h)
              + (frame.getDataLineSize(1) * ((h + 1) / 2));
          lineLength = frame.getDataLineSize(2);
          sliceLen = lineLength * ((h + 1) / 2);
          for (int i = offset; i < offset + sliceLen; i++)
          {
            if (crossHatchH > 0 && crossHatchW > 0)
            {
              // put x and y in bottom right of pixel range
              int x = ((i - offset) % lineLength) * 2;
              int y = ((i - offset) / lineLength) * 2;

              int[] xCoords = new int[]
              {
                  x, x + 1, x, x + 1
              };
              int[] yCoords = new int[]
              {
                  y, y, y + 1, y + 1
              };
              int finalColor = 0;
              for (int j = 0; j < xCoords.length; j++)
              {
                int color = vColor;
                x = xCoords[j];
                y = yCoords[j];
                if (((x / crossHatchW) % 2 == 1 && (y / crossHatchH) % 2 == 0)
                    || ((x / crossHatchW) % 2 == 0 && (y / crossHatchH) % 2 == 1))
                  color = crossHatchVColor;
                finalColor += color;
              }
              finalColor /= xCoords.length;
              buffer.put(i, (byte) finalColor);
            }
            else
              buffer.put(i, (byte) vColor);
          }
        }
        // set it complete
        frame.setComplete(true, IPixelFormat.Type.YUV420P, w, h, pts);
      }
      finally
      {
        if (data != null)
          data.delete();
        if (ref.get() != null)
          ref.get().delete();
      }

    }
    return frame;
  }
 
  /**
   * Get a new blank frame object encoded in {@link IPixelFormat.Type#YUV420P} format.
   *
   * @param w width of object
   * @param h height of object
   * @param y Y component of background color.
   * @param u U component of background color.
   * @param v V component of background color.
   * @param pts The time stamp, in microseconds, you want this frame to have, or {@link Global#NO_PTS} for none.
   * @return A new frame, or null if we can't create it.
   */
  public static IVideoPicture getBlankFrame(int w, int h, int y, int u, int v, long pts)
  {
    return getBlankFrame(w, h, y, u, v, pts, 0, 0, 0, 0, 0);
  }
 
  /**
   * Returns a blank frame with a green-screen background.
   *
   * @see #getBlankFrame(int, int, int, int, int, long)
   *
   * @param w width in pixels
   * @param h height in pixels
   * @param pts presentation timestamp (in {@link TimeUnit#MICROSECONDS} you want set
   * @return a new blank frame
   */
  public static IVideoPicture getBlankFrame(int w, int h, int pts)
  {
    return getBlankFrame(w, h, 0, 0, 0, pts);
  }

  /**
   * For a given sample rate, returns how long it would take to play a number of samples.
   * @param numSamples The number of samples you want to find the duration for
   * @param sampleRate The sample rate in Hz
   * @return The duration it would take to play numSamples of sampleRate audio
   */
  public static ITimeValue samplesToTimeValue(long numSamples, int sampleRate)
  {
    if (sampleRate <= 0)
      throw new IllegalArgumentException("sampleRate must be greater than zero");
   
    return ITimeValue.make(
        IAudioSamples.samplesToDefaultPts(numSamples, sampleRate),
        ITimeValue.Unit.MICROSECONDS);
  }
 
  /**
   * For a given time duration and sample rate, return the number of samples it would take to fill.
   * @param duration duration
   * @param sampleRate sample rate of audio
   * @return number of samples required to fill that duration
   */
  public static long timeValueToSamples(ITimeValue duration, int sampleRate)
  {
    if (duration == null)
      throw new IllegalArgumentException("must pass in a valid duration");
    if (sampleRate <= 0)
      throw new IllegalArgumentException("sampleRate must be greater than zero");
    return IAudioSamples.defaultPtsToSamples(duration.get(ITimeValue.Unit.MICROSECONDS), sampleRate);
  }
 
  /**
   * Convert an {@link IVideoPicture} to a {@link BufferedImage}.  The
   * input picture should be of type {@link IPixelFormat.Type#BGR24}
   * to avoid making unnecessary copies.
   *
   * The image data ultimately resides in java memory space, which
   * means the caller does not need to concern themselves with memory
   * management issues.
   *
   * @param picture The {@link IVideoPicture} to be converted.
   *
   * @return the resultant {@link BufferedImage} which will contain
   * the video frame.
   *
   * @throws IllegalArgumentException if the passed {@link
   * IVideoPicture} is NULL;
   * @throws IllegalArgumentException if the passed {@link
   * IVideoPicture} is not complete.
   *
   * @deprecated Image and picture conversion functionality has been
   * replaced by {@link com.xuggle.xuggler.video.ConverterFactory}.  The
   * current implementation of {@link #videoPictureToImage} creates a new
   * {@link com.xuggle.xuggler.video.IConverter} on each call, which is
   * not very efficient.
   */
 
  @Deprecated
    public static BufferedImage videoPictureToImage(IVideoPicture picture)
  {
    // if the pictre is NULL, throw up
   
    if (picture == null)
      throw new IllegalArgumentException("The video picture is NULL.");

    // create the converter

    IConverter converter = ConverterFactory.createConverter(
      ConverterFactory.XUGGLER_BGR_24, picture);

    // return the conveter

    return converter.toImage(picture);
  }
 
  /**
   * Convert a {@link BufferedImage} to an {@link IVideoPicture} of
   * type {@link IPixelFormat.Type#BGR24}.  The {@link BufferedImage} must be a
   * {@link BufferedImage#TYPE_3BYTE_BGR} type.
   *
   * @param image The source {@link BufferedImage}.
   * @param pts The presentation time stamp of the picture.
   *
   * @return An {@link IVideoPicture} in {@link
   * IPixelFormat.Type#BGR24} format.
   *
   * @throws IllegalArgumentException if the passed {@link
   * BufferedImage} is NULL;
   * @throws IllegalArgumentException if the passed {@link
   * BufferedImage} is not of type {@link BufferedImage#TYPE_3BYTE_BGR}.
   * @throws IllegalArgumentException if the underlying data buffer of
   * the {@link BufferedImage} is composed of types other bytes or
   * integers.
   *
   * @deprecated Image and picture conversion functionality has been
   * replaced by {@link com.xuggle.xuggler.video.ConverterFactory}.  The
   * current implementation of {@link #imageToVideoPicture} creates a new
   * {@link com.xuggle.xuggler.video.IConverter} on each call, which is
   * not very efficient.
   */
 
  @Deprecated
    public static IVideoPicture imageToVideoPicture(BufferedImage image, long pts)
  {
    // if the image is NULL, throw up
   
    if (image == null)
      throw new IllegalArgumentException("The image is NULL.");

    if (image.getType() != BufferedImage.TYPE_3BYTE_BGR)
      throw new IllegalArgumentException(
        "The image is of type #" + image.getType() +
        " but is required to be BufferedImage.TYPE_3BYTE_BGR of type #" +
        BufferedImage.TYPE_3BYTE_BGR + ".");

    // create the converter

    IConverter converter = ConverterFactory.createConverter(
      image, IPixelFormat.Type.BGR24);

    // return the converted picture

    return converter.toPicture(image, pts);
  }
}
TOP

Related Classes of com.xuggle.xuggler.Utils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.