2016-07-22 133 views
0

於是,我就實現消費者 - 在Android的場景製作模式是這樣的:ArrayBlockingQueue總是返回true

public class CameraPreview extends SurfaceView ... { 

    ....... 

    public ArrayBlockingQueue<ByteBuffer> mProcessingQueue; 

    public CameraPreview(){ 
      mProcessingQueue = new ArrayBlockingQueue<ByteBuffer>(10); 
      HandlerThread handlerThread = new HandlerThread("Image Processing Thread"); 
      handlerThread.start(); 
      Handler handler = new Handler(handlerThread.getLooper()); 
      handler.post(new Runnable() { 
       @Override 
       public void run() { 
        new ImageProcessingThread().start(); 
       } 
      }); 
     } 


    public void onPreviewFrame(final byte[] data, Camera camera){ 

      ....... 

      if(!mProcessingQueue.offer(byteBuffer)) { 
       byteBuffer.clear(); 
       Log.v("IMAGE_AVOIDED", count + ""); 
      } else { 
       Log.v("IMAGE_PUSHED", count + ""); 
      } 

    } 

    public void processImage(ByteBuffer image){ 

      .. call to opencv jni function .. 

    } 

    public class ImageProcessingThread extends Thread{ 
      int count = 0; 

      @Override 
     public void run() { 
      super.run(); 

      while(mImageProcessingRunning){ 
       try { 
        ByteBuffer image = mProcessingQueue.take(); 
        Log.v("IMAGE_TAKEN", count++ + ""); 
        processImage(image); 
        image.clear(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

} 

然而,當我運行此代碼..它永遠不會產生IMAGE_AVOIDED日誌語句..它在IMAGE_TAKEN和IMAGE_PUSHED之間交替..一幀被推動..和一個幀處理..

我希望我能夠不斷地將幀放入mProcessingQueue,並且當消費者線程準備就緒時,從隊列中取出..這樣我可以丟棄幀,如果隊列已滿,只有將最新的幀放入隊列中才能更接近於re時間..

我敢肯定它的同步問題..也許我在一個進程中運行相同的兩個線程,因此調度程序希望來回通過任務?

任何想法/指針?

+1

聽起來像消費者線程的處理速度足夠快,隊列永遠不會填滿... – wakjah

+0

我在想,但它不能,生產者應該運行30 fps可能接近20給定的時間來填充數據的ByteBuffer,並且執行JNI代碼的時間肯定比實時慢 – Arjun

+0

在消費者方法中引入睡眠或掛起以確保隊列已滿,並查看會發生什麼。 – Bex

回答

0

所以事實證明,上面的實現是正確的..但是我在onPreviewFrame函數調用中做了一些計算..這給消費者線程足夠的時間來執行手頭的工作..謝謝大家!