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);
}
相关推荐
没有了遇见4 分钟前
Android 渐变色整理之功能实现<二>文字,背景,边框,进度条等
android
没有了遇见1 小时前
Android RecycleView 条目进入和滑出屏幕的渐变阴影效果
android
站在巨人肩膀上的码农2 小时前
去掉长按遥控器power键后提示关机、飞行模式的弹窗
android·安卓·rk·关机弹窗·power键·长按·飞行模式弹窗
呼啦啦--隔壁老王2 小时前
屏幕旋转流程
android
人生何处不修行2 小时前
实战:Android 15 (API 35) 适配 & 构建踩坑全记录
android
用户2018792831672 小时前
gralde的《依赖契约法典》
android
沐尘而生4 小时前
【AI智能体】智能音视频-硬件设备基于 WebSocket 实现语音交互
大数据·人工智能·websocket·机器学习·ai作画·音视频·娱乐
你过来啊你6 小时前
Android Handler机制与底层原理详解
android·handler
RichardLai886 小时前
Kotlin Flow:构建响应式流的现代 Kotlin 之道
android·前端·kotlin
AirDroid_cn6 小时前
iQOO手机怎样相互远程控制?其他手机可以远程控制iQOO吗?
android·智能手机·iphone·远程控制·远程控制手机·手机远程控制手机