美文网首页
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