Comment utiliser MediaCodec sans MediaExtractor pour H264

J'ai besoin d'utiliser MediaCodec sans MediaExtractor et je suis en train de lire le fichier à l'aide d'un FileInputStream. Actuellement, il n'est pas de travail, elle montre un verdâtre brouillé l'image sur l'écran.

C'est l'ensemble du code source:

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();

Si j'utilise le MediaExtractor, tout fonctionne bien. J'ai eu la SPS/PPS valeurs en regardant le MediaFormat lors de l'utilisation de MediaExtractor. Si je supprime la section ci-dessous, rien n'est indiqué sur l'écran.

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);

Ce que je suis absent? Comment puis-je obtenir la SPS/PPS valeurs par programmation sans MediaExtractor?

  • pourriez-vous partager avec nous le code corrigé s'il vous plaît??
  • Sont SPS et PPS les valeurs que vous avez utilisé les valeurs standard? Dans mon cas, je suis l'obtention de données sous la forme d'unités NAL, donc je suis à la recherche d'images avec NAL de type 7 et 8 pour les PPS et SPS. Au lieu de cela puis-je utiliser les valeurs ci-dessus directement? Aussi, je ne comprenais pas posté de répondre clairement. Pouvez-vous expliquer quel était exactement le problème avec votre code? Je suis en utilisant ce code comme une référence pour mon scénario.
  • Non, chaque flux a son propre SPS/PPS valeurs, vous devriez le faire comme vous l'avez mentionné ci-dessus. Le problème est que j'ai été l'envoi de MediaCodec (queueInputBuffer) fixe la taille de la mémoire tampon (avec la taille 18800 * 4), mais au lieu de cela vous devez envoyer des images vidéo seulement. Il est clair maintenant?
  • Il y a un moyen d'exclure MediaExtractor et mettre byte[] cadre (un par un) directement à la inputBuffer (ByteBuffer). Est-ce ce que vous voulez vraiment?
InformationsquelleAutor thiagolr | 2013-11-02