用mediacodec对4k分辨率视频进行h.264\h.265\vp8的编码和解码的问题?

wangzhensuo 2017-02-10 06:09:38
找到个demo程序:https://github.com/pingu342/android-app-mediacodectest
是对1920*1080 h.264进行编码和解码的。
原理是:app界面有2个surfaceview,通过camera获取图像,然后编码,再解码显示到第二个surface上面;
原先版本的现象:1920*1080 h.264情况下,是可以正常运行的。

现在的问题是:
1)原先的代码有颜色不正常,有偏差。这个找到原因了,是u和v的转换问题,目前有个函数,但是不知道在哪里调用来实现转换,NV21toYUV420SemiPlanar(stillImageFrame, stillImageFrame, Width,Height);
2)为什么我将1920*1080修改为3840*2160分辨率,程序就报错;
02-10 17:45:51.522: D/sakalog(11363): create decoder.
02-10 17:45:51.552: I/OMXClient(11363): Using client-side OMX mux.
02-10 17:45:51.552: D/sakalog(11363): Configuring decoder with input format : {csd-0=java.nio.DirectByteBuffer[position=0,limit=26,capacity=12533760], height=2160, width=3840, mime=video/avc}
02-10 17:45:51.562: I/ACodec(11363): [OMX.qcom.video.decoder.avc] DRC Mode: Dynamic Buffer Mode
02-10 17:45:51.562: E/ACodec(11363): [OMX.qcom.video.decoder.avc] configureCodec returning error -2147483648
02-10 17:45:51.562: E/ACodec(11363): signalError(omxError 0x80001001, internalError -2147483648)
02-10 17:45:51.562: E/MediaCodec(11363): Codec reported err 0x80001001, actionCode 0, while in state 3
02-10 17:45:51.562: E/MediaCodec(11363): configure failed with err 0x80001001, resetting...
02-10 17:45:51.562: I/OMXClient(11363): Using client-side OMX mux.
02-10 17:45:51.572: E/AndroidRuntime(11363): FATAL EXCEPTION: Thread-19740
02-10 17:45:51.572: E/AndroidRuntime(11363): Process: jp.saka.mediacodectest, PID: 11363
02-10 17:45:51.572: E/AndroidRuntime(11363): android.media.MediaCodec$CodecException: Error 0x80001001
02-10 17:45:51.572: E/AndroidRuntime(11363): at android.media.MediaCodec.native_configure(Native Method)
02-10 17:45:51.572: E/AndroidRuntime(11363): at android.media.MediaCodec.configure(MediaCodec.java:577)
02-10 17:45:51.572: E/AndroidRuntime(11363): at jp.saka.mediacodectest.MediaCodecTest$EncDecThread.startEncodeDecodeVideo(MediaCodecTest.java:808)
02-10 17:45:51.572: E/AndroidRuntime(11363): at jp.saka.mediacodectest.MediaCodecTest$EncDecThread.run(MediaCodecTest.java:473)
我查了代码中的这个config,没有问题啊;
encoder.configure(
outputFormat, //the desired format of the output data (encoder).
null, //a surface on which to render the output of this decoder. (encoderのためnull指定)
null, //a crypto object to facilitate secure decryption of the media data.
MediaCodec.CONFIGURE_FLAG_ENCODE //configure the component as an encoder.
);
理论上,只改变分辨率是可以的,我尝试将1920*1080缩小一倍,是可以的。是手机太卡的原因吗,我用的是小米4c测试的。

...全文
2842 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangzhensuo 2017-10-10
  • 打赏
  • 举报
回复
在此 谢谢ss182172633的转换方法!
wangzhensuo 2017-10-10
  • 打赏
  • 举报
回复
已经过去好久了,不做安卓了。回复一下这个“请问楼主有没有遇到解码播放绿屏花屏问题,不是所有手机都这样,这个是什么问题” 遇到过这个问题,原因就是YUV和其他颜色格式的转换问题。可以打印log确认手机颜色格式。然后根据具体情况转换一下看看。
冰水凝 2017-06-13
  • 打赏
  • 举报
回复
请问楼主有没有遇到解码播放绿屏花屏问题,不是所有手机都这样,这个是什么问题
u012027644 2017-03-28
  • 打赏
  • 举报
回复
引用 11 楼 ss182172633 的回复:
[quote=引用 4 楼 wangrunhuan 的回复:] 更新一下,方便以后的人来查,颜色不正常的问题解决了; 加上下面这个函数就行了; private void NV21ToNV12(byte[] nv21,byte[] nv12,int width,int height){ if(nv21 == null || nv12 == null)return; int framesize = width*height; int i = 0,j = 0; System.arraycopy(nv21, 0, nv12, 0, framesize); for(i = 0; i < framesize; i++){ nv12[i] = nv21[i]; } for (j = 0; j < framesize/2; j+=2) { nv12[framesize + j-1] = nv21[j+framesize]; } for (j = 0; j < framesize/2; j+=2) { nv12[framesize + j] = nv21[j+framesize-1]; } }
我擦, 竟然看到了我写的方法[/quote] 给力啊,这个方法有用!
sszpf 2017-03-20
  • 打赏
  • 举报
回复
引用 4 楼 wangrunhuan 的回复:
更新一下,方便以后的人来查,颜色不正常的问题解决了; 加上下面这个函数就行了; private void NV21ToNV12(byte[] nv21,byte[] nv12,int width,int height){ if(nv21 == null || nv12 == null)return; int framesize = width*height; int i = 0,j = 0; System.arraycopy(nv21, 0, nv12, 0, framesize); for(i = 0; i < framesize; i++){ nv12[i] = nv21[i]; } for (j = 0; j < framesize/2; j+=2) { nv12[framesize + j-1] = nv21[j+framesize]; } for (j = 0; j < framesize/2; j+=2) { nv12[framesize + j] = nv21[j+framesize-1]; } }
我擦, 竟然看到了我写的方法
wangzhensuo 2017-02-23
  • 打赏
  • 举报
回复
本人QQ 1938162227 。
wangzhensuo 2017-02-21
  • 打赏
  • 举报
回复
4K的不支持,通过修改底层的最大分辨率得到解决了。
冒出来一个新的问题:
现在实现了4k的h.264编码解码,为什么我修改了编码解码方式为vp8后,程序就报错了?(修改成h.265是可以直接实现h.265的编码和解码的)
// String mimeType = "video/avc";
String mimeType = "video/x-vnd.on2.vp8";

MediaFormat outputFormat = MediaFormat.createVideoFormat(mimeType, width, height);

01-01 00:21:43.665: E/AndroidRuntime(7199): FATAL EXCEPTION: Thread-316
01-01 00:21:43.665: E/AndroidRuntime(7199): Process: jp.saka.mediacodectest, PID: 7199
01-01 00:21:43.665: E/AndroidRuntime(7199): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.media.MediaCodec.dequeueInputBuffer(long)' on a null object reference
01-01 00:21:43.665: E/AndroidRuntime(7199): at jp.saka.mediacodectest.MediaCodecTest$EncDecThread.startEncodeDecodeVideo(MediaCodecTest.java:795)
01-01 00:21:43.665: E/AndroidRuntime(7199): at jp.saka.mediacodectest.MediaCodecTest$EncDecThread.run(MediaCodecTest.java:509)
目前可以确认的是:encoder.dequeueOutputBuffer 这句之前是正常的log,这句之后,就不对了。已经检查encoder.dequeueOutputBuffer里面的参数,传入的没有问题,encoder.dequeueInputBuffer也没有问题,dequeueOutputBuffer(MediaCodec.BufferInfo info, long timeoutUs)的timeoutUs我分别试了5000,-1,0,都报同样的错误。
Log.d("xiaoming", "encoder.dequeueOutputBuffer之前 info.flags ="+ info.flags);// OK 0 NG 0
int res = encoder.dequeueOutputBuffer(info, kTimeOutUs);
Log.d("xiaoming", "info.flags =" + info.flags);// 正常是0, NG是4
想了解的是除了app层,底层需要修改吗?大致思考方向是什么?
上一次是分辨率小,通过修改底层实现了,但是这次编码方式是mediacodec自己带的,我还需要考虑底层的修改吗?
各位大神给个思路,先谢谢了。
wangzhensuo 2017-02-21
  • 打赏
  • 举报
回复
引用 7 楼 luowenlong860502 的回复:
你需要注意几个问题: 1.颜色格式(色彩空间),每款手机都不通,不是说你调用一个转换函数就万事大吉了 camera输出的默认颜色格式是什么,然后可以自己设置颜色格式 2.mediacodec编码支持哪些颜色格式,可以设置颜色格式,可以支持哪些分辨率,可以设置分辨率 .... 参数每款手机都不一样,你需要这款手机支持什么,然后做动态选择
谢谢回答
媒体盒子 2017-02-16
  • 打赏
  • 举报
回复
你需要注意几个问题: 1.颜色格式(色彩空间),每款手机都不通,不是说你调用一个转换函数就万事大吉了 camera输出的默认颜色格式是什么,然后可以自己设置颜色格式 2.mediacodec编码支持哪些颜色格式,可以设置颜色格式,可以支持哪些分辨率,可以设置分辨率 .... 参数每款手机都不一样,你需要这款手机支持什么,然后做动态选择
magicyang1234 2017-02-13
  • 打赏
  • 举报
回复
ANDROID有自己的JAVA层的MEDIACODEC,这个类支持的编解码类型不多。
magicyang1234 2017-02-13
  • 打赏
  • 举报
回复
回答你后面的问题,MEDIACODEC是底层硬解,FFMPEG是解码库,本身就不是一个东西。FFMPEG默认的底层是EGL,也就是软解。如果需要FFMPEG支持硬解,需要自己写底层。个人理解仅供参考。
wangzhensuo 2017-02-13
  • 打赏
  • 举报
回复
引用 3 楼 yangchengtest 的回复:
ANDROID有自己的JAVA层的MEDIACODEC,这个类支持的编解码类型不多。
谢谢啦
wangzhensuo 2017-02-13
  • 打赏
  • 举报
回复
引用 2 楼 yangchengtest 的回复:
回答你后面的问题,MEDIACODEC是底层硬解,FFMPEG是解码库,本身就不是一个东西。FFMPEG默认的底层是EGL,也就是软解。如果需要FFMPEG支持硬解,需要自己写底层。个人理解仅供参考。
谢谢回答
wangzhensuo 2017-02-13
  • 打赏
  • 举报
回复
更新一下,方便以后的人来查,颜色不正常的问题解决了; 加上下面这个函数就行了; private void NV21ToNV12(byte[] nv21,byte[] nv12,int width,int height){ if(nv21 == null || nv12 == null)return; int framesize = width*height; int i = 0,j = 0; System.arraycopy(nv21, 0, nv12, 0, framesize); for(i = 0; i < framesize; i++){ nv12[i] = nv21[i]; } for (j = 0; j < framesize/2; j+=2) { nv12[framesize + j-1] = nv21[j+framesize]; } for (j = 0; j < framesize/2; j+=2) { nv12[framesize + j] = nv21[j+framesize-1]; } }
wangzhensuo 2017-02-10
  • 打赏
  • 举报
回复
本人只看了一遍《andorid第一行代码》就开始接手这个了。目前只是知道midiacodec可以视频解码编码,网上搜索还有ffmpeg的。这两个哪个性能上比较好些?谢谢各位大神了。

80,350

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧