2015-01-28 10 views
6

Próbuję stworzyć aplikację do obsługi kamer, która przetwarza wideo przed nagraniem wideo. Zdecydowałem się użyć Rendrscript do przetwarzania, ponieważ zapewnia on wiele operacji, których chcę użyć. I chcę użyć MediaCodec do kodowania. Znalazłem kilka próbek (w tym Grafika), które pokazują, jak używać GLES do przetwarzania, ale nie znalazłem próbki, która pokazuje, jak to zrobić z RenderScript. Próbując zastąpić GLES z Renderscript Mam następujące pytania:Używanie renderscript do przetwarzania i mediacodec do kodowania

  1. tworzę RenderScript wyjściowy Alokacja z powierzchni wejścia enkodera. W próbce Grafika EGL swapbuffer() służy do wysyłania bufora do kodera. Czy Allocation.ioSend() zrobić to samo?
  2. W języku EGL setPresentationTime() służy do ustawiania znacznika czasu. Jak ustawić znacznik czasu w programie Renderscript: Allocation?
  3. Czy powinienem użyć MediaCodec.queueInputBuffer() zamiast tego, aby przesłać bufor wejściowy i znacznik czasu? W takim przypadku powinienem jeszcze zadzwonić Allocation.ioSend() przed wywołaniem queueInputBuffer?

Odpowiedz

1

Natrafiłem na ten sam problem, a rozwiązaniem, którego używam, jest ustawienie znacznika czasu za pośrednictwem EGL, podobnego do RecordFBOActivity#doFrame. W tym celu pośrednia alokacja służy do wypełnienia luki między RenderScript i OpenGL/EGL.

Zobaczmy przepływ danych jako rurociąg przetwarzający ze stopniami.

Original Pipeline

[Camera] 
    --> [ImageAllocation] 
     --> [RenderScript] 
      --> [MediaCodecSurfaceAllocationForEncoder] 
       --> [MediaCodec] 

W oryginalnym rurociągu wszystkie bufory są przydziały RS.

MediaCodecSurfaceAllocation opiera się na powierzchni zwróconej z kodera, tj. MediaCodec#getSurface().

nowego rurociągu

[Camera] 
    --> [ImageAllocation] 
     --> [RenderScript] 
      --> [IntermediateAllocation] 
       --> [EglWindowSurfaceForEncoder] 
        --> [MediaCodec] 

W nowym rurociągiem istnieją dwa duże zmiany, IntermediateAllocation i EglWindowSurfaceForEncoder

IntermediateAllocation jest przydział SurfaceTexture oparte, podobnie jak ful ekran tekstury blitter stosowanych w CameraCaptureActivity.

EglWindowSurfaceForEncoder otacza powierzchnię wejścia enkodera, podobny do RecordFBOActivity#startEncoder

Kluczem tutaj jest, aby ustawić własny OnFrameAvailableListener.

Kod Konfiguracja

void setup() { 
    mEglWindowSurfaceForEncoder= new WindowSurface(mEglCore, encoderCore.getInputSurface(), true); 

    mFullScreen = new FullFrameRect(
      new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT)); 
    mTextureId = mFullScreen.createTextureObject(); 
    mSurfaceTexture = new SurfaceTexture(mTextureId);  

    Type renderType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript)) 
     .setX(width) 
     .setY(height) 
     .create(); 

    mIntermediateAllocation = Allocation.createTyped(
     renderScript, 
     renderType, 
                   Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT); 

    mIntermediateAllocation .setSurface(surface); 

    mAllocationFromCamera = ... 
} 

OnNewCameraImage

mIntermediateAllocation.copyFrom(mAllocationFromCamera); 

OnFrameAvailableListener

mSurfaceTexture.setOnFrameAvailableListener(
    new SurfaceTexture.OnFrameAvailableListener() { 
     public void onFrameAvailableListener(SurfaceTexture) { 

      //latch the image data from camera 
      mSurfaceTexture.updateTexImage(); 

      // Draw the frame. 
      mSurfaceTexture.getTransformMatrix(mSTMatrix); 
      mFullScreen.drawFrame(mTextureId, mSTMatrix); 

      // latch frame to encoder input 
      mEglWindowSurfaceForEncoder.setPresentationTimes(timestampNanos); 
      mEglWindowSurfaceForEncoder.swapBuffers(); 

     }   
    } 
} 

Powyższy kod musi działać w kontekście EGL (tj. W wątku renderowania OpenGl).

Powiązane problemy