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

Commit 5e65a6ad authored by jiabin's avatar jiabin
Browse files

Add haptic metadata for Ogg file.

Add a key "haptic" in Ogg file metadata, which indicating the haptic
channel count of the Ogg file. When it is present as a valid number,
OggExtractor will set haptic channel mask accordingly to support haptic
playback via audio. This is part of haptic playback support.

Bug: 111454766
Test: Manually test
Change-Id: I9f9ba22358b7c538382f23f24143057970f6d7ad
parent 6b6a0f05
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -7,6 +7,10 @@ cc_library_shared {
        "external/tremolo",
    ],

    header_libs: [
        "libaudio_system_headers",
    ],

    shared_libs: [
        "liblog",
        "libmediaextractor",
+32 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaDataBase.h>
#include <media/stagefright/MetaDataUtils.h>
#include <system/audio.h>
#include <utils/String8.h>

extern "C" {
@@ -133,6 +134,8 @@ protected:

    Vector<TOCEntry> mTableOfContents;

    int32_t mHapticChannelCount;

    ssize_t readPage(off64_t offset, Page *page);
    status_t findNextPage(off64_t startOffset, off64_t *pageOffset);

@@ -163,6 +166,8 @@ protected:

    void buildTableOfContents();

    void setChannelMask(int channelCount);

    MyOggExtractor(const MyOggExtractor &);
    MyOggExtractor &operator=(const MyOggExtractor &);
};
@@ -310,7 +315,8 @@ MyOggExtractor::MyOggExtractor(
      mMimeType(mimeType),
      mNumHeaders(numHeaders),
      mSeekPreRollUs(seekPreRollUs),
      mFirstDataOffset(-1) {
      mFirstDataOffset(-1),
      mHapticChannelCount(0) {
    mCurrentPage.mNumSegments = 0;

    vorbis_info_init(&mVi);
@@ -1083,6 +1089,7 @@ media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) {
    }

    parseFileMetaData();
    setChannelMask(mChannelCount);
    return AMEDIA_OK;
}

@@ -1157,6 +1164,7 @@ media_status_t MyVorbisExtractor::verifyHeader(
            }

            parseFileMetaData();
            setChannelMask(mVi.channels);
            break;
        }

@@ -1192,6 +1200,29 @@ void MyOggExtractor::parseFileMetaData() {
        parseVorbisComment(mFileMeta, comment, commentLength);
        //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
    }

    AMediaFormat_getInt32(mFileMeta, "haptic", &mHapticChannelCount);
}

void MyOggExtractor::setChannelMask(int channelCount) {
    // Set channel mask according to channel count. When haptic channel count is found in
    // file meta, set haptic channel mask to try haptic playback.
    if (mHapticChannelCount > 0) {
        const audio_channel_mask_t hapticChannelMask =
                haptic_channel_mask_from_count(mHapticChannelCount);
        const int32_t audioChannelCount = channelCount - mHapticChannelCount;
        if (hapticChannelMask == AUDIO_CHANNEL_INVALID
                || audioChannelCount <= 0 || audioChannelCount > FCC_8) {
            ALOGE("Invalid haptic channel count found in metadata: %d", mHapticChannelCount);
        } else {
            const audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(
                    audioChannelCount) | hapticChannelMask;
            AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK, channelMask);
        }
    } else {
        AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK,
                audio_channel_out_mask_from_count(channelCount));
    }
}


+12 −0
Original line number Diff line number Diff line
@@ -308,6 +308,8 @@ static void extractAlbumArt(

void parseVorbisComment(
        AMediaFormat *fileMeta, const char *comment, size_t commentLength) {
    // Haptic tag is only kept here as it will only be used in extractor to generate channel mask.
    const char* const haptic = "haptic";
    struct {
        const char *const mTag;
        const char *mKey;
@@ -328,6 +330,7 @@ void parseVorbisComment(
        { "LYRICIST", AMEDIAFORMAT_KEY_LYRICIST },
        { "METADATA_BLOCK_PICTURE", AMEDIAFORMAT_KEY_ALBUMART },
        { "ANDROID_LOOP", AMEDIAFORMAT_KEY_LOOP },
        { "ANDROID_HAPTIC", haptic },
    };

        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
@@ -343,6 +346,15 @@ void parseVorbisComment(
                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
                        AMediaFormat_setInt32(fileMeta, AMEDIAFORMAT_KEY_LOOP, 1);
                    }
                } else if (kMap[j].mKey == haptic) {
                    char *end;
                    errno = 0;
                    const int hapticChannelCount = strtol(&comment[tagLen + 1], &end, 10);
                    if (errno == 0) {
                        AMediaFormat_setInt32(fileMeta, haptic, hapticChannelCount);
                    } else {
                        ALOGE("Error(%d) when parsing haptic channel count", errno);
                    }
                } else {
                    AMediaFormat_setString(fileMeta, kMap[j].mKey, &comment[tagLen + 1]);
                }