Loading media/codec2/components/apv/C2SoftApvDec.cpp +106 −4 Original line number Diff line number Diff line Loading @@ -279,6 +279,10 @@ class C2SoftApvDec::IntfImpl : public SimpleInterface<void>::BaseParams { if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) { pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010); } if (isHalPixelFormatSupported((AHardwareBuffer_Format)AHARDWAREBUFFER_FORMAT_YCbCr_P210)) { pixelFormats.push_back(AHARDWAREBUFFER_FORMAT_YCbCr_P210); } // If color format surface isn't added to supported formats, there is no way to know // when the color-format is configured to surface. This is necessary to be able to // choose 10-bit format while decoding 10-bit clips in surface mode. Loading Loading @@ -374,6 +378,8 @@ class C2SoftApvDec::IntfImpl : public SimpleInterface<void>::BaseParams { (void)mayBlock; ALOGV("%s", __FUNCTION__); // take default values for all unspecified fields, and coded values for specified ones ALOGV("%s - coded range: %u, primaries: %u, transfer: %u, matrix: %u", __func__, coded.v.range, coded.v.primaries, coded.v.transfer, coded.v.matrix); me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range; me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED ? def.v.primaries : coded.v.primaries; Loading Loading @@ -717,6 +723,22 @@ static void copyBufferFromYUV420ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* ds } } static void copyBufferP210(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY, const uint16_t *srcUV, size_t srcYStride, size_t srcUVStride, size_t dstYStride, size_t dstUVStride, size_t width, size_t height) { for (size_t y = 0; y < height; ++y) { memcpy(dstY, srcY, width * sizeof(uint16_t)); srcY += srcYStride; dstY += dstYStride; } for (size_t y = 0; y < height; ++y) { memcpy(dstUV, srcUV, width * sizeof(uint16_t)); srcUV += srcUVStride; dstUV += dstUVStride; } } static void copyBufferFromYUV422ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY, const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride, size_t srcUStride, Loading Loading @@ -992,28 +1014,81 @@ void C2SoftApvDec::process(const std::unique_ptr<C2Work>& work, } } void C2SoftApvDec::getVuiParams(VuiColorAspects* buffer) { VuiColorAspects vuiColorAspects; vuiColorAspects.primaries = buffer->primaries; vuiColorAspects.transfer = buffer->transfer; vuiColorAspects.coeffs = buffer->coeffs; vuiColorAspects.fullRange = buffer->fullRange; // convert vui aspects to C2 values if changed if (!(vuiColorAspects == mBitstreamColorAspects)) { mBitstreamColorAspects = vuiColorAspects; ColorAspects sfAspects; C2StreamColorAspectsInfo::input codedAspects = { 0u }; ColorUtils::convertIsoColorAspectsToCodecAspects( vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs, vuiColorAspects.fullRange, sfAspects); if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) { codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED; } if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) { codedAspects.range = C2Color::RANGE_UNSPECIFIED; } if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) { codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED; } if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) { codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED; } ALOGV("colorAspects: primaries:%d, transfer:%d, coeffs:%d, fullRange:%d", codedAspects.primaries, codedAspects.transfer, codedAspects.matrix, codedAspects.range); std::vector<std::unique_ptr<C2SettingResult>> failures; mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures); } } status_t C2SoftApvDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool, const std::unique_ptr<C2Work>& work) { if (!(work && pool)) return BAD_VALUE; oapv_imgb_t* imgbOutput; oapv_imgb_t* imgbOutput = nullptr; std::shared_ptr<C2GraphicBlock> block; if (ofrms.num_frms > 0) { for(int i = 0; i < ofrms.num_frms; i++) { oapv_frm_t* frm = &ofrms.frm[0]; if(frm->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) { imgbOutput = frm->imgb; break; } } if(imgbOutput == nullptr) { ALOGW("No OAPV primary frame"); return false; } } else { ALOGW("No output frames"); return false; } bool isMonochrome = OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CS_YCBCR400; // TODO: use bitstream color aspect after vui parsing VuiColorAspects colorAspect; colorAspect.primaries = 2; colorAspect.transfer = 2; colorAspect.coeffs = 2; colorAspect.fullRange = 1; getVuiParams(&colorAspect); uint32_t format = HAL_PIXEL_FORMAT_YV12; std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects; if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) { IntfImpl::Lock lock = mIntf->lock(); codedColorAspects = mIntf->getColorAspects_l(); bool allowRGBA1010102 = false; if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 && codedColorAspects->matrix == C2Color::MATRIX_BT2020 && Loading Loading @@ -1070,7 +1145,34 @@ status_t C2SoftApvDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool, size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc; size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc; if (format == HAL_PIXEL_FORMAT_YCBCR_P010) { if(format == AHARDWAREBUFFER_FORMAT_YCbCr_P210) { if(OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) { const uint16_t *srcY = (const uint16_t *)imgbOutput->a[0]; const uint16_t *srcU = (const uint16_t *)imgbOutput->a[1]; const uint16_t *srcV = (const uint16_t *)imgbOutput->a[2]; size_t srcYStride = imgbOutput->s[0] / 2; size_t srcUStride = imgbOutput->s[1] / 2; size_t srcVStride = imgbOutput->s[2] / 2; dstYStride /= 2; dstUStride /= 2; dstVStride /= 2; ALOGV("OAPV_CS_P210 buffer"); copyBufferP210((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcYStride, srcUStride, dstYStride, dstUStride, mWidth, mHeight); } else { ALOGE("Not supported convder from bd:%d, format: %d(%s), to format: %d(%s)", OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs), OAPV_CS_GET_FORMAT(imgbOutput->cs), OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420 ? "YUV420" : (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422 ? "YUV422" : "UNKNOWN"), format, format == HAL_PIXEL_FORMAT_YCBCR_P010 ? "P010" : (format == HAL_PIXEL_FORMAT_YCBCR_420_888 ? "YUV420" : (format == HAL_PIXEL_FORMAT_YV12 ? "YV12" : "UNKNOWN")) ); } } else if(format == HAL_PIXEL_FORMAT_YCBCR_P010) { if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) { const uint16_t* srcY = (const uint16_t*)imgbOutput->a[0]; const uint16_t* srcU = (const uint16_t*)imgbOutput->a[1]; Loading media/codec2/components/apv/C2SoftApvDec.h +22 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,26 @@ struct C2SoftApvDec final : public SimpleC2Component { uint32_t mHeight; bool mSignalledOutputEos; bool mSignalledError; // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid // converting them to C2 values for each frame struct VuiColorAspects { uint8_t primaries; uint8_t transfer; uint8_t coeffs; uint8_t fullRange; // default color aspects VuiColorAspects() : primaries(C2Color::PRIMARIES_UNSPECIFIED), transfer(C2Color::TRANSFER_UNSPECIFIED), coeffs(C2Color::MATRIX_UNSPECIFIED), fullRange(C2Color::RANGE_UNSPECIFIED) { } bool operator==(const VuiColorAspects &o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } } mBitstreamColorAspects; oapvd_t oapvdHandle; oapvm_t oapvmHandle; Loading @@ -126,6 +146,8 @@ struct C2SoftApvDec final : public SimpleC2Component { int outputCsp; void getVuiParams(VuiColorAspects* buffer); C2_DO_NOT_COPY(C2SoftApvDec); }; Loading media/codec2/components/apv/C2SoftApvEnc.cpp +33 −78 Original line number Diff line number Diff line Loading @@ -226,6 +226,9 @@ class C2SoftApvEnc::IntfImpl : public SimpleInterface<void>::BaseParams { if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) { pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010); } if (isHalPixelFormatSupported((AHardwareBuffer_Format)AHARDWAREBUFFER_FORMAT_YCbCr_P210)) { pixelFormats.push_back(AHARDWAREBUFFER_FORMAT_YCbCr_P210); } addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) .withDefault(new C2StreamPixelFormatInfo::input( 0u, HAL_PIXEL_FORMAT_YCBCR_P010)) Loading Loading @@ -623,12 +626,6 @@ c2_status_t C2SoftApvEnc::initEncoder() { return C2_NO_MEMORY; } /* Calculate SDR to HDR mapping values */ mSdrToHdrMapping.clear(); for (int32_t i = 0; i < 256; i++) { mSdrToHdrMapping.push_back((uint16_t)(i * 1023 / 255 + 0.5)); } mStarted = true; mInitEncoder = true; return C2_OK; Loading Loading @@ -692,26 +689,48 @@ c2_status_t C2SoftApvEnc::setEncodeArgs(oapv_frms_t* inputFrames, const C2Graphi switch (layout.type) { case C2PlanarLayout::TYPE_RGB: [[fallthrough]]; case C2PlanarLayout::TYPE_RGBA: { // TODO: Add RGBA1010102 support ALOGE("Not supported RGB color format"); return C2_BAD_VALUE; case C2PlanarLayout::TYPE_RGBA: { [[fallthrough]]; } case C2PlanarLayout::TYPE_YUVA: { ALOGV("Convert from ABGR2101010 to P210"); uint16_t *dstY, *dstU, *dstV; dstY = (uint16_t*)inputFrames->frm[0].imgb->a[0]; dstU = (uint16_t*)inputFrames->frm[0].imgb->a[1]; dstV = (uint16_t*)inputFrames->frm[0].imgb->a[2]; convertRGBA1010102ToYUV420Planar16(dstY, dstU, dstV, (uint32_t*)(input->data()[0]), layout.planes[layout.PLANE_Y].rowInc / 4, width, height, mColorAspects->matrix, mColorAspects->range); break; } case C2PlanarLayout::TYPE_YUV: { if (IsP010(*input)) { if (mColorFormat == OAPV_CF_YCBCR422) { ColorConvertP010ToYUV422P10le(input, inputFrames->frm[0].imgb); } else if (mColorFormat == OAPV_CF_PLANAR2) { ColorConvertP010ToP210(input, inputFrames->frm[0].imgb); uint16_t *srcY = (uint16_t*)(input->data()[0]); uint16_t *srcUV = (uint16_t*)(input->data()[1]); uint16_t *dstY = (uint16_t*)inputFrames->frm[0].imgb->a[0]; uint16_t *dstUV = (uint16_t*)inputFrames->frm[0].imgb->a[1]; convertP010ToP210(dstY, dstUV, srcY, srcUV, input->width(), input->width(), input->width(), input->height()); } else { ALOGE("Not supported color format. %d", mColorFormat); return C2_BAD_VALUE; } } else if (IsNV12(*input)) { ColorConvertNv12ToP210(input, inputFrames->frm[0].imgb); } else if (IsNV21(*input)) { ColorConvertNv12ToP210(input, inputFrames->frm[0].imgb); uint8_t *srcY = (uint8_t*)input->data()[0]; uint8_t *srcUV = (uint8_t*)input->data()[1]; uint16_t *dstY = (uint16_t*)inputFrames->frm[0].imgb->a[0]; uint16_t *dstUV = (uint16_t*)inputFrames->frm[0].imgb->a[1]; convertSemiPlanar8ToP210(dstY, dstUV, srcY, srcUV, input->width(), input->width(), input->width(), input->width(), input->width(), input->height(), CONV_FORMAT_I420); } else if (IsYUV420(*input)) { return C2_BAD_VALUE; } else if (IsI420(*input)) { Loading @@ -731,46 +750,6 @@ c2_status_t C2SoftApvEnc::setEncodeArgs(oapv_frms_t* inputFrames, const C2Graphi return C2_OK; } void C2SoftApvEnc::ColorConvertNv12ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb) { auto width = input->width(); auto height = input->height(); auto* yPlane = (uint8_t*)input->data()[0]; auto* uvPlane = (uint8_t*)input->data()[1]; auto* dst = (uint16_t*)imgb->a[0]; int32_t lumaOffset = 0; for (int32_t y = 0; y < height; ++y) { for (int32_t x = 0; x < width; ++x) { lumaOffset = y * width + x; dst[lumaOffset] = (mSdrToHdrMapping[yPlane[lumaOffset]] << 6) | ((mSdrToHdrMapping[yPlane[lumaOffset]] & 0x300) >> 3); } } auto* dst_uv = (uint16_t*)imgb->a[1]; uint32_t uvDstStride = width; int32_t srcOffset = 0; int32_t dstOffset1 = 0, dstOffset2 = 0; int32_t tmp1 = 0, tmp2 = 0; for (int32_t y = 0; y < height / 2; ++y) { for (int32_t x = 0; x < width; x += 2) { srcOffset = y * width + x; dstOffset1 = (y * 2) * width + x; dstOffset2 = ((y * 2) + 1) * width + x; tmp1 = (mSdrToHdrMapping[uvPlane[srcOffset]] << 6) | ((mSdrToHdrMapping[uvPlane[srcOffset]] & 0x300) >> 3); tmp2 = (mSdrToHdrMapping[uvPlane[srcOffset + 1]] << 6) | ((mSdrToHdrMapping[uvPlane[srcOffset + 1]] & 0x300) >> 3); dst_uv[dstOffset1] = (uint16_t)tmp1; dst_uv[dstOffset1 + 1] = (uint16_t)tmp2; dst_uv[dstOffset2] = (uint16_t)tmp1; dst_uv[dstOffset2 + 1] = (uint16_t)tmp2; } } } C2Config::level_t C2SoftApvEnc::decisionApvLevel(int32_t width, int32_t height, int32_t fps, int32_t bitrate, int32_t band) { C2Config::level_t level = C2Config::LEVEL_APV_1_BAND_0; Loading Loading @@ -885,30 +864,6 @@ C2Config::level_t C2SoftApvEnc::decisionApvLevel(int32_t width, int32_t height, return level; } void C2SoftApvEnc::ColorConvertP010ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb) { auto width = input->width(); auto height = input->height(); auto* yPlane = (uint8_t*)input->data()[0]; auto* uvPlane = (uint8_t*)input->data()[1]; uint32_t uvStride = width * 2; auto* src = yPlane; auto* dst = (uint8_t*)imgb->a[0]; std::memcpy(dst, src, width * height * 2); auto* dst_uv = (uint8_t*)imgb->a[1]; int32_t offset1 = 0, offset2 = 0; for (int32_t y = 0; y < height / 2; ++y) { offset1 = (y * 2) * uvStride; offset2 = (y * 2 + 1) * uvStride; src = uvPlane + (y * uvStride); std::memcpy(dst_uv + offset1, src, uvStride); std::memcpy(dst_uv + offset2, src, uvStride); } } void C2SoftApvEnc::ColorConvertP010ToYUV422P10le(const C2GraphicView* const input, oapv_imgb_t* imgb) { uint32_t width = input->width(); Loading media/codec2/components/apv/C2SoftApvEnc.h +0 −3 Original line number Diff line number Diff line Loading @@ -65,9 +65,7 @@ struct C2SoftApvEnc final : public SimpleC2Component { void showEncoderParams(oapve_cdesc_t* cdsc); void ColorConvertNv12ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb); void ColorConvertP010ToYUV422P10le(const C2GraphicView* const input, oapv_imgb_t* imgb); void ColorConvertP010ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb); void createCsdData(const std::unique_ptr<C2Work>& work, oapv_bitb_t* bitb, uint32_t encodedSize); Loading Loading @@ -106,7 +104,6 @@ struct C2SoftApvEnc final : public SimpleC2Component { oapve_t mEncoderId; oapvm_t mMetaId; uint8_t* mBitstreamBuf = nullptr; std::vector<uint16_t> mSdrToHdrMapping; bool mReceivedFirstFrame = false; C2_DO_NOT_COPY(C2SoftApvEnc); }; Loading media/codec2/components/base/SimpleC2Component.cpp +82 −0 Original line number Diff line number Diff line Loading @@ -463,6 +463,19 @@ void convertP010ToYUV420Planar16(uint16_t *dstY, uint16_t *dstU, uint16_t *dstV, } } void convertP010ToP210(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY, const uint16_t *srcUV, size_t srcUVStride, size_t dstUVStride, size_t width, size_t height) { std::memcpy(dstY, srcY, width * height * sizeof(uint16_t)); int32_t offsetTop, offsetBot; for (size_t y = 0; y < (height + 1) / 2; ++y) { offsetTop = (y * 2) * dstUVStride; offsetBot = (y * 2 + 1) * dstUVStride; std::memcpy(dstUV + offsetTop, srcUV + (y * srcUVStride), srcUVStride * sizeof(uint16_t)); std::memcpy(dstUV + offsetBot, srcUV + (y * srcUVStride), srcUVStride * sizeof(uint16_t)); } } static const int16_t bt709Matrix_10bit[2][3][3] = { { { 218, 732, 74 }, { -117, -395, 512 }, { 512, -465, -47 } }, /* RANGE_FULL */ { { 186, 627, 63 }, { -103, -345, 448 }, { 448, -407, -41 } }, /* RANGE_LIMITED */ Loading Loading @@ -517,6 +530,45 @@ void convertRGBA1010102ToYUV420Planar16(uint16_t* dstY, uint16_t* dstU, uint16_t } } void convertRGBA1010102ToP210(uint16_t* dstY, uint16_t* dstUV, const uint32_t* srcRGBA, size_t srcRGBStride, size_t width, size_t height, C2Color::matrix_t colorMatrix, C2Color::range_t colorRange) { uint16_t r, g, b; int32_t i32Y, i32U, i32V; uint16_t zeroLvl = colorRange == C2Color::RANGE_FULL ? 0 : 64; uint16_t maxLvlLuma = colorRange == C2Color::RANGE_FULL ? 1023 : 940; uint16_t maxLvlChroma = colorRange == C2Color::RANGE_FULL ? 1023 : 960; // set default range as limited if (colorRange != C2Color::RANGE_FULL) { colorRange = C2Color::RANGE_LIMITED; } const int16_t(*weights)[3] = (colorMatrix == C2Color::MATRIX_BT709) ? bt709Matrix_10bit[colorRange - 1] : bt2020Matrix_10bit[colorRange - 1]; for (size_t y = 0; y < height; ++y) { for (size_t x = 0; x < width; ++x) { b = (srcRGBA[x] >> 20) & 0x3FF; g = (srcRGBA[x] >> 10) & 0x3FF; r = srcRGBA[x] & 0x3FF; i32Y = ((r * weights[0][0] + g * weights[0][1] + b * weights[0][2] + 512) >> 10) + zeroLvl; dstY[x] = (CLIP3(zeroLvl, i32Y, maxLvlLuma) << 6) & 0xFFC0; if (x % 2 == 0) { i32U = ((r * weights[1][0] + g * weights[1][1] + b * weights[1][2] + 512) >> 10) + 512; i32V = ((r * weights[2][0] + g * weights[2][1] + b * weights[2][2] + 512) >> 10) + 512; dstUV[x] = (CLIP3(zeroLvl, i32U, maxLvlChroma) << 6) & 0xFFC0; dstUV[x + 1] = (CLIP3(zeroLvl, i32V, maxLvlChroma) << 6) & 0xFFC0; } } srcRGBA += srcRGBStride; dstY += width; } } void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride, size_t srcUStride, size_t srcVStride, size_t dstStride, size_t width, Loading Loading @@ -631,6 +683,36 @@ void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uin isMonochrome); } } void convertSemiPlanar8ToP210(uint16_t *dstY, uint16_t *dstUV, const uint8_t *srcY, const uint8_t *srcUV, size_t srcYStride, size_t srcUVStride, size_t dstYStride, size_t dstUVStride, uint32_t width, uint32_t height, CONV_FORMAT_T format) { if (format != CONV_FORMAT_I420) { ALOGE("No support for semi-planar8 to P210. format is %d", format); return; } for (int32_t y = 0; y < height; ++y) { for (int32_t x = 0; x < width; ++x) { dstY[x] = ((uint16_t)((double)srcY[x] * 1023 / 255 + 0.5) << 6) & 0xFFC0; } dstY += dstYStride; srcY += srcYStride; } for (int32_t y = 0; y < height / 2; ++y) { for (int32_t x = 0; x < width; ++x) { dstUV[x] = dstUV[dstUVStride + x] = ((uint16_t)((double)srcUV[x] * 1023 / 255 + 0.5) << 6) & 0xFFC0; } srcUV += srcUVStride; dstUV += dstUVStride << 1; } } std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() { std::unique_ptr<C2Work> work = std::move(mQueue.front().work); mQueue.pop_front(); Loading Loading
media/codec2/components/apv/C2SoftApvDec.cpp +106 −4 Original line number Diff line number Diff line Loading @@ -279,6 +279,10 @@ class C2SoftApvDec::IntfImpl : public SimpleInterface<void>::BaseParams { if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) { pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010); } if (isHalPixelFormatSupported((AHardwareBuffer_Format)AHARDWAREBUFFER_FORMAT_YCbCr_P210)) { pixelFormats.push_back(AHARDWAREBUFFER_FORMAT_YCbCr_P210); } // If color format surface isn't added to supported formats, there is no way to know // when the color-format is configured to surface. This is necessary to be able to // choose 10-bit format while decoding 10-bit clips in surface mode. Loading Loading @@ -374,6 +378,8 @@ class C2SoftApvDec::IntfImpl : public SimpleInterface<void>::BaseParams { (void)mayBlock; ALOGV("%s", __FUNCTION__); // take default values for all unspecified fields, and coded values for specified ones ALOGV("%s - coded range: %u, primaries: %u, transfer: %u, matrix: %u", __func__, coded.v.range, coded.v.primaries, coded.v.transfer, coded.v.matrix); me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range; me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED ? def.v.primaries : coded.v.primaries; Loading Loading @@ -717,6 +723,22 @@ static void copyBufferFromYUV420ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* ds } } static void copyBufferP210(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY, const uint16_t *srcUV, size_t srcYStride, size_t srcUVStride, size_t dstYStride, size_t dstUVStride, size_t width, size_t height) { for (size_t y = 0; y < height; ++y) { memcpy(dstY, srcY, width * sizeof(uint16_t)); srcY += srcYStride; dstY += dstYStride; } for (size_t y = 0; y < height; ++y) { memcpy(dstUV, srcUV, width * sizeof(uint16_t)); srcUV += srcUVStride; dstUV += dstUVStride; } } static void copyBufferFromYUV422ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY, const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride, size_t srcUStride, Loading Loading @@ -992,28 +1014,81 @@ void C2SoftApvDec::process(const std::unique_ptr<C2Work>& work, } } void C2SoftApvDec::getVuiParams(VuiColorAspects* buffer) { VuiColorAspects vuiColorAspects; vuiColorAspects.primaries = buffer->primaries; vuiColorAspects.transfer = buffer->transfer; vuiColorAspects.coeffs = buffer->coeffs; vuiColorAspects.fullRange = buffer->fullRange; // convert vui aspects to C2 values if changed if (!(vuiColorAspects == mBitstreamColorAspects)) { mBitstreamColorAspects = vuiColorAspects; ColorAspects sfAspects; C2StreamColorAspectsInfo::input codedAspects = { 0u }; ColorUtils::convertIsoColorAspectsToCodecAspects( vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs, vuiColorAspects.fullRange, sfAspects); if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) { codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED; } if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) { codedAspects.range = C2Color::RANGE_UNSPECIFIED; } if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) { codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED; } if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) { codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED; } ALOGV("colorAspects: primaries:%d, transfer:%d, coeffs:%d, fullRange:%d", codedAspects.primaries, codedAspects.transfer, codedAspects.matrix, codedAspects.range); std::vector<std::unique_ptr<C2SettingResult>> failures; mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures); } } status_t C2SoftApvDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool, const std::unique_ptr<C2Work>& work) { if (!(work && pool)) return BAD_VALUE; oapv_imgb_t* imgbOutput; oapv_imgb_t* imgbOutput = nullptr; std::shared_ptr<C2GraphicBlock> block; if (ofrms.num_frms > 0) { for(int i = 0; i < ofrms.num_frms; i++) { oapv_frm_t* frm = &ofrms.frm[0]; if(frm->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) { imgbOutput = frm->imgb; break; } } if(imgbOutput == nullptr) { ALOGW("No OAPV primary frame"); return false; } } else { ALOGW("No output frames"); return false; } bool isMonochrome = OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CS_YCBCR400; // TODO: use bitstream color aspect after vui parsing VuiColorAspects colorAspect; colorAspect.primaries = 2; colorAspect.transfer = 2; colorAspect.coeffs = 2; colorAspect.fullRange = 1; getVuiParams(&colorAspect); uint32_t format = HAL_PIXEL_FORMAT_YV12; std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects; if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) { IntfImpl::Lock lock = mIntf->lock(); codedColorAspects = mIntf->getColorAspects_l(); bool allowRGBA1010102 = false; if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 && codedColorAspects->matrix == C2Color::MATRIX_BT2020 && Loading Loading @@ -1070,7 +1145,34 @@ status_t C2SoftApvDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool, size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc; size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc; if (format == HAL_PIXEL_FORMAT_YCBCR_P010) { if(format == AHARDWAREBUFFER_FORMAT_YCbCr_P210) { if(OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) { const uint16_t *srcY = (const uint16_t *)imgbOutput->a[0]; const uint16_t *srcU = (const uint16_t *)imgbOutput->a[1]; const uint16_t *srcV = (const uint16_t *)imgbOutput->a[2]; size_t srcYStride = imgbOutput->s[0] / 2; size_t srcUStride = imgbOutput->s[1] / 2; size_t srcVStride = imgbOutput->s[2] / 2; dstYStride /= 2; dstUStride /= 2; dstVStride /= 2; ALOGV("OAPV_CS_P210 buffer"); copyBufferP210((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcYStride, srcUStride, dstYStride, dstUStride, mWidth, mHeight); } else { ALOGE("Not supported convder from bd:%d, format: %d(%s), to format: %d(%s)", OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs), OAPV_CS_GET_FORMAT(imgbOutput->cs), OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420 ? "YUV420" : (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422 ? "YUV422" : "UNKNOWN"), format, format == HAL_PIXEL_FORMAT_YCBCR_P010 ? "P010" : (format == HAL_PIXEL_FORMAT_YCBCR_420_888 ? "YUV420" : (format == HAL_PIXEL_FORMAT_YV12 ? "YV12" : "UNKNOWN")) ); } } else if(format == HAL_PIXEL_FORMAT_YCBCR_P010) { if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) { const uint16_t* srcY = (const uint16_t*)imgbOutput->a[0]; const uint16_t* srcU = (const uint16_t*)imgbOutput->a[1]; Loading
media/codec2/components/apv/C2SoftApvDec.h +22 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,26 @@ struct C2SoftApvDec final : public SimpleC2Component { uint32_t mHeight; bool mSignalledOutputEos; bool mSignalledError; // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid // converting them to C2 values for each frame struct VuiColorAspects { uint8_t primaries; uint8_t transfer; uint8_t coeffs; uint8_t fullRange; // default color aspects VuiColorAspects() : primaries(C2Color::PRIMARIES_UNSPECIFIED), transfer(C2Color::TRANSFER_UNSPECIFIED), coeffs(C2Color::MATRIX_UNSPECIFIED), fullRange(C2Color::RANGE_UNSPECIFIED) { } bool operator==(const VuiColorAspects &o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } } mBitstreamColorAspects; oapvd_t oapvdHandle; oapvm_t oapvmHandle; Loading @@ -126,6 +146,8 @@ struct C2SoftApvDec final : public SimpleC2Component { int outputCsp; void getVuiParams(VuiColorAspects* buffer); C2_DO_NOT_COPY(C2SoftApvDec); }; Loading
media/codec2/components/apv/C2SoftApvEnc.cpp +33 −78 Original line number Diff line number Diff line Loading @@ -226,6 +226,9 @@ class C2SoftApvEnc::IntfImpl : public SimpleInterface<void>::BaseParams { if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) { pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010); } if (isHalPixelFormatSupported((AHardwareBuffer_Format)AHARDWAREBUFFER_FORMAT_YCbCr_P210)) { pixelFormats.push_back(AHARDWAREBUFFER_FORMAT_YCbCr_P210); } addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT) .withDefault(new C2StreamPixelFormatInfo::input( 0u, HAL_PIXEL_FORMAT_YCBCR_P010)) Loading Loading @@ -623,12 +626,6 @@ c2_status_t C2SoftApvEnc::initEncoder() { return C2_NO_MEMORY; } /* Calculate SDR to HDR mapping values */ mSdrToHdrMapping.clear(); for (int32_t i = 0; i < 256; i++) { mSdrToHdrMapping.push_back((uint16_t)(i * 1023 / 255 + 0.5)); } mStarted = true; mInitEncoder = true; return C2_OK; Loading Loading @@ -692,26 +689,48 @@ c2_status_t C2SoftApvEnc::setEncodeArgs(oapv_frms_t* inputFrames, const C2Graphi switch (layout.type) { case C2PlanarLayout::TYPE_RGB: [[fallthrough]]; case C2PlanarLayout::TYPE_RGBA: { // TODO: Add RGBA1010102 support ALOGE("Not supported RGB color format"); return C2_BAD_VALUE; case C2PlanarLayout::TYPE_RGBA: { [[fallthrough]]; } case C2PlanarLayout::TYPE_YUVA: { ALOGV("Convert from ABGR2101010 to P210"); uint16_t *dstY, *dstU, *dstV; dstY = (uint16_t*)inputFrames->frm[0].imgb->a[0]; dstU = (uint16_t*)inputFrames->frm[0].imgb->a[1]; dstV = (uint16_t*)inputFrames->frm[0].imgb->a[2]; convertRGBA1010102ToYUV420Planar16(dstY, dstU, dstV, (uint32_t*)(input->data()[0]), layout.planes[layout.PLANE_Y].rowInc / 4, width, height, mColorAspects->matrix, mColorAspects->range); break; } case C2PlanarLayout::TYPE_YUV: { if (IsP010(*input)) { if (mColorFormat == OAPV_CF_YCBCR422) { ColorConvertP010ToYUV422P10le(input, inputFrames->frm[0].imgb); } else if (mColorFormat == OAPV_CF_PLANAR2) { ColorConvertP010ToP210(input, inputFrames->frm[0].imgb); uint16_t *srcY = (uint16_t*)(input->data()[0]); uint16_t *srcUV = (uint16_t*)(input->data()[1]); uint16_t *dstY = (uint16_t*)inputFrames->frm[0].imgb->a[0]; uint16_t *dstUV = (uint16_t*)inputFrames->frm[0].imgb->a[1]; convertP010ToP210(dstY, dstUV, srcY, srcUV, input->width(), input->width(), input->width(), input->height()); } else { ALOGE("Not supported color format. %d", mColorFormat); return C2_BAD_VALUE; } } else if (IsNV12(*input)) { ColorConvertNv12ToP210(input, inputFrames->frm[0].imgb); } else if (IsNV21(*input)) { ColorConvertNv12ToP210(input, inputFrames->frm[0].imgb); uint8_t *srcY = (uint8_t*)input->data()[0]; uint8_t *srcUV = (uint8_t*)input->data()[1]; uint16_t *dstY = (uint16_t*)inputFrames->frm[0].imgb->a[0]; uint16_t *dstUV = (uint16_t*)inputFrames->frm[0].imgb->a[1]; convertSemiPlanar8ToP210(dstY, dstUV, srcY, srcUV, input->width(), input->width(), input->width(), input->width(), input->width(), input->height(), CONV_FORMAT_I420); } else if (IsYUV420(*input)) { return C2_BAD_VALUE; } else if (IsI420(*input)) { Loading @@ -731,46 +750,6 @@ c2_status_t C2SoftApvEnc::setEncodeArgs(oapv_frms_t* inputFrames, const C2Graphi return C2_OK; } void C2SoftApvEnc::ColorConvertNv12ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb) { auto width = input->width(); auto height = input->height(); auto* yPlane = (uint8_t*)input->data()[0]; auto* uvPlane = (uint8_t*)input->data()[1]; auto* dst = (uint16_t*)imgb->a[0]; int32_t lumaOffset = 0; for (int32_t y = 0; y < height; ++y) { for (int32_t x = 0; x < width; ++x) { lumaOffset = y * width + x; dst[lumaOffset] = (mSdrToHdrMapping[yPlane[lumaOffset]] << 6) | ((mSdrToHdrMapping[yPlane[lumaOffset]] & 0x300) >> 3); } } auto* dst_uv = (uint16_t*)imgb->a[1]; uint32_t uvDstStride = width; int32_t srcOffset = 0; int32_t dstOffset1 = 0, dstOffset2 = 0; int32_t tmp1 = 0, tmp2 = 0; for (int32_t y = 0; y < height / 2; ++y) { for (int32_t x = 0; x < width; x += 2) { srcOffset = y * width + x; dstOffset1 = (y * 2) * width + x; dstOffset2 = ((y * 2) + 1) * width + x; tmp1 = (mSdrToHdrMapping[uvPlane[srcOffset]] << 6) | ((mSdrToHdrMapping[uvPlane[srcOffset]] & 0x300) >> 3); tmp2 = (mSdrToHdrMapping[uvPlane[srcOffset + 1]] << 6) | ((mSdrToHdrMapping[uvPlane[srcOffset + 1]] & 0x300) >> 3); dst_uv[dstOffset1] = (uint16_t)tmp1; dst_uv[dstOffset1 + 1] = (uint16_t)tmp2; dst_uv[dstOffset2] = (uint16_t)tmp1; dst_uv[dstOffset2 + 1] = (uint16_t)tmp2; } } } C2Config::level_t C2SoftApvEnc::decisionApvLevel(int32_t width, int32_t height, int32_t fps, int32_t bitrate, int32_t band) { C2Config::level_t level = C2Config::LEVEL_APV_1_BAND_0; Loading Loading @@ -885,30 +864,6 @@ C2Config::level_t C2SoftApvEnc::decisionApvLevel(int32_t width, int32_t height, return level; } void C2SoftApvEnc::ColorConvertP010ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb) { auto width = input->width(); auto height = input->height(); auto* yPlane = (uint8_t*)input->data()[0]; auto* uvPlane = (uint8_t*)input->data()[1]; uint32_t uvStride = width * 2; auto* src = yPlane; auto* dst = (uint8_t*)imgb->a[0]; std::memcpy(dst, src, width * height * 2); auto* dst_uv = (uint8_t*)imgb->a[1]; int32_t offset1 = 0, offset2 = 0; for (int32_t y = 0; y < height / 2; ++y) { offset1 = (y * 2) * uvStride; offset2 = (y * 2 + 1) * uvStride; src = uvPlane + (y * uvStride); std::memcpy(dst_uv + offset1, src, uvStride); std::memcpy(dst_uv + offset2, src, uvStride); } } void C2SoftApvEnc::ColorConvertP010ToYUV422P10le(const C2GraphicView* const input, oapv_imgb_t* imgb) { uint32_t width = input->width(); Loading
media/codec2/components/apv/C2SoftApvEnc.h +0 −3 Original line number Diff line number Diff line Loading @@ -65,9 +65,7 @@ struct C2SoftApvEnc final : public SimpleC2Component { void showEncoderParams(oapve_cdesc_t* cdsc); void ColorConvertNv12ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb); void ColorConvertP010ToYUV422P10le(const C2GraphicView* const input, oapv_imgb_t* imgb); void ColorConvertP010ToP210(const C2GraphicView* const input, oapv_imgb_t* imgb); void createCsdData(const std::unique_ptr<C2Work>& work, oapv_bitb_t* bitb, uint32_t encodedSize); Loading Loading @@ -106,7 +104,6 @@ struct C2SoftApvEnc final : public SimpleC2Component { oapve_t mEncoderId; oapvm_t mMetaId; uint8_t* mBitstreamBuf = nullptr; std::vector<uint16_t> mSdrToHdrMapping; bool mReceivedFirstFrame = false; C2_DO_NOT_COPY(C2SoftApvEnc); }; Loading
media/codec2/components/base/SimpleC2Component.cpp +82 −0 Original line number Diff line number Diff line Loading @@ -463,6 +463,19 @@ void convertP010ToYUV420Planar16(uint16_t *dstY, uint16_t *dstU, uint16_t *dstV, } } void convertP010ToP210(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY, const uint16_t *srcUV, size_t srcUVStride, size_t dstUVStride, size_t width, size_t height) { std::memcpy(dstY, srcY, width * height * sizeof(uint16_t)); int32_t offsetTop, offsetBot; for (size_t y = 0; y < (height + 1) / 2; ++y) { offsetTop = (y * 2) * dstUVStride; offsetBot = (y * 2 + 1) * dstUVStride; std::memcpy(dstUV + offsetTop, srcUV + (y * srcUVStride), srcUVStride * sizeof(uint16_t)); std::memcpy(dstUV + offsetBot, srcUV + (y * srcUVStride), srcUVStride * sizeof(uint16_t)); } } static const int16_t bt709Matrix_10bit[2][3][3] = { { { 218, 732, 74 }, { -117, -395, 512 }, { 512, -465, -47 } }, /* RANGE_FULL */ { { 186, 627, 63 }, { -103, -345, 448 }, { 448, -407, -41 } }, /* RANGE_LIMITED */ Loading Loading @@ -517,6 +530,45 @@ void convertRGBA1010102ToYUV420Planar16(uint16_t* dstY, uint16_t* dstU, uint16_t } } void convertRGBA1010102ToP210(uint16_t* dstY, uint16_t* dstUV, const uint32_t* srcRGBA, size_t srcRGBStride, size_t width, size_t height, C2Color::matrix_t colorMatrix, C2Color::range_t colorRange) { uint16_t r, g, b; int32_t i32Y, i32U, i32V; uint16_t zeroLvl = colorRange == C2Color::RANGE_FULL ? 0 : 64; uint16_t maxLvlLuma = colorRange == C2Color::RANGE_FULL ? 1023 : 940; uint16_t maxLvlChroma = colorRange == C2Color::RANGE_FULL ? 1023 : 960; // set default range as limited if (colorRange != C2Color::RANGE_FULL) { colorRange = C2Color::RANGE_LIMITED; } const int16_t(*weights)[3] = (colorMatrix == C2Color::MATRIX_BT709) ? bt709Matrix_10bit[colorRange - 1] : bt2020Matrix_10bit[colorRange - 1]; for (size_t y = 0; y < height; ++y) { for (size_t x = 0; x < width; ++x) { b = (srcRGBA[x] >> 20) & 0x3FF; g = (srcRGBA[x] >> 10) & 0x3FF; r = srcRGBA[x] & 0x3FF; i32Y = ((r * weights[0][0] + g * weights[0][1] + b * weights[0][2] + 512) >> 10) + zeroLvl; dstY[x] = (CLIP3(zeroLvl, i32Y, maxLvlLuma) << 6) & 0xFFC0; if (x % 2 == 0) { i32U = ((r * weights[1][0] + g * weights[1][1] + b * weights[1][2] + 512) >> 10) + 512; i32V = ((r * weights[2][0] + g * weights[2][1] + b * weights[2][2] + 512) >> 10) + 512; dstUV[x] = (CLIP3(zeroLvl, i32U, maxLvlChroma) << 6) & 0xFFC0; dstUV[x + 1] = (CLIP3(zeroLvl, i32V, maxLvlChroma) << 6) & 0xFFC0; } } srcRGBA += srcRGBStride; dstY += width; } } void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride, size_t srcUStride, size_t srcVStride, size_t dstStride, size_t width, Loading Loading @@ -631,6 +683,36 @@ void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uin isMonochrome); } } void convertSemiPlanar8ToP210(uint16_t *dstY, uint16_t *dstUV, const uint8_t *srcY, const uint8_t *srcUV, size_t srcYStride, size_t srcUVStride, size_t dstYStride, size_t dstUVStride, uint32_t width, uint32_t height, CONV_FORMAT_T format) { if (format != CONV_FORMAT_I420) { ALOGE("No support for semi-planar8 to P210. format is %d", format); return; } for (int32_t y = 0; y < height; ++y) { for (int32_t x = 0; x < width; ++x) { dstY[x] = ((uint16_t)((double)srcY[x] * 1023 / 255 + 0.5) << 6) & 0xFFC0; } dstY += dstYStride; srcY += srcYStride; } for (int32_t y = 0; y < height / 2; ++y) { for (int32_t x = 0; x < width; ++x) { dstUV[x] = dstUV[dstUVStride + x] = ((uint16_t)((double)srcUV[x] * 1023 / 255 + 0.5) << 6) & 0xFFC0; } srcUV += srcUVStride; dstUV += dstUVStride << 1; } } std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() { std::unique_ptr<C2Work> work = std::move(mQueue.front().work); mQueue.pop_front(); Loading