Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added example of SDAVAssetExportSessionDelegate #58

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions SDAVAssetExportSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,26 @@ - (void)exportAsynchronouslyWithCompletionHandler:(void (^)())handler
{
[self.writer addInput:self.videoInput];
}
NSDictionary *pixelBufferAttributes = @
if ([self.delegate respondsToSelector:@selector(exportSession:renderFrame:withPresentationTime:toBuffer:)])
{
(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
(id)kCVPixelBufferWidthKey: @(self.videoOutput.videoComposition.renderSize.width),
(id)kCVPixelBufferHeightKey: @(self.videoOutput.videoComposition.renderSize.height),
@"IOSurfaceOpenGLESTextureCompatibility": @YES,
@"IOSurfaceOpenGLESFBOCompatibility": @YES,
};
self.videoPixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:self.videoInput sourcePixelBufferAttributes:pixelBufferAttributes];
// If a pixel format was specified in videoInputSettings, use the same pixel format for the render buffers
// In practice, kCVPixelFormatType_32BGRA always seems to be the fastest (even when transcoding between YpCbCr formats, such as H.264)
// This is despite the fact that the YpCbCr pixel buffers are less than half the size (12 bits/pixel vs. 32 bits/pixel)
id pixelFormat = self.videoInputSettings[(id)kCVPixelBufferPixelFormatTypeKey];
if (!pixelFormat)
{
pixelFormat = @(kCVPixelFormatType_32BGRA);
}
NSDictionary *pixelBufferAttributes = @
{
(id)kCVPixelBufferPixelFormatTypeKey: pixelFormat,
(id)kCVPixelBufferWidthKey: @(self.videoOutput.videoComposition.renderSize.width),
(id)kCVPixelBufferHeightKey: @(self.videoOutput.videoComposition.renderSize.height),
@"IOSurfaceOpenGLESTextureCompatibility": @YES,
@"IOSurfaceOpenGLESFBOCompatibility": @YES,
};
self.videoPixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:self.videoInput sourcePixelBufferAttributes:pixelBufferAttributes];
}
}

//
Expand Down
17 changes: 17 additions & 0 deletions SDAVAssetExportSessionDelegateExample.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// SDAVAssetExportSessionDelegateExample.h
//
// This file is part of the SDAVAssetExportSession package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

#import <Foundation/Foundation.h>
#import "SDAVAssetExportSession.h"

@interface SDAVAssetExportSessionDelegateExample : NSObject <SDAVAssetExportSessionDelegate>

- (void)exportSession:(SDAVAssetExportSession *)exportSession renderFrame:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime toBuffer:(CVPixelBufferRef)renderBuffer;

@end
74 changes: 74 additions & 0 deletions SDAVAssetExportSessionDelegateExample.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// SDAVAssetExportSessionDelegateExample.m
//
// This file is part of the SDAVAssetExportSession package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

#import "SDAVAssetExportSessionDelegateExample.h"

/**
* An example implementation of `SDAVAssetExportSessionDelegate` that just copies the input 'pixelBuffer' to the output 'renderBuffer' unmodified.
* You can control the pixel format that the 'AVAssetReaderTrackOutput' produces by setting 'exportSession.videoInputSettings':
*
* exportSession.videoInputSettings = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) };
*
* The default format of kCVPixelFormatType_32BGRA is generally the fastest for transcoding, even when the input video is a YpCbCr format, such as H.264
*/

@implementation SDAVAssetExportSessionDelegateExample

- (void)exportSession:(SDAVAssetExportSession *)exportSession renderFrame:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime toBuffer:(CVPixelBufferRef)renderBuffer
{
// Print the presentation times of the frames
// CMTimeShow(presentationTime);

// Print details -- just for the first frame
if (presentationTime.value == 0)
{
OSType sourceFormat = CVPixelBufferGetPixelFormatType(pixelBuffer);
OSType destFormat = CVPixelBufferGetPixelFormatType(renderBuffer);
size_t dataSize = CVPixelBufferGetDataSize(pixelBuffer);

NSLog(@"source format: %@, dest format: %@, planar: %d, size: %zu", NSFileTypeForHFSTypeCode(sourceFormat), NSFileTypeForHFSTypeCode(destFormat), CVPixelBufferIsPlanar(pixelBuffer), dataSize);
}

// Copy the source pixel buffer to the output pixel buffer.
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
CVPixelBufferLockBaseAddress(renderBuffer, 0);

if (CVPixelBufferIsPlanar(pixelBuffer))
{
// Planar formats, such as kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange and kCVPixelFormatType_420YpCbCr8BiPlanarFullRange.
size_t planeCount = CVPixelBufferGetPlaneCount(pixelBuffer);

for (size_t i = 0; i < planeCount; i++)
{
int height = (int)CVPixelBufferGetHeightOfPlane(pixelBuffer, i);
size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, i);

void *pixelBufferBaseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, i);
void *renderBufferBaseAddress = CVPixelBufferGetBaseAddressOfPlane(renderBuffer, i);

memcpy(renderBufferBaseAddress, pixelBufferBaseAddress, height * bytesPerRow);
}
}
else
{
// Packed formats, such as kCVPixelFormatType_32BGRA, kCVPixelFormatType_32ARGB, and kCVPixelFormatType_422YpCbCr8.
int height = (int)CVPixelBufferGetHeight(pixelBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);

void *pixelBufferBaseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
void *renderBufferBaseAddress = CVPixelBufferGetBaseAddress(renderBuffer);

memcpy(renderBufferBaseAddress, pixelBufferBaseAddress, height * bytesPerRow);
}

CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
CVPixelBufferUnlockBaseAddress(renderBuffer, 0);
}

@end