Camera: Heic: Update codec quality per shot

Update codec quality setting at the time of:
- Input pending frame creation if there is no inflight encoding.
- Any pending input frame is done processing.

Note that since there is no way for camera framework to synchronize
quality setting per-frame when encoder runs in surface mode, the update
of quality is on best-effort basis.

Test: vendor testing, and camera CTS
Bug: 140506016
Change-Id: I58ddc9302b1507428ccf42f4c77c6624f1c600ba
gugelfrei
Shuzhen Wang 5 years ago
parent b7b2f5d865
commit 62f49ed064

@ -67,6 +67,7 @@ HeicCompositeStream::HeicCompositeStream(wp<CameraDeviceBase> device,
mDequeuedOutputBufferCnt(0),
mLockedAppSegmentBufferCnt(0),
mCodecOutputCounter(0),
mQuality(-1),
mGridTimestampUs(0) {
}
@ -525,6 +526,12 @@ void HeicCompositeStream::compilePendingInputLocked() {
mPendingInputFrames[it->first].orientation = it->second.first;
mPendingInputFrames[it->first].quality = it->second.second;
mSettingsByTimestamp.erase(it);
// Set encoder quality if no inflight encoding
if (mPendingInputFrames.size() == 1) {
int32_t newQuality = mPendingInputFrames.begin()->second.quality;
updateCodecQualityLocked(newQuality);
}
}
while (!mInputAppSegmentBuffers.empty()) {
@ -851,17 +858,6 @@ status_t HeicCompositeStream::startMuxerForInputFrame(nsecs_t timestamp, InputFr
strerror(-res), res);
return res;
}
// Set encoder quality
{
sp<AMessage> qualityParams = new AMessage;
qualityParams->setInt32(PARAMETER_KEY_VIDEO_BITRATE, inputFrame.quality);
res = mCodec->setParameters(qualityParams);
if (res != OK) {
ALOGE("%s: Failed to set codec quality: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
}
ssize_t trackId = inputFrame.muxer->addTrack(inputFrame.format);
if (trackId < 0) {
@ -1148,16 +1144,30 @@ void HeicCompositeStream::releaseInputFrameLocked(InputFrame *inputFrame /*out*/
void HeicCompositeStream::releaseInputFramesLocked() {
auto it = mPendingInputFrames.begin();
bool inputFrameDone = false;
while (it != mPendingInputFrames.end()) {
auto& inputFrame = it->second;
if (inputFrame.error ||
(inputFrame.appSegmentWritten && inputFrame.pendingOutputTiles == 0)) {
releaseInputFrameLocked(&inputFrame);
it = mPendingInputFrames.erase(it);
inputFrameDone = true;
} else {
it++;
}
}
// Update codec quality based on first upcoming input frame.
// Note that when encoding is in surface mode, currently there is no
// way for camera service to synchronize quality setting on a per-frame
// basis: we don't get notification when codec is ready to consume a new
// input frame. So we update codec quality on a best-effort basis.
if (inputFrameDone) {
auto firstPendingFrame = mPendingInputFrames.begin();
if (firstPendingFrame != mPendingInputFrames.end()) {
updateCodecQualityLocked(firstPendingFrame->second.quality);
}
}
}
status_t HeicCompositeStream::initializeCodec(uint32_t width, uint32_t height,
@ -1546,6 +1556,20 @@ size_t HeicCompositeStream::calcAppSegmentMaxSize(const CameraMetadata& info) {
return maxAppsSegment * (2 + 0xFFFF) + sizeof(struct CameraBlob);
}
void HeicCompositeStream::updateCodecQualityLocked(int32_t quality) {
if (quality != mQuality) {
sp<AMessage> qualityParams = new AMessage;
qualityParams->setInt32(PARAMETER_KEY_VIDEO_BITRATE, quality);
status_t res = mCodec->setParameters(qualityParams);
if (res != OK) {
ALOGE("%s: Failed to set codec quality: %s (%d)",
__FUNCTION__, strerror(-res), res);
} else {
mQuality = quality;
}
}
}
bool HeicCompositeStream::threadLoop() {
int64_t currentTs = INT64_MAX;
bool newInputAvailable = false;

@ -199,6 +199,7 @@ private:
size_t top, size_t left, size_t width, size_t height);
void initCopyRowFunction(int32_t width);
static size_t calcAppSegmentMaxSize(const CameraMetadata& info);
void updateCodecQualityLocked(int32_t quality);
static const nsecs_t kWaitDuration = 10000000; // 10 ms
static const int32_t kDefaultJpegQuality = 99;
@ -240,6 +241,7 @@ private:
std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
std::queue<int64_t> mCodecOutputBufferTimestamps;
size_t mCodecOutputCounter;
int32_t mQuality;
// Keep all incoming Yuv buffer pending tiling and encoding (for HEVC YUV tiling only)
std::vector<int64_t> mInputYuvBuffers;

Loading…
Cancel
Save