您的当前位置:首页正文

《AVFoundation》官方文档08--时间和媒体表示

来源:华佗小知识

基于时间的视听数据,例如电影文件或视频流,在AV Foundation框架中被表示AVAsset。其结构决定了大部分的框架作品。AV Foundation用来表示时间和媒体的几个低级数据结构,如样本缓冲区来自Core Media框架。

Asset表示

图6-1 AVAsset提供了基于时间的视听数据的抽象 图6-2 AVAssetTrack

时间的表示

AVFoundation的时间由Core Media框架的原始结构表示。

CMTime表示时间长度

除了简单的时间值之外,CMTime结构可以表示非数值值:+无穷大,-infinity和无限期。它也可以指示时间是否在某点被舍入,并且它保持一个时代数字。

使用CMTime
CMTime time1 = CMTimeMake(200, 2); // 200 half-seconds
CMTime time2 = CMTimeMake(400, 4); // 400 quarter-seconds

// time1 and time2 both represent 100 seconds, but using different timescales.
if (CMTimeCompare(time1, time2) == 0) {
NSLog(@"time1 and time2 are the same");
}

Float64 float64Seconds = 200.0 / 3;
CMTime time3 = CMTimeMakeWithSeconds(float64Seconds , 3); // 66.66... third-seconds
time3 = CMTimeMultiply(time3, 3);
// time3 now represents 200 seconds; next subtract time1 (100 seconds).
time3 = CMTimeSubtract(time3, time1);
CMTimeShow(time3);

if (CMTIME_COMPARE_INLINE(time2, ==, time3)) {
NSLog(@"time2 and time3 are the same");
}
CMTime的特殊价值
CMTime myTime = <#Get a CMTime#>;
if (CMTIME_IS_INVALID(myTime)) {
// Perhaps treat this as an error; display a suitable alert to the user.
}

你不应该比较任意CMTime结构的值kCMTimeInvalid。

将CMTime表示为对象
Epochs

CMTime结构的时代号通常设置为0,但您可以使用它来区分不相关的时间轴。例如,可以使用呈现循环在每个循环中递增历元,以区分N循环0中的时间N和循环1中的时间。

CMTimeRange表示时间范围

  • CMTimeRange 结构不能跨越不同的时代。
  • CMTime表示时间戳的结构中的时期可能不为零,但您只能对起始字段具有相同历元的范围执行范围操作(例如)。
  • CMTime表示持续时间的结构中的时期应始终为0,该值必须为非负数。
使用时间范围

鉴于时间范围不包括开始时间加上持续时间的时间,以下表达式总是计算为false:

CMTimeRangeContainsTime(range,CMTimeRangeGetEnd(range))

CMTimeRange的特殊值

CMTimeRange myTimeRange = <#Get a CMTimeRange#>;
if (CMTIMERANGE_IS_EMPTY(myTimeRange)) {
// The time range is zero.
}

你不应该比较任意CMTimeRange结构的值kCMTimeRangeInvalid。

将CMTimeRange结构表示为对象

媒体表示

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(<#A CMSampleBuffer#>);

除了视频数据外,您还可以检索视频帧的其他方面:

  •   CMSampleBufferRef sampleBuffer = <#获取一个样本缓冲区#>;
    
    CFDictionaryRef metadataDictionary =
    
    CMGetAttachment(sampleBuffer,CFSTR(“MetadataDictionary”,NULL);
    
    if(metadataDictionary){
    
    //用元数据做某事
    
    }
    

将CMSampleBuffer转换为UIImage对象

以下代码显示了如何将a转换CMSampleBuffer为UIImage对象。使用前请仔细考虑您的要求。执行转换是相对昂贵的操作。例如,从每秒钟拍摄的视频数据帧中创建静止图像是适当的。您不应该使用它来实时地操纵来自捕获设备的每一帧视频。

// Create a UIImage from sample buffer data
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer

{
// Get a CMSampleBuffer's Core Video image buffer for the media data
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// Lock the base address of the pixel buffer
CVPixelBufferLockBaseAddress(imageBuffer, 0);

// Get the number of bytes per row for the pixel buffer
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);

// Get the number of bytes per row for the pixel buffer
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
// Get the pixel buffer width and height
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);

// Create a device-dependent RGB color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// Create a bitmap graphics context with the sample buffer data
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
  bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// Create a Quartz image from the pixel data in the bitmap graphics context
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);

// Free up the context and color space
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

// Create an image object from the Quartz image
UIImage *image = [UIImage imageWithCGImage:quartzImage];

// Release the Quartz image
CGImageRelease(quartzImage);

return (image);
}