diff options
Diffstat (limited to 'common/EncodeHelpers.cpp')
-rw-r--r-- | common/EncodeHelpers.cpp | 118 |
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 |