Time and Media Representations - 時間和媒體表現
Time-based audiovisual data, such as a movie file or a video stream, is represented in the AV Foundation framework by AVAsset. Its structure dictates much of the framework works. Several low-level data structures that AV Foundation uses to represent time and media such as sample buffers come from the Core Media framework.
基于視聽資料的時間,比如一個電影文件或視頻流,在AV Foundation
框架中是由 AVAsset
代表的。它的結構決定了大部分的框架工程。一些低層的數據結構(AV Foundation
使用來表示時間和媒體,比如樣本緩沖區)來自 Core Media framework
。
Representation of Assets - 資產的表示
AVAsset is the core class in the AV Foundation framework. It provides a format-independent abstraction of time-based audiovisual data, such as a movie file or a video stream. The primary relationships are shown in Figure 6-1. In many cases, you work with one of its subclasses: You use the composition subclasses when you create new assets (see Editing), and you use AVURLAsset to create a new asset instance from media at a given URL (including assets from the MPMedia framework or the Asset Library framework—see Using Assets).
AVAsset 是 AV Foundation
框架的核心類。它提供了一個格式 – 與基于時間的視聽數據的抽象無關,比如電影文件或視頻流。主要的關系如圖 6-1所示。在很多情況下,你都與它的一個子類一起工作:當你創建新的資產(見 Editing)使用組件的子類,并使用 AVURLAsset 從給定 URL
的媒體來創建一個新的資產實例。(包括來自 MPMedia
框架或者 Asset Library framework
的資產,見Using Assets)
<center style="box-sizing: border-box; color: rgb(63, 63, 63); font-family: "microsoft yahei"; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);">
</center>
An asset contains a collection of tracks that are intended to be presented or processed together, each of a uniform media type, including (but not limited to) audio, video, text, closed captions, and subtitles. The asset object provides information about whole resource, such as its duration or title, as well as hints for presentation, such as its natural size. Assets may also have metadata, represented by instances of AVMetadataItem.
資產包含了一組軌道,旨在被一起呈現或一起處理,每一個統一的媒體類型,包括(但不僅限于)音頻、視頻、文本、隱藏式字幕,以及字幕。資產對象提供關于整個資源的信息,比如它的持續時間或標題,以及用于呈現提示的信息,例如它的自然尺寸。資產也有可能擁有元數據,通過 AVMetadataItem 的實例表示。
A track is represented by an instance of AVAssetTrack, as shown in Figure 6-2. In a typical simple case, one track represents the audio component and another represents the video component; in a complex composition, there may be multiple overlapping tracks of audio and video.
軌道由 AVAssetTrack 的實例表示,如圖 6-2所示。在一個典型簡單的情況下,一個軌道代表代表音頻組件,另一個代表視頻組件;在復雜的組成中,可以存在音頻和視頻的多個重疊的軌道。
<center style="box-sizing: border-box; color: rgb(63, 63, 63); font-family: "microsoft yahei"; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);">
</center>
A track has a number of properties, such as its type (video or audio), visual and/or audible characteristics (as appropriate), metadata, and timeline (expressed in terms of its parent asset). A track also has an array of format descriptions. The array contains CMFormatDescription objects (see CMFormatDescriptionRef), each of which describes the format of media samples referenced by the track. A track that contains uniform media (for example, all encoded using to the same settings) will provide an array with a count of 1.
軌道有許多屬性,比如它的類型(視頻或者音頻),視覺和/或聽覺特性(根據需要),元數據和時間軸(在其父資產表示)。一個軌道也有格式描述的數組。數組包含 CMFormatDescription
對象(見 CMFormatDescriptionRef),其中每一個都描述了軌道引用的媒體樣本的格式。包含了統一媒體的軌道(例如,所有使用相同設置的編碼)將提供計數為 1
的數組。
A track may itself be divided into segments, represented by instances of AVAssetTrackSegment. A segment is a time mapping from the source to the asset track timeline.
軌道自身可以被分成幾段,由 AVAssetTrackSegment 的實例表示。一個片段是一個時間映射,從資源到資產軌道時間軸的映射。
Representations of Time - 時間的表示
Time in AV Foundation is represented by primitive structures from the Core Media framework.
AV Foundation
中的時間是由來自 Core Media framework
的原始結構體表示的。
CMTime Represents a Length of Time - CMTime
表示時間的長度
CMTime is a C structure that represents time as a rational number, with a numerator (an int64_t value), and a denominator (an int32_t timescale). Conceptually, the timescale specifies the fraction of a second each unit in the numerator occupies. Thus if the timescale is 4, each unit represents a quarter of a second; if the timescale is 10, each unit represents a tenth of a second, and so on. You frequently use a timescale of 600, because this is a multiple of several commonly used frame rates: 24 fps for film, 30 fps for NTSC (used for TV in North America and Japan), and 25 fps for PAL (used for TV in Europe). Using a timescale of 600, you can exactly represent any number of frames in these systems.
CMTime 是一個C語言的結構體,以一個有理數表示時間,有一個分子(一個 int64_t
值)和一個分母(一個 int32_t
時間刻度)。在概念上講,時間刻度指定一秒中每個單元占據的分數。因此如果時間刻度為 4
,每個單元代表一秒的四分之一;如果時間刻度為 10
,每個單元代表一秒的十分之一,等等。經常使用時間刻度為 600
,因為這是因為這是幾種常用幀速率的倍數:24 fps
的電影, 30 fps
的NTSC
(用在北美洲和日本的電視),25 fps
的 PAL
(用于歐洲電視)。使用 600
的時間刻度,可以在這些系統中精確的表示任意數量的幀。
In addition to a simple time value, a CMTime structure can represent nonnumeric values: +infinity, -infinity, and indefinite. It can also indicate whether the time been rounded at some point, and it maintains an epoch number.
除了簡單的時間值,CMTime
結構體可以表示非數字的值:正無窮大、負無窮大,不確定的。它也可以表示時間在哪一位約等于,并且它能保持一個紀元數字。
Using CMTime - 使用 CMTime
You create a time using CMTimeMake or one of the related functions such as CMTimeMakeWithSeconds (which allows you to create a time using a float value and specify a preferred timescale). There are several functions for time-based arithmetic and for comparing times, as illustrated in the following example:
使用 CMTimeMake 或一個相關功能的 來創建一個時間,例如 CMTimeMakeWithSeconds (它允許你使用浮點值來創建一個時間,并指定一個首選時間刻度)。有基于時間算術的和比較時間的幾個功能,如下面的示例所示:
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");
}
For a list of all the available functions, see CMTime Reference.
有關所有可用的功能列表,請參閱 CMTime Reference
Special Values of CMTime - CMTime
的特殊值
Core Media provides constants for special values: kCMTimeZero, kCMTimeInvalid, kCMTimePositiveInfinity, and kCMTimeNegativeInfinity. There are many ways in which a CMTime structure can, for example, represent a time that is invalid. To test whether a CMTime is valid, or a nonnumeric value, you should use an appropriate macro, such as CMTIME_IS_INVALID, CMTIME_IS_POSITIVE_INFINITY, or CMTIME_IS_INDEFINITE.
Core Media
提供了特殊值的常量:kCMTimeZero,kCMTimeInvalid,kCMTimePositiveInfinity,以及 kCMTimeNegativeInfinity。有許多方法,例如,其中 CMTime
結構體可以表示一個無效的時間。為了測試CMTime
是否是無效的,或者是一個非數字值,應該使用一個適當的宏,比如 CMTIME_IS_INVALID,CMTIME_IS_POSITIVE_INFINITY,或者 CMTIME_IS_INDEFINITE
CMTime myTime = <#Get a CMTime#>;
if (CMTIME_IS_INVALID(myTime)) {
// Perhaps treat this as an error; display a suitable alert to the user.
}
You should not compare the value of an arbitrary CMTime structure with kCMTimeInvalid.
你不應該將一個任意的 CMTime
結構體的值與 kCMTimeInvalid
比較。
Representing CMTime as an Object - CMTime
表示為一個對象
If you need to use CMTime structures in annotations or Core Foundation containers, you can convert a CMTime structure to and from a CFDictionary opaque type (see CFDictionaryRef) using the CMTimeCopyAsDictionary and CMTimeMakeFromDictionary functions, respectively. You can also get a string representation of a CMTime structure using the CMTimeCopyDescription function.
如果你需要在注釋或者 Core Foundation
容器中使用 CMTime
結構體,可以使用 CMTimeCopyAsDictionary 將 CMTime
結構體轉換,使用 CMTimeMakeFromDictionary 從一個 CFDictionary
不透明的類型(見 CFDictionaryRef)。使用 CMTimeCopyDescription 函數可以得到一個 CMTime
結構體的字符串表示。
Epochs - 紀元
The epoch number of a CMTime structure is usually set to 0, but you can use it to distinguish unrelated timelines. For example, the epoch could be incremented through each cycle using a presentation loop, to differentiate between time N in loop 0 and time N in loop 1.
CMTime
結構體的紀元數量通常設置為 0
,但是你可以用它來區分不相關的時間軸。例如,紀元可以通過使用演示循環每個周期遞增,區分循環0
中的時間 N
與循環1
中的時間 N
。
CMTimeRange Represents a Time Range - CMTimeRange
表示一個時間范圍
CMTimeRange is a C structure that has a start time and duration, both expressed as CMTime structures. A time range does not include the time that is the start time plus the duration.
You create a time range using CMTimeRangeMake or CMTimeRangeFromTimeToTime. There are constraints on the value of the CMTime epochs:
- CMTimeRange structures cannot span different epochs.
- The epoch in a CMTime structure that represents a timestamp may be nonzero, but you can only - perform range operations (such as CMTimeRangeGetUnion) on ranges whose start fields have the - same epoch.
- The epoch in a CMTime structure that represents a duration should always be 0, and the value must be nonnegative.
CMTimeRange 是一個 C語言結構體,有開始時間和持續時間,即表示為 CMTime
結構體。時間范圍不包括開始時間加上持續時間。
使用 CMTimeRangeMake 或者 CMTimeRangeFromTimeToTime 創建一個時間范圍。有關 CMTime
紀元的值,有一些約束:
-
CMTimeRange
結構體不能跨越不同的紀元。 -
CMTime
結構體中的紀元,表示一個時間戳可能是非零,但你只能在其開始字段具有相同紀元的范圍內執行范圍操作(比如 CMTimeRangeGetUnion)。 - 在
CMTime
結構體中的紀元,表示持續時間應該總是為0
,并且值必須是非負數。
Working with Time Ranges - 與時間范圍工作
Core Media provides functions you can use to determine whether a time range contains a given time or other time range, to determine whether two time ranges are equal, and to calculate unions and intersections of time ranges, such as CMTimeRangeContainsTime, CMTimeRangeEqual, CMTimeRangeContainsTimeRange, and CMTimeRangeGetUnion.
Core Media
提供了一些功能,可用于確定一個時間范圍是否包含一個特定的時間或其他時間范圍,確定兩個時間范圍是否相等,并計算時間范圍的接口和相交范圍,比如 CMTimeRangeContainsTime,CMTimeRangeEqual,CMTimeRangeContainsTimeRange,以及 CMTimeRangeGetUnion。
Given that a time range does not include the time that is the start time plus the duration, the following expression always evaluates to false:
由于時間范圍不包括開始時間加上持續時間,下面的表達式的結果總是為 false
:
CMTimeRangeContainsTime(range, CMTimeRangeGetEnd(range))
For a list of all the available functions, see CMTimeRange Reference.
有關所有可用功能的列表,請參閱 CMTimeRange Reference。
Special Values of CMTimeRange - CMTimeRange
的特殊值
Core Media provides constants for a zero-length range and an invalid range, kCMTimeRangeZero and kCMTimeRangeInvalid, respectively. There are many ways, though in which a CMTimeRange structure can be invalid, or zero—or indefinite (if one of the CMTime structures is indefinite. If you need to test whether a CMTimeRange structure is valid, zero, or indefinite, you should use an appropriate macro: CMTIMERANGE_IS_VALID, CMTIMERANGE_IS_INVALID, CMTIMERANGE_IS_EMPTY, or CMTIMERANGE_IS_EMPTY.
Core Media
分別提供一個長度為0的范圍和一個無效范圍,就是kCMTimeRangeZero 和 kCMTimeRangeInvalid。有很多種方法,盡管 CMTimeRange
結構可以是無效的,或為零,或是不確定的(如果CMTime
結構是不確定的)。如果你需要測試 ``CMTimeRange` 結構體是否是有效的,零,或者不確定,你應該使用適當的宏:CMTIMERANGE_IS_VALID,CMTIMERANGE_IS_INVALID,CMTIMERANGE_IS_EMPTY,或者 CMTIMERANGE_IS_INDEFINITE。
CMTimeRange myTimeRange = <#Get a CMTimeRange#>;
if (CMTIMERANGE_IS_EMPTY(myTimeRange)) {
// The time range is zero.
}
You should not compare the value of an arbitrary CMTimeRange structure with kCMTimeRangeInvalid.
你不應該將任意的 CMTimeRange
結構體的值與 kCMTimeRangeInvalid
進行比較。
Representing a CMTimeRange Structure as an Object - 將 CMTimeRange
結構體表示為對象
If you need to use CMTimeRange structures in annotations or Core Foundation containers, you can convert a CMTimeRange structure to and from a CFDictionary opaque type (see CFDictionaryRef) using CMTimeRangeCopyAsDictionary and CMTimeRangeMakeFromDictionary, respectively. You can also get a string representation of a CMTime structure using the CMTimeRangeCopyDescription function.
如果你需要在注釋或 Core Foundation
容器中使用 CMTimeRange
結構,可以使用 CMTimeRangeCopyAsDictionary 轉換一個 CMTimeRange
,使用 CMTimeRangeMakeFromDictionary 從一個 CFDictionary
不透明類型 (見 CFDictionaryRef)。也可以 CMTimeRangeCopyDescription 功能得到 CMTime
結構的一個字符串表示。
Representations of Media - 媒體的表示
Video data and its associated metadata are represented in AV Foundation by opaque objects from the Core Media framework. Core Media represents video data using CMSampleBuffer (see CMSampleBufferRef). CMSampleBuffer is a Core Foundation-style opaque type; an instance contains the sample buffer for a frame of video data as a Core Video pixel buffer (see CVPixelBufferRef). You access the pixel buffer from a sample buffer using CMSampleBufferGetImageBuffer:
視頻數據和其相關的元數據都是被 AV Foundation
中來自 Core Media framework
的不透明對象表示。Core Media
表示視頻數據 使用 CMSampleBuffer
(見 CMSampleBufferRef)。CMSampleBuffer
是 Core Foundation
風格的不透明類型;實例包含了用于作為Core Video
像素緩沖(見CVPixelBufferRef)的視頻數據的單幀樣品緩沖區。使用 CMSampleBufferGetImageBuffer 從一個樣本緩沖區訪問像素緩沖。
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(<#A CMSampleBuffer#>);
From the pixel buffer, you can access the actual video data. For an example, see Converting CMSampleBuffer to a UIImage Object.
In addition to the video data, you can retrieve a number of other aspects of the video frame:
- Timing information. You get accurate timestamps for both the original presentation time and - the decode time using CMSampleBufferGetPresentationTimeStamp and - CMSampleBufferGetDecodeTimeStamp respectively.
- Format information. The format information is encapsulated in a CMFormatDescription object (- see CMFormatDescriptionRef). From the format description, you can get for example the pixel - type and video dimensions using CMVideoFormatDescriptionGetCodecType and - CMVideoFormatDescriptionGetDimensions respectively.
- Metadata. Metadata are stored in a dictionary as an attachment. You use CMGetAttachment to retrieve the dictionary:
從像素緩沖區,可以訪問實際的視頻數據。有個例子,請參閱 Converting CMSampleBuffer to a UIImage Object。
除了視頻數據之外,可以從數據幀中檢索多個其他方面的信息:
- 定時信息。分別使用 CMSampleBufferGetPresentationTimeStamp 和 CMSampleBufferGetDecodeTimeStamp為原來的呈現時間和解碼時間,獲取準確的時間戳。
- 格式信息。格式信息被封裝在
CMFormatDescription
對象(見 CMFormatDescriptionRef)。從格式的描述,分別使用CMVideoFormatDescriptionGetCodecType
和 CMVideoFormatDescriptionGetDimensions 可以得到例如像素類型和視頻尺寸。 - 元數據。元數據作為附件被存儲在字典中。使用 CMGetAttachment 去檢索詞典:
CMSampleBufferRef sampleBuffer = <#Get a sample buffer#>;
CFDictionaryRef metadataDictionary =
CMGetAttachment(sampleBuffer, CFSTR("MetadataDictionary", NULL);
if (metadataDictionary) {
// Do something with the metadata.
}
Converting CMSampleBuffer to a UIImage Object - 將 CMSampleBuffer
轉化為 UIImage
對象
The following code shows how you can convert a CMSampleBuffer to a UIImage object. You should consider your requirements carefully before using it. Performing the conversion is a comparatively expensive operation. It is appropriate to, for example, create a still image from a frame of video data taken every second or so. You should not use this as a means to manipulate every frame of video coming from a capture device in real time.
下面的代碼展示了如何將一個 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);
}
原文鏈接:http://blog.csdn.net/zyq522376829/article/details/52144326