2016-05-29 4 views
1

Ich stoße auf das große Problem.BebopVideoView zu Mat

Ich versuche BebopVideoView zu Mat. (BebopVideoView ist Papagei Drohne Quellcode)

Aber ich war für mehrere Tage fehlgeschlagen.

Hier ist der Code.

package com.hyeonjung.dronecontroll.view; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Rect; 
import android.media.MediaCodec; 
import android.media.MediaFormat; 
import android.os.Environment; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

import com.parrot.arsdk.arcontroller.ARCONTROLLER_STREAM_CODEC_TYPE_ENUM; 

import com.parrot.arsdk.arcontroller.ARControllerCodec; 
import com.parrot.arsdk.arcontroller.ARFrame; 

import org.opencv.core.CvType; 
import org.opencv.core.Mat; 
import org.opencv.imgcodecs.Imgcodecs; 
import org.opencv.imgproc.Imgproc; 

import java.io.File; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

public class BebopVideoView extends SurfaceView implements SurfaceHolder.Callback { 

    private static final String TAG = "BebopVideoView"; 
    private static final String VIDEO_MIME_TYPE = "video/avc"; 
    private static final int VIDEO_DEQUEUE_TIMEOUT = 33000; 

    private MediaCodec mMediaCodec; 
    private Lock mReadyLock; 

    private boolean mIsCodecConfigured = false; 

    private ByteBuffer mSpsBuffer; 
    private ByteBuffer mPpsBuffer; 

    private ByteBuffer[] mBuffers; 

    private static final int VIDEO_WIDTH = 640; 
    private static final int VIDEO_HEIGHT = 368; 

    public byte[] a; 
    public Mat k; 


    public BebopVideoView(Context context) { 
     super(context); 
     customInit(); 
    } 

    public BebopVideoView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     customInit(); 
    } 

    public BebopVideoView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     customInit(); 
    } 

    private void customInit() { 
     mReadyLock = new ReentrantLock(); 
     getHolder().addCallback(this); 
    } 

    public void displayFrame(ARFrame frame) { 
     mReadyLock.lock(); 

     if ((mMediaCodec != null)) { 
      if (mIsCodecConfigured) { 
       // Here we have either a good PFrame, or an IFrame 
       int index = -1; 

       try { 
        index = mMediaCodec.dequeueInputBuffer(VIDEO_DEQUEUE_TIMEOUT); 
       } catch (IllegalStateException e) { 
        Log.e(TAG, "Error while dequeue input buffer"); 
       } 
       if (index >= 0) { 
        ByteBuffer b; 
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { 
         b = mMediaCodec.getInputBuffer(index); // fill inputBuffer with valid data 
        } 
        else { 
         b = mBuffers[index]; // fill inputBuffer with valid data 
         b.clear(); 
        } 

        if (b != null) { 
         b.put(frame.getByteData(), 0, frame.getDataSize()); //write to b. 
         getMat(frame); 
         saveMat(k); 
        } 

        try { 
         mMediaCodec.queueInputBuffer(index, 0, frame.getDataSize(), 0, 0); //end of stream 
        } catch (IllegalStateException e) { 
         Log.e(TAG, "Error while queue input buffer"); 
        } 
       } 
      } 

      // Try to display previous frame 
      MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 
      int outIndex; 
      try { 
       outIndex = mMediaCodec.dequeueOutputBuffer(info, 0); 

       while (outIndex >= 0) { 
        mMediaCodec.releaseOutputBuffer(outIndex, true); 
        outIndex = mMediaCodec.dequeueOutputBuffer(info, 0); 
       } 
      } catch (IllegalStateException e) { 
       Log.e(TAG, "Error while dequeue input buffer (outIndex)"); 
      } 
     } 


     mReadyLock.unlock(); 
    } 

    public void configureDecoder(ARControllerCodec codec) { 
     mReadyLock.lock(); 

     if (codec.getType() == ARCONTROLLER_STREAM_CODEC_TYPE_ENUM.ARCONTROLLER_STREAM_CODEC_TYPE_H264) { 
      ARControllerCodec.H264 codecH264 = codec.getAsH264(); 

      mSpsBuffer = ByteBuffer.wrap(codecH264.getSps().getByteData()); 
      mPpsBuffer = ByteBuffer.wrap(codecH264.getPps().getByteData()); 
     } 

     if ((mMediaCodec != null) && (mSpsBuffer != null)) { 
      configureMediaCodec(); 
     } 

     mReadyLock.unlock(); 
    } 

    private void configureMediaCodec() { 
     MediaFormat format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, VIDEO_WIDTH, VIDEO_HEIGHT); 
     format.setByteBuffer("csd-0", mSpsBuffer); 
     format.setByteBuffer("csd-1", mPpsBuffer); 

     mMediaCodec.configure(format, getHolder().getSurface(), null, 0); 
     mMediaCodec.start(); 

     if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) { 
      mBuffers = mMediaCodec.getInputBuffers(); 
     } 

     mIsCodecConfigured = true; 
    } 

    private void initMediaCodec(String type) { 
     try { 
      mMediaCodec = MediaCodec.createDecoderByType(type); 
     } catch (IOException e) { 
      Log.e(TAG, "Exception", e); 
     } 

     if ((mMediaCodec != null) && (mSpsBuffer != null)) { 
      configureMediaCodec(); 
     } 
    } 

    private void releaseMediaCodec() { 
     if (mMediaCodec != null) { 
      if (mIsCodecConfigured) { 
       mMediaCodec.stop(); 
       mMediaCodec.release(); 
      } 
      mIsCodecConfigured = false; 
      mMediaCodec = null; 
     } 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     mReadyLock.lock(); 
     initMediaCodec(VIDEO_MIME_TYPE); 
     mReadyLock.unlock(); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     mReadyLock.lock(); 
     releaseMediaCodec(); 
     mReadyLock.unlock(); 
    } 

    public void getMat(ARFrame frame) { 
     k = new Mat(); 

     k.get(150, 150, frame.getByteData()); 
     k.put(150, 150, frame.getByteData()); 

     //or 
     //byte[] a= new byte[b.remaining()]; 
     //b.get(a); 
     //k.get(150, 150, a); 
     //k.put(150, 150, a); 

    } 

    public void saveMat (Mat mat) { 
     Mat mIntermediateMat = new Mat(150, 150, CvType.CV_8UC1); 
     Imgproc.cvtColor(mat, mIntermediateMat, Imgproc.COLOR_GRAY2BGR); 

     File path = new File(Environment.getExternalStorageDirectory() + "/data"); 
     path.mkdirs(); 
     File file = new File(path, "image.png"); 
     String filename = file.toString(); 
     Boolean bool = Imgcodecs.imwrite(filename, mIntermediateMat); 

     if (bool) 
      Log.i(TAG, "SUCCESS writing image to external storage"); 
     else 
      Log.i(TAG, "Fail writing image to external storage"); 
    } 

} 

Ich glaube, ich kann ein Bild bezogene Daten von ByteBuffer b oder frame.get ByteData() erhalten.

Ich wurde bestätigt ByteBuffer b und frame.getByteData().

Es war char-Datentyp mit einem Bereich von -128 bis 127

So wurde ich das Ergebnis von getMat, saveMat bestätigt und das Ergebnis war eine NULL (Mat k).

Was ist los?

Bitte helfen Sie mir T.T

Antwort

0

Wenn Sie eine TextureView verwenden Sie einfach eine Bitmap, es greifen und es zu einer Matte konvertieren. Sie müssen die von TextureView bereitgestellte Oberfläche anstelle des typischen SurfaceView-Halters verwenden. Dies erfordert ein zusätzliches Refactoring des mediaCodec-Lebenszyklus, ist aber eine ziemlich geringfügige Änderung.

public class BebopVideoView extends TextureView implements TextureView.SurfaceTextureListener { 

    @Override 
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
     this.surface = new Surface(surface); 
     surfaceCreated = true; 
    } 

... 

} 

Und innerhalb von configureMediaCodec die Klasse ebene Fläche statt in onSurfaceTextureAvailable gefangen verwenden ....

mediaCodec.configure(format, surface, null, 0); 

mit einem paar anderen kleineren Verbesserungen Sie jetzt viel mehr Kontrolle über die Aussicht. Sie können Dinge tun, wie SetTransform() und noch wichtiger in Ihrem Fall getBitmap:

Mat mat = new Mat(); 
Utils.bitmapToMat(getBitmap(), mat); 
+0

OMG .. Vielen Dank. Ich werde es nochmal versuchen und kommentieren. – kimms

+0

Das Beste, was Sie tun können, ist, meine Antwort als Lösung zu markieren und/oder auszuwählen. Vielen Dank. – ShellDude