美文网首页
NuMediaExtractor 使用随笔

NuMediaExtractor 使用随笔

作者: Nothing_655f | 来源:发表于2022-03-25 17:20 被阅读0次

NuMediaExtractor 使用随笔

记录一个随笔改动,有个改法是想获取片源中某个特定的信息,然后根据其来判断选择player,在MediaPlayerFactory@scoreFactory 中就可以直接调用extractor中来获取extractor中一些mime信息

    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
                            int fd,
                            int64_t offset,
                            int64_t length,
                            float /*curScore*/) {
            // ...
            sp<NuMediaExtractor> extractor = new NuMediaExtractor;
            extractor->setDataSource(fd, 0, 0x7ffffffffffffffL);
            size_t nums = extractor->countTracks();
            sp<AMessage> format;
            AString mime;
            for (size_t i=0; i<nums; i++) {
                if (extractor->getTrackFormat(i, &format) == OK
                    && format->findString("mime", &mime)) {
                    if (!strncasecmp(mime.c_str(), "text/pgs", 8)) {
                        return 1.2;
                    }
                }
            }
            // ...
    }

然后看了下这个用法其实在NDK中就有了,具体看 frameworks/av/media/ndk/NdkMediaExtractor.cpp
在Android P中的frameworks/base/media/jni/soundpool/SoundPool.cpp代码也可以看到其用法

static status_t decode(int fd, int64_t offset, int64_t length,
        uint32_t *rate, int *numChannels, audio_format_t *audioFormat,
        sp<MemoryHeapBase> heap, size_t *memsize) {

    ALOGV("fd %d, offset %" PRId64 ", size %" PRId64, fd, offset, length);
    AMediaExtractor *ex = AMediaExtractor_new();
    status_t err = AMediaExtractor_setDataSourceFd(ex, fd, offset, length);

    if (err != AMEDIA_OK) {
        AMediaExtractor_delete(ex);
        return err;
    }

    *audioFormat = AUDIO_FORMAT_PCM_16_BIT;

    size_t numTracks = AMediaExtractor_getTrackCount(ex);
    for (size_t i = 0; i < numTracks; i++) {
        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
        const char *mime;
        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
            AMediaExtractor_delete(ex);
            AMediaFormat_delete(format);
            return UNKNOWN_ERROR;
        }
        if (strncmp(mime, "audio/", 6) == 0) {

            AMediaCodec *codec = AMediaCodec_createDecoderByType(mime);
            if (codec == NULL
                    || AMediaCodec_configure(codec, format,
                            NULL /* window */, NULL /* drm */, 0 /* flags */) != AMEDIA_OK
                    || AMediaCodec_start(codec) != AMEDIA_OK
                    || AMediaExtractor_selectTrack(ex, i) != AMEDIA_OK) {
                AMediaExtractor_delete(ex);
                AMediaCodec_delete(codec);
                AMediaFormat_delete(format);
                return UNKNOWN_ERROR;
            }

            bool sawInputEOS = false;
            bool sawOutputEOS = false;
            uint8_t* writePos = static_cast<uint8_t*>(heap->getBase());
            size_t available = heap->getSize();
            size_t written = 0;

            AMediaFormat_delete(format);
            format = AMediaCodec_getOutputFormat(codec);

            while (!sawOutputEOS) {
                if (!sawInputEOS) {
                    ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
                    ALOGV("input buffer %zd", bufidx);
                    if (bufidx >= 0) {
                        size_t bufsize;
                        uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
                        if (buf == nullptr) {
                            ALOGE("AMediaCodec_getInputBuffer returned nullptr, short decode");
                            break;
                        }
                        int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
                        ALOGV("read %d", sampleSize);
                        if (sampleSize < 0) {
                            sampleSize = 0;
                            sawInputEOS = true;
                            ALOGV("EOS");
                        }
                        int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);

                        media_status_t mstatus = AMediaCodec_queueInputBuffer(codec, bufidx,
                                0 /* offset */, sampleSize, presentationTimeUs,
                                sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
                        if (mstatus != AMEDIA_OK) {
                            // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES }
                            ALOGE("AMediaCodec_queueInputBuffer returned status %d, short decode",
                                    (int)mstatus);
                            break;
                        }
                        (void)AMediaExtractor_advance(ex);
                    }
                }

                AMediaCodecBufferInfo info;
                int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1);
                ALOGV("dequeueoutput returned: %d", status);
                if (status >= 0) {
                    if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
                        ALOGV("output EOS");
                        sawOutputEOS = true;
                    }
                    ALOGV("got decoded buffer size %d", info.size);

                    uint8_t *buf = AMediaCodec_getOutputBuffer(codec, status, NULL /* out_size */);
                    if (buf == nullptr) {
                        ALOGE("AMediaCodec_getOutputBuffer returned nullptr, short decode");
                        break;
                    }
                    size_t dataSize = info.size;
                    if (dataSize > available) {
                        dataSize = available;
                    }
                    memcpy(writePos, buf + info.offset, dataSize);
                    writePos += dataSize;
                    written += dataSize;
                    available -= dataSize;
                    media_status_t mstatus = AMediaCodec_releaseOutputBuffer(
                            codec, status, false /* render */);
                    if (mstatus != AMEDIA_OK) {
                        // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES }
                        ALOGE("AMediaCodec_releaseOutputBuffer returned status %d, short decode",
                                (int)mstatus);
                        break;
                    }
                    if (available == 0) {
                        // there might be more data, but there's no space for it
                        sawOutputEOS = true;
                    }
                } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
                    ALOGV("output buffers changed");
                } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
                    AMediaFormat_delete(format);
                    format = AMediaCodec_getOutputFormat(codec);
                    ALOGV("format changed to: %s", AMediaFormat_toString(format));
                } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
                    ALOGV("no output buffer right now");
                } else if (status <= AMEDIA_ERROR_BASE) {
                    ALOGE("decode error: %d", status);
                    break;
                } else {
                    ALOGV("unexpected info code: %d", status);
                }
            }

            (void)AMediaCodec_stop(codec);
            (void)AMediaCodec_delete(codec);
            (void)AMediaExtractor_delete(ex);
            if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) ||
                    !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels)) {
                (void)AMediaFormat_delete(format);
                return UNKNOWN_ERROR;
            }
            (void)AMediaFormat_delete(format);
            *memsize = written;
            return OK;
        }
        (void)AMediaFormat_delete(format);
    }
    (void)AMediaExtractor_delete(ex);
    return UNKNOWN_ERROR;
}

还有一个是往上对接framework MediaExtractor 接口的使用,具体可以看这篇文章分析

MediaExtractor源码分析 - 简书

相关文章

网友评论

      本文标题:NuMediaExtractor 使用随笔

      本文链接:https://www.haomeiwen.com/subject/xfsdjrtx.html