我有一个基于文档的应用程序,其中每个文档都有一个带有NSScrollView的窗口,它只使用Cocoa进行一些(相当连续的)绘图.
要调用绘图,我使用的是CVDisplayLink,如下面的代码所示:
- (void)windowControllerDidLoadNib:(NSWindowController *) aController {
//other stuff...
[self prepareDisplayLink]; //For some reason putting this in awakeFromNib crashes
}
//Prep the display link.
- (void)prepareDisplayLink {
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetCurrentCGDisplay(displayLink, ((CGDirectDisplayID)[[[[[self windowForSheet]screen]deviceDescription]objectForKey:@"NSScreenNumber"]intValue]));
CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
}
//Callback to draw frame
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc]init];
CVReturn result = [(ScrollView*)displayLinkContext getFrameForTime:outputTime];
[pool drain];
return result;
}
//Drawing function:
- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
{
[scrollView lockFocusIfCanDraw];
[self addToCurrentPostion:(dist/time)*CVDisplayLinkGetActualOutputVideoRefreshPeriod(displayLink)]; …Run Code Online (Sandbox Code Playgroud) 使用AVFoundation框架工作捕获视频.借助Apple文档http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/03_MediaCapture.html%23//apple_ref/doc/ UID/TP40010188-CH5-SW2
现在我做了以下事情
1.Created videoCaptureDevice
2.Created AVCaptureDeviceInput并设置videoCaptureDevice
3.Created AVCaptureVideoDataOutput和实现代表
4.Created AVCaptureSession-设定输入作为AVCaptureDeviceInput并设置输出作为AVCaptureVideoDataOutput
5.在AVCaptureVideoDataOutput委托方法中
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
Run Code Online (Sandbox Code Playgroud)
我有CMSamplebuffer并转换成UIImage并测试使用打印UIImageview
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
Run Code Online (Sandbox Code Playgroud)
每件事情都很顺利........
我的问题是,我需要通过UDP套接字发送视频帧.尽管下面的一个是我试过的坏主意,UIImage到NSData和通过UDP Pocket发送.BUt得到了如此延迟的视频处理.由于UIImage NSDate导致了很多问题
所以请给我解决方案我的问题
1)任何方法将CMSampleBUffer或CVImageBuffer转换为NSData ??
2)像音频队列服务和视频队列存储UIImage和UIImage到NSDate和发送???
如果我骑在错误的算法背后请在写方向路径我
提前致谢
我正在创建一个MTLTexture来自CVImageBuffers(来自相机和玩家)使用CVMetalTextureCacheCreateTextureFromImage来获得a CVMetalTexture然后CVMetalTextureGetTexture获得MTLTexture.
我看到的问题是,当我稍后使用Metal渲染纹理时,我偶尔会看到无序渲染的视频帧(视觉上它在时间上来回断断续续),可能是因为CoreVideo正在修改底层CVImageBuffer存储而且MTLTexture只是指向那里.
有没有办法让CoreVideo不触及该缓冲区并使用其池中的另一个缓冲区直到我释放该MTLTexture对象?
我当前的解决方法是使用a MTLBlitCommandEncoder来对纹理进行blitting,但是因为我只需要保持纹理约30毫秒,这似乎是不必要的.
我想将a转换CGImage为CMSampleBufferRef并AVAssetWriterInput使用该appendSampleBuffer:方法将其附加到a .我已经设法CMSampleBufferRef使用以下代码,但appendSampleBuffer:只是NO在我提供结果时返回CMSampleBufferRef.我究竟做错了什么?
- (void) appendCGImage: (CGImageRef) frame
{
const int width = CGImageGetWidth(frame);
const int height = CGImageGetHeight(frame);
// Create a dummy pixel buffer to try the encoding
// on something simple.
CVPixelBufferRef pixelBuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width, height,
kCVPixelFormatType_32BGRA, NULL, &pixelBuffer);
NSParameterAssert(status == kCVReturnSuccess && pixelBuffer != NULL);
// Sample timing info.
CMTime frameTime = CMTimeMake(1, 30);
CMTime currentTime = …Run Code Online (Sandbox Code Playgroud) 我在iOS中访问相机并使用会话预设,如下所示:
captureSession.sessionPreset = AVCaptureSessionPresetMedium;
Run Code Online (Sandbox Code Playgroud)
很标准的东西.但是,我想提前知道由于这个预设而我将获得的视频分辨率(特别是因为取决于设备它会有所不同).我知道有在线表格可以查看(例如:http://cmgresearch.blogspot.com/2010/10/augmented-reality-on-iphone-with-ios40.html).但是我希望能够以编程方式获得这个,这样我才不仅仅依赖于魔术数字.
所以,这样的事情(理论上):
[captureSession resolutionForPreset:AVCaptureSessionPresetMedium];
Run Code Online (Sandbox Code Playgroud)
可能会返回{宽度:360,高度:480}的CGSize.我还没有找到任何这样的API,到目前为止,我不得不求助于等待获取我的第一个捕获的图像然后查询它(由于我的程序流中的其他原因并不好).
我正在寻找一种使用iOS API检索视频的各个帧的方法.我尝试使用AVAssetImageGenerator,但它似乎只提供最接近的秒的帧,这对我的使用来说有点太粗糙了.
根据我对文档的理解,AVAssetReader,AVAssetReaderOutput和CMSampleBufferGetImageBuffer的管道我应该可以做一些事情,但我坚持使用CVImageBufferRef.有了这个,我正在寻找一种方法来获得CGImageRef或UIImage,但还没有找到它.
不需要实时,我越能坚持提供API越多越好.
非常感谢!
编辑:基于这个网站:http://www.7twenty7.com/blog/2010/11/video-processing-with-av-foundation和这个问题:如何将CVImageBufferRef转换为UIImage我即将解决方案.问题,AVAssetReader在第一次之后停止读取copyNextSampleBuffer而没有给我任何东西(sampleBuffer为NULL).
该视频可由MPMoviePlayerController读取.我不明白什么是错的.
我确定我的缓冲区属性出了问题,但是我不清楚它是什么 - 它没有很好地记录应该去那里的东西,所以我猜是基于CVPixelBufferPoolCreate- 而Core Foundation对我来说几乎是一本封闭的书.
// "width" and "height" are const ints
CFNumberRef cfWidth = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &width);
CFNumberRef cfHeight = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &height);
CFStringRef keys[] = {
kCVPixelBufferWidthKey,
kCVPixelBufferHeightKey,
kCVPixelBufferCGImageCompatibilityKey
};
CFTypeRef values[] = {
cfWidth,
cfHeight,
kCFBooleanTrue
};
int numValues = sizeof(keys) / sizeof(keys[0]);
CFDictionaryRef bufferAttributes = CFDictionaryCreate(kCFAllocatorDefault,
(const void **)&keys,
(const void **)&values,
numValues,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
);
AVAssetWriterInputPixelBufferAdaptor *adaptor = [[AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:(NSDictionary*)bufferAttributes] retain];
CVPixelBufferPoolRef bufferPool = adaptor.pixelBufferPool;
NSParameterAssert(bufferPool != NULL); // fails
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用a将视频旋转到正确的方向AVAssetExportSession,我总是会收到以下错误:
Error Domain=AVFoundationErrorDomain Code=-11841 "The operation couldn’t be completed. (AVFoundationErrorDomain error -11841.)"
Run Code Online (Sandbox Code Playgroud)
这转化为AVErrorInvalidVideoComposition但我看不出我的视频构图有什么问题.这是代码:
AVAssetTrack *sourceVideo = [[avAsset tracksWithMediaType:AVMediaTypeVideo] lastObject];
AVAssetTrack *sourceAudio = [[avAsset tracksWithMediaType:AVMediaTypeAudio] lastObject];
CGAffineTransform preferredTransform = [sourceVideo preferredTransform];
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetExportSession *exporter = [[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality] autorelease];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration)
ofTrack:sourceVideo
atTime:kCMTimeZero
error:nil];
if( !CGAffineTransformIsIdentity(preferredTransform) ) {
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.renderSize = CGSizeMake([avAsset naturalSize].height, [avAsset naturalSize].width);
videoComposition.frameDuration = CMTimeMake(1, compositionVideoTrack.naturalTimeScale);
AVMutableVideoCompositionLayerInstruction …Run Code Online (Sandbox Code Playgroud) 我有一个项目,我需要从实时网络流解码h264视频,最终得到一个纹理,我可以在iOS设备上的另一个框架(Unity3D)中显示.我可以使用VTDecompressionSession成功解码视频,然后使用CVMetalTextureCacheCreateTextureFromImage(或OpenGL变体)获取纹理.当我使用低延迟编码器并且图像缓冲器按显示顺序出现时,它工作得很好,但是,当我使用常规编码器时,图像缓冲区不按显示顺序出现,重新排序图像缓冲区显然要困难得多.我期望.
第一次尝试是使用kVTDecodeFrame_EnableAsynchronousDecompression和kVTDecodeFrame_EnableTemporalProcessing设置VTDecodeFrameFlags ...然而,事实证明VTDecompressionSession可以选择忽略该标志并做任何它想要的......在我的情况下,它选择忽略该标志并仍然输出编码器顺序的缓冲区(不是显示顺序).基本上没用.
下一次尝试是将图像缓冲区与显示时间戳相关联,然后将它们放入一个向量中,这样我就可以在创建纹理时抓取所需的图像缓冲区.问题似乎是进入与时间戳相关联的VTDecompressionSession的图像缓冲区不再是出现的相同缓冲区,从而使时间戳无效.
例如,进入解码器......
VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;
VTDecodeInfoFlags flagOut;
// Presentation time stamp to be passed with the buffer
NSNumber *nsPts = [NSNumber numberWithDouble:pts];
VTDecompressionSessionDecodeFrame(_decompressionSession, sampleBuffer, flags,
(void*)CFBridgingRetain(nsPts), &flagOut);
Run Code Online (Sandbox Code Playgroud)
在回调方......
void decompressionSessionDecodeFrameCallback(void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration)
{
// The presentation time stamp...
// No longer seems to be associated with the buffer that it went in with!
NSNumber* pts = CFBridgingRelease(sourceFrameRefCon);
}
Run Code Online (Sandbox Code Playgroud)
订购时,回调端的时间戳按预期速率单调增加,但缓冲区的顺序不正确.有没有人在这里看到我在哪里犯错误?或者知道如何确定回调端缓冲区的顺序?在这一点上,我已经尝试了我能想到的一切.
core-video ×10
ios ×7
avfoundation ×4
iphone ×2
video ×2
cocoa ×1
core-media ×1
frame ×1
ios4 ×1
ipad ×1
metal ×1
nsview ×1
screen ×1
swift ×1