IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:17:25  更:2022-08-19 19:18:29 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码