1. View the stream configuration information when SnapDragonCamera turns on the HFR function
By grabbing the log, the following log is obtained:
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:855 configure_streams() Number of streams: 2
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:871 configure_streams() stream[0] = 0xe5fad694 - info:
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:874 configure_streams() format : 34, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:876 configure_streams() width : 640
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:878 configure_streams() height : 480
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:881 configure_streams() stream_type : 00000000, CAMERA3_STREAM_OUTPUT
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:883 configure_streams() usage : 00000900
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:885 configure_streams() max_buffers : 0
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:888 configure_streams() rotation : 00000000, CAMERA3_STREAM_ROTATION_0
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:891 configure_streams() data_space : 00000000, HAL_DATASPACE_UNKNOWN
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:893 configure_streams() priv : 0x0
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:871 configure_streams() stream[1] = 0xe5fad6f4 - info:
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:874 configure_streams() format : 34, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:876 configure_streams() width : 640
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:878 configure_streams() height : 480
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:881 configure_streams() stream_type : 00000000, CAMERA3_STREAM_OUTPUT
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:883 configure_streams() usage : 00010000
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:885 configure_streams() max_buffers : 0
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:888 configure_streams() rotation : 00000000, CAMERA3_STREAM_ROTATION_0
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:891 configure_streams() data_space : 00000103, HAL_DATASPACE_BT601_525
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:893 configure_streams() priv : 0x0
06-22 12:33:54.059 586 1032 I CamX : [ INFO][HAL ] camxhal3.cpp:901 configure_streams() operation_mode: 1
stream[0] is the preview stream. The
preview stream usage is: GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER
stream[1] is the video stream. The
video stream usage is:GRALLOC_USAGE_HW_VIDEO_ENCODER
2. When HFR configures the stream, prepare the surface
2.1 Preparation in the preview stream surface
//参考代码见frameworks\av\media\libstagefright\omx\GraphicBufferSource.cpp
void configPreviewSurface()
{
ALOGD("%s,%d E .", __FUNCTION__,__LINE__);
// Setup a buffer queue
BufferQueue::createBufferQueue(&mspGbProducer, &mspGbConsumer);
mPreviewSurface = new Surface(mspGbProducer);
String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d",
m_iWidth, m_iHeight, m_iFormat, MAX_BUFFER_NUM, getpid());
mspGbConsumer->setConsumerName(consumerName);
// Set default size and format
mspGbConsumer->setDefaultBufferSize(640, 480);
mspGbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_YCbCr_420_888);
uint32_t consumerUsage;
consumerUsage |= GRALLOC_USAGE_HW_TEXTURE|GRALLOC_USAGE_HW_COMPOSER;
mspGbConsumer->setConsumerUsageBits(consumerUsage);
int32_t dataSpace= 0;
ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
mspGbConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
wp<BufferQueue::ConsumerListener> listener =
static_cast<BufferQueue::ConsumerListener*>(this);
sp<IConsumerListener> proxy =
new BufferQueue::ProxyConsumerListener(listener);
mInitCheck = mspGbConsumer->consumerConnect(proxy, false);
ALOGD("%s,%d X .", __FUNCTION__,__LINE__);
}
2.2 Preparation in the video stream surface
//参考代码见frameworks\av\media\libstagefright\omx\GraphicBufferSource.cpp
void configVideoSurface()
{
ALOGD("%s,%d E .", __FUNCTION__,__LINE__);
// Setup a buffer queue
BufferQueue::createBufferQueue(&mspGbProducer, &mspGbConsumer);
mVideoSurface = new Surface(mspGbProducer);
String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d",
m_iWidth, m_iHeight, m_iFormat, MAX_BUFFER_NUM, getpid());
mspGbConsumer->setConsumerName(consumerName);
// Set default size and format
mspGbConsumer->setDefaultBufferSize(640, 480);
mspGbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_YCbCr_420_888);
uint32_t consumerUsage;
consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
mspGbConsumer->setConsumerUsageBits(consumerUsage);
int32_t dataSpace= HAL_DATASPACE_BT601_525;
ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
mspGbConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
wp<BufferQueue::ConsumerListener> listener =
static_cast<BufferQueue::ConsumerListener*>(this);
sp<IConsumerListener> proxy =
new BufferQueue::ProxyConsumerListener(listener);
mInitCheck = mspGbConsumer->consumerConnect(proxy, false);
ALOGD("%s,%d X .", __FUNCTION__,__LINE__);
}
3. 配置ConstrainedHighSpeed Stream
int configureDevice()
{
binder::Status res;
setupPreviewSurface();
#ifdef ENABLE_FEATURE_HFR
setupVideoSurface();
#endif
ALOGD("waitUntilIdle E");
res = mspDevice->waitUntilIdle();
ALOGD("waitUntilIdle X");
res = mspDevice->beginConfigure();
ALOGD("create preview Stream E");
OutputConfiguration previewOutPut(mspGbProducer, /*rotation*/ 0);
res = mspDevice->createStream(previewOutPut, &mPreviewStreamId);
ALOGD("create preview Stream mPreviewStreamId = %d X",mPreviewStreamId);
#ifdef ENABLE_FEATURE_HFR
ALOGD("create video Stream E");
OutputConfiguration videoOutPut = OutputConfiguration(mspVideoGbpProducer, /*rotation*/ 0);
res = mspDevice->createStream(videoOutPut, &mVideoStreamId);
ALOGD("create video Stream mCaptureStreamId = %d X",mVideoStreamId);
#endif
ALOGD("endConfigure E .");
#ifdef ENABLE_FEATURE_HFR
res = mspDevice->endConfigure(/*isConstrainedHighSpeed*/true);
#else
res = mspDevice->endConfigure(/*isConstrainedHighSpeed*/false);
#endif
ALOGD("endConfigure X .");
return 0;
}
4. HFR preview and video data application
After configuring the high-speed stream, you can apply for preview and video data.
The frame rate of the HFR preview stream and the frame rate of the video stream are multiples. The multiple is called batchSize, and its related information is defined in the HAL layer:
//vendor\qcom\proprietary\camx\src\hwl\titan17x/camxtitan17xcontext.cpp
CamxResult Titan17xContext::GetStaticCaps(
PlatformStaticCaps* pCaps)
{
CamxResult result = CamxResultSuccess;
CSLCameraPlatform CSLPlatform = {
};
UINT32 size = 0;
UINT32 numIPEs = 2;
UINT32 HFRPreviewFPS = 30;
// Initialize platform specific static capabilities
...
CAMX_LOG_INFO(CamxLogGroupHWL, "HFR Preview FPS %d", HFRPreviewFPS);
// Availiable HFR configurations
pCaps->numDefaultHFRVideoSizes = NumSupportedHFRVideoSizes;
for (UINT8 i = 0; i < pCaps->numDefaultHFRVideoSizes; i++)
{
pCaps->defaultHFRVideoSizes[i].width = SupportedHFRVideoSizes[i].width;
pCaps->defaultHFRVideoSizes[i].height = SupportedHFRVideoSizes[i].height;
pCaps->defaultHFRVideoSizes[i].minFPS = SupportedHFRVideoSizes[i].minFPS;
pCaps->defaultHFRVideoSizes[i].maxFPS = SupportedHFRVideoSizes[i].maxFPS;
pCaps->defaultHFRVideoSizes[i].batchSizeMax = SupportedHFRVideoSizes[i].maxFPS / HFRPreviewFPS;
}
...
return result;
}
The conclusion that can be drawn from the above information is:
HFR (high frame rate) is actually the frame rate of the video stream, and it has no effect on the frame rate of the preview stream.
In order to realize that the video stream is a multiple of the batchSize of the preview stream, the implementation scheme of cameraAPI2 is:
by calling submitRequestList
(submit multiple request applications at the same time each time. The code is as follows:
camera2::CaptureRequest singleTargetRequest;//recoding
singleTargetRequest.mMetadata = mRequestTemplate;
//request.mSurfaceList.add(mspSurface);
singleTargetRequest.mSurfaceList.add(videoSurface);
singleTargetRequest.mIsReprocess = false;
camera2::CaptureRequest doubleTargetRequest;//recording+preview
doubleTargetRequest.mMetadata = mRequestTemplate;
doubleTargetRequest.mSurfaceList.add(mspSurface);
doubleTargetRequest.mSurfaceList.add(videoSurface);
doubleTargetRequest.mIsReprocess = false;
//我做的Demo中preview为30fps,videorecording为120fps,batchsize是4,
//就是一次submitRequestList需要提交4个request,
//一个preview+recording,三个recording
const ::std::vector< ::android::hardware::camera2::CaptureRequest>requestList{
doubleTargetRequestBuilder/*first Request must be doubleTargetRequest*/,
singleTargetRequestBuilder,singleTargetRequestBuilder,singleTargetRequestBuilder};
camera2::utils::SubmitInfo info;
res = mspDevice->submitRequestList(requestList, /*streaming*/ true, /*out*/ &info);
So far the HFR study summary is complete