我正在尝试将PNG文件转换为单片视频片段,以便在项目中启动。
我的代码是: -
private boolean MediaConversion()
{
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;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.image);
Log.e("Uploaded", "Bitmap:" + bitmap.getWidth() + "X" + bitmap.getHeight());
} catch (Exception e) {
e.printStackTrace();
}
bitmap = Bitmap.createScaledBitmap(bitmap, WIDTH, HEIGHT, false);
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
byteArrayOutputStream);
byte[] dat = byteArrayOutputStream.toByteArray();
info = new BufferInfo();
**// Exception occurred on this below line in Emulator, LINE No. 182//**
inputBufferIndex = codec.dequeueInputBuffer(WAITTIME);
if(dat.length<=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;
**// Exception occurred on this below line in DEVICE, LINE No. 193 //**
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){
dos = array;
}
codec.releaseOutputBuffer(outputBufferIndex, false);
inputBuffers[inputBufferIndex].clear();
outputBuffers[outputBufferIndex].clear();
}
}else{
codec.queueInputBuffer(inputBufferIndex, 0, 0, presentationTime, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
outputBufferIndex = codec.dequeueOutputBuffer(info, WAITTIME);
Log.i("CHAK", "outputBufferIndex="+outputBufferIndex);
if(outputBufferIndex >= 0){
byte[] array = new byte[info.size];
outputBuffers[outputBufferIndex].get(array);
if(array != null){
dos = array;
}
codec.releaseOutputBuffer(outputBufferIndex, false);
inputBuffers[inputBufferIndex].clear();
outputBuffers[outputBufferIndex].clear();
}
}
}
codec.stop();
codec.release();
codec = null;
return true;
}
这是异常日志: -
当试图在模拟器Api等级19上运行时:
12-02 23:58:58.214: E/SoftAVCEncoder(1193): internalSetParameter: StoreMetadataInBuffersParams.nPortIndex not zero!
12-02 23:58:58.214: E/OMXNodeInstance(1193): OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x80001001
12-02 23:58:58.224: E/ACodec(1193): [OMX.google.h264.encoder] storeMetaDataInBuffers (output) failed w/ err -2147483648
12-02 23:58:58.224: I/ACodec(1193): setupVideoEncoder succeeded
12-02 23:58:58.254: E/SoftAVCEncoder(1193): Failed to initialize the encoder: -8
12-02 23:58:58.254: E/ACodec(1193): [OMX.google.h264.encoder] ERROR(0x80001001)
12-02 23:58:58.254: E/MediaCodec(1193): Codec reported an error. (omx error 0x80001001, internalError -2147483648)
12-02 23:59:00.424: E/AndroidRuntime(1193): FATAL EXCEPTION: main
12-02 23:59:00.424: E/AndroidRuntime(1193): Process: com.antech.kefilm, PID: 1193
12-02 23:59:00.424: E/AndroidRuntime(1193): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.antech.kefilm/com.antech.kefilm.NewClass}: java.lang.IllegalStateException
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2176)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2226)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.access$700(ActivityThread.java:135)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.os.Handler.dispatchMessage(Handler.java:102)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.os.Looper.loop(Looper.java:137)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.main(ActivityThread.java:4998)
12-02 23:59:00.424: E/AndroidRuntime(1193): at java.lang.reflect.Method.invokeNative(Native Method)
12-02 23:59:00.424: E/AndroidRuntime(1193): at java.lang.reflect.Method.invoke(Method.java:515)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
12-02 23:59:00.424: E/AndroidRuntime(1193): at dalvik.system.NativeStart.main(Native Method)
12-02 23:59:00.424: E/AndroidRuntime(1193): Caused by: java.lang.IllegalStateException
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.media.MediaCodec.dequeueInputBuffer(Native Method)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.antech.kefilm.NewClass.MediaConversion(NewClass.java:182)
12-02 23:59:00.424: E/AndroidRuntime(1193): at com.antech.kefilm.NewClass.onCreate(NewClass.java:83)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.Activity.performCreate(Activity.java:5243)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
12-02 23:59:00.424: E/AndroidRuntime(1193): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
12-02 23:59:00.424: E/AndroidRuntime(1193): ... 11 more
但是,当在Galaxy Tab 3(设备)上运行时:
12-03 05:32:09.670: E/ACodec(3096): [OMX.MARVELL.VIDEO.HW.CODA7542ENCODER] ERROR(0x80001005)
12-03 05:32:09.670: E/MediaCodec(3096): Codec reported an error. (omx error 0x80001005, internalError -2147483648)
12-03 05:32:09.670: E/AndroidRuntime(3096): Caused by: java.lang.IllegalStateException
12-03 05:32:09.670: E/AndroidRuntime(3096): at android.media.MediaCodec.dequeueOutputBuffer(Native Method)
12-03 05:32:09.670: E/AndroidRuntime(3096): at com.antech.kefilm.NewClass.MediaConversion(NewClass.java:193)
12-03 05:32:09.670: E/AndroidRuntime(3096): at com.antech.kefilm.NewClass.onCreate(NewClass.java:83)
参考资料,据我开始这个项目: -
提前致谢。
答案 0 :(得分:6)
首先,我不希望模拟器编解码器完全正常工作。如果他们确实有效,我会感到惊喜。这种观点有助于我避免失望。
其次,我的猜测是传递给编码器的帧的大小是错误的。您正在从Bitmap解码RGBA帧并将其填充到YUV 420缓冲区中。这不起作用。您传入的数据量应该与YUV420的宽度*高度* 1.5字节完全相同(其中stride == width并且平面打包在一起)。在Android 4.3+设备上,此行为通过CTS EncodeDecodeTest确认;旧设备无法保证正常工作。
另外,您要将格式设置为COLOR_FormatYUV420SemiPlanar
;一般来说,你不能假设。您需要在编解码器中查询支持的格式列表,确定输入是平面还是半平面,然后相应地格式化缓冲区输入。 EncodeDecodeTest中的缓冲区到缓冲区和缓冲区到表面的测试演示了如何执行此操作。
或者,在Android 4.3及更高版本中,您可以将位图上传到纹理,为Surface输入配置编解码器,并使用GLES渲染纹理(如果位图大小没有,则可以让硬件处理任何缩放问题) t匹配您的视频大小)。这需要更多的代码。
说了这么多,MediaCodec
诊断通常没用,所以这都是猜测。