如题,我是参考 http://blog.51cto.com/ticktick/1710743 改写了一下,但是MediaFormat是通过手动创建的,通过Extractor解出来的Buffer手动的创建MediaFormat,遇到几个问题:将第一帧写入MediaFormat后手动调用MediaExtractor的advance方法运行后直接crash,error是muxer fail to stop 2.SPS和PPS写入MediaFormat后是否还需要再通过muxer写入,不写入的话时间戳会不会有问题?
public class MainActivity extends Activity {
private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath();
private static final String INPUT_FILEPATH = SDCARD_PATH + "/input.mp4";
private static final String OUTPUT_FILEPATH = SDCARD_PATH + "/output.mp4";
private int i = 0;
private TextView mLogView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLogView = (TextView) findViewById(R.id.LogView);
new Thread(new Runnable() {
@Override
public void run() {
try {
transcode(INPUT_FILEPATH, OUTPUT_FILEPATH);
} catch (IOException e) {
e.printStackTrace();
logout(e.getMessage());
}
}
}).start();
}
protected boolean transcode(String input, String output) throws IOException {
logout("start processing...");
MediaMuxer muxer = null;
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(input);
logout("start demuxer: " + input);
MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720);
extractor.selectTrack(0);
// if (muxer == null) {
// logout("no video found !");
// return false;
// }
BufferInfo info = new BufferInfo();
info.presentationTimeUs = 0;
ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024 * 2);
int i = - 1;
while (true) {
i++;
int sampleSize = extractor.readSampleData(buffer, 0);
if (sampleSize < 0) {
logout("read sample data failed , break !");
break;
}
if (i == 0 ){
byte[] sps_header = new byte[sampleSize];
for (int j = 0;j < sampleSize;j++){
sps_header[j] = buffer.array()[sampleSize];
}
//SPS
videoFormat.setByteBuffer("csd-0", ByteBuffer.wrap(sps_header));
extractor.advance();
continue;
}else if (i == 1){
//PPS
byte[] pps_header = new byte[sampleSize];
for (int j = 0; j < sampleSize; j++){
pps_header[j] = buffer.array()[sampleSize];
}
videoFormat.setByteBuffer("csd-1",ByteBuffer.wrap(pps_header));
videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
videoFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
videoFormat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 25);
muxer = new MediaMuxer(output,OutputFormat.MUXER_OUTPUT_MPEG_4);
muxer.addTrack(videoFormat);
muxer.start();
continue;
}
Log.d("xiaxingyu","i = " + i);
info.offset = 0;
info.size = sampleSize;
info.flags = extractor.getSampleFlags();
info.presentationTimeUs = extractor.getSampleTime();
boolean keyframe = (info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) > 0;
logout("write sample " + keyframe + ", " + sampleSize + ", " + info.presentationTimeUs);
muxer.writeSampleData(0, buffer, info);
extractor.advance();
}
extractor.release();
muxer.stop();
muxer.release();
logout("process success !");
return true;
}
private void logout(final String content) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("MediaDemo", content);
mLogView.setText(mLogView.getText() + "\n" + content);
}
});
}
}
要先调用readSampleData方法