Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
241 changes: 223 additions & 18 deletions codec2/C2FFMPEGVideoDecodeComponent.cpp

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions codec2/C2FFMPEGVideoDecodeComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,16 @@ class C2FFMPEGVideoDecodeComponent : public SimpleC2Component {
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool);
c2_status_t downloadFrame(bool forceSw);
bool updateColorAspects(std::vector<std::unique_ptr<C2Param>>& configUpdate);
c2_status_t reconfigureOutputDelay(std::vector<std::unique_ptr<C2Param>>& configUpdate);
bool shouldUseP010Output(const AVHWFramesContext* hwfc = nullptr) const;
uint32_t getActivePixelFormat(bool flexible, const AVHWFramesContext* hwfc = nullptr) const;
#if CONFIG_VAAPI
uint32_t getActiveVAFormat(const AVHWFramesContext* hwfc = nullptr) const;
uint32_t getActiveVAFOURCCFormat(const AVHWFramesContext* hwfc = nullptr) const;
#endif
uint32_t getActiveDRMFOURCCFormat(const AVHWFramesContext* hwfc = nullptr) const;
enum AVPixelFormat getActiveAVFormat(const AVHWFramesContext* hwfc = nullptr) const;

void pushPendingWork(const std::unique_ptr<C2Work>& work);
void popPendingWork(const std::unique_ptr<C2Work>& work);
Expand Down Expand Up @@ -114,6 +123,7 @@ class C2FFMPEGVideoDecodeComponent : public SimpleC2Component {
bool mExtradataReady;
bool mEOSSignalled;
bool mFilterInitialized;
C2ColorAspectsStruct mFrameColorAspects;
int mDeinterlaceMode;
int mDeinterlaceIndicator;
std::deque<PendingWork> mPendingWorkQueue;
Expand Down
115 changes: 111 additions & 4 deletions codec2/C2FFMPEGVideoDecodeInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ C2FFMPEGVideoDecodeInterface::C2FFMPEGVideoDecodeInterface(
addParameter(
DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
.withDefault(new C2StreamProfileLevelInfo::input(0u,
C2Config::PROFILE_HEVC_MAIN, C2Config::LEVEL_HEVC_MAIN_5_1))
C2Config::PROFILE_HEVC_MAIN_10, C2Config::LEVEL_HEVC_MAIN_5_1))
.withFields({
C2F(mProfileLevel, profile).oneOf({
C2Config::PROFILE_HEVC_MAIN,
C2Config::PROFILE_HEVC_MAIN_10,
C2Config::PROFILE_HEVC_MAIN_STILL}),
C2F(mProfileLevel, level).oneOf({
C2Config::LEVEL_HEVC_MAIN_1,
Expand Down Expand Up @@ -218,21 +219,23 @@ C2FFMPEGVideoDecodeInterface::C2FFMPEGVideoDecodeInterface(

std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo = nullptr;

const uint32_t defaultBitDepth = mUtils->getBitDepth();

if (mUtils->isPixelFormatYUV420()) {
C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() };
defaultColorInfo =
C2StreamColorInfo::output::AllocShared(
1u, 0u, 8u /* bitDepth */, C2Color::YUV_420);
1u, 0u, defaultBitDepth, C2Color::YUV_420);
memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));

defaultColorInfo =
C2StreamColorInfo::output::AllocShared(
{ C2ChromaOffsetStruct::ITU_YUV_420_0() },
0u, 8u /* bitDepth */, C2Color::YUV_420);
0u, defaultBitDepth, C2Color::YUV_420);
} else {
defaultColorInfo =
C2StreamColorInfo::output::AllocShared(
0u, 0u, 8u /* bitDepth */, C2Color::RGB);
0u, 0u, defaultBitDepth, C2Color::RGB);
helper->addStructDescriptors<C2ChromaOffsetStruct>();
}

Expand All @@ -241,6 +244,60 @@ C2FFMPEGVideoDecodeInterface::C2FFMPEGVideoDecodeInterface(
.withConstValue(defaultColorInfo)
.build());

addParameter(
DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
.withDefault(new C2StreamColorAspectsTuning::output(
0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
.withFields({
C2F(mDefaultColorAspects, range).inRange(
C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
C2F(mDefaultColorAspects, primaries).inRange(
C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
C2F(mDefaultColorAspects, transfer).inRange(
C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
C2F(mDefaultColorAspects, matrix).inRange(
C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER),
})
.withSetter(DefaultColorAspectsSetter)
.build());

addParameter(
DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
.withDefault(new C2StreamColorAspectsInfo::input(
0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
.withFields({
C2F(mCodedColorAspects, range).inRange(
C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
C2F(mCodedColorAspects, primaries).inRange(
C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
C2F(mCodedColorAspects, transfer).inRange(
C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
C2F(mCodedColorAspects, matrix).inRange(
C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER),
})
.withSetter(CodedColorAspectsSetter)
.build());

addParameter(
DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
.withDefault(new C2StreamColorAspectsInfo::output(
0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
.withFields({
C2F(mColorAspects, range).inRange(
C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
C2F(mColorAspects, primaries).inRange(
C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
C2F(mColorAspects, transfer).inRange(
C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
C2F(mColorAspects, matrix).inRange(
C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER),
})
.withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
.build());

addParameter(
DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
.withDefault(new C2StreamPixelFormatInfo::output(
Expand Down Expand Up @@ -290,6 +347,56 @@ C2R C2FFMPEGVideoDecodeInterface::ProfileLevelSetter(
return C2R::Ok();
}

C2R C2FFMPEGVideoDecodeInterface::DefaultColorAspectsSetter(
bool mayBlock __unused, C2P<C2StreamColorAspectsTuning::output>& me) {
if (me.v.range > C2Color::RANGE_OTHER) {
me.set().range = C2Color::RANGE_OTHER;
}
if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
me.set().primaries = C2Color::PRIMARIES_OTHER;
}
if (me.v.transfer > C2Color::TRANSFER_OTHER) {
me.set().transfer = C2Color::TRANSFER_OTHER;
}
if (me.v.matrix > C2Color::MATRIX_OTHER) {
me.set().matrix = C2Color::MATRIX_OTHER;
}
return C2R::Ok();
}

C2R C2FFMPEGVideoDecodeInterface::CodedColorAspectsSetter(
bool mayBlock __unused, C2P<C2StreamColorAspectsInfo::input>& me) {
if (me.v.range > C2Color::RANGE_OTHER) {
me.set().range = C2Color::RANGE_OTHER;
}
if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
me.set().primaries = C2Color::PRIMARIES_OTHER;
}
if (me.v.transfer > C2Color::TRANSFER_OTHER) {
me.set().transfer = C2Color::TRANSFER_OTHER;
}
if (me.v.matrix > C2Color::MATRIX_OTHER) {
me.set().matrix = C2Color::MATRIX_OTHER;
}
return C2R::Ok();
}

C2R C2FFMPEGVideoDecodeInterface::ColorAspectsSetter(
bool mayBlock __unused,
C2P<C2StreamColorAspectsInfo::output>& me,
const C2P<C2StreamColorAspectsTuning::output>& def,
const C2P<C2StreamColorAspectsInfo::input>& coded) {
me.set().range = coded.v.range == C2Color::RANGE_UNSPECIFIED
? def.v.range : coded.v.range;
me.set().primaries = coded.v.primaries == C2Color::PRIMARIES_UNSPECIFIED
? def.v.primaries : coded.v.primaries;
me.set().transfer = coded.v.transfer == C2Color::TRANSFER_UNSPECIFIED
? def.v.transfer : coded.v.transfer;
me.set().matrix = coded.v.matrix == C2Color::MATRIX_UNSPECIFIED
? def.v.matrix : coded.v.matrix;
return C2R::Ok();
}

C2R C2FFMPEGVideoDecodeInterface::CodecSetter(
bool mayBlock __unused, C2P<C2StreamRawCodecDataInfo::input>& me __unused) {
return C2R::Ok();
Expand Down
15 changes: 15 additions & 0 deletions codec2/C2FFMPEGVideoDecodeInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ class C2FFMPEGVideoDecodeInterface : public SimpleInterface<void>::BaseParams {
uint64_t getConsumerUsage() const { return mConsumerUsage->value; }
const std::shared_ptr<C2StreamPixelFormatInfo::output>&
getPixelFormatInfo() const { return mPixelFormat; }
const std::shared_ptr<C2StreamColorAspectsInfo::output>&
getColorAspectsInfo() const { return mColorAspects; }
uint32_t getPixelFormat() const { return mPixelFormat->value; }
uint32_t getOutputDelay() const { return mActualOutputDelay->value; }
uint32_t getBitDepth() const { return mUtils->getBitDepth(); }

private:
static C2R SizeSetter(
Expand All @@ -48,13 +51,25 @@ class C2FFMPEGVideoDecodeInterface : public SimpleInterface<void>::BaseParams {
bool mayBlock,
C2P<C2StreamProfileLevelInfo::input> &me,
const C2P<C2StreamPictureSizeInfo::output> &size);
static C2R DefaultColorAspectsSetter(
bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me);
static C2R CodedColorAspectsSetter(
bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me);
static C2R ColorAspectsSetter(
bool mayBlock,
C2P<C2StreamColorAspectsInfo::output> &me,
const C2P<C2StreamColorAspectsTuning::output> &def,
const C2P<C2StreamColorAspectsInfo::input> &coded);
static C2R CodecSetter(
bool mayBlock, C2P<C2StreamRawCodecDataInfo::input>& me);

private:
std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
std::shared_ptr<C2StreamRawCodecDataInfo::input> mRawCodecData;
std::shared_ptr<C2StreamUsageTuning::output> mConsumerUsage;
Expand Down
29 changes: 28 additions & 1 deletion codec2/C2FFMPEGVideoUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ bool C2FFMPEGVideoUtils::shouldEnableCodec(const std::string codec, bool hwonly)
bool C2FFMPEGVideoUtils::isPixelFormatYUV420() const {
switch (getPixelFormatType()) {
case PixelFormatType::YUV_420:
case PixelFormatType::YUV_420_P010:
case PixelFormatType::YUV_420_PLANER:
return true;
default:
Expand All @@ -72,7 +73,23 @@ bool C2FFMPEGVideoUtils::isPixelFormatYUV420() const {
}

bool C2FFMPEGVideoUtils::isVPPMode() const {
return (mUseDrmPrime && getPixelFormatType() != PixelFormatType::YUV_420);
return (mUseDrmPrime && getPixelFormatType() != PixelFormatType::YUV_420
&& getPixelFormatType() != PixelFormatType::YUV_420_P010);
}

uint32_t C2FFMPEGVideoUtils::getBitDepth() const {
switch (getPixelFormatType()) {
case PixelFormatType::YUV_420_P010:
return 10;
case PixelFormatType::YUV_420:
case PixelFormatType::YUV_420_PLANER:
case PixelFormatType::RGB_565:
case PixelFormatType::RGBX_8888:
case PixelFormatType::BGRA_8888:
case PixelFormatType::UNKNOWN:
default:
return 8;
}
}

PixelFormatType C2FFMPEGVideoUtils::getPixelFormatType() const {
Expand All @@ -88,6 +105,8 @@ uint32_t C2FFMPEGVideoUtils::getPixelFormat(bool flexible) const {
} else {
return HAL_PIXEL_FORMAT_YV12;
}
case PixelFormatType::YUV_420_P010:
return HAL_PIXEL_FORMAT_YCBCR_P010;
case PixelFormatType::YUV_420_PLANER:
return HAL_PIXEL_FORMAT_YV12;
case PixelFormatType::RGB_565:
Expand All @@ -109,6 +128,8 @@ uint32_t C2FFMPEGVideoUtils::getVAFormat() const {
case PixelFormatType::YUV_420:
case PixelFormatType::YUV_420_PLANER:
return VA_RT_FORMAT_YUV420;
case PixelFormatType::YUV_420_P010:
return VA_RT_FORMAT_YUV420_10BPP;
case PixelFormatType::RGB_565:
return VA_RT_FORMAT_RGB16;
case PixelFormatType::BGRA_8888:
Expand All @@ -125,6 +146,8 @@ uint32_t C2FFMPEGVideoUtils::getVAFOURCCFormat() const {
switch (getPixelFormatType()) {
case PixelFormatType::YUV_420:
return VA_FOURCC_NV12;
case PixelFormatType::YUV_420_P010:
return VA_FOURCC_P010;
case PixelFormatType::YUV_420_PLANER:
return VA_FOURCC_YV12;
case PixelFormatType::RGB_565:
Expand All @@ -145,6 +168,8 @@ uint32_t C2FFMPEGVideoUtils::getDRMFOURCCFormat() const {
switch (getPixelFormatType()) {
case PixelFormatType::YUV_420:
return mUseDrmPrime ? DRM_FORMAT_NV12 : DRM_FORMAT_YVU420;
case PixelFormatType::YUV_420_P010:
return DRM_FORMAT_P010;
case PixelFormatType::YUV_420_PLANER:
return DRM_FORMAT_YVU420;
case PixelFormatType::RGB_565:
Expand All @@ -164,6 +189,8 @@ enum AVPixelFormat C2FFMPEGVideoUtils::getAVFormat() const {
switch (getPixelFormatType()) {
case PixelFormatType::YUV_420:
return mUseDrmPrime ? AV_PIX_FMT_NV12 : AV_PIX_FMT_YUV420P;
case PixelFormatType::YUV_420_P010:
return AV_PIX_FMT_P010;
case PixelFormatType::YUV_420_PLANER:
return AV_PIX_FMT_YUV420P;
case PixelFormatType::RGB_565:
Expand Down
3 changes: 3 additions & 0 deletions codec2/C2FFMPEGVideoUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace android {

enum class PixelFormatType {
YUV_420,
YUV_420_P010,
YUV_420_PLANER,
RGB_565,
RGBX_8888,
Expand All @@ -48,6 +49,7 @@ class C2FFMPEGVideoUtils {
bool shouldEnableCodec(const std::string codec, bool hwonly) const;
bool isPixelFormatYUV420() const;
bool isVPPMode() const;
uint32_t getBitDepth() const;
uint32_t getPixelFormat(bool flexible) const;
#if CONFIG_VAAPI
uint32_t getVAFormat() const;
Expand All @@ -62,6 +64,7 @@ class C2FFMPEGVideoUtils {
private:
const std::map<std::string, PixelFormatType> mPixelFormatMap = {
{ "YUV_420", PixelFormatType::YUV_420 },
{ "YUV_420_P010", PixelFormatType::YUV_420_P010 },
{ "YUV_420_PLANER", PixelFormatType::YUV_420_PLANER },
{ "RGB_565", PixelFormatType::RGB_565 },
{ "RGBX_8888", PixelFormatType::RGBX_8888 },
Expand Down
7 changes: 6 additions & 1 deletion codec2/media_codecs_ffmpeg_c2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,13 @@
</MediaCodec>
<MediaCodec name="c2.ffmpeg.av1.decoder" type="video/av01">
<Alias name="OMX.ffmpeg.av1.decoder" />
<Limit name="size" min="2x2" max="2048x2048" />
<Limit name="size" min="2x2" max="4096x4096" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="24-2073600" />
<Limit name="bitrate" range="1-120000000" />
<Limit name="frame-rate" range="1-480" />
<Limit name="performance-point-3840x2160" value="30" />
<Feature name="adaptive-playback" />
<Feature name="low-latency" />
</MediaCodec>
Expand Down
13 changes: 10 additions & 3 deletions utils/ffmpeg_hwaccel.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "config.h"
#include "ffmpeg_hwaccel.h"
#include "libavutil/opt.h"
#include "libavutil/hwcontext.h"

int ffmpeg_hwaccel_init(AVCodecContext *avctx) {
if (!property_get_bool("media.sf.hwaccel", 0))
Expand Down Expand Up @@ -75,6 +76,12 @@ int ffmpeg_hwaccel_get_frame(AVCodecContext *avctx __unused, AVFrame *frame) {
return 0;
}

enum AVPixelFormat sw_format = AV_PIX_FMT_YUV420P;
AVHWFramesContext *hwfc = (AVHWFramesContext *)frame->hw_frames_ctx->data;
if (hwfc && hwfc->sw_format == AV_PIX_FMT_P010) {
sw_format = AV_PIX_FMT_P010;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write to output->format directly?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have output->format = sw_format; later and we may need to use this variable again in the future, for specific cases / hardware support , etc. but if you prefer, it's totally fine to just change that! It's just a future proof.


AVFrame* output;
int err;

Expand All @@ -97,9 +104,9 @@ int ffmpeg_hwaccel_get_frame(AVCodecContext *avctx __unused, AVFrame *frame) {
// would be successful (and if it fails, then method 3 will also
// likely fail).

// YUV420P mapping (slower)
// Software frame mapping (slower)

output->format = AV_PIX_FMT_YUV420P;
output->format = sw_format;

err = av_hwframe_map(output, frame, AV_HWFRAME_MAP_READ);
if (err == 0) {
Expand All @@ -109,7 +116,7 @@ int ffmpeg_hwaccel_get_frame(AVCodecContext *avctx __unused, AVFrame *frame) {

// HW frame download (slowest)

output->format = AV_PIX_FMT_YUV420P;
output->format = sw_format;

err = av_hwframe_transfer_data(output, frame, 0);
if (err < 0) {
Expand Down