TextureView с декодером MediaCodec для потоков H264
Это дополнительный вопрос этого вопроса.
Это мое TextureView
код:
public class VideoTextureView extends TextureView implements SurfaceTextureListener{
private static final String LOG_TAG = VideoTextureView.class.getSimpleName();
private MediaCodecDecoder mMediaDecoder;
private MediaCodecAsyncDecoder mMediaAsyncDecoder;
public VideoTextureView(Context context, AttributeSet attrs) {
super(context, attrs);
setSurfaceTextureListener(this);
Log.d(LOG_TAG, "Video texture created.");
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Log.d(LOG_TAG, "Surface Available: " + width + " x " + height);
mMediaDecoder = new MediaCodecDecoder();
mMediaDecoder.Start();
mMediaDecoder.SetSurface(new Surface(getSurfaceTexture()));
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mMediaDecoder.Stop();
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// TODO Auto-generated method stub
}
}
Мой вопрос - это мой TextureView
реализация в порядке для рендеринга потоков H264, декодированных MediaCodec
? Или мне нужно сделать настройку EGL или еще что-нибудь?
Заранее спасибо!
2 ответа
Мой TextureView
реализация в порядке, как я пытался с SurfaceView
тоже и нашел такой же результат. И как сказал @fadden -
Настройка EGL требуется только при рендеринге с GLES. TextureView сочетает в себе SurfaceTexture с пользовательским представлением и выполняет визуализацию GLES для вас. Вот почему представление должно быть аппаратно ускорено, чтобы TextureView работал.
Благодаря @fadden.
В настоящее время я использую TextureView для рендеринга нескольких потоков в одном действии с использованием ячеек представления коллекции на Android (извините за терминологию ios там).
Он работает нормально, но проблема в том, что когда вы, например, поворачиваете устройство, будет Surface_destroyed, а затем Surface_available. Как я вижу, вы правильно останавливаете и запускаете свой декодер.
Одна вещь, которую я делаю в своем декодере:
List<NaluSegment> segments = NaluParser.parseNaluSegments(buffer);
for (NaluSegment segment : segments) {
// ignore unspecified NAL units.
if (segment.getType() != NaluType.UNSPECIFIED) {
// Hold the parameter set for stop/start initialization speed
if (segment.getType() == NaluType.PPS) {
lastParameterSet[0] = segment;
} else if (segment.getType() == NaluType.SPS) {
lastParameterSet[1] = segment;
} else if (segment.getType() == NaluType.CODED_SLICE_IDR) {
lastParameterSet[2] = segment;
}
// add to input queue
naluSegmentQueue.add(segment);
}
}
Я держу последние наборы параметров и последний ключевой кадр, и при запуске я заполняю naluSegmentQueue этими первыми, чтобы уменьшить задержку при рендеринге видео.