aboutsummaryrefslogtreecommitdiff
path: root/common/EncodeHelpers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/EncodeHelpers.cpp')
-rw-r--r--common/EncodeHelpers.cpp118
1 files changed, 86 insertions, 32 deletions
diff --git a/common/EncodeHelpers.cpp b/common/EncodeHelpers.cpp
index 4575197..757d064 100644
--- a/common/EncodeHelpers.cpp
+++ b/common/EncodeHelpers.cpp
@@ -7,51 +7,81 @@
#include <v4l2_codec2/common/EncodeHelpers.h>
-#include <linux/v4l2-controls.h>
+#include <string.h>
#include <C2AllocatorGralloc.h>
#include <cutils/native_handle.h>
#include <ui/GraphicBuffer.h>
#include <utils/Log.h>
-#include <v4l2_codec2/common/NalParser.h>
-
namespace android {
-uint8_t c2LevelToV4L2Level(C2Config::level_t level) {
+media::VideoCodecProfile c2ProfileToVideoCodecProfile(C2Config::profile_t profile) {
+ switch (profile) {
+ case C2Config::PROFILE_AVC_BASELINE:
+ return media::VideoCodecProfile::H264PROFILE_BASELINE;
+ case C2Config::PROFILE_AVC_MAIN:
+ return media::VideoCodecProfile::H264PROFILE_MAIN;
+ case C2Config::PROFILE_AVC_EXTENDED:
+ return media::VideoCodecProfile::H264PROFILE_EXTENDED;
+ case C2Config::PROFILE_AVC_HIGH:
+ return media::VideoCodecProfile::H264PROFILE_HIGH;
+ case C2Config::PROFILE_AVC_HIGH_10:
+ return media::VideoCodecProfile::H264PROFILE_HIGH10PROFILE;
+ case C2Config::PROFILE_AVC_HIGH_422:
+ return media::VideoCodecProfile::H264PROFILE_HIGH422PROFILE;
+ case C2Config::PROFILE_AVC_HIGH_444_PREDICTIVE:
+ return media::VideoCodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE;
+ case C2Config::PROFILE_AVC_SCALABLE_BASELINE:
+ return media::VideoCodecProfile::H264PROFILE_SCALABLEBASELINE;
+ case C2Config::PROFILE_AVC_SCALABLE_HIGH:
+ return media::VideoCodecProfile::H264PROFILE_SCALABLEHIGH;
+ case C2Config::PROFILE_AVC_STEREO_HIGH:
+ return media::VideoCodecProfile::H264PROFILE_STEREOHIGH;
+ case C2Config::PROFILE_AVC_MULTIVIEW_HIGH:
+ return media::VideoCodecProfile::H264PROFILE_MULTIVIEWHIGH;
+ default:
+ ALOGE("Unrecognizable C2 profile (value = 0x%x)...", profile);
+ return media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+}
+
+uint8_t c2LevelToLevelIDC(C2Config::level_t level) {
switch (level) {
case C2Config::LEVEL_AVC_1:
- return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
+ return 10;
case C2Config::LEVEL_AVC_1B:
- return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
+ return 9;
case C2Config::LEVEL_AVC_1_1:
- return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
+ return 11;
case C2Config::LEVEL_AVC_1_2:
- return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
+ return 12;
case C2Config::LEVEL_AVC_1_3:
- return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
+ return 13;
case C2Config::LEVEL_AVC_2:
- return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
+ return 20;
case C2Config::LEVEL_AVC_2_1:
- return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
+ return 21;
case C2Config::LEVEL_AVC_2_2:
- return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
+ return 22;
case C2Config::LEVEL_AVC_3:
- return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
+ return 30;
case C2Config::LEVEL_AVC_3_1:
- return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
+ return 31;
case C2Config::LEVEL_AVC_3_2:
- return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
+ return 32;
case C2Config::LEVEL_AVC_4:
- return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+ return 40;
case C2Config::LEVEL_AVC_4_1:
- return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
+ return 41;
case C2Config::LEVEL_AVC_4_2:
- return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
+ return 42;
case C2Config::LEVEL_AVC_5:
- return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
+ return 50;
case C2Config::LEVEL_AVC_5_1:
- return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
+ return 51;
+ case C2Config::LEVEL_AVC_5_2:
+ return 52;
default:
ALOGE("Unrecognizable C2 level (value = 0x%x)...", level);
return 0;
@@ -68,24 +98,20 @@ android_ycbcr getGraphicBlockInfo(const C2ConstGraphicBlock& block) {
height, format, 1, usage, stride);
native_handle_delete(grallocHandle);
- // Pass SW flag so that ARCVM returns the guest buffer dimensions instead
- // of the host buffer dimensions. This means we will have to convert the
- // return value from ptrs to buffer offsets ourselves.
android_ycbcr ycbcr = {};
- int32_t status = buf->lockYCbCr(GRALLOC_USAGE_SW_READ_OFTEN, &ycbcr);
+ // Usage flag without SW_READ/WRITE bits.
+ constexpr uint32_t kNonSWLockUsage = 0;
+ int32_t status = buf->lockYCbCr(kNonSWLockUsage, &ycbcr);
if (status != OK) ALOGE("lockYCbCr is failed: %d", (int)status);
buf->unlock();
-
- uintptr_t y = reinterpret_cast<uintptr_t>(ycbcr.y);
- ycbcr.y = nullptr;
- ycbcr.cb = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ycbcr.cb) - y);
- ycbcr.cr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ycbcr.cr) - y);
-
return ycbcr;
}
void extractCSDInfo(std::unique_ptr<C2StreamInitDataInfo::output>* const csd, const uint8_t* data,
size_t length) {
+ constexpr uint8_t kTypeSeqParamSet = 7;
+ constexpr uint8_t kTypePicParamSet = 8;
+
// Android frameworks needs 4 bytes start code.
constexpr uint8_t kStartCode[] = {0x00, 0x00, 0x00, 0x01};
constexpr int kStartCodeLength = 4;
@@ -101,9 +127,9 @@ void extractCSDInfo(std::unique_ptr<C2StreamInitDataInfo::output>* const csd, co
NalParser parser(data, length);
while (parser.locateNextNal()) {
if (parser.length() == 0) continue;
- uint8_t nalType = parser.type();
+ uint8_t nalType = *parser.data() & 0x1f;
ALOGV("find next NAL: type=%d, length=%zu", nalType, parser.length());
- if (nalType != NalParser::kSPSType && nalType != NalParser::kPPSType) continue;
+ if (nalType != kTypeSeqParamSet && nalType != kTypePicParamSet) continue;
if (tmpOutput + kStartCodeLength + parser.length() > tmpConfigDataEnd) {
ALOGE("Buffer overflow on extracting codec config data (length=%zu)", length);
@@ -121,4 +147,32 @@ void extractCSDInfo(std::unique_ptr<C2StreamInitDataInfo::output>* const csd, co
std::memcpy((*csd)->m.value, tmpConfigData.get(), configDataLength);
}
+NalParser::NalParser(const uint8_t* data, size_t length)
+ : mCurrNalDataPos(data), mDataEnd(data + length) {
+ mNextNalStartCodePos = findNextStartCodePos();
+}
+
+bool NalParser::locateNextNal() {
+ if (mNextNalStartCodePos == mDataEnd) return false;
+ mCurrNalDataPos = mNextNalStartCodePos + kNalStartCodeLength; // skip start code.
+ mNextNalStartCodePos = findNextStartCodePos();
+ return true;
+}
+
+const uint8_t* NalParser::data() const {
+ return mCurrNalDataPos;
+}
+
+size_t NalParser::length() const {
+ if (mNextNalStartCodePos == mDataEnd) return mDataEnd - mCurrNalDataPos;
+ size_t length = mNextNalStartCodePos - mCurrNalDataPos;
+ // The start code could be 3 or 4 bytes, i.e., 0x000001 or 0x00000001.
+ return *(mNextNalStartCodePos - 1) == 0x00 ? length - 1 : length;
+}
+
+const uint8_t* NalParser::findNextStartCodePos() const {
+ return std::search(mCurrNalDataPos, mDataEnd, kNalStartCode,
+ kNalStartCode + kNalStartCodeLength);
+}
+
} // namespace android