Я пытаюсь разработать следующие модули в конвейере:
[Receive data on Socket]
|
buffer1
|
v
[Async Decode Frame]
|
buffer2
|
v
[Async Render to FBO-Texture-pair]
|
buffer3
|
v
[Display_on_screen]
* Обозначения: [] указывают модули, буфер * указывает промежуточные буферы
- Каждый модуль работает в отдельном потоке.
- Не все данные (или кадры), принятые в buffer1, будут декодированы и отправлены в buffer2
- Не все декодированные выходные кадры в буфере 2 будут отображаться в
(FBO-текстура) с
- Не все визуализированные FBO-текстуры в буфере3 будут
отображается на экране.
Я знаю, что это своего рода исключительный случай использования, но я управляю объектами буфера в разных буферах, используя понятие пула памяти, чтобы избежать выделения памяти и повысить производительность.
Чтобы реализовать [Async Decode Frame], я изучил примеры асинхронного декодера Android MediaCodec и ниже я имею в виду один из них с вопросом (Q1), встроенными комментариями.
Предположим, что следующий фрагмент кода является частью потока [Async Decode Frame]:
MediaCodec codec = MediaCodec.createByCodecName(name);
MediaFormat mOutputFormat; // member variable
codec.setCallback(new MediaCodec.Callback() {
@Override
void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
// fill inputBuffer with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
@Override
void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
// bufferFormat is equivalent to mOutputFormat
// outputBuffer is ready to be processed or rendered.
// Q1. Will this logic work and efficient?
// send outputBuffer to [Async-Render to FBO-Texture-pair] handler
// when done, send message to DecoderThreadHandler/[Async Decode Frame] to release outputBufferId
}
@Override
void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
mOutputFormat = format; // option B
}
@Override
void onError(…) {
…
}
});
codec.configure(format, …);
mOutputFormat = codec.getOutputFormat(); // option B
codec.start();
// wait for processing to complete
codec.stop();
codec.release();
Вопросы
- Будет ли вопрос (размещен в строке) визуализировать (в FBO-Texture-pair) в отдельном потоке будет эффективным или есть лучший подход?
- Как видите, я пытаюсь избежать рендеринга в Surface, не вызывая
codec.releaseOutputBuffer(outputBufferId, ...)
в onOutputBufferAvailable()
callback. Основная причина для этого состоит в том, что я могу не рендерить все декодированные кадры, поскольку я могу отбросить некоторые декодированные кадры и освободить соответствующие объекты обратно в соответствующий пул памяти. Другая причина избегать рендеринга в Surface объясняется в этой ссылке , которая предполагает, что мой поток рендеринга может непреднамеренно пропустить определенные кадры, если поток декодирования работает слишком быстро. Будет ли этот подход работать хорошо?
- В этом блоге сообщение предлагает скопировать данные из outputBufferId декодера во временный буфер, однако вариант использования отличается от моего, и я не уверен, стоит ли использовать то же самое. Я запутался здесь в основном потому, что не хочу делать ненужный пинг-понг между GPU-памятью в смартфонах (если есть) и оперативной памятью.
Любое предложение высоко ценится. Дайте мне знать, если вам понадобятся дальнейшие разъяснения.