2015-10-05 89 views
0

我试图制作一个通过互联网广播视频的应用程序,目前我使用弃用的Camera API,将Camera.PreviewCallback添加到Camera对象,然后发送进来的字节数组Camera.PreviewCallback中的onPreviewFrame()方法。使用Android的Camera2 API进行视频广播

但现在我想测试新Camera2 API,我看在Camera2BasicTutorial,我认为我需要做一个CameraCaptureSession.CaptureCallback对象来获取图像的字节数组,类似的教程说:

CameraCaptureSession.CaptureCallback CaptureCallback 
       = new CameraCaptureSession.CaptureCallback() { 

      @Override 
      public void onCaptureCompleted(@NonNull CameraCaptureSession session, 
              @NonNull CaptureRequest request, 
              @NonNull TotalCaptureResult result) { 
       showToast("Saved: " + mFile); 
       Log.d(TAG, mFile.toString()); 
       unlockFocus(); 


      } 
     }; 

然后将其添加到CameraCaptureSession:

mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null); 

的问题是,我不知道如何从任何onCaptureCompleted()的参数从CaptureCallback的检索每个图像的字节数组。

任何帮助?

+0

https://sites.google.com/site/averagelosercom/android/android-camera-api-v2-preview – Sree

回答

0

至少我意识到怎么做我想要的东西,从Camera2BasicTutorial,我做了如下修改Camera2BasicFragment类:

  1. 修改captureStillPicture()方法来删除,我确定这是不必要的东西我的广播的需求,也不允许这种方法停止重复模式:

    private void captureStillPicture() { 
    try { 
        final Activity activity = getActivity(); 
        if (null == activity || null == mCameraDevice) { 
         return; 
        } 
    
        final CaptureRequest.Builder captureBuilder = 
          mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
        captureBuilder.addTarget(mImageReader.getSurface()); 
    
        CameraCaptureSession.CaptureCallback CaptureCallback 
          = new CameraCaptureSession.CaptureCallback() { 
    
         @Override 
         public void onCaptureCompleted(@NonNull CameraCaptureSession session, 
                 @NonNull CaptureRequest request, 
                 @NonNull TotalCaptureResult result) { 
         } 
        }; 
    
        mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null); 
    } catch (CameraAccessException e) { 
        e.printStackTrace(); 
    } 
    } 
    
  2. 在createCameraPreviewSession()方法,禁用闪光灯automaticall:

    // When the session is ready, we start displaying the preview. 
            mCaptureSession = cameraCaptureSession; 
            try { 
             // Auto focus should be continuous for camera preview. 
             mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, 
               CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 
             // Flash is automatically enabled when necessary. 
    // mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, 
    // CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 
    
             // Finally, we start displaying the camera preview. 
             mPreviewRequest = mPreviewRequestBuilder.build(); 
             mCaptureSession.setRepeatingRequest(mPreviewRequest, 
               mCaptureCallback, mBackgroundHandler); 
            } catch (CameraAccessException e) { 
             e.printStackTrace(); 
            } 
    
  3. 我创建了一个布尔变量来检测当前正在处理的图像是否不包含相机捕获的所有帧;和跟踪另一个布尔如果存在通过因特网发送的帧:

    private boolean mWorking = false; 
    private boolean mNetworkWorking = false; 
    
  4. 修改CaptureCallback对象运行在每个帧中(只有当没有帧处理的时刻)的captureStillPicture()方法。

      case STATE_PREVIEW: { 
    
          if (!mWorking){ 
           Log.d(TAG, "capturing.."); 
           mWorking = true; 
    
           mBackgroundHandler.post(new Runnable() { 
            @Override 
            public void run() { 
             captureStillPicture(); 
            } 
           }); 
    
          } else { 
           Log.d(TAG, "thread working, doing nothing"); 
          } 
    
    
          break; 
    
  5. 最后,读取帧并发送它;我实现了这个修改OnImageAvailableListener对象:

    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener 
        = new ImageReader.OnImageAvailableListener() { 
    
    @Override 
    public void onImageAvailable(final ImageReader reader) { 
    
        // Process the image. 
        Image image = reader.acquireNextImage(); 
        ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
        final byte[] bytes = new byte[buffer.remaining()]; 
        buffer.get(bytes); 
        image.close(); 
    
        if (!mNetworkWorking){ 
         Thread thread = new Thread(){ 
          @Override 
          public void run(){ 
    
           mNetworkWorking = true; 
    
           HttpResponse response = null; 
           HttpClient client = new DefaultHttpClient(); 
           HttpPost post = new HttpPost(mBroadcastUrl); 
           post.setEntity(new ByteArrayEntity(bytes)); 
    
           try { 
            response = client.execute(post); 
           } catch (ClientProtocolException e) { 
            if (BuildConfig.LOCAL_LOG) 
             Log.w(TAG, "ClientProtocolException: "+e.getMessage()); 
           } catch (IOException e) { 
            if (BuildConfig.LOCAL_LOG) 
             Log.w(TAG, "IOException: "+e.getMessage()); 
           } 
    
           mNetworkWorking = false; 
    
          } 
         }; 
    
         thread.setName("networkThread"); 
         thread.setPriority(Thread.MAX_PRIORITY); 
         thread.start(); 
        } 
    
        mWorking = false; 
    
    } 
    
    }; 
    

这就是全部。

+0

我试过你的代码,但它调用onImageAvailable 3次。 – user1154390

0

你是对的 - 你无法从onCaptureCompleted()方法获取图像数据。该回调仅为您自己的簿记返回有关曝光的元数据。实际图像信息会发送到您在曝光CaptureRequest中指示的Surface

+0

请问您能提供更多代码细节吗? – svprdga

+0

这不是一个特定的代码问题,而是对camera2基本框架/系统的理解。这里最好概述:https://developer.android.com/reference/android/hardware/camera2/package-summary。html 当涉及到图像数据将出现的实际Surface时,您可能需要使用MediaCodec或MediaRecorder的Surface,而我对这些Surface并不熟悉,因此无法提供代码示例。 – rcsumner