在處理視頻的時(shí)候,有個(gè)畫中畫的需求抗果,需要展示視頻的一張靜態(tài)圖,作為占位;所以選擇把AVFrame轉(zhuǎn)成UIImage供后面需要調(diào)用的地方使用葵擎,當(dāng)然如果截屏的操作也可以這么做;但是后面在使用UIImage過程中會遇到一個(gè)問題码撰,如下所示谭期;
分析原因大概就是要訪問的這片內(nèi)存空間不可被讀取,結(jié)合之前使用UIImage做視頻渲染所遇到的問題:
即AVFrame->UIImage->render->release;
也是遇到同樣的問題兆旬,報(bào)錯(cuò)定位在Release假抄;
CGColorSpaceRelease(colorSpace);
現(xiàn)在的步驟是:
即AVFrame->UIImage->saveCache->release->waitRender;
所以分析原因還是圖片在使用之前時(shí)候已經(jīng)被釋放掉了,所以此時(shí)考慮對圖片做一次深拷貝丽猬,保證圖片顏色內(nèi)存空間跟數(shù)據(jù)緩存區(qū)不被釋放宿饱;
處理方法是,對圖片進(jìn)行縮放(因?yàn)檎嘉恍D不需要那么大的size)脚祟,再對圖片信息進(jìn)行壓縮谬以,最后再轉(zhuǎn)成image緩存起來;
result = [UIImage imageWithCGImage:cgImage];
UIImage *uimage = (UIImage *)result;
CGFloat zoomWidth = kScreenWidth/3 * 2;
// 轉(zhuǎn)一下由桌,才能保證后續(xù)在使用的時(shí)候不報(bào)錯(cuò)为黎,縮小尺寸,減少內(nèi)存占用
uimage = [uimage transformWidth:zoomWidth Height:zoomWidth*kPreviewImageScale];
NSData *imageData = UIImageJPEGRepresentation(uimage, 0.5);
result = [UIImage imageWithData:imageData];
完整的AVFrame轉(zhuǎn)UIImage的代碼
// type:0沥寥、獲取識別到的人臉數(shù)組 1碍舍、獲取轉(zhuǎn)碼的image
- (id)getFaceResultData:(const AVFrame *)frame type:(int)type {
int width = frame->width;
int height = frame->height;
enum AVPixelFormat format = AV_PIX_FMT_RGB24;// (enum AVPixelFormat)srcFrame->format;
AVFrame *picture = av_frame_alloc();
picture->width = width;
picture->height = height;
int ret = av_image_alloc(
picture->data,
picture->linesize,
picture->width,
picture->height,
format, 1);
SwsContext *sws_ctx = NULL;
sws_ctx = sws_getContext(width, height, (enum AVPixelFormat)frame->format,
width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
ret = sws_scale(sws_ctx, // 轉(zhuǎn)換格式上下文
frame->data, // 輸入圖像每個(gè)顏色AV_PIX_FMT_YUV420通道數(shù)據(jù)的指針
frame->linesize, // 輸入圖像每個(gè)顏色通道的跨度
0, // 處理的開始位置(這里從圖像開頭處理)
frame->height, // 處理的范圍(這里處理的范圍是整個(gè)圖像)
picture->data, // 輸出圖像數(shù)據(jù)位置
picture->linesize); // 輸出圖像每個(gè)顏色通道的跨度
CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, picture->data[0], picture->linesize[0]*height,kCFAllocatorNull);
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef cgImage = CGImageCreate(width,
height,
8,
24,
picture->linesize[0],
colorSpace,
bitmapInfo,
provider,
NULL,
NO,
kCGRenderingIntentDefault);
CIImage *image = [CIImage imageWithCGImage:cgImage];
id result = nil;
if (type == 1) {
result = [UIImage imageWithCGImage:cgImage];
UIImage *uimage = (UIImage *)result;
CGFloat zoomWidth = kScreenWidth/3 * 2;
// 轉(zhuǎn)一下,才能保證后續(xù)在使用的時(shí)候不報(bào)錯(cuò)邑雅,縮小尺寸片橡,減少內(nèi)存占用
uimage = [uimage transformWidth:zoomWidth Height:zoomWidth*kPreviewImageScale];
NSData *imageData = UIImageJPEGRepresentation(uimage, 0.5);
result = [UIImage imageWithData:imageData];
} else {
// CIDetector 屏幕左下角是坐標(biāo)原點(diǎn),需要進(jìn)行坐標(biāo)系轉(zhuǎn)換
#warning TODO 識別度不高淮野,需要坐標(biāo)系轉(zhuǎn)換
result = [self.detector featuresInImage:image];
}
#warning TODO frame #0: 0x00000001ab5175fc CoreGraphics`ERROR_CGDataProvider_BufferIsNotReadable
CGColorSpaceRelease(colorSpace);
CGImageRelease(cgImage);
CGDataProviderRelease(provider);
CFRelease(data);
sws_freeContext(sws_ctx);
if(picture){
av_freep(&picture->data[0]);
av_frame_free(&picture);
}
return result;
}
以上捧书,就是我在處理AVFrame轉(zhuǎn)UIImage時(shí)遇到的問題的一些解決思路吹泡,如有不妥或者更好的方式,歡迎留言探討指正经瓷!