|
@@ -178,6 +178,154 @@
|
|
|
}
|
|
|
|
|
|
|
|
|
+//+ (CMSampleBufferRef)cropSampleBufferBySoftware:(CMSampleBufferRef)sampleBuffer {
|
|
|
+// OSStatus status;
|
|
|
+//
|
|
|
+// // CVPixelBufferRef pixelBuffer = [self modifyImage:buffer];
|
|
|
+// CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
|
|
+// // Lock the image buffer
|
|
|
+// CVPixelBufferLockBaseAddress(imageBuffer,0);
|
|
|
+// // Get information about the image
|
|
|
+// uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
|
|
|
+// size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
|
|
|
+// size_t width = CVPixelBufferGetWidth(imageBuffer);
|
|
|
+// // size_t height = CVPixelBufferGetHeight(imageBuffer);
|
|
|
+// NSInteger bytesPerPixel = bytesPerRow/width;
|
|
|
+//
|
|
|
+// // YUV 420 Rule
|
|
|
+// if (_cropX % 2 != 0) _cropX += 1;
|
|
|
+// NSInteger baseAddressStart = _cropY*bytesPerRow+bytesPerPixel*_cropX;
|
|
|
+// static NSInteger lastAddressStart = 0;
|
|
|
+// lastAddressStart = baseAddressStart;
|
|
|
+//
|
|
|
+// // pixbuffer 与 videoInfo 只有位置变换或者切换分辨率或者相机重启时需要更新,其余情况不需要,Demo里只写了位置更新,其余情况自行添加
|
|
|
+// // NSLog(@"demon pix first : %zu - %zu - %@ - %d - %d - %d -%d",width, height, self.currentResolution,_cropX,_cropY,self.currentResolutionW,self.currentResolutionH);
|
|
|
+// static CVPixelBufferRef pixbuffer = NULL;
|
|
|
+// static CMVideoFormatDescriptionRef videoInfo = NULL;
|
|
|
+//
|
|
|
+// // x,y changed need to reset pixbuffer and videoinfo
|
|
|
+// if (lastAddressStart != baseAddressStart) {
|
|
|
+// if (pixbuffer != NULL) {
|
|
|
+// CVPixelBufferRelease(pixbuffer);
|
|
|
+// pixbuffer = NULL;
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (videoInfo != NULL) {
|
|
|
+// CFRelease(videoInfo);
|
|
|
+// videoInfo = NULL;
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (pixbuffer == NULL) {
|
|
|
+// NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
+// [NSNumber numberWithBool : YES], kCVPixelBufferCGImageCompatibilityKey,
|
|
|
+// [NSNumber numberWithBool : YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
|
|
|
+// [NSNumber numberWithInt : g_width_size], kCVPixelBufferWidthKey,
|
|
|
+// [NSNumber numberWithInt : g_height_size], kCVPixelBufferHeightKey,
|
|
|
+// nil];
|
|
|
+//
|
|
|
+// status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, g_width_size, g_height_size, kCVPixelFormatType_32BGRA, &baseAddress[baseAddressStart], bytesPerRow, NULL, NULL, (__bridge CFDictionaryRef)options, &pixbuffer);
|
|
|
+// if (status != 0) {
|
|
|
+// NSLog(@"Crop CVPixelBufferCreateWithBytes error %d",(int)status);
|
|
|
+// return NULL;
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// CVPixelBufferUnlockBaseAddress(imageBuffer,0);
|
|
|
+//
|
|
|
+// CMSampleTimingInfo sampleTime = {
|
|
|
+// .duration = CMSampleBufferGetDuration(sampleBuffer),
|
|
|
+// .presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer),
|
|
|
+// .decodeTimeStamp = CMSampleBufferGetDecodeTimeStamp(sampleBuffer)
|
|
|
+// };
|
|
|
+//
|
|
|
+// if (videoInfo == NULL) {
|
|
|
+// status = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixbuffer, &videoInfo);
|
|
|
+// if (status != 0) NSLog(@"Crop CMVideoFormatDescriptionCreateForImageBuffer error %d",(int)status);
|
|
|
+// }
|
|
|
+//
|
|
|
+// CMSampleBufferRef cropBuffer = NULL;
|
|
|
+// status = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixbuffer, true, NULL, NULL, videoInfo, &sampleTime, &cropBuffer);
|
|
|
+// if (status != 0) NSLog(@"Crop CMSampleBufferCreateForImageBuffer error %d",(int)status);
|
|
|
+//
|
|
|
+// lastAddressStart = baseAddressStart;
|
|
|
+//
|
|
|
+// return cropBuffer;
|
|
|
+//}
|
|
|
+//
|
|
|
+
|
|
|
+
|
|
|
+// hardware crop
|
|
|
++ (CMSampleBufferRef)cropSampleBufferByHardware:(CMSampleBufferRef)buffer
|
|
|
+ rect:(CGRect)rect{
|
|
|
+ // a CMSampleBuffer CVImageBuffer of media data.
|
|
|
+ CGFloat _cropX = rect.origin.x;
|
|
|
+ CGFloat _cropY = rect.origin.y;
|
|
|
+ CGFloat g_width_size = rect.size.width;
|
|
|
+ CGFloat g_height_size = rect.size.height;
|
|
|
+
|
|
|
+ CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(buffer);
|
|
|
+ CGRect cropRect = CGRectMake(_cropX, _cropY, g_width_size, g_height_size);
|
|
|
+ // log4cplus_debug("Crop", "dropRect x: %f - y : %f - width : %zu - height : %zu", cropViewX, cropViewY, width, height);
|
|
|
+
|
|
|
+ /*
|
|
|
+ First, to render to a texture, you need an image that is compatible with the OpenGL texture cache. Images that were created with the camera API are already compatible and you can immediately map them for inputs. Suppose you want to create an image to render on and later read out for some other processing though. You have to have create the image with a special property. The attributes for the image must have kCVPixelBufferIOSurfacePropertiesKey as one of the keys to the dictionary.
|
|
|
+ 如果要进行页面渲染,需要一个和OpenGL缓冲兼容的图像。用相机API创建的图像已经兼容,您可以马上映射他们进行输入。假设你从已有画面中截取一个新的画面,用作其他处理,你必须创建一种特殊的属性用来创建图像。对于图像的属性必须有kCVPixelBufferIOSurfacePropertiesKey 作为字典的Key.因此以下步骤不可省略
|
|
|
+ */
|
|
|
+
|
|
|
+ OSStatus status;
|
|
|
+
|
|
|
+ /* Only resolution has changed we need to reset pixBuffer and videoInfo so that reduce calculate count */
|
|
|
+ static CVPixelBufferRef pixbuffer = NULL;
|
|
|
+ static CMVideoFormatDescriptionRef videoInfo = NULL;
|
|
|
+
|
|
|
+ if (pixbuffer == NULL) {
|
|
|
+
|
|
|
+ NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
+ [NSNumber numberWithInt:g_width_size], kCVPixelBufferWidthKey,
|
|
|
+ [NSNumber numberWithInt:g_height_size], kCVPixelBufferHeightKey, nil];
|
|
|
+ status = CVPixelBufferCreate(kCFAllocatorSystemDefault, g_width_size, g_height_size, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, (__bridge CFDictionaryRef)options, &pixbuffer);
|
|
|
+ // ensures that the CVPixelBuffer is accessible in system memory. This should only be called if the base address is going to be used and the pixel data will be accessed by the CPU
|
|
|
+ if (status != noErr) {
|
|
|
+ NSLog(@"Crop CVPixelBufferCreate error %d",(int)status);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
|
|
|
+ ciImage = [ciImage imageByCroppingToRect:cropRect];
|
|
|
+ // Ciimage get real image is not in the original point after excute crop. So we need to pan.
|
|
|
+ ciImage = [ciImage imageByApplyingTransform:CGAffineTransformMakeTranslation(-_cropX, -_cropY)];
|
|
|
+
|
|
|
+ static CIContext *ciContext = nil;
|
|
|
+ if (ciContext == nil) {
|
|
|
+ // NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
|
|
|
+ // [options setObject:[NSNull null] forKey:kCIContextWorkingColorSpace];
|
|
|
+ // [options setObject:@0 forKey:kCIContextUseSoftwareRenderer];
|
|
|
+ EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
|
|
+ ciContext = [CIContext contextWithEAGLContext:eaglContext options:nil];
|
|
|
+ }
|
|
|
+ [ciContext render:ciImage toCVPixelBuffer:pixbuffer];
|
|
|
+ // [ciContext render:ciImage toCVPixelBuffer:pixbuffer bounds:cropRect colorSpace:nil];
|
|
|
+
|
|
|
+ CMSampleTimingInfo sampleTime = {
|
|
|
+ .duration = CMSampleBufferGetDuration(buffer),
|
|
|
+ .presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(buffer),
|
|
|
+ .decodeTimeStamp = CMSampleBufferGetDecodeTimeStamp(buffer)
|
|
|
+ };
|
|
|
+
|
|
|
+ if (videoInfo == NULL) {
|
|
|
+ status = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixbuffer, &videoInfo);
|
|
|
+ if (status != 0) NSLog(@"Crop CMVideoFormatDescriptionCreateForImageBuffer error %d",(int)status);
|
|
|
+ }
|
|
|
+
|
|
|
+ CMSampleBufferRef cropBuffer;
|
|
|
+ status = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixbuffer, true, NULL, NULL, videoInfo, &sampleTime, &cropBuffer);
|
|
|
+ if (status != 0) NSLog(@"Crop CMSampleBufferCreateForImageBuffer error %d",(int)status);
|
|
|
+ return cropBuffer;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ (CMSampleBufferRef *)GPUImageCreateResizedSampleBuffer:(CVPixelBufferRef) cameraFrame finalSize:(CGSize)finalSize
|
|
|
{
|
|
|
// CVPixelBufferCreateWithPlanarBytes for YUV input
|