これまでは、ビデオストリームをエンコードするためにMediaCodecをセットアップすることができました。目的は、ユーザーが作成したアートワークをビデオファイルに保存することです。AndroidのMediaCodecコンテキストでByteBufferを使用する方法
私はフレームをストリームにプッシュするために、ユーザーのアートワークのアンドロイドビットマップオブジェクトを使用します。
私は(それは完全なコード何がトリミングされていないです)この記事の下部にある使用コードスニペットを参照してください:
MediaCodecは、ビデオ/オーディオストリームに対処するためのByteBufferを使用しています。 []私が扱うときに契約がByteBufferのための場所であるかを把握するためにいくつかの研究を行なった[]
int型のサイズX4必要になるのバイトに変換された場合
ビットマップはint型に基づいています
[] MediaCodecのビデオ/オーディオストリームを使用していますが、その情報はzilchとほぼ同じです。だから、 MediaCodecのByteBuffer使用契約は何ですか?
MediaFormatでフレームのサイズを指定すると、自動的にByteBuffersの幅*高さ* 4バイトの容量が指定されますか?
(私は、各フレームの時間でビットマップオブジェクトを使用する)任意の助け
感謝。
はByteBuffer
の正確なレイアウトは、選択した入力フォーマットのコーデックによって決定される
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;
}
}