edu-lance / LivePublisher

Android rtmp推流器
MIT License
177 stars 95 forks source link

请问如何正方形预览,接收端正方形接收? #4

Open aqianglala opened 8 years ago

aqianglala commented 8 years ago

我把serfaceView的宽高设置成正方形,再调用了camera.parameter.setPreviewSize也设置成了正方形,实现了正方形预览,但是接收的图像全乱了,请问是什么原因呢?如何解决?感激不尽

edu-lance commented 8 years ago

你好, 正方形预览是什么意思? 你把surfaceview设置为正方形,就好像是你把一个界面调整为宽高相等。 你的预览分辨率需要getSupportedPreviewSizes查看你android设备支持的预览分辨率。 你可以看看 VideoPusher#setPreviewSize(parameters) ; 而编码的分辨率、码率是在 VideoPusher#setPreviewOrientation(parameters); 传递给c层。 最后在 onPreviewFrame 回调中获取预览数据并根据设备当前朝向进行计算后得到原始nv21数据进行编码打包。

aqianglala commented 8 years ago

就是预览窗口的宽高比例是1:1,我尝试把surface的宽高比例设置成4:3,获取设备支持的previewSize,从中挑选一个比例最接近4:3的,但是在设置previewsize时,把宽设置成高,把高设置成宽,这样就达到了我的效果,但是只有在魅族mx4上能成功,在其他手机都预览失败了,有解决办法吗?

/**
 * 在支持的预览大小中,选择一个最接近的size
 * @param parameters
 */

// private void setPreviewSize(Camera.Parameters parameters) { // List supportedPreviewSizes = parameters // .getSupportedPreviewSizes(); // // Size size = supportedPreviewSizes.get(0); // float m = (float) size.width/size.height; // float abs = Math.abs(m - (float) 1.3333333); // supportedPreviewSizes.remove(0); // Iterator iterator = supportedPreviewSizes.iterator(); // while (iterator.hasNext()) { // Size next = iterator.next(); // float i = (float)next.width / next.height; // float abs1 = Math.abs(i - (float) 1.3333333); // if(abs1<=abs){ // if(next.width>size.width){ // abs = abs1; // m = i; // size = next; // } // } // } // mParam.setHeight(size.width); // mParam.setWidth(size.height); // parameters.setPreviewSize(mParam.getWidth(), mParam.getHeight()); // Log.e("size", "预览分辨率 width:" + size.width + " height:" + size.height); // }

设置surfaceview宽高: // RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mSurfaceView.getLayoutParams(); // layoutParams.width = screenWidth; // layoutParams.height = (int) (screenWidth/1.3333333); // mSurfaceView.setLayoutParams(layoutParams);

edu-lance commented 8 years ago

如果你获取设备支持的预览分辨率只有320x240,那么你setPreviewSize只能用320x240这一个,不能使用240x320,更不能设置为其他,否则会出现错误。 如果设置了不支持的PreviewSize,会抛出setParameters failed错误。 另外surfaceview的宽高与图像数据的分辨率无关。 而你的回调数据是由你分辨率以及预览格式决定的,比如你预览格式为nv21,那么你每帧的数据字节数为: width(320)*height(240) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)/8

aqianglala commented 8 years ago

我试过几个手机,获取支持的预览分辨率都没有接近正方形的,如果我想实现竖频录制下,预览的分辨率希望能是3:4,而不是4:3,如何实现呢,像你那样说的话,好像没办法设置。。。

edu-lance commented 8 years ago

你在android上的预览分辨率只能是那些,不能变的。 但是你可以对数据二/三次线性插值等进行缩放, 可以看看ffmpeg的sws_scale函数。

aqianglala commented 8 years ago

缩放的话,只能在推流端的预览上面达到效果,但是推出去的比例还是一样的啊,比如我比例是4:3,我缩放到1:1,接收端接收到的比例还是4:3啊,还是解决不了

edu-lance commented 8 years ago

我说了,你改变的只是surfaveview的物理大小,分辨率还是那样。 你应该在onPreviewFrame中把获取的帧数据进行缩放。 你要缩放->编码->推送。 缩放这里没写。你要自己去实现。

lisnstatic commented 8 years ago

@liuxang 你好,请教一下,为什么帧率设置的是30,在接收端还不到10,也就是设置的帧率无效是什么原因,已经困扰了好久