Android 13 - Media框架(25)- MPEG2TSExtractor

cpp 复制代码
media_status_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) {
    HalToken halToken;
    halToken.setToExternal((uint8_t*)casToken, size);
    sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
    ALOGD("setMediaCas: %p", cas.get());

    status_t err = mParser->setMediaCas(cas);
    if (err == OK) {
        ALOGI("All tracks now have descramblers");
        init();
        return AMEDIA_OK;
    }
    return AMEDIA_ERROR_UNKNOWN;
}

status_t MPEG2TSExtractor::findIndexOfSource(const sp<AnotherPacketSource> &impl, size_t *index) {
    for (size_t i = 0; i < mSourceImpls.size(); i++) {
        if (mSourceImpls[i] == impl) {
            *index = i;
            return OK;
        }
    }
    return NAME_NOT_FOUND;
}

void MPEG2TSExtractor::addSource(const sp<AnotherPacketSource> &impl) {
    size_t index;
    if (findIndexOfSource(impl, &index) != OK) {
        mSourceImpls.push(impl);
        mSyncPoints.push();
    }
}

void MPEG2TSExtractor::init() {
    bool haveAudio = false;
    bool haveVideo = false;
    int64_t startTime = ALooper::GetNowUs();
    size_t index;

    status_t err;
    while ((err = feedMore(true /* isInit */)) == OK
            || err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
        if (haveAudio && haveVideo) {
            addSyncPoint_l(mLastSyncEvent);
            mLastSyncEvent.reset();
            break;
        }
        if (!haveVideo) {
            sp<AnotherPacketSource> impl = mParser->getSource(ATSParser::VIDEO);

            if (impl != NULL) {
                sp<MetaData> format = impl->getFormat();
                if (format != NULL) {
                    haveVideo = true;
                    addSource(impl);
                    if (!isScrambledFormat(*(format.get()))) {
                        if (findIndexOfSource(impl, &index) == OK) {
                            mSeekSyncPoints = &mSyncPoints.editItemAt(index);
                        }
                    }
                }
            }
        }

        if (!haveAudio) {
            sp<AnotherPacketSource> impl = mParser->getSource(ATSParser::AUDIO);

            if (impl != NULL) {
                sp<MetaData> format = impl->getFormat();
                if (format != NULL) {
                    haveAudio = true;
                    addSource(impl);
                    if (!isScrambledFormat(*(format.get())) && !haveVideo) {
                        if (findIndexOfSource(impl, &index) == OK) {
                            mSeekSyncPoints = &mSyncPoints.editItemAt(index);
                        }
                    }
                }
            }
        }

        addSyncPoint_l(mLastSyncEvent);
        mLastSyncEvent.reset();

        // ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED is returned when the mpeg2ts
        // is scrambled but we don't have a MediaCas object set. The extraction
        // will only continue when setMediaCas() is called successfully.
        if (err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
            ALOGI("stopped parsing scrambled content, "
                  "haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
                    haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
            return;
        }

        // Wait only for 2 seconds to detect audio/video streams.
        if (ALooper::GetNowUs() - startTime > 2000000LL) {
            break;
        }
    }

    off64_t size;
    if (mDataSource->getSize(&size) == OK && (haveAudio || haveVideo)) {
        size_t prevSyncSize = 1;
        int64_t durationUs = -1;
        List<int64_t> durations;
        // Estimate duration --- stabilize until you get <500ms deviation.
        while (feedMore() == OK
                && ALooper::GetNowUs() - startTime <= 2000000LL) {
            if (mSeekSyncPoints->size() > prevSyncSize) {
                prevSyncSize = mSeekSyncPoints->size();
                int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
                        - mSeekSyncPoints->keyAt(0);
                off64_t diffOffset = mSeekSyncPoints->valueAt(prevSyncSize - 1)
                        - mSeekSyncPoints->valueAt(0);
                int64_t currentDurationUs = size * diffUs / diffOffset;
                durations.push_back(currentDurationUs);
                if (durations.size() > 5) {
                    durations.erase(durations.begin());
                    int64_t min = *durations.begin();
                    int64_t max = *durations.begin();
                    for (auto duration : durations) {
                        if (min > duration) {
                            min = duration;
                        }
                        if (max < duration) {
                            max = duration;
                        }
                    }
                    if (max - min < 500 * 1000) {
                        durationUs = currentDurationUs;
                        break;
                    }
                }
            }
        }

        bool found = false;
        for (int i = 0; i < ATSParser::NUM_SOURCE_TYPES; ++i) {
            ATSParser::SourceType type = static_cast<ATSParser::SourceType>(i);
            sp<AnotherPacketSource> impl = mParser->getSource(type);
            if (impl == NULL) {
                continue;
            }

            int64_t trackDurationUs = durationUs;

            status_t err;
            int64_t bufferedDurationUs = impl->getBufferedDurationUs(&err);
            if (err == ERROR_END_OF_STREAM) {
                trackDurationUs = bufferedDurationUs;
            }
            if (trackDurationUs > 0) {
                ALOGV("[SourceType%d] durationUs=%" PRId64 "", type, trackDurationUs);
                const sp<MetaData> meta = impl->getFormat();
                meta->setInt64(kKeyDuration, trackDurationUs);
                impl->setFormat(meta);

                found = true;
            }
        }
        if (!found) {
            estimateDurationsFromTimesUsAtEnd();
        }
    }

    ALOGI("haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
            haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
}
相关推荐
Eric.Lee20212 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
却道天凉_好个秋7 分钟前
音视频学习(二十四):hls协议
音视频·hls
拭心11 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
darkdragonking13 小时前
FLV视频封装格式详解
音视频
带电的小王13 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡14 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道14 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库15 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道16 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe16 小时前
Android Hook - 动态加载so库
android