mam pewne kłopoty z plikami pisanie mp4 na Androidzie używając MediaRecorder i Jcodec, tutaj jest mój kodTworzenie plików mp4 na Androidzie używając Jcodec
public class SequenceEncoder {
private final static String CLASSTAG = SequenceEncoder.class.getSimpleName();
private SeekableByteChannel ch;
private byte[] yuv = null;
private ArrayList<ByteBuffer> spsList;
private ArrayList<ByteBuffer> ppsList;
private CompressedTrack outTrack;
private int frameNo;
private MP4Muxer muxer;
ArrayList<ByteBuffer> spsListTmp = new ArrayList<ByteBuffer>();
ArrayList<ByteBuffer> ppsListTmp = new ArrayList<ByteBuffer>();
// Encoder
private MediaCodec mediaCodec = null;
public SequenceEncoder(File out) throws IOException {
this.ch = NIOUtils.writableFileChannel(out);
// Muxer that will store the encoded frames
muxer = new MP4Muxer(ch, Brand.MP4);
// Add video track to muxer
outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25);
// Encoder extra data (SPS, PPS) to be stored in a special place of
// MP4
spsList = new ArrayList<ByteBuffer>();
ppsList = new ArrayList<ByteBuffer>();
}
@SuppressWarnings("unchecked")
public void encodeImage(ByteBuffer buffer, int width, int height) throws IOException {
if (yuv == null) {
int bufferSize = width * height * 3/2;
yuv = new byte[bufferSize];
int bitRate = bufferSize;
int frameRate = 25;
String mimeType = "video/avc";
// "video/avc"
mediaCodec = MediaCodec.createEncoderByType(mimeType);
MediaFormat mediaFormat = MediaFormat.createVideoFormat(mimeType, width, height);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); // 125000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
}
byte[] rgba = buffer.array();
// Convert RGBA image to NV12 (YUV420SemiPlanar)
Rgba2Yuv420.convert(rgba, yuv, width, height);
synchronized (mediaCodec) {
try {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(yuv);
mediaCodec.queueInputBuffer(inputBufferIndex, 0,
yuv.length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(
bufferInfo, 0);
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
ByteBuffer frameBuffer = ByteBuffer.wrap(outData);
spsListTmp.clear();
ppsListTmp.clear();
H264Utils.encodeMOVPacket(frameBuffer, spsListTmp, ppsListTmp);
if (!spsListTmp.isEmpty())
spsList = (ArrayList<ByteBuffer>) spsListTmp.clone();
if (!ppsListTmp.isEmpty())
ppsList = (ArrayList<ByteBuffer>) ppsListTmp.clone();
outTrack.addFrame(new MP4Packet(frameBuffer, frameNo, 25, 1,
frameNo, true, null, frameNo, 0));
frameNo++;
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(
bufferInfo, 0);
}
if (outputBufferIndex < 0)
switch (outputBufferIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
outputBuffers = mediaCodec.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
break;
}
} catch (Exception e) {
}
}
}
public void finish() throws IOException {
if (!ch.isOpen())
return;
if (mediaCodec != null) {
mediaCodec.stop();
mediaCodec.release();
}
outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));
// Write MP4 header and finalize recording
muxer.writeHeader();
NIOUtils.closeQuietly(ch);
ch.close();
}
}
Jak widzimy Android MediaCodec oczekiwać YUV420SemiPlanar jako obrazu wejściowego, tak ja Podaję mu właściwą. W rezultacie mam uszkodzony plik MP4 z nieprawidłowymi kolorami, kiedy otwieram ten plik MP4 z AVCon widzę, że format koloru w pliku wyjściowym to yuv420p, więc może to jest problem? Proszę zasugerować, jak to naprawić.
Mam również inne pytanie, jak dodać skompresowany strumień audio do Muxer, nie znalazłem przykłady.