我是JNI新手,为什么我的android jni C++ try块没有捕获到异常
I am a novice JNI,Why doesn't my android jni C ++ try block catch an exception
我是JNI新手,为什么我的androidjni C++ try块没有捕获到异常,代码崩溃时应用程序崩溃没有跳转到异常处理
这是我的代码
Activity重新编码
在 JAVA 层接收带队列的 H264 数据
启动一个解码线程,不断从队列中取出一帧H264数据包进入C++层用FFmpeg解码
class decode extends Thread {
@Override
public void run() {
// super.run();
while (isDecode) {
byte[] data = one.poll();
if (data != null)
if (ffmpegUtilsInSignalOne != null)
ffmpegUtilsInSignalOne.decodeH264One(data);
}
}
}
cpp 文件代码
extern "C"
JNIEXPORT void JNICALL
Java_cn_zhihuiyun_control_utils_FFMPEGUtils_decodeH264One(JNIEnv *env, jobject thiz,
jbyteArray data) {
if (packetOne != nullptr && pCodecCtxOne != nullptr && vFrameOne != nullptr) {
if (data == nullptr)
return;;
if (isPlay == 0)
return;
jbyte *arr = env->GetByteArrayElements(data, JNI_FALSE);
packetOne->data = (uint8_t *) arr;
packetOne->size = env->GetArrayLength(data);
avcodec_send_packet(pCodecCtxOne, packetOne);
avcodec_receive_frame(pCodecCtxOne, vFrameOne);
av_packet_unref(packetOne);
env->ReleaseByteArrayElements(data, arr, 0);
}
}
此时在C层启动一个显示线程进行屏幕渲染
extern "C"
JNIEXPORT void JNICALL
Java_cn_zhihuiyun_control_utils_FFMPEGUtils_initVisThread(JNIEnv *env, jobject thiz) {
isPlay = 1;
threadVister = pthread_create(&threadVister, nullptr,
reinterpret_cast<void *(*)(void *)>(&showVideo),
(void *) env);
pthread_detach(threadVister);
}
void *showVideo(JNIEnv *env) {
try {
while (isPlay == 1) {
if (vFrameOne != nullptr && pFrameRGBAOne != nullptr && pCodecCtxOne != nullptr &&
nativeWindowOne != nullptr) {
ANativeWindow_lock(nativeWindowOne, &windowBufferOne, nullptr);
av_image_fill_arrays(pFrameRGBAOne->data, pFrameRGBAOne->linesize,
(const uint8_t *) windowBufferOne.bits, AV_PIX_FMT_RGBA,
detWidth, detHeight, 1);
int re = -1;
try {
re = libyuv::I420ToARGB(vFrameOne->data[0], vFrameOne->linesize[0],
vFrameOne->data[2], vFrameOne->linesize[2],
vFrameOne->data[1], vFrameOne->linesize[1],
pFrameRGBAOne->data[0], pFrameRGBAOne->linesize[0],
pCodecCtxOne->width, pCodecCtxOne->height);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
} catch (...) {
}
if (re == -1) {
} else {
ANativeWindow_unlockAndPost(nativeWindowOne);
}
}
}
}
} catch (...) {
printf("error");
}
if (vFrameOne != nullptr) {
av_frame_free(&vFrameOne);
vFrameOne = nullptr;
}
if (packetOne != nullptr) {
av_free(packetOne);
packetOne = nullptr;
}
if (pFrameRGBAOne != nullptr) {
av_free(pFrameRGBAOne);
pFrameRGBAOne = nullptr;
}
if (pCodecCtxOne != nullptr) {
avcodec_free_context(&pCodecCtxOne);
pCodecCtxOne = nullptr;
}
if (nativeWindowOne != nullptr) {
ANativeWindow_release(nativeWindowOne);
nativeWindowOne = nullptr;
}
pthread_exit(&threadVister);
}
你应该仔细阅读 avcodec_receive_frame
的 documentation:
Return decoded output data from a decoder.
Parameters
avctx codec context
frame This will be set to a reference-counted video or audio frame (depending on the decoder type) allocated by the decoder. Note that the function will always call av_frame_unref(frame) before doing anything else.
Returns
0: success, a frame was returned
AVERROR(EAGAIN): output is not available in this state - user must try to send new input
AVERROR_EOF: the decoder has been fully flushed, and there will be no more output frames
AVERROR(EINVAL): codec not opened, or it is an encoder other negative values: legitimate decoding errors
我强调了两个关键信息:
- 首先,对
avcodec_receive_frame
的调用将使 vFrameOne
无效。如果你的另一个线程正在解码,你的程序就会崩溃。您需要在接收线程和显示线程之间建立同步机制,以确保接收器始终接收到只有它有权访问的帧,并且它只将完整的帧传递给显示端。 (见下一点)
- 其次,您应该检查
avcodec_receive_frame
的 return 值。如果您看到 AVERROR(EAGAIN)
,则表示您没有收到足够的数据包来生成完整的帧。只有当这个函数产生0时,你才能把完整的帧交给显示线程。
我是JNI新手,为什么我的androidjni C++ try块没有捕获到异常,代码崩溃时应用程序崩溃没有跳转到异常处理 这是我的代码
Activity重新编码 在 JAVA 层接收带队列的 H264 数据 启动一个解码线程,不断从队列中取出一帧H264数据包进入C++层用FFmpeg解码
class decode extends Thread {
@Override
public void run() {
// super.run();
while (isDecode) {
byte[] data = one.poll();
if (data != null)
if (ffmpegUtilsInSignalOne != null)
ffmpegUtilsInSignalOne.decodeH264One(data);
}
}
}
cpp 文件代码
extern "C"
JNIEXPORT void JNICALL
Java_cn_zhihuiyun_control_utils_FFMPEGUtils_decodeH264One(JNIEnv *env, jobject thiz,
jbyteArray data) {
if (packetOne != nullptr && pCodecCtxOne != nullptr && vFrameOne != nullptr) {
if (data == nullptr)
return;;
if (isPlay == 0)
return;
jbyte *arr = env->GetByteArrayElements(data, JNI_FALSE);
packetOne->data = (uint8_t *) arr;
packetOne->size = env->GetArrayLength(data);
avcodec_send_packet(pCodecCtxOne, packetOne);
avcodec_receive_frame(pCodecCtxOne, vFrameOne);
av_packet_unref(packetOne);
env->ReleaseByteArrayElements(data, arr, 0);
}
}
此时在C层启动一个显示线程进行屏幕渲染
extern "C"
JNIEXPORT void JNICALL
Java_cn_zhihuiyun_control_utils_FFMPEGUtils_initVisThread(JNIEnv *env, jobject thiz) {
isPlay = 1;
threadVister = pthread_create(&threadVister, nullptr,
reinterpret_cast<void *(*)(void *)>(&showVideo),
(void *) env);
pthread_detach(threadVister);
}
void *showVideo(JNIEnv *env) {
try {
while (isPlay == 1) {
if (vFrameOne != nullptr && pFrameRGBAOne != nullptr && pCodecCtxOne != nullptr &&
nativeWindowOne != nullptr) {
ANativeWindow_lock(nativeWindowOne, &windowBufferOne, nullptr);
av_image_fill_arrays(pFrameRGBAOne->data, pFrameRGBAOne->linesize,
(const uint8_t *) windowBufferOne.bits, AV_PIX_FMT_RGBA,
detWidth, detHeight, 1);
int re = -1;
try {
re = libyuv::I420ToARGB(vFrameOne->data[0], vFrameOne->linesize[0],
vFrameOne->data[2], vFrameOne->linesize[2],
vFrameOne->data[1], vFrameOne->linesize[1],
pFrameRGBAOne->data[0], pFrameRGBAOne->linesize[0],
pCodecCtxOne->width, pCodecCtxOne->height);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
} catch (...) {
}
if (re == -1) {
} else {
ANativeWindow_unlockAndPost(nativeWindowOne);
}
}
}
}
} catch (...) {
printf("error");
}
if (vFrameOne != nullptr) {
av_frame_free(&vFrameOne);
vFrameOne = nullptr;
}
if (packetOne != nullptr) {
av_free(packetOne);
packetOne = nullptr;
}
if (pFrameRGBAOne != nullptr) {
av_free(pFrameRGBAOne);
pFrameRGBAOne = nullptr;
}
if (pCodecCtxOne != nullptr) {
avcodec_free_context(&pCodecCtxOne);
pCodecCtxOne = nullptr;
}
if (nativeWindowOne != nullptr) {
ANativeWindow_release(nativeWindowOne);
nativeWindowOne = nullptr;
}
pthread_exit(&threadVister);
}
你应该仔细阅读 avcodec_receive_frame
的 documentation:
Return decoded output data from a decoder.
Parameters
avctx codec context
frame This will be set to a reference-counted video or audio frame (depending on the decoder type) allocated by the decoder. Note that the function will always call av_frame_unref(frame) before doing anything else.Returns 0: success, a frame was returned
AVERROR(EAGAIN): output is not available in this state - user must try to send new input
AVERROR_EOF: the decoder has been fully flushed, and there will be no more output frames AVERROR(EINVAL): codec not opened, or it is an encoder other negative values: legitimate decoding errors
我强调了两个关键信息:
- 首先,对
avcodec_receive_frame
的调用将使vFrameOne
无效。如果你的另一个线程正在解码,你的程序就会崩溃。您需要在接收线程和显示线程之间建立同步机制,以确保接收器始终接收到只有它有权访问的帧,并且它只将完整的帧传递给显示端。 (见下一点) - 其次,您应该检查
avcodec_receive_frame
的 return 值。如果您看到AVERROR(EAGAIN)
,则表示您没有收到足够的数据包来生成完整的帧。只有当这个函数产生0时,你才能把完整的帧交给显示线程。