001/*******************************************************************************
002 * Copyright (c) 2024, 2026, Olivier Ayache.  All rights reserved.
003 *
004 * This file is part of AVPKit.
005 *
006 * AVPKit is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU Lesser General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * AVPKit is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with AVPKit.  If not, see <http://www.gnu.org/licenses/>.
018 *******************************************************************************/
019
020package com.avpkit.mediatool.demos;
021import java.awt.Rectangle;
022import java.awt.Robot;
023import java.awt.Toolkit;
024import java.awt.image.BufferedImage;
025import java.util.concurrent.TimeUnit;
026
027import com.avpkit.mediatool.ToolFactory;
028import com.avpkit.mediatool.IMediaWriter;
029import com.avpkit.core.IRational;
030
031/**
032 * Using {@link IMediaWriter}, takes snapshots of your desktop and
033 * encodes them to video.
034 * 
035 * @author aclarke
036 * 
037 */
038
039public class CaptureScreenToFile
040{
041  private static IRational FRAME_RATE=IRational.make(3,1);
042  private static final int SECONDS_TO_RUN_FOR = 15;
043  
044  /**
045   * Takes a screen shot of your entire screen and writes it to
046   * output.flv
047   * 
048   * @param args
049   */
050  public static void main(String[] args)
051  {
052    try
053    {
054      final String outFile;
055      if (args.length > 0)
056        outFile = args[0];
057      else
058        outFile = "output.mp4";
059      // This is the robot for taking a snapshot of the
060      // screen.  It's part of Java AWT
061      final Robot robot = new Robot();
062      final Toolkit toolkit = Toolkit.getDefaultToolkit();
063      final Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
064      
065      // First, let's make a IMediaWriter to write the file.
066      final IMediaWriter writer = ToolFactory.makeWriter(outFile);
067      
068      // We tell it we're going to add one video stream, with id 0,
069      // at position 0, and that it will have a fixed frame rate of
070      // FRAME_RATE.
071      writer.addVideoStream(0, 0,
072          FRAME_RATE,
073          screenBounds.width, screenBounds.height);
074      
075      // Now, we're going to loop
076      long startTime = System.nanoTime();
077      for (int index = 0; index < SECONDS_TO_RUN_FOR*FRAME_RATE.getDouble(); index++)
078      {
079        // take the screen shot
080        BufferedImage screen = robot.createScreenCapture(screenBounds);
081        
082        // convert to the right image type
083        BufferedImage bgrScreen = convertToType(screen,
084            BufferedImage.TYPE_3BYTE_BGR);
085        
086        // encode the image
087        writer.encodeVideo(0,bgrScreen,
088            System.nanoTime()-startTime, TimeUnit.NANOSECONDS);
089
090        System.out.println("encoded image: " +index);
091        
092        // sleep for framerate milliseconds
093        Thread.sleep((long) (1000 / FRAME_RATE.getDouble()));
094
095      }
096      // Finally we tell the writer to close and write the trailer if
097      // needed
098      writer.close();
099    }
100    catch (Throwable e)
101    {
102      System.err.println("an error occurred: " + e.getMessage());
103    }
104  }
105  /**
106   * Convert a {@link BufferedImage} of any type, to {@link BufferedImage} of a
107   * specified type. If the source image is the same type as the target type,
108   * then original image is returned, otherwise new image of the correct type is
109   * created and the content of the source image is copied into the new image.
110   * 
111   * @param sourceImage
112   *          the image to be converted
113   * @param targetType
114   *          the desired BufferedImage type
115   * 
116   * @return a BufferedImage of the specifed target type.
117   * 
118   * @see BufferedImage
119   */
120
121  public static BufferedImage convertToType(BufferedImage sourceImage,
122      int targetType)
123  {
124    BufferedImage image;
125
126    // if the source image is already the target type, return the source image
127
128    if (sourceImage.getType() == targetType)
129      image = sourceImage;
130
131    // otherwise create a new image of the target type and draw the new
132    // image
133
134    else
135    {
136      image = new BufferedImage(sourceImage.getWidth(),
137          sourceImage.getHeight(), targetType);
138      image.getGraphics().drawImage(sourceImage, 0, 0, null);
139    }
140
141    return image;
142  }
143
144}