Saturday, May 11, 2013

Frames Capture and Video Creation Using Xuggler

The concept is to open the media file, loop through a specific video stream and at specific intervals capture the corresponding frame, convert it to an image and dump the binary contents into a file. Here is what the code for all these looks like:

package com.javacodegeeks.xuggler;




import java.awt.image.BufferedImage;

import java.io.File;


import java.io.IOException;




import javax.imageio.ImageIO;




import com.xuggle.mediatool.IMediaReader;

import com.xuggle.mediatool.MediaListenerAdapter;


import com.xuggle.mediatool.ToolFactory;

import com.xuggle.mediatool.event.IVideoPictureEvent;


import com.xuggle.xuggler.Global;




public class VideoThumbnailsExample {

     


    public static final double SECONDS_BETWEEN_FRAMES = 10;




    private static final String inputFilename = "c:/Java_is_Everywhere.mp4";

    private static final String outputFilePrefix = "c:/snapshots/mysnapshot";


     

    // The video stream index, used to ensure we display frames from one and


    // only one video stream from the media container.

    private static int mVideoStreamIndex = -1;


     

    // Time of last frame write


    private static long mLastPtsWrite = Global.NO_PTS;

     


    public static final long MICRO_SECONDS_BETWEEN_FRAMES =

        (long)(Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES);




   public static void main(String[] args) {




        IMediaReader mediaReader = ToolFactory.makeReader(inputFilename);




        // stipulate that we want BufferedImages created in BGR 24bit color space


        mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);

         


        mediaReader.addListener(new ImageSnapListener());




        // read out the contents of the media file and

        // dispatch events to the attached listener


        while (mediaReader.readPacket() == null) ;




    }




    private static class ImageSnapListener extends MediaListenerAdapter {




        public void onVideoPicture(IVideoPictureEvent event) {




            if (event.getStreamIndex() != mVideoStreamIndex) {

                // if the selected video stream id is not yet set, go ahead an


                // select this lucky video stream

               if (mVideoStreamIndex == -1)


                    mVideoStreamIndex = event.getStreamIndex();

                // no need to show frames from this video stream


                else

                    return;


            }




            // if uninitialized, back date mLastPtsWrite to get the very first frame

            if (mLastPtsWrite == Global.NO_PTS)


                mLastPtsWrite = event.getTimeStamp() - MICRO_SECONDS_BETWEEN_FRAMES;




            // if it's time to write the next frame

            if (event.getTimeStamp() - mLastPtsWrite >=


                    MICRO_SECONDS_BETWEEN_FRAMES) {

                                 


                String outputFilename = dumpImageToFile(event.getImage());




                // indicate file written

                double seconds = ((double) event.getTimeStamp()) /


                    Global.DEFAULT_PTS_PER_SECOND;

                System.out.printf(


                       "at elapsed time of %6.3f seconds wrote: %s\n",

                        seconds, outputFilename);




                // update last write time


                mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES;

            }




        }


         

        private String dumpImageToFile(BufferedImage image) {


            try {

                String outputFilename = outputFilePrefix +


                     System.currentTimeMillis() + ".png";

               ImageIO.write(image, "png", new File(outputFilename));


               return outputFilename;

            }


            catch (IOException e) {

                e.printStackTrace();


                return null;

            }


        }




    }




}
This might seem a bit overwhelming, but it is really quite straightforward. Let me provide some details for you. We start by creating anIMediaReader from an input file. The media reader is used to read and decode media. Since we wish to manipulate the captures video frames as images, we use the setBufferedImageTypeToGenerate method to denote this. The reader opens up a media container, reads packets from it, decodes the data, and then dispatches information about the data to any registered IMediaListener objects. Here is where our custom class, ImageSnapListener, comes into play.

Our listener extends the 
MediaListenerAdapter, which is an adapter (provides empty methods) implementing the IMediaListener interface. Objects that implement this interface are notified about events generated during the video processing. We only care about handling video events, thus we only implement the IMediaListener.onVideoPicture method. Inside that we use the provided IVideoPictureEvent object to find what stream (video only) we are dealing with.

Since we wish to capture frames in specific times, we have to mess a little with timestamps. First, we make sure we handle the very first frame by checking against the value of the 
Global.NO_PTS constant, which is a value that means no time stamp is set for a given object. Then, if the minimum elapsed time has passes, we capture the frame by invoking the IVideoPictureEvent.getImage method, which returns the underlying BufferedImage. Note that we are talking about elapsed video time and not “real time”. We then dump the image data to a file in PNG format using the ImageIO.write utility method. Finally, we update the last write time.

Let’s run this application in order to see the results. As input file, I am using an old Sun commercial proclaiming that “
Java is Everywhere”. I have downloaded locally the MP4 version provided. Here is what the output console will look like:

at elapsed time of 0.000 seconds wrote: c:/snapshots/mysnapshot1298228503292.png
at elapsed time of 10.010 seconds wrote: c:/snapshots/mysnapshot1298228504014.png
at elapsed time of 20.020 seconds wrote: c:/snapshots/mysnapshot1298228504463.png
…
at elapsed time of 130.063 seconds wrote: c:/snapshots/mysnapshot1298228509454.png
at elapsed time of 140.007 seconds wrote: c:/snapshots/mysnapshot1298228509933.png
at elapsed time of 150.017 seconds wrote: c:/snapshots/mysnapshot1298228510379.png

The total video time is about 151 seconds so we capture 16 frames.


In order to create video, we will have to take a bit more low level approach in comparison to the 
MediaTool API that we have seen so far. Don’t worry though, it is not going to be complicated. The main idea is that we create a media writer, add some stream information to it, encode our media (the screenshot images), and close the writer. Let’s see the code used to achieve this:

package com.javacodegeeks.xuggler;




import java.awt.AWTException;

import java.awt.Dimension;


import java.awt.Rectangle;

import java.awt.Robot;


import java.awt.Toolkit;

import java.awt.image.BufferedImage;


import java.util.concurrent.TimeUnit;




import com.xuggle.mediatool.IMediaWriter;

import com.xuggle.mediatool.ToolFactory;


import com.xuggle.xuggler.ICodec;




public class ScreenRecordingExample {

     


    private static final double FRAME_RATE = 50;

     


   private static final int SECONDS_TO_RUN_FOR = 20;

     


    private static final String outputFilename = "c:/mydesktop.mp4";

     


    private static Dimension screenBounds;




    public static void main(String[] args) {




        // let's make a IMediaWriter to write the file.

        final IMediaWriter writer = ToolFactory.makeWriter(outputFilename);


         

        screenBounds = Toolkit.getDefaultToolkit().getScreenSize();




        // We tell it we're going to add one video stream, with id 0,


        // at position 0, and that it will have a fixed frame rate of FRAME_RATE.

        writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_MPEG4,


                   screenBounds.width/2, screenBounds.height/2);




        long startTime = System.nanoTime();

         


      for (int index = 0; index < SECONDS_TO_RUN_FOR * FRAME_RATE; index++) {

             


            // take the screen shot

            BufferedImage screen = getDesktopScreenshot();




            // convert to the right image type


            BufferedImage bgrScreen = convertToType(screen,

                   BufferedImage.TYPE_3BYTE_BGR);




            // encode the image to stream #0


            writer.encodeVideo(0, bgrScreen, System.nanoTime() - startTime,

                   TimeUnit.NANOSECONDS);




            // sleep for frame rate milliseconds


            try {

                Thread.sleep((long) (1000 / FRAME_RATE));


           }

            catch (InterruptedException e) {


                // ignore

           }


             

        }


         

        // tell the writer to close and write the trailer if  needed


        writer.close();




    }

     


    public static BufferedImage convertToType(BufferedImage sourceImage, int targetType) {

         


        BufferedImage image;




        // if the source image is already the target type, return the source image

        if (sourceImage.getType() == targetType) {


            image = sourceImage;

        }


        // otherwise create a new image of the target type and draw the new image

        else {


            image = new BufferedImage(sourceImage.getWidth(),

                 sourceImage.getHeight(), targetType);


            image.getGraphics().drawImage(sourceImage, 0, 0, null);

        }




        return image;


         

    }


     

    private static BufferedImage getDesktopScreenshot() {


        try {

            Robot robot = new Robot();


            Rectangle captureSize = new Rectangle(screenBounds);

           return robot.createScreenCapture(captureSize);


        }

        catch (AWTException e) {


            e.printStackTrace();

            return null;


        }

         


    }




}


We start by creating an 
IMediaWriter from a given output file. This class encodes and decodes media, handling both audio and video streams. Xuggler guesses the output format from the file name extension (in our case MP4) and sets some default values appropriately. We then use the addVideoStream method to add a new video stream, providing its index, the codec type used (MPEG-4 here) and the video dimensions. The dimensions are set equal to half of the screen’s dimensions in this example.

Then we execute a loop that runs for a number of times equal to the desired frame rate multiplied with the desired running time. Inside the loop, we generate a screen snapshot as described in the Java2D: Screenshots with Java article. We retrieve the screenshot as a
BufferedImage and convert it to the appropriate type (TYPE_3BYTE_BGR) if it is not already there.

Next, we encode the image to the video stream using the 
IMediaWriter.encodeVideo method. We provide the stream index, the image, the elapsed video time and the time unit. Then, we sleep for the appropriate number of time, depending on the desired frame rate. When the loop is over, we close the writer and write the trailer if necessary, depending on the video format (this is done automatically by Xuggler).

If we execute the application, a video will be created which has recorded your desktop actions.

Thursday, May 2, 2013

Compile Device Driver using Eclipse



Compile Device Driver Using Eclipse

 
There is an easy way to compile device driver in Linux using eclipse, once its been setup life becomes much easy, as you don't have to switch between the editor and the command shell every time you need to change something,

Here is the screen shot of my project, Look at it carefully, all you need to add to the project are main.c and a makefile. rest are the result of compilation. makefile will only contain one line obj-m := main.o


Most of the things remain same for the simple C project as mentioned in the previous post, after creating the project, you need to change the command to build the project as,

make -C /usr/src/linux-headers-2.6.35-22-generic M=$(PWD) modules

The path given above is my linux kernel header file path, change to yours accordingly. After this, you set the build directory to the directory of your source code for device drivers. And in the behavior tab, remove the all from build command line, other wise it will crib saying could not find rule to build all !! 

Thats it, you are ready to use the Eclipse IDE for device driver development.

Comment for questions.








*taken from another author's material sometime back

Sunday, February 24, 2013

The Scrum/Agile Methodology


What new Agile teams don’t realize, is that there are different types of Agile methodologies, the most popular one being Scrum.

The Scrum Methodology

Most teams that transition to Agile choose to start with Scrum because it is simple and allows for a lot of flexibility.

As explained on Scrummethodology.com, “Scrum is unique because it introduced the idea of “empirical process control.” That is, Scrum uses the real-world progress of a project — not a best guess or uninformed forecast — to plan and schedule releases.”
What differentiates Scrum from other methodologies?

– Scrum has three roles: Product owner, team members, scrum master.

– Projects are divided into sprints, which typically last one, two or three weeks.

– At the end of each sprint, all stakeholders meet to assess the progress and plan its next steps.

– The advantage of scrum is that a project’s direction to be adjusted based on completed work, not on speculation or predictions.
The Scrum process includes the following steps:
Backlog refinement

This process allows all team members to share thoughts and concerns, and properly understand the workflow.
Sprint planning

Every iteration starts with a sprint planning meeting. The product owner holds a conversation with the team and decides which stories are highest in priority, and which ones they will tackle first. Stories are added to the sprint backlog, and the team then breaks down the stories and turn them into tasks.
Daily Scrum

The daily scrum is also known as the daily standup meeting. This serves to tighten communication and ensure that the entire team is on the same page. Each member goes through what they have done since the last standup, what they plan to work on before the next one, and outline any obstacles.
Sprint review meeting

At the end of a sprint, the team presents their work to the product owner. The product owner goes through the sprint backlog and either accepts or rejects the work. All uncompleted stories are rejected by the product owner.
Sprint retrospective meeting

Finally, after a sprint, the scrum master meets with the team for a retrospective meeting. They go over what went well, what did not, and what can be improved in the next sprint. The product owner is also present, and will listen to the team lay out the good and bad aspects of the sprint. This process allows the entire team to focus on its overall performance and identify strategies for improvement. It is crucial as the ScrumMaster can observe common impediments and work to resolve them.

ADB: All Commands and Options



ADB stands for "Android Debug Bridge". It comes with the android 2.0 sdk and can be run from the windows command prompt or a mac/linux terminal.

In order to run ADB from your machine, you will need to set up the following in your Droid "Settings".

Settings -> Application Settings -> Developement
Then check all of the boxes. Really, you only need the "USB Debugging" box checked, but I checked em all cause I'm cool like that.​


Once you have ADB and have your Droid set for developement, you can plud your Droid into your machine with the USB cable supplied with the device.

On a Mac or Linux machine, you will have to "cd" to the "Tools" directory, under where ever you put the the "android-sdk-(mac or linux)" folder.

EX. On a mac you would do the following:

CODE:cd /Users/[I]yourusername[/I]/android-sdk-mac/tools


(Its prettty much the same on a PC, but there are .bat files to run ADB for you in the "tools" folder)

Now that you can start adb here is how you can use it. I pulled the following from my terminal:

Android Debug Bridge version 1.0.25

 -d                            - directs command to the only connected USB device
                                 returns an error if more than one USB device is present.
 -e                            - directs command to the only running emulator.
                                 returns an error if more than one emulator is running.
 -s <serial number>            - directs command to the USB device or emulator with
                                 the given serial number. Overrides ANDROID_SERIAL
                                 envivornment variable.
 -p <product name or path>     - simple product name like 'sooner', or
                                 a relative/absolute path to a product
                                 out directory like 'out/target/product/sooner'.
                                 If -p is not specified, the ANDROID_PRODUCT_OUT
                                 environment variable is used, which must
                                 be an absolute path.
 devices                       - list all connected devices
 connect <host>:<port>         - connect to a device via TCP/IP 
 disconnect <host>:<port>      - disconnect from a TCP/IP device

device commands:
  adb push <local> <remote>    - copy file/dir to device
  adb pull <remote> <local>    - copy file/dir from device
  adb sync [ <directory> ]     - copy host->device only if changed
                                 (see 'adb help all')
  adb shell                    - run remote shell interactively
  adb shell <command>          - run remote shell command
  adb emu <command>            - run emulator console command
  adb logcat [ <filter-spec> ] - View device log
  adb forward <local> <remote> - forward socket connections
                                 forward specs are one of: 
                                   tcp:<port>
                                   localabstract:<unix domain socket name>
                                   localreserved:<unix domain socket name>
                                   localfilesystem:<unix domain socket name>
                                   dev:<character device name>
                                   jdwp:<process pid> (remote only)
  adb jdwp                     - list PIDs of processes hosting a JDWP transport
  adb install [-l] [-r] <file> - push this package file to the device and install it
                                 ('-l' means forward-lock the app)
                                 ('-r' means reinstall the app, keeping its data)
  adb uninstall [-k] <package> - remove this app package from the device
                                 ('-k' means keep the data and cache directories)
  adb bugreport                - return all information from the device
                                 that should be included in a bug report.

  adb help                     - show this help message
  adb version                  - show version num

DATAOPTS:
 (no option)                   - don't touch the data partition
  -w                           - wipe the data partition
  -d                           - flash the data partition

scripting:
  adb wait-for-device          - block until device is online
  adb start-server             - ensure that there is a server running
  adb kill-server              - kill the server if it is running
  adb get-state                - prints: offline | bootloader | device
  adb get-serialno             - prints: <serial-number>
  adb status-window            - continuously print device status for a specified device
  adb remount                  - remounts the /system partition on the device read-write
  adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program
  adb root                     - restarts the adbd daemon with root permissions
  adb usb                      - restarts the adbd daemon listening on USB  
  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port

networking:
  adb ppp <tty> [parameters]   - Run PPP over USB.
 Note: you should not automatically start a PPP connection.
 <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1
 [parameters] - Eg. defaultroute debug dump local notty usepeerdns

adb sync notes: adb sync [ <directory> ]
  <localdir> can be interpreted in several ways:

  - If <directory> is not specified, both /system and /data partitions will be updated.

  - If it is "system" or "data", only the corresponding partition
    is updated.


From the above, you should be able to see that you can send adb commands from your machine to your Droid using the following:

CODE:adb -s [yourdeviceserialnumberhere] shell


The above will start an interactive shell from your machine, but running on your device. So if you "cd" to a directory, it will be on your device. Use "ls" or "ls -l" to see what is in the directory that your are currently in. NOTE: Runing the adb shell directly has gotten me nowhere as far as rooting the device, but its a good place to start learning.

Now for the fun part!! You can "pull" some data from your device using:

CODE:adb -s [yourdeviceserialnumberhere] pull /system /somedirectoryonyourmachine


This will try and write all the files and folders from the "/system" directory on your Droid, to wherever you decide you want it on you machine.

I did the "pull" on a mac and I was able to get about 140mb of the data from the following directories on my Droid:

/dev
/proc
/sys
/system​

It both as an admin and a super user on the mac and I got about the same results. My Droid was in the regular boot mode. I have not tried booting into the restore or safe modes and tried a "pull" ... yet.