2015-10-05 75 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

相關問題