Wie zu verwenden MediaCodec ohne MediaExtractor für H264
Ich MediaCodec ohne die MediaExtractor und ich lese die Datei mit einem FileInputStream. Derzeit ist es nicht funktioniert, es zeigt eine grünlich verschlüsselt Bild auf dem Bildschirm.
Dies ist der ganze Quellcode:
FileInputStream in = new FileInputStream("/sdcard/sample.ts");
String mimeType = "video/avc";
MediaCodec decoder = MediaCodec.createDecoderByType(mimeType);
MediaFormat format = MediaFormat.createVideoFormat(mimeType, 1920, 1080);
byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108 };
byte[] header_pps = { 0, 0, 0, 1, 104, -18, 60, -128 };
format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps));
format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps));
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
format.setInteger("durationUs", 63446722);
decoder.configure(format, surface, null, 0);
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
BufferInfo info = new BufferInfo();
boolean isEOS = false;
long startMs = System.currentTimeMillis();
while (!Thread.interrupted()) {
if (!isEOS) {
int inIndex = decoder.dequeueInputBuffer(1000);
if (inIndex >= 0) {
byte buffer2[] = new byte[18800 * 8 * 8 * 8];
ByteBuffer buffer = inputBuffers[inIndex];
int sampleSize;
sampleSize = in.read(buffer2, 0, 18800 * 4);
buffer.clear();
buffer.put(buffer2, 0, sampleSize);
buffer.clear();
if (sampleSize < 0) {
decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
decoder.queueInputBuffer(inIndex, 0, sampleSize, 0, 0);
}
}
}
int outIndex = decoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d("DecodeActivity", "dequeueOutputBuffer timed out! " + info);
break;
default:
ByteBuffer buffer = outputBuffers[outIndex];
Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer);
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
decoder.releaseOutputBuffer(outIndex, true);
break;
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
break;
}
}
decoder.stop();
decoder.release();
Nutzen, wenn ich die MediaExtractor, funktioniert alles einwandfrei. Ich habe die SPS/PPS-Werte, indem man die MediaFormat bei der Verwendung MediaExtractor. Wenn ich das entfernen der Abschnitt unten, nichts auf dem Bildschirm angezeigt wird.
byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108 };
byte[] header_pps = { 0, 0, 0, 1, 104, -18, 60, -128 };
format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps));
format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps));
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
format.setInteger("durationUs", 63446722);
Was ich bin fehlt? Wie bekomme ich die SPS/PPS-Werte programmgesteuert ohne MediaExtractor?
InformationsquelleAutor der Frage thiagolr | 2013-11-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gehe ich davon aus, das Sie Lesen, eine raw-H. 264-elementary-stream und nicht eine MP4-Datei.
Wie es aussieht, sind die Fütterung von fester Größe Blöcke von Daten an die decoder. Das funktioniert aber nicht. Sie müssen, um eine einzelne access-Einheit in jeder Puffer.
InformationsquelleAutor der Antwort fadden
Zu deiner letzten Frage also wie kann man
SPS
undPPS
Wertebenötigen Sie einen Mechanismus, um die gleichen Lesen aus der Datei.Wenn Sie mit einem
elementary stream
Datei, dann würden Sie brauchen, um eine Analyse der Datei, identifizierenNALU
Header und extrahieren Sie den Inhalt.Wenn Sie
container
- format, werden Sie brauchen, um einen Mechanismus zum Lesen derfile format
descontainer
Typ und die Informationen extrahieren.Wenn Sie eine
streaming
Eingang, dann erhalten Sie die Inhalte von eingehendenSDP
Informationen.Als für Ihren aktuellen code, ich würde empfehlen, die Verkettung der beiden
SPS
undPPS
in einen Puffer und bieten die gleichen der zugrunde liegendencodec
wie unten gezeigtInformationsquelleAutor der Antwort Ganesh