Closed ghost closed 10 years ago
Hey. Did you tried this with the latest SCRecorder version? I had to fix this issue for iOS 8. How is working the tutorial on your phone?
Thanks for the fast reply. Downloaded the latest version and it still isnt working. Only 2 files I changed + changing the class in the storyboard:
//
// SCVideoPlayerViewController.h
// SCAudioVideoRecorder
//
// Created by Simon CORSIN on 8/30/13.
// Copyright (c) 2013 rFlex. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SCVideoPlayerView.h"
#import "SCRecorder.h"
@interface SCVideoPlayerViewController : UIViewController<SCPlayerDelegate>
@property (strong, nonatomic) SCRecordSession *recordSession;
@property (weak, nonatomic) IBOutlet SCVideoPlayerView *filterSwitcherView;
@end
//
// SCVideoPlayerViewController.m
// SCAudioVideoRecorder
//
// Created by Simon CORSIN on 8/30/13.
// Copyright (c) 2013 rFlex. All rights reserved.
//
#import "SCVideoPlayerViewController.h"
#import "SCEditVideoViewController.h"
#import "SCAssetExportSession.h"
#import "SCImageView.h"
@interface SCVideoPlayerViewController () {
SCPlayer *_player;
}
@property SCImageView *ImageView;
@end
@implementation SCVideoPlayerViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc {
self.filterSwitcherView = nil;
[_player pause];
_player = nil;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.filterSwitcherView.contentMode = UIViewContentModeScaleAspectFit;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleBordered target:self action:@selector(saveToCameraRoll)];
self.filterSwitcherView.player.loopEnabled = YES;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.filterSwitcherView.player setItemByAsset:_recordSession.assetRepresentingRecordSegments];
[self.filterSwitcherView.player play];
SCImageView *ImageView = [SCImageView new];
ImageView.filterGroup = [SCFilterGroup filterGroupWithFilter:[SCFilter filterWithName:@"CIPhotoEffectNoir"]];
ImageView.frame = self.view.bounds;
[self.view addSubview:ImageView];
self.filterSwitcherView.player.CIImageRenderer = ImageView;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[_player pause];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[SCEditVideoViewController class]]) {
SCEditVideoViewController *editVideo = segue.destinationViewController;
editVideo.recordSession = self.recordSession;
}
}
@end
Still works fine when I remove the ImageView + SCFilter, but only shows a black screen where the video should be when I add the ImageView + SCFilter.
Is the example working though?
Yep, the example without any modifications works. Is the way the filters are applied in the example different from how I apply mine? (Like I said I couldn't manage to find where this happens in the code).
By the way I recommend that you create the SCImageView on the viewDidLoad, you can then set the CIImageRenderer on willWillAppear and set it to null on viewDidDisappear. It's usually better to not mess up too much the view hierarchy in the viewWillAppear. Setup your views inside viewDidLoad, hide/show them as you like on viewWillAppear viewDidDisappear.
I'll look what's going on anyway.
Switched up the views, code now looks like this, but I'm still getting the same black screen issue:
//
// SCVideoPlayerViewController.m
// SCAudioVideoRecorder
//
// Created by Simon CORSIN on 8/30/13.
// Copyright (c) 2013 rFlex. All rights reserved.
//
#import "SCVideoPlayerViewController.h"
#import "SCEditVideoViewController.h"
#import "SCAssetExportSession.h"
#import "SCImageView.h"
@interface SCVideoPlayerViewController () {
SCPlayer *_player;
}
@property SCImageView *ImageView;
@end
@implementation SCVideoPlayerViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc {
self.filterSwitcherView = nil;
[_player pause];
_player = nil;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.filterSwitcherView.contentMode = UIViewContentModeScaleAspectFit;
self.ImageView = [SCImageView new];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleBordered target:self action:@selector(saveToCameraRoll)];
self.filterSwitcherView.player.loopEnabled = YES;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.filterSwitcherView.player setItemByAsset:_recordSession.assetRepresentingRecordSegments];
[self.filterSwitcherView.player play];
self.ImageView.filterGroup = [SCFilterGroup filterGroupWithFilter:[SCFilter filterWithName:@"CIPhotoEffectNoir"]];
self.ImageView.frame = self.view.bounds;
[self.view addSubview:self.ImageView];
self.filterSwitcherView.player.CIImageRenderer = self.ImageView;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.ImageView = nil;
[_player pause];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[SCEditVideoViewController class]]) {
SCEditVideoViewController *editVideo = segue.destinationViewController;
editVideo.recordSession = self.recordSession;
}
}
@end
Here is a copy of the entire project as I have it now, if it helps: http://a.pomf.se/ffokei.zip
OK after picking through the code for a little bit I think I found the culprit, the SCImageViewEnabled property on SCVideoPlayerView. After setting that to true, the video now displays with the filter.
Sorry, weird new issue: I'm trying to use a custom filter created using an RGB lookup table with this code:
@implementation CIFilter (LUT)
+(CIFilter *) filterWithLUT:(NSString *)name dimension:(NSInteger)n
{
UIImage *image = [UIImage imageNamed:name];
NSInteger width = CGImageGetWidth(image.CGImage);
NSInteger height = CGImageGetHeight(image.CGImage);
NSInteger rowNum = height / n;
NSInteger columnNum = width / n;
if ((width % n != 0) || (height % n != 0) || (rowNum * columnNum != n))
{
NSLog(@"Invalid colorLUT");
return nil;
}
unsigned char *bitmap = [self createRGBABitmapFromImage:image.CGImage];
if (bitmap == NULL)
{
return nil;
}
NSInteger size = n * n * n * sizeof(float) * 4;
float *data = malloc(size);
int bitmapOffest = 0;
int z = 0;
for (int row = 0; row < rowNum; row++)
{
for (int y = 0; y < n; y++)
{
int tmp = z;
for (int col = 0; col < columnNum; col++)
{
for (int x = 0; x < n; x++) {
float r = (unsigned int)bitmap[bitmapOffest];
float g = (unsigned int)bitmap[bitmapOffest + 1];
float b = (unsigned int)bitmap[bitmapOffest + 2];
float a = (unsigned int)bitmap[bitmapOffest + 3];
NSInteger dataOffset = (z*n*n + y*n + x) * 4;
data[dataOffset] = r / 255.0;
data[dataOffset + 1] = g / 255.0;
data[dataOffset + 2] = b / 255.0;
data[dataOffset + 3] = a / 255.0;
bitmapOffest += 4;
}
z++;
}
z = tmp;
}
z += columnNum;
}
free(bitmap);
CIFilter *filter = [CIFilter filterWithName:@"CIColorCube"];
[filter setValue:[NSData dataWithBytesNoCopy:data length:size freeWhenDone:YES] forKey:@"inputCubeData"];
[filter setValue:[NSNumber numberWithInteger:n] forKey:@"inputCubeDimension"];
return filter;
}
+ (unsigned char *)createRGBABitmapFromImage:(CGImageRef)image
{
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
unsigned char *bitmap;
NSInteger bitmapSize;
NSInteger bytesPerRow;
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
bytesPerRow = (width * 4);
bitmapSize = (bytesPerRow * height);
bitmap = malloc( bitmapSize );
if (bitmap == NULL)
{
return NULL;
}
colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL)
{
free(bitmap);
return NULL;
}
context = CGBitmapContextCreate (bitmap,
width,
height,
8,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease( colorSpace );
if (context == NULL)
{
free (bitmap);
}
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
CGContextRelease(context);
return bitmap;
}
@end
I then use the filterWithCIFilter method of SCFilter to make an SCFilter from this, and apply it to the video. When displaying the video in the video player view with the filter on it, it looks fine. However after saving it using an export session, the exported video looks much darker than it looked in the video player view, see here:
In the video player view:
After exporting:
I'm thinking this has something to do with the way the pixel buffers are handled in the export section, but I haven't been able to figure out exactly what is causing it.
Figured it out. The color space was getting messed up, so now I pass this in the commonInit.
NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };
Now it writes to disk with the correct colors. I was writing my own custom implementation of the filter preview view so I could be independent of any 3rd party libraries and this tripped me up again, odd. I guess I should read up more on digital color.
hey, i'm getting the black screen and cannot find SCImageViewEnabled to set it true. any help?
I was playing around with your example app, and switched out the SCSwipeableFilterView called filterSwitcherView for a SCVideoPlayerView. Playing unfiltered videos in it works fine, but when I try to add a filter like the way shown in the tutorial:
I get a black screen where the movie should be playing. This is running on an iPhone 5 with iOS 8. It seems to run fine on another phone with iOS 7. Without any modifications the filters included with the app are working with the SCSwipeableFilterView, but I wasn't able to figure out where the filters actually get applied in the code, what with it being spread across a bunch of files and having the OpenGL stuff.
Thanks for putting this awesome library together, it provides good examples of a lot of stuff I was trying to learn.