Mixer Layout

Max

Administrator
Staff member
Good day.
Or what kind of professional we should employee to do that?
You should hire Java developer to do this.
But, custom mixer layout allows only to arrange stream pictures but not to separate one of them (desktop). We raised the ticket WCS-2752 to investigate and implement this. We'll let you know in this topic.
 
Dear!

We create this file in JAVA, its reach 90% our needs BUT we are facing an issue, webcams are random positioned and if attach 4 streams mixer stop to work without error on logs file.
Could you help me please?

// Package name should be strictly defined as com.flashphoner.mixerlayout
package com.flashphoner.mixerlayout;

// Import mixer layout interface
import com.flashphoner.sdk.media.IVideoMixerLayout;
// Import YUV frame description
import com.flashphoner.sdk.media.YUVFrame;
import com.flashphoner.sdk.setting.Settings;


// 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_IN = Settings.MIXER_VIDEO_DESKTOP_LAYOUT_INLINE_PADDING.getValue().intValue();

@Override
public IVideoMixerLayout.Layout[] computeLayout(YUVFrame[] yUVFrameArr, String[] strArr, int canvasWidth, int canvasHeight) {

if (yUVFrameArr.length == 0) {
return new IVideoMixerLayout.Layout[0];
}

ArrayList<IVideoMixerLayout.Layout> layout = new ArrayList<>();

int layoutWidth = 0;
int layoutHeight = 0;
int first = 0;

if(yUVFrameArr.length == 1)
{
Point ltPoint = new Point(PADDING_IN, PADDING_IN);
layoutWidth = canvasWidth - 2*PADDING_IN;
layoutHeight = Math.min((int)(layoutWidth*9.0d/16.0d), canvasHeight - 2*PADDING_IN);
layout.add(new IVideoMixerLayout.Layout(ltPoint, new Dimension(layoutWidth, layoutHeight), yUVFrameArr[0]));
}
else { // length >= 2
for (int c = 0; c < yUVFrameArr.length; c++) {

// Set starting point of the picture
Point currentPoint = new Point();

/*Point prevPoint = new Point();
Dimension prevDimension = new Dimension();
if (layout.size() > 1) {
// Find previous picture location to calculate next one
prevPoint.setLocation(layout.get(c - 1).getPoint());
prevDimension.setSize(layout.get(c - 1).getDimension());
}*/

if (strArr[c].toLowerCase().startsWith("d") == true) { //c == first
currentPoint = new Point((int)(canvasWidth * 0.25d) + PADDING_IN, PADDING_IN);
layoutWidth = (int)(canvasWidth * 0.75d) - 2*PADDING_IN;
layoutHeight = Math.min((int)(layoutWidth*9.0d/16.0d), canvasHeight - 2*PADDING_IN);
} else {
//currentPoint = new Point( PADDING_IN, (int) (prevPoint.getY() + prevDimension.getHeight() + PADDING_IN) );
layoutWidth = (int)(canvasWidth * 0.25d) - 2*PADDING_IN;
layoutHeight = Math.min((int) ((layoutWidth*9.0d/16.0d)), (int) ((canvasHeight - (yUVFrameArr.length - 1) * PADDING_IN)/ (double) (yUVFrameArr.length - 1)));
currentPoint = new Point( PADDING_IN, (int) (layoutHeight*c + PADDING_IN) );
}

// Create the picture layout passing starting point, dimensions and raw picture YUV frames
layout.add(new IVideoMixerLayout.Layout(currentPoint, new Dimension(layoutWidth, layoutHeight), yUVFrameArr[c]));
}
}
// Return pictures layouts calculated as array
return layout.toArray(new IVideoMixerLayout.Layout[layout.size()]);
}

}
 

Max

Administrator
Staff member
webcams are random positioned
Yes, by default. You can order layouts by stream name: user1, user2, ...
if attach 4 streams mixer stop to work without error on logs file.
Actually, server crashes here. The reason is this string
Code:
layoutHeight = Math.min((int) ((layoutWidth*9.0d/16.0d)), (int) ((canvasHeight - (yUVFrameArr.length - 1) * PADDING_IN)/ (double) (yUVFrameArr.length - 1)));
In this expression (yUVFrameArr.length - 1) * PADDING_IN)/ (double) (yUVFrameArr.length - 1), yUVFrameArr.length is actually shortened, and picture height is always canvasHeight - PADDING_IN. So 5th stream picture goes out of main picture height.
Please refactor this line to
Code:
layoutHeight = Math.min((int) ((layoutWidth*9.0d/16.0d)), (int) ((canvasHeight / yUVFrameArr.length) - PADDING_IN));
for example. With this fix, server is not crashed in our test environment.
 
Hello!

Thanks as always for solve our questions.
Changing this line solve the server crashs.
Now we face the latest issue, a blank space on left area as bellow:

1594647256022.png
 

Max

Administrator
Staff member
Now we face the latest issue, a blank space on left area as bellow:
In this string
Code:
currentPoint = new Point( PADDING_IN, (int) (layoutHeight*c + PADDING_IN) );
you should skip desktop stream index, for example
Code:
int layoutWidth = 0;
int layoutHeight = 0;
int desktopIdx = -1;
...
for (int c = 0; c < yUVFrameArr.length; c++) {
    Point currentPoint = new Point();
    if (strArr[c].toLowerCase().startsWith("d") == true) {
        ...
        desktopIdx = c;
    } else {
        layoutWidth = (int)(canvasWidth * 0.25d) - 2*PADDING_IN;
        layoutHeight = Math.min((int) ((layoutWidth*9.0d/16.0d)), (int) ((canvasHeight / yUVFrameArr.length) - PADDING_IN));
        int streamIdx = c;
        if (desktopIdx != -1) {
             streamIdx--;
        }
        currentPoint = new Point( PADDING_IN, (int) (layoutHeight*streamIdx + PADDING_IN) );
    }
    layout.add(new IVideoMixerLayout.Layout(currentPoint, new Dimension(layoutWidth, layoutHeight), yUVFrameArr[c]));
}
 

Max

Administrator
Staff member
Good day.
Since build 5.2.710 it is possible to change screen sharing picture placement with the following parameter:
Code:
mixer_desktop_align=RIGHT
In this case, you don't need custom desktop layout. Please read the details here.
 
Top