美文网首页
Android万能音频播放器07--添加停止播放功能并释放内存

Android万能音频播放器07--添加停止播放功能并释放内存

作者: 张俊峰0613 | 来源:发表于2019-01-10 09:45 被阅读0次

    1、释放所分配的内存

    释放顺序:释放队列->释放OpenSL->释放Audio->释放FFmpeg
    

    1.1、释放队列

    JfQueue.cpp

    void JfQueue::clearAVPacket() {
        //有可能释放资源时线程还在加锁中
        pthread_cond_signal(&condPacket);
    
        pthread_mutex_lock(&mutexPacket);
    
        while (!queuePacket.empty()){
            //先出队再释放
            AVPacket *packet = queuePacket.front();
            queuePacket.pop();
            av_packet_free(&packet);
            av_free(packet);
            packet = NULL;
        }
        pthread_mutex_unlock(&mutexPacket);
    }
    

    暂停播放:

    void JfAudio::stop() {
        if (pcmPlayerObject != NULL){
            (*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay,  SL_PLAYSTATE_STOPPED);
        }
    }
    

    1.2、释放OpenSL、Audio:

    void JfAudio::release() {
        stop();
    
        if (queue != NULL){
            delete(queue);
            queue = NULL;
        }
    
        if (pcmPlayerObject != NULL){
            (*pcmPlayerObject)->Destroy(pcmPlayerObject);
            pcmPlayerObject = NULL;
            pcmPlayerPlay = NULL;
            pcmBufferQueue = NULL;
        }
    
        if (outputMixObject != NULL){
            (*outputMixObject)->Destroy(outputMixObject);
            outputMixObject = NULL;
            outputMixEnvReb = NULL;
        }
    
        if (engineObject != NULL){
            (*engineObject)->Destroy(engineObject);
            engineObject = NULL;
            engineEngine = NULL;
        }
    
        if (buffer != NULL){
            free(buffer);
            buffer = NULL;
        }
    
        if (pACodecCtx != NULL){
            avcodec_close(pACodecCtx);
            avcodec_free_context(&pACodecCtx);
            pACodecCtx = NULL;
        }
    
        if (playStatus != NULL){
            playStatus = NULL;
        }
    
        if (callJava != NULL){
            callJava = NULL;
        }
    }
    

    1.3、释放FFmpeg:

    这个比较麻烦,可能网络初始化中,可能还有其他线程,所以设置线程超时回调:void JfFFmpeg::decodeAudioThread()

    int avformat_callback(void *ctx){
        JfFFmpeg *jfFFmpeg = (JfFFmpeg *)ctx;
        if (jfFFmpeg->playStatus->exit){
            return AVERROR_EOF;
        }
        return 0;
    }
    
    pAFmtCtx->interrupt_callback.callback = avformat_callback;
    pAFmtCtx->interrupt_callback.opaque = this;
    

    释放FFmpeg资源

    void JfFFmpeg::release() {
        if (playStatus->exit){
            return;
        }
        //这里的代码会直接继续向下走,但是某些线程可能还在执行
        //如果在解码线程执行过程中就给线程加锁,一直等待线程执行完然后
        playStatus->exit = true;
    
        pthread_mutex_lock(&init_mutex);
    
        int sleepCount = 0;
        while (!exit){
            if (sleepCount > 1000){
                exit = true;
            }
            if (LOG_DEBUG){
                LOGD("WAIT FFMPEG EXIT %d",sleepCount);
            }
            sleepCount++;
            av_usleep(1000 * 10);//10ms
        }
    
        if (audio != NULL){
            audio->release();
            delete(audio);
            audio = NULL;
        }
        if (pAFmtCtx != NULL){
            avformat_close_input(&pAFmtCtx);
            avformat_free_context(pAFmtCtx);
            pAFmtCtx = NULL;
        }
        if (playStatus != NULL){
            playStatus = NULL;
        }
        if (callJava != NULL) {
            callJava = NULL;
        }
        pthread_mutex_unlock(&init_mutex);
    }
    

    1.4、Java调用暂停

    public void stop(){
        //在C++层有一个while循环,可能会耗时较长
        new Thread(new Runnable() {
            @Override
            public void run() {
                n_stop();
            }
        }).start();
    }
    
    private native void n_stop();
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_example_myplayer_player_JfPlayer_n_1stop(JNIEnv *env, jobject instance) {
    
        // TODO
        if (ffmpeg != NULL){
            ffmpeg->release();
            delete(ffmpeg);
            ffmpeg = NULL;
    
            if (callJava != NULL){
                delete(callJava);
                callJava = NULL;
            }
            if (playStatus != NULL){
                delete(playStatus);
                playStatus = NULL;
            }
        }
    }
    

    2、处理异常情况

    比如:数据流还在加载中,就停止播放。
    

    相关文章

      网友评论

          本文标题:Android万能音频播放器07--添加停止播放功能并释放内存

          本文链接:https://www.haomeiwen.com/subject/foeprqtx.html