Я пытаюсь декодировать mp4 с помощью MediaCode c и отображать его с помощью GLSurfaceView. В MediaCode c configure () я передаю созданную Surface с SurfaceTexture. В SurfaceTexture я вызываю Listener и синхронизирую его в методе OnDrawFrame и вызываю surfacetexture.upadteTexImage (); Результатом является surfaceTexture.updateTexImage () для пустой ссылки на объект. Мне интересно, как это вообще возможно? Так как слушатель выдает сообщение о наличии кадра, как он может вернуть ноль? Должен сказать, что у меня вообще проблема с настройкой MediaCode c с OpenGlES. Сначала я думал, что это из-за декодера устройства Samsung, но когда я попытался декодировать в SurfaceView, он работал хорошо.
SurfaceTexture surfaceTexture = new SurfaceTexture(textures[1]);
surface = new Surface(surfaceTexture);
surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
synchronized (mediaPlayerObject) {
mediaPlayeUpdate = true;
mediaPlayerObject.notifyAll();
}
}
});
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT);
synchronized (mediaPlayerObject) {
surfaceTexture.updateTexImage();
mediaPlayeUpdate = false;
}
И я вызываю это на SurfaceChanged (GL ...)
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void run() {
mediaExtractor = new MediaExtractor();
try {
mediaExtractor.setDataSource("sdcard/nagranie2.mp4");
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
mediaExtractor.selectTrack(i);
try {
decoder = MediaCodec.createDecoderByType(mime);
} catch (IOException e) {
e.printStackTrace();
}
decoder.configure(format, surface, null, 0);
break;
}
}
if (decoder == null) {
Log.e("DecodeActivity", "Can't find video info!");
return;
}
decoder.start();
ByteBuffer[] decoderInputBuffers = decoder.getInputBuffers();
ByteBuffer[] decoderOutputBuffers = decoder.getOutputBuffers();
MediaCodec.BufferInfo info1 = new MediaCodec.BufferInfo();
boolean isOES = false;
long startMs = System.currentTimeMillis();
while (!Thread.interrupted()) {
if (!isOES) {
int intBufIndex = decoder.dequeueInputBuffer(10000);
if (intBufIndex >= 0) {
ByteBuffer inputBuffer = decoderInputBuffers[intBufIndex];
int chunkSize = mediaExtractor.readSampleData(inputBuffer, 0);
if (chunkSize < 0) {
decoder.queueInputBuffer(intBufIndex, 0, 0, 0L, decoder.BUFFER_FLAG_END_OF_STREAM);
isOES = true;
} else {
decoder.queueInputBuffer(intBufIndex, 0, chunkSize, mediaExtractor.getSampleTime(), 0);
mediaExtractor.advance();
}
}
}
int decoderStatus = decoder.dequeueOutputBuffer(info1, 10000);
switch (decoderStatus)
{
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
decoderOutputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
ByteBuffer byteBuffer = decoderOutputBuffers[decoderStatus];
/* while (info1.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
decoder.releaseOutputBuffer(decoderStatus, true);
break;
}
if ((info1.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
}
decoder.stop();
decoder.release();
mediaExtractor.release();
}