...
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
// 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 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
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
...