業(yè)務(wù)場景:jni用ffmpeg解壓視頻數(shù)據(jù)流蝶缀,Android端用surfaceview顯示視頻,點擊按鈕進(jìn)行截圖吱雏。一般的Android截圖方法對于surfaceview是不管用的访诱,因此這里使用jni方法進(jìn)行截圖
邏輯思路:ffmpeg解壓出來的數(shù)據(jù)流是一幀一幀的赊琳,截圖只是把其中一幀的數(shù)據(jù)抽出來放到bitmap中就可以了。Android端創(chuàng)建bitmap文件并傳入jni中焊切,jni通過AndroidBitmap的操作ApI獲取到bitmap的數(shù)據(jù)緩存地址扮授,然后把frame幀數(shù)據(jù)拷貝到bitmap的數(shù)據(jù)緩存中,然后通知Android端數(shù)據(jù)已經(jīng)寫完专肪,可以顯示截屏圖片了
關(guān)鍵代碼:
//幀數(shù)據(jù)
vframe = (AVPicture*) data->pointer;
//調(diào)用java方法獲取到bitmap的引用(在Android端創(chuàng)建的)
jobject bmp = needSaveBitmap(rtspThreadParam.jnienv);
if(NULL != bmp){
ga_log("new bitmap success");
uint8_t *srcData = NULL;
//鎖定了像素緩存以確保像素的內(nèi)存不會被移動,并返回像素緩存的一個原生指針
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);
//數(shù)據(jù)拷貝(bitmap的寬高和幀數(shù)據(jù)的寬高應(yīng)該是相等的)
for (int i = 0; i <(srcInfo.width*srcInfo.height*2) ; i++) {
srcData[i] = vframe->data[0][i];
}
//釋放像素緩存的指針
AndroidBitmap_unlockPixels(rtspThreadParam.jnienv, bmp);
//調(diào)用java方法通知Android端截圖已經(jīng)生成
showScreenImage(rtspThreadParam.jnienv);
//釋放
free(srcData);
}