<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Camera2、MediaCodec錄制mp4

          共 4273字,需瀏覽 9分鐘

           ·

          2021-01-18 16:25

          PS:做想做的事,每天至少做一點(diǎn),不求做多少,慢慢改變。
          了解了音視頻的相關(guān)知識,可以先閱讀下面兩篇文章:
          本文的主要內(nèi)容是通過 Android 原生的硬編解碼框架 MediaCodec 和復(fù)用器 MediaMuxer 實(shí)現(xiàn) mp4 視頻文件的錄制,視頻數(shù)據(jù)源由 Camera2 來提供,這里重點(diǎn)是編碼、復(fù)用的這個過程而不是 mp4 的錄制,如果僅僅是視頻錄制,可以選擇更方便的 MediaRecorder,按照慣例還是以案列的形式學(xué)習(xí) MediaCodec,其更多用法將在后續(xù)的文章中介紹,本文主要內(nèi)容如下:
          1. Camera2的使用

          2. MediaCodec輸入方式

          3. MediaCodec編碼Camera2數(shù)據(jù)

          4. 錄制流程

          5. 錄制效果

          Camera2的使用

          Camera2 是從 Android 5.0 開始推出的新的相機(jī) API,最新的是 CameraX,CameraX 基于 Camera2,相較 Camera2 提供了更好用的 API,后文中涉及到的相關(guān)的 API 可以直接參考下面這張示意圖,這也是 Camera2 的使用示意圖,如下:
          來自 smewise
          具體使用可查看文末源碼。

          MediaCodec的輸入方式

          為了能夠使用 MediaCodec 進(jìn)行編碼操作,就需要將相機(jī)的數(shù)據(jù)輸入到編碼器 MediaCodec 中,可以通過兩種方式將數(shù)據(jù)寫入 MediaCodec,具體如下:
          • Surface:使用 Surface 作為編碼器 MediaCodec 的輸入,即將 MediaCodec 創(chuàng)建的 Surface 作為其輸入,這個 Surface 由 MediaCodec 的 createInputSurface 方法創(chuàng)建,當(dāng)相機(jī)將會將有效數(shù)據(jù)渲染到該 Surface 中,MediaCodec 就可以直接輸出編碼后的數(shù)據(jù)了。

          • InputBuffer:使用輸入緩沖區(qū)作為編碼器 MediaCodec 的輸入,這里需要填充的數(shù)據(jù)就是原始幀數(shù)據(jù),對應(yīng) Camera2 來說可直接通過 ImageReader 來進(jìn)行幀數(shù)據(jù)的獲取,獲取到的 Image 包含了寬度、高度、格式、時間戳及 YUV 數(shù)據(jù)分量等信息,可控程度更高。

          MediaCodec編碼Camera2數(shù)據(jù)

          簡單說一下 MediaCodec 的數(shù)據(jù)處理方式,Android 5.0 之前只支持 ByteBuffer[] 的同步方式,之后推薦使用 ByteBuffer 的同步、異步方式,這里使用 ByteBuffer 的同步方式,涉及的流程主要是視頻數(shù)據(jù)編碼和復(fù)用,因?yàn)榍懊嫣岬?MediaCodec 的輸入是通過 Surface 完成的,所以這里只需要獲取的已經(jīng)編碼好的數(shù)據(jù)和使用復(fù)用器 MediaMuxer 來實(shí)現(xiàn) Mp4 文件的生成,關(guān)鍵代碼如下:
          1//?返回已成功編碼的輸出緩沖區(qū)的索引
          2var?outputBufferId:?Int?=?mMediaCodec.dequeueOutputBuffer(bufferInfo,?0)
          3if?(outputBufferId?==?MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)?{
          4????//?添加視頻軌道
          5????mTrackIndex?=?mMediaMuxer.addTrack(mMediaCodec.outputFormat)
          6????mMediaMuxer.start()
          7????mStartMuxer?=?true
          8}?else?{
          9????while?(outputBufferId?>=?0)?{
          10????????if?(!mStartMuxer)?{
          11????????????Log.i(TAG,?"MediaMuxer?not?start")
          12????????????continue
          13????????}
          14????????//?獲取有效數(shù)據(jù)
          15????????val?outputBuffer?=?mMediaCodec.getOutputBuffer(outputBufferId)??:?continue
          16????????outputBuffer.position(bufferInfo.offset)
          17????????outputBuffer.limit(bufferInfo.offset?+?bufferInfo.size)
          18????????if?(pts?==?0L)?{
          19????????????pts?=?bufferInfo.presentationTimeUs
          20????????}
          21????????bufferInfo.presentationTimeUs?=?bufferInfo.presentationTimeUs?-?pts
          22????????//?將數(shù)據(jù)寫入復(fù)用器以生成文件
          23????????mMediaMuxer.writeSampleData(mTrackIndex,?outputBuffer,?bufferInfo)
          24????????Log.d(
          25????????????TAG,
          26????????????"pts?=?${bufferInfo.presentationTimeUs?/?1000000.0f}?s?,${pts?/?1000}?ms"
          27????????)
          28????????mMediaCodec.releaseOutputBuffer(outputBufferId,?false)
          29????????outputBufferId?=?mMediaCodec.dequeueOutputBuffer(bufferInfo,?0)
          30????}
          31}

          錄制流程

          這里使用 Surface 作為編碼器 MediaCodec 的輸入,在 MediaCodec 進(jìn)入配置狀態(tài)才可以創(chuàng)建 Surface,也就是 createInputSurface 只能在 configure 與 start之間調(diào)用,參考如下:
          1//?配置狀態(tài)
          2mMediaCodec.configure(mediaFormat,?null,?null,?MediaCodec.CONFIGURE_FLAG_ENCODE)
          3//?創(chuàng)建Surface作為MediaCodec的輸入,createInputSurface只能在configure與start之間調(diào)用創(chuàng)建Surface
          4mSurface?=?mMediaCodec.createInputSurface()
          5//?start?...
          將其添加到 SessionConfiguration 的輸出 Surface 列表中,參考如下:
          1//?創(chuàng)建CaptureSession
          2@RequiresApi(Build.VERSION_CODES.P)
          3private?suspend?fun?createCaptureSession():?CameraCaptureSession?=?suspendCoroutine?{?cont?->
          4????val?outputs?=?mutableListOf()
          5????//?預(yù)覽Surface??????????????????????????????????????????????????????????????????????????????
          6????outputs.add(OutputConfiguration(mSurface))
          7????//?添加MediaCodec用作輸入的Surface???????????????????????????????????????????????????????????????????????????????
          8????outputs.add(OutputConfiguration(EncodeManager.getSurface()))
          9????val?sessionConfiguration?=?SessionConfiguration(
          10????????SessionConfiguration.SESSION_REGULAR,
          11????????outputs,?mExecutor,?...)
          12????mCameraDevice.createCaptureSession(sessionConfiguration)
          13}
          然后發(fā)起 CaptureRequest 開啟預(yù)覽和接收 Surface 輸出,同時開啟編碼,參考如下:
          1//?添加預(yù)覽的Surface和生成Image的Surface
          2mCaptureRequestBuild?=?mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
          3val?sur?=?EncodeManager.getSurface()
          4mCaptureRequestBuild.addTarget(sur)
          5mCaptureRequestBuild.addTarget(mSurface)
          6
          7//?設(shè)置各種參數(shù)
          8mCaptureRequestBuild.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,?1)?//?視頻穩(wěn)定功能是否激活
          9//?發(fā)送CaptureRequest
          10mCameraCaptureSession.setRepeatingRequest(
          11????mCaptureRequestBuild.build(),
          12????null,
          13????mCameraHandler
          14)
          15//?開始編碼
          16EncodeManager.startEncode()

          錄制效果

          可在公眾號后臺回復(fù)關(guān)鍵字【record】獲取源碼。
          推薦閱讀:
          瀏覽 119
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆成人在线视频 | 久久99精品久久只有精品 | 亚洲一级片免费看 | 一级A片黄 | 亚洲男女免费视频 |