Android

您所在的位置:网站首页 安卓手机录制视频是什么格式 Android

Android

2024-07-16 05:18| 来源: 网络整理| 查看: 265

前言:

      目前有很多APP都有视频录像的功能,eg: 微信、抖音等。那么视频录制的时候yuv数据是怎么传输的呢?

       视频录制(单指video流)其实就是两部分,第一部分是从camera获取yuv流,第二部分是对yuv流进行编码。那么yuv数据的具体传输是怎么样的呢?

       目前安卓框架支持两种yuv数据的传输方式:

       第一种是APP从camera获取录制的yuv,然后一帧帧再送给codec去做编码。

       第二种是APP设置好camera和encoder的传输关系,camera直接把数据传给encoder,不用经过app去中转。

        两种方案的优劣也很明显,第一种数据需要经过APP,还要有数据的拷贝等操作,耗时耗内存,但是这种方案就有利于APP加自己的算法去做一些处理,eg: 美颜,加emoji等。第二种方案,数据不用传给app,所以实现起来很简单,节省空间和时间,但是APP厂商无法用自己的算法。

      综上,其实现在大部分app都会使用第一种方案,因为app都有自己的视频算法。手机厂商自带的系统相机更偏向第二种,因为系统相机的算法可以在camera底层直接实现,然后直接送给codec去做处理。

 

方案简介: 方案一:

        APP从camera获取录制的yuv,然后一帧帧再送给codec去做编码。此处我们只看codec和app的交互.

// step1 请求一个输入缓存的bufferIndex int bufferIndex = mediaCodec.dequeueInputBuffer(TIME_OUT_US /* timeoutUs */); // 取出mAvailPortBuffers的第一个buffer // step2 根据bufferIndex得到buffer ByteBuffer buffer = mediaCodec.getInputBuffer(bufferIndex); // step3 给buffer中写入数据 int size = mediaExtractor.readSampleData(buffer, 0 /* offset */); // memcpy((uint8_t *)buffer->data(), src, it->mBuffer->range_length()); // step4 buffer入队 mediaCodec.queueInputBuffer(bufferIndex,0 /* offset */,size, timestampUs, signaledEos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);

 

方案二:

      APP设置好camera和encoder的传输关系,camera直接把数据传给encoder,不用经过app去中转。

      这种方案就是一个生产者消费者模式,app把camera的surface当做生产者送给codec,然后codec有一个消费者去消耗数据。

app调用MediaCodec::setInputSurface,此函数会把camera当做一个producer传给mediacodec, 然后: ACodec::initiateSetInputSurface ACodec::LoadedState::onSetInputSurface // mCodec->mGraphicBufferSource = surface->getBufferSource(); ACodec::LoadedState::setupInputSurface // 在此函数中会做很多对mGraphicBufferSource的设置 mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace),将mGraphicBufferSource和omx关联起来。 LWGraphicBufferSource::configure IGraphicBufferSource::configure 接口类,在TWGraphicBufferSource被实现 TWGraphicBufferSource::configure omxNode->setInputSurface(mOmxBufferSource) 和 mBase->configure(new TWOmxNodeWrapper(omxNode),toRawDataspace (dataspace),def.nBufferCountActual,def.format.video.nFrameWidth,def.format.video.nFrameHeight,consumerUsage) LWOmxNode::setInputSurface 在此函数中mBase->setInputSurface(new TWOmxBufferSource(bufferSource)) OmxGraphicBufferSource::configure GraphicBufferSource::configure   GraphicBufferSource::GraphicBufferSource()中BufferQueue::createBufferQueue(&mProducer, &mConsumer); 在mConsumer就会调用acquireBuffer、releaseBuffer等函数,实现数据的写入读出。 设置完成之后上层可以通过调用getIGraphicBufferProducer获取mProducer并返回给APP。mConsumer会调用mConsumer->consumerConnect连接到listener。 BufferQueueProducer调用queueBuffer、requestBuffer、dequeueBuffer等函数实现数据的写入读出。BufferQueueProducer在调用dequeueBuffer中会通知frameAvailableListener->onFrameAvailable。然后会调用到GraphicBufferSource::onFrameAvailable,然后调用过程如下: GraphicBufferSource::onFrameAvailable GraphicBufferSource::onBufferAcquired_l GraphicBufferSource::fillCodecBuffer_l GraphicBufferSource::submitBuffer_l OmxGraphicBufferSource.cpp中submitBuffer 调用 mOmxNode->emptyBuffer

    

总结:

      以上就是视频录制的两种数据传输方式,其实无论那种方式都离不开生产者消费者模型。整个buffer的轮转无非就是写入和读出,差别就在于从哪里写入和读出。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3