黑马程序员毕向东Java入门视频
黑马程序员方立勋JavaWeb视频
黑马程序员项目视频经典之作巴巴运动网续集
黑马程序员项目视频经典之作巴巴运动网106集
黑马程序员Java视频教程(最适合Java初学者的经典入门视频)
黑马程序员张孝祥2010年贺岁视频:Java高新技术
黑马程序员JavaWEB开发(JSP+Servlet)视频
黑马程序员JDBC视频教程
黑马程序员_struts2实用简洁版视频
黑马程序员张孝祥Struts开发视频教程
黑马程序员Struts1 视频教程
黑马程序员AJax技术入门视频教程
黑马程序员Hibernate视频教程
黑马程序员Spring25视频教程
黑马程序员EJB30视频教程
黑马程序员JPA详解视频教程
黑马程序员ibatis视频教程
黑马程序员张孝祥-7K月薪面试题破解之二:银行业务调度系统
黑马程序员张孝祥-7K月薪面试题破解之一:交通灯管理系统
黑马程序员java网上在线支付实战视频
黑马程序员JAVA邮件开发视频教程
黑马程序员FCKeditor视频教程
黑马程序员俄罗斯、贪吃蛇游戏-项目视频
黑马程序员HTML、CSS、JavaScript技术的入门视频
黑马程序员王泽佑JNI视频教程
黑马程序员_FTP视频教程
黑马程序员Oracle视频教程(内部经典)
黑马程序员OA+工作流(JBPM)
视频持续更新中
详情请搜索:黑马程序员视频
可以
1 创建并配置MediaCodec
private val MIME_TYPE = "video/avc"
val format = MediaFormatcreateVideoFormat("video/avc", width, height)apply {
setInteger(MediaFormatKEY_COLOR_FORMAT, MediaCodecInfoCodecCapabilitiesCOLOR_FormatSurface)
setInteger(MediaFormatKEY_BIT_RATE, 5120000)
setInteger(MediaFormatKEY_FRAME_RATE, 25)
setInteger(MediaFormatKEY_I_FRAME_INTERVAL, 1)
}
mediaCodec = MediaCodeccreateEncoderByType(MIME_TYPE)
mediaCodecconfigure(format, null, null, MediaCodecCONFIGURE_FLAG_ENCODE)
mediaCodecstart()
复制代码
这里我们通过将帧渲染到surface上的方式向MediaCodec提供编码数据,因此KEY_COLOR_FORMAT是COLOR_FormatSurface,另外码率、帧率及关键帧间隔可根据需要设置。
2 创建EGL
什么是EGL?关于EGL的概念可以参考我的一篇文章《OpenGL ES 高级进阶:EGL及GL线程》,这里EGL的作用主要是2个,一个是向MediaCodec提供编码帧是通过将帧内容渲染到一个EGL Surface上,这个EGL Surface需要通过MediaCodec给出的input surface来创建,另一个作用是做texture的共享,因为编码通常会放到另一个线程里,和提供帧texture的线程不是同一个线程。
egl = EncodeEGL(shareContext, mediaCodeccreateInputSurface())apply {
init()
makeCurrent()
}
复制代码
然后将这个EGL绑定到调用线程中,我的demo是将编码放到一个独立的线程上,所以只makeCurrent就可以了,不需要之后再restore回来。
3 创建MediaMuxer
这个东西是用来进行视频容器封装的,编码只是得到了一堆视频帧数据,那播放器怎么知道怎样去播这堆数据呢?这时就需要容器这个东西,这里用的是mp4:
mediaMuxer = MediaMuxer(filePath, MediaMuxerOutputFormatMUXER_OUTPUT_MPEG_4)
复制代码
4 渲染编码帧
这里渲染编码帧就是很简单地渲染一个texture,没什么好说的,然后还要设置帧时间戳,这样播放器播的时候才知道什么时间播哪帧,最后swapBuffers完成渲染,这样就向MediaCodec提供了一个待编码的帧。
encodeRendererdrawFrame(texture)
eglsetTimestamp(timestamp)
eglswapBuffers()
复制代码
5 获取编码好的帧并将数据写入文件
这一步有点复杂,因为要处理的情况比较多,这里只把一些关键的步骤列出来。
首先dequeueOutputBuffer()将编码好的一帧的index拿出来,可以设置超时时间,如果在超时时间到达时还未获取到编好的一帧,就会返回,可以通过返回的值来判断是否成功拿到了编码好的帧index。
得到了index就从encoderOutputBuffers中取出编码好的帧数据,然后通过MediaMuxer将数据写入文件。
最后把dequeue出来的buffer再归还回去。
val ret = mediaCodecdequeueOutputBuffer(bufferInfo, 0)
encoderOutputBuffers = mediaCodecoutputBuffers
val encodedData = encoderOutputBuffers[ret]
encodedDataposition(bufferInfooffset)
encodedDatalimit(bufferInfooffset + bufferInfosize)
mediaMuxerwriteSampleData(trackIndex, encodedData, bufferInfo)
mediaCodecreleaseOutputBuffer(ret, false)
复制代码
现在来看一下demo:
Thread {
val egl = EGL()apply {
init()
bind()
}
val bitmap = decodeBitmapFromAssets("testpng")
Thread {
val videoEncoder = VideoEncoder()
videoEncoderinit("/sdcard/testmp4", 540, 540, egleglContext)
for (i in 0 until 100) {
val texture = GLUtilbitmap2Texture(rotateBitmap(bitmap, i 2f))
videoEncoderencodeFrame(texture, 100 i 1000000L)
GLUtildeleteTexture(texture)
}
videoEncoderencodeFrame(0, 0)
videoEncoderrelease()
}start()
}start()
复制代码
视频编码比较常见的使用场景是相机录像和将一个视频生成带特效的视频,简单起见,这里我把一张图旋转成不的角度来做为视频的帧,编码出一个540540的mp4视频,帧间隔为100ms,
上篇文章已经配置好FFmpeg的环境变量了
每一帧画面都带有数字标记,非常便于作为原视频调试编解码或者视频处理的帧顺序,可验证转码后的视频帧时间戳是否正常
duration = 视频长度单位秒
H264解析slice就可以找到帧,可以从帧信息中获得DTS时间,从sps信息中获得PTS时间
AAC解析frame,根据AAC编码码率信息,可以知道每一个frame的时间增量,获得PTS时间
一种方法是使用一个命令行工具叫做 TimeBackexe,它可以修改文件的创建时间和修改时间。您可以下载这个工具,并将它和一个批处理脚本放在同一个文件夹下,然后运行批处理脚本。批处理脚本的内容大致如下:
@echo off
for %%a in (mp4) do (
for /f "tokens=1-6 delims=/: " %%b in ('TimeBack /f "%%a" ^| find "创建时间"') do (
ren "%%a" "%%a-%%b%%c%%d-%%e%%fmp4"
)
)
这个脚本会遍历当前文件夹下的所有 mp4 文件,读取它们的创建时间,并在文件名后面加上日期和时间。如果您想修改时间格式或者其他细节,您可以根据自己的需要修改脚本。
另一种方法是使用一个软件叫做 Bulk Rename Utility,它是一个强大的批量重命名工具,支持多种规则和选项。您可以下载并安装这个软件,然后打开它,选择您想要重命名的 mp4 文件,在右侧的面板中设置好重命名规则,并点击开始按钮。重命名规则中有一个选项叫做 Date (7) ,它可以让您根据文件的创建日期或者修改日期来重命名文件。您可以在这里选择合适的日期格式和分隔符。
以上就是关于在android平台录制视频时,怎么添加时间戳全部的内容,包括:在android平台录制视频时,怎么添加时间戳、可以通过视频编码获取视频吗、FFmpeg(二)filter生成视频编解码时间戳测试视频等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)