Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejava
themeRDark
titleTestLayoutWithBox.java
collapsetrue
// Package name should be strictly defined as com.flashphoner.mixerlayout
package com.flashphoner.mixerlayout;

// Import mixer layout interface
import com.flashphoner.media.mixer.video.presentation.BoxPosition;
import com.flashphoner.sdk.media.IVideoMixerLayout;
// Import YUV frame description
import com.flashphoner.sdk.media.YUVFrame;
// Import Box class for picture operations
import com.flashphoner.media.mixer.video.presentation.Box;
// Import MixerConfig class
Uncomment this if using build 5.2.878-5.2.976
// import com.flashphoner.server.commons.rmi.data.impl.MixerConfig;

// Import Java packages to use
import java.awt.*;
import java.util.ArrayList;

/**
 * Custom mixer layout implementation example
 */
public class TestLayout implements IVideoMixerLayout {

    // Pictures padding, should be even (or zero if no padding needed)
    private static final int PADDING = 4;

    /**
     * Function to compute layout, will be called by mixer before encoding output stream picture
     * This example computes one-line grid layout
     * @param yuvFrames - incoming streams raw pictures array in YUV format
     * @param strings - incoming streams names array
     * @param canvasWidth - mixer output picture canwas width
     * @param canvasHeight - mixer output picture canwas heigth
     * @return array of pictures layouts
     */
    @Override
    public Layout[] computeLayout(YUVFrame[] yuvFrames, String[] strings, int canvasWidth, int canvasHeight) {
        // This object represents mixer canvas
        Box mainBox = new Box(null, canvasWidth, canvasHeight);

        // Find every picture dimensions (this are the same for all the pictures because this is grid layout)
        int frameBoxWidth = canvasWidth / yuvFrames.length - PADDING;
        int frameBoxHeight = canvasHeight / yuvFrames.length;

        // Container to place stream pictures
        Box container = new Box(mainBox, canvasWidth, frameBoxHeight);
        container.setPosition(BoxPosition.CENTER);

        // Iterate through incoming stream pictures array
        // Note: streams pictures order corresponds to stream names array, use this to reorder pictures if needed
        boolean firstFrame = true;
        for (int c = 0; c < yuvFrames.length; c++) {
            // Stream picture parent rectangle
            // This rectangle can include stream caption if mixer_text_outside_frame setting is enabled
            Box frameBox = new Box(container, frameBoxWidth, (int)container.getSize().getHeight());
            frameBox.setPosition(BoxPosition.INLINE_HORIZONTAL_CENTER);
            // Add padding for subsequent pictures
            if (!firstFrame) {
                frameBox.setPaddingLeft(PADDING);
            }
            firstFrame = false;
            // Compute picture frame placement including stream caption text
            Box frame = Box.computeBoxWithFrame(frameBox, yuvFrames[c]);
            // Adjust picture to the parent rectangle
            frame.fillParent();

        }
        // Prepare an array to return layout calculated
        ArrayList<IVideoMixerLayout.Layout> layout = new ArrayList<>();
        // Calculate mixer layout
        mainBox.computeLayout(layout);
        // Return the result
        return layout.toArray(new IVideoMixerLayout.Layout[layout.size()]);
    }

    /**
     * The function for internal use. Must be overriden.
     * Uncomment this if using build 5.2.878-5.2.976
     */
    //@Override
    //public void setConfig(MixerConfig mixerConfig) {
    //}
}

Main Box class methods:

...

Code Block
languagejava
themeRDark
titleSideBySideLayout.java
collapsetrue
package com.flashphoner.mixerlayout;

// Import mixer layout interface
import com.flashphoner.media.mixer.video.presentation.BoxPosition;
import com.flashphoner.sdk.media.IVideoMixerLayout;
// Import YUV frame description
import com.flashphoner.sdk.media.YUVFrame;
// Import Box class for picture operations
import com.flashphoner.media.mixer.video.presentation.Box;
// Import MixerConfig class
 Uncomment this if using build 5.2.878-5.2.976
// import com.flashphoner.server.commons.rmi.data.impl.MixerConfig;

// Import Java packages to use
import java.awt.*;
import java.util.ArrayList;

public class SideBySideLayout implements IVideoMixerLayout {
    // Owner's stream name
    private static final String USERFOR = "user_for";
    // Challenger's stream name
    private static final String USERAGAINST = "user_against";

    /**
     * Function to compute layout, will be called by mixer before encoding output stream picture
     * This example computes grid layout
     * @param yuvFrames - incoming streams raw pictures array in YUV format
     * @param strings - incoming streams names array
     * @param canvasWidth - mixer output picture canwas width
     * @param canvasHeight - mixer output picture canwas heigth
     * @return array of pictures layouts
     */
    @Override
    public Layout[] computeLayout(YUVFrame[] yuvFrames, String[] strings, int canvasWidth, int canvasHeight) {
        // This object represents mixer canvas
        Box mainBox = new Box(null, canvasWidth, canvasHeight);

        // Container to place CHALLENGER stream pictures
        Box userForContainer = new Box(mainBox, canvasWidth / 2, canvasHeight);
        userForContainer.setPosition(BoxPosition.LEFT);
        // Container to place OWNER stream pictures
        Box userAgainstContainer = new Box(mainBox, canvasWidth / 2, canvasHeight);
        userAgainstContainer.setPosition(BoxPosition.RIGHT);

        // Iterate through incoming stream pictures array
        for (int c = 0; c < yuvFrames.length; c++) {
            String name = strings[c];
            Box container;
            
            // Chhose container depending on stream name
            if (name.contains(USERFOR)) {
                container = userForContainer;
            } else if (name.contains(USERAGAINST)) {
                container = userAgainstContainer;
            } else {
                // Wrong stream name
                continue;
            }
            // Fill the container by the stream picture
            Box frameBox = Box.computeBoxWithFrame(container, yuvFrames[c]);
            frameBox.fillParentNoScale();
        }        
        // Prepare an array to return layout calculated
        ArrayList<IVideoMixerLayout.Layout> layout = new ArrayList<>();
        // Calculate mixer layout
        mainBox.computeLayout(layout);
        // Return the result
        return layout.toArray(new IVideoMixerLayout.Layout[layout.size()]);        
    }
    
    /**
     * The function for internal use. Must be overriden.
     * Uncomment this if using build 5.2.878-5.2.976
     */
    //@Override
    //public void setConfig(MixerConfig mixerConfig) {
    //}
}

Mixer layout management while creating mixer

...