Правильный способ обработки видео файлов и видео потоков

//Обновить

Я обнаружил небольшое улучшение в моей проблеме: я начинаю конвертировать небольшие фрагменты видео, пока оно записывается с очень низким потоком. После остановки игры, я установил средний априорный, не прерывая поток пользовательского интерфейса. Таким образом, после этого пользователь должен ждать около ~0,3*O(t), где t - продолжительность видео.

Кроме того, я нашел элегантное решение, но его сложно реализовать. https://github.com/WIZARDISHUNGRY/qctv Это должно сделать фильм во время записи.

//Обновить

У меня есть некоторые проблемы с конвертированием видео. Цель моей программы - применить несколько фильтров к видеоизображению с веб-камеры в режиме реального времени, например, фильтр сепии и отражение.

Прямо сейчас я использую пост видео обработки.

И вот вопрос:

Есть ли способ изменить видеокадры до их записи в видеофайл? Или изменить входное видео с камеры? Как применение CIFilter CIColorCube из инфраструктуры CoreImage к CIImage.

Я пытаюсь разделить исходное видео на маленькие фрагменты продолжительностью 1-2 секунды. И после этого обрабатывается с помощью метода, написанного под этим текстом.

Я уверен, что есть способ наложения фильтров прямо на выходе из веб-камеры, но я не могу найти его из-за огромного количества высокоуровневых фреймворков, которые не позволяют делать такие вещи.

У меня есть несколько требований: мне нужно поддерживать Mac OS X с версии 10.6, и я не могу использовать фреймворки или библиотеки размером более 5 МБ, потому что обработка выполняется на стороне клиента.

Класс NSOperation для преобразования фильмов

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <QTKit/QTkit.h>
#import <Quartz/Quartz.h>

@protocol ConvertOperationProtocol <NSObject>
-(void)movieWithNumberReady:(NSNumber*)number;
@end
@interface MSMovieConvertOperation : NSOperation
{
    QTMovie* movieToRead;
    QTMovie* movieToWrite;
}
@property int numberOfMovie;
@property NSArray* filtersArray;
@property NSObject<ConvertOperationProtocol>* ConvertOperationDelegate;
@end





#import "MSMovieConvertOperation.h"

@implementation MSMovieConvertOperation

@synthesize numberOfMovie,filtersArray;

//main operation
-(void)main
{
    NSString* movToReadPath = [NSString stringWithFormat:@"/Users/Shared/ms%d.mov",numberOfMovie];
    NSString* movToWritePath = [NSString stringWithFormat:@"/Users/Shared/pms%d",numberOfMovie];


    movieToRead = [QTMovie movieWithFile:movToReadPath error:NULL];
    movieToWrite = [[QTMovie alloc] initToWritableFile:movToWritePath error:NULL];

    while(QTTimeCompare([movieToRead currentTime], [movieToRead duration]) != NSOrderedSame)
    {
        QTTime time = movieToRead.currentTime;
         /////////////////////From here i haven't got any image/ciimage releases
         NSImage* sourceImage = [movieToRead frameImageAtTime:time];

        //Apply filters
        CIImage* inputImage = [CIImage imageWithData:[sourceImage
                                                      TIFFRepresentation]];



        inputImage = [inputImage imageByApplyingTransform:CGAffineTransformMakeScale(-1, 1)];
        if (!(filtersArray == nil || filtersArray.count < 1))
        {
            for (int i = 0; i < filtersArray.count; ++i)
            {
                CIFilter* filt = [filtersArray[i] copy];
                [filt setValue:inputImage forKey:@"inputImage"];
                inputImage = [filt valueForKey:@"outputImage"];
                filt = nil;
            }
        }

        NSRect outputImageRect = NSRectFromCGRect([inputImage extent]);
        [sourceImage lockFocus];
        [inputImage drawAtPoint:NSZeroPoint fromRect:outputImageRect
                      operation:NSCompositeCopy fraction:1.0];
        [sourceImage unlockFocus];
        //////////////////////////////////till there
        //Apply filters
        //jpeg
        time.timeValue = 2000;
        [movieToWrite addImage:sourceImage forDuration:time withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                                              @"avc1", QTAddImageCodecType, nil]];
        [movieToWrite setCurrentTime:[movieToWrite duration]];
        // I do some stuff with some things
        // Which seems to work fine
        [movieToRead stepForward];
        sourceImage = nil;
        inputImage = nil;

    }

    NSArray *allTracks = [movieToRead tracks];
    NSInteger totalFrames = 0;
    QTTrack* trackToWrite;
    QTTimeRange videoRange = QTMakeTimeRange(QTZeroTime, [movieToWrite duration]);
    for(QTTrack *track in allTracks)
    {
        QTMedia *media = [track media];

        // Checks to make sure the quicktime media being inputted has a video track.

        if (([[media attributeForKey:QTMediaTypeAttribute] isEqualToString:QTMediaTypeSound]))
        {
            trackToWrite = track;
        }

        if([[media attributeForKey:QTMediaTypeAttribute] isEqualToString:QTMediaTypeVideo])
        {
            NSNumber *samples = [media attributeForKey:QTMediaSampleCountAttribute];
            totalFrames = [samples integerValue];
//            NSLog(@"Total Frames: %ld", totalFrames);
//            NSLog(@"Frame Rate:  %@", [track attributeForKey:QTTrackTimeScaleAttribute]);
        }
    }

    [movieToWrite insertSegmentOfTrack:trackToWrite timeRange:videoRange atTime:QTZeroTime];

    // write the QTMovie to a 3GPP movie file on disk
    NSString* pathToWrite = [NSString stringWithFormat:@"/Users/Shared/pms%d.mov",numberOfMovie];

    [movieToWrite writeToFile:[[NSURL fileURLWithPath:pathToWrite] path] withAttributes:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:QTMovieFlatten] error:nil];
    //movieToWrite = nil;
    movieToRead = nil;
    movieToWrite = nil;
    [self.ConvertOperationDelegate performSelectorOnMainThread:@selector(movieWithNumberReady:) withObject:[NSNumber numberWithInt:numberOfMovie] waitUntilDone:NO];

    //NSLog(@"Video #%d Recorded!",numberOfMovie);
}

@end

Вот код для объединения маленьких фильмов в большие и обратного вызова из класса NSOperation

//looking for progress
-(void)movieWithNumberReady:(NSNumber *)number
{
    [statusOfFilesConverting replaceObjectAtIndex:number.intValue withObject:@1];
    BOOL readyToMerge = YES;
    for (int i = 0; i < statusOfFilesConverting.count; ++i)
    {
        if ([statusOfFilesConverting[i] intValue] == 0)
        {
            readyToMerge = NO;
            break;
        }
    }
    if (readyToMerge)
    {
        [self startMergeSmallMoviesIntoLargeOne];
    }
}


//Start to convert
-(IBAction)convertVideoWithNSOperationQueue:(id)sender
{
    [self clearFiles]; //deleting all work copies of video files
    timeStart = [NSDate date];
    statusOfFilesConverting = [[NSMutableArray alloc] init];
    for (int i = 0; i < _amountOfMovies; ++i) // calculated in advance the number of files
        [statusOfFilesConverting addObject:@0];

    NSOperationQueue* queue = [NSOperationQueue new];
    [queue setMaxConcurrentOperationCount:2];
    for (int i = 0; i < _amountOfMovies; ++i)
    {
        MSMovieConvertOperation* op = [MSMovieConvertOperation new];
        op.ConvertOperationDelegate = self;
        op.numberOfMovie = i;
        op.filtersArray = [_movieDelegate getFiltersArray];
        [queue addOperation:op];
    }
}

//merging
-(void)startMergeSmallMoviesIntoLargeOne
{
    NSLog(@"Start Merging Small movies");
    NSError *err = nil;

    QTMovie *myCombinedMovie = [[QTMovie alloc] initToWritableData:[NSMutableData data] error:&err];
    if (err)
    {
        NSLog(@"Error creating myCombinedMovie: %@", [err localizedDescription]);
        return;
    }

    NSMutableArray* _myMovieURLs = [[NSMutableArray alloc] init];
    for (int i = 0; i < _amountOfMovies; ++i)
    {
        NSURL* url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"/Users/Shared/pms%d.mov",i]];
        [_myMovieURLs addObject:url];
    }

    for (NSURL *url in _myMovieURLs)
    {
        QTMovie *theMovie = [QTMovie movieWithURL:url error:&err];
        if (err){
            NSLog(@"Error loading one of the movies: %@", [err localizedDescription]);
            return;
        }
        QTTimeRange timeRange = QTMakeTimeRange(QTZeroTime, [theMovie duration]);
        QTTime insertionTime = [myCombinedMovie duration];
        [myCombinedMovie insertSegmentOfMovie:theMovie timeRange:timeRange atTime:insertionTime];
    }

    NSDictionary *writeAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], QTMovieFlatten, nil];
    bool success = [myCombinedMovie writeToFile:@"/Users/Shared/outputMovie.mp4" withAttributes:writeAttributes error:&err];
    if (!success)
    {
        NSLog(@"Error writing movie: %@", [err localizedDescription]);
        return;
    }
    else
    {
        NSLog(@"Video end processing!");
        timeFinish = [NSDate date];
        [self multiThreadRecordingFinish];
    }
}

Заранее спасибо!

0 ответов

Другие вопросы по тегам