业务场景:jni用ffmpeg解压视频数据流,Android端用surfaceview显示视频,点击按钮进行截图。一般的Android截图方法对于surfaceview是不管用的,因此这里使用jni方法进行截图
逻辑思路:ffmpeg解压出来的数据流是一帧一帧的,截图只是把其中一帧的数据抽出来放到bitmap中就可以了。Android端创建bitmap文件并传入jni中,jni通过AndroidBitmap的操作ApI获取到bitmap的数据缓存地址,然后把frame帧数据拷贝到bitmap的数据缓存中,然后通知Android端数据已经写完,可以显示截屏图片了
关键代码:
//帧数据
vframe = (AVPicture*) data->pointer;
//调用java方法获取到bitmap的引用(在Android端创建的)
jobject bmp = needSaveBitmap(rtspThreadParam.jnienv);
if(NULL != bmp){
ga_log("new bitmap success");
uint8_t *srcData = NULL;
//锁定了像素缓存以确保像素的内存不会被移动,并返回像素缓存的一个原生指针
AndroidBitmap_lockPixels(rtspThreadParam.jnienv, bmp, (void**)&srcData);
AndroidBitmapInfo srcInfo;
//获取bitmap的信息(宽高等)
AndroidBitmap_getInfo(rtspThreadParam.jnienv, bmp, &srcInfo);
ga_log("srcinfo width=%d height=%d",srcInfo.width,srcInfo.height);
//数据拷贝(bitmap的宽高和帧数据的宽高应该是相等的)
for (int i = 0; i <(srcInfo.width*srcInfo.height*2) ; i++) {
srcData[i] = vframe->data[0][i];
}
//释放像素缓存的指针
AndroidBitmap_unlockPixels(rtspThreadParam.jnienv, bmp);
//调用java方法通知Android端截图已经生成
showScreenImage(rtspThreadParam.jnienv);
//释放
free(srcData);
}