Articles of h.264

通过MP4video向后搜索时,显示时间戳不正确

我正在使用MediaCodec和MediaExtractor以可变速率播放video,包括向前和向后。 代码使用类似SpeedControlCallback的东西来建立帧间暂停 – 从输出缓冲区向它提供presentationTimeUs字段。 这种方法在99%的情况下运行良好,但是看起来三星S6上的AVC编解码器在向后搜索时提供了错误的呈现时间 – 它们被固定在寻求转发的最高价值时,如果这有意义的话。 缓冲区中的数据是正确/更改的 – 它只是与固定的显示时间不对应。 S6可以使用品牌/ ftype的avc1处理MP4文件中的后向avc1 ,但我尝试过的其他品牌的H.264video( mp42 , mp42 )在100%的时间内都不起作用。 相同的文件在三星S5以及我尝试过的所有其他设备上都能正常工作。 编解码器记录这个: 09-15 11:16:21.611 2992-16618/? W/EXYNOS_VIDEO_DEC﹕ sCurrentTimestamp(6002033) is smaller than latestTimeStamp(7001744), uses latestTimeStamp 在每次向后搜索( SEEK_TO_PREVIOUS_SYNC )时,将为所有关键帧提供错误的latestTimestampValue 。 是否有人在Galaxy S6上遇到与AVC编解码器类似的问题,或者是否能够提供任何(非hacky)解决方案?

无法兼容音频和video

我正在编写一个使用MediaCodec记录屏幕捕获和音频的应用程序。 我使用MediaMuxer来复用video和音频来创建mp4文件。 我成功地分别编写了video和音频,但是当我尝试将它们混合在一起时,结果出乎意料。 音频播放时没有video,或video播放后立即播放。 我的猜测是我对时间戳做错了,但我无法弄清楚到底是什么。 我已经看过这些例子: https : //github.com/OnlyInAmerica/HWEncoderExperiments/tree/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments和bigflake.com上的那些并且无法find回答。 这是我的媒体格式配置: mVideoFormat = createMediaFormat(); private static MediaFormat createVideoFormat() { MediaFormat format = MediaFormat.createVideoFormat( Preferences.MIME_TYPE, mScreenWidth, mScreenHeight); format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); format.setInteger(MediaFormat.KEY_BIT_RATE, Preferences.BIT_RATE); format.setInteger(MediaFormat.KEY_FRAME_RATE, Preferences.FRAME_RATE); format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, Preferences.IFRAME_INTERVAL); return format; } mAudioFormat = createAudioFormat(); private static MediaFormat createAudioFormat() { MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, “audio/mp4a-latm”); format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); […]

MediaCodec H264编码器无法在Snapdragon 800设备上运行

我使用Android的MediaCodec API编写了H264流编码器。 我使用不同的处理器在大约十种不同的设备上进行了测试,除了Snapdragon 800驱动的设备(谷歌Nexus 5和索尼Xperia Z1)之外,它在所有设备上都有效。 在那些设备上,我得到了SPS和PPS以及第一个Keyframe,但之后mEncoder.dequeueOutputBuffer(mBufferInfo,0)只返回MediaCodec.INFO_TRY_AGAIN_LATER。 我已经尝试过不同的超时,比特率,分辨率和其他配置选项,但无济于事。 结果总是一样的。 我使用以下代码初始化编码器: mBufferInfo = new MediaCodec.BufferInfo(); encoder = MediaCodec.createEncoderByType(“video/avc”); MediaFormat mediaFormat = MediaFormat.createVideoFormat(“video/avc”, 640, 480); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 768000); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mEncoderColorFormat); mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); encoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 所选颜色格式为: MediaCodecInfo.CodecCapabilities capabilities = mCodecInfo.getCapabilitiesForType(MIME_TYPE); for (int i = 0; i < capabilities.colorFormats.length && selectedColorFormat == 0; i++) { int […]

如何在Android MediaCodec中播放原始NAL单元

我最初尝试过如何在Andoid exoplayer中播放原始NAL单元? 但是我注意到我必须做一些低级别的事情。 我发现了这个简单的MediaCodec示例 。 正如您所看到的,它是一个在传递给它的表面上播放文件的线程。 注意这些线条 mExtractor = new MediaExtractor(); mExtractor.setDataSource(filePath); 看起来我应该创建自己的MediaExtractor ,而不是从文件中提取video单元,它将使用我将提供的缓冲区中的h264 NAL单元。 然后我可以调用mExtractor.setDataSource(MediaDataSource dataSource) ,参见MediaDataSource 它有readAt(long position, byte[] buffer, int offset, int size) 这是它读取NAL单位的地方。 但是,我应该如何通过它们? 我没有关于需要读取的缓冲区结构的信息。 我应该传递一个带有NAL单元的byte[] buffer ,如果是这样,以哪种格式? 偏移量是多少? 如果它是一个缓冲区,我不应该只删除读取的行,因此没有偏移或大小? 顺便说一句,h264 NAL单元是流媒体单元,它们来自RTP数据包,而不是文件。 我将通过C ++获取它们并将它们存储在缓冲区中,尝试传递给mediaExtractor。 更新: 我一直在阅读很多关于MediaCodec的内容,我想我更了解它。 根据https://developer.android.com/reference/android/media/MediaCodec ,一切都依赖于这种types的东西: MediaCodec codec = MediaCodec.createByCodecName(name); MediaFormat mOutputFormat; // member variable codec.setCallback(new MediaCodec.Callback() { @Override […]

如何使用Android MediaCodec编码相机数据(YUV420sp)

谢谢你的关注! 我想使用Android MediaCodec API对从Camera获取的video帧进行编码,不幸的是,我没有成功做到这一点! 我仍然不熟悉MediaCodec API。以下是我的代码,我需要你的帮助来弄清楚我应该做什么。 1,相机设置: Parameters parameters = mCamera.getParameters(); parameters.setPreviewFormat(ImageFormat.NV21); parameters.setPreviewSize(320, 240); mCamera.setParameters(parameters); 2,设置编码器: private void initCodec() { try { fos = new FileOutputStream(mVideoFile, false); } catch (FileNotFoundException e) { e.printStackTrace(); } mMediaCodec = MediaCodec.createEncoderByType(“video/avc”); MediaFormat mediaFormat = MediaFormat.createVideoFormat(“video/avc”, 320, 240); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar); mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5); mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); […]

如何在没有MediaExtractor的情况下为H264使用MediaCodec

我需要在没有MediaExtractor的情况下使用MediaCodec,我正在使用FileInputStream读取文件。 目前它不起作用,它在屏幕上显示绿色的乱码图像。 这是完整的源代码: FileInputStream in = new FileInputStream(“/sdcard/sample.ts”); String mimeType = “video/avc”; MediaCodec decoder = MediaCodec.createDecoderByType(mimeType); MediaFormat format = MediaFormat.createVideoFormat(mimeType, 1920, 1080); byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, […]

如何使用MediaCodec将位图编码为video?

我想将一组位图编码到h264中。 这可以通过MediaEncoder吗? 我已经编写了一些代码来执行此操作,但输出无法在我尝试过的任何媒体播放器中播放。 这里是我主要从Stackoverflow上find的其他来源借用的一些代码。 mMediaCodec = MediaCodec.createEncoderByType(“video/avc”); mMediaFormat = MediaFormat.createVideoFormat(“video/avc”, 320, 240); mMediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000); mMediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15); mMediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar); mMediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5); mMediaCodec.configure(mMediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mMediaCodec.start(); mInputBuffers = mMediaCodec.getInputBuffers(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); // image is the bitmap byte[] input = byteArrayOutputStream.toByteArray(); int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { ByteBuffer […]

使用Android MediaCodec从摄像头编码H.264

我试图让它在Android 4.1(使用升级的Asus Transformer平板电脑)上运行。 感谢Alex对我之前的问题的回答 ,我已经能够将一些原始的H.264数据写入文件,但是这个文件只能用ffplay -f h264播放,而且它似乎丢失了有关帧率的所有信息(非常快速播放)。 此外,色彩空间看起来也不正确(atm使用摄像机默认的编码器侧)。 public class AvcEncoder { private MediaCodec mediaCodec; private BufferedOutputStream outputStream; public AvcEncoder() { File f = new File(Environment.getExternalStorageDirectory(), “Download/video_encoded.264”); touch (f); try { outputStream = new BufferedOutputStream(new FileOutputStream(f)); Log.i(“AvcEncoder”, “outputStream initialized”); } catch (Exception e){ e.printStackTrace(); } mediaCodec = MediaCodec.createEncoderByType(“video/avc”); MediaFormat mediaFormat = MediaFormat.createVideoFormat(“video/avc”, 320, 240); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, […]

使用ffmpeg实时解码android的硬件编码H264相机源

我正在尝试使用Android上的硬件H264编码器从相机创建video,并使用FFmpeg来复用音频(所有这些都在Android手机上) 到目前为止我所做的是将H264video打包成rtsp数据包,并使用VLC(通过UDP )对其进行解码,因此我知道video的格式至少是正确的。 但是,我无法以可以理解的格式将video数据发送到ffmpeg 。 我尝试将相同的rtsp数据包发送到localhost上的端口5006(通过UDP),然后向ffmpeg提供sdp文件,该文件告诉它video流进入哪个本地端口以及如何解码video,如果我理解的话rtsp正确流式传输。 然而,这不起作用,我无法诊断为什么,因为ffmpeg只是坐在那里等待输入。 出于延迟和可扩展性的原因,我不能只将video和音频发送到服务器并将其复制到那里,必须在手机上以尽可能轻的方式完成。 我想我正在寻找的是关于如何实现这一点的建议。 最佳解决方案是将分组化的H264video通过管道发送到ffmpeg ,但是我无法向ffmpeg发送解码video所需的sdp文件参数。 我可以根据请求提供更多信息,例如如何为Android编译ffmpeg ,但我怀疑这是必要的。 哦,我开始ffmpeg的方式是通过命令行,我真的宁愿避免与jni混淆,如果这是可能的。 非常感谢帮助,谢谢。

使用MediaCodec H264stream媒体

我目前正在尝试将Android用作Skype端点。 在这个阶段,我需要将video编码为H.264(因为它是Skype支持的唯一格式),并使用RTP进行封装,以使stream媒体能够正常工作。 MediaRecorder显然不是很适合这个由于各种原因。 一个是因为它完成后添加MP4或3GP头。 另一个原因是为了将延迟降到最低,硬件加速可能派上用场。 这就是为什么我想利用最近低层次的框架,如MediaCodec , MediaExtractor等 目前,我打算如下工作。 相机将其video写入缓冲区。 MediaCodec使用H264编码video并将结果写入另一个缓冲区。 该缓冲区由RTP封装器读取,该封装器将stream数据发送到服务器。 这是我的第一个问题:这个计划对您来说听起来是否可行? 现在我已经陷入了第一步。 由于互联网上有关使用相机的所有文档都使用MediaRecorder ,所以在编码之前,我找不到将其原始数据存储到缓冲区的方法。 是addCallbackBuffer适合这个? 任何人都有一个例子的链接? 接下来,我找不到很多关于MediaCodec的文档(因为它是相当新的)。 谁有一个坚实的教程? 最后:关于RTP库的任何build议? 提前感谢!