Finora sono in grado di configurare un MediaCodec per codificare un flusso video. L'obiettivo è di salvare il mio materiale illustrativo generato dall'utente in un file video.Come utilizzare ByteBuffer nel contesto MediaCodec in Android
Uso gli oggetti bitmap Android del disegno utente per inserire fotogrammi nello stream.
Vedi il frammento di codice che uso in fondo a questo post (che è il codice completo non viene tagliato):
MediaCodec utilizza ByteBuffer a che fare con i flussi video/audio.
Bitmap si basano su int [] che, se convertito in byte [] richiederà x4 la dimensione del int []
ho fatto qualche ricerca per capire che cosa i contratti sono in atto per la ByteBuffer quando si tratta con flussi video/audio in MediaCodec, ma le informazioni sono quasi vicine a zilch.
Quindi, quali sono i contratti di utilizzo ByteBuffer in MediaCodec?
Specificare le dimensioni della cornice in MediaFormat significa automaticamente che i ByteBuffer hanno larghezza * altezza * 4 byte di capacità?
(uso un oggetto bitmap alla volta per ogni fotogramma)
Grazie per qualsiasi aiuto.
(a cura, codice aggiunto)
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import android.graphics.Rect;
import android.graphics.Bitmap.CompressFormat;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.CamcorderProfile;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Log;
import android.view.View;
public class VideoCaptureManager {
private boolean running;
private long presentationTime;
public void start(View rootView, String saveFilePath){
Log.e("OUT", saveFilePath);
this.running = true;
this.presentationTime = 0;
this.capture(rootView, saveFilePath);
}
private void capture(final View rootView, String saveFilePath){
if(rootView != null){
rootView.setDrawingCacheEnabled(true);
final Rect drawingRect = new Rect();
rootView.getDrawingRect(drawingRect);
try{
final File file = new File(saveFilePath);
if(file.exists()){
// File exists return
return;
} else {
File parent = file.getParentFile();
if(!parent.exists()){
parent.mkdirs();
}
}
new Thread(){
public void run(){
try{
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
MediaCodec codec = MediaCodec.createEncoderByType("video/mp4v-es");
MediaFormat mediaFormat = null;
if(CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)){
mediaFormat = MediaFormat.createVideoFormat("video/mp4v-es", 720, 1280);
} else {
mediaFormat = MediaFormat.createVideoFormat("video/mp4v-es", 480, 720);
}
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 700000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
codec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
while(VideoCaptureManager.this.running){
try{
int inputBufferIndex = codec.dequeueInputBuffer(-2);
if(inputBufferIndex >= 0){
// Fill in the bitmap bytes
// inputBuffers[inputBufferIndex].
ByteArrayOutputStream baos = new ByteArrayOutputStream();
rootView.getDrawingCache().compress(CompressFormat.JPEG, 80, baos);
inputBuffers[inputBufferIndex].put(baos.toByteArray());
codec.queueInputBuffer(inputBufferIndex, 0, inputBuffers[inputBufferIndex].capacity(), presentationTime, MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
presentationTime += 100;
}
BufferInfo info = new BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(info, -2);
if(outputBufferIndex >= 0){
// Write the bytes to file
byte[] array = outputBuffers[outputBufferIndex].array(); // THIS THORWS AN EXCEPTION. WHAT IS THE CONTRACT TO DEAL WITH ByteBuffer in this code?
if(array != null){
dos.write(array);
}
codec.releaseOutputBuffer(outputBufferIndex, false);
} else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED){
outputBuffers = codec.getOutputBuffers();
} else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){
// codec format is changed
MediaFormat format = codec.getOutputFormat();
}
Thread.sleep(100);
}catch(Throwable th){
Log.e("OUT", th.getMessage(), th);
}
}
codec.stop();
codec.release();
codec = null;
dos.flush();
dos.close();
}catch(Throwable th){
Log.e("OUT", th.getMessage(), th);
}
}
}.start();
}catch(Throwable th){
Log.e("OUT", th.getMessage(), th);
}
}
}
public void stop(){
this.running = false;
}
}