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");

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android 中的 MediaCodec 类可以用于进行音频和视频的件加速解码,也可以用于软解码。下面是一个使用 MediaCodec 进行软解码的简单示例: 1. 首先创建一个 MediaExtractor 对象,用于从媒体文件中提取音视频数据。 ```java MediaExtractor extractor = new MediaExtractor(); extractor.setDataSource(filePath); ``` 2. 根据需要解码的轨道类型(音频或视频),选择对应的轨道进行解码。 ```java int trackIndex = -1; for (int i = 0; i < extractor.getTrackCount(); i++) { MediaFormat format = extractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME); if (mime.startsWith("audio/")) { // 解码音频轨道 trackIndex = i; break; } else if (mime.startsWith("video/")) { // 解码视频轨道 trackIndex = i; break; } } if (trackIndex == -1) { // 没有找到相应的轨道,退出 return; } extractor.selectTrack(trackIndex); ``` 3. 创建 MediaCodec 对象并进行配置。 ```java MediaFormat format = extractor.getTrackFormat(trackIndex); MediaCodec codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME)); codec.configure(format, null, null, 0); codec.start(); ``` 4. 循环读取音视频数据并进行解码。读取的数据需要写入到 MediaCodec 的输入缓冲区中,然后调用 MediaCodec 的 dequeueInputBuffer() 方法获取已经被填充数据的输入缓冲区,并将其传递给 MediaCodec 进行解码解码完成后,从 MediaCodec 的输出缓冲区中读取解码后的音视频数据。 ```java boolean inputEnd = false; boolean outputEnd = false; while (!outputEnd) { if (!inputEnd) { int inputBufferIndex = codec.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex); int sampleSize = extractor.readSampleData(inputBuffer, 0); if (sampleSize < 0) { inputEnd = true; codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); } else { codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, extractor.getSampleTime(), 0); extractor.advance(); } } } int outputBufferIndex = codec.dequeueOutputBuffer(info, -1); if (outputBufferIndex >= 0) { if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { outputEnd = true; } ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferIndex); // 处理解码后的音视频数据 codec.releaseOutputBuffer(outputBufferIndex, false); } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { MediaFormat newFormat = codec.getOutputFormat(); // 处理输出格式的变化 } } ``` 5. 最后,释放资源。 ```java codec.stop(); codec.release(); extractor.release(); ``` 这只是一个简单的示例,实际上使用 MediaCodec 进行软解码需要考虑很多细节,例如解码后的音视频数据的处理、异常情况的处理等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无v邪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值