/**
 * Copyright (c) 2006 - 2012 Smaxe Ltd (www.smaxe.com).
 * All rights reserved.
 */
import com.smaxe.io.ByteArray;
import com.smaxe.uv.media.core.IMedia;
import com.smaxe.uv.media.core.IMediaFileReader;
import com.smaxe.uv.media.core.IMediaFileWriter;
import com.smaxe.uv.media.core.MediaContainer;
import com.smaxe.uv.media.core.MediaTrackInfo;
import com.smaxe.uv.media.sdk.IMediaContainerSdk;
import com.smaxe.uv.media.sdk.IMediaSdk;
import com.smaxe.uv.media.sdk.MediaSdkFactory;
import com.smaxe.uv.media.util.IterableIterator;

import java.io.File;
import java.util.Iterator;

/**
 * <code>ExMediaSdkMediaFileContainer</code> - {@link IMediaSdk} example to
 * read/write media files. 
 * 
 * @author Andrei Sochirca
 * @see <a href="http://www.smaxe.com/product.jsf?id=juv-media-sdk" target="_blank">JUV Media SDK</a>
 */
public final class ExMediaSdkMediaFileContainer extends Object
{
    /**
     * Entry point.
     * 
     * @param args
     * @throws Exception
     */
    public static void main(final String[] args) throws Exception
    {
        // NOTE:
        // Evaluation version has some limitations:
        // - video decoder watermarks frames (and blacks it sometimes)
        
        IMediaSdk mediaSdk = MediaSdkFactory.getMediaSdk();
        
        // 
        // getMediaFileTracksAndSamples(mediaSdk, "d:/sample.flv");
        
        createMediaFileSlice(mediaSdk, "d:/sample.flv", "d:/sample.h264", 0, 1000000);
    }
    
    /**
     * Creates <code>src</code> media file 'slice' starting with <code>start</code> timestamp.
     * 
     * @param mediaSdk
     * @param src source file
     * @param dst destination file
     * @param start
     * @param duration
     * @throws Exception if an exception occurred
     */
    public static void createMediaFileSlice(final IMediaSdk mediaSdk,
            final String src, final String dst, final long start, final long duration) throws Exception
    {
        final IMediaContainerSdk containerSdk = mediaSdk.getMediaContainerSdk();
        
        final IMediaFileReader reader = containerSdk.openFileReader(new File(src));
        // Note: media file container is the same as reader container
        final IMediaFileWriter writer = containerSdk.openFileWriter(new File(dst), MediaContainer.H264);
        
        // Note: if track is not defined than samples (from all tracks) are returned in time order
        final Iterator<IMedia.ITrackSample> samples = reader.getTrackSamples(MediaTrackInfo.ALL_TRACKS, start);
        
        for (IMedia.ITrackSample sample : new IterableIterator<IMedia.ITrackSample>(samples))
        {
            final long timestamp = sample.getTimestamp();
            if (timestamp > start + duration) break;
            
            final ByteArray sampleData = reader.readTrackSample(sample, new byte[(int) sample.getSize()], 0);
            
            writer.writeTrackSample(sample.getTrack(), timestamp, sampleData);
        }
        
        writer.close();
        reader.close();
    }
    
    /**
     * Prints media <code>file</code> tracks and samples.
     * 
     * @param mediaSdk
     * @param file
     * @throws Exception if an exception occurred
     */
    public static void printMediaFileTracksAndSamples(final IMediaSdk mediaSdk, final String file) throws Exception
    {
        final IMediaContainerSdk containerSdk = mediaSdk.getMediaContainerSdk();
        
        final IMediaFileReader reader = containerSdk.openFileReader(new File(file));
        
        final MediaTrackInfo[] tracks = reader.getTracksInfo();
        
        for (int i = 0; i < tracks.length; i++)
        {
            System.out.println(tracks[i]);
            
            final Iterator<IMediaFileReader.ITrackSample> samples = reader.getTrackSamples(tracks[i], 0 /*timestamp*/);
            
            for (IMediaFileReader.ITrackSample sample : new IterableIterator<IMediaFileReader.ITrackSample>(samples))
            {
                System.out.println(sample);
            }
        }
        
        reader.close();
    }
    
    /**
     * Constructor.
     */
    private ExMediaSdkMediaFileContainer()
    {
    }
}