All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.libav.video.Frame2VideoFrameAdapter Maven / Gradle / Ivy

/*
 * Copyright (C) 2012 Ondrej Perutka
 *
 * This program 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.
 *
 * This library 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 this library. If not, see 
 * .
 */
package org.libav.video;

import java.nio.ByteOrder;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.libav.LibavException;
import org.libav.avcodec.FrameWrapperFactory;
import org.libav.avcodec.IFrameWrapper;
import org.libav.avutil.bridge.PixelFormat;
import org.libav.data.IFrameConsumer;
import org.libav.swscale.ScaleContextWrapper;
import org.libav.swscale.bridge.ISWScaleLibrary;

/**
 * Frame to VideoFrame adapter. It translates frame wrappers to video frames.
 * 
 * @author Ondrej Perutka
 */
public class Frame2VideoFrameAdapter implements IFrameConsumer, IVideoFrameProducer {
    
    private int srcWidth;
    private int srcHeight;
    private int srcFormat;
    
    private int dstWidth;
    private int dstHeight;
    private int dstFormat;
    
    private ScaleContextWrapper scaleContext;
    private int scalingAlg;
    
    private IFrameWrapper rgbPicture;
    
    private final Set consumers;

    /**
     * Create a new frame to video frame adapter and set scaling parameters.
     * 
     * @param srcWidth a width of source images
     * @param srcHeight a height of source images
     * @param srcFormat a pixel format of source images
     * @param dstWidth a width of produced images
     * @param dstHeight a height of produced images
     * @throws LibavException if an error occurs
     */
    public Frame2VideoFrameAdapter(int srcWidth, int srcHeight, int srcFormat, int dstWidth, int dstHeight) throws LibavException {
        this.srcWidth = srcWidth;
        this.srcHeight = srcHeight;
        this.srcFormat = srcFormat;
        this.dstWidth = dstWidth;
        this.dstHeight = dstHeight;
        
        dstFormat = PixelFormat.PIX_FMT_BGRA;
        if (ByteOrder.BIG_ENDIAN.equals(ByteOrder.nativeOrder()))
            dstFormat = PixelFormat.PIX_FMT_ARGB;
        scalingAlg = ISWScaleLibrary.SWS_BICUBIC;
        
        init();
        
        consumers = Collections.synchronizedSet(new HashSet());
    }
    
    private void init() throws LibavException {
        if (scaleContext != null)
            scaleContext.free();
        if (rgbPicture != null)
            rgbPicture.free();
        scaleContext = ScaleContextWrapper.createContext(srcWidth, srcHeight, srcFormat, dstWidth, dstHeight, dstFormat, scalingAlg);
        rgbPicture = FrameWrapperFactory.getInstance().allocPicture(dstFormat, dstWidth, dstHeight);
    }
    
    /**
     * Set expected format of source images.
     * 
     * @param width a width
     * @param height a height
     * @param pixelFormat a pixel format
     * @throws LibavException if an error occurs
     */
    public synchronized void setSourceImageFormat(int width, int height, int pixelFormat) throws LibavException {
        if (width != srcWidth || height != srcHeight || srcFormat != pixelFormat) {
            srcWidth = width;
            srcHeight = height;
            srcFormat = pixelFormat;
            init();
        }
    }
    
    /**
     * Get expected width of source images.
     * 
     * @return expected width of source images
     */
    public int getSourceImageWidth() {
        return srcWidth;
    }
    
    /**
     * Get expected height of source images.
     * 
     * @return expected height of source images
     */
    public int getSourceImageHeight() {
        return srcHeight;
    }
    
    /**
     * Get expected pixel format of source images.
     * 
     * @return expected pixel format of source images
     */
    public int getSourceImagePixelFormat() {
        return srcFormat;
    }
    
    /**
     * Set format of produced images.
     * 
     * @param width a width
     * @param height a height
     * @throws LibavException if an error occurs
     */
    public synchronized void setDestinationImageFormat(int width, int height) throws LibavException {
        if (width != dstWidth || height != dstHeight) {
            dstWidth = width;
            dstHeight = height;
            init();
        }
    }
    
    /**
     * Get width of produced images.
     * 
     * @return width of produced images
     */
    public int getDestinationImageWidth() {
        return dstWidth;
    }
    
    /**
     * Get height of produced images.
     * 
     * @return height of produced images
     */
    public int getDestinationImageHeight() {
        return dstHeight;
    }
    
    /**
     * Set scaling algorithm.
     * 
     * @param scalingAlgorithm a scaling algorithm
     * @throws LibavException if an error occurs
     */
    public synchronized void setScalingAlgorithm(int scalingAlgorithm) throws LibavException {
        if (scalingAlgorithm != scalingAlg) {
            scalingAlg = scalingAlgorithm;
            init();
        }
    }
    
    /**
     * Get scaling algorithm.
     * 
     * @return scaling algorithm
     */
    public int getScalingAlgorithm() {
        return scalingAlg;
    }
    
    /**
     * Release all native sources.
     */
    public synchronized void dispose() {
        if (scaleContext != null)
            scaleContext.free();
        if (rgbPicture != null)
            rgbPicture.free();
        
        scaleContext = null;
        rgbPicture = null;
    }

    @Override
    public synchronized void processFrame(Object producer, IFrameWrapper frame) throws LibavException {
        if (scaleContext == null)
            return;
        
        scaleContext.scale(frame, rgbPicture, 0, srcHeight);
        int[] pixels = rgbPicture.getData()[0].getIntArray(0, dstWidth * dstHeight);
        sendVideoFrame(new VideoFrame(pixels, dstWidth, dstHeight, frame.getPts()));
    }
    
    private void sendVideoFrame(VideoFrame vf) throws LibavException {
        synchronized (consumers) {
            for (IVideoFrameConsumer c : consumers)
                c.processFrame(this, vf);
        }
    }

    @Override
    public void addVideoFrameConsumer(IVideoFrameConsumer consumer) {
        consumers.add(consumer);
    }

    @Override
    public void removeVideoFrameConsumer(IVideoFrameConsumer consumer) {
        consumers.remove(consumer);
    }
    
    public int getConsumerCount() {
        return consumers.size();
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy