Go to Android Camera Development (2): Use TextureView and SurfaceTexture to preview the basic Camera demo of Camera

Source: Internet
Author: User

Google has output TextureView from Android4.0. Why? This is to make up for Surfaceview's shortcomings. On the other hand, it is also to balance GlSurfaceView. Of course, this is my speculation. The relationships between TextureView, Surfaceview, SurfaceTexture, and GLSurfaceView will be analyzed after the artist launches GLSurfaceview preview Camera. This article describes how to preview Camera with TextureView.

In fact, the official website has provided a demo on how to use TextureView to preview Camera. For more information, see here. In addition, link 1 and link 2 also provide a complete preview of the Camera demo, but it is a bunch of things. This article uses a lightweight Camera framework built above to quickly replace Surfaceview. If Surfaceview is used for preview, A SurfaceHolder is passed in. If Textureview is used for preview, A SurfaceTexture is required. Other Camera processes remain unchanged.

1. The new CameraTextureView class inherits TextureView and implements the TextureView. SurfaceTextureListener interface. Implementing this interface is like implementing SurfaceHolder. Callback. The main purpose is to know after SurfaceTexture is ready, that is, the onSurfaceTextureAvailable function.

CameraTextureView. java

Package org. yanzi. camera. preview; import org. yanzi. camera. cameraInterface; import android. content. context; import android. graphics. pixelFormat; import android. graphics. surfaceTexture; import android. util. attributeSet; import android. util. log; import android. view. surfaceHolder; import android. view. surfaceView; import android. view. textureView; public class CameraTextureView extends TextureView implements TextureView. surfaceTextureListener {private static final String TAG = "yanzi"; Context mContext; SurfaceTexture mSurface; public CameraTextureView (Context context, AttributeSet attrs) {super (context, attrs ); // TODO Auto-generated constructor stubmContext = context; this. setSurfaceTextureListener (this) ;}@ Overridepublic void onSurfaceTextureAvailable (SurfaceTexture surface, int width, int height) {// TODO Auto-generated method stubLog. I (TAG, "onSurfaceTextureAvailable... "); mSurface = surface; // CameraInterface. getInstance (). doStartPreview (surface, 1.33f) ;}@ Overridepublic boolean onSurfaceTextureDestroyed (SurfaceTexture surface) {// TODO Auto-generated method stubLog. I (TAG, "onSurfaceTextureDestroyed... "); CameraInterface. getInstance (). doStopCamera (); return true ;}@ Overridepublic void onSurfaceTextureSizeChanged (SurfaceTexture surface, int width, int height) {// TODO Auto-generated method stubLog. I (TAG, "onSurfaceTextureSizeChanged... ") ;}@ Overridepublic void onSurfaceTextureUpdated (SurfaceTexture surface) {// TODO Auto-generated method stubLog. I (TAG, "onSurfaceTextureUpdated... ");}/* enables the Activity to get the SurfaceTexture of TextureView * @ see android. view. textureView # getSurfaceTexture () */public SurfaceTexture _ getSurfaceTexture () {return mSurface ;}}
2. Add it to the layout file, because its parent class is View, just like a general View.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".CameraActivity" >    <FrameLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content" >        <org.yanzi.camera.preview.CameraTextureView            android:id="@+id/camera_textureview"            android:layout_width="0dip"            android:layout_height="0dip" />    </FrameLayout>    <ImageButton        android:id="@+id/btn_shutter"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:background="@drawable/btn_shutter_background"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"         android:layout_marginBottom="10dip"/></RelativeLayout>

3. In CameraInterface, I encapsulate two functions:

/** Use Surfaceview to enable preview * @ param holder * @ param previewRate */public void doStartPreview (SurfaceHolder holder, float previewRate) {Log. I (TAG, "doStartPreview... "); if (isPreviewing) {mCamera. stopPreview (); return;} if (mCamera! = Null) {try {mCamera. setPreviewDisplay (holder);} catch (IOException e) {// TODO Auto-generated catch blocke. printStackTrace ();} initCamera (previewRate);}/** use TextureView to preview Camera * @ param surface * @ param previewRate */public void doStartPreview (SurfaceTexture surface, float previewRate) {Log. I (TAG, "doStartPreview... "); if (isPreviewing) {mCamera. stopPreview (); return;} if (mCamera! = Null) {try {mCamera. setPreviewTexture (surface);} catch (IOException e) {// TODO Auto-generated catch blocke. printStackTrace ();} initCamera (previewRate );}}
Surfaceview and TextureView preview are displayed respectively. We can see that the input parameters are different, and the initCamera () items are the same.

Private void initCamera (float previewRate) {if (mCamera! = Null) {mParams = mCamera. getParameters (); mParams. setPictureFormat (PixelFormat. JPEG); // set the image format stored after the photo is taken. // CamParaUtil. getInstance (). printsupppicpicturesize (mParams); // CamParaUtil. getInstance (). printSupportPreviewSize (mParams); // set PreviewSize and PictureSizeSize pictureSize = CamParaUtil. getInstance (). getPropPictureSize (mParams. getSupportedPictureSizes (), previewRate, 800); mParams. setPictureSize (pictureSize. width, pictureSize. height); Size previewSize = CamParaUtil. getInstance (). getPropPreviewSize (mParams. getSupportedPreviewSizes (), previewRate, 800); mParams. setPreviewSize (previewSize. width, previewSize. height); mCamera. setDisplayOrientation (90); // CamParaUtil. getInstance (). printSupportFocusMode (mParams); List <String> focusModes = mParams. getSupportedFocusModes (); if (focusModes. contains ("continuous-video") {mParams. setFocusMode (Camera. parameters. FOCUS_MODE_CONTINUOUS_VIDEO);} mCamera. setParameters (mParams); mCamera. startPreview (); // enable isPreviewing = true; mPreviwRate = previewRate; mParams = mCamera. getParameters (); // get the Log again. I (TAG, "final setting: PreviewSize -- With =" + mParams. getPreviewSize (). width + "Height =" + mParams. getPreviewSize (). height); Log. I (TAG, "final settings: PictureSize -- With =" + mParams. getPictureSize (). width + "Height =" + mParams. getPictureSize (). height );}}

4. In the Activity, we still open a thread to open Camera:

Thread openThread = new Thread(){@Overridepublic void run() {// TODO Auto-generated method stubCameraInterface.getInstance().doOpenCamera(CameraActivity.this);}};openThread.start();

Open the preview in the callback after the Camera Open:

@Overridepublic void cameraHasOpened() {// TODO Auto-generated method stubSurfaceTexture surface = textureView._getSurfaceTexture();CameraInterface.getInstance().doStartPreview(surface, previewRate);}

After that, it will run normally. We can see that the changes to Surfaceview preview Camera are very small.


Several notes:

1. TextureView is added after Android 4.0. Is it a lower version. TextureView must work in the environment where hardware acceleration is enabled, that is, the setting item of Activity in the configuration file: android: hardwareAccelerated = "true". By default, this property is true, therefore, you do not need to write any more. But if it is written as false, we can see that the onSurfaceTextureAvailable () callback cannot be entered, and the TextureView does not have SurfaceTexture.

2. In this demo, open camera and preview the normal log:

Line 417: 06-22 12:37:43. 682 I/yanzi (4917): Camera open .... line 489: 06-22 12:37:43. 758 I/yanzi (4917): onSurfaceTextureAvailable... line 533: 06-22 12:37:43. 819 I/yanzi (4917): Camera open over .... line 535: 06-22 12:37:43. 819 I/yanzi (4917): doStartPreview... line 537: 06-22 12:37:43. 825 I/yanzi (4917): PictureSize: w = 1280 h = 720 Line 539: 06-22 12:37:43. 825 I/yanzi (4917): PreviewSize: w = 800 h = 448 Line 555: 06-22 12:37:43. 874 I/yanzi (4917): final setting: PreviewSize -- With = 800 Height = 448 Line 557: 06-22 12:37:43. 874 I/yanzi (4917): final setting: PictureSize -- With = 1280 Height = 720 Line 577: 06-22 12:37:44. 106 I/yanzi (4917): onSurfaceTextureUpdated... line 579: 06-22 12:37:44. 138 I/yanzi (4917): onSurfaceTextureUpdated... line 583: 06-22 12:37:44. 169 I/yanzi (4917): onSurfaceTextureUpdated... line 585: 06-22 12:37:44. 220 I/yanzi (4917): onSurfaceTextureUpdated... line 587: 06-22 12:37:44. 253 I/yanzi (4917): onSurfaceTextureUpdated...

The test mobile phone is ZTE Geek. This mobile phone Camera is still awesome. It is better than the Huawei G700, that is, it occasionally cannot connect to the Camera Service and sweat. From the log, it can be seen that the onSurfaceTextureAvailable callback takes some time. Camera. open () uses more than 130 ms. But there are two differences with Surfaceview. First, no onSurfaceTextureSizeChanged () is entered during the creation of TextureView ()In this function. When SurfaceView is created, it will be called back when the size changes from nothing. Second, the onSurfaceTextureUpdated () function comes in every frame of data.. This is the greatest part of Surfaceview. This interface can be used to send the SurfaceTexture to OpenGL for processing. This callback is real-time, rather than two callback methods, such as PreviewCallback of Camera. In terms of time, there is basically one frame of data every 32 ms, that is, 30 frames per second, which is consistent with the Camera performance of the mobile phone.

3. When Camera executes startPreview again, it must ensure that the SurfaceTexture of the TextureView comes up. If the onSurfaceTextureAvailable () callback is not enabled due to some performance reasons, the preview cannot be enabled. In this case, the open and startPreview operations are performed in the onSurfaceTextureAvailable () callback to ensure that nothing is lost.

4. TextureView itself has the getSurfaceTexture () function, and I encapsulate another function:

/* Let the Activity get the SurfaceTexture * @ see android. view. TextureView # getSurfaceTexture () */public SurfaceTexture _ getSurfaceTexture () {return mSurface ;}
MSurface is the SurfaceTexture passed in the onSurfaceTextureAvailable () callback. Test proof: You can call this function directly during preview.

TextureView. getSurfaceTexture () and pass it to Camera: mCamera. setPreviewTexture (surface); the preview is also normal. However, the former is recommended for the following reasons:

A TextureView's SurfaceTexture can be obtained either by invokinggetSurfaceTexture()Or by usingTextureView.SurfaceTextureListener. It is important to know that a SurfaceTexture is available only after the TextureView is attached to a window (andonAttachedToWindow()Has been invoked.) It is therefore highly recommended you use a listener to be notified when the SurfaceTexture becomes available.

SurfaceTexture can be obtained in two ways. We recommend that you use a listener. Because tSurfaceTexture of TextureView is only available when onAttachedToWindow is executed.

5. Relationship between SurfaceTexture and TextureView:

Using a TextureView is simple: all you need to do is get itsSurfaceTexture.SurfaceTextureCan then be used to render content

If TextureView is a painting, SurfaceTexture is the canvas, and the actual rendering carrier is SurfaceTexture.

6. TextureView can perform various changes like a general View. One of them is textureView. setAlpha (1.0f). By default, this sentence is not written, and its alpha is 1.0f, that is, opacity. If it is set to transparent 0.0f, nothing can be seen. This is the opposite of Surfaceview. Surfaceview SurfaceHolder generally needs to set the Transparent to Transparent. However, because TextureView is a view, the transparency of any png image is set to 0, and nothing can be seen.

7. If you think that previewing a Camera is the mission of TextureView and SurfaceTexture, it is a big mistake. The true intention is to seamlessly connect with OpenGL.

-------------------- This article is original. For more information, see the author yanzi1225627.

Version: playcamera_v2.0.0[2014-6-222.16.zip

CSDN download link: http://download.csdn.net/detail/yanzi1225627/7540903

Baidu cloud Disk:



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.