Figure 6-1 AVAsset provides an abstraction of time-based audiovisual data

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).

AVAssetAV 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);">


Figure 6-1 AVAsset provides an abstraction of time-based audiovisual data

</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);">


Figure 6-2 AVAssetTrack

</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 fpsNTSC(用在北美洲和日本的電視),25 fpsPAL(用于歐洲電視)。使用 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 提供了特殊值的常量:kCMTimeZerokCMTimeInvalidkCMTimePositiveInfinity,以及 kCMTimeNegativeInfinity。有許多方法,例如,其中 CMTime 結構體可以表示一個無效的時間。為了測試CMTime 是否是無效的,或者是一個非數字值,應該使用一個適當的宏,比如 CMTIME_IS_INVALIDCMTIME_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 結構體,可以使用 CMTimeCopyAsDictionaryCMTime 結構體轉換,使用 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 提供了一些功能,可用于確定一個時間范圍是否包含一個特定的時間或其他時間范圍,確定兩個時間范圍是否相等,并計算時間范圍的接口和相交范圍,比如 CMTimeRangeContainsTimeCMTimeRangeEqualCMTimeRangeContainsTimeRange,以及 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的范圍和一個無效范圍,就是kCMTimeRangeZerokCMTimeRangeInvalid。有很多種方法,盡管 CMTimeRange 結構可以是無效的,或為零,或是不確定的(如果CMTime 結構是不確定的)。如果你需要測試 ``CMTimeRange` 結構體是否是有效的,零,或者不確定,你應該使用適當的宏:CMTIMERANGE_IS_VALIDCMTIMERANGE_IS_INVALIDCMTIMERANGE_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)。CMSampleBufferCore 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

除了視頻數據之外,可以從數據幀中檢索多個其他方面的信息:

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375