Comments (12)
1:1 aspect ratio maybe stretch or compress the camera preview. Is the following snippet what you expected:
<com.pili.pldroid.streaming.widget.AspectFrameLayout
android:id="@+id/cameraPreview_afl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<android.opengl.GLSurfaceView
android:id="@+id/cameraPreview_surfaceView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center" />
</com.pili.pldroid.streaming.widget.AspectFrameLayout>
from pldroidmediastreaming.
The scaling and the cropping has to be handled by your code (may be the
same way you handle 4:3 ratio) else the output will be stretched or
compressed.
I am currently using open source Kickflip sdk and I modified certain part
of their code via matrix transformation for proper square aspect ratio.
On Aug 23, 2015 7:45 AM, "jpxiong" [email protected] wrote:
1:1 aspect ratio maybe stretch or compress the camera preview. Is the
following snippet what you expected:<com.pili.pldroid.streaming.widget.AspectFrameLayout android:id="@+id/cameraPreview_afl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" > <android.opengl.GLSurfaceView android:id="@+id/cameraPreview_surfaceView" android:layout_width="200dp" android:layout_height="200dp" android:layout_gravity="center" /> </com.pili.pldroid.streaming.widget.AspectFrameLayout>
—
Reply to this email directly or view it on GitHub
#16 (comment)
.
from pldroidmediastreaming.
OK. You just need the 1:1 (Square) aspect ratio for the layout , but not the GLSurfaceView. Right ?
from pldroidmediastreaming.
My requirement is that the output video should be Square format and the preview should be square as well. So I guess it has to be implemented in your code to properly handle 1:1 aspect and exposed via your API, something like CameraStreamingSetting.PREVIEW_SIZE_RATIO.RATIO_SQUARE
In Kickflip, they have a FullScreenRect.java (https://github.com/Kickflip/kickflip-android-sdk/blob/master/sdk/src/main/java/io/kickflip/sdk/av/FullFrameRect.java) which accepts a TextTure2DProgram as constructor argument. They have a function called adjustForVerticalVideo() which is called first time camera and preview is ready and called subsequently to adjust ratios when the camera is rotated (from portrait to landscape etc..)
I modified that part of code as follows, for proper scaling into square aspect ratio. The SurfaceVIew in my code resides in a square layout and hence the preview and output are both square.
Matrix.setIdentityM(IDENTITY_MATRIX, 0);
float scaleval = isWideScreen ? 1.78f : 1.33f; //if(16:9) then 1.78 scale factor, else if 4:3 then 1.33 scale factor
switch (orientation) {
case VERTICAL:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, 1f, 1f);
case LANDSCAPE:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
break;
case UPSIDEDOWN_VERTICAL:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
break;
case UPSIDEDOWN_LANDSCAPE:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
break;
}
from pldroidmediastreaming.
Thanks for your sharing. It's very helpful to me.
from pldroidmediastreaming.
It seems adjustForVerticalVideo
can't work properly .
After i invoked the adjustForVerticalVideo
, the preview didn't any change. What did i miss?
public void adjustForVerticalVideo(SCREEN_ROTATION orientation, boolean isWideScreen) {
synchronized (mDrawLock) {
Log.i("FullFrameRect", "adjustForVerticalVideo orientation:" + orientation + ",isWideScreen:" + isWideScreen);
mCorrectVerticalVideo = true;
requestedOrientation = orientation;
Matrix.setIdentityM(IDENTITY_MATRIX, 0);
float scaleval = isWideScreen ? 1.78f : 1.33f; //if(16:9) then 1.78 scale factor, else if 4:3 then 1.33 scale factor
switch (orientation) {
case VERTICAL:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, 1f, 1f);
case LANDSCAPE:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
break;
case UPSIDEDOWN_VERTICAL:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
break;
case UPSIDEDOWN_LANDSCAPE:
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
break;
}
}
}
from pldroidmediastreaming.
I remember that I had to change a lot of other stuff as well along with this piece of code. I had to change the section which calls adjustForverticalVideo and the section that handles phone rotation among other things..I also had to comment out a portion of code in the same file fullframerect.java, which
P.S: I am still trying to figure out how to go to a specific time in my commit to retrieve the entire source code tree and then I would be able to tell you what changes I did exactly. Source code is hosted in Microsoft and I guess there is no direct way to browse the entire tree at certain commit. I guess I would have to clone a specific commit to my machine.
from pldroidmediastreaming.
This is how my fullframerect.java looks. Please note that //Matrix.scaleM(texMatrix, 0, 0.316f, 1.0f, 1f); is commented out in drawFrame()
public class FullFrameRect {
public static enum SCREEN_ROTATION {LANDSCAPE, VERTICAL, UPSIDEDOWN_LANDSCAPE, UPSIDEDOWN_VERTICAL}
private final Drawable2d mRectDrawable = new Drawable2d(Drawable2d.Prefab.FULL_RECTANGLE);
private Texture2dProgram mProgram;
private final Object mDrawLock = new Object();
private static final int SIZEOF_FLOAT = 4;
private float[] IDENTITY_MATRIX = new float[16];
private static final float TEX_COORDS[] = {
0.0f, 0.0f, // 0 bottom left
1.0f, 0.0f, // 1 bottom right
0.0f, 1.0f, // 2 top left
1.0f, 1.0f // 3 top right
};
private static final FloatBuffer TEX_COORDS_BUF = GlUtil.createFloatBuffer(TEX_COORDS);
private static final int TEX_COORDS_STRIDE = 2 * SIZEOF_FLOAT;
private boolean mCorrectHorizontalVideo = false;
private boolean mScaleToFit;
private SCREEN_ROTATION requestedOrientation = SCREEN_ROTATION.VERTICAL;
/**
* Prepares the object.
*
* @param program The program to use. FullFrameRect takes ownership, and will release
* the program when no longer needed.
*/
public FullFrameRect(Texture2dProgram program) {
mProgram = program;
Matrix.setIdentityM(IDENTITY_MATRIX, 0);
}
/**
* Adjust the MVP Matrix to rotate and crop the texture
* to make Horizontal video appear upright
*/
public void fixAspectRatio(SCREEN_ROTATION orientation, boolean scaleToFit, boolean isWideScreen) {
synchronized (mDrawLock) {
mCorrectHorizontalVideo = true;
mScaleToFit = scaleToFit;
requestedOrientation = orientation;
Matrix.setIdentityM(IDENTITY_MATRIX, 0);
float scaleval = isWideScreen ? 1.78f : 1.33f;
switch (orientation) {
case VERTICAL:
if(scaleToFit)
{
//Matrix.rotateM(IDENTITY_MATRIX, 0, -90, 0f, 0f, 1f);
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, 1f, 1f);
}
else {
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, 1f, 1f);
}
case LANDSCAPE:
if (scaleToFit) {
//Matrix.rotateM(IDENTITY_MATRIX, 0, 90, 0f, 0f, 1f);
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
} else {
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
}
break;
case UPSIDEDOWN_VERTICAL:
if(scaleToFit)
{
//Matrix.rotateM(IDENTITY_MATRIX, 0, -90, 0f, 0f, 1f);
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
}
else {
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
}
break;
case UPSIDEDOWN_LANDSCAPE:
if (scaleToFit) {
//Matrix.rotateM(IDENTITY_MATRIX, 0, -90, 0f, 0f, 1f);
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
} else {
Matrix.scaleM(IDENTITY_MATRIX, 0, 1f, scaleval, 1f);
}
break;
}
}
}
/**
* Releases resources.
*/
public void release() {
if (mProgram != null) {
mProgram.release();
mProgram = null;
}
}
/**
* Returns the program currently in use.
*/
public Texture2dProgram getProgram() {
return mProgram;
}
/**
* Changes the program. The previous program will be released.
*/
public void changeProgram(Texture2dProgram program) {
mProgram.release();
mProgram = program;
}
/**
* Creates a texture object suitable for use with drawFrame().
*/
public int createTextureObject() {
return mProgram.createTextureObject();
}
/**
* Draws a viewport-filling rect, texturing it with the specified texture object.
*/
public void drawFrame(int textureId, float[] texMatrix) {
// Use the identity matrix for MVP so our 2x2 FULL_RECTANGLE covers the viewport.
synchronized (mDrawLock) {
if (mCorrectHorizontalVideo && !mScaleToFit && (requestedOrientation == SCREEN_ROTATION.LANDSCAPE || requestedOrientation == SCREEN_ROTATION.UPSIDEDOWN_LANDSCAPE)) {
//Matrix.scaleM(texMatrix, 0, 0.316f, 1.0f, 1f);
}
mProgram.draw(IDENTITY_MATRIX, mRectDrawable.getVertexArray(), 0,
mRectDrawable.getVertexCount(), mRectDrawable.getCoordsPerVertex(),
mRectDrawable.getVertexStride(),
texMatrix, TEX_COORDS_BUF, textureId, TEX_COORDS_STRIDE);
}
}
/**
* Pass touch event down to the
* texture's shader program
*
* @param ev
*/
public void handleTouchEvent(MotionEvent ev) {
mProgram.handleTouchEvent(ev);
}
}
from pldroidmediastreaming.
This is how my SensonChangedListener looks like (BroadcastActivity.java). mBroadcaster.fixAspectRatio calls fixAspectRatio in CameraEncoder.
private SensorEventListener mOrientationListener = new SensorEventListener() {
final int SENSOR_CONFIRMATION_THRESHOLD = 5;
int[] confirmations = new int[2];
int orientation = -1;
@Override
public void onSensorChanged(SensorEvent event) {
if (activity != null && activity.findViewById(R.id.rotateDeviceHint) != null) {
//Log.i(TAG, "Sensor " + event.values[1]);
if (event.values[1] > 10 || event.values[1] < -10) {
// Sensor noise. Ignore.
} else if (event.values[1] < 5.5 && event.values[1] > -5.5) {
// Landscape
if (orientation != 1 && readingConfirmed(1)) {
if (mBroadcaster.getSessionConfig().getFixAspectRatio()) {
if (event.values[0] > 0) {
mBroadcaster.fixAspectRatio(FullFrameRect.SCREEN_ROTATION.LANDSCAPE);
} else {
mBroadcaster.fixAspectRatio(FullFrameRect.SCREEN_ROTATION.UPSIDEDOWN_LANDSCAPE);
}
} else {
activity.findViewById(R.id.rotateDeviceHint).setVisibility(View.VISIBLE);
}
orientation = 1;
}
} else if (event.values[1] > 7.5 || event.values[1] < -7.5) {
// Portrait
if (orientation != 0 && readingConfirmed(0)) {
if (mBroadcaster.getSessionConfig().getFixAspectRatio()) {
if (event.values[1] > 0) {
mBroadcaster.fixAspectRatio(FullFrameRect.SCREEN_ROTATION.VERTICAL);
} else {
mBroadcaster.fixAspectRatio(FullFrameRect.SCREEN_ROTATION.UPSIDEDOWN_VERTICAL);
}
} else {
activity.findViewById(R.id.rotateDeviceHint).setVisibility(View.GONE);
}
orientation = 0;
}
}
}
}
/**
* Determine if a sensor reading is trustworthy
* based on a series of consistent readings
*/
private boolean readingConfirmed(int orientation) {
confirmations[orientation]++;
confirmations[orientation == 0 ? 1 : 0] = 0;
return confirmations[orientation] > SENSOR_CONFIRMATION_THRESHOLD;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
from pldroidmediastreaming.
This is how my fixAspectRatio() in CameraEncoder.java looks like mFullScreen.fixAspectRatio calls AspectRatio of fullframerect.java and mDisplayRenderer.fixAspectRatio calls fixAspectRatio of CameraSurfaceRenderer.java
public void fixAspectRatio(FullFrameRect.SCREEN_ROTATION orientation) {
if (mFullScreen != null) mFullScreen.fixAspectRatio(orientation, true, isWideScreen());
mDisplayRenderer.fixAspectRatio(orientation);
}
private boolean isWideScreen()
{
if(mCamera == null) return true;
return mCamera.getParameters().getPreviewSize().height * 16 == mCamera.getParameters().getPreviewSize().width * 9;
}
from pldroidmediastreaming.
This is how my fixAspectRatio in CameraSurfaceRenderer.java looks like
public void fixAspectRatio(FullFrameRect.SCREEN_ROTATION isVertical) {
if (mFullScreenCamera != null) mFullScreenCamera.fixAspectRatio(isVertical, false, isWideScreen(mCameraEncoder));
}
from pldroidmediastreaming.
This is how my GLCameraView looks like
public class GLCameraView extends GLSurfaceView {
private static final String TAG = "GLCameraView";
private static final double ASPECT_RATIO = 4.0 / 4.0;
protected ScaleGestureDetector mScaleGestureDetector;
private Camera mCamera;
private int mMaxZoom;
public GLCameraView(Context context) {
super(context);
init(context);
}
public GLCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context){
mMaxZoom = 0;
}
public void setCamera(Camera camera){
mCamera = camera;
mCamera.setDisplayOrientation(90);
Camera.Parameters camParams = mCamera.getParameters();
if(camParams.isZoomSupported()){
mMaxZoom = camParams.getMaxZoom();
mScaleGestureDetector = new ScaleGestureDetector(getContext(), mScaleListener);
}
}
public void releaseCamera(){
mCamera = null;
mScaleGestureDetector = null;
}
private ScaleGestureDetector.SimpleOnScaleGestureListener mScaleListener = new ScaleGestureDetector.SimpleOnScaleGestureListener(){
int mZoomWhenScaleBegan = 0;
int mCurrentZoom = 0;
@Override
public boolean onScale(ScaleGestureDetector detector) {
if(mCamera != null){
Camera.Parameters params = mCamera.getParameters();
mCurrentZoom = (int) (mZoomWhenScaleBegan + (mMaxZoom * (detector.getScaleFactor() - 1)));
mCurrentZoom = Math.min(mCurrentZoom, mMaxZoom);
mCurrentZoom = Math.max(0, mCurrentZoom);
params.setZoom(mCurrentZoom);
mCamera.setParameters(params);
}
return false;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mZoomWhenScaleBegan = mCamera.getParameters().getZoom();
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
};
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(mScaleGestureDetector != null){
if(!mScaleGestureDetector.onTouchEvent(ev)){
// No scale gesture detected
}
}
return true;
}
/**
* Measure the view and its content to determine the measured width and the
* measured height
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
if (width > height * ASPECT_RATIO) {
width = (int) (height * ASPECT_RATIO + 0.5);
}
else {
height = (int) (width / ASPECT_RATIO + 0.5);
}
setMeasuredDimension(width, height);
}
/*@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = View.MeasureSpec.getSize( widthMeasureSpec );
int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
int height = (width * 9)/16;
int newheightMeasureSpec = View.MeasureSpec.makeMeasureSpec( height, heightMode );
super.onMeasure(widthMeasureSpec, newheightMeasureSpec);
}*/
}
from pldroidmediastreaming.
Related Issues (20)
- Youtube rtmp link not working HOT 1
- 录屏推流需要使用CameraPreviewFrameView吗?
- 视频进度条 HOT 1
- Access denied finding property "camera.aux.packagelist"
- 推流端预览左右两边有黑色 HOT 1
- 如何推流前预览? HOT 1
- 开始推流后 返回状态码 streamingState = UNAUTHORIZED_STREAMING_URL extra = -3 HOT 1
- 快速开始是不是已经不能快速开始了? HOT 1
- targetSdkVersion 29录屏会闪退 HOT 1
- 编译报错,与我的项目中使用的库有冲突? HOT 2
- 通过captureFrame截帧,图像变形。
- 引用happy-dns,还报NoSuchMethodError错误 HOT 4
- No static method defaultResolver() HOT 3
- Issue with the support of 64 bit libraries.
- Unauthorized Package while starting the Streaming
- Pili Streaming not working with Pili Android Version 2.4.0
- activity添加两个fragment,使用懒加载,第二个fragment,无法调起相机 HOT 1
- 最新Demo运行不起来 HOT 3
- 急急急,请问为啥下载的apk demo是牛直播,github上下载的代码跑起来又不像同一个app
- 播放器拉流问题
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pldroidmediastreaming.