Использование MediaCodec для сохранения серии изображений в качестве видео
Я пытаюсь использоватьMediaCodec
сохранить серию изображений, сохраненных в виде байтовых массивов в файле, в видеофайл. Я проверил эти изображения наSurfaceView
(играет их в серии), и я вижу их хорошо. Я посмотрел на множество примеров, используяMediaCodec
и вот что я понимаю (поправьте меня, если я ошибаюсь):
Получить InputBuffers из объекта MediaCodec -> заполнить его данными изображения вашего кадра -> поставить в очередь входной буфер -> получить закодированный выходной буфер -> записать его в файл -> увеличить время представления и повторить
Тем не менее, я проверил это много, и я в конечном итоге один из двух случаев:
Все примеры проектов, которые я пытался имитировать, приводили к смерти сервера мультимедиа при вызове.queueInputBuffer
во второй раз.Я пробовал звонитьcodec.flush()
в конце (после сохранения выходного буфера в файл, хотя ни один из примеров, которые я видел, не сделал этого) и медиасервер не умер, однако я не могу открыть выходной видеофайл с помощью любого медиаплеера, поэтому что-то не так ,Вот мой код:
MediaCodec codec = MediaCodec.createEncoderByType(MIMETYPE);
MediaFormat mediaFormat = null;
if(CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)){
mediaFormat = MediaFormat.createVideoFormat(MIMETYPE, 1280 , 720);
} else {
mediaFormat = MediaFormat.createVideoFormat(MIMETYPE, 720, 480);
}
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 700000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
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();
boolean sawInputEOS = false;
int inputBufferIndex=-1,outputBufferIndex=-1;
BufferInfo info=null;
//loop to read YUV byte array from file
inputBufferIndex = codec.dequeueInputBuffer(WAITTIME);
if(bytesread<=0)sawInputEOS=true;
if(inputBufferIndex >= 0){
if(!sawInputEOS){
int samplesiz=dat.length;
inputBuffers[inputBufferIndex].put(dat);
codec.queueInputBuffer(inputBufferIndex, 0, samplesiz, presentationTime, 0);
presentationTime += 100;
info = new BufferInfo();
outputBufferIndex = codec.dequeueOutputBuffer(info, WAITTIME);
Log.i("BATA", "outputBufferIndex="+outputBufferIndex);
if(outputBufferIndex >= 0){
byte[] array = new byte[info.size];
outputBuffers[outputBufferIndex].get(array);
if(array != null){
try {
dos.write(array);
} catch (IOException e) {
e.printStackTrace();
}
}
codec.releaseOutputBuffer(outputBufferIndex, false);
inputBuffers[inputBufferIndex].clear();
outputBuffers[outputBufferIndex].clear();
if(sawInputEOS) break;
}
}else{
codec.queueInputBuffer(inputBufferIndex, 0, 0, presentationTime, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
info = new BufferInfo();
outputBufferIndex = codec.dequeueOutputBuffer(info, WAITTIME);
if(outputBufferIndex >= 0){
byte[] array = new byte[info.size];
outputBuffers[outputBufferIndex].get(array);
if(array != null){
try {
dos.write(array);
} catch (IOException e) {
e.printStackTrace();
}
}
codec.releaseOutputBuffer(outputBufferIndex, false);
inputBuffers[inputBufferIndex].clear();
outputBuffers[outputBufferIndex].clear();
break;
}
}
}
}
codec.flush();
try {
fstream2.close();
dos.flush();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
codec.stop();
codec.release();
codec = null;
return true;
}
У меня вопрос, как я могу получить рабочее видео из потока изображений с помощью MediaCodec. Что я делаю неправильно?
Еще один вопрос (если я не слишком жадный), я хотел бы добавить звуковую дорожку к этому видео, это также можно сделать с помощью MediaCodec, или я должен использовать FFmpeg?
Запись: Я знаю оMediaMux
в Android 4.3, однако, это не вариант для меня, так как мое приложение должно работать на Android 4.1+.
Обновить Благодаря ответу Fadden, я смог достичь EOS без смерти Медиа-сервера (Выше код после модификации). Тем не менее, файл, который я получаю, производит бред. Вот снимок видео, которое я получаю (работает только как файл .h264).
Мой входной формат изображения - изображение YUV (NV21 от предварительного просмотра камеры). Я не могу заставить его быть в любом воспроизводимом формате. Я перепробовал все форматы COLOR_FormatYUV420 и одинаковый бред. И я до сих пор не могу найти (используя MediaCodec), чтобы добавить аудио.