2016-08-19 9 views
1

나는 우리의 애플 리케이션의 프레임 추출을 개선하기 위해 노력하고있어. 기본적으로 전 탐색을 위해 Grafika의 MoviePlayer과 BigFlake의 ExtractMpegFramesTest에서 프레임을 추출하는 솔루션을 결합했습니다. 추출을 위해 이전 키 프레임으로 돌아가서 앞으로 디코딩하고 마지막 프레임 만 저장합니다.Android MediaCodec이 동시에 두 서피스로 디코딩 할 수 있습니까?

decoder.releaseOutputBuffer(decoderStatus, doRender); 
    if (doRender) { 
     if (VERBOSE) Log.d(TAG, "awaiting decode of frame " + decodeCount); 
     outputSurface.awaitNewImage(); 
     outputSurface.drawImage(false); 

     if(extractor.getSampleTime() == mPosition){ 
      Log.d(TAG, "sampleTime: " + extractor.getSampleTime() + " mPosition: " + mPosition + "----- EXTRACTING FRAME"); 
      long startWhen = System.currentTimeMillis(); 
      outputSurface.saveFrame(); 
      long frameSaveTime = System.currentTimeMillis() - startWhen; 
      Log.d(TAG, "sampleTime: frame saved in: " + frameSaveTime + " millisecond"); 
      return; 
     } 
     decodeCount++; 
    } 

문제 때때로 똑바로 앞으로의 하나와 일치하지 않는 것 뒤로 다음 앞으로 디코딩하고자하는 경우 extractor.getSampleTime()에서 검색 샘플 시간이 같은 뭔가 (내 previous question보다 완전한 설명은 참조) 추구.

나는이 명확하게하기 위해 로그를 포함 시켰습니다 : 당신이 볼 수 있듯이

position is the seeking position in microsecond 
sampleTime: 12112100 -- position: 12139000 ----- FORWARD 
sampleTime: 12120441 -- position: 12139000 ----- FORWARD 
sampleTime: 12128783 -- position: 12139000 ----- FORWARD 
sampleTime: 12137125 -- position: 12139000 ----- FORWARD 

sampleTime: 12012000 -- position: 12139000 ----- BACKWARD 
sampleTime: 12020341 -- position: 12139000 ----- BACKWARD 
sampleTime: 12028683 -- position: 12139000 ----- BACKWARD 
sampleTime: 12037025 -- position: 12139000 ----- BACKWARD 
sampleTime: 12045366 -- position: 12139000 ----- BACKWARD 
sampleTime: 12053708 -- position: 12139000 ----- BACKWARD 
sampleTime: 12062050 -- position: 12139000 ----- BACKWARD 
sampleTime: 12070391 -- position: 12139000 ----- BACKWARD 
sampleTime: 12078733 -- position: 12139000 ----- BACKWARD 
sampleTime: 12087075 -- position: 12139000 ----- BACKWARD 
sampleTime: 12095416 -- position: 12139000 ----- BACKWARD 
sampleTime: 12103758 -- position: 12139000 ----- BACKWARD 
sampleTime: 12112100 -- position: 12139000 ----- BACKWARD 
sampleTime: 12120441 -- position: 12139000 ----- BACKWARD 
sampleTime: 12128783 -- position: 12139000 ----- BACKWARD 

, 앞으로의 extractor.getSampleTime()을 추구하는 것은 앞으로 디코딩 다시 추구하면서 12137125 위치를 도달 할 수 있습니다, 그것은 단지에 도달 할 수 있습니다 12128783. 왜 그런 일이 발생하는지 모르겠지만 표현 프레임과 추출 된 프레임이 일치하지 않습니다. 또한이 방법은 프레임을 추출해야 할 때마다 EGLSurface을 설정하고 디코드해야하므로 매우 효율적이지 않습니다. 이전 키 프레임에서 필요한 프레임까지의 거리에 따라이 작업을 수행하는 데 3-5 초가 소요될 수 있습니다.

디코더를 양면으로 디코딩 할 수 있는지 (듀얼 디스플레이를 위해 SurfaceView, 프레임 검색을 위해 EGLSurface) 동시에이 정확성과 성능 문제를 모두 해결할 수 있는지 묻고 싶습니다.

FFmpeg를 사용하여 이전에 프레임을 검색해 보았습니다. 성능은 거의 같습니다. OpenGL을 사용하는 것보다 프레임을 검색하는 더 좋은 방법이 있다면, 나는 매우 기꺼이 노력할 것입니다.

편집 : 검색된 프레임이 때때로 표시 프레임과 일치하지 않을 수도 있지만 추가 테스트 후 두 방법 모두 extractor.getSampleTime()을 일치시킬 수 있습니다. EDIT 2

: 표시된 프레임 추출 프레임 사이의 불일치에 대해서는, 실제로는 매우 간단하지만 당신은 어떻게 MediaCodec 일을 모르는 경우 처음에는 매우 혼란. 문제를 더 잘 이해하기 위해 모든 fadden의 의견을 다시 읽어야합니다 (this은 저에게 "ah ha"의 순간입니다). 요컨대, 디코더는 임의의 표현 버퍼를 뱉기 전에 다중 버퍼를 소비하는 것을 좋아합니다. 따라서 현재 표시되는 것은 현재 extractor.getSampleTime() 위치에있는 것과 동일하지 않습니다. 그래서 올바른 값을 표시하고 출력 버퍼의 presentationTime, 이런 식으로 뭔가해야 추출간에 동기화 할 :

mCurrentSampleTime = mBufferInfo.presentationTimeUs;

많은 상기 제 1 프레임이없는 이유를 여러 신비 질문 (이 해결하는 데 도움 이해 0 위치에?). 희망이 사람을 도울 것입니다.

답변

1

내 질문에 대한 구체적인 대답은 아니지만 프레임 추출 시간을 향상시키는 방법을 찾았습니다.이 PNG에서 같은 대신 순수한 소프트웨어 압축의 하드웨어 가속을 사용합니다

outputBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);

과 : 당신이 형식에 대한 PNG에 대한 어떤 엄격한 요구 사항이없는 경우 기본적으로 다음 그냥이 같은 jpeg로 출력 이미지를 압축 상당히 빠릅니다. 나는 전체 작동을 위해 ~ 600ms를 얻고 있으며, 압축 비트는 ~ 200ms 정도 소요됩니다. 이는 이전의 5 초에서 매우 큰 개선이며, PNG 압축을 사용합니다.

이론적으로 투명성에 신경 쓰지 않는다면 Bitmap.Config.ARGB_8888 대신에 출력 이미지에 Bitmap.Config.RGB_565을 사용하면 더 많은 성능을 얻을 수 있습니다. 그러나 실제로 나는 이렇게하지 못하게하는 2 가지 문제를 겪는다 :

  • 출력 이미지의 색이 엉망이된다.
  • 실제로 이미지를 추출하는 데 더 오래 걸립니다.