Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cc7fcad authored by Linus Nilsson's avatar Linus Nilsson Committed by Android (Google) Code Review
Browse files

Merge "Transcoder: Adopt MediaCodec HDR->SDR conversion" into sc-dev

parents 26e1639d f4641545
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -234,7 +234,6 @@ media_status_t MediaTranscoder::configureSource(int fd) {
    lseek(fd, 0, SEEK_SET);

    mSampleReader = MediaSampleReaderNDK::createFromFd(fd, 0 /* offset */, fileSize);

    if (mSampleReader == nullptr) {
        LOG(ERROR) << "Unable to parse source fd: " << fd;
        return AMEDIA_ERROR_UNSUPPORTED;
+3 −0
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ const char* TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
const char* TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate";
const char* TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES = "max-bframes";

/* TODO(lnilsson): Finalize value or adopt AMediaFormat key once available. */
const char* TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST = "color-transfer-request";

namespace AMediaFormatUtils {

#define DEFINE_FORMAT_VALUE_COPY_FUNC(_type, _typeName)                                      \
+53 −0
Original line number Diff line number Diff line
@@ -51,6 +51,32 @@ static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
// Default frame rate.
static constexpr int32_t kDefaultFrameRate = 30;

// Determines whether a track format describes HDR video content or not. The
// logic is based on isHdr() in libstagefright/Utils.cpp.
static bool isHdr(AMediaFormat* format) {
    // If VUI signals HDR content, this internal flag is set by the extractor.
    int32_t isHdr;
    if (AMediaFormat_getInt32(format, "android._is-hdr", &isHdr)) {
        return isHdr;
    }

    // If container supplied HDR static info without transfer set, assume HDR.
    const char* hdrInfo;
    int32_t transfer;
    if ((AMediaFormat_getString(format, AMEDIAFORMAT_KEY_HDR_STATIC_INFO, &hdrInfo) ||
         AMediaFormat_getString(format, "hdr10-plus-info", &hdrInfo)) &&
        !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_TRANSFER, &transfer)) {
        return true;
    }

    // Otherwise, check if an HDR transfer function is set.
    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_TRANSFER, &transfer)) {
        return transfer == COLOR_TRANSFER_ST2084 || transfer == COLOR_TRANSFER_HLG;
    }

    return false;
}

template <typename T>
void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
    {
@@ -320,6 +346,14 @@ media_status_t VideoTrackTranscoder::configureDestinationFormat(
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    // Request decoder to convert HDR content to SDR.
    const bool sourceIsHdr = isHdr(mSourceFormat.get());
    if (sourceIsHdr) {
        AMediaFormat_setInt32(decoderFormat.get(),
                              TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST,
                              COLOR_TRANSFER_SDR_VIDEO);
    }

    // Prevent decoder from overwriting frames that the encoder has not yet consumed.
    AMediaFormat_setInt32(decoderFormat.get(), TBD_AMEDIACODEC_PARAMETER_KEY_ALLOW_FRAME_DROP, 0);

@@ -340,6 +374,25 @@ media_status_t VideoTrackTranscoder::configureDestinationFormat(
        return status;
    }

    if (sourceIsHdr) {
        bool supported = false;
        AMediaFormat* inputFormat = AMediaCodec_getInputFormat(mDecoder);

        if (inputFormat != nullptr) {
            int32_t transferFunc;
            supported = AMediaFormat_getInt32(inputFormat,
                                              TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST,
                                              &transferFunc) &&
                        transferFunc == COLOR_TRANSFER_SDR_VIDEO;
            AMediaFormat_delete(inputFormat);
        }

        if (!supported) {
            LOG(ERROR) << "HDR to SDR conversion unsupported by the codec";
            return AMEDIA_ERROR_UNSUPPORTED;
        }
    }

    // Configure codecs to run in async mode.
    AMediaCodecOnAsyncNotifyCallback asyncCodecCallbacks = {
            .onAsyncInputAvailable = AsyncCodecCallbackDispatch::onAsyncInputAvailable,
+7 −0
Original line number Diff line number Diff line
@@ -45,11 +45,18 @@ static constexpr int COLOR_FormatYUV420SemiPlanar = 21;
static constexpr int COLOR_FormatYUV420Flexible = 0x7F420888;
static constexpr int COLOR_FormatSurface = 0x7f000789;

// Color transfer functions defined by MediaCodecConstants.h but not in NDK
static constexpr int32_t COLOR_TRANSFER_HLG = 7;
static constexpr int32_t COLOR_TRANSFER_LINEAR = 1;
static constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
static constexpr int32_t COLOR_TRANSFER_ST2084 = 6;

// constants not defined in NDK
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_ALLOW_FRAME_DROP;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES;
extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_COLOR_TRANSFER_REQUEST;
static constexpr int TBD_AMEDIACODEC_BUFFER_FLAG_KEY_FRAME = 0x1;

static constexpr int kBitrateModeConstant = 2;
+7 −1
Original line number Diff line number Diff line
#!/bin/bash

# Exit on compilation error.
set -e

#
# Run tests in this directory.
#

if [ "$SYNC_FINISHED" != true ]; then
  if [ -z "$ANDROID_BUILD_TOP" ]; then
      echo "Android build environment not set"
@@ -24,6 +27,9 @@ fi

echo "========================================"

# Don't exit if a test fails.
set +e

echo "testing MediaSampleReaderNDK"
adb shell ASAN_OPTIONS=detect_container_overflow=0 /data/nativetest64/MediaSampleReaderNDKTests/MediaSampleReaderNDKTests