Во-первых, спасибо, что нашли время прочитать это. Мне нужна помощь или понимание, поскольку я сталкиваюсь с проблемой декодирования кадров h264. Я публикую этот вопрос, так как большинство других связанных с ним сообщений не содержат четких шагов. Я поделился кодом для потока декодера, который получил основной лог c. Я получаю sps, pps и данные из сети, и, таким образом, я делаю этот флаг mConfigured
как истинный, когда sps и pps принимаются и соответствующие массивы подаются. Я могу предоставить больше информации, если это необходимо. PS - Пожалуйста, извините за стандарты кодирования, поскольку это все еще PO C в разработке.
decoder.dequeueOutputBuffer >> всегда возвращает -1
// ниже функции, вызываемой из сети, когда новый пакет получен.
public void decodeAndPlayVideoFrame(byte[] encodedData, int frameType) {
if (frameType == 1) {
SPS = encodedData;
} else if (frameType == 2) {
PPS = encodedData;
} else if (frameType == 0) {
Log.d("EncodeDecode", "enqueueing frame no: " + (frameID));
try {
Frame frame = new Frame(frameID);
int totalDataLength = encodedData.length + SPS.length + PPS.length;
frame.frameData = new byte[totalDataLength];
System.arraycopy(SPS, 0, frame.frameData, 0, SPS.length);
System.arraycopy(PPS, 0, frame.frameData, SPS.length, PPS.length);
System.arraycopy(encodedData, 0, frame.frameData, SPS.length + PPS.length, encodedData.length);
queue.add(frame);
frameID++;
} catch (NullPointerException e) {
Log.e("EncodeDecode", "frame is null");
e.printStackTrace();
} catch (IllegalArgumentException e) {
Log.e("EncodeDecode", "problem inserting in the queue");
e.printStackTrace();
} catch (IllegalStateException e) {
Log.e("EncodeDecode", "problem inserting in the queue");
e.printStackTrace();
}
Log.d("EncodeDecode", "frame enqueued. queue size now: " + queue.size());
}
}
// Поток проигрывателя запускается при запуске экрана и обрабатывает пакеты, поступающие в очередь.
private class PlayerThread extends Thread {
//private MediaExtractor extractor;
private MediaCodec decoder;
private Surface surface;
private boolean mConfigured;
public PlayerThread(Surface surface) {
this.surface = surface;
}
private void initCodec() throws IOException {
MediaFormat mediaFormat = null;
decoder = MediaCodec.createDecoderByType("video/avc");
mediaFormat = MediaFormat.createVideoFormat("video/avc",
320,
240);
try {
decoder.configure(mediaFormat,
surface,
null,
0);
frameID = 0;
mConfigured = true;
decoder.start();
Log.d("EncodeDecode", "DECODER_THREAD:: decoder.start() called");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (SPS == null || PPS == null || SPS.length == 0 || PPS.length == 0) {
try {
Log.d("EncodeDecode", "DECODER_THREAD:: sps,pps not ready yet");
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!mConfigured) {
try {
initCodec();
} catch (IOException e) {
e.printStackTrace();
}
}
int i = 0;
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
while (!Thread.interrupted()) {
Frame currentFrame = null;
try {
Log.d("EncodeDecode", "DECODER_THREAD:: calling queue.take(), if there is no frame in the queue it will wait");
currentFrame = queue.take();
} catch (InterruptedException e) {
Log.e("EncodeDecode", "DECODER_THREAD:: interrupted while PlayerThread was waiting for the next frame");
e.printStackTrace();
}
if (currentFrame == null)
Log.e("EncodeDecode", "DECODER_THREAD:: null frame dequeued");
else
Log.d("EncodeDecode", "DECODER_THREAD:: " + currentFrame.id + " no frame dequeued");
if (currentFrame != null && currentFrame.frameData != null && currentFrame.frameData.length != 0) {
Log.d("EncodeDecode", "DECODER_THREAD:: decoding frame no: " + i + " , dataLength = " + currentFrame.frameData.length);
int inIndex = decoder.dequeueInputBuffer(-1);
if (inIndex >= 0) {
Log.d("EncodeDecode", "DECODER_THREAD:: sample size: " + currentFrame.frameData.length + "->" + currentFrame.frameData[0] + "to" + currentFrame.frameData[currentFrame.frameData.length-1]);
ByteBuffer buffer = inputBuffers[inIndex];
buffer.clear();
buffer.put(currentFrame.frameData);
decoder.queueInputBuffer(inIndex, 0, currentFrame.frameData.length, 0, 0);
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outIndex = decoder.dequeueOutputBuffer(info, 0);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.e("EncodeDecode", "DECODER_THREAD:: INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.e("EncodeDecode", "DECODER_THREAD:: New format " + decoder.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.e("EncodeDecode", "DECODER_THREAD:: dequeueOutputBuffer timed out!");
break;
default:
Log.d("EncodeDecode", "DECODER_THREAD:: decoded SUCCESSFULLY!!!");
ByteBuffer outbuffer = outputBuffers[outIndex];
decoder.releaseOutputBuffer(outIndex, true);
break;
}
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}
decoder.stop();
decoder.release();
mConfigured = false;
}
}