如果出错,要把出错信息传给应用层,告诉开发者出错信息,然后做相应处理,出错回调:
void onError(int code, String msg);
在出错回调里面回收资源,并添加变量避免重复调用stop方法。
回调Listener方法:
public interface JfOnErrorListener {
void onError(int code,String msg);
}
设置回调:
private JfOnErrorListener jfOnErrorListener;
public void setJfOnErrorListener(JfOnErrorListener jfOnErrorListener) {
this.jfOnErrorListener = jfOnErrorListener;
}
//供C++调用
public void onCallError(int code,String msg){
if (jfOnErrorListener != null) {
jfOnErrorListener.onError(code,msg);
}
}
C++调用Java方法:
jmid_error = env->GetMethodID(jclz,"onCallError","(ILjava/lang/String;)V");
void JfCallJava::onCallError(int threadType, int code, char *msg) {
if (threadType == MAIN_THREAD){
jstring jmsg = jniEnv->NewStringUTF(msg);
jniEnv->CallVoidMethod(jobj,jmid_error,code,jmsg);
jniEnv->DeleteLocalRef(jmsg);
} else if (threadType == CHILD_THREAD){
JNIEnv *jniEnv;
if (javaVM->AttachCurrentThread(&jniEnv,0) != JNI_OK){
if (LOG_DEBUG) {
LOGE("GET CHILD THREAD JNIENV ERROR");
return;
}
}
jstring jmsg = jniEnv->NewStringUTF(msg);
jniEnv->CallVoidMethod(jobj,jmid_error,code,jmsg);
jniEnv->DeleteLocalRef(jmsg);
javaVM->DetachCurrentThread();
}
}
在出错的地方调用,例如:
void JfFFmpeg::decodeAudioThread() {
pthread_mutex_lock(&init_mutex);
av_register_all();
avformat_network_init();
pAFmtCtx = avformat_alloc_context();
pAFmtCtx->interrupt_callback.callback = avformat_callback;
pAFmtCtx->interrupt_callback.opaque = this;
if (avformat_open_input(&pAFmtCtx,url,NULL,NULL) != 0){
if (LOG_DEBUG){
LOGE("open url file error url === %s",url);
callJava->onCallError(CHILD_THREAD,401,"open url file error url");
}
exit = true;
pthread_mutex_unlock(&init_mutex);
return;
}
if (avformat_find_stream_info(pAFmtCtx,NULL) < 0){
if (LOG_DEBUG){
LOGE("find stream info error url === %s",url);
callJava->onCallError(CHILD_THREAD,402,"find stream info error url");
}
exit = true;
pthread_mutex_unlock(&init_mutex);
return;
}
for (int i = 0; i < pAFmtCtx->nb_streams; i++) {
if (pAFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
if (audio == NULL) {
audio = new JfAudio(playStatus,pAFmtCtx->streams[i]->codecpar->sample_rate,callJava);
audio->streamIndex = i;
audio->codecpar = pAFmtCtx->streams[i]->codecpar;
audio->duration = pAFmtCtx->duration / AV_TIME_BASE;//单位是秒
audio->time_base = pAFmtCtx->streams[i]->time_base;
}
}
}
AVCodec *dec = avcodec_find_decoder(audio->codecpar->codec_id);
if (!dec){
if (LOG_DEBUG){
LOGE("FIND DECODER ERROR");
callJava->onCallError(CHILD_THREAD,403,"FIND DECODER ERROR");
}
exit = true;
pthread_mutex_unlock(&init_mutex);
return;
}
audio->pACodecCtx = avcodec_alloc_context3(dec);
if (!audio->pACodecCtx){
if (LOG_DEBUG){
LOGE("avcodec_alloc_context3 ERROR");
callJava->onCallError(CHILD_THREAD,404,"avcodec_alloc_context3 ERROR");
}
exit = true;
pthread_mutex_unlock(&init_mutex);
return;
}
if (avcodec_parameters_to_context(audio->pACodecCtx,audio->codecpar)){//将解码器中信息复制到上下文当中
if (LOG_DEBUG){
LOGE("avcodec_parameters_to_context ERROR");
callJava->onCallError(CHILD_THREAD,405,"avcodec_parameters_to_context ERROR");
}
exit = true;
pthread_mutex_unlock(&init_mutex);
return;
}
if (avcodec_open2(audio->pACodecCtx,dec,NULL) < 0){
if (LOG_DEBUG){
LOGE("avcodec_open2 ERROR");
callJava->onCallError(CHILD_THREAD,406,"avcodec_open2 ERROR");
}
exit = true;
pthread_mutex_unlock(&init_mutex);
return;
}
if (callJava != NULL){
if (playStatus != NULL && !playStatus->exit){
callJava->onCallPrepared(CHILD_THREAD);
} else {
exit = true;
}
}
pthread_mutex_unlock(&init_mutex);
}
在出错的时候要释放资源,调用stop方法,并添加变量避免重复调用stop方法。将变量nexit的初始值设为true,调用Java_com_example_myplayer_player_JfPlayer_n_1stop时,将nexit设为false,一直到资源释放完毕,再将nexit设为true,如果资源还没释放完毕,再次调用Java_com_example_myplayer_player_JfPlayer_n_1stop,此时nexit == false,则return,防止重复调用!
bool nexit = true;
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myplayer_player_JfPlayer_n_1stop(JNIEnv *env, jobject instance) {
if (!nexit){
return;
}
// TODO
nexit = false;
if (ffmpeg != NULL){
ffmpeg->release();
delete(ffmpeg);
ffmpeg = NULL;
if (callJava != NULL){
delete(callJava);
callJava = NULL;
}
if (playStatus != NULL){
delete(playStatus);
playStatus = NULL;
}
}
nexit = true;
}
网友评论