| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> android native层使用mediacodec(硬编解码) mediamuxer mediaExtractor做转码工具。 -> 正文阅读 |
|
[移动开发]android native层使用mediacodec(硬编解码) mediamuxer mediaExtractor做转码工具。 |
android::sp<android::NuMediaExtractor> spMediaExtractor = new android::NuMediaExtractor(IMediaExtractor::EntryPoint::SDK);//传OTHER压力测试,setDataSource会卡住 ? ? ? ?// android::sp<android::FileSource> spFsrc = new android::FileSource(srcPath.c_str()); ? ? ? ? if(spMediaExtractor->setDataSource(NULL,srcPath.c_str()) != android::OK){ ? ? ? ? ? ? return ErrCode::CodeRetEBADF; ? ? ? ? } 源码如下: /* ?* @Descripttion: ?* @version: ?* @Author: chengfan ?* @Date: 2022-08-10 09:30:05 ?* @LastEditors: chengfan ?* @LastEditTime: 2022-08-16 19:45:30 ?*/ #include "OffSensitive.hpp" #include "MiscUtils.h" #include <thread> #include <media/openmax/OMX_IVCommon.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaCodec.h> #include <datasource/FileSource.h> #include <media/IMediaHTTPService.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaMuxer.h> #include <media/stagefright/NuMediaExtractor.h> #include <gui/Surface.h> #include <mediadrm/ICrypto.h> #include <media/MediaCodecBuffer.h> #include <utils/KeyedVector.h> #define HAS_SUR 0 #if HAS_SUR #include <ui/PixelFormat.h> #include <gui/ISurfaceComposer.h> #include <gui/SurfaceComposerClient.h> #endif using namespace android; //using android::android::ALooper; namespace yfcf { ? ? OffSensitive *OffSensitive::pOffSensitive = nullptr; ? ? OffSensitive::OffSensitive() ? ? { ? ? } ? ? OffSensitive::~OffSensitive() ? ? { ? ? } ? ? OffSensitive *OffSensitive::getInstance() ? ? { ? ? ? ? if (pOffSensitive == nullptr) ? ? ? ? ? ? pOffSensitive = new OffSensitive(); ? ? ? ? return pOffSensitive; ? ? } ? ? void OffSensitive::freeInstance() ? ? { ? ? ? ? delete pOffSensitive; ? ? ? ? pOffSensitive = nullptr; ? ? } ? ? ? ? struct AllPoints{ ? ? ? ? NuMediaExtractor* extr; ? ? ? ? MediaCodec* vd; ? ? ? ? MediaCodec* ad; ? ? ? ? MediaMuxer* mux; ? ? ? ? MediaCodec* ve; ? ? ? ? MediaCodec* ae; ? ? ? ? bool * shouldEnd; ? ? ? ? bool muxStarted; ? ? ? ? bool mvStarted; ? ? ? ? bool maStarted; ? ? ? ? yuv420pHandler hd; ? ? }; ? ? static void vdFunc(void* arg); ? ? static void adFunc(void* arg); ? ? static void veFunc(void* arg); ? ? static void aeFunc(void* arg); ? ? ErrCode OffSensitive::start(string srcPath, string dstDir , string dstFileName,yuv420pHandler hd) ? ? { ? ? ? ? size_t srcFileSize = get_file_size(srcPath.c_str()); ? ? ? ? if( srcFileSize == 0){ ? ? ? ? ? ? return ErrCode::CodeRetEINVAL; ? ? ? ? } ? ? ? ? uint64_t remainSpace = ?check_par_remain(dstDir.c_str()); ? ? ? ? if(remainSpace <= srcFileSize ){ ? ? ? ? ? ? return ErrCode::CodeRetENOSPC; ? ? ? ? } ? ? ? ? bool shouldEnd = true; ? ? ? ? android::sp<android::NuMediaExtractor> spMediaExtractor = new android::NuMediaExtractor(IMediaExtractor::EntryPoint::OTHER); ? ? ? ?// android::sp<android::FileSource> spFsrc = new android::FileSource(srcPath.c_str()); ? ? ? ? if(spMediaExtractor->setDataSource(NULL,srcPath.c_str()) != android::OK){ ? ? ? ? ? ? return ErrCode::CodeRetEBADF; ? ? ? ? } ? ? ? ? size_t trackCnt = spMediaExtractor->countTracks(); ? ? ? ? android::sp<android::AMessage> spFormat; ? ? ? ? android::AString mime; ? ? ? ? int32_t vTrackId = -1; ? ? ? ? sp<android::ALooper> spVideoDecLooper ; ? ? ? ? sp<MediaCodec> spVideoDec ; ? ? ? ? sp<android::ALooper> spVideoEncLooper ; ? ? ? ? sp<MediaCodec> spVideoEnc ; ? ? ? ? int32_t aTrackId = -1; ? ? ? ? sp<android::ALooper> spAudioDecLooper ; ? ? ? ? sp<MediaCodec> spAudioDec ; ? ? ? ? sp<android::ALooper> spAudioEncLooper ; ? ? ? ? sp<MediaCodec> spAudioEnc ; ? ? ? ? #if HAS_SUR ? ? ? ? sp<SurfaceComposerClient> mSession = new SurfaceComposerClient(); ? ? ? ? sp<SurfaceControl> control = mSession->createSurface(String8("offsen"), ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1920, 1080, PIXEL_FORMAT_RGBA_8888); ? ? ? ? SurfaceComposerClient::Transaction t; ? ? ? ? t.setLayer(control, 0x10000000); ? ? ? ? t.setLayerStack(control, 0); ? ? ? ? t.show(control); ? ? ? ? t.apply(); ? ? ? ? sp<Surface> mFlingerSurface = control->getSurface(); ? ? ? ? #endif ? ? ? ? for(size_t i = 0; i<trackCnt; i++){ ? ? ? ? ? ? if(spMediaExtractor->getTrackFormat(i,&spFormat)!=OK || spFormat->findString("mime",&mime)==false ) ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? int32_t br = 0; ? ? ? ? ? ? spFormat->findInt32("bitrate",&br); ? ? ? ? ? ? int32_t prof = -1;spFormat->findInt32("profile",&prof); ? ? ? ? ? ? if (strncasecmp(mime.c_str(),"video/",6)==0){ ? ? ? ? ? ? ? ? int32_t w = 0; ? ? ? ? ? ? ? ? spFormat->findInt32("width",&w); ? ? ? ? ? ? ? ? int32_t h = 0; ? ? ? ? ? ? ? ? spFormat->findInt32("height",&h); ? ? ? ? ? ? ? ? float fr = 0.; ? ? ? ? ? ? ? ? spFormat->findFloat("frame-rate",&fr); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"w=%d h=%d fr=%f br=%d",w,h,fr,br); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int32_t level = -1; spFormat->findInt32("level",&level); ? ? ? ? ? ? ? ? int32_t ifr = -1; spFormat->findInt32("frame-rate",&ifr); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"prof%d level=%d %d",prof,level,ifr); ? ? ? ? ? ? ? ? if(w==0 || h==0 ){ ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spVideoDecLooper = new android::ALooper(); ? ? ? ? ? ? ? ? spVideoDecLooper->setName("video_dec"); ? ? ? ? ? ? ? ? if(spVideoDecLooper->start() != OK){ ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"video dec loop start err"); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spVideoDec = MediaCodec::CreateByType(spVideoDecLooper,mime,false); ? ? ? ? ? ? ? ? if(spVideoDec.get() == nullptr){ ? ? ? ? ? ? ? ? ? ? spVideoDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"create video dec err:%s",mime.c_str()); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? // ?sp<Surface> spSurface; ? ? ? ? ? ? ? #if HAS_SUR ? ? ? ? ? ? ? ? if(spVideoDec->configure(spFormat,mFlingerSurface,NULL,0) != OK){ ? ? ? ? ? ? ? #else ? ? ? ? ? ? ? ? if(spVideoDec->configure(spFormat,NULL,NULL,0) != OK){ ? ? ? ? ? ? ? #endif ? ? ? ? ? ? ? ? ? ? spVideoDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? spVideoDec->release(); ? ? ? ? ? ? ? ? ? ? spVideoDec.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"configure video dec err"); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? sp<AMessage> veformat = new AMessage; ? ? ? ? ? ? ? ? veformat->setInt32("width", w); ? ? ? ? ? ? ? ? ? ? veformat->setInt32("height", h); ? ? ? ? ? ? ? ? ? veformat->setString("mime", "video/avc"); ? ? ? ? ? ? ? ? ? //OMX_COLOR_FormatYUV420Flexible ? ? ? ? ? ? ? ? ? veformat->setInt32("color-format", OMX_COLOR_FormatYUV420Flexible); ? ? ? ? ? ? ? ? if(br<10) ? ? ? ? ? ? ? ? ? ? br = w*h*58/10; ? ? ? ? ? ? ? ?// LOGW(LOG_TAG,"BR IS %d",br); ? ? ? ? ? ? ? ? veformat->setInt32("bitrate", br); ? ? ? ? ? ? ? ? if(fr>1.0) ? ? ? ? ? ? ? ? ? ? veformat->setFloat("frame-rate",fr); ? ? ? ? ? ? ? ? if(ifr>2) ? ? ? ? ? ? ? ? ? ? veformat->setInt32("frame-rate",ifr); ? ? ? ? ? ? ? ?// veformat->setInt32("level",level); ? ? ? ? ? ? ? ? //PROFILE_AVC_MAIN ? ? ? ? ? ? ? ? if(prof==-1) ? ? ? ? ? ? ? ? ? ? prof = 2; ? ? ? ? ? ? ? // ?veformat->setInt32("profile", prof); ? ? ? ? ? ? ? ? ? veformat->setInt32("i-frame-interval", 5); ? ? ? ? ? ? ? ? ? spVideoEncLooper = new android::ALooper(); ? ? ? ? ? ? ? ? spVideoEncLooper->setName("video_enc"); ? ? ? ? ? ? ? ? if(spVideoEncLooper->start() != OK){ ? ? ? ? ? ? ? ? ? ? spVideoDec->release(); ? ? ? ? ? ? ? ? ? ? spVideoDec.clear(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"video enc loop start err"); ? ? ? ? ? ? ? ? ? ? spVideoEncLooper.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? spVideoEnc = MediaCodec::CreateByType(spVideoEncLooper,"video/avc",true); ? ? ? ? ? ? ? ? if(spVideoEnc.get() == nullptr){ ? ? ? ? ? ? ? ? ? ? spVideoEncLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoEncLooper.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"create video enc err:%s",mime.c_str()); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? spVideoDec->release(); ? ? ? ? ? ? ? ? ? ? spVideoDec.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(spVideoEnc->configure(veformat,nullptr,nullptr,MediaCodec::CONFIGURE_FLAG_ENCODE) != OK){ ? ? ? ? ? ? ? ? ? ? spVideoEnc->release(); ? ? ? ? ? ? ? ? ? ? spVideoEnc.clear(); ? ? ? ? ? ? ? ? ? ? spVideoEncLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoEncLooper.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"configure video enc err"); ? ? ? ? ? ? ? ? ? ? spVideoDec->release(); ? ? ? ? ? ? ? ? ? ? spVideoDec.clear(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spVideoDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(YFUNLIKELY(spMediaExtractor->selectTrack(i)!=OK)){ ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"extractor select video track err"); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? vTrackId = i; ? ? ? ? ? ? ? ? shouldEnd = false; ? ? ? ? ? ? }else if(strncasecmp(mime.c_str(),"audio/",6)==0 && spAudioDecLooper.get()==nullptr){ ? ? ? ? ? ? ? ? int32_t sr = 0; ? ? ? ? ? ? ? ? spFormat->findInt32("sample-rate",&sr); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int32_t mis = 0; ? ? ? ? ? ? ? ? spFormat->findInt32("max-input-size",&mis); ? ? ? ? ? ? ? ? int32_t chanelCnt= 0; ? ? ? ? ? ? ? ? spFormat->findInt32("channel-count",&chanelCnt); ? ? ? ? ? ? ? ? int32_t aacProf = -1; ? ? ? ? ? ? ? ? spFormat->findInt32("aac-profile",&aacProf); ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"sr=%d ?br=%d mis=%d chanelCnt=%d aac_profile=%d",sr,br,mis,chanelCnt,aacProf); ? ? ? ? ? ? ? ? if(spAudioEnc.get()){ ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"audio codec already inited"); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spAudioDecLooper = new android::ALooper(); ? ? ? ? ? ? ? ? spAudioDecLooper->setName("audio_dec"); ? ? ? ? ? ? ? ? if(spAudioDecLooper->start() != OK){ ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"Audio dec loop start err"); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spAudioDec = MediaCodec::CreateByType(spAudioDecLooper,mime,false); ? ? ? ? ? ? ? ? if(spAudioDec.get() == nullptr){ ? ? ? ? ? ? ? ? ? ? spAudioDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"create Audio dec err:%s",mime.c_str()); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(spAudioDec->configure(spFormat,nullptr,nullptr,0) != OK){ ? ? ? ? ? ? ? ? ? ? spAudioDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? spAudioDec->release(); ? ? ? ? ? ? ? ? ? ? spAudioDec.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"configure Audio dec err"); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? sp<AMessage> aeformat = new AMessage; ? ? ? ? ? ? ? ? aeformat->setString("mime", "audio/mp4a-latm"); ? ? ? ? ? ? ? ? if(br<10) ? ? ? ? ? ? ? ? ? ? br = 48000; ? ? ? ? ? ? ? ? ? ? aeformat->setInt32("bitrate", 125000); ? ? ? ? ? ? ? ? if(sr<100) ? ? ? ? ? ? ? ? ? ? sr = 48000; ? ? ? ? ? ? ? ? aeformat->setInt32("sample-rate",sr); ? ? ? ? ? ? ? ? if(mis<10) ? ? ? ? ? ? ? ? ? ? mis = ?65541; mis = 1048576; ? ? ? ? ? ? ? ? aeformat->setInt32("max-input-size",mis); ? ? ? ? ? ? ? ? aeformat->setInt32("channel-count",1); ? ? ? ? ? ? ? // ?aeformat->setInt32("profile", prof); ? ? ? ? ? ? ? ? if(aacProf==-1) ? ? ? ? ? ? ? ? ? ? aacProf = 2; ? ? ? ? ? ? ? ? aeformat->setInt32("aac-profile", aacProf); ? ? ? ? ? ? ? ? ? spAudioEncLooper = new android::ALooper(); ? ? ? ? ? ? ? ? spAudioEncLooper->setName("Audio_enc"); ? ? ? ? ? ? ? ? if(spAudioEncLooper->start() != OK){ ? ? ? ? ? ? ? ? ? ? spAudioDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? spAudioDec->release(); ? ? ? ? ? ? ? ? ? ? spAudioDec.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"Audio enc loop start err"); ? ? ? ? ? ? ? ? ? ? spAudioEncLooper.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spAudioEnc = MediaCodec::CreateByType(spAudioEncLooper,"audio/mp4a-latm",true); ? ? ? ? ? ? ? ? if(spAudioEnc.get() == nullptr){ ? ? ? ? ? ? ? ? ? ? spAudioEncLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioEncLooper.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"create Audio enc err:%s",mime.c_str()); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? spAudioDec->release(); ? ? ? ? ? ? ? ? ? ? spAudioDec.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(spAudioEnc->configure(aeformat,NULL,NULL,MediaCodec::CONFIGURE_FLAG_ENCODE) != OK){ ? ? ? ? ? ? ? ? ? ? spAudioEncLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioEncLooper.clear(); ? ? ? ? ? ? ? ? ? ? spAudioEnc->release(); ? ? ? ? ? ? ? ? ? ? spAudioEnc.clear(); ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"configure Audio enc err"); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper->stop(); ? ? ? ? ? ? ? ? ? ? spAudioDecLooper.clear(); ? ? ? ? ? ? ? ? ? ? spAudioDec->release(); ? ? ? ? ? ? ? ? ? ? spAudioDec.clear(); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(YFUNLIKELY(spMediaExtractor->selectTrack(i)!=OK)){ ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"extractor select Audio track err"); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? aTrackId = i; ? ? ? ? ? ? ? ? shouldEnd = false; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? if(shouldEnd){ ? ? ? ? ? ? return ErrCode::CodeRetEBADF; ? ? ? ? } ? ? ? ? string dstFileFull = dstDir + dstFileName; ? ? ? ? int outFd = open( dstFileFull.c_str(), O_CREAT|O_CLOEXEC|O_TRUNC|O_RDWR,0666); ? ? ? ? if(outFd == -1){ ? ? ? ? ? ? LOGE(LOG_TAG,"open file err %s %s",dstFileFull.c_str(),strerror(errno)); ? ? ? ? } ? ? ? ? sp<MediaMuxer> spMediaMux = new MediaMuxer(outFd,MediaMuxer::OUTPUT_FORMAT_MPEG_4); ? ? ? ? if(vTrackId>=0){ ? ? ? ? ? ? if(spVideoDec->start()!=OK) ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"video dec start err,should never happen"); ? ? ? ? ? ? } ? ? ? ? if(aTrackId>=0){ ? ? ? ? ? ? if(spAudioDec->start()!=OK) ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"audio dec start err,should never happen"); ? ? ? ? } ? ? ? ? AllPoints arg = {spMediaExtractor.get(),spVideoDec.get(),spAudioDec.get(),spMediaMux.get(),spVideoEnc.get(),spAudioEnc.get(),&shouldEnd,false,false,false,hd}; ? ? ? ? std::thread vdTid(vdFunc,&arg); ? ? ? ? std::thread adTid(adFunc,&arg); ? ? ? ? size_t avTrackId = -1011; ? ? ? ? size_t buffIndex; ? ? ? ? ? ? ? ? status_t tmp; ? ? ? ? size_t sampSize; ? ? ? ? int64_t pts; ? ? ? ? AString err_str; ? ? ? ? sp<ABuffer> spAbuf; ? ? ? ? #if 0 ? ? ? ? Vector<sp<MediaCodecBuffer>> vdBufs; ? ? ? ? spVideoDec->getInputBuffers(&vdBufs); ? ? ? ? Vector<sp<MediaCodecBuffer>> adBufs; ? ? ? ? spVideoDec->getInputBuffers(&adBufs); ? ? ? ? #endif ? ? ? ? while (!shouldEnd) ? ? ? ? { ? ? ? ? ? ? tmp = spMediaExtractor->getSampleTrackIndex(&avTrackId); ? ? ? ? ? // ?LOGD(LOG_TAG,"avTrackId is %" PRIuFAST32,avTrackId); ? ? ? ? ? ? if(tmp == -1011){ ? ? ? ? ? ? ? ? shouldEnd = true; ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"EXTRACTOR end"); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? if(spMediaExtractor->getSampleSize(&sampSize) != OK || spMediaExtractor->getSampleTime(&pts)!= OK){ ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"this should never happen"); ? ? ? ? ? ? } ? ? ? ? ? ? if(sampSize<=0){ ? ? ? ? ? ? ? ? shouldEnd = true; ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"EXTRACTOR end2"); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? if(avTrackId == vTrackId){ ? ? ? ? ? ? ? ? while( (tmp = spVideoDec->dequeueInputBuffer(&buffIndex,70000))!=OK) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? static uint32_t cnt = 0; ? ? ? ? ? ? ? ? ? ? cnt++; ? ? ? ? ? ? ? ? ? ? if(tmp!=-11) ? ? ? ? ? ? ? ? ? ? ? ? cnt = 11; ? ? ? ? ? ? ? ? ? ? if(cnt>=10){ ? ? ? ? ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"VD dequeue ibuff err %d",tmp); ? ? ? ? ? ? ? ? ? ? ? ? cnt = 0; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? sp<MediaCodecBuffer> spMediaCodecBuf; ? ? ? ? ? ? ? ? spVideoDec->getInputBuffer(buffIndex,&spMediaCodecBuf); ? ? ? ? ? ? ? // ?spMediaCodecBuf = vdBufs.itemAt(buffIndex); ? ? ? ? ? ? ? ? spAbuf = ?new ABuffer(spMediaCodecBuf->base(), spMediaCodecBuf->capacity()); ? ? ? ? ? ? ? ? tmp =spMediaExtractor->readSampleData(spAbuf); ? ? ? ? ? ? ? ? if(tmp != OK){ ? ? ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"V readSampleData err %" PRId32,tmp); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spMediaCodecBuf->setRange(spAbuf->offset(), spAbuf->size()); ? ? ? ? ? ? ? ? tmp = spVideoDec->queueInputBuffer(buffIndex,spAbuf->offset(),spAbuf->size(),pts,0,&err_str); ? ? ? ? ? ? ? ? if(tmp!=OK){ ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"V dec queue ibuff err:%d %s",tmp,err_str.c_str()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spMediaExtractor->advance(); ? ? ? ? ? ? }else if(avTrackId == aTrackId){ ? ? ? ? ? ? ? ? while( (tmp = spAudioDec->dequeueInputBuffer(&buffIndex,50000))!= OK){ ? ? ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"aD dequeue ibuff err %" PRId32,tmp); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? sp<MediaCodecBuffer> spMediaCodecBuf; ? ? ? ? ? ? ? ? while ( (tmp = spAudioDec->getInputBuffer(buffIndex,&spMediaCodecBuf))!=OK) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"a err %d bidx=%" PRIuFAST32,tmp,buffIndex); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spAbuf = ?new ABuffer(spMediaCodecBuf->base(), spMediaCodecBuf->capacity()); ? ? ? ? ? ? ? ? tmp =spMediaExtractor->readSampleData(spAbuf); ? ? ? ? ? ? ? ? if(tmp != OK){ ? ? ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"a readSampleData err %" PRId32,tmp); ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? tmp = spAudioDec->queueInputBuffer(buffIndex,0,sampSize,pts,0,&err_str); ? ? ? ? ? ? ? ? if(tmp!=OK){ ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"a dec queue ibuff err:%d %s",tmp,err_str.c_str()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? spMediaExtractor->advance(); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? vdTid.join(); ? ? ? ? adTid.join(); ? ? ? ? spMediaMux->stop(); ? ? ? ? if(outFd!=-1) ? ? ? ? ? ? close(outFd); ? ? ? ? spVideoDec->stop(); ? ? ? ? spVideoDec->release(); ? ? ? ? spVideoDecLooper->stop(); ? ? ? ? spVideoEnc->stop(); ? ? ? ? spVideoEnc->release(); ? ? ? ? spVideoEncLooper->stop(); ? ? ? ? spAudioDec->stop(); ? ? ? ? spAudioDec->release(); ? ? ? ? spAudioDecLooper->stop(); ? ? ? ? spAudioEnc->stop(); ? ? ? ? spAudioEnc->release(); ? ? ? ? spAudioEncLooper->stop(); ? ? ? ? #if HAS_SUR ? ? ? ? mFlingerSurface.clear(); ? ? ? ? control.clear(); ? ? ? ? mSession.clear(); ? ? ? ? #endif ? ? ? ? LOGI(LOG_TAG,"off-sensitive end"); ? ? ? ? return ?ErrCode::CodeRetOK; ? ? } ? ? ? ? void vdFunc(void* arg){ ? ? ? ? AllPoints* all = (AllPoints*)arg; ? ? ? ? all->ve->start(); ? ? ? ? size_t bufIdx; ? ? ? ? size_t offset = 0; ? ? ? ? size_t sampSize; ? ? ? ? int64_t pts; ? ? ? ? uint32_t oFlags; ? ? ? ? size_t oBufIdx; ? ? ? ? status_t tmp; ? ? ? ? sp<MediaCodecBuffer> spMcb; ? ? ? ? sp<MediaCodecBuffer> spMcbi; ? ? ? ? AString err_str; ? ? ? ? bool* shouldEnd = all->shouldEnd; ? ? ? ? std::thread veTid(veFunc,arg); ? ? ? ? while(*shouldEnd == false){ ? ? ? ? ? ? oFlags = 0; ? ? ? ? ? ? tmp = all->vd->dequeueOutputBuffer(&bufIdx,&offset,&sampSize,&pts,&oFlags,20000); ? ? ? ? ? ? if((tmp!=OK && tmp!=-11)||oFlags>1 ){ ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"VD de obuf tmp=%d flag %d index=%" PRIuFAST32 ,tmp,oFlags,bufIdx); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? if(tmp == -1012){ ? ? ? ? ? ? ? ? sp<AMessage> format ; ? ? ? ? ? ? ? ? all->vd->getOutputFormat(&format); ? ? ? ? ? ? ? ? int32_t cf = -1; ? ? ? ? ? ? ? ? format->findInt32("color-format",&cf); ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"VD COlor format is %d",cf); ? ? ? ? ? ? } ? ? ? ? ? ? if(tmp!=OK) ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? if(oFlags&MediaCodec::BUFFER_FLAG_EOS){ ? ? ? ? ? ? ? ? *shouldEnd = true; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? if(bufIdx>=0){ ? ? ? ? ? ? ? ? all->vd->getOutputBuffer(bufIdx,&spMcb); ? ? ? ? ? ? ? ? if(all->hd) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? all->hd(spMcb->data(),spMcb->size()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? while( (tmp = all->ve->dequeueInputBuffer(&oBufIdx,50000) ) !=OK){ ? ? ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"VE de ibuf err %" PRId32,tmp); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? all->ve->getInputBuffer(oBufIdx,&spMcbi); ? ? ? ? ? ? ? ? spMcbi->setRange(spMcb->offset(),spMcb->size()); ? ? ? ? ? ? ? ? memcpy(spMcbi->data(),spMcb->data(),spMcb->size()); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tmp =all->ve->queueInputBuffer(oBufIdx,0,sampSize,pts,0,&err_str); ? ? ? ? ? ? ? ? if(tmp!=OK){ ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"ve queue ibuf err %s %" PRId32,err_str.c_str(),tmp); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? all->vd->releaseOutputBuffer(bufIdx); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? all->vd->flush(); ? ? ? ? LOGI(LOG_TAG,"vd end"); ? ? ? ? veTid.join(); ? ? } ? ? static uint64_t avTs[2] = {0,0}; ? ? void veFunc(void* arg){ ? ? ? ? AllPoints* all = (AllPoints*)arg; ? ? ? ? size_t bufIdx; ? ? ? ? size_t offset = 0; ? ? ? ? size_t sampSize; ? ? ? ? int64_t pts; ? ? ? ? uint32_t oFlags; ? ? ? ? size_t oBufIdx; ? ? ? ? status_t tmp; ? ? ? ? sp<MediaCodecBuffer> spMcb; ? ? ? ? AString err_str; ? ? ? ? sp<AMessage> oFormat; ? ? ? ? bool* shouldEnd = all->shouldEnd; ? ? ? ? size_t vTrackIdE = -1; ? ? ? ? sp<ABuffer> spAbuf; ? ? ? ? while (*shouldEnd == false) ? ? ? ? { ? ? ? ? ? ? oFlags = 0; ? ? ? ? ? ? tmp = all->ve->dequeueOutputBuffer(&bufIdx,&offset,&sampSize,&pts,&oFlags,20000); ? ? ? ? ? ? if((tmp!=OK && tmp!=-11)||oFlags >1 ){ ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"Ve de obuf tmp=%d flag %d index=%" PRIuFAST32 ,tmp,oFlags,bufIdx); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? switch (tmp) ? ? ? ? ? ? { ? ? ? ? ? ? case OK:{ ? ? ? ? ? ? ? ? all->ve->getOutputBuffer(bufIdx,&spMcb); ? ? ? ? ? ? ? ? spAbuf = new ABuffer(spMcb->data(),spMcb->size()); ? ? ? ? ? ? ? ? if(avTs[0]==0){ ? ? ? ? ? ? ? ? ? ? avTs[0] = bag_get_boot_time(); ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"vpts=%" PRId64 ,pts); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(all->muxStarted) ? ? ? ? ? ? ? ? ? ? all->mux->writeSampleData(spAbuf,vTrackIdE,pts,oFlags); ? ? ? ? ? ? ? ? all->ve->releaseOutputBuffer(bufIdx); ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case INFO_FORMAT_CHANGED:{ ? ? ? ? ? ? ? ? all->ve->getOutputFormat(&oFormat); ? ? ? ? ? ? ? ? vTrackIdE = all->mux->addTrack(oFormat); ? ? ? ? ? ? ? ? //toDo lock ? ? ? ? ? ? ? ? all->mvStarted = true; ? ? ? ? ? ? ? ? if(all->maStarted){ ? ? ? ? ? ? ? ? ? ? all->mux->start(); ? ? ? ? ? ? ? ? ? ? all->muxStarted = true; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? default: ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? if(oFlags&MediaCodec::BUFFER_FLAG_EOS ){ ? ? ? ? ? ? ? ? *shouldEnd = true; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? all->ve->flush(); ? ? ? ? LOGI(LOG_TAG,"ve end"); ? ? } ? ? void adFunc(void* arg){ ? ? ? ? AllPoints* all = (AllPoints*)arg; ? ? ? ? all->ae->start(); ? ? ? ? size_t bufIdx; ? ? ? ? size_t offset = 0; ? ? ? ? size_t sampSize; ? ? ? ? int64_t pts; ? ? ? ? uint32_t oFlags; ? ? ? ? size_t oBufIdx; ? ? ? ? status_t tmp; ? ? ? ? sp<MediaCodecBuffer> spMcb; ? ? ? ? sp<MediaCodecBuffer> spMcbi; ? ? ? ? AString err_str; ? ? ? ? bool* shouldEnd = all->shouldEnd; ? ? ? ? std::thread aeTid(aeFunc,arg); ? ? ? ? while(*shouldEnd == false){ ? ? ? ? ? ? oFlags = 0; ? ? ? ? ? ? tmp = all->ad->dequeueOutputBuffer(&bufIdx,&offset,&sampSize,&pts,&oFlags,20000); ? ? ? ? ? ? if((tmp!=OK && tmp!=-11)||oFlags>1 ){ ? ? ? ? ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"aD de obuf flag %d tmp=%d index=%" PRIuFAST32 ,oFlags,tmp,bufIdx); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? if(oFlags&MediaCodec::BUFFER_FLAG_EOS ){ ? ? ? ? ? ? ? ? *shouldEnd = true; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? if(tmp == OK){ ? ? ? ? ? ? ? ? all->ad->getOutputBuffer(bufIdx,&spMcb); ? ? ? ? ? ? ? ? while( (tmp = all->ae->dequeueInputBuffer(&oBufIdx,50000) ) !=OK){ ? ? ? ? ? ? ? ? ? ? LOGI(LOG_TAG,"aE de ibuf err %" PRId32,tmp); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? all->ae->getInputBuffer(oBufIdx,&spMcbi); ? ? ? ? ? ? ?// ? LOGD(LOG_TAG,"off=%" PRIuFAST32 "cap=%" PRIuFAST32,spMcb->offset(),spMcb->capacity()); ? ? ? ? ? ? ? ? spMcbi->setRange(spMcb->offset(),spMcb->size()); ? ? ? ? ? ? ? ? memcpy(spMcbi->data(),spMcb->data(),spMcb->size()); ? ? ? ? ? ? ? ? tmp =all->ae->queueInputBuffer(oBufIdx,0,sampSize,pts,0,&err_str); ? ? ? ? ? ? ? ? if(tmp!=OK){ ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"ae queue ibuf err %s %" PRId32,err_str.c_str(),tmp); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? all->ad->releaseOutputBuffer(bufIdx); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? all->ad->flush(); ? ? ? ? LOGI(LOG_TAG,"ad end"); ? ? ? ? aeTid.join(); ? ? } ? ? struct ABuffInfo{ ? ? ? ? uint8_t* data; ? ? ? ? size_t dl; ? ? ? ? uint32_t oFlags; ? ? ? ? int64_t pts; ? ? }; ? ? void aeFunc(void* arg){ ? ? ? ? AllPoints* all = (AllPoints*)arg; ? ? ? ? size_t bufIdx; ? ? ? ? size_t offset = 0; ? ? ? ? size_t sampSize; ? ? ? ? int64_t pts; ? ? ? ? uint32_t oFlags; ? ? ? ? size_t oBufIdx; ? ? ? ? status_t tmp; ? ? ? ? sp<MediaCodecBuffer> spMcb; ? ? ? ? AString err_str; ? ? ? ? sp<AMessage> oFormat; ? ? ? ? bool* shouldEnd = all->shouldEnd; ? ? ? ? size_t aTrackIdE = -1; ? ? ? ? sp<ABuffer> spAbuf; ? ? ? ? Vector<ABuffInfo*> bufs; ? ? ? ? bufs.clear(); ? ? ? ? int ccc=0; ? ? ? ? while (*shouldEnd == false) ? ? ? ? { ? ? ? ? ? ? oFlags = 0; ? ? ? ? ? ? tmp = all->ae->dequeueOutputBuffer(&bufIdx,&offset,&sampSize,&pts,&oFlags,20000); ? ? ? ? ? ? if((tmp!=OK && tmp!=-11)||oFlags>1 ){ ? ? ? ? ? ? ? ? LOGD(LOG_TAG,"ae de obuf tmp=%d flag %d index=%" PRIuFAST32 ,tmp,oFlags,bufIdx); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? switch (tmp) ? ? ? ? ? ? { ? ? ? ? ? ? case OK:{ ? ? ? ? ? ? ? ? if(oFlags&MediaCodec::BUFFER_FLAG_EOS ){ ? ? ? ? ? ? ? ? ? ? *shouldEnd = true; ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? }else if(oFlags&MediaCodec::BUFFER_FLAG_CODECCONFIG){ ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? all->ae->getOutputBuffer(bufIdx,&spMcb); ? ? ? ? ? ? ? ? spAbuf = new ABuffer(spMcb->data(),sampSize); ? ? ? ? ? ? ? ? static uint64_t loss = 0; ? ? ? ? ? ? ? ? static int64_t ps = 0; ? ? ? ? ? ? ? ? #if 1 ? ? ? ? ? ? ? ? ? ? ABuffInfo* bi = new ABuffInfo; ? ? ? ? ? ? ? ? ? ? bi->data = (uint8_t*)malloc(sampSize); ? ? ? ? ? ? ? ? ? ? memcpy(bi->data,spMcb->data(),sampSize); ? ? ? ? ? ? ? ? ? ? bi->dl = sampSize; ? ? ? ? ? ? ? ? ? ? bi->oFlags = oFlags; ? ? ? ? ? ? ? ? ? ? bi->pts = pts; ? ? ? ? ? ? ? ? ? ? bufs.add(bi); ? ? ? ? ? ? ? ? ? ? ccc++; ? ? ? ? ? ? ? ? ? ? #endif ? ? ? ? ? ? ? ? if(all->muxStarted){ ? ? ? ? ? ? ? ? ? ? #if 1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for(size_t i =0 ;i<bufs.size();i++){ ? ? ? ? ? ? ? ? ? ? ? ? sp<ABuffer> ab = new ABuffer(bufs.editItemAt(i)->data,bufs.editItemAt(i)->dl); ? ? ? ? ? ? ? ? ? ? ? ? tmp = all->mux->writeSampleData(ab,aTrackIdE,bufs.editItemAt(i)->pts,bufs.editItemAt(i)->oFlags); ? ? ? ? ? ? ? ? ? ? ? ? if(tmp!=OK || bufs.editItemAt(i)->oFlags){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? LOGE(LOG_TAG,"tmp-=%d %" PRIu32,tmp,bufs.editItemAt(i)->oFlags); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? free(bufs.editItemAt(i)->data); ? ? ? ? ? ? ? ? ? ? ? ? delete bufs.editItemAt(i); ? ? ? ? ? ? ? ? ? ? ? ? bufs.removeAt(i); ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? #endif ? ? ? ? ? ? ? ? ? ? if(avTs[1]==0){ ? ? ? ? ? ? ? ? ? ? ? ? avTs[1] = bag_get_boot_time(); ? ? ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"av %" PRIu64 " %" PRIu64,avTs[1],avTs[0]); ? ? ? ? ? ? ? ? ? ? ? ? LOGW(LOG_TAG,"TS %" PRId64 " %" PRId64 " %" PRIu64,ps,pts,loss); ? ? ? ? ? ? ? ? ? ? ? ? ps = pts; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ?// ? tmp = all->mux->writeSampleData(spAbuf,aTrackIdE,pts,oFlags); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? else{ ? ? ? ? ? ? ? ? ? ? if(ps==0) ? ? ? ? ? ? ? ? ? ? ? ? ps = pts; ? ? ? ? ? ? ? ? ? ? loss+=sampSize; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? all->ae->releaseOutputBuffer(bufIdx); ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case INFO_FORMAT_CHANGED:{ ? ? ? ? ? ? ? ? all->ae->getOutputFormat(&oFormat); ? ? ? ? ? ? ? ? aTrackIdE = all->mux->addTrack(oFormat); ? ? ? ? ? ? ? ? //toDo lock ? ? ? ? ? ? ? ? all->maStarted = true; ? ? ? ? ? ? ? ? if(all->mvStarted){ ? ? ? ? ? ? ? ? ? ? all->mux->start(); ? ? ? ? ? ? ? ? ? ? all->muxStarted = true; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? default: ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? all->ae->flush(); ? ? ? ? LOGI(LOG_TAG,"ae end"); ? ? } } |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 4:19:44- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |