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、处理异常情况
比如:数据流还在加载中,就停止播放。
网友评论